Merge branch 'master' of https://github.com/yuzu-emu/yuzu into service-impl

This commit is contained in:
David Marcec 2018-04-26 14:28:54 -07:00
commit 7391741a20
110 changed files with 1815 additions and 2248 deletions

View file

@ -31,7 +31,6 @@ add_library(common STATIC
bit_set.h bit_set.h
break_points.cpp break_points.cpp
break_points.h break_points.h
chunk_file.h
cityhash.cpp cityhash.cpp
cityhash.h cityhash.h
color.h color.h
@ -41,7 +40,6 @@ add_library(common STATIC
file_util.cpp file_util.cpp
file_util.h file_util.h
hash.h hash.h
linear_disk_cache.h
logging/backend.cpp logging/backend.cpp
logging/backend.h logging/backend.h
logging/filter.cpp logging/filter.cpp

View file

@ -1,623 +0,0 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#pragma once
// Extremely simple serialization framework.
// (mis)-features:
// + Super fast
// + Very simple
// + Same code is used for serialization and deserializaition (in most cases)
// - Zero backwards/forwards compatibility
// - Serialization code for anything complex has to be manually written.
#include <cstring>
#include <deque>
#include <list>
#include <map>
#include <set>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
#include "common/assert.h"
#include "common/common_types.h"
#include "common/logging/log.h"
template <class T>
struct LinkedListItem : public T {
LinkedListItem<T>* next;
};
class PointerWrap;
class PointerWrapSection {
public:
PointerWrapSection(PointerWrap& p, int ver, const char* title)
: p_(p), ver_(ver), title_(title) {}
~PointerWrapSection();
bool operator==(const int& v) const {
return ver_ == v;
}
bool operator!=(const int& v) const {
return ver_ != v;
}
bool operator<=(const int& v) const {
return ver_ <= v;
}
bool operator>=(const int& v) const {
return ver_ >= v;
}
bool operator<(const int& v) const {
return ver_ < v;
}
bool operator>(const int& v) const {
return ver_ > v;
}
operator bool() const {
return ver_ > 0;
}
private:
PointerWrap& p_;
int ver_;
const char* title_;
};
// Wrapper class
class PointerWrap {
// This makes it a compile error if you forget to define DoState() on non-POD.
// Which also can be a problem, for example struct tm is non-POD on linux, for whatever reason...
#ifdef _MSC_VER
template <typename T, bool isPOD = std::is_pod<T>::value,
bool isPointer = std::is_pointer<T>::value>
#else
template <typename T, bool isPOD = __is_pod(T), bool isPointer = std::is_pointer<T>::value>
#endif
struct DoHelper {
static void DoArray(PointerWrap* p, T* x, int count) {
for (int i = 0; i < count; ++i)
p->Do(x[i]);
}
static void Do(PointerWrap* p, T& x) {
p->DoClass(x);
}
};
template <typename T>
struct DoHelper<T, true, false> {
static void DoArray(PointerWrap* p, T* x, int count) {
p->DoVoid((void*)x, sizeof(T) * count);
}
static void Do(PointerWrap* p, T& x) {
p->DoVoid((void*)&x, sizeof(x));
}
};
public:
enum Mode {
MODE_READ = 1, // load
MODE_WRITE, // save
MODE_MEASURE, // calculate size
MODE_VERIFY, // compare
};
enum Error {
ERROR_NONE = 0,
ERROR_WARNING = 1,
ERROR_FAILURE = 2,
};
u8** ptr;
Mode mode;
Error error;
public:
PointerWrap(u8** ptr_, Mode mode_) : ptr(ptr_), mode(mode_), error(ERROR_NONE) {}
PointerWrap(unsigned char** ptr_, int mode_)
: ptr((u8**)ptr_), mode((Mode)mode_), error(ERROR_NONE) {}
PointerWrapSection Section(const char* title, int ver) {
return Section(title, ver, ver);
}
// The returned object can be compared against the version that was loaded.
// This can be used to support versions as old as minVer.
// Version = 0 means the section was not found.
PointerWrapSection Section(const char* title, int minVer, int ver) {
char marker[16] = {0};
int foundVersion = ver;
strncpy(marker, title, sizeof(marker));
if (!ExpectVoid(marker, sizeof(marker))) {
// Might be before we added name markers for safety.
if (foundVersion == 1 && ExpectVoid(&foundVersion, sizeof(foundVersion)))
DoMarker(title);
// Wasn't found, but maybe we can still load the state.
else
foundVersion = 0;
} else
Do(foundVersion);
if (error == ERROR_FAILURE || foundVersion < minVer || foundVersion > ver) {
LOG_ERROR(Common, "Savestate failure: wrong version %d found for %s", foundVersion,
title);
SetError(ERROR_FAILURE);
return PointerWrapSection(*this, -1, title);
}
return PointerWrapSection(*this, foundVersion, title);
}
void SetMode(Mode mode_) {
mode = mode_;
}
Mode GetMode() const {
return mode;
}
u8** GetPPtr() {
return ptr;
}
void SetError(Error error_) {
if (error < error_)
error = error_;
if (error > ERROR_WARNING)
mode = PointerWrap::MODE_MEASURE;
}
bool ExpectVoid(void* data, int size) {
switch (mode) {
case MODE_READ:
if (memcmp(data, *ptr, size) != 0)
return false;
break;
case MODE_WRITE:
memcpy(*ptr, data, size);
break;
case MODE_MEASURE:
break; // MODE_MEASURE - don't need to do anything
case MODE_VERIFY:
for (int i = 0; i < size; i++) {
DEBUG_ASSERT_MSG(
((u8*)data)[i] == (*ptr)[i],
"Savestate verification failure: %d (0x%X) (at %p) != %d (0x%X) (at %p).\n",
((u8*)data)[i], ((u8*)data)[i], &((u8*)data)[i], (*ptr)[i], (*ptr)[i],
&(*ptr)[i]);
}
break;
default:
break; // throw an error?
}
(*ptr) += size;
return true;
}
void DoVoid(void* data, int size) {
switch (mode) {
case MODE_READ:
memcpy(data, *ptr, size);
break;
case MODE_WRITE:
memcpy(*ptr, data, size);
break;
case MODE_MEASURE:
break; // MODE_MEASURE - don't need to do anything
case MODE_VERIFY:
for (int i = 0; i < size; i++) {
DEBUG_ASSERT_MSG(
((u8*)data)[i] == (*ptr)[i],
"Savestate verification failure: %d (0x%X) (at %p) != %d (0x%X) (at %p).\n",
((u8*)data)[i], ((u8*)data)[i], &((u8*)data)[i], (*ptr)[i], (*ptr)[i],
&(*ptr)[i]);
}
break;
default:
break; // throw an error?
}
(*ptr) += size;
}
template <class K, class T>
void Do(std::map<K, T*>& x) {
if (mode == MODE_READ) {
for (auto it = x.begin(), end = x.end(); it != end; ++it) {
if (it->second != nullptr)
delete it->second;
}
}
T* dv = nullptr;
DoMap(x, dv);
}
template <class K, class T>
void Do(std::map<K, T>& x) {
T dv = T();
DoMap(x, dv);
}
template <class K, class T>
void DoMap(std::map<K, T>& x, T& default_val) {
unsigned int number = (unsigned int)x.size();
Do(number);
switch (mode) {
case MODE_READ: {
x.clear();
while (number > 0) {
K first = K();
Do(first);
T second = default_val;
Do(second);
x[first] = second;
--number;
}
} break;
case MODE_WRITE:
case MODE_MEASURE:
case MODE_VERIFY: {
typename std::map<K, T>::iterator itr = x.begin();
while (number > 0) {
K first = itr->first;
Do(first);
Do(itr->second);
--number;
++itr;
}
} break;
}
}
template <class K, class T>
void Do(std::multimap<K, T*>& x) {
if (mode == MODE_READ) {
for (auto it = x.begin(), end = x.end(); it != end; ++it) {
if (it->second != nullptr)
delete it->second;
}
}
T* dv = nullptr;
DoMultimap(x, dv);
}
template <class K, class T>
void Do(std::multimap<K, T>& x) {
T dv = T();
DoMultimap(x, dv);
}
template <class K, class T>
void DoMultimap(std::multimap<K, T>& x, T& default_val) {
unsigned int number = (unsigned int)x.size();
Do(number);
switch (mode) {
case MODE_READ: {
x.clear();
while (number > 0) {
K first = K();
Do(first);
T second = default_val;
Do(second);
x.insert(std::make_pair(first, second));
--number;
}
} break;
case MODE_WRITE:
case MODE_MEASURE:
case MODE_VERIFY: {
typename std::multimap<K, T>::iterator itr = x.begin();
while (number > 0) {
Do(itr->first);
Do(itr->second);
--number;
++itr;
}
} break;
}
}
// Store vectors.
template <class T>
void Do(std::vector<T*>& x) {
T* dv = nullptr;
DoVector(x, dv);
}
template <class T>
void Do(std::vector<T>& x) {
T dv = T();
DoVector(x, dv);
}
template <class T>
void DoPOD(std::vector<T>& x) {
T dv = T();
DoVectorPOD(x, dv);
}
template <class T>
void Do(std::vector<T>& x, T& default_val) {
DoVector(x, default_val);
}
template <class T>
void DoVector(std::vector<T>& x, T& default_val) {
u32 vec_size = (u32)x.size();
Do(vec_size);
x.resize(vec_size, default_val);
if (vec_size > 0)
DoArray(&x[0], vec_size);
}
template <class T>
void DoVectorPOD(std::vector<T>& x, T& default_val) {
u32 vec_size = (u32)x.size();
Do(vec_size);
x.resize(vec_size, default_val);
if (vec_size > 0)
DoArray(&x[0], vec_size);
}
// Store deques.
template <class T>
void Do(std::deque<T*>& x) {
T* dv = nullptr;
DoDeque(x, dv);
}
template <class T>
void Do(std::deque<T>& x) {
T dv = T();
DoDeque(x, dv);
}
template <class T>
void DoDeque(std::deque<T>& x, T& default_val) {
u32 deq_size = (u32)x.size();
Do(deq_size);
x.resize(deq_size, default_val);
u32 i;
for (i = 0; i < deq_size; i++)
Do(x[i]);
}
// Store STL lists.
template <class T>
void Do(std::list<T*>& x) {
T* dv = nullptr;
Do(x, dv);
}
template <class T>
void Do(std::list<T>& x) {
T dv = T();
DoList(x, dv);
}
template <class T>
void Do(std::list<T>& x, T& default_val) {
DoList(x, default_val);
}
template <class T>
void DoList(std::list<T>& x, T& default_val) {
u32 list_size = (u32)x.size();
Do(list_size);
x.resize(list_size, default_val);
typename std::list<T>::iterator itr, end;
for (itr = x.begin(), end = x.end(); itr != end; ++itr)
Do(*itr);
}
// Store STL sets.
template <class T>
void Do(std::set<T*>& x) {
if (mode == MODE_READ) {
for (auto it = x.begin(), end = x.end(); it != end; ++it) {
if (*it != nullptr)
delete *it;
}
}
DoSet(x);
}
template <class T>
void Do(std::set<T>& x) {
DoSet(x);
}
template <class T>
void DoSet(std::set<T>& x) {
unsigned int number = (unsigned int)x.size();
Do(number);
switch (mode) {
case MODE_READ: {
x.clear();
while (number-- > 0) {
T it = T();
Do(it);
x.insert(it);
}
} break;
case MODE_WRITE:
case MODE_MEASURE:
case MODE_VERIFY: {
typename std::set<T>::iterator itr = x.begin();
while (number-- > 0)
Do(*itr++);
} break;
default:
LOG_ERROR(Common, "Savestate error: invalid mode %d.", mode);
}
}
// Store strings.
void Do(std::string& x) {
int stringLen = (int)x.length() + 1;
Do(stringLen);
switch (mode) {
case MODE_READ:
x = (char*)*ptr;
break;
case MODE_WRITE:
memcpy(*ptr, x.c_str(), stringLen);
break;
case MODE_MEASURE:
break;
case MODE_VERIFY:
DEBUG_ASSERT_MSG((x == (char*)*ptr),
"Savestate verification failure: \"%s\" != \"%s\" (at %p).\n",
x.c_str(), (char*)*ptr, ptr);
break;
}
(*ptr) += stringLen;
}
void Do(std::wstring& x) {
int stringLen = sizeof(wchar_t) * ((int)x.length() + 1);
Do(stringLen);
switch (mode) {
case MODE_READ:
x = (wchar_t*)*ptr;
break;
case MODE_WRITE:
memcpy(*ptr, x.c_str(), stringLen);
break;
case MODE_MEASURE:
break;
case MODE_VERIFY:
DEBUG_ASSERT_MSG((x == (wchar_t*)*ptr),
"Savestate verification failure: \"%ls\" != \"%ls\" (at %p).\n",
x.c_str(), (wchar_t*)*ptr, ptr);
break;
}
(*ptr) += stringLen;
}
template <class T>
void DoClass(T& x) {
x.DoState(*this);
}
template <class T>
void DoClass(T*& x) {
if (mode == MODE_READ) {
if (x != nullptr)
delete x;
x = new T();
}
x->DoState(*this);
}
template <class T>
void DoArray(T* x, int count) {
DoHelper<T>::DoArray(this, x, count);
}
template <class T>
void Do(T& x) {
DoHelper<T>::Do(this, x);
}
template <class T>
void DoPOD(T& x) {
DoHelper<T>::Do(this, x);
}
template <class T>
void DoPointer(T*& x, T* const base) {
// pointers can be more than 2^31 apart, but you're using this function wrong if you need
// that much range
s32 offset = x - base;
Do(offset);
if (mode == MODE_READ)
x = base + offset;
}
template <class T, LinkedListItem<T>* (*TNew)(), void (*TFree)(LinkedListItem<T>*),
void (*TDo)(PointerWrap&, T*)>
void DoLinkedList(LinkedListItem<T>*& list_start, LinkedListItem<T>** list_end = nullptr) {
LinkedListItem<T>* list_cur = list_start;
LinkedListItem<T>* prev = nullptr;
while (true) {
u8 shouldExist = (list_cur ? 1 : 0);
Do(shouldExist);
if (shouldExist == 1) {
LinkedListItem<T>* cur = list_cur ? list_cur : TNew();
TDo(*this, (T*)cur);
if (!list_cur) {
if (mode == MODE_READ) {
cur->next = nullptr;
list_cur = cur;
if (prev)
prev->next = cur;
else
list_start = cur;
} else {
TFree(cur);
continue;
}
}
} else {
if (mode == MODE_READ) {
if (prev)
prev->next = nullptr;
if (list_end)
*list_end = prev;
if (list_cur) {
if (list_start == list_cur)
list_start = nullptr;
do {
LinkedListItem<T>* next = list_cur->next;
TFree(list_cur);
list_cur = next;
} while (list_cur);
}
}
break;
}
prev = list_cur;
list_cur = list_cur->next;
}
}
void DoMarker(const char* prevName, u32 arbitraryNumber = 0x42) {
u32 cookie = arbitraryNumber;
Do(cookie);
if (mode == PointerWrap::MODE_READ && cookie != arbitraryNumber) {
LOG_ERROR(Common,
"After \"%s\", found %d (0x%X) instead of save marker %d (0x%X). "
"Aborting savestate load...",
prevName, cookie, cookie, arbitraryNumber, arbitraryNumber);
SetError(ERROR_FAILURE);
}
}
};
inline PointerWrapSection::~PointerWrapSection() {
if (ver_ > 0) {
p_.DoMarker(title_);
}
}

View file

@ -1,167 +0,0 @@
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <fstream>
#include "common/common_types.h"
// defined in Version.cpp
extern const char* scm_rev_git_str;
// On disk format:
// header{
// u32 'DCAC';
// u32 version; // svn_rev
// u16 sizeof(key_type);
// u16 sizeof(value_type);
//}
// key_value_pair{
// u32 value_size;
// key_type key;
// value_type[value_size] value;
//}
template <typename K, typename V>
class LinearDiskCacheReader {
public:
virtual void Read(const K& key, const V* value, u32 value_size) = 0;
};
// Dead simple unsorted key-value store with append functionality.
// No random read functionality, all reading is done in OpenAndRead.
// Keys and values can contain any characters, including \0.
//
// Suitable for caching generated shader bytecode between executions.
// Not tuned for extreme performance but should be reasonably fast.
// Does not support keys or values larger than 2GB, which should be reasonable.
// Keys must have non-zero length; values can have zero length.
// K and V are some POD type
// K : the key type
// V : value array type
template <typename K, typename V>
class LinearDiskCache {
public:
// return number of read entries
u32 OpenAndRead(const char* filename, LinearDiskCacheReader<K, V>& reader) {
using std::ios_base;
// close any currently opened file
Close();
m_num_entries = 0;
// try opening for reading/writing
OpenFStream(m_file, filename, ios_base::in | ios_base::out | ios_base::binary);
m_file.seekg(0, std::ios::end);
std::fstream::pos_type end_pos = m_file.tellg();
m_file.seekg(0, std::ios::beg);
std::fstream::pos_type start_pos = m_file.tellg();
std::streamoff file_size = end_pos - start_pos;
if (m_file.is_open() && ValidateHeader()) {
// good header, read some key/value pairs
K key;
V* value = nullptr;
u32 value_size;
u32 entry_number;
std::fstream::pos_type last_pos = m_file.tellg();
while (Read(&value_size)) {
std::streamoff next_extent =
(last_pos - start_pos) + sizeof(value_size) + value_size;
if (next_extent > file_size)
break;
delete[] value;
value = new V[value_size];
// read key/value and pass to reader
if (Read(&key) && Read(value, value_size) && Read(&entry_number) &&
entry_number == m_num_entries + 1) {
reader.Read(key, value, value_size);
} else {
break;
}
m_num_entries++;
last_pos = m_file.tellg();
}
m_file.seekp(last_pos);
m_file.clear();
delete[] value;
return m_num_entries;
}
// failed to open file for reading or bad header
// close and recreate file
Close();
m_file.open(filename, ios_base::out | ios_base::trunc | ios_base::binary);
WriteHeader();
return 0;
}
void Sync() {
m_file.flush();
}
void Close() {
if (m_file.is_open())
m_file.close();
// clear any error flags
m_file.clear();
}
// Appends a key-value pair to the store.
void Append(const K& key, const V* value, u32 value_size) {
// TODO: Should do a check that we don't already have "key"? (I think each caller does that
// already.)
Write(&value_size);
Write(&key);
Write(value, value_size);
m_num_entries++;
Write(&m_num_entries);
}
private:
void WriteHeader() {
Write(&m_header);
}
bool ValidateHeader() {
char file_header[sizeof(Header)];
return (Read(file_header, sizeof(Header)) &&
!memcmp((const char*)&m_header, file_header, sizeof(Header)));
}
template <typename D>
bool Write(const D* data, u32 count = 1) {
return m_file.write((const char*)data, count * sizeof(D)).good();
}
template <typename D>
bool Read(const D* data, u32 count = 1) {
return m_file.read((char*)data, count * sizeof(D)).good();
}
struct Header {
Header() : id(*(u32*)"DCAC"), key_t_size(sizeof(K)), value_t_size(sizeof(V)) {
memcpy(ver, scm_rev_git_str, 40);
}
const u32 id;
const u16 key_t_size, value_t_size;
char ver[40];
} m_header;
std::fstream m_file;
u32 m_num_entries;
};

View file

@ -42,8 +42,6 @@ add_library(core STATIC
hle/kernel/client_port.h hle/kernel/client_port.h
hle/kernel/client_session.cpp hle/kernel/client_session.cpp
hle/kernel/client_session.h hle/kernel/client_session.h
hle/kernel/condition_variable.cpp
hle/kernel/condition_variable.h
hle/kernel/errors.h hle/kernel/errors.h
hle/kernel/event.cpp hle/kernel/event.cpp
hle/kernel/event.h hle/kernel/event.h
@ -183,10 +181,10 @@ add_library(core STATIC
hle/service/nvflinger/buffer_queue.h hle/service/nvflinger/buffer_queue.h
hle/service/nvflinger/nvflinger.cpp hle/service/nvflinger/nvflinger.cpp
hle/service/nvflinger/nvflinger.h hle/service/nvflinger/nvflinger.h
hle/service/pctl/module.cpp
hle/service/pctl/module.h
hle/service/pctl/pctl.cpp hle/service/pctl/pctl.cpp
hle/service/pctl/pctl.h hle/service/pctl/pctl.h
hle/service/pctl/pctl_a.cpp
hle/service/pctl/pctl_a.h
hle/service/prepo/prepo.cpp hle/service/prepo/prepo.cpp
hle/service/prepo/prepo.h hle/service/prepo/prepo.h
hle/service/service.cpp hle/service/service.cpp

View file

@ -67,26 +67,32 @@ ResultCode Disk_FileSystem::DeleteFile(const std::string& path) const {
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
ResultCode Disk_FileSystem::RenameFile(const Path& src_path, const Path& dest_path) const { ResultCode Disk_FileSystem::RenameFile(const std::string& src_path,
LOG_WARNING(Service_FS, "(STUBBED) called"); const std::string& dest_path) const {
const std::string full_src_path = base_directory + src_path;
const std::string full_dest_path = base_directory + dest_path;
if (!FileUtil::Exists(full_src_path)) {
return ERROR_PATH_NOT_FOUND;
}
// TODO(wwylele): Use correct error code // TODO(wwylele): Use correct error code
return ResultCode(-1); return FileUtil::Rename(full_src_path, full_dest_path) ? RESULT_SUCCESS : ResultCode(-1);
} }
ResultCode Disk_FileSystem::DeleteDirectory(const Path& path) const { ResultCode Disk_FileSystem::DeleteDirectory(const Path& path) const {
LOG_WARNING(Service_FS, "(STUBBED) called"); NGLOG_WARNING(Service_FS, "(STUBBED) called");
// TODO(wwylele): Use correct error code // TODO(wwylele): Use correct error code
return ResultCode(-1); return ResultCode(-1);
} }
ResultCode Disk_FileSystem::DeleteDirectoryRecursively(const Path& path) const { ResultCode Disk_FileSystem::DeleteDirectoryRecursively(const Path& path) const {
LOG_WARNING(Service_FS, "(STUBBED) called"); NGLOG_WARNING(Service_FS, "(STUBBED) called");
// TODO(wwylele): Use correct error code // TODO(wwylele): Use correct error code
return ResultCode(-1); return ResultCode(-1);
} }
ResultCode Disk_FileSystem::CreateFile(const std::string& path, u64 size) const { ResultCode Disk_FileSystem::CreateFile(const std::string& path, u64 size) const {
LOG_WARNING(Service_FS, "(STUBBED) called"); NGLOG_WARNING(Service_FS, "(STUBBED) called");
std::string full_path = base_directory + path; std::string full_path = base_directory + path;
if (size == 0) { if (size == 0) {
@ -101,7 +107,7 @@ ResultCode Disk_FileSystem::CreateFile(const std::string& path, u64 size) const
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
LOG_ERROR(Service_FS, "Too large file"); NGLOG_ERROR(Service_FS, "Too large file");
// TODO(Subv): Find out the correct error code // TODO(Subv): Find out the correct error code
return ResultCode(-1); return ResultCode(-1);
} }
@ -114,13 +120,13 @@ ResultCode Disk_FileSystem::CreateDirectory(const std::string& path) const {
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
LOG_CRITICAL(Service_FS, "(unreachable) Unknown error creating %s", full_path.c_str()); NGLOG_CRITICAL(Service_FS, "(unreachable) Unknown error creating {}", full_path);
// TODO(wwylele): Use correct error code // TODO(wwylele): Use correct error code
return ResultCode(-1); return ResultCode(-1);
} }
ResultCode Disk_FileSystem::RenameDirectory(const Path& src_path, const Path& dest_path) const { ResultCode Disk_FileSystem::RenameDirectory(const Path& src_path, const Path& dest_path) const {
LOG_WARNING(Service_FS, "(STUBBED) called"); NGLOG_WARNING(Service_FS, "(STUBBED) called");
// TODO(wwylele): Use correct error code // TODO(wwylele): Use correct error code
return ResultCode(-1); return ResultCode(-1);
} }
@ -140,7 +146,7 @@ ResultVal<std::unique_ptr<DirectoryBackend>> Disk_FileSystem::OpenDirectory(
} }
u64 Disk_FileSystem::GetFreeSpaceSize() const { u64 Disk_FileSystem::GetFreeSpaceSize() const {
LOG_WARNING(Service_FS, "(STUBBED) called"); NGLOG_WARNING(Service_FS, "(STUBBED) called");
return 0; return 0;
} }
@ -157,14 +163,14 @@ ResultVal<FileSys::EntryType> Disk_FileSystem::GetEntryType(const std::string& p
} }
ResultVal<size_t> Disk_Storage::Read(const u64 offset, const size_t length, u8* buffer) const { ResultVal<size_t> Disk_Storage::Read(const u64 offset, const size_t length, u8* buffer) const {
LOG_TRACE(Service_FS, "called offset=%llu, length=%zu", offset, length); NGLOG_TRACE(Service_FS, "called offset={}, length={}", offset, length);
file->Seek(offset, SEEK_SET); file->Seek(offset, SEEK_SET);
return MakeResult<size_t>(file->ReadBytes(buffer, length)); return MakeResult<size_t>(file->ReadBytes(buffer, length));
} }
ResultVal<size_t> Disk_Storage::Write(const u64 offset, const size_t length, const bool flush, ResultVal<size_t> Disk_Storage::Write(const u64 offset, const size_t length, const bool flush,
const u8* buffer) const { const u8* buffer) const {
LOG_WARNING(Service_FS, "(STUBBED) called"); NGLOG_WARNING(Service_FS, "(STUBBED) called");
file->Seek(offset, SEEK_SET); file->Seek(offset, SEEK_SET);
size_t written = file->WriteBytes(buffer, length); size_t written = file->WriteBytes(buffer, length);
if (flush) { if (flush) {
@ -198,8 +204,7 @@ u64 Disk_Directory::Read(const u64 count, Entry* entries) {
const std::string& filename = file.virtualName; const std::string& filename = file.virtualName;
Entry& entry = entries[entries_read]; Entry& entry = entries[entries_read];
LOG_TRACE(Service_FS, "File %s: size=%llu dir=%d", filename.c_str(), file.size, NGLOG_TRACE(Service_FS, "File {}: size={} dir={}", filename, file.size, file.isDirectory);
file.isDirectory);
// TODO(Link Mauve): use a proper conversion to UTF-16. // TODO(Link Mauve): use a proper conversion to UTF-16.
for (size_t j = 0; j < FILENAME_LENGTH; ++j) { for (size_t j = 0; j < FILENAME_LENGTH; ++j) {

View file

@ -26,7 +26,7 @@ public:
ResultVal<std::unique_ptr<StorageBackend>> OpenFile(const std::string& path, ResultVal<std::unique_ptr<StorageBackend>> OpenFile(const std::string& path,
Mode mode) const override; Mode mode) const override;
ResultCode DeleteFile(const std::string& path) const override; ResultCode DeleteFile(const std::string& path) const override;
ResultCode RenameFile(const Path& src_path, const Path& dest_path) const override; ResultCode RenameFile(const std::string& src_path, const std::string& dest_path) const override;
ResultCode DeleteDirectory(const Path& path) const override; ResultCode DeleteDirectory(const Path& path) const override;
ResultCode DeleteDirectoryRecursively(const Path& path) const override; ResultCode DeleteDirectoryRecursively(const Path& path) const override;
ResultCode CreateFile(const std::string& path, u64 size) const override; ResultCode CreateFile(const std::string& path, u64 size) const override;

View file

@ -71,7 +71,7 @@ std::string Path::AsString() const {
case Binary: case Binary:
default: default:
// TODO(yuriks): Add assert // TODO(yuriks): Add assert
LOG_ERROR(Service_FS, "LowPathType cannot be converted to string!"); NGLOG_ERROR(Service_FS, "LowPathType cannot be converted to string!");
return {}; return {};
} }
} }
@ -87,7 +87,7 @@ std::u16string Path::AsU16Str() const {
case Invalid: case Invalid:
case Binary: case Binary:
// TODO(yuriks): Add assert // TODO(yuriks): Add assert
LOG_ERROR(Service_FS, "LowPathType cannot be converted to u16string!"); NGLOG_ERROR(Service_FS, "LowPathType cannot be converted to u16string!");
return {}; return {};
} }
@ -115,7 +115,7 @@ std::vector<u8> Path::AsBinary() const {
case Invalid: case Invalid:
default: default:
// TODO(yuriks): Add assert // TODO(yuriks): Add assert
LOG_ERROR(Service_FS, "LowPathType cannot be converted to binary!"); NGLOG_ERROR(Service_FS, "LowPathType cannot be converted to binary!");
return {}; return {};
} }
} }

View file

@ -126,7 +126,8 @@ public:
* @param dest_path Destination path relative to the archive * @param dest_path Destination path relative to the archive
* @return Result of the operation * @return Result of the operation
*/ */
virtual ResultCode RenameFile(const Path& src_path, const Path& dest_path) const = 0; virtual ResultCode RenameFile(const std::string& src_path,
const std::string& dest_path) const = 0;
/** /**
* Rename a Directory specified by its path * Rename a Directory specified by its path

View file

@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <cinttypes>
#include <utility> #include <utility>
#include "common/file_util.h" #include "common/file_util.h"
#include "common/logging/log.h" #include "common/logging/log.h"
@ -40,7 +39,7 @@ Loader::ResultStatus PartitionFilesystem::Load(const std::string& file_path, siz
Loader::ResultStatus result = Load(file_data); Loader::ResultStatus result = Load(file_data);
if (result != Loader::ResultStatus::Success) if (result != Loader::ResultStatus::Success)
LOG_ERROR(Service_FS, "Failed to load PFS from file %s!", file_path.c_str()); NGLOG_ERROR(Service_FS, "Failed to load PFS from file {}!", file_path);
return result; return result;
} }

View file

@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <cinttypes>
#include "common/file_util.h" #include "common/file_util.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/file_sys/program_metadata.h" #include "core/file_sys/program_metadata.h"
@ -22,7 +21,7 @@ Loader::ResultStatus ProgramMetadata::Load(const std::string& file_path) {
Loader::ResultStatus result = Load(file_data); Loader::ResultStatus result = Load(file_data);
if (result != Loader::ResultStatus::Success) if (result != Loader::ResultStatus::Success)
LOG_ERROR(Service_FS, "Failed to load NPDM from file %s!", file_path.c_str()); NGLOG_ERROR(Service_FS, "Failed to load NPDM from file {}!", file_path);
return result; return result;
} }
@ -77,13 +76,13 @@ u64 ProgramMetadata::GetFilesystemPermissions() const {
} }
void ProgramMetadata::Print() const { void ProgramMetadata::Print() const {
LOG_DEBUG(Service_FS, "Magic: %.4s", npdm_header.magic.data()); NGLOG_DEBUG(Service_FS, "Magic: {:.4}", npdm_header.magic.data());
LOG_DEBUG(Service_FS, "Main thread priority: 0x%02x", npdm_header.main_thread_priority); NGLOG_DEBUG(Service_FS, "Main thread priority: {:#04X}", npdm_header.main_thread_priority);
LOG_DEBUG(Service_FS, "Main thread core: %u", npdm_header.main_thread_cpu); NGLOG_DEBUG(Service_FS, "Main thread core: {}", npdm_header.main_thread_cpu);
LOG_DEBUG(Service_FS, "Main thread stack size: 0x%x bytes", npdm_header.main_stack_size); NGLOG_DEBUG(Service_FS, "Main thread stack size: {:#X} bytes", npdm_header.main_stack_size);
LOG_DEBUG(Service_FS, "Process category: %u", npdm_header.process_category); NGLOG_DEBUG(Service_FS, "Process category: {}", npdm_header.process_category);
LOG_DEBUG(Service_FS, "Flags: %02x", npdm_header.flags); NGLOG_DEBUG(Service_FS, "Flags: {:02X}", npdm_header.flags);
LOG_DEBUG(Service_FS, " > 64-bit instructions: %s", NGLOG_DEBUG(Service_FS, " > 64-bit instructions: {}",
npdm_header.has_64_bit_instructions ? "YES" : "NO"); npdm_header.has_64_bit_instructions ? "YES" : "NO");
auto address_space = "Unknown"; auto address_space = "Unknown";
@ -96,19 +95,19 @@ void ProgramMetadata::Print() const {
break; break;
} }
LOG_DEBUG(Service_FS, " > Address space: %s\n", address_space); NGLOG_DEBUG(Service_FS, " > Address space: {}\n", address_space);
// Begin ACID printing (potential perms, signed) // Begin ACID printing (potential perms, signed)
LOG_DEBUG(Service_FS, "Magic: %.4s", acid_header.magic.data()); NGLOG_DEBUG(Service_FS, "Magic: {:.4}", acid_header.magic.data());
LOG_DEBUG(Service_FS, "Flags: %02x", acid_header.flags); NGLOG_DEBUG(Service_FS, "Flags: {:02X}", acid_header.flags);
LOG_DEBUG(Service_FS, " > Is Retail: %s", acid_header.is_retail ? "YES" : "NO"); NGLOG_DEBUG(Service_FS, " > Is Retail: {}", acid_header.is_retail ? "YES" : "NO");
LOG_DEBUG(Service_FS, "Title ID Min: %016" PRIX64, acid_header.title_id_min); NGLOG_DEBUG(Service_FS, "Title ID Min: {:016X}", acid_header.title_id_min);
LOG_DEBUG(Service_FS, "Title ID Max: %016" PRIX64, acid_header.title_id_max); NGLOG_DEBUG(Service_FS, "Title ID Max: {:016X}", acid_header.title_id_max);
LOG_DEBUG(Service_FS, "Filesystem Access: %016" PRIX64 "\n", acid_file_access.permissions); NGLOG_DEBUG(Service_FS, "Filesystem Access: {:016X}\n", acid_file_access.permissions);
// Begin ACI0 printing (actual perms, unsigned) // Begin ACI0 printing (actual perms, unsigned)
LOG_DEBUG(Service_FS, "Magic: %.4s", aci_header.magic.data()); NGLOG_DEBUG(Service_FS, "Magic: {:.4}", aci_header.magic.data());
LOG_DEBUG(Service_FS, "Title ID: %016" PRIX64, aci_header.title_id); NGLOG_DEBUG(Service_FS, "Title ID: {:016X}", aci_header.title_id);
LOG_DEBUG(Service_FS, "Filesystem Access: %016" PRIX64 "\n", aci_file_access.permissions); NGLOG_DEBUG(Service_FS, "Filesystem Access: {:016X}\n", aci_file_access.permissions);
} }
} // namespace FileSys } // namespace FileSys

View file

@ -14,7 +14,7 @@ namespace FileSys {
RomFS_Factory::RomFS_Factory(Loader::AppLoader& app_loader) { RomFS_Factory::RomFS_Factory(Loader::AppLoader& app_loader) {
// Load the RomFS from the app // Load the RomFS from the app
if (Loader::ResultStatus::Success != app_loader.ReadRomFS(romfs_file, data_offset, data_size)) { if (Loader::ResultStatus::Success != app_loader.ReadRomFS(romfs_file, data_offset, data_size)) {
LOG_ERROR(Service_FS, "Unable to read RomFS!"); NGLOG_ERROR(Service_FS, "Unable to read RomFS!");
} }
} }
@ -24,13 +24,13 @@ ResultVal<std::unique_ptr<FileSystemBackend>> RomFS_Factory::Open(const Path& pa
} }
ResultCode RomFS_Factory::Format(const Path& path) { ResultCode RomFS_Factory::Format(const Path& path) {
LOG_ERROR(Service_FS, "Unimplemented Format archive %s", GetName().c_str()); NGLOG_ERROR(Service_FS, "Unimplemented Format archive {}", GetName());
// TODO(bunnei): Find the right error code for this // TODO(bunnei): Find the right error code for this
return ResultCode(-1); return ResultCode(-1);
} }
ResultVal<ArchiveFormatInfo> RomFS_Factory::GetFormatInfo(const Path& path) const { ResultVal<ArchiveFormatInfo> RomFS_Factory::GetFormatInfo(const Path& path) const {
LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive %s", GetName().c_str()); NGLOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive {}", GetName());
// TODO(bunnei): Find the right error code for this // TODO(bunnei): Find the right error code for this
return ResultCode(-1); return ResultCode(-1);
} }

View file

@ -21,73 +21,72 @@ ResultVal<std::unique_ptr<StorageBackend>> RomFS_FileSystem::OpenFile(const std:
} }
ResultCode RomFS_FileSystem::DeleteFile(const std::string& path) const { ResultCode RomFS_FileSystem::DeleteFile(const std::string& path) const {
LOG_CRITICAL(Service_FS, "Attempted to delete a file from an ROMFS archive (%s).", NGLOG_CRITICAL(Service_FS, "Attempted to delete a file from an ROMFS archive ({}).", GetName());
GetName().c_str());
// TODO(bunnei): Use correct error code // TODO(bunnei): Use correct error code
return ResultCode(-1); return ResultCode(-1);
} }
ResultCode RomFS_FileSystem::RenameFile(const Path& src_path, const Path& dest_path) const { ResultCode RomFS_FileSystem::RenameFile(const std::string& src_path,
LOG_CRITICAL(Service_FS, "Attempted to rename a file within an ROMFS archive (%s).", const std::string& dest_path) const {
GetName().c_str()); NGLOG_CRITICAL(Service_FS, "Attempted to rename a file within an ROMFS archive ({}).",
GetName());
// TODO(wwylele): Use correct error code // TODO(wwylele): Use correct error code
return ResultCode(-1); return ResultCode(-1);
} }
ResultCode RomFS_FileSystem::DeleteDirectory(const Path& path) const { ResultCode RomFS_FileSystem::DeleteDirectory(const Path& path) const {
LOG_CRITICAL(Service_FS, "Attempted to delete a directory from an ROMFS archive (%s).", NGLOG_CRITICAL(Service_FS, "Attempted to delete a directory from an ROMFS archive ({}).",
GetName().c_str()); GetName());
// TODO(wwylele): Use correct error code // TODO(wwylele): Use correct error code
return ResultCode(-1); return ResultCode(-1);
} }
ResultCode RomFS_FileSystem::DeleteDirectoryRecursively(const Path& path) const { ResultCode RomFS_FileSystem::DeleteDirectoryRecursively(const Path& path) const {
LOG_CRITICAL(Service_FS, "Attempted to delete a directory from an ROMFS archive (%s).", NGLOG_CRITICAL(Service_FS, "Attempted to delete a directory from an ROMFS archive ({}).",
GetName().c_str()); GetName());
// TODO(wwylele): Use correct error code // TODO(wwylele): Use correct error code
return ResultCode(-1); return ResultCode(-1);
} }
ResultCode RomFS_FileSystem::CreateFile(const std::string& path, u64 size) const { ResultCode RomFS_FileSystem::CreateFile(const std::string& path, u64 size) const {
LOG_CRITICAL(Service_FS, "Attempted to create a file in an ROMFS archive (%s).", NGLOG_CRITICAL(Service_FS, "Attempted to create a file in an ROMFS archive ({}).", GetName());
GetName().c_str());
// TODO(bunnei): Use correct error code // TODO(bunnei): Use correct error code
return ResultCode(-1); return ResultCode(-1);
} }
ResultCode RomFS_FileSystem::CreateDirectory(const std::string& path) const { ResultCode RomFS_FileSystem::CreateDirectory(const std::string& path) const {
LOG_CRITICAL(Service_FS, "Attempted to create a directory in an ROMFS archive (%s).", NGLOG_CRITICAL(Service_FS, "Attempted to create a directory in an ROMFS archive ({}).",
GetName().c_str()); GetName());
// TODO(wwylele): Use correct error code // TODO(wwylele): Use correct error code
return ResultCode(-1); return ResultCode(-1);
} }
ResultCode RomFS_FileSystem::RenameDirectory(const Path& src_path, const Path& dest_path) const { ResultCode RomFS_FileSystem::RenameDirectory(const Path& src_path, const Path& dest_path) const {
LOG_CRITICAL(Service_FS, "Attempted to rename a file within an ROMFS archive (%s).", NGLOG_CRITICAL(Service_FS, "Attempted to rename a file within an ROMFS archive ({}).",
GetName().c_str()); GetName());
// TODO(wwylele): Use correct error code // TODO(wwylele): Use correct error code
return ResultCode(-1); return ResultCode(-1);
} }
ResultVal<std::unique_ptr<DirectoryBackend>> RomFS_FileSystem::OpenDirectory( ResultVal<std::unique_ptr<DirectoryBackend>> RomFS_FileSystem::OpenDirectory(
const std::string& path) const { const std::string& path) const {
LOG_WARNING(Service_FS, "Opening Directory in a ROMFS archive"); NGLOG_WARNING(Service_FS, "Opening Directory in a ROMFS archive");
return MakeResult<std::unique_ptr<DirectoryBackend>>(std::make_unique<ROMFSDirectory>()); return MakeResult<std::unique_ptr<DirectoryBackend>>(std::make_unique<ROMFSDirectory>());
} }
u64 RomFS_FileSystem::GetFreeSpaceSize() const { u64 RomFS_FileSystem::GetFreeSpaceSize() const {
LOG_WARNING(Service_FS, "Attempted to get the free space in an ROMFS archive"); NGLOG_WARNING(Service_FS, "Attempted to get the free space in an ROMFS archive");
return 0; return 0;
} }
ResultVal<FileSys::EntryType> RomFS_FileSystem::GetEntryType(const std::string& path) const { ResultVal<FileSys::EntryType> RomFS_FileSystem::GetEntryType(const std::string& path) const {
LOG_CRITICAL(Service_FS, "Called within an ROMFS archive (path %s).", path.c_str()); NGLOG_CRITICAL(Service_FS, "Called within an ROMFS archive (path {}).", path);
// TODO(wwylele): Use correct error code // TODO(wwylele): Use correct error code
return ResultCode(-1); return ResultCode(-1);
} }
ResultVal<size_t> RomFS_Storage::Read(const u64 offset, const size_t length, u8* buffer) const { ResultVal<size_t> RomFS_Storage::Read(const u64 offset, const size_t length, u8* buffer) const {
LOG_TRACE(Service_FS, "called offset=%llu, length=%zu", offset, length); NGLOG_TRACE(Service_FS, "called offset={}, length={}", offset, length);
romfs_file->Seek(data_offset + offset, SEEK_SET); romfs_file->Seek(data_offset + offset, SEEK_SET);
size_t read_length = (size_t)std::min((u64)length, data_size - offset); size_t read_length = (size_t)std::min((u64)length, data_size - offset);
@ -96,7 +95,7 @@ ResultVal<size_t> RomFS_Storage::Read(const u64 offset, const size_t length, u8*
ResultVal<size_t> RomFS_Storage::Write(const u64 offset, const size_t length, const bool flush, ResultVal<size_t> RomFS_Storage::Write(const u64 offset, const size_t length, const bool flush,
const u8* buffer) const { const u8* buffer) const {
LOG_ERROR(Service_FS, "Attempted to write to ROMFS file"); NGLOG_ERROR(Service_FS, "Attempted to write to ROMFS file");
// TODO(Subv): Find error code // TODO(Subv): Find error code
return MakeResult<size_t>(0); return MakeResult<size_t>(0);
} }
@ -106,7 +105,7 @@ u64 RomFS_Storage::GetSize() const {
} }
bool RomFS_Storage::SetSize(const u64 size) const { bool RomFS_Storage::SetSize(const u64 size) const {
LOG_ERROR(Service_FS, "Attempted to set the size of an ROMFS file"); NGLOG_ERROR(Service_FS, "Attempted to set the size of an ROMFS file");
return false; return false;
} }

View file

@ -32,7 +32,7 @@ public:
ResultVal<std::unique_ptr<StorageBackend>> OpenFile(const std::string& path, ResultVal<std::unique_ptr<StorageBackend>> OpenFile(const std::string& path,
Mode mode) const override; Mode mode) const override;
ResultCode DeleteFile(const std::string& path) const override; ResultCode DeleteFile(const std::string& path) const override;
ResultCode RenameFile(const Path& src_path, const Path& dest_path) const override; ResultCode RenameFile(const std::string& src_path, const std::string& dest_path) const override;
ResultCode DeleteDirectory(const Path& path) const override; ResultCode DeleteDirectory(const Path& path) const override;
ResultCode DeleteDirectoryRecursively(const Path& path) const override; ResultCode DeleteDirectoryRecursively(const Path& path) const override;
ResultCode CreateFile(const std::string& path, u64 size) const override; ResultCode CreateFile(const std::string& path, u64 size) const override;

View file

@ -2,11 +2,9 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <cinttypes>
#include <memory> #include <memory>
#include "common/common_types.h" #include "common/common_types.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/string_util.h"
#include "core/core.h" #include "core/core.h"
#include "core/file_sys/disk_filesystem.h" #include "core/file_sys/disk_filesystem.h"
#include "core/file_sys/savedata_factory.h" #include "core/file_sys/savedata_factory.h"
@ -30,7 +28,7 @@ ResultVal<std::unique_ptr<FileSystemBackend>> SaveData_Factory::Open(const Path&
} }
ResultCode SaveData_Factory::Format(const Path& path) { ResultCode SaveData_Factory::Format(const Path& path) {
LOG_WARNING(Service_FS, "Format archive %s", GetName().c_str()); NGLOG_WARNING(Service_FS, "Format archive {}", GetName());
// Create the save data directory. // Create the save data directory.
if (!FileUtil::CreateFullPath(GetFullPath())) { if (!FileUtil::CreateFullPath(GetFullPath())) {
// TODO(Subv): Find the correct error code. // TODO(Subv): Find the correct error code.
@ -41,7 +39,7 @@ ResultCode SaveData_Factory::Format(const Path& path) {
} }
ResultVal<ArchiveFormatInfo> SaveData_Factory::GetFormatInfo(const Path& path) const { ResultVal<ArchiveFormatInfo> SaveData_Factory::GetFormatInfo(const Path& path) const {
LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive %s", GetName().c_str()); NGLOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive {}", GetName());
// TODO(bunnei): Find the right error code for this // TODO(bunnei): Find the right error code for this
return ResultCode(-1); return ResultCode(-1);
} }
@ -50,8 +48,7 @@ std::string SaveData_Factory::GetFullPath() const {
u64 title_id = Core::CurrentProcess()->program_id; u64 title_id = Core::CurrentProcess()->program_id;
// TODO(Subv): Somehow obtain this value. // TODO(Subv): Somehow obtain this value.
u32 user = 0; u32 user = 0;
return Common::StringFromFormat("%ssave/%016" PRIX64 "/%08X/", nand_directory.c_str(), title_id, return fmt::format("{}save/{:016X}/{:08X}/", nand_directory, title_id, user);
user);
} }
} // namespace FileSys } // namespace FileSys

View file

@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <cinttypes>
#include <memory> #include <memory>
#include "common/common_types.h" #include "common/common_types.h"
#include "common/logging/log.h" #include "common/logging/log.h"
@ -26,13 +25,13 @@ ResultVal<std::unique_ptr<FileSystemBackend>> SDMC_Factory::Open(const Path& pat
} }
ResultCode SDMC_Factory::Format(const Path& path) { ResultCode SDMC_Factory::Format(const Path& path) {
LOG_ERROR(Service_FS, "Unimplemented Format archive %s", GetName().c_str()); NGLOG_ERROR(Service_FS, "Unimplemented Format archive {}", GetName());
// TODO(Subv): Find the right error code for this // TODO(Subv): Find the right error code for this
return ResultCode(-1); return ResultCode(-1);
} }
ResultVal<ArchiveFormatInfo> SDMC_Factory::GetFormatInfo(const Path& path) const { ResultVal<ArchiveFormatInfo> SDMC_Factory::GetFormatInfo(const Path& path) const {
LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive %s", GetName().c_str()); NGLOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive {}", GetName());
// TODO(bunnei): Find the right error code for this // TODO(bunnei): Find the right error code for this
return ResultCode(-1); return ResultCode(-1);
} }

View file

@ -6,7 +6,6 @@
#include <algorithm> #include <algorithm>
#include <atomic> #include <atomic>
#include <cinttypes>
#include <climits> #include <climits>
#include <csignal> #include <csignal>
#include <cstdarg> #include <cstdarg>
@ -180,7 +179,7 @@ static u8 HexCharToValue(u8 hex) {
return hex - 'A' + 0xA; return hex - 'A' + 0xA;
} }
LOG_ERROR(Debug_GDBStub, "Invalid nibble: %c (%02x)\n", hex, hex); NGLOG_ERROR(Debug_GDBStub, "Invalid nibble: {} ({:02X})", hex, hex);
return 0; return 0;
} }
@ -320,7 +319,7 @@ static u8 ReadByte() {
u8 c; u8 c;
size_t received_size = recv(gdbserver_socket, reinterpret_cast<char*>(&c), 1, MSG_WAITALL); size_t received_size = recv(gdbserver_socket, reinterpret_cast<char*>(&c), 1, MSG_WAITALL);
if (received_size != 1) { if (received_size != 1) {
LOG_ERROR(Debug_GDBStub, "recv failed : %ld", received_size); NGLOG_ERROR(Debug_GDBStub, "recv failed: {}", received_size);
Shutdown(); Shutdown();
} }
@ -361,8 +360,7 @@ static void RemoveBreakpoint(BreakpointType type, PAddr addr) {
auto bp = p.find(static_cast<u64>(addr)); auto bp = p.find(static_cast<u64>(addr));
if (bp != p.end()) { if (bp != p.end()) {
LOG_DEBUG(Debug_GDBStub, NGLOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: {:016X} bytes at {:016X} of type {}",
"gdb: removed a breakpoint: %016" PRIx64 " bytes at %016" PRIx64 " of type %d\n",
bp->second.len, bp->second.addr, static_cast<int>(type)); bp->second.len, bp->second.addr, static_cast<int>(type));
p.erase(static_cast<u64>(addr)); p.erase(static_cast<u64>(addr));
} }
@ -408,9 +406,9 @@ bool CheckBreakpoint(PAddr addr, BreakpointType type) {
} }
if (bp->second.active && (addr >= bp->second.addr && addr < bp->second.addr + len)) { if (bp->second.active && (addr >= bp->second.addr && addr < bp->second.addr + len)) {
LOG_DEBUG(Debug_GDBStub, NGLOG_DEBUG(Debug_GDBStub,
"Found breakpoint type %d @ %016" PRIx64 ", range: %016" PRIx64 "Found breakpoint type {} @ {:016X}, range: {:016X}"
" - %016" PRIx64 " (%" PRIx64 " bytes)\n", " - {:016X} ({:X} bytes)",
static_cast<int>(type), addr, bp->second.addr, bp->second.addr + len, len); static_cast<int>(type), addr, bp->second.addr, bp->second.addr + len, len);
return true; return true;
} }
@ -427,7 +425,7 @@ bool CheckBreakpoint(PAddr addr, BreakpointType type) {
static void SendPacket(const char packet) { static void SendPacket(const char packet) {
size_t sent_size = send(gdbserver_socket, &packet, 1, 0); size_t sent_size = send(gdbserver_socket, &packet, 1, 0);
if (sent_size != 1) { if (sent_size != 1) {
LOG_ERROR(Debug_GDBStub, "send failed"); NGLOG_ERROR(Debug_GDBStub, "send failed");
} }
} }
@ -445,7 +443,7 @@ static void SendReply(const char* reply) {
command_length = static_cast<u32>(strlen(reply)); command_length = static_cast<u32>(strlen(reply));
if (command_length + 4 > sizeof(command_buffer)) { if (command_length + 4 > sizeof(command_buffer)) {
LOG_ERROR(Debug_GDBStub, "command_buffer overflow in SendReply"); NGLOG_ERROR(Debug_GDBStub, "command_buffer overflow in SendReply");
return; return;
} }
@ -462,7 +460,7 @@ static void SendReply(const char* reply) {
while (left > 0) { while (left > 0) {
int sent_size = send(gdbserver_socket, reinterpret_cast<char*>(ptr), left, 0); int sent_size = send(gdbserver_socket, reinterpret_cast<char*>(ptr), left, 0);
if (sent_size < 0) { if (sent_size < 0) {
LOG_ERROR(Debug_GDBStub, "gdb: send failed"); NGLOG_ERROR(Debug_GDBStub, "gdb: send failed");
return Shutdown(); return Shutdown();
} }
@ -473,7 +471,7 @@ static void SendReply(const char* reply) {
/// Handle query command from gdb client. /// Handle query command from gdb client.
static void HandleQuery() { static void HandleQuery() {
LOG_DEBUG(Debug_GDBStub, "gdb: query '%s'\n", command_buffer + 1); NGLOG_DEBUG(Debug_GDBStub, "gdb: query '{}'", command_buffer + 1);
const char* query = reinterpret_cast<const char*>(command_buffer + 1); const char* query = reinterpret_cast<const char*>(command_buffer + 1);
@ -512,8 +510,8 @@ static void SendSignal(u32 signal) {
latest_signal = signal; latest_signal = signal;
std::string buffer = Common::StringFromFormat("T%02x", latest_signal); std::string buffer = fmt::format("T{:02x}", latest_signal);
LOG_DEBUG(Debug_GDBStub, "Response: %s", buffer.c_str()); NGLOG_DEBUG(Debug_GDBStub, "Response: {}", buffer);
SendReply(buffer.c_str()); SendReply(buffer.c_str());
} }
@ -527,18 +525,18 @@ static void ReadCommand() {
// ignore ack // ignore ack
return; return;
} else if (c == 0x03) { } else if (c == 0x03) {
LOG_INFO(Debug_GDBStub, "gdb: found break command\n"); NGLOG_INFO(Debug_GDBStub, "gdb: found break command");
halt_loop = true; halt_loop = true;
SendSignal(SIGTRAP); SendSignal(SIGTRAP);
return; return;
} else if (c != GDB_STUB_START) { } else if (c != GDB_STUB_START) {
LOG_DEBUG(Debug_GDBStub, "gdb: read invalid byte %02x\n", c); NGLOG_DEBUG(Debug_GDBStub, "gdb: read invalid byte {:02X}", c);
return; return;
} }
while ((c = ReadByte()) != GDB_STUB_END) { while ((c = ReadByte()) != GDB_STUB_END) {
if (command_length >= sizeof(command_buffer)) { if (command_length >= sizeof(command_buffer)) {
LOG_ERROR(Debug_GDBStub, "gdb: command_buffer overflow\n"); NGLOG_ERROR(Debug_GDBStub, "gdb: command_buffer overflow");
SendPacket(GDB_STUB_NACK); SendPacket(GDB_STUB_NACK);
return; return;
} }
@ -551,8 +549,9 @@ static void ReadCommand() {
u8 checksum_calculated = CalculateChecksum(command_buffer, command_length); u8 checksum_calculated = CalculateChecksum(command_buffer, command_length);
if (checksum_received != checksum_calculated) { if (checksum_received != checksum_calculated) {
LOG_ERROR(Debug_GDBStub, NGLOG_ERROR(
"gdb: invalid checksum: calculated %02x and read %02x for $%s# (length: %d)\n", Debug_GDBStub,
"gdb: invalid checksum: calculated {:02X} and read {:02X} for ${}# (length: {})",
checksum_calculated, checksum_received, command_buffer, command_length); checksum_calculated, checksum_received, command_buffer, command_length);
command_length = 0; command_length = 0;
@ -580,7 +579,7 @@ static bool IsDataAvailable() {
t.tv_usec = 0; t.tv_usec = 0;
if (select(gdbserver_socket + 1, &fd_socket, nullptr, nullptr, &t) < 0) { if (select(gdbserver_socket + 1, &fd_socket, nullptr, nullptr, &t) < 0) {
LOG_ERROR(Debug_GDBStub, "select failed"); NGLOG_ERROR(Debug_GDBStub, "select failed");
return false; return false;
} }
@ -693,7 +692,7 @@ static void ReadMemory() {
u64 len = u64 len =
HexToLong(start_offset, static_cast<u64>((command_buffer + command_length) - start_offset)); HexToLong(start_offset, static_cast<u64>((command_buffer + command_length) - start_offset));
LOG_DEBUG(Debug_GDBStub, "gdb: addr: %016lx len: %016lx\n", addr, len); NGLOG_DEBUG(Debug_GDBStub, "gdb: addr: {:016X} len: {:016X}", addr, len);
if (len * 2 > sizeof(reply)) { if (len * 2 > sizeof(reply)) {
SendReply("E01"); SendReply("E01");
@ -781,7 +780,7 @@ static bool CommitBreakpoint(BreakpointType type, PAddr addr, u64 len) {
breakpoint.len = len; breakpoint.len = len;
p.insert({addr, breakpoint}); p.insert({addr, breakpoint});
LOG_DEBUG(Debug_GDBStub, "gdb: added %d breakpoint: %016" PRIx64 " bytes at %016" PRIx64 "\n", NGLOG_DEBUG(Debug_GDBStub, "gdb: added {} breakpoint: {:016X} bytes at {:016X}",
static_cast<int>(type), breakpoint.len, breakpoint.addr); static_cast<int>(type), breakpoint.len, breakpoint.addr);
return true; return true;
@ -889,7 +888,7 @@ void HandlePacket() {
return; return;
} }
LOG_DEBUG(Debug_GDBStub, "Packet: %s", command_buffer); NGLOG_DEBUG(Debug_GDBStub, "Packet: {}", command_buffer);
switch (command_buffer[0]) { switch (command_buffer[0]) {
case 'q': case 'q':
@ -903,7 +902,7 @@ void HandlePacket() {
break; break;
case 'k': case 'k':
Shutdown(); Shutdown();
LOG_INFO(Debug_GDBStub, "killed by gdb"); NGLOG_INFO(Debug_GDBStub, "killed by gdb");
return; return;
case 'g': case 'g':
ReadRegisters(); ReadRegisters();
@ -982,7 +981,7 @@ static void Init(u16 port) {
breakpoints_write.clear(); breakpoints_write.clear();
// Start gdb server // Start gdb server
LOG_INFO(Debug_GDBStub, "Starting GDB server on port %d...", port); NGLOG_INFO(Debug_GDBStub, "Starting GDB server on port {}...", port);
sockaddr_in saddr_server = {}; sockaddr_in saddr_server = {};
saddr_server.sin_family = AF_INET; saddr_server.sin_family = AF_INET;
@ -995,28 +994,28 @@ static void Init(u16 port) {
int tmpsock = static_cast<int>(socket(PF_INET, SOCK_STREAM, 0)); int tmpsock = static_cast<int>(socket(PF_INET, SOCK_STREAM, 0));
if (tmpsock == -1) { if (tmpsock == -1) {
LOG_ERROR(Debug_GDBStub, "Failed to create gdb socket"); NGLOG_ERROR(Debug_GDBStub, "Failed to create gdb socket");
} }
// Set socket to SO_REUSEADDR so it can always bind on the same port // Set socket to SO_REUSEADDR so it can always bind on the same port
int reuse_enabled = 1; int reuse_enabled = 1;
if (setsockopt(tmpsock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse_enabled, if (setsockopt(tmpsock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse_enabled,
sizeof(reuse_enabled)) < 0) { sizeof(reuse_enabled)) < 0) {
LOG_ERROR(Debug_GDBStub, "Failed to set gdb socket option"); NGLOG_ERROR(Debug_GDBStub, "Failed to set gdb socket option");
} }
const sockaddr* server_addr = reinterpret_cast<const sockaddr*>(&saddr_server); const sockaddr* server_addr = reinterpret_cast<const sockaddr*>(&saddr_server);
socklen_t server_addrlen = sizeof(saddr_server); socklen_t server_addrlen = sizeof(saddr_server);
if (bind(tmpsock, server_addr, server_addrlen) < 0) { if (bind(tmpsock, server_addr, server_addrlen) < 0) {
LOG_ERROR(Debug_GDBStub, "Failed to bind gdb socket"); NGLOG_ERROR(Debug_GDBStub, "Failed to bind gdb socket");
} }
if (listen(tmpsock, 1) < 0) { if (listen(tmpsock, 1) < 0) {
LOG_ERROR(Debug_GDBStub, "Failed to listen to gdb socket"); NGLOG_ERROR(Debug_GDBStub, "Failed to listen to gdb socket");
} }
// Wait for gdb to connect // Wait for gdb to connect
LOG_INFO(Debug_GDBStub, "Waiting for gdb to connect...\n"); NGLOG_INFO(Debug_GDBStub, "Waiting for gdb to connect...");
sockaddr_in saddr_client; sockaddr_in saddr_client;
sockaddr* client_addr = reinterpret_cast<sockaddr*>(&saddr_client); sockaddr* client_addr = reinterpret_cast<sockaddr*>(&saddr_client);
socklen_t client_addrlen = sizeof(saddr_client); socklen_t client_addrlen = sizeof(saddr_client);
@ -1027,9 +1026,9 @@ static void Init(u16 port) {
halt_loop = false; halt_loop = false;
step_loop = false; step_loop = false;
LOG_ERROR(Debug_GDBStub, "Failed to accept gdb client"); NGLOG_ERROR(Debug_GDBStub, "Failed to accept gdb client");
} else { } else {
LOG_INFO(Debug_GDBStub, "Client connected.\n"); NGLOG_INFO(Debug_GDBStub, "Client connected.");
saddr_client.sin_addr.s_addr = ntohl(saddr_client.sin_addr.s_addr); saddr_client.sin_addr.s_addr = ntohl(saddr_client.sin_addr.s_addr);
} }
@ -1048,7 +1047,7 @@ void Shutdown() {
return; return;
} }
LOG_INFO(Debug_GDBStub, "Stopping GDB ..."); NGLOG_INFO(Debug_GDBStub, "Stopping GDB ...");
if (gdbserver_socket != -1) { if (gdbserver_socket != -1) {
shutdown(gdbserver_socket, SHUT_RDWR); shutdown(gdbserver_socket, SHUT_RDWR);
gdbserver_socket = -1; gdbserver_socket = -1;
@ -1058,7 +1057,7 @@ void Shutdown() {
WSACleanup(); WSACleanup();
#endif #endif
LOG_INFO(Debug_GDBStub, "GDB stopped."); NGLOG_INFO(Debug_GDBStub, "GDB stopped.");
} }
bool IsServerEnabled() { bool IsServerEnabled() {

View file

@ -1,64 +0,0 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/assert.h"
#include "core/hle/kernel/condition_variable.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/object_address_table.h"
#include "core/hle/kernel/thread.h"
namespace Kernel {
ConditionVariable::ConditionVariable() {}
ConditionVariable::~ConditionVariable() {}
ResultVal<SharedPtr<ConditionVariable>> ConditionVariable::Create(VAddr guest_addr,
std::string name) {
SharedPtr<ConditionVariable> condition_variable(new ConditionVariable);
condition_variable->name = std::move(name);
condition_variable->guest_addr = guest_addr;
condition_variable->mutex_addr = 0;
// Condition variables are referenced by guest address, so track this in the kernel
g_object_address_table.Insert(guest_addr, condition_variable);
return MakeResult<SharedPtr<ConditionVariable>>(std::move(condition_variable));
}
bool ConditionVariable::ShouldWait(Thread* thread) const {
return GetAvailableCount() <= 0;
}
void ConditionVariable::Acquire(Thread* thread) {
if (GetAvailableCount() <= 0)
return;
SetAvailableCount(GetAvailableCount() - 1);
}
ResultCode ConditionVariable::Release(s32 target) {
if (target == -1) {
// When -1, wake up all waiting threads
SetAvailableCount(static_cast<s32>(GetWaitingThreads().size()));
WakeupAllWaitingThreads();
} else {
// Otherwise, wake up just a single thread
SetAvailableCount(target);
WakeupWaitingThread(GetHighestPriorityReadyThread());
}
return RESULT_SUCCESS;
}
s32 ConditionVariable::GetAvailableCount() const {
return Memory::Read32(guest_addr);
}
void ConditionVariable::SetAvailableCount(s32 value) const {
Memory::Write32(guest_addr, value);
}
} // namespace Kernel

View file

@ -1,63 +0,0 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <string>
#include <queue>
#include "common/common_types.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/wait_object.h"
#include "core/hle/result.h"
namespace Kernel {
class ConditionVariable final : public WaitObject {
public:
/**
* Creates a condition variable.
* @param guest_addr Address of the object tracking the condition variable in guest memory. If
* specified, this condition variable will update the guest object when its state changes.
* @param name Optional name of condition variable.
* @return The created condition variable.
*/
static ResultVal<SharedPtr<ConditionVariable>> Create(VAddr guest_addr,
std::string name = "Unknown");
std::string GetTypeName() const override {
return "ConditionVariable";
}
std::string GetName() const override {
return name;
}
static const HandleType HANDLE_TYPE = HandleType::ConditionVariable;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
}
s32 GetAvailableCount() const;
void SetAvailableCount(s32 value) const;
std::string name; ///< Name of condition variable (optional)
VAddr guest_addr; ///< Address of the guest condition variable value
VAddr mutex_addr; ///< (optional) Address of guest mutex value associated with this condition
///< variable, used for implementing events
bool ShouldWait(Thread* thread) const override;
void Acquire(Thread* thread) override;
/**
* Releases a slot from a condition variable.
* @param target The number of threads to wakeup, -1 is all.
* @return ResultCode indicating if the operation succeeded.
*/
ResultCode Release(s32 target);
private:
ConditionVariable();
~ConditionVariable() override;
};
} // namespace Kernel

View file

@ -20,6 +20,7 @@ enum {
MaxConnectionsReached = 52, MaxConnectionsReached = 52,
// Confirmed Switch OS error codes // Confirmed Switch OS error codes
MisalignedAddress = 102,
InvalidHandle = 114, InvalidHandle = 114,
Timeout = 117, Timeout = 117,
SynchronizationCanceled = 118, SynchronizationCanceled = 118,

View file

@ -26,7 +26,7 @@ ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
u16 slot = next_free_slot; u16 slot = next_free_slot;
if (slot >= generations.size()) { if (slot >= generations.size()) {
LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use."); NGLOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use.");
return ERR_OUT_OF_HANDLES; return ERR_OUT_OF_HANDLES;
} }
next_free_slot = generations[slot]; next_free_slot = generations[slot];
@ -48,7 +48,7 @@ ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
ResultVal<Handle> HandleTable::Duplicate(Handle handle) { ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
SharedPtr<Object> object = GetGeneric(handle); SharedPtr<Object> object = GetGeneric(handle);
if (object == nullptr) { if (object == nullptr) {
LOG_ERROR(Kernel, "Tried to duplicate invalid handle: %08X", handle); NGLOG_ERROR(Kernel, "Tried to duplicate invalid handle: {:08X}", handle);
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
} }
return Create(std::move(object)); return Create(std::move(object));

View file

@ -118,7 +118,7 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) {
std::make_shared<IPC::DomainMessageHeader>(rp.PopRaw<IPC::DomainMessageHeader>()); std::make_shared<IPC::DomainMessageHeader>(rp.PopRaw<IPC::DomainMessageHeader>());
} else { } else {
if (Session()->IsDomain()) if (Session()->IsDomain())
LOG_WARNING(IPC, "Domain request has no DomainMessageHeader!"); NGLOG_WARNING(IPC, "Domain request has no DomainMessageHeader!");
} }
} }
@ -270,7 +270,8 @@ size_t HLERequestContext::WriteBuffer(const void* buffer, size_t size) const {
const bool is_buffer_b{BufferDescriptorB().size() && BufferDescriptorB()[0].Size()}; const bool is_buffer_b{BufferDescriptorB().size() && BufferDescriptorB()[0].Size()};
const size_t buffer_size{GetWriteBufferSize()}; const size_t buffer_size{GetWriteBufferSize()};
if (size > buffer_size) { if (size > buffer_size) {
LOG_CRITICAL(Core, "size (%016zx) is greater than buffer_size (%016zx)", size, buffer_size); NGLOG_CRITICAL(Core, "size ({:016X}) is greater than buffer_size ({:016X})", size,
buffer_size);
size = buffer_size; // TODO(bunnei): This needs to be HW tested size = buffer_size; // TODO(bunnei): This needs to be HW tested
} }

View file

@ -18,12 +18,10 @@ using Handle = u32;
enum class HandleType : u32 { enum class HandleType : u32 {
Unknown, Unknown,
Event, Event,
Mutex,
SharedMemory, SharedMemory,
Thread, Thread,
Process, Process,
AddressArbiter, AddressArbiter,
ConditionVariable,
Timer, Timer,
ResourceLimit, ResourceLimit,
CodeSet, CodeSet,
@ -63,9 +61,7 @@ public:
bool IsWaitable() const { bool IsWaitable() const {
switch (GetHandleType()) { switch (GetHandleType()) {
case HandleType::Event: case HandleType::Event:
case HandleType::Mutex:
case HandleType::Thread: case HandleType::Thread:
case HandleType::ConditionVariable:
case HandleType::Timer: case HandleType::Timer:
case HandleType::ServerPort: case HandleType::ServerPort:
case HandleType::ServerSession: case HandleType::ServerSession:

View file

@ -7,6 +7,7 @@
#include <boost/range/algorithm_ext/erase.hpp> #include <boost/range/algorithm_ext/erase.hpp>
#include "common/assert.h" #include "common/assert.h"
#include "core/core.h" #include "core/core.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/mutex.h" #include "core/hle/kernel/mutex.h"
@ -15,124 +16,120 @@
namespace Kernel { namespace Kernel {
void ReleaseThreadMutexes(Thread* thread) { /// Returns the number of threads that are waiting for a mutex, and the highest priority one among
for (auto& mtx : thread->held_mutexes) { /// those.
mtx->SetHasWaiters(false); static std::pair<SharedPtr<Thread>, u32> GetHighestPriorityMutexWaitingThread(
mtx->SetHoldingThread(nullptr); SharedPtr<Thread> current_thread, VAddr mutex_addr) {
mtx->WakeupAllWaitingThreads();
SharedPtr<Thread> highest_priority_thread;
u32 num_waiters = 0;
for (auto& thread : current_thread->wait_mutex_threads) {
if (thread->mutex_wait_address != mutex_addr)
continue;
ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX);
++num_waiters;
if (highest_priority_thread == nullptr ||
thread->GetPriority() < highest_priority_thread->GetPriority()) {
highest_priority_thread = thread;
} }
thread->held_mutexes.clear();
} }
Mutex::Mutex() {} return {highest_priority_thread, num_waiters};
Mutex::~Mutex() {}
SharedPtr<Mutex> Mutex::Create(SharedPtr<Kernel::Thread> holding_thread, VAddr guest_addr,
std::string name) {
SharedPtr<Mutex> mutex(new Mutex);
mutex->guest_addr = guest_addr;
mutex->name = std::move(name);
// If mutex was initialized with a holding thread, acquire it by the holding thread
if (holding_thread) {
mutex->Acquire(holding_thread.get());
} }
// Mutexes are referenced by guest address, so track this in the kernel /// Update the mutex owner field of all threads waiting on the mutex to point to the new owner.
g_object_address_table.Insert(guest_addr, mutex); static void TransferMutexOwnership(VAddr mutex_addr, SharedPtr<Thread> current_thread,
SharedPtr<Thread> new_owner) {
auto threads = current_thread->wait_mutex_threads;
for (auto& thread : threads) {
if (thread->mutex_wait_address != mutex_addr)
continue;
return mutex; ASSERT(thread->lock_owner == current_thread);
current_thread->RemoveMutexWaiter(thread);
if (new_owner != thread)
new_owner->AddMutexWaiter(thread);
}
} }
bool Mutex::ShouldWait(Thread* thread) const { ResultCode Mutex::TryAcquire(VAddr address, Handle holding_thread_handle,
auto holding_thread = GetHoldingThread(); Handle requesting_thread_handle) {
return holding_thread != nullptr && thread != holding_thread; // The mutex address must be 4-byte aligned
if ((address % sizeof(u32)) != 0) {
return ResultCode(ErrorModule::Kernel, ErrCodes::MisalignedAddress);
} }
void Mutex::Acquire(Thread* thread) { SharedPtr<Thread> holding_thread = g_handle_table.Get<Thread>(holding_thread_handle);
ASSERT_MSG(!ShouldWait(thread), "object unavailable!"); SharedPtr<Thread> requesting_thread = g_handle_table.Get<Thread>(requesting_thread_handle);
priority = thread->current_priority; // TODO(Subv): It is currently unknown if it is possible to lock a mutex in behalf of another
thread->held_mutexes.insert(this); // thread.
SetHoldingThread(thread); ASSERT(requesting_thread == GetCurrentThread());
thread->UpdatePriority();
Core::System::GetInstance().PrepareReschedule(); u32 addr_value = Memory::Read32(address);
// If the mutex isn't being held, just return success.
if (addr_value != (holding_thread_handle | Mutex::MutexHasWaitersFlag)) {
return RESULT_SUCCESS;
} }
ResultCode Mutex::Release(Thread* thread) { if (holding_thread == nullptr)
auto holding_thread = GetHoldingThread(); return ERR_INVALID_HANDLE;
ASSERT(holding_thread);
// We can only release the mutex if it's held by the calling thread. // Wait until the mutex is released
ASSERT(thread == holding_thread); GetCurrentThread()->mutex_wait_address = address;
GetCurrentThread()->wait_handle = requesting_thread_handle;
GetCurrentThread()->status = THREADSTATUS_WAIT_MUTEX;
GetCurrentThread()->wakeup_callback = nullptr;
// Update the lock holder thread's priority to prevent priority inversion.
holding_thread->AddMutexWaiter(GetCurrentThread());
holding_thread->held_mutexes.erase(this);
holding_thread->UpdatePriority();
SetHoldingThread(nullptr);
SetHasWaiters(!GetWaitingThreads().empty());
WakeupAllWaitingThreads();
Core::System::GetInstance().PrepareReschedule(); Core::System::GetInstance().PrepareReschedule();
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
void Mutex::AddWaitingThread(SharedPtr<Thread> thread) { ResultCode Mutex::Release(VAddr address) {
WaitObject::AddWaitingThread(thread); // The mutex address must be 4-byte aligned
thread->pending_mutexes.insert(this); if ((address % sizeof(u32)) != 0) {
SetHasWaiters(true); return ResultCode(ErrorModule::Kernel, ErrCodes::MisalignedAddress);
UpdatePriority();
} }
void Mutex::RemoveWaitingThread(Thread* thread) { auto [thread, num_waiters] = GetHighestPriorityMutexWaitingThread(GetCurrentThread(), address);
WaitObject::RemoveWaitingThread(thread);
thread->pending_mutexes.erase(this); // There are no more threads waiting for the mutex, release it completely.
if (!GetHasWaiters()) if (thread == nullptr) {
SetHasWaiters(!GetWaitingThreads().empty()); ASSERT(GetCurrentThread()->wait_mutex_threads.empty());
UpdatePriority(); Memory::Write32(address, 0);
return RESULT_SUCCESS;
} }
void Mutex::UpdatePriority() { // Transfer the ownership of the mutex from the previous owner to the new one.
if (!GetHoldingThread()) TransferMutexOwnership(address, GetCurrentThread(), thread);
return;
u32 best_priority = THREADPRIO_LOWEST; u32 mutex_value = thread->wait_handle;
for (auto& waiter : GetWaitingThreads()) {
if (waiter->current_priority < best_priority) if (num_waiters >= 2) {
best_priority = waiter->current_priority; // Notify the guest that there are still some threads waiting for the mutex
mutex_value |= Mutex::MutexHasWaitersFlag;
} }
if (best_priority != priority) { // Grant the mutex to the next waiting thread and resume it.
priority = best_priority; Memory::Write32(address, mutex_value);
GetHoldingThread()->UpdatePriority();
}
}
Handle Mutex::GetOwnerHandle() const { ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX);
GuestState guest_state{Memory::Read32(guest_addr)}; thread->ResumeFromWait();
return guest_state.holding_thread_handle;
}
SharedPtr<Thread> Mutex::GetHoldingThread() const { thread->lock_owner = nullptr;
GuestState guest_state{Memory::Read32(guest_addr)}; thread->condvar_wait_address = 0;
return g_handle_table.Get<Thread>(guest_state.holding_thread_handle); thread->mutex_wait_address = 0;
} thread->wait_handle = 0;
void Mutex::SetHoldingThread(SharedPtr<Thread> thread) { return RESULT_SUCCESS;
GuestState guest_state{Memory::Read32(guest_addr)};
guest_state.holding_thread_handle.Assign(thread ? thread->guest_handle : 0);
Memory::Write32(guest_addr, guest_state.raw);
} }
bool Mutex::GetHasWaiters() const {
GuestState guest_state{Memory::Read32(guest_addr)};
return guest_state.has_waiters != 0;
}
void Mutex::SetHasWaiters(bool has_waiters) {
GuestState guest_state{Memory::Read32(guest_addr)};
guest_state.has_waiters.Assign(has_waiters ? 1 : 0);
Memory::Write32(guest_addr, guest_state.raw);
}
} // namespace Kernel } // namespace Kernel

View file

@ -15,87 +15,23 @@ namespace Kernel {
class Thread; class Thread;
class Mutex final : public WaitObject { class Mutex final {
public: public:
/** /// Flag that indicates that a mutex still has threads waiting for it.
* Creates a mutex. static constexpr u32 MutexHasWaitersFlag = 0x40000000;
* @param holding_thread Specifies a thread already holding the mutex. If not nullptr, this /// Mask of the bits in a mutex address value that contain the mutex owner.
* thread will acquire the mutex. static constexpr u32 MutexOwnerMask = 0xBFFFFFFF;
* @param guest_addr Address of the object tracking the mutex in guest memory. If specified,
* this mutex will update the guest object when its state changes.
* @param name Optional name of mutex
* @return Pointer to new Mutex object
*/
static SharedPtr<Mutex> Create(SharedPtr<Kernel::Thread> holding_thread, VAddr guest_addr = 0,
std::string name = "Unknown");
std::string GetTypeName() const override { /// Attempts to acquire a mutex at the specified address.
return "Mutex"; static ResultCode TryAcquire(VAddr address, Handle holding_thread_handle,
} Handle requesting_thread_handle);
std::string GetName() const override {
return name;
}
static const HandleType HANDLE_TYPE = HandleType::Mutex; /// Releases the mutex at the specified address.
HandleType GetHandleType() const override { static ResultCode Release(VAddr address);
return HANDLE_TYPE;
}
u32 priority; ///< The priority of the mutex, used for priority inheritance.
std::string name; ///< Name of mutex (optional)
VAddr guest_addr; ///< Address of the guest mutex value
/**
* Elevate the mutex priority to the best priority
* among the priorities of all its waiting threads.
*/
void UpdatePriority();
bool ShouldWait(Thread* thread) const override;
void Acquire(Thread* thread) override;
void AddWaitingThread(SharedPtr<Thread> thread) override;
void RemoveWaitingThread(Thread* thread) override;
/**
* Attempts to release the mutex from the specified thread.
* @param thread Thread that wants to release the mutex.
* @returns The result code of the operation.
*/
ResultCode Release(Thread* thread);
/// Gets the handle to the holding process stored in the guest state.
Handle GetOwnerHandle() const;
/// Gets the Thread pointed to by the owner handle
SharedPtr<Thread> GetHoldingThread() const;
/// Sets the holding process handle in the guest state.
void SetHoldingThread(SharedPtr<Thread> thread);
/// Returns the has_waiters bit in the guest state.
bool GetHasWaiters() const;
/// Sets the has_waiters bit in the guest state.
void SetHasWaiters(bool has_waiters);
private: private:
Mutex(); Mutex() = default;
~Mutex() override; ~Mutex() = default;
/// Object in guest memory used to track the mutex state
union GuestState {
u32_le raw;
/// Handle of the thread that currently holds the mutex, 0 if available
BitField<0, 30, u32_le> holding_thread_handle;
/// 1 when there are threads waiting for this mutex, otherwise 0
BitField<30, 1, u32_le> has_waiters;
}; };
static_assert(sizeof(GuestState) == 4, "GuestState size is incorrect");
};
/**
* Releases all the mutexes held by the specified thread
* @param thread Thread that is holding the mutexes
*/
void ReleaseThreadMutexes(Thread* thread);
} // namespace Kernel } // namespace Kernel

View file

@ -54,7 +54,7 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
continue; continue;
} else if ((type & 0xF00) == 0xE00) { // 0x0FFF } else if ((type & 0xF00) == 0xE00) { // 0x0FFF
// Allowed interrupts list // Allowed interrupts list
LOG_WARNING(Loader, "ExHeader allowed interrupts list ignored"); NGLOG_WARNING(Loader, "ExHeader allowed interrupts list ignored");
} else if ((type & 0xF80) == 0xF00) { // 0x07FF } else if ((type & 0xF80) == 0xF00) { // 0x07FF
// Allowed syscalls mask // Allowed syscalls mask
unsigned int index = ((descriptor >> 24) & 7) * 24; unsigned int index = ((descriptor >> 24) & 7) * 24;
@ -74,7 +74,7 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
} else if ((type & 0xFFE) == 0xFF8) { // 0x001F } else if ((type & 0xFFE) == 0xFF8) { // 0x001F
// Mapped memory range // Mapped memory range
if (i + 1 >= len || ((kernel_caps[i + 1] >> 20) & 0xFFE) != 0xFF8) { if (i + 1 >= len || ((kernel_caps[i + 1] >> 20) & 0xFFE) != 0xFF8) {
LOG_WARNING(Loader, "Incomplete exheader memory range descriptor ignored."); NGLOG_WARNING(Loader, "Incomplete exheader memory range descriptor ignored.");
continue; continue;
} }
u32 end_desc = kernel_caps[i + 1]; u32 end_desc = kernel_caps[i + 1];
@ -109,9 +109,9 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
int minor = kernel_version & 0xFF; int minor = kernel_version & 0xFF;
int major = (kernel_version >> 8) & 0xFF; int major = (kernel_version >> 8) & 0xFF;
LOG_INFO(Loader, "ExHeader kernel version: %d.%d", major, minor); NGLOG_INFO(Loader, "ExHeader kernel version: {}.{}", major, minor);
} else { } else {
LOG_ERROR(Loader, "Unhandled kernel caps descriptor: 0x%08X", descriptor); NGLOG_ERROR(Loader, "Unhandled kernel caps descriptor: {:#010X}", descriptor);
} }
} }
} }

View file

@ -29,7 +29,7 @@ SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory cat
case ResourceLimitCategory::OTHER: case ResourceLimitCategory::OTHER:
return resource_limits[static_cast<u8>(category)]; return resource_limits[static_cast<u8>(category)];
default: default:
LOG_CRITICAL(Kernel, "Unknown resource limit category"); NGLOG_CRITICAL(Kernel, "Unknown resource limit category");
UNREACHABLE(); UNREACHABLE();
} }
} }
@ -55,7 +55,7 @@ s32 ResourceLimit::GetCurrentResourceValue(ResourceType resource) const {
case ResourceType::CPUTime: case ResourceType::CPUTime:
return current_cpu_time; return current_cpu_time;
default: default:
LOG_ERROR(Kernel, "Unknown resource type=%08X", static_cast<u32>(resource)); NGLOG_ERROR(Kernel, "Unknown resource type={:08X}", static_cast<u32>(resource));
UNIMPLEMENTED(); UNIMPLEMENTED();
return 0; return 0;
} }
@ -84,7 +84,7 @@ u32 ResourceLimit::GetMaxResourceValue(ResourceType resource) const {
case ResourceType::CPUTime: case ResourceType::CPUTime:
return max_cpu_time; return max_cpu_time;
default: default:
LOG_ERROR(Kernel, "Unknown resource type=%08X", static_cast<u32>(resource)); NGLOG_ERROR(Kernel, "Unknown resource type={:08X}", static_cast<u32>(resource));
UNIMPLEMENTED(); UNIMPLEMENTED();
return 0; return 0;
} }

View file

@ -94,11 +94,11 @@ void Scheduler::Reschedule() {
Thread* next = PopNextReadyThread(); Thread* next = PopNextReadyThread();
if (cur && next) { if (cur && next) {
LOG_TRACE(Kernel, "context switch %u -> %u", cur->GetObjectId(), next->GetObjectId()); NGLOG_TRACE(Kernel, "context switch {} -> {}", cur->GetObjectId(), next->GetObjectId());
} else if (cur) { } else if (cur) {
LOG_TRACE(Kernel, "context switch %u -> idle", cur->GetObjectId()); NGLOG_TRACE(Kernel, "context switch {} -> idle", cur->GetObjectId());
} else if (next) { } else if (next) {
LOG_TRACE(Kernel, "context switch idle -> %u", next->GetObjectId()); NGLOG_TRACE(Kernel, "context switch idle -> {}", next->GetObjectId());
} }
SwitchContext(next); SwitchContext(next);

View file

@ -68,7 +68,7 @@ ResultCode ServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& con
return domain_request_handlers[object_id - 1]->HandleSyncRequest(context); return domain_request_handlers[object_id - 1]->HandleSyncRequest(context);
case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: { case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: {
LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x%08X", object_id); NGLOG_DEBUG(IPC, "CloseVirtualHandle, object_id={:#010X}", object_id);
domain_request_handlers[object_id - 1] = nullptr; domain_request_handlers[object_id - 1] = nullptr;
@ -78,7 +78,7 @@ ResultCode ServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& con
} }
} }
LOG_CRITICAL(IPC, "Unknown domain command=%d", NGLOG_CRITICAL(IPC, "Unknown domain command={}",
static_cast<int>(domain_message_header->command.Value())); static_cast<int>(domain_message_header->command.Value()));
ASSERT(false); ASSERT(false);
} }

View file

@ -107,16 +107,16 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
// Error out if the requested permissions don't match what the creator process allows. // Error out if the requested permissions don't match what the creator process allows.
if (static_cast<u32>(permissions) & ~static_cast<u32>(own_other_permissions)) { if (static_cast<u32>(permissions) & ~static_cast<u32>(own_other_permissions)) {
LOG_ERROR(Kernel, "cannot map id=%u, address=0x%lx name=%s, permissions don't match", NGLOG_ERROR(Kernel, "cannot map id={}, address={:#X} name={}, permissions don't match",
GetObjectId(), address, name.c_str()); GetObjectId(), address, name);
return ERR_INVALID_COMBINATION; return ERR_INVALID_COMBINATION;
} }
// Error out if the provided permissions are not compatible with what the creator process needs. // Error out if the provided permissions are not compatible with what the creator process needs.
if (other_permissions != MemoryPermission::DontCare && if (other_permissions != MemoryPermission::DontCare &&
static_cast<u32>(this->permissions) & ~static_cast<u32>(other_permissions)) { static_cast<u32>(this->permissions) & ~static_cast<u32>(other_permissions)) {
LOG_ERROR(Kernel, "cannot map id=%u, address=0x%lx name=%s, permissions don't match", NGLOG_ERROR(Kernel, "cannot map id={}, address={:#X} name={}, permissions don't match",
GetObjectId(), address, name.c_str()); GetObjectId(), address, name);
return ERR_WRONG_PERMISSION; return ERR_WRONG_PERMISSION;
} }
@ -131,9 +131,10 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
auto result = target_process->vm_manager.MapMemoryBlock( auto result = target_process->vm_manager.MapMemoryBlock(
target_address, backing_block, backing_block_offset, size, MemoryState::Shared); target_address, backing_block, backing_block_offset, size, MemoryState::Shared);
if (result.Failed()) { if (result.Failed()) {
LOG_ERROR(Kernel, NGLOG_ERROR(
"cannot map id=%u, target_address=0x%lx name=%s, error mapping to virtual memory", Kernel,
GetObjectId(), target_address, name.c_str()); "cannot map id={}, target_address={:#X} name={}, error mapping to virtual memory",
GetObjectId(), target_address, name);
return result.Code(); return result.Code();
} }
@ -151,7 +152,7 @@ VMAPermission SharedMemory::ConvertPermissions(MemoryPermission permission) {
u32 masked_permissions = u32 masked_permissions =
static_cast<u32>(permission) & static_cast<u32>(MemoryPermission::ReadWriteExecute); static_cast<u32>(permission) & static_cast<u32>(MemoryPermission::ReadWriteExecute);
return static_cast<VMAPermission>(masked_permissions); return static_cast<VMAPermission>(masked_permissions);
}; }
u8* SharedMemory::GetPointer(u32 offset) { u8* SharedMemory::GetPointer(u32 offset) {
return backing_block->data() + backing_block_offset + offset; return backing_block->data() + backing_block_offset + offset;

View file

@ -13,7 +13,6 @@
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/hle/kernel/client_port.h" #include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h" #include "core/hle/kernel/client_session.h"
#include "core/hle/kernel/condition_variable.h"
#include "core/hle/kernel/event.h" #include "core/hle/kernel/event.h"
#include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/mutex.h" #include "core/hle/kernel/mutex.h"
@ -32,7 +31,7 @@ namespace Kernel {
/// Set the process heap to a given Size. It can both extend and shrink the heap. /// 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) { static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) {
LOG_TRACE(Kernel_SVC, "called, heap_size=0x%llx", heap_size); NGLOG_TRACE(Kernel_SVC, "called, heap_size={:#X}", heap_size);
auto& process = *Core::CurrentProcess(); auto& process = *Core::CurrentProcess();
CASCADE_RESULT(*heap_addr, CASCADE_RESULT(*heap_addr,
process.HeapAllocate(Memory::HEAP_VADDR, heap_size, VMAPermission::ReadWrite)); process.HeapAllocate(Memory::HEAP_VADDR, heap_size, VMAPermission::ReadWrite));
@ -40,20 +39,20 @@ static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) {
} }
static ResultCode SetMemoryAttribute(VAddr addr, u64 size, u32 state0, u32 state1) { static ResultCode SetMemoryAttribute(VAddr addr, u64 size, u32 state0, u32 state1) {
LOG_WARNING(Kernel_SVC, "(STUBBED) called, addr=0x%lx", addr); NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, addr={:#X}", addr);
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
/// Maps a memory range into a different range. /// Maps a memory range into a different range.
static ResultCode MapMemory(VAddr dst_addr, VAddr src_addr, u64 size) { 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, NGLOG_TRACE(Kernel_SVC, "called, dst_addr={:#X}, src_addr={:#X}, size={:#X}", dst_addr,
src_addr, size); src_addr, size);
return Core::CurrentProcess()->MirrorMemory(dst_addr, src_addr, size); return Core::CurrentProcess()->MirrorMemory(dst_addr, src_addr, size);
} }
/// Unmaps a region that was previously mapped with svcMapMemory /// Unmaps a region that was previously mapped with svcMapMemory
static ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size) { 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, NGLOG_TRACE(Kernel_SVC, "called, dst_addr={:#X}, src_addr={:#X}, size={:#X}", dst_addr,
src_addr, size); src_addr, size);
return Core::CurrentProcess()->UnmapMemory(dst_addr, src_addr, size); return Core::CurrentProcess()->UnmapMemory(dst_addr, src_addr, size);
} }
@ -69,11 +68,11 @@ static ResultCode ConnectToNamedPort(Handle* out_handle, VAddr port_name_address
if (port_name.size() > PortNameMaxLength) if (port_name.size() > PortNameMaxLength)
return ERR_PORT_NAME_TOO_LONG; return ERR_PORT_NAME_TOO_LONG;
LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name.c_str()); NGLOG_TRACE(Kernel_SVC, "called port_name={}", port_name);
auto it = Service::g_kernel_named_ports.find(port_name); auto it = Service::g_kernel_named_ports.find(port_name);
if (it == Service::g_kernel_named_ports.end()) { if (it == Service::g_kernel_named_ports.end()) {
LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: %s", port_name.c_str()); NGLOG_WARNING(Kernel_SVC, "tried to connect to unknown port: {}", port_name);
return ERR_NOT_FOUND; return ERR_NOT_FOUND;
} }
@ -91,11 +90,11 @@ static ResultCode ConnectToNamedPort(Handle* out_handle, VAddr port_name_address
static ResultCode SendSyncRequest(Handle handle) { static ResultCode SendSyncRequest(Handle handle) {
SharedPtr<ClientSession> session = g_handle_table.Get<ClientSession>(handle); SharedPtr<ClientSession> session = g_handle_table.Get<ClientSession>(handle);
if (!session) { if (!session) {
LOG_ERROR(Kernel_SVC, "called with invalid handle=0x%08X", handle); NGLOG_ERROR(Kernel_SVC, "called with invalid handle={:#010X}", handle);
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
} }
LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s)", handle, session->GetName().c_str()); NGLOG_TRACE(Kernel_SVC, "called handle={:#010X}({})", handle, session->GetName());
Core::System::GetInstance().PrepareReschedule(); Core::System::GetInstance().PrepareReschedule();
@ -106,7 +105,7 @@ static ResultCode SendSyncRequest(Handle handle) {
/// Get the ID for the specified thread. /// Get the ID for the specified thread.
static ResultCode GetThreadId(u32* thread_id, Handle thread_handle) { static ResultCode GetThreadId(u32* thread_id, Handle thread_handle) {
LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle); NGLOG_TRACE(Kernel_SVC, "called thread={:#010X}", thread_handle);
const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
if (!thread) { if (!thread) {
@ -119,7 +118,7 @@ static ResultCode GetThreadId(u32* thread_id, Handle thread_handle) {
/// Get the ID of the specified process /// Get the ID of the specified process
static ResultCode GetProcessId(u32* process_id, Handle process_handle) { static ResultCode GetProcessId(u32* process_id, Handle process_handle) {
LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle); NGLOG_TRACE(Kernel_SVC, "called process={:#010X}", process_handle);
const SharedPtr<Process> process = g_handle_table.Get<Process>(process_handle); const SharedPtr<Process> process = g_handle_table.Get<Process>(process_handle);
if (!process) { if (!process) {
@ -179,7 +178,7 @@ static ResultCode WaitSynchronization1(
/// Wait for the given handles to synchronize, timeout after the specified nanoseconds /// Wait for the given handles to synchronize, timeout after the specified nanoseconds
static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64 handle_count, static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64 handle_count,
s64 nano_seconds) { s64 nano_seconds) {
LOG_TRACE(Kernel_SVC, "called handles_address=0x%llx, handle_count=%d, nano_seconds=%d", NGLOG_TRACE(Kernel_SVC, "called handles_address={:#X}, handle_count={}, nano_seconds={}",
handles_address, handle_count, nano_seconds); handles_address, handle_count, nano_seconds);
if (!Memory::IsValidVirtualAddress(handles_address)) if (!Memory::IsValidVirtualAddress(handles_address))
@ -240,7 +239,7 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64
/// Resumes a thread waiting on WaitSynchronization /// Resumes a thread waiting on WaitSynchronization
static ResultCode CancelSynchronization(Handle thread_handle) { static ResultCode CancelSynchronization(Handle thread_handle) {
LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle); NGLOG_TRACE(Kernel_SVC, "called thread={:#X}", thread_handle);
const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
if (!thread) { if (!thread) {
@ -257,55 +256,37 @@ static ResultCode CancelSynchronization(Handle thread_handle) {
/// Attempts to locks a mutex, creating it if it does not already exist /// Attempts to locks a mutex, creating it if it does not already exist
static ResultCode ArbitrateLock(Handle holding_thread_handle, VAddr mutex_addr, static ResultCode ArbitrateLock(Handle holding_thread_handle, VAddr mutex_addr,
Handle requesting_thread_handle) { Handle requesting_thread_handle) {
LOG_TRACE(Kernel_SVC, NGLOG_TRACE(Kernel_SVC,
"called holding_thread_handle=0x%08X, mutex_addr=0x%llx, " "called holding_thread_handle={:#010X}, mutex_addr={:#X}, "
"requesting_current_thread_handle=0x%08X", "requesting_current_thread_handle={:#010X}",
holding_thread_handle, mutex_addr, requesting_thread_handle); holding_thread_handle, mutex_addr, requesting_thread_handle);
SharedPtr<Thread> holding_thread = g_handle_table.Get<Thread>(holding_thread_handle); return Mutex::TryAcquire(mutex_addr, holding_thread_handle, requesting_thread_handle);
SharedPtr<Thread> requesting_thread = g_handle_table.Get<Thread>(requesting_thread_handle);
ASSERT(requesting_thread);
ASSERT(requesting_thread == GetCurrentThread());
SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(mutex_addr);
if (!mutex) {
// Create a new mutex for the specified address if one does not already exist
mutex = Mutex::Create(holding_thread, mutex_addr);
mutex->name = Common::StringFromFormat("mutex-%llx", mutex_addr);
}
ASSERT(holding_thread == mutex->GetHoldingThread());
return WaitSynchronization1(mutex, requesting_thread.get());
} }
/// Unlock a mutex /// Unlock a mutex
static ResultCode ArbitrateUnlock(VAddr mutex_addr) { static ResultCode ArbitrateUnlock(VAddr mutex_addr) {
LOG_TRACE(Kernel_SVC, "called mutex_addr=0x%llx", mutex_addr); NGLOG_TRACE(Kernel_SVC, "called mutex_addr={:#X}", mutex_addr);
SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(mutex_addr); return Mutex::Release(mutex_addr);
ASSERT(mutex);
return mutex->Release(GetCurrentThread());
} }
/// Break program execution /// Break program execution
static void Break(u64 unk_0, u64 unk_1, u64 unk_2) { static void Break(u64 unk_0, u64 unk_1, u64 unk_2) {
LOG_CRITICAL(Debug_Emulated, "Emulated program broke execution!"); NGLOG_CRITICAL(Debug_Emulated, "Emulated program broke execution!");
ASSERT(false); ASSERT(false);
} }
/// Used to output a message on a debug hardware unit - does nothing on a retail unit /// Used to output a message on a debug hardware unit - does nothing on a retail unit
static void OutputDebugString(VAddr address, s32 len) { static void OutputDebugString(VAddr address, s32 len) {
std::vector<char> string(len); std::string str(len, '\0');
Memory::ReadBlock(address, string.data(), len); Memory::ReadBlock(address, str.data(), str.size());
LOG_DEBUG(Debug_Emulated, "%.*s", len, string.data()); NGLOG_DEBUG(Debug_Emulated, "{}", str);
} }
/// Gets system/memory information for the current process /// Gets system/memory information for the current process
static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) { 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, NGLOG_TRACE(Kernel_SVC, "called info_id={:#X}, info_sub_id={:#X}, handle={:#010X}", info_id,
info_sub_id, handle); info_sub_id, handle);
auto& vm_manager = Core::CurrentProcess()->vm_manager; auto& vm_manager = Core::CurrentProcess()->vm_manager;
@ -357,12 +338,12 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
*result = Core::CurrentProcess()->is_virtual_address_memory_enabled; *result = Core::CurrentProcess()->is_virtual_address_memory_enabled;
break; break;
case GetInfoType::TitleId: case GetInfoType::TitleId:
LOG_WARNING(Kernel_SVC, "(STUBBED) Attempted to query titleid, returned 0"); NGLOG_WARNING(Kernel_SVC, "(STUBBED) Attempted to query titleid, returned 0");
*result = 0; *result = 0;
break; break;
case GetInfoType::PrivilegedProcessId: case GetInfoType::PrivilegedProcessId:
LOG_WARNING(Kernel_SVC, NGLOG_WARNING(Kernel_SVC,
"(STUBBED) Attempted to query priviledged process id bounds, returned 0"); "(STUBBED) Attempted to query privileged process id bounds, returned 0");
*result = 0; *result = 0;
break; break;
default: default:
@ -374,13 +355,14 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
/// Sets the thread activity /// Sets the thread activity
static ResultCode SetThreadActivity(Handle handle, u32 unknown) { static ResultCode SetThreadActivity(Handle handle, u32 unknown) {
LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x%08X, unknown=0x%08X", handle, unknown); NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, handle={:#010X}, unknown={:#010X}", handle,
unknown);
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
/// Gets the thread context /// Gets the thread context
static ResultCode GetThreadContext(Handle handle, VAddr addr) { static ResultCode GetThreadContext(Handle handle, VAddr addr) {
LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x%08X, addr=0x%" PRIx64, handle, addr); NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, handle={:#010X}, addr={:#X}", handle, addr);
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
@ -412,11 +394,6 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
} }
thread->SetPriority(priority); thread->SetPriority(priority);
thread->UpdatePriority();
// Update the mutexes that this thread is waiting for
for (auto& mutex : thread->pending_mutexes)
mutex->UpdatePriority();
Core::System::GetInstance().PrepareReschedule(); Core::System::GetInstance().PrepareReschedule();
return RESULT_SUCCESS; return RESULT_SUCCESS;
@ -424,14 +401,14 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
/// Get which CPU core is executing the current thread /// Get which CPU core is executing the current thread
static u32 GetCurrentProcessorNumber() { static u32 GetCurrentProcessorNumber() {
LOG_WARNING(Kernel_SVC, "(STUBBED) called, defaulting to processor 0"); NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, defaulting to processor 0");
return 0; return 0;
} }
static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size, static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size,
u32 permissions) { u32 permissions) {
LOG_TRACE(Kernel_SVC, NGLOG_TRACE(Kernel_SVC,
"called, shared_memory_handle=0x%08X, addr=0x%llx, size=0x%llx, permissions=0x%08X", "called, shared_memory_handle={:#X}, addr={:#X}, size={:#X}, permissions={:#010X}",
shared_memory_handle, addr, size, permissions); shared_memory_handle, addr, size, permissions);
SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(shared_memory_handle); SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(shared_memory_handle);
@ -452,15 +429,14 @@ static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 s
return shared_memory->Map(Core::CurrentProcess().get(), addr, permissions_type, return shared_memory->Map(Core::CurrentProcess().get(), addr, permissions_type,
MemoryPermission::DontCare); MemoryPermission::DontCare);
default: default:
LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions); NGLOG_ERROR(Kernel_SVC, "unknown permissions={:#010X}", permissions);
} }
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size) { static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size) {
LOG_WARNING(Kernel_SVC, NGLOG_WARNING(Kernel_SVC, "called, shared_memory_handle={:#010X}, addr={:#X}, size={:#X}",
"called, shared_memory_handle=0x%08X, addr=0x%" PRIx64 ", size=0x%" PRIx64 "",
shared_memory_handle, addr, size); shared_memory_handle, addr, size);
SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(shared_memory_handle); SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(shared_memory_handle);
@ -489,19 +465,19 @@ static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* /*page_i
memory_info->type = static_cast<u32>(vma->second.meminfo_state); memory_info->type = static_cast<u32>(vma->second.meminfo_state);
} }
LOG_TRACE(Kernel_SVC, "called process=0x%08X addr=%llx", process_handle, addr); NGLOG_TRACE(Kernel_SVC, "called process={:#010X} addr={:X}", process_handle, addr);
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
/// Query memory /// Query memory
static ResultCode QueryMemory(MemoryInfo* memory_info, PageInfo* page_info, VAddr addr) { static ResultCode QueryMemory(MemoryInfo* memory_info, PageInfo* page_info, VAddr addr) {
LOG_TRACE(Kernel_SVC, "called, addr=%llx", addr); NGLOG_TRACE(Kernel_SVC, "called, addr={:X}", addr);
return QueryProcessMemory(memory_info, page_info, CurrentProcess, addr); return QueryProcessMemory(memory_info, page_info, CurrentProcess, addr);
} }
/// Exits the current process /// Exits the current process
static void ExitProcess() { static void ExitProcess() {
LOG_INFO(Kernel_SVC, "Process %u exiting", Core::CurrentProcess()->process_id); NGLOG_INFO(Kernel_SVC, "Process {} exiting", Core::CurrentProcess()->process_id);
ASSERT_MSG(Core::CurrentProcess()->status == ProcessStatus::Running, ASSERT_MSG(Core::CurrentProcess()->status == ProcessStatus::Running,
"Process has already exited"); "Process has already exited");
@ -558,8 +534,8 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
case THREADPROCESSORID_2: case THREADPROCESSORID_2:
case THREADPROCESSORID_3: case THREADPROCESSORID_3:
// TODO(bunnei): Implement support for other processor IDs // TODO(bunnei): Implement support for other processor IDs
LOG_ERROR(Kernel_SVC, NGLOG_ERROR(Kernel_SVC,
"Newly created thread must run in another thread (%u), unimplemented.", "Newly created thread must run in another thread ({}), unimplemented.",
processor_id); processor_id);
break; break;
default: default:
@ -575,17 +551,17 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
Core::System::GetInstance().PrepareReschedule(); Core::System::GetInstance().PrepareReschedule();
LOG_TRACE(Kernel_SVC, NGLOG_TRACE(Kernel_SVC,
"called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " "called entrypoint={:#010X} ({}), arg={:#010X}, stacktop={:#010X}, "
"threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", "threadpriority={:#010X}, processorid={:#010X} : created handle={:#010X}",
entry_point, name.c_str(), arg, stack_top, priority, processor_id, *out_handle); entry_point, name, arg, stack_top, priority, processor_id, *out_handle);
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
/// Starts the thread for the provided handle /// Starts the thread for the provided handle
static ResultCode StartThread(Handle thread_handle) { static ResultCode StartThread(Handle thread_handle) {
LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle); NGLOG_TRACE(Kernel_SVC, "called thread={:#010X}", thread_handle);
const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
if (!thread) { if (!thread) {
@ -599,7 +575,7 @@ static ResultCode StartThread(Handle thread_handle) {
/// Called when a thread exits /// Called when a thread exits
static void ExitThread() { static void ExitThread() {
LOG_TRACE(Kernel_SVC, "called, pc=0x%08X", Core::CPU().GetPC()); NGLOG_TRACE(Kernel_SVC, "called, pc={:#010X}", Core::CPU().GetPC());
ExitCurrentThread(); ExitCurrentThread();
Core::System::GetInstance().PrepareReschedule(); Core::System::GetInstance().PrepareReschedule();
@ -607,7 +583,7 @@ static void ExitThread() {
/// Sleep the current thread /// Sleep the current thread
static void SleepThread(s64 nanoseconds) { static void SleepThread(s64 nanoseconds) {
LOG_TRACE(Kernel_SVC, "called nanoseconds=%lld", nanoseconds); NGLOG_TRACE(Kernel_SVC, "called nanoseconds={}", nanoseconds);
// Don't attempt to yield execution if there are no available threads to run, // Don't attempt to yield execution if there are no available threads to run,
// this way we avoid a useless reschedule to the idle thread. // this way we avoid a useless reschedule to the idle thread.
@ -626,111 +602,83 @@ static void SleepThread(s64 nanoseconds) {
/// Signal process wide key atomic /// Signal process wide key atomic
static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_variable_addr, static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_variable_addr,
Handle thread_handle, s64 nano_seconds) { Handle thread_handle, s64 nano_seconds) {
LOG_TRACE( NGLOG_TRACE(
Kernel_SVC, Kernel_SVC,
"called mutex_addr=%llx, condition_variable_addr=%llx, thread_handle=0x%08X, timeout=%d", "called mutex_addr={:X}, condition_variable_addr={:X}, thread_handle={:#010X}, timeout={}",
mutex_addr, condition_variable_addr, thread_handle, nano_seconds); mutex_addr, condition_variable_addr, thread_handle, nano_seconds);
SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
ASSERT(thread); ASSERT(thread);
SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(mutex_addr); CASCADE_CODE(Mutex::Release(mutex_addr));
if (!mutex) {
// Create a new mutex for the specified address if one does not already exist
mutex = Mutex::Create(thread, mutex_addr);
mutex->name = Common::StringFromFormat("mutex-%llx", mutex_addr);
}
SharedPtr<ConditionVariable> condition_variable = SharedPtr<Thread> current_thread = GetCurrentThread();
g_object_address_table.Get<ConditionVariable>(condition_variable_addr); current_thread->condvar_wait_address = condition_variable_addr;
if (!condition_variable) { current_thread->mutex_wait_address = mutex_addr;
// Create a new condition_variable for the specified address if one does not already exist current_thread->wait_handle = thread_handle;
condition_variable = ConditionVariable::Create(condition_variable_addr).Unwrap(); current_thread->status = THREADSTATUS_WAIT_MUTEX;
condition_variable->name = current_thread->wakeup_callback = nullptr;
Common::StringFromFormat("condition-variable-%llx", condition_variable_addr);
}
if (condition_variable->mutex_addr) { current_thread->WakeAfterDelay(nano_seconds);
// Previously created the ConditionVariable using WaitProcessWideKeyAtomic, verify
// everything is correct
ASSERT(condition_variable->mutex_addr == mutex_addr);
} else {
// Previously created the ConditionVariable using SignalProcessWideKey, set the mutex
// associated with it
condition_variable->mutex_addr = mutex_addr;
}
if (mutex->GetOwnerHandle()) { // Note: Deliberately don't attempt to inherit the lock owner's priority.
// Release the mutex if the current thread is holding it
mutex->Release(thread.get());
}
auto wakeup_callback = [mutex, nano_seconds](ThreadWakeupReason reason,
SharedPtr<Thread> thread,
SharedPtr<WaitObject> object, size_t index) {
ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ANY);
if (reason == ThreadWakeupReason::Timeout) {
thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
return true;
}
ASSERT(reason == ThreadWakeupReason::Signal);
// Now try to acquire the mutex and don't resume if it's not available.
if (!mutex->ShouldWait(thread.get())) {
mutex->Acquire(thread.get());
thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
return true;
}
if (nano_seconds == 0) {
thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
return true;
}
thread->wait_objects = {mutex};
mutex->AddWaitingThread(thread);
thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
// Create an event to wake the thread up after the
// specified nanosecond delay has passed
thread->WakeAfterDelay(nano_seconds);
thread->wakeup_callback = DefaultThreadWakeupCallback;
Core::System::GetInstance().PrepareReschedule(); Core::System::GetInstance().PrepareReschedule();
return false;
};
CASCADE_CODE(
WaitSynchronization1(condition_variable, thread.get(), nano_seconds, wakeup_callback));
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
/// Signal process wide key /// Signal process wide key
static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target) { static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target) {
LOG_TRACE(Kernel_SVC, "called, condition_variable_addr=0x%llx, target=0x%08x", NGLOG_TRACE(Kernel_SVC, "called, condition_variable_addr={:#X}, target={:#010X}",
condition_variable_addr, target); condition_variable_addr, target);
// Wakeup all or one thread - Any other value is unimplemented u32 processed = 0;
ASSERT(target == -1 || target == 1); auto& thread_list = Core::System::GetInstance().Scheduler().GetThreadList();
SharedPtr<ConditionVariable> condition_variable = for (auto& thread : thread_list) {
g_object_address_table.Get<ConditionVariable>(condition_variable_addr); if (thread->condvar_wait_address != condition_variable_addr)
if (!condition_variable) { continue;
// Create a new condition_variable for the specified address if one does not already exist
condition_variable = ConditionVariable::Create(condition_variable_addr).Unwrap(); // Only process up to 'target' threads, unless 'target' is -1, in which case process
condition_variable->name = // them all.
Common::StringFromFormat("condition-variable-%llx", condition_variable_addr); if (target != -1 && processed >= target)
break;
// If the mutex is not yet acquired, acquire it.
u32 mutex_val = Memory::Read32(thread->mutex_wait_address);
if (mutex_val == 0) {
// We were able to acquire the mutex, resume this thread.
Memory::Write32(thread->mutex_wait_address, thread->wait_handle);
ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX);
thread->ResumeFromWait();
auto lock_owner = thread->lock_owner;
if (lock_owner)
lock_owner->RemoveMutexWaiter(thread);
thread->lock_owner = nullptr;
thread->mutex_wait_address = 0;
thread->condvar_wait_address = 0;
thread->wait_handle = 0;
} else {
// Couldn't acquire the mutex, block the thread.
Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask);
auto owner = g_handle_table.Get<Thread>(owner_handle);
ASSERT(owner);
ASSERT(thread->status != THREADSTATUS_RUNNING);
thread->status = THREADSTATUS_WAIT_MUTEX;
thread->wakeup_callback = nullptr;
// Signal that the mutex now has a waiting thread.
Memory::Write32(thread->mutex_wait_address, mutex_val | Mutex::MutexHasWaitersFlag);
owner->AddMutexWaiter(thread);
Core::System::GetInstance().PrepareReschedule();
} }
CASCADE_CODE(condition_variable->Release(target)); ++processed;
if (condition_variable->mutex_addr) {
// If a mutex was created for this condition_variable, wait the current thread on it
SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(condition_variable->mutex_addr);
return WaitSynchronization1(mutex, GetCurrentThread());
} }
return RESULT_SUCCESS; return RESULT_SUCCESS;
@ -748,13 +696,13 @@ static u64 GetSystemTick() {
/// Close a handle /// Close a handle
static ResultCode CloseHandle(Handle handle) { static ResultCode CloseHandle(Handle handle) {
LOG_TRACE(Kernel_SVC, "Closing handle 0x%08X", handle); NGLOG_TRACE(Kernel_SVC, "Closing handle {:#010X}", handle);
return g_handle_table.Close(handle); return g_handle_table.Close(handle);
} }
/// Reset an event /// Reset an event
static ResultCode ResetSignal(Handle handle) { static ResultCode ResetSignal(Handle handle) {
LOG_WARNING(Kernel_SVC, "(STUBBED) called handle 0x%08X", handle); NGLOG_WARNING(Kernel_SVC, "(STUBBED) called handle {:#010X}", handle);
auto event = g_handle_table.Get<Event>(handle); auto event = g_handle_table.Get<Event>(handle);
ASSERT(event != nullptr); ASSERT(event != nullptr);
event->Clear(); event->Clear();
@ -763,28 +711,28 @@ static ResultCode ResetSignal(Handle handle) {
/// Creates a TransferMemory object /// Creates a TransferMemory object
static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32 permissions) { static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32 permissions) {
LOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x%lx, size=0x%lx, perms=%08X", addr, size, NGLOG_WARNING(Kernel_SVC, "(STUBBED) called addr={:#X}, size={:#X}, perms={:010X}", addr, size,
permissions); permissions);
*handle = 0; *handle = 0;
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
static ResultCode GetThreadCoreMask(Handle handle, u32* mask, u64* unknown) { static ResultCode GetThreadCoreMask(Handle handle, u32* mask, u64* unknown) {
LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x%08X", handle); NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, handle={:010X}", handle);
*mask = 0x0; *mask = 0x0;
*unknown = 0xf; *unknown = 0xf;
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
static ResultCode SetThreadCoreMask(Handle handle, u32 mask, u64 unknown) { static ResultCode SetThreadCoreMask(Handle handle, u32 mask, u64 unknown) {
LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x%08X, mask=0x%08X, unknown=0x%lx", handle, NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, handle={:#010X}, mask={:#010X}, unknown={:#X}",
mask, unknown); handle, mask, unknown);
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permissions, static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permissions,
u32 remote_permissions) { u32 remote_permissions) {
LOG_TRACE(Kernel_SVC, "called, size=0x%llx, localPerms=0x%08x, remotePerms=0x%08x", size, NGLOG_TRACE(Kernel_SVC, "called, size={:#X}, localPerms={:#010X}, remotePerms={:#010X}", size,
local_permissions, remote_permissions); local_permissions, remote_permissions);
auto sharedMemHandle = auto sharedMemHandle =
SharedMemory::Create(g_handle_table.Get<Process>(KernelHandle::CurrentProcess), size, SharedMemory::Create(g_handle_table.Get<Process>(KernelHandle::CurrentProcess), size,
@ -796,7 +744,7 @@ static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permiss
} }
static ResultCode ClearEvent(Handle handle) { static ResultCode ClearEvent(Handle handle) {
LOG_TRACE(Kernel_SVC, "called, event=0xX", handle); NGLOG_TRACE(Kernel_SVC, "called, event={:010X}", handle);
SharedPtr<Event> evt = g_handle_table.Get<Event>(handle); SharedPtr<Event> evt = g_handle_table.Get<Event>(handle);
if (evt == nullptr) if (evt == nullptr)
@ -948,7 +896,7 @@ static const FunctionDef SVC_Table[] = {
static const FunctionDef* GetSVCInfo(u32 func_num) { static const FunctionDef* GetSVCInfo(u32 func_num) {
if (func_num >= std::size(SVC_Table)) { if (func_num >= std::size(SVC_Table)) {
LOG_ERROR(Kernel_SVC, "unknown svc=0x%02X", func_num); NGLOG_ERROR(Kernel_SVC, "Unknown svc={:#04X}", func_num);
return nullptr; return nullptr;
} }
return &SVC_Table[func_num]; return &SVC_Table[func_num];
@ -967,10 +915,10 @@ void CallSVC(u32 immediate) {
if (info->func) { if (info->func) {
info->func(); info->func();
} else { } else {
LOG_CRITICAL(Kernel_SVC, "unimplemented SVC function %s(..)", info->name); NGLOG_CRITICAL(Kernel_SVC, "Unimplemented SVC function {}(..)", info->name);
} }
} else { } else {
LOG_CRITICAL(Kernel_SVC, "unknown SVC function 0x%x", immediate); NGLOG_CRITICAL(Kernel_SVC, "Unknown SVC function {:#X}", immediate);
} }
} }

View file

@ -77,9 +77,6 @@ void Thread::Stop() {
} }
wait_objects.clear(); wait_objects.clear();
// Release all the mutexes that this thread holds
ReleaseThreadMutexes(this);
// Mark the TLS slot in the thread's page as free. // Mark the TLS slot in the thread's page as free.
u64 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE; u64 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE;
u64 tls_slot = u64 tls_slot =
@ -104,9 +101,10 @@ void ExitCurrentThread() {
* @param cycles_late The number of CPU cycles that have passed since the desired wakeup time * @param cycles_late The number of CPU cycles that have passed since the desired wakeup time
*/ */
static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) { static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
SharedPtr<Thread> thread = wakeup_callback_handle_table.Get<Thread>((Handle)thread_handle); const auto proper_handle = static_cast<Handle>(thread_handle);
SharedPtr<Thread> thread = wakeup_callback_handle_table.Get<Thread>(proper_handle);
if (thread == nullptr) { if (thread == nullptr) {
LOG_CRITICAL(Kernel, "Callback fired for invalid thread %08X", (Handle)thread_handle); NGLOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", proper_handle);
return; return;
} }
@ -126,6 +124,19 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
resume = thread->wakeup_callback(ThreadWakeupReason::Timeout, thread, nullptr, 0); resume = thread->wakeup_callback(ThreadWakeupReason::Timeout, thread, nullptr, 0);
} }
if (thread->mutex_wait_address != 0 || thread->condvar_wait_address != 0 ||
thread->wait_handle) {
ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX);
thread->mutex_wait_address = 0;
thread->condvar_wait_address = 0;
thread->wait_handle = 0;
auto lock_owner = thread->lock_owner;
// Threads waking up by timeout from WaitProcessWideKey do not perform priority inheritance
// and don't have a lock owner.
ASSERT(lock_owner == nullptr);
}
if (resume) if (resume)
thread->ResumeFromWait(); thread->ResumeFromWait();
} }
@ -151,6 +162,7 @@ void Thread::ResumeFromWait() {
case THREADSTATUS_WAIT_HLE_EVENT: case THREADSTATUS_WAIT_HLE_EVENT:
case THREADSTATUS_WAIT_SLEEP: case THREADSTATUS_WAIT_SLEEP:
case THREADSTATUS_WAIT_IPC: case THREADSTATUS_WAIT_IPC:
case THREADSTATUS_WAIT_MUTEX:
break; break;
case THREADSTATUS_READY: case THREADSTATUS_READY:
@ -227,19 +239,19 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
SharedPtr<Process> owner_process) { SharedPtr<Process> owner_process) {
// Check if priority is in ranged. Lowest priority -> highest priority id. // Check if priority is in ranged. Lowest priority -> highest priority id.
if (priority > THREADPRIO_LOWEST) { if (priority > THREADPRIO_LOWEST) {
LOG_ERROR(Kernel_SVC, "Invalid thread priority: %u", priority); NGLOG_ERROR(Kernel_SVC, "Invalid thread priority: {}", priority);
return ERR_OUT_OF_RANGE; return ERR_OUT_OF_RANGE;
} }
if (processor_id > THREADPROCESSORID_MAX) { if (processor_id > THREADPROCESSORID_MAX) {
LOG_ERROR(Kernel_SVC, "Invalid processor id: %d", processor_id); NGLOG_ERROR(Kernel_SVC, "Invalid processor id: {}", processor_id);
return ERR_OUT_OF_RANGE_KERNEL; return ERR_OUT_OF_RANGE_KERNEL;
} }
// TODO(yuriks): Other checks, returning 0xD9001BEA // TODO(yuriks): Other checks, returning 0xD9001BEA
if (!Memory::IsValidVirtualAddress(*owner_process, entry_point)) { if (!Memory::IsValidVirtualAddress(*owner_process, entry_point)) {
LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %016" PRIx64, name.c_str(), entry_point); NGLOG_ERROR(Kernel_SVC, "(name={}): invalid entry {:016X}", name, entry_point);
// TODO (bunnei): Find the correct error code to use here // TODO (bunnei): Find the correct error code to use here
return ResultCode(-1); return ResultCode(-1);
} }
@ -256,7 +268,9 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
thread->last_running_ticks = CoreTiming::GetTicks(); thread->last_running_ticks = CoreTiming::GetTicks();
thread->processor_id = processor_id; thread->processor_id = processor_id;
thread->wait_objects.clear(); thread->wait_objects.clear();
thread->wait_address = 0; thread->mutex_wait_address = 0;
thread->condvar_wait_address = 0;
thread->wait_handle = 0;
thread->name = std::move(name); thread->name = std::move(name);
thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap(); thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap();
thread->owner_process = owner_process; thread->owner_process = owner_process;
@ -276,7 +290,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
auto& linheap_memory = memory_region->linear_heap_memory; auto& linheap_memory = memory_region->linear_heap_memory;
if (linheap_memory->size() + Memory::PAGE_SIZE > memory_region->size) { if (linheap_memory->size() + Memory::PAGE_SIZE > memory_region->size) {
LOG_ERROR(Kernel_SVC, NGLOG_ERROR(Kernel_SVC,
"Not enough space in region to allocate a new TLS page for thread"); "Not enough space in region to allocate a new TLS page for thread");
return ERR_OUT_OF_MEMORY; return ERR_OUT_OF_MEMORY;
} }
@ -317,17 +331,8 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
void Thread::SetPriority(u32 priority) { void Thread::SetPriority(u32 priority) {
ASSERT_MSG(priority <= THREADPRIO_LOWEST && priority >= THREADPRIO_HIGHEST, ASSERT_MSG(priority <= THREADPRIO_LOWEST && priority >= THREADPRIO_HIGHEST,
"Invalid priority value."); "Invalid priority value.");
Core::System::GetInstance().Scheduler().SetThreadPriority(this, priority); nominal_priority = priority;
nominal_priority = current_priority = priority; UpdatePriority();
}
void Thread::UpdatePriority() {
u32 best_priority = nominal_priority;
for (auto& mutex : held_mutexes) {
if (mutex->priority < best_priority)
best_priority = mutex->priority;
}
BoostPriority(best_priority);
} }
void Thread::BoostPriority(u32 priority) { void Thread::BoostPriority(u32 priority) {
@ -377,6 +382,38 @@ VAddr Thread::GetCommandBufferAddress() const {
return GetTLSAddress() + CommandHeaderOffset; return GetTLSAddress() + CommandHeaderOffset;
} }
void Thread::AddMutexWaiter(SharedPtr<Thread> thread) {
thread->lock_owner = this;
wait_mutex_threads.emplace_back(std::move(thread));
UpdatePriority();
}
void Thread::RemoveMutexWaiter(SharedPtr<Thread> thread) {
boost::remove_erase(wait_mutex_threads, thread);
thread->lock_owner = nullptr;
UpdatePriority();
}
void Thread::UpdatePriority() {
// Find the highest priority among all the threads that are waiting for this thread's lock
u32 new_priority = nominal_priority;
for (const auto& thread : wait_mutex_threads) {
if (thread->nominal_priority < new_priority)
new_priority = thread->nominal_priority;
}
if (new_priority == current_priority)
return;
Core::System::GetInstance().Scheduler().SetThreadPriority(this, new_priority);
current_priority = new_priority;
// Recursively update the priority of the thread that depends on the priority of this one.
if (lock_owner)
lock_owner->UpdatePriority();
}
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
/** /**

View file

@ -18,7 +18,7 @@
enum ThreadPriority : u32 { enum ThreadPriority : u32 {
THREADPRIO_HIGHEST = 0, ///< Highest thread priority THREADPRIO_HIGHEST = 0, ///< Highest thread priority
THREADPRIO_USERLAND_MAX = 24, ///< Highest thread priority for userland apps THREADPRIO_USERLAND_MAX = 24, ///< Highest thread priority for userland apps
THREADPRIO_DEFAULT = 48, ///< Default thread priority for userland apps THREADPRIO_DEFAULT = 44, ///< Default thread priority for userland apps
THREADPRIO_LOWEST = 63, ///< Lowest thread priority THREADPRIO_LOWEST = 63, ///< Lowest thread priority
}; };
@ -43,6 +43,7 @@ enum ThreadStatus {
THREADSTATUS_WAIT_IPC, ///< Waiting for the reply from an IPC request THREADSTATUS_WAIT_IPC, ///< Waiting for the reply from an IPC request
THREADSTATUS_WAIT_SYNCH_ANY, ///< Waiting due to WaitSynch1 or WaitSynchN with wait_all = false THREADSTATUS_WAIT_SYNCH_ANY, ///< Waiting due to WaitSynch1 or WaitSynchN with wait_all = false
THREADSTATUS_WAIT_SYNCH_ALL, ///< Waiting due to WaitSynchronizationN with wait_all = true THREADSTATUS_WAIT_SYNCH_ALL, ///< Waiting due to WaitSynchronizationN with wait_all = true
THREADSTATUS_WAIT_MUTEX, ///< Waiting due to an ArbitrateLock/WaitProcessWideKey svc
THREADSTATUS_DORMANT, ///< Created but not yet made ready THREADSTATUS_DORMANT, ///< Created but not yet made ready
THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated
}; };
@ -54,7 +55,6 @@ enum class ThreadWakeupReason {
namespace Kernel { namespace Kernel {
class Mutex;
class Process; class Process;
class Thread final : public WaitObject { class Thread final : public WaitObject {
@ -103,18 +103,21 @@ public:
*/ */
void SetPriority(u32 priority); void SetPriority(u32 priority);
/**
* Boost's a thread's priority to the best priority among the thread's held mutexes.
* This prevents priority inversion via priority inheritance.
*/
void UpdatePriority();
/** /**
* Temporarily boosts the thread's priority until the next time it is scheduled * Temporarily boosts the thread's priority until the next time it is scheduled
* @param priority The new priority * @param priority The new priority
*/ */
void BoostPriority(u32 priority); void BoostPriority(u32 priority);
/// Adds a thread to the list of threads that are waiting for a lock held by this thread.
void AddMutexWaiter(SharedPtr<Thread> thread);
/// Removes a thread from the list of threads that are waiting for a lock held by this thread.
void RemoveMutexWaiter(SharedPtr<Thread> thread);
/// Recalculates the current priority taking into account priority inheritance.
void UpdatePriority();
/** /**
* Gets the thread's thread ID * Gets the thread's thread ID
* @return The thread's ID * @return The thread's ID
@ -205,19 +208,22 @@ public:
VAddr tls_address; ///< Virtual address of the Thread Local Storage of the thread VAddr tls_address; ///< Virtual address of the Thread Local Storage of the thread
/// Mutexes currently held by this thread, which will be released when it exits.
boost::container::flat_set<SharedPtr<Mutex>> held_mutexes;
/// Mutexes that this thread is currently waiting for.
boost::container::flat_set<SharedPtr<Mutex>> pending_mutexes;
SharedPtr<Process> owner_process; ///< Process that owns this thread SharedPtr<Process> owner_process; ///< Process that owns this thread
/// Objects that the thread is waiting on, in the same order as they were /// Objects that the thread is waiting on, in the same order as they were
// passed to WaitSynchronization1/N. // passed to WaitSynchronization1/N.
std::vector<SharedPtr<WaitObject>> wait_objects; std::vector<SharedPtr<WaitObject>> wait_objects;
VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address /// List of threads that are waiting for a mutex that is held by this thread.
std::vector<SharedPtr<Thread>> wait_mutex_threads;
/// Thread that owns the lock that this thread is waiting for.
SharedPtr<Thread> lock_owner;
// If waiting on a ConditionVariable, this is the ConditionVariable address
VAddr condvar_wait_address;
VAddr mutex_wait_address; ///< If waiting on a Mutex, this is the mutex address
Handle wait_handle; ///< The handle used to wait for the mutex.
std::string name; std::string name;

View file

@ -77,7 +77,7 @@ void Timer::WakeupAllWaitingThreads() {
} }
void Timer::Signal(int cycles_late) { void Timer::Signal(int cycles_late) {
LOG_TRACE(Kernel, "Timer %u fired", GetObjectId()); NGLOG_TRACE(Kernel, "Timer {} fired", GetObjectId());
signaled = true; signaled = true;
@ -97,7 +97,7 @@ static void TimerCallback(u64 timer_handle, int cycles_late) {
timer_callback_handle_table.Get<Timer>(static_cast<Handle>(timer_handle)); timer_callback_handle_table.Get<Timer>(static_cast<Handle>(timer_handle));
if (timer == nullptr) { if (timer == nullptr) {
LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08" PRIx64, timer_handle); NGLOG_CRITICAL(Kernel, "Callback fired for invalid timer {:016X}", timer_handle);
return; return;
} }

View file

@ -379,22 +379,22 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) {
} }
u64 VMManager::GetTotalMemoryUsage() { u64 VMManager::GetTotalMemoryUsage() {
LOG_WARNING(Kernel, "(STUBBED) called"); NGLOG_WARNING(Kernel, "(STUBBED) called");
return 0xF8000000; return 0xF8000000;
} }
u64 VMManager::GetTotalHeapUsage() { u64 VMManager::GetTotalHeapUsage() {
LOG_WARNING(Kernel, "(STUBBED) called"); NGLOG_WARNING(Kernel, "(STUBBED) called");
return 0x0; return 0x0;
} }
VAddr VMManager::GetAddressSpaceBaseAddr() { VAddr VMManager::GetAddressSpaceBaseAddr() {
LOG_WARNING(Kernel, "(STUBBED) called"); NGLOG_WARNING(Kernel, "(STUBBED) called");
return 0x8000000; return 0x8000000;
} }
u64 VMManager::GetAddressSpaceSize() { u64 VMManager::GetAddressSpaceSize() {
LOG_WARNING(Kernel, "(STUBBED) called"); NGLOG_WARNING(Kernel, "(STUBBED) called");
return MAX_ADDRESS; return MAX_ADDRESS;
} }

View file

@ -47,7 +47,7 @@ public:
private: private:
void GetBase(Kernel::HLERequestContext& ctx) { void GetBase(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called"); NGLOG_WARNING(Service_ACC, "(STUBBED) called");
ProfileBase profile_base{}; ProfileBase profile_base{};
IPC::ResponseBuilder rb{ctx, 16}; IPC::ResponseBuilder rb{ctx, 16};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
@ -72,14 +72,14 @@ public:
private: private:
void CheckAvailability(Kernel::HLERequestContext& ctx) { void CheckAvailability(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called"); NGLOG_WARNING(Service_ACC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push(true); // TODO: Check when this is supposed to return true and when not rb.Push(true); // TODO: Check when this is supposed to return true and when not
} }
void GetAccountId(Kernel::HLERequestContext& ctx) { void GetAccountId(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called"); NGLOG_WARNING(Service_ACC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push<u64>(0x12345678ABCDEF); rb.Push<u64>(0x12345678ABCDEF);
@ -87,14 +87,14 @@ private:
}; };
void Module::Interface::GetUserExistence(Kernel::HLERequestContext& ctx) { void Module::Interface::GetUserExistence(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called"); NGLOG_WARNING(Service_ACC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push(true); // TODO: Check when this is supposed to return true and when not rb.Push(true); // TODO: Check when this is supposed to return true and when not
} }
void Module::Interface::ListAllUsers(Kernel::HLERequestContext& ctx) { void Module::Interface::ListAllUsers(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called"); NGLOG_WARNING(Service_ACC, "(STUBBED) called");
constexpr std::array<u128, 10> user_ids{DEFAULT_USER_ID}; constexpr std::array<u128, 10> user_ids{DEFAULT_USER_ID};
ctx.WriteBuffer(user_ids.data(), user_ids.size()); ctx.WriteBuffer(user_ids.data(), user_ids.size());
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
@ -102,7 +102,7 @@ void Module::Interface::ListAllUsers(Kernel::HLERequestContext& ctx) {
} }
void Module::Interface::ListOpenUsers(Kernel::HLERequestContext& ctx) { void Module::Interface::ListOpenUsers(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called"); NGLOG_WARNING(Service_ACC, "(STUBBED) called");
constexpr std::array<u128, 10> user_ids{DEFAULT_USER_ID}; constexpr std::array<u128, 10> user_ids{DEFAULT_USER_ID};
ctx.WriteBuffer(user_ids.data(), user_ids.size()); ctx.WriteBuffer(user_ids.data(), user_ids.size());
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
@ -113,11 +113,11 @@ void Module::Interface::GetProfile(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IProfile>(); rb.PushIpcInterface<IProfile>();
LOG_DEBUG(Service_ACC, "called"); NGLOG_DEBUG(Service_ACC, "called");
} }
void Module::Interface::InitializeApplicationInfo(Kernel::HLERequestContext& ctx) { void Module::Interface::InitializeApplicationInfo(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called"); NGLOG_WARNING(Service_ACC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
} }
@ -126,11 +126,11 @@ void Module::Interface::GetBaasAccountManagerForApplication(Kernel::HLERequestCo
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IManagerForApplication>(); rb.PushIpcInterface<IManagerForApplication>();
LOG_DEBUG(Service_ACC, "called"); NGLOG_DEBUG(Service_ACC, "called");
} }
void Module::Interface::GetLastOpenedUser(Kernel::HLERequestContext& ctx) { void Module::Interface::GetLastOpenedUser(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called"); NGLOG_WARNING(Service_ACC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 6}; IPC::ResponseBuilder rb{ctx, 6};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushRaw(DEFAULT_USER_ID); rb.PushRaw(DEFAULT_USER_ID);

View file

@ -28,14 +28,14 @@ IWindowController::IWindowController() : ServiceFramework("IWindowController") {
} }
void IWindowController::GetAppletResourceUserId(Kernel::HLERequestContext& ctx) { void IWindowController::GetAppletResourceUserId(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called"); NGLOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push<u64>(0); rb.Push<u64>(0);
} }
void IWindowController::AcquireForegroundRights(Kernel::HLERequestContext& ctx) { void IWindowController::AcquireForegroundRights(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called"); NGLOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
} }
@ -54,20 +54,20 @@ IAudioController::IAudioController() : ServiceFramework("IAudioController") {
} }
void IAudioController::SetExpectedMasterVolume(Kernel::HLERequestContext& ctx) { void IAudioController::SetExpectedMasterVolume(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called"); NGLOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
} }
void IAudioController::GetMainAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx) { void IAudioController::GetMainAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called"); NGLOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push(volume); rb.Push(volume);
} }
void IAudioController::GetLibraryAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx) { void IAudioController::GetLibraryAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called"); NGLOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push(volume); rb.Push(volume);
@ -139,14 +139,14 @@ void ISelfController::SetFocusHandlingMode(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called"); NGLOG_WARNING(Service_AM, "(STUBBED) called");
} }
void ISelfController::SetRestartMessageEnabled(Kernel::HLERequestContext& ctx) { void ISelfController::SetRestartMessageEnabled(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called"); NGLOG_WARNING(Service_AM, "(STUBBED) called");
} }
void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) { void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) {
@ -157,14 +157,14 @@ void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestCo
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called flag=%u", static_cast<u32>(flag)); NGLOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
} }
void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) { void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called"); NGLOG_WARNING(Service_AM, "(STUBBED) called");
} }
void ISelfController::SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx) { void ISelfController::SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx) {
@ -175,7 +175,7 @@ void ISelfController::SetOperationModeChangedNotification(Kernel::HLERequestCont
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called flag=%u", static_cast<u32>(flag)); NGLOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
} }
void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) { void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) {
@ -188,21 +188,21 @@ void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext&
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called enabled=%u", static_cast<u32>(enabled)); NGLOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled);
} }
void ISelfController::LockExit(Kernel::HLERequestContext& ctx) { void ISelfController::LockExit(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called"); NGLOG_WARNING(Service_AM, "(STUBBED) called");
} }
void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) { void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called"); NGLOG_WARNING(Service_AM, "(STUBBED) called");
} }
void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) { void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) {
@ -212,7 +212,7 @@ void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext&
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(launchable_event); rb.PushCopyObjects(launchable_event);
LOG_WARNING(Service_AM, "(STUBBED) called"); NGLOG_WARNING(Service_AM, "(STUBBED) called");
} }
void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx) { void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx) {
@ -225,7 +225,7 @@ void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx)
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push(layer_id); rb.Push(layer_id);
LOG_WARNING(Service_AM, "(STUBBED) called"); NGLOG_WARNING(Service_AM, "(STUBBED) called");
} }
ICommonStateGetter::ICommonStateGetter() : ServiceFramework("ICommonStateGetter") { ICommonStateGetter::ICommonStateGetter() : ServiceFramework("ICommonStateGetter") {
@ -269,7 +269,7 @@ void ICommonStateGetter::GetEventHandle(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(event); rb.PushCopyObjects(event);
LOG_WARNING(Service_AM, "(STUBBED) called"); NGLOG_WARNING(Service_AM, "(STUBBED) called");
} }
void ICommonStateGetter::ReceiveMessage(Kernel::HLERequestContext& ctx) { void ICommonStateGetter::ReceiveMessage(Kernel::HLERequestContext& ctx) {
@ -277,7 +277,7 @@ void ICommonStateGetter::ReceiveMessage(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push<u32>(15); rb.Push<u32>(15);
LOG_WARNING(Service_AM, "(STUBBED) called"); NGLOG_WARNING(Service_AM, "(STUBBED) called");
} }
void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) { void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) {
@ -285,7 +285,7 @@ void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push(static_cast<u8>(FocusState::InFocus)); rb.Push(static_cast<u8>(FocusState::InFocus));
LOG_WARNING(Service_AM, "(STUBBED) called"); NGLOG_WARNING(Service_AM, "(STUBBED) called");
} }
void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) { void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) {
@ -294,7 +294,7 @@ void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push(static_cast<u8>(use_docked_mode ? OperationMode::Docked : OperationMode::Handheld)); rb.Push(static_cast<u8>(use_docked_mode ? OperationMode::Docked : OperationMode::Handheld));
LOG_WARNING(Service_AM, "(STUBBED) called"); NGLOG_WARNING(Service_AM, "(STUBBED) called");
} }
void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) { void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) {
@ -304,7 +304,7 @@ void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) {
rb.Push(static_cast<u32>(use_docked_mode ? APM::PerformanceMode::Docked rb.Push(static_cast<u32>(use_docked_mode ? APM::PerformanceMode::Docked
: APM::PerformanceMode::Handheld)); : APM::PerformanceMode::Handheld));
LOG_WARNING(Service_AM, "(STUBBED) called"); NGLOG_WARNING(Service_AM, "(STUBBED) called");
} }
class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> { class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> {
@ -344,7 +344,7 @@ private:
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(state_changed_event); rb.PushCopyObjects(state_changed_event);
LOG_WARNING(Service_AM, "(STUBBED) called"); NGLOG_WARNING(Service_AM, "(STUBBED) called");
} }
Kernel::SharedPtr<Kernel::Event> state_changed_event; Kernel::SharedPtr<Kernel::Event> state_changed_event;
@ -368,7 +368,7 @@ void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx)
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<AM::ILibraryAppletAccessor>(); rb.PushIpcInterface<AM::ILibraryAppletAccessor>();
LOG_DEBUG(Service_AM, "called"); NGLOG_DEBUG(Service_AM, "called");
} }
class IStorageAccessor final : public ServiceFramework<IStorageAccessor> { class IStorageAccessor final : public ServiceFramework<IStorageAccessor> {
@ -392,7 +392,7 @@ private:
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push(static_cast<u64>(buffer.size())); rb.Push(static_cast<u64>(buffer.size()));
LOG_DEBUG(Service_AM, "called"); NGLOG_DEBUG(Service_AM, "called");
} }
void Read(Kernel::HLERequestContext& ctx) { void Read(Kernel::HLERequestContext& ctx) {
@ -410,7 +410,7 @@ private:
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_AM, "called"); NGLOG_DEBUG(Service_AM, "called");
} }
}; };
@ -434,7 +434,7 @@ private:
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<AM::IStorageAccessor>(buffer); rb.PushIpcInterface<AM::IStorageAccessor>(buffer);
LOG_DEBUG(Service_AM, "called"); NGLOG_DEBUG(Service_AM, "called");
} }
}; };
@ -498,14 +498,14 @@ void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<AM::IStorage>(buffer); rb.PushIpcInterface<AM::IStorage>(buffer);
LOG_DEBUG(Service_AM, "called"); NGLOG_DEBUG(Service_AM, "called");
} }
void IApplicationFunctions::EnsureSaveData(Kernel::HLERequestContext& ctx) { void IApplicationFunctions::EnsureSaveData(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
u128 uid = rp.PopRaw<u128>(); u128 uid = rp.PopRaw<u128>();
LOG_WARNING(Service, "(STUBBED) called uid = %016" PRIX64 "%016" PRIX64, uid[1], uid[0]); NGLOG_WARNING(Service, "(STUBBED) called uid = {:016X}{:016X}", uid[1], uid[0]);
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
@ -533,27 +533,27 @@ void IApplicationFunctions::SetTerminateResult(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called, result=0x%08X", result); NGLOG_WARNING(Service_AM, "(STUBBED) called, result={:#010}", result);
} }
void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) { void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push<u64>(SystemLanguage::English); rb.Push<u64>(SystemLanguage::English);
LOG_WARNING(Service_AM, "(STUBBED) called"); NGLOG_WARNING(Service_AM, "(STUBBED) called");
} }
void IApplicationFunctions::InitializeGamePlayRecording(Kernel::HLERequestContext& ctx) { void IApplicationFunctions::InitializeGamePlayRecording(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called"); NGLOG_WARNING(Service_AM, "(STUBBED) called");
} }
void IApplicationFunctions::SetGamePlayRecordingState(Kernel::HLERequestContext& ctx) { void IApplicationFunctions::SetGamePlayRecordingState(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_AM, "(STUBBED) called"); NGLOG_WARNING(Service_AM, "(STUBBED) called");
} }
void IApplicationFunctions::NotifyRunning(Kernel::HLERequestContext& ctx) { void IApplicationFunctions::NotifyRunning(Kernel::HLERequestContext& ctx) {
@ -561,7 +561,7 @@ void IApplicationFunctions::NotifyRunning(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push<u8>(0); // Unknown, seems to be ignored by official processes rb.Push<u8>(0); // Unknown, seems to be ignored by official processes
LOG_WARNING(Service_AM, "(STUBBED) called"); NGLOG_WARNING(Service_AM, "(STUBBED) called");
} }
void InstallInterfaces(SM::ServiceManager& service_manager, void InstallInterfaces(SM::ServiceManager& service_manager,

View file

@ -33,56 +33,56 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ICommonStateGetter>(); rb.PushIpcInterface<ICommonStateGetter>();
LOG_DEBUG(Service_AM, "called"); NGLOG_DEBUG(Service_AM, "called");
} }
void GetSelfController(Kernel::HLERequestContext& ctx) { void GetSelfController(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISelfController>(nvflinger); rb.PushIpcInterface<ISelfController>(nvflinger);
LOG_DEBUG(Service_AM, "called"); NGLOG_DEBUG(Service_AM, "called");
} }
void GetWindowController(Kernel::HLERequestContext& ctx) { void GetWindowController(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IWindowController>(); rb.PushIpcInterface<IWindowController>();
LOG_DEBUG(Service_AM, "called"); NGLOG_DEBUG(Service_AM, "called");
} }
void GetAudioController(Kernel::HLERequestContext& ctx) { void GetAudioController(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IAudioController>(); rb.PushIpcInterface<IAudioController>();
LOG_DEBUG(Service_AM, "called"); NGLOG_DEBUG(Service_AM, "called");
} }
void GetDisplayController(Kernel::HLERequestContext& ctx) { void GetDisplayController(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IDisplayController>(); rb.PushIpcInterface<IDisplayController>();
LOG_DEBUG(Service_AM, "called"); NGLOG_DEBUG(Service_AM, "called");
} }
void GetDebugFunctions(Kernel::HLERequestContext& ctx) { void GetDebugFunctions(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IDebugFunctions>(); rb.PushIpcInterface<IDebugFunctions>();
LOG_DEBUG(Service_AM, "called"); NGLOG_DEBUG(Service_AM, "called");
} }
void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) { void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ILibraryAppletCreator>(); rb.PushIpcInterface<ILibraryAppletCreator>();
LOG_DEBUG(Service_AM, "called"); NGLOG_DEBUG(Service_AM, "called");
} }
void GetApplicationFunctions(Kernel::HLERequestContext& ctx) { void GetApplicationFunctions(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IApplicationFunctions>(); rb.PushIpcInterface<IApplicationFunctions>();
LOG_DEBUG(Service_AM, "called"); NGLOG_DEBUG(Service_AM, "called");
} }
std::shared_ptr<NVFlinger::NVFlinger> nvflinger; std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
@ -92,7 +92,7 @@ void AppletAE::OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger); rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger);
LOG_DEBUG(Service_AM, "called"); NGLOG_DEBUG(Service_AM, "called");
} }
AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger) AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)

View file

@ -33,56 +33,56 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IAudioController>(); rb.PushIpcInterface<IAudioController>();
LOG_DEBUG(Service_AM, "called"); NGLOG_DEBUG(Service_AM, "called");
} }
void GetDisplayController(Kernel::HLERequestContext& ctx) { void GetDisplayController(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IDisplayController>(); rb.PushIpcInterface<IDisplayController>();
LOG_DEBUG(Service_AM, "called"); NGLOG_DEBUG(Service_AM, "called");
} }
void GetDebugFunctions(Kernel::HLERequestContext& ctx) { void GetDebugFunctions(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IDebugFunctions>(); rb.PushIpcInterface<IDebugFunctions>();
LOG_DEBUG(Service_AM, "called"); NGLOG_DEBUG(Service_AM, "called");
} }
void GetWindowController(Kernel::HLERequestContext& ctx) { void GetWindowController(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IWindowController>(); rb.PushIpcInterface<IWindowController>();
LOG_DEBUG(Service_AM, "called"); NGLOG_DEBUG(Service_AM, "called");
} }
void GetSelfController(Kernel::HLERequestContext& ctx) { void GetSelfController(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISelfController>(nvflinger); rb.PushIpcInterface<ISelfController>(nvflinger);
LOG_DEBUG(Service_AM, "called"); NGLOG_DEBUG(Service_AM, "called");
} }
void GetCommonStateGetter(Kernel::HLERequestContext& ctx) { void GetCommonStateGetter(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ICommonStateGetter>(); rb.PushIpcInterface<ICommonStateGetter>();
LOG_DEBUG(Service_AM, "called"); NGLOG_DEBUG(Service_AM, "called");
} }
void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) { void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ILibraryAppletCreator>(); rb.PushIpcInterface<ILibraryAppletCreator>();
LOG_DEBUG(Service_AM, "called"); NGLOG_DEBUG(Service_AM, "called");
} }
void GetApplicationFunctions(Kernel::HLERequestContext& ctx) { void GetApplicationFunctions(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IApplicationFunctions>(); rb.PushIpcInterface<IApplicationFunctions>();
LOG_DEBUG(Service_AM, "called"); NGLOG_DEBUG(Service_AM, "called");
} }
std::shared_ptr<NVFlinger::NVFlinger> nvflinger; std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
@ -92,7 +92,7 @@ void AppletOE::OpenApplicationProxy(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IApplicationProxy>(nvflinger); rb.PushIpcInterface<IApplicationProxy>(nvflinger);
LOG_DEBUG(Service_AM, "called"); NGLOG_DEBUG(Service_AM, "called");
} }
AppletOE::AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger) AppletOE::AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)

View file

@ -27,14 +27,14 @@ void AOC_U::CountAddOnContent(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push<u64>(0); rb.Push<u64>(0);
LOG_WARNING(Service_AOC, "(STUBBED) called"); NGLOG_WARNING(Service_AOC, "(STUBBED) called");
} }
void AOC_U::ListAddOnContent(Kernel::HLERequestContext& ctx) { void AOC_U::ListAddOnContent(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push<u64>(0); rb.Push<u64>(0);
LOG_WARNING(Service_AOC, "(STUBBED) called"); NGLOG_WARNING(Service_AOC, "(STUBBED) called");
} }
void InstallInterfaces(SM::ServiceManager& service_manager) { void InstallInterfaces(SM::ServiceManager& service_manager) {

View file

@ -29,7 +29,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_APM, "(STUBBED) called mode=%u config=%u", static_cast<u32>(mode), NGLOG_WARNING(Service_APM, "(STUBBED) called mode={} config={}", static_cast<u32>(mode),
config); config);
} }
@ -42,7 +42,7 @@ private:
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0); // Performance configuration rb.Push<u32>(0); // Performance configuration
LOG_WARNING(Service_APM, "(STUBBED) called mode=%u", static_cast<u32>(mode)); NGLOG_WARNING(Service_APM, "(STUBBED) called mode={}", static_cast<u32>(mode));
} }
}; };

View file

@ -60,14 +60,14 @@ public:
private: private:
void GetAudioOutState(Kernel::HLERequestContext& ctx) { void GetAudioOutState(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "called"); NGLOG_DEBUG(Service_Audio, "called");
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push(static_cast<u32>(audio_out_state)); rb.Push(static_cast<u32>(audio_out_state));
} }
void StartAudioOut(Kernel::HLERequestContext& ctx) { void StartAudioOut(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called"); NGLOG_WARNING(Service_Audio, "(STUBBED) called");
// Start audio // Start audio
audio_out_state = AudioState::Started; audio_out_state = AudioState::Started;
@ -77,7 +77,7 @@ private:
} }
void StopAudioOut(Kernel::HLERequestContext& ctx) { void StopAudioOut(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called"); NGLOG_WARNING(Service_Audio, "(STUBBED) called");
// Stop audio // Stop audio
audio_out_state = AudioState::Stopped; audio_out_state = AudioState::Stopped;
@ -89,7 +89,7 @@ private:
} }
void RegisterBufferEvent(Kernel::HLERequestContext& ctx) { void RegisterBufferEvent(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called"); NGLOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 1}; IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
@ -97,7 +97,7 @@ private:
} }
void AppendAudioOutBuffer(Kernel::HLERequestContext& ctx) { void AppendAudioOutBuffer(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called"); NGLOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const u64 key{rp.Pop<u64>()}; const u64 key{rp.Pop<u64>()};
@ -108,7 +108,7 @@ private:
} }
void GetReleasedAudioOutBuffer(Kernel::HLERequestContext& ctx) { void GetReleasedAudioOutBuffer(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called"); NGLOG_WARNING(Service_Audio, "(STUBBED) called");
// TODO(st4rk): This is how libtransistor currently implements the // TODO(st4rk): This is how libtransistor currently implements the
// GetReleasedAudioOutBuffer, it should return the key (a VAddr) to the app and this address // GetReleasedAudioOutBuffer, it should return the key (a VAddr) to the app and this address
@ -164,7 +164,7 @@ private:
}; };
void AudOutU::ListAudioOuts(Kernel::HLERequestContext& ctx) { void AudOutU::ListAudioOuts(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called"); NGLOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const std::string audio_interface = "AudioInterface"; const std::string audio_interface = "AudioInterface";
@ -180,7 +180,7 @@ void AudOutU::ListAudioOuts(Kernel::HLERequestContext& ctx) {
} }
void AudOutU::OpenAudioOut(Kernel::HLERequestContext& ctx) { void AudOutU::OpenAudioOut(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called"); NGLOG_WARNING(Service_Audio, "(STUBBED) called");
if (!audio_out_interface) { if (!audio_out_interface) {
audio_out_interface = std::make_shared<IAudioOut>(); audio_out_interface = std::make_shared<IAudioOut>();

View file

@ -56,7 +56,7 @@ private:
} }
void RequestUpdateAudioRenderer(Kernel::HLERequestContext& ctx) { void RequestUpdateAudioRenderer(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "%s", ctx.Description().c_str()); NGLOG_DEBUG(Service_Audio, "{}", ctx.Description());
AudioRendererResponseData response_data{}; AudioRendererResponseData response_data{};
response_data.section_0_size = response_data.section_0_size =
@ -79,7 +79,7 @@ private:
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_Audio, "(STUBBED) called"); NGLOG_WARNING(Service_Audio, "(STUBBED) called");
} }
void StartAudioRenderer(Kernel::HLERequestContext& ctx) { void StartAudioRenderer(Kernel::HLERequestContext& ctx) {
@ -87,7 +87,7 @@ private:
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_Audio, "(STUBBED) called"); NGLOG_WARNING(Service_Audio, "(STUBBED) called");
} }
void StopAudioRenderer(Kernel::HLERequestContext& ctx) { void StopAudioRenderer(Kernel::HLERequestContext& ctx) {
@ -95,7 +95,7 @@ private:
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_Audio, "(STUBBED) called"); NGLOG_WARNING(Service_Audio, "(STUBBED) called");
} }
void QuerySystemEvent(Kernel::HLERequestContext& ctx) { void QuerySystemEvent(Kernel::HLERequestContext& ctx) {
@ -105,7 +105,7 @@ private:
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(system_event); rb.PushCopyObjects(system_event);
LOG_WARNING(Service_Audio, "(STUBBED) called"); NGLOG_WARNING(Service_Audio, "(STUBBED) called");
} }
struct AudioRendererStateEntry { struct AudioRendererStateEntry {
@ -177,7 +177,7 @@ public:
private: private:
void ListAudioDeviceName(Kernel::HLERequestContext& ctx) { void ListAudioDeviceName(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called"); NGLOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const std::string audio_interface = "AudioInterface"; const std::string audio_interface = "AudioInterface";
@ -189,7 +189,7 @@ private:
} }
void SetAudioDeviceOutputVolume(Kernel::HLERequestContext& ctx) { void SetAudioDeviceOutputVolume(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called"); NGLOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
f32 volume = static_cast<f32>(rp.Pop<u32>()); f32 volume = static_cast<f32>(rp.Pop<u32>());
@ -202,7 +202,7 @@ private:
} }
void GetActiveAudioDeviceName(Kernel::HLERequestContext& ctx) { void GetActiveAudioDeviceName(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called"); NGLOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const std::string audio_interface = "AudioDevice"; const std::string audio_interface = "AudioDevice";
@ -214,7 +214,7 @@ private:
} }
void QueryAudioDeviceSystemEvent(Kernel::HLERequestContext& ctx) { void QueryAudioDeviceSystemEvent(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called"); NGLOG_WARNING(Service_Audio, "(STUBBED) called");
buffer_event->Signal(); buffer_event->Signal();
@ -224,7 +224,7 @@ private:
} }
void GetActiveChannelCount(Kernel::HLERequestContext& ctx) { void GetActiveChannelCount(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called"); NGLOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push<u32>(1); rb.Push<u32>(1);
@ -251,7 +251,7 @@ void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<Audio::IAudioRenderer>(); rb.PushIpcInterface<Audio::IAudioRenderer>();
LOG_DEBUG(Service_Audio, "called"); NGLOG_DEBUG(Service_Audio, "called");
} }
void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) { void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
@ -260,7 +260,7 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push<u64>(0x4000); rb.Push<u64>(0x4000);
LOG_WARNING(Service_Audio, "(STUBBED) called"); NGLOG_WARNING(Service_Audio, "(STUBBED) called");
} }
void AudRenU::GetAudioDevice(Kernel::HLERequestContext& ctx) { void AudRenU::GetAudioDevice(Kernel::HLERequestContext& ctx) {
@ -269,7 +269,7 @@ void AudRenU::GetAudioDevice(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<Audio::IAudioDevice>(); rb.PushIpcInterface<Audio::IAudioDevice>();
LOG_DEBUG(Service_Audio, "called"); NGLOG_DEBUG(Service_Audio, "called");
} }
} // namespace Service::Audio } // namespace Service::Audio

View file

@ -16,13 +16,13 @@ Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
void Module::Interface::FatalSimple(Kernel::HLERequestContext& ctx) { void Module::Interface::FatalSimple(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx); IPC::RequestParser rp(ctx);
u32 error_code = rp.Pop<u32>(); u32 error_code = rp.Pop<u32>();
LOG_WARNING(Service_Fatal, "(STUBBED) called, error_code=0x%X", error_code); NGLOG_WARNING(Service_Fatal, "(STUBBED) called, error_code={:#X}", error_code);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
} }
void Module::Interface::TransitionToFatalError(Kernel::HLERequestContext& ctx) { void Module::Interface::TransitionToFatalError(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Fatal, "(STUBBED) called"); NGLOG_WARNING(Service_Fatal, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
} }

View file

@ -25,14 +25,14 @@ ResultCode RegisterFileSystem(std::unique_ptr<FileSys::FileSystemFactory>&& fact
ASSERT_MSG(inserted, "Tried to register more than one system with same id code"); ASSERT_MSG(inserted, "Tried to register more than one system with same id code");
auto& filesystem = result.first->second; auto& filesystem = result.first->second;
LOG_DEBUG(Service_FS, "Registered file system %s with id code 0x%08X", NGLOG_DEBUG(Service_FS, "Registered file system {} with id code {:#010X}",
filesystem->GetName().c_str(), static_cast<u32>(type)); filesystem->GetName(), static_cast<u32>(type));
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenFileSystem(Type type, ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenFileSystem(Type type,
FileSys::Path& path) { FileSys::Path& path) {
LOG_TRACE(Service_FS, "Opening FileSystem with type=%d", type); NGLOG_TRACE(Service_FS, "Opening FileSystem with type={}", static_cast<u32>(type));
auto itr = filesystem_map.find(type); auto itr = filesystem_map.find(type);
if (itr == filesystem_map.end()) { if (itr == filesystem_map.end()) {
@ -44,7 +44,7 @@ ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenFileSystem(Type type,
} }
ResultCode FormatFileSystem(Type type) { ResultCode FormatFileSystem(Type type) {
LOG_TRACE(Service_FS, "Formatting FileSystem with type=%d", type); NGLOG_TRACE(Service_FS, "Formatting FileSystem with type={}", static_cast<u32>(type));
auto itr = filesystem_map.find(type); auto itr = filesystem_map.find(type);
if (itr == filesystem_map.end()) { if (itr == filesystem_map.end()) {

View file

@ -35,7 +35,7 @@ private:
const s64 offset = rp.Pop<s64>(); const s64 offset = rp.Pop<s64>();
const s64 length = rp.Pop<s64>(); const s64 length = rp.Pop<s64>();
LOG_DEBUG(Service_FS, "called, offset=0x%ld, length=0x%ld", offset, length); NGLOG_DEBUG(Service_FS, "called, offset={:#X}, length={}", offset, length);
// Error checking // Error checking
if (length < 0) { if (length < 0) {
@ -87,7 +87,7 @@ private:
const s64 offset = rp.Pop<s64>(); const s64 offset = rp.Pop<s64>();
const s64 length = rp.Pop<s64>(); const s64 length = rp.Pop<s64>();
LOG_DEBUG(Service_FS, "called, offset=0x%ld, length=0x%ld", offset, length); NGLOG_DEBUG(Service_FS, "called, offset={:#X}, length={}", offset, length);
// Error checking // Error checking
if (length < 0) { if (length < 0) {
@ -124,7 +124,7 @@ private:
const s64 offset = rp.Pop<s64>(); const s64 offset = rp.Pop<s64>();
const s64 length = rp.Pop<s64>(); const s64 length = rp.Pop<s64>();
LOG_DEBUG(Service_FS, "called, offset=0x%ld, length=0x%ld", offset, length); NGLOG_DEBUG(Service_FS, "called, offset={:#X}, length={}", offset, length);
// Error checking // Error checking
if (length < 0) { if (length < 0) {
@ -152,7 +152,7 @@ private:
} }
void Flush(Kernel::HLERequestContext& ctx) { void Flush(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called"); NGLOG_DEBUG(Service_FS, "called");
backend->Flush(); backend->Flush();
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
@ -163,7 +163,7 @@ private:
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const u64 size = rp.Pop<u64>(); const u64 size = rp.Pop<u64>();
backend->SetSize(size); backend->SetSize(size);
LOG_DEBUG(Service_FS, "called, size=%" PRIu64, size); NGLOG_DEBUG(Service_FS, "called, size={}", size);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
@ -171,7 +171,7 @@ private:
void GetSize(Kernel::HLERequestContext& ctx) { void GetSize(Kernel::HLERequestContext& ctx) {
const u64 size = backend->GetSize(); const u64 size = backend->GetSize();
LOG_DEBUG(Service_FS, "called, size=%" PRIu64, size); NGLOG_DEBUG(Service_FS, "called, size={}", size);
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
@ -197,7 +197,7 @@ private:
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const u64 unk = rp.Pop<u64>(); const u64 unk = rp.Pop<u64>();
LOG_DEBUG(Service_FS, "called, unk=0x%llx", unk); NGLOG_DEBUG(Service_FS, "called, unk={:#X}", unk);
// Calculate how many entries we can fit in the output buffer // Calculate how many entries we can fit in the output buffer
u64 count_entries = ctx.GetWriteBufferSize() / sizeof(FileSys::Entry); u64 count_entries = ctx.GetWriteBufferSize() / sizeof(FileSys::Entry);
@ -219,7 +219,7 @@ private:
} }
void GetEntryCount(Kernel::HLERequestContext& ctx) { void GetEntryCount(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called"); NGLOG_DEBUG(Service_FS, "called");
u64 count = backend->GetEntryCount(); u64 count = backend->GetEntryCount();
@ -239,7 +239,7 @@ public:
{2, &IFileSystem::CreateDirectory, "CreateDirectory"}, {2, &IFileSystem::CreateDirectory, "CreateDirectory"},
{3, nullptr, "DeleteDirectory"}, {3, nullptr, "DeleteDirectory"},
{4, nullptr, "DeleteDirectoryRecursively"}, {4, nullptr, "DeleteDirectoryRecursively"},
{5, nullptr, "RenameFile"}, {5, &IFileSystem::RenameFile, "RenameFile"},
{6, nullptr, "RenameDirectory"}, {6, nullptr, "RenameDirectory"},
{7, &IFileSystem::GetEntryType, "GetEntryType"}, {7, &IFileSystem::GetEntryType, "GetEntryType"},
{8, &IFileSystem::OpenFile, "OpenFile"}, {8, &IFileSystem::OpenFile, "OpenFile"},
@ -265,8 +265,7 @@ public:
u64 mode = rp.Pop<u64>(); u64 mode = rp.Pop<u64>();
u32 size = rp.Pop<u32>(); u32 size = rp.Pop<u32>();
LOG_DEBUG(Service_FS, "called file %s mode 0x%" PRIX64 " size 0x%08X", name.c_str(), mode, NGLOG_DEBUG(Service_FS, "called file {} mode {:#X} size {:#010X}", name, mode, size);
size);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(backend->CreateFile(name, size)); rb.Push(backend->CreateFile(name, size));
@ -280,7 +279,7 @@ public:
std::string name(file_buffer.begin(), end); std::string name(file_buffer.begin(), end);
LOG_DEBUG(Service_FS, "called file %s", name.c_str()); NGLOG_DEBUG(Service_FS, "called file {}", name);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(backend->DeleteFile(name)); rb.Push(backend->DeleteFile(name));
@ -294,12 +293,32 @@ public:
std::string name(file_buffer.begin(), end); std::string name(file_buffer.begin(), end);
LOG_DEBUG(Service_FS, "called directory %s", name.c_str()); NGLOG_DEBUG(Service_FS, "called directory {}", name);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(backend->CreateDirectory(name)); rb.Push(backend->CreateDirectory(name));
} }
void RenameFile(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
std::vector<u8> buffer;
buffer.resize(ctx.BufferDescriptorX()[0].Size());
Memory::ReadBlock(ctx.BufferDescriptorX()[0].Address(), buffer.data(), buffer.size());
auto end = std::find(buffer.begin(), buffer.end(), '\0');
std::string src_name(buffer.begin(), end);
buffer.resize(ctx.BufferDescriptorX()[1].Size());
Memory::ReadBlock(ctx.BufferDescriptorX()[1].Address(), buffer.data(), buffer.size());
end = std::find(buffer.begin(), buffer.end(), '\0');
std::string dst_name(buffer.begin(), end);
NGLOG_DEBUG(Service_FS, "called file '{}' to file '{}'", src_name, dst_name);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(backend->RenameFile(src_name, dst_name));
}
void OpenFile(Kernel::HLERequestContext& ctx) { void OpenFile(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
@ -310,7 +329,7 @@ public:
auto mode = static_cast<FileSys::Mode>(rp.Pop<u32>()); auto mode = static_cast<FileSys::Mode>(rp.Pop<u32>());
LOG_DEBUG(Service_FS, "called file %s mode %u", name.c_str(), static_cast<u32>(mode)); NGLOG_DEBUG(Service_FS, "called file {} mode {}", name, static_cast<u32>(mode));
auto result = backend->OpenFile(name, mode); auto result = backend->OpenFile(name, mode);
if (result.Failed()) { if (result.Failed()) {
@ -337,7 +356,7 @@ public:
// TODO(Subv): Implement this filter. // TODO(Subv): Implement this filter.
u32 filter_flags = rp.Pop<u32>(); u32 filter_flags = rp.Pop<u32>();
LOG_DEBUG(Service_FS, "called directory %s filter %u", name.c_str(), filter_flags); NGLOG_DEBUG(Service_FS, "called directory {} filter {}", name, filter_flags);
auto result = backend->OpenDirectory(name); auto result = backend->OpenDirectory(name);
if (result.Failed()) { if (result.Failed()) {
@ -361,7 +380,7 @@ public:
std::string name(file_buffer.begin(), end); std::string name(file_buffer.begin(), end);
LOG_DEBUG(Service_FS, "called file %s", name.c_str()); NGLOG_DEBUG(Service_FS, "called file {}", name);
auto result = backend->GetEntryType(name); auto result = backend->GetEntryType(name);
if (result.Failed()) { if (result.Failed()) {
@ -376,7 +395,7 @@ public:
} }
void Commit(Kernel::HLERequestContext& ctx) { void Commit(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_FS, "(STUBBED) called"); NGLOG_WARNING(Service_FS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
@ -492,14 +511,14 @@ void FSP_SRV::TryLoadRomFS() {
} }
void FSP_SRV::Initialize(Kernel::HLERequestContext& ctx) { void FSP_SRV::Initialize(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_FS, "(STUBBED) called"); NGLOG_WARNING(Service_FS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
} }
void FSP_SRV::MountSdCard(Kernel::HLERequestContext& ctx) { void FSP_SRV::MountSdCard(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called"); NGLOG_DEBUG(Service_FS, "called");
FileSys::Path unused; FileSys::Path unused;
auto filesystem = OpenFileSystem(Type::SDMC, unused).Unwrap(); auto filesystem = OpenFileSystem(Type::SDMC, unused).Unwrap();
@ -516,14 +535,14 @@ void FSP_SRV::CreateSaveData(Kernel::HLERequestContext& ctx) {
auto save_create_struct = rp.PopRaw<std::array<u8, 0x40>>(); auto save_create_struct = rp.PopRaw<std::array<u8, 0x40>>();
u128 uid = rp.PopRaw<u128>(); u128 uid = rp.PopRaw<u128>();
LOG_WARNING(Service_FS, "(STUBBED) called uid = %016" PRIX64 "%016" PRIX64, uid[1], uid[0]); NGLOG_WARNING(Service_FS, "(STUBBED) called uid = {:016X}{:016X}", uid[1], uid[0]);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
} }
void FSP_SRV::MountSaveData(Kernel::HLERequestContext& ctx) { void FSP_SRV::MountSaveData(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_FS, "(STUBBED) called"); NGLOG_WARNING(Service_FS, "(STUBBED) called");
FileSys::Path unused; FileSys::Path unused;
auto filesystem = OpenFileSystem(Type::SaveData, unused).Unwrap(); auto filesystem = OpenFileSystem(Type::SaveData, unused).Unwrap();
@ -534,7 +553,7 @@ void FSP_SRV::MountSaveData(Kernel::HLERequestContext& ctx) {
} }
void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_FS, "(STUBBED) called"); NGLOG_WARNING(Service_FS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
@ -542,12 +561,12 @@ void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) {
} }
void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) { void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called"); NGLOG_DEBUG(Service_FS, "called");
TryLoadRomFS(); TryLoadRomFS();
if (!romfs) { if (!romfs) {
// TODO (bunnei): Find the right error code to use here // TODO (bunnei): Find the right error code to use here
LOG_CRITICAL(Service_FS, "no file system interface available!"); NGLOG_CRITICAL(Service_FS, "no file system interface available!");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultCode(-1)); rb.Push(ResultCode(-1));
return; return;
@ -556,7 +575,7 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) {
// Attempt to open a StorageBackend interface to the RomFS // Attempt to open a StorageBackend interface to the RomFS
auto storage = romfs->OpenFile({}, {}); auto storage = romfs->OpenFile({}, {});
if (storage.Failed()) { if (storage.Failed()) {
LOG_CRITICAL(Service_FS, "no storage interface available!"); NGLOG_CRITICAL(Service_FS, "no storage interface available!");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(storage.Code()); rb.Push(storage.Code());
return; return;
@ -568,7 +587,7 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) {
} }
void FSP_SRV::OpenRomStorage(Kernel::HLERequestContext& ctx) { void FSP_SRV::OpenRomStorage(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_FS, "(STUBBED) called, using OpenDataStorageByCurrentProcess"); NGLOG_WARNING(Service_FS, "(STUBBED) called, using OpenDataStorageByCurrentProcess");
OpenDataStorageByCurrentProcess(ctx); OpenDataStorageByCurrentProcess(ctx);
} }

View file

@ -13,7 +13,7 @@ namespace Service::Friend {
void Module::Interface::CreateFriendService(Kernel::HLERequestContext& ctx) { void Module::Interface::CreateFriendService(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_Friend, "(STUBBED) called"); NGLOG_WARNING(Service_Friend, "(STUBBED) called");
} }
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)

View file

@ -53,7 +53,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1}; IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(shared_mem); rb.PushCopyObjects(shared_mem);
LOG_DEBUG(Service_HID, "called"); NGLOG_DEBUG(Service_HID, "called");
} }
void LoadInputDevices() { void LoadInputDevices() {
@ -184,7 +184,7 @@ private:
void ActivateVibrationDevice(Kernel::HLERequestContext& ctx) { void ActivateVibrationDevice(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called"); NGLOG_WARNING(Service_HID, "(STUBBED) called");
} }
}; };
@ -286,144 +286,144 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IAppletResource>(applet_resource); rb.PushIpcInterface<IAppletResource>(applet_resource);
LOG_DEBUG(Service_HID, "called"); NGLOG_DEBUG(Service_HID, "called");
} }
void ActivateDebugPad(Kernel::HLERequestContext& ctx) { void ActivateDebugPad(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called"); NGLOG_WARNING(Service_HID, "(STUBBED) called");
} }
void ActivateTouchScreen(Kernel::HLERequestContext& ctx) { void ActivateTouchScreen(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called"); NGLOG_WARNING(Service_HID, "(STUBBED) called");
} }
void ActivateMouse(Kernel::HLERequestContext& ctx) { void ActivateMouse(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called"); NGLOG_WARNING(Service_HID, "(STUBBED) called");
} }
void ActivateKeyboard(Kernel::HLERequestContext& ctx) { void ActivateKeyboard(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called"); NGLOG_WARNING(Service_HID, "(STUBBED) called");
} }
void StartSixAxisSensor(Kernel::HLERequestContext& ctx) { void StartSixAxisSensor(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called"); NGLOG_WARNING(Service_HID, "(STUBBED) called");
} }
void SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { void SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called"); NGLOG_WARNING(Service_HID, "(STUBBED) called");
} }
void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called"); NGLOG_WARNING(Service_HID, "(STUBBED) called");
} }
void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0); rb.Push<u32>(0);
LOG_WARNING(Service_HID, "(STUBBED) called"); NGLOG_WARNING(Service_HID, "(STUBBED) called");
} }
void SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) { void SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called"); NGLOG_WARNING(Service_HID, "(STUBBED) called");
} }
void ActivateNpad(Kernel::HLERequestContext& ctx) { void ActivateNpad(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called"); NGLOG_WARNING(Service_HID, "(STUBBED) called");
} }
void AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) { void AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 1}; IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(event); rb.PushCopyObjects(event);
LOG_WARNING(Service_HID, "(STUBBED) called"); NGLOG_WARNING(Service_HID, "(STUBBED) called");
} }
void GetPlayerLedPattern(Kernel::HLERequestContext& ctx) { void GetPlayerLedPattern(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called"); NGLOG_WARNING(Service_HID, "(STUBBED) called");
} }
void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called"); NGLOG_WARNING(Service_HID, "(STUBBED) called");
} }
void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push(joy_hold_type); rb.Push(joy_hold_type);
LOG_WARNING(Service_HID, "(STUBBED) called"); NGLOG_WARNING(Service_HID, "(STUBBED) called");
} }
void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) { void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called"); NGLOG_WARNING(Service_HID, "(STUBBED) called");
} }
void SendVibrationValue(Kernel::HLERequestContext& ctx) { void SendVibrationValue(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called"); NGLOG_WARNING(Service_HID, "(STUBBED) called");
} }
void GetActualVibrationValue(Kernel::HLERequestContext& ctx) { void GetActualVibrationValue(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called"); NGLOG_WARNING(Service_HID, "(STUBBED) called");
} }
void SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { void SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called"); NGLOG_WARNING(Service_HID, "(STUBBED) called");
} }
void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) { void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called"); NGLOG_WARNING(Service_HID, "(STUBBED) called");
} }
void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push<u64>(0); rb.Push<u64>(0);
LOG_WARNING(Service_HID, "(STUBBED) called"); NGLOG_WARNING(Service_HID, "(STUBBED) called");
} }
void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) { void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IActiveVibrationDeviceList>(); rb.PushIpcInterface<IActiveVibrationDeviceList>();
LOG_DEBUG(Service_HID, "called"); NGLOG_DEBUG(Service_HID, "called");
} }
void SendVibrationValues(Kernel::HLERequestContext& ctx) { void SendVibrationValues(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called"); NGLOG_WARNING(Service_HID, "(STUBBED) called");
} }
}; };

View file

@ -141,19 +141,19 @@ private:
if (header.IsTailLog()) { if (header.IsTailLog()) {
switch (header.severity) { switch (header.severity) {
case MessageHeader::Severity::Trace: case MessageHeader::Severity::Trace:
LOG_TRACE(Debug_Emulated, "%s", log_stream.str().c_str()); NGLOG_TRACE(Debug_Emulated, "{}", log_stream.str());
break; break;
case MessageHeader::Severity::Info: case MessageHeader::Severity::Info:
LOG_INFO(Debug_Emulated, "%s", log_stream.str().c_str()); NGLOG_INFO(Debug_Emulated, "{}", log_stream.str());
break; break;
case MessageHeader::Severity::Warning: case MessageHeader::Severity::Warning:
LOG_WARNING(Debug_Emulated, "%s", log_stream.str().c_str()); NGLOG_WARNING(Debug_Emulated, "{}", log_stream.str());
break; break;
case MessageHeader::Severity::Error: case MessageHeader::Severity::Error:
LOG_ERROR(Debug_Emulated, "%s", log_stream.str().c_str()); NGLOG_ERROR(Debug_Emulated, "{}", log_stream.str());
break; break;
case MessageHeader::Severity::Critical: case MessageHeader::Severity::Critical:
LOG_CRITICAL(Debug_Emulated, "%s", log_stream.str().c_str()); NGLOG_CRITICAL(Debug_Emulated, "{}", log_stream.str());
break; break;
} }
} }
@ -178,7 +178,7 @@ void LM::Initialize(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<Logger>(); rb.PushIpcInterface<Logger>();
LOG_DEBUG(Service_LM, "called"); NGLOG_DEBUG(Service_LM, "called");
} }
LM::LM() : ServiceFramework("lm") { LM::LM() : ServiceFramework("lm") {

View file

@ -62,24 +62,24 @@ public:
private: private:
void GetRequestState(Kernel::HLERequestContext& ctx) { void GetRequestState(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called"); NGLOG_WARNING(Service_NIFM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0); rb.Push<u32>(0);
} }
void GetResult(Kernel::HLERequestContext& ctx) { void GetResult(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called"); NGLOG_WARNING(Service_NIFM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
} }
void GetSystemEventReadableHandles(Kernel::HLERequestContext& ctx) { void GetSystemEventReadableHandles(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called"); NGLOG_WARNING(Service_NIFM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 2}; IPC::ResponseBuilder rb{ctx, 2, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(event1, event2); rb.PushCopyObjects(event1, event2);
} }
void Cancel(Kernel::HLERequestContext& ctx) { void Cancel(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called"); NGLOG_WARNING(Service_NIFM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
} }
@ -105,7 +105,7 @@ public:
private: private:
void GetClientId(Kernel::HLERequestContext& ctx) { void GetClientId(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called"); NGLOG_WARNING(Service_NIFM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push<u64>(0); rb.Push<u64>(0);
@ -116,7 +116,7 @@ private:
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IScanRequest>(); rb.PushIpcInterface<IScanRequest>();
LOG_DEBUG(Service_NIFM, "called"); NGLOG_DEBUG(Service_NIFM, "called");
} }
void CreateRequest(Kernel::HLERequestContext& ctx) { void CreateRequest(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
@ -124,10 +124,10 @@ private:
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IRequest>(); rb.PushIpcInterface<IRequest>();
LOG_DEBUG(Service_NIFM, "called"); NGLOG_DEBUG(Service_NIFM, "called");
} }
void RemoveNetworkProfile(Kernel::HLERequestContext& ctx) { void RemoveNetworkProfile(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called"); NGLOG_WARNING(Service_NIFM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
} }
@ -137,7 +137,7 @@ private:
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<INetworkProfile>(); rb.PushIpcInterface<INetworkProfile>();
LOG_DEBUG(Service_NIFM, "called"); NGLOG_DEBUG(Service_NIFM, "called");
} }
}; };
@ -187,14 +187,14 @@ void Module::Interface::CreateGeneralServiceOld(Kernel::HLERequestContext& ctx)
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IGeneralService>(); rb.PushIpcInterface<IGeneralService>();
LOG_DEBUG(Service_NIFM, "called"); NGLOG_DEBUG(Service_NIFM, "called");
} }
void Module::Interface::CreateGeneralService(Kernel::HLERequestContext& ctx) { void Module::Interface::CreateGeneralService(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IGeneralService>(); rb.PushIpcInterface<IGeneralService>();
LOG_DEBUG(Service_NIFM, "called"); NGLOG_DEBUG(Service_NIFM, "called");
} }
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)

View file

@ -52,7 +52,7 @@ PL_U::PL_U() : ServiceFramework("pl:u") {
ASSERT(file.GetSize() == SHARED_FONT_MEM_SIZE); ASSERT(file.GetSize() == SHARED_FONT_MEM_SIZE);
file.ReadBytes(shared_font->data(), shared_font->size()); file.ReadBytes(shared_font->data(), shared_font->size());
} else { } else {
LOG_WARNING(Service_NS, "Unable to load shared font: %s", filepath.c_str()); NGLOG_WARNING(Service_NS, "Unable to load shared font: {}", filepath);
} }
} }
@ -60,7 +60,7 @@ void PL_U::RequestLoad(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const u32 shared_font_type{rp.Pop<u32>()}; const u32 shared_font_type{rp.Pop<u32>()};
LOG_DEBUG(Service_NS, "called, shared_font_type=%d", shared_font_type); NGLOG_DEBUG(Service_NS, "called, shared_font_type={}", shared_font_type);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
} }
@ -69,7 +69,7 @@ void PL_U::GetLoadState(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const u32 font_id{rp.Pop<u32>()}; const u32 font_id{rp.Pop<u32>()};
LOG_DEBUG(Service_NS, "called, font_id=%d", font_id); NGLOG_DEBUG(Service_NS, "called, font_id={}", font_id);
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push<u32>(static_cast<u32>(LoadState::Done)); rb.Push<u32>(static_cast<u32>(LoadState::Done));
@ -79,7 +79,7 @@ void PL_U::GetSize(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const u32 font_id{rp.Pop<u32>()}; const u32 font_id{rp.Pop<u32>()};
LOG_DEBUG(Service_NS, "called, font_id=%d", font_id); NGLOG_DEBUG(Service_NS, "called, font_id={}", font_id);
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push<u32>(SHARED_FONT_REGIONS[font_id].size); rb.Push<u32>(SHARED_FONT_REGIONS[font_id].size);
@ -89,7 +89,7 @@ void PL_U::GetSharedMemoryAddressOffset(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const u32 font_id{rp.Pop<u32>()}; const u32 font_id{rp.Pop<u32>()};
LOG_DEBUG(Service_NS, "called, font_id=%d", font_id); NGLOG_DEBUG(Service_NS, "called, font_id={}", font_id);
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push<u32>(SHARED_FONT_REGIONS[font_id].offset); rb.Push<u32>(SHARED_FONT_REGIONS[font_id].offset);
@ -110,7 +110,7 @@ void PL_U::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) {
Kernel::MemoryPermission::Read, SHARED_FONT_MEM_VADDR, Kernel::MemoryRegion::BASE, Kernel::MemoryPermission::Read, SHARED_FONT_MEM_VADDR, Kernel::MemoryRegion::BASE,
"PL_U:shared_font_mem"); "PL_U:shared_font_mem");
LOG_DEBUG(Service_NS, "called"); NGLOG_DEBUG(Service_NS, "called");
IPC::ResponseBuilder rb{ctx, 2, 1}; IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(shared_font_mem); rb.PushCopyObjects(shared_font_mem);

View file

@ -13,16 +13,16 @@
namespace Service::Nvidia::Devices { namespace Service::Nvidia::Devices {
u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
UNIMPLEMENTED(); UNIMPLEMENTED_MSG("Unimplemented ioctl");
return 0; return 0;
} }
void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height,
u32 stride, NVFlinger::BufferQueue::BufferTransformFlags transform) { u32 stride, NVFlinger::BufferQueue::BufferTransformFlags transform) {
VAddr addr = nvmap_dev->GetObjectAddress(buffer_handle); VAddr addr = nvmap_dev->GetObjectAddress(buffer_handle);
LOG_WARNING(Service, NGLOG_WARNING(Service,
"Drawing from address %lx offset %08X Width %u Height %u Stride %u Format %u", addr, "Drawing from address {:X} offset {:08X} Width {} Height {} Stride {} Format {}",
offset, width, height, stride, format); addr, offset, width, height, stride, format);
using PixelFormat = Tegra::FramebufferConfig::PixelFormat; using PixelFormat = Tegra::FramebufferConfig::PixelFormat;
const Tegra::FramebufferConfig framebuffer{ const Tegra::FramebufferConfig framebuffer{

View file

@ -12,7 +12,7 @@
namespace Service::Nvidia::Devices { namespace Service::Nvidia::Devices {
u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called, command=0x%08x, input_size=0x%zx, output_size=0x%zx", NGLOG_DEBUG(Service_NVDRV, "called, command={:#010X}, input_size={:#X}, output_size={:#X}",
command.raw, input.size(), output.size()); command.raw, input.size(), output.size());
switch (static_cast<IoctlCommand>(command.raw)) { switch (static_cast<IoctlCommand>(command.raw)) {
@ -27,13 +27,18 @@ u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vecto
case IoctlCommand::IocGetVaRegionsCommand: case IoctlCommand::IocGetVaRegionsCommand:
return GetVARegions(input, output); return GetVARegions(input, output);
} }
if (static_cast<IoctlCommand>(command.cmd.Value()) == IoctlCommand::IocRemapCommand)
return Remap(input, output);
UNIMPLEMENTED_MSG("Unimplemented ioctl command");
return 0; return 0;
} }
u32 nvhost_as_gpu::InitalizeEx(const std::vector<u8>& input, std::vector<u8>& output) { u32 nvhost_as_gpu::InitalizeEx(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlInitalizeEx params{}; IoctlInitalizeEx params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
LOG_WARNING(Service_NVDRV, "(STUBBED) called, big_page_size=0x%x", params.big_page_size); NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, big_page_size={:#X}", params.big_page_size);
std::memcpy(output.data(), &params, output.size()); std::memcpy(output.data(), &params, output.size());
return 0; return 0;
} }
@ -41,7 +46,7 @@ u32 nvhost_as_gpu::InitalizeEx(const std::vector<u8>& input, std::vector<u8>& ou
u32 nvhost_as_gpu::AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output) { u32 nvhost_as_gpu::AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlAllocSpace params{}; IoctlAllocSpace params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "called, pages=%x, page_size=%x, flags=%x", params.pages, NGLOG_DEBUG(Service_NVDRV, "called, pages={:X}, page_size={:X}, flags={:X}", params.pages,
params.page_size, params.flags); params.page_size, params.flags);
auto& gpu = Core::System::GetInstance().GPU(); auto& gpu = Core::System::GetInstance().GPU();
@ -56,13 +61,43 @@ u32 nvhost_as_gpu::AllocateSpace(const std::vector<u8>& input, std::vector<u8>&
return 0; return 0;
} }
u32 nvhost_as_gpu::Remap(const std::vector<u8>& input, std::vector<u8>& output) {
size_t num_entries = input.size() / sizeof(IoctlRemapEntry);
NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, num_entries=0x{:X}", num_entries);
std::vector<IoctlRemapEntry> entries(num_entries);
std::memcpy(entries.data(), input.data(), input.size());
auto& gpu = Core::System::GetInstance().GPU();
for (const auto& entry : entries) {
NGLOG_WARNING(Service_NVDRV, "remap entry, offset=0x{:X} handle=0x{:X} pages=0x{:X}",
entry.offset, entry.nvmap_handle, entry.pages);
Tegra::GPUVAddr offset = static_cast<Tegra::GPUVAddr>(entry.offset) << 0x10;
auto object = nvmap_dev->GetObject(entry.nvmap_handle);
ASSERT(object);
ASSERT(object->status == nvmap::Object::Status::Allocated);
u64 size = static_cast<u64>(entry.pages) << 0x10;
ASSERT(size <= object->size);
Tegra::GPUVAddr returned = gpu.memory_manager->MapBufferEx(object->addr, offset, size);
ASSERT(returned == offset);
}
std::memcpy(output.data(), entries.data(), output.size());
return 0;
}
u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) { u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlMapBufferEx params{}; IoctlMapBufferEx params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, NGLOG_DEBUG(Service_NVDRV,
"called, flags=%x, nvmap_handle=%x, buffer_offset=%" PRIu64 ", mapping_size=%" PRIu64 "called, flags={:X}, nvmap_handle={:X}, buffer_offset={}, mapping_size={}"
", offset=%" PRIu64, ", offset={}",
params.flags, params.nvmap_handle, params.buffer_offset, params.mapping_size, params.flags, params.nvmap_handle, params.buffer_offset, params.mapping_size,
params.offset); params.offset);
@ -73,6 +108,16 @@ u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& ou
auto object = nvmap_dev->GetObject(params.nvmap_handle); auto object = nvmap_dev->GetObject(params.nvmap_handle);
ASSERT(object); ASSERT(object);
// We can only map objects that have already been assigned a CPU address.
ASSERT(object->status == nvmap::Object::Status::Allocated);
ASSERT(params.buffer_offset == 0);
// The real nvservices doesn't make a distinction between handles and ids, and
// object can only have one handle and it will be the same as its id. Assert that this is the
// case to prevent unexpected behavior.
ASSERT(object->id == params.nvmap_handle);
auto& gpu = Core::System::GetInstance().GPU(); auto& gpu = Core::System::GetInstance().GPU();
if (params.flags & 1) { if (params.flags & 1) {
@ -88,7 +133,7 @@ u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& ou
u32 nvhost_as_gpu::BindChannel(const std::vector<u8>& input, std::vector<u8>& output) { u32 nvhost_as_gpu::BindChannel(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlBindChannel params{}; IoctlBindChannel params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "called, fd=%x", params.fd); NGLOG_DEBUG(Service_NVDRV, "called, fd={:X}", params.fd);
channel = params.fd; channel = params.fd;
std::memcpy(output.data(), &params, output.size()); std::memcpy(output.data(), &params, output.size());
return 0; return 0;
@ -97,8 +142,8 @@ u32 nvhost_as_gpu::BindChannel(const std::vector<u8>& input, std::vector<u8>& ou
u32 nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u8>& output) { u32 nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlGetVaRegions params{}; IoctlGetVaRegions params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
LOG_WARNING(Service_NVDRV, "(STUBBED) called, buf_addr=%" PRIu64 ", buf_size=%x", NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, buf_addr={:X}, buf_size={:X}", params.buf_addr,
params.buf_addr, params.buf_size); params.buf_size);
params.buf_size = 0x30; params.buf_size = 0x30;
params.regions[0].offset = 0x04000000; params.regions[0].offset = 0x04000000;

View file

@ -26,6 +26,7 @@ private:
enum class IoctlCommand : u32_le { enum class IoctlCommand : u32_le {
IocInitalizeExCommand = 0x40284109, IocInitalizeExCommand = 0x40284109,
IocAllocateSpaceCommand = 0xC0184102, IocAllocateSpaceCommand = 0xC0184102,
IocRemapCommand = 0x00000014,
IocMapBufferExCommand = 0xC0284106, IocMapBufferExCommand = 0xC0284106,
IocBindChannelCommand = 0x40044101, IocBindChannelCommand = 0x40044101,
IocGetVaRegionsCommand = 0xC0404108, IocGetVaRegionsCommand = 0xC0404108,
@ -54,6 +55,16 @@ private:
}; };
static_assert(sizeof(IoctlAllocSpace) == 24, "IoctlInitalizeEx is incorrect size"); static_assert(sizeof(IoctlAllocSpace) == 24, "IoctlInitalizeEx is incorrect size");
struct IoctlRemapEntry {
u16_le flags;
u16_le kind;
u32_le nvmap_handle;
INSERT_PADDING_WORDS(1);
u32_le offset;
u32_le pages;
};
static_assert(sizeof(IoctlRemapEntry) == 20, "IoctlRemapEntry is incorrect size");
struct IoctlMapBufferEx { struct IoctlMapBufferEx {
u32_le flags; // bit0: fixed_offset, bit2: cacheable u32_le flags; // bit0: fixed_offset, bit2: cacheable
u32_le kind; // -1 is default u32_le kind; // -1 is default
@ -91,6 +102,7 @@ private:
u32 InitalizeEx(const std::vector<u8>& input, std::vector<u8>& output); u32 InitalizeEx(const std::vector<u8>& input, std::vector<u8>& output);
u32 AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output); u32 AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output);
u32 Remap(const std::vector<u8>& input, std::vector<u8>& output);
u32 MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output); u32 MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output);
u32 BindChannel(const std::vector<u8>& input, std::vector<u8>& output); u32 BindChannel(const std::vector<u8>& input, std::vector<u8>& output);
u32 GetVARegions(const std::vector<u8>& input, std::vector<u8>& output); u32 GetVARegions(const std::vector<u8>& input, std::vector<u8>& output);

View file

@ -9,7 +9,7 @@
namespace Service::Nvidia::Devices { namespace Service::Nvidia::Devices {
u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called, command=0x%08x, input_size=0x%zx, output_size=0x%zx", NGLOG_DEBUG(Service_NVDRV, "called, command={:#010X}, input_size={:#X}, output_size={:#X}",
command.raw, input.size(), output.size()); command.raw, input.size(), output.size());
switch (static_cast<IoctlCommand>(command.raw)) { switch (static_cast<IoctlCommand>(command.raw)) {
@ -18,14 +18,14 @@ u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<
case IoctlCommand::IocCtrlEventWaitCommand: case IoctlCommand::IocCtrlEventWaitCommand:
return IocCtrlEventWait(input, output); return IocCtrlEventWait(input, output);
} }
UNIMPLEMENTED(); UNIMPLEMENTED_MSG("Unimplemented ioctl");
return 0; return 0;
} }
u32 nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output) { u32 nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output) {
IocGetConfigParams params{}; IocGetConfigParams params{};
std::memcpy(&params, input.data(), sizeof(params)); std::memcpy(&params, input.data(), sizeof(params));
LOG_DEBUG(Service_NVDRV, "called, setting=%s!%s", params.domain_str.data(), NGLOG_DEBUG(Service_NVDRV, "called, setting={}!{}", params.domain_str.data(),
params.param_str.data()); params.param_str.data());
if (!strcmp(params.domain_str.data(), "nv")) { if (!strcmp(params.domain_str.data(), "nv")) {
@ -48,7 +48,7 @@ u32 nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>&
u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output) { u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output) {
IocCtrlEventWaitParams params{}; IocCtrlEventWaitParams params{};
std::memcpy(&params, input.data(), sizeof(params)); std::memcpy(&params, input.data(), sizeof(params));
LOG_WARNING(Service_NVDRV, "(STUBBED) called, syncpt_id=%u threshold=%u timeout=%d", NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, syncpt_id={} threshold={} timeout={}",
params.syncpt_id, params.threshold, params.timeout); params.syncpt_id, params.threshold, params.timeout);
// TODO(Subv): Implement actual syncpt waiting. // TODO(Subv): Implement actual syncpt waiting.

View file

@ -10,7 +10,7 @@
namespace Service::Nvidia::Devices { namespace Service::Nvidia::Devices {
u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called, command=0x%08x, input_size=0x%zx, output_size=0x%zx", NGLOG_DEBUG(Service_NVDRV, "called, command={:#010X}, input_size={:#X}, output_size={:#X}",
command.raw, input.size(), output.size()); command.raw, input.size(), output.size());
switch (static_cast<IoctlCommand>(command.raw)) { switch (static_cast<IoctlCommand>(command.raw)) {
@ -25,12 +25,12 @@ u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vec
case IoctlCommand::IocZcullGetInfo: case IoctlCommand::IocZcullGetInfo:
return ZCullGetInfo(input, output); return ZCullGetInfo(input, output);
} }
UNIMPLEMENTED(); UNIMPLEMENTED_MSG("Unimplemented ioctl");
return 0; return 0;
} }
u32 nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output) { u32 nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called"); NGLOG_DEBUG(Service_NVDRV, "called");
IoctlCharacteristics params{}; IoctlCharacteristics params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
params.gc.arch = 0x120; params.gc.arch = 0x120;
@ -77,7 +77,7 @@ u32 nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::vecto
u32 nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output) { u32 nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlGpuGetTpcMasksArgs params{}; IoctlGpuGetTpcMasksArgs params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
LOG_WARNING(Service_NVDRV, "(STUBBED) called, mask=0x%x, mask_buf_addr=0x%" PRIx64, NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, mask={:#X}, mask_buf_addr={:#X}",
params.mask_buf_size, params.mask_buf_addr); params.mask_buf_size, params.mask_buf_addr);
params.unk = 0xcafe; // TODO(ogniK): Needs to be non 0, what does this actually do? params.unk = 0xcafe; // TODO(ogniK): Needs to be non 0, what does this actually do?
std::memcpy(output.data(), &params, sizeof(params)); std::memcpy(output.data(), &params, sizeof(params));
@ -85,7 +85,7 @@ u32 nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<u8>&
} }
u32 nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output) { u32 nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called"); NGLOG_DEBUG(Service_NVDRV, "called");
IoctlActiveSlotMask params{}; IoctlActiveSlotMask params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
params.slot = 0x07; params.slot = 0x07;
@ -95,7 +95,7 @@ u32 nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector
} }
u32 nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output) { u32 nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called"); NGLOG_DEBUG(Service_NVDRV, "called");
IoctlZcullGetCtxSize params{}; IoctlZcullGetCtxSize params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
params.size = 0x1; params.size = 0x1;
@ -104,7 +104,7 @@ u32 nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u
} }
u32 nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output) { u32 nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called"); NGLOG_DEBUG(Service_NVDRV, "called");
IoctlNvgpuGpuZcullGetInfoArgs params{}; IoctlNvgpuGpuZcullGetInfoArgs params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
params.width_align_pixels = 0x20; params.width_align_pixels = 0x20;

View file

@ -12,7 +12,7 @@
namespace Service::Nvidia::Devices { namespace Service::Nvidia::Devices {
u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called, command=0x%08x, input_size=0x%zx, output_size=0x%zx", NGLOG_DEBUG(Service_NVDRV, "called, command={:#010X}, input_size={:#X}, output_size={:#X}",
command.raw, input.size(), output.size()); command.raw, input.size(), output.size());
switch (static_cast<IoctlCommand>(command.raw)) { switch (static_cast<IoctlCommand>(command.raw)) {
@ -40,21 +40,21 @@ u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u
} }
} }
UNIMPLEMENTED(); UNIMPLEMENTED_MSG("Unimplemented ioctl");
return 0; return 0;
}; };
u32 nvhost_gpu::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) { u32 nvhost_gpu::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlSetNvmapFD params{}; IoctlSetNvmapFD params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "called, fd=%x", params.nvmap_fd); NGLOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
nvmap_fd = params.nvmap_fd; nvmap_fd = params.nvmap_fd;
std::memcpy(output.data(), &params, output.size()); std::memcpy(output.data(), &params, output.size());
return 0; return 0;
} }
u32 nvhost_gpu::SetClientData(const std::vector<u8>& input, std::vector<u8>& output) { u32 nvhost_gpu::SetClientData(const std::vector<u8>& input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called"); NGLOG_DEBUG(Service_NVDRV, "called");
IoctlClientData params{}; IoctlClientData params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
user_data = params.data; user_data = params.data;
@ -63,7 +63,7 @@ u32 nvhost_gpu::SetClientData(const std::vector<u8>& input, std::vector<u8>& out
} }
u32 nvhost_gpu::GetClientData(const std::vector<u8>& input, std::vector<u8>& output) { u32 nvhost_gpu::GetClientData(const std::vector<u8>& input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called"); NGLOG_DEBUG(Service_NVDRV, "called");
IoctlClientData params{}; IoctlClientData params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
params.data = user_data; params.data = user_data;
@ -73,7 +73,7 @@ u32 nvhost_gpu::GetClientData(const std::vector<u8>& input, std::vector<u8>& out
u32 nvhost_gpu::ZCullBind(const std::vector<u8>& input, std::vector<u8>& output) { u32 nvhost_gpu::ZCullBind(const std::vector<u8>& input, std::vector<u8>& output) {
std::memcpy(&zcull_params, input.data(), input.size()); std::memcpy(&zcull_params, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "called, gpu_va=%" PRIx64 ", mode=%x", zcull_params.gpu_va, NGLOG_DEBUG(Service_NVDRV, "called, gpu_va={:X}, mode={:X}", zcull_params.gpu_va,
zcull_params.mode); zcull_params.mode);
std::memcpy(output.data(), &zcull_params, output.size()); std::memcpy(output.data(), &zcull_params, output.size());
return 0; return 0;
@ -82,7 +82,7 @@ u32 nvhost_gpu::ZCullBind(const std::vector<u8>& input, std::vector<u8>& output)
u32 nvhost_gpu::SetErrorNotifier(const std::vector<u8>& input, std::vector<u8>& output) { u32 nvhost_gpu::SetErrorNotifier(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlSetErrorNotifier params{}; IoctlSetErrorNotifier params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
LOG_WARNING(Service_NVDRV, "(STUBBED) called, offset=%" PRIx64 ", size=%" PRIx64 ", mem=%x", NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, offset={:X}, size={:X}, mem={:X}",
params.offset, params.size, params.mem); params.offset, params.size, params.mem);
std::memcpy(output.data(), &params, output.size()); std::memcpy(output.data(), &params, output.size());
return 0; return 0;
@ -90,7 +90,7 @@ u32 nvhost_gpu::SetErrorNotifier(const std::vector<u8>& input, std::vector<u8>&
u32 nvhost_gpu::SetChannelPriority(const std::vector<u8>& input, std::vector<u8>& output) { u32 nvhost_gpu::SetChannelPriority(const std::vector<u8>& input, std::vector<u8>& output) {
std::memcpy(&channel_priority, input.data(), input.size()); std::memcpy(&channel_priority, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority=%x", channel_priority); NGLOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority={:X}", channel_priority);
std::memcpy(output.data(), &channel_priority, output.size()); std::memcpy(output.data(), &channel_priority, output.size());
return 0; return 0;
} }
@ -98,8 +98,9 @@ u32 nvhost_gpu::SetChannelPriority(const std::vector<u8>& input, std::vector<u8>
u32 nvhost_gpu::AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output) { u32 nvhost_gpu::AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlAllocGpfifoEx2 params{}; IoctlAllocGpfifoEx2 params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
LOG_WARNING(Service_NVDRV, NGLOG_WARNING(Service_NVDRV,
"(STUBBED) called, num_entries=%x, flags=%x, unk0=%x, unk1=%x, unk2=%x, unk3=%x", "(STUBBED) called, num_entries={:X}, flags={:X}, unk0={:X}, "
"unk1={:X}, unk2={:X}, unk3={:X}",
params.num_entries, params.flags, params.unk0, params.unk1, params.unk2, params.num_entries, params.flags, params.unk0, params.unk1, params.unk2,
params.unk3); params.unk3);
params.fence_out.id = 0; params.fence_out.id = 0;
@ -111,7 +112,7 @@ u32 nvhost_gpu::AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& ou
u32 nvhost_gpu::AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output) { u32 nvhost_gpu::AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlAllocObjCtx params{}; IoctlAllocObjCtx params{};
std::memcpy(&params, input.data(), input.size()); std::memcpy(&params, input.data(), input.size());
LOG_WARNING(Service_NVDRV, "(STUBBED) called, class_num=%x, flags=%x", params.class_num, NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, class_num={:X}, flags={:X}", params.class_num,
params.flags); params.flags);
params.obj_id = 0x0; params.obj_id = 0x0;
std::memcpy(output.data(), &params, output.size()); std::memcpy(output.data(), &params, output.size());
@ -123,7 +124,7 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp
UNIMPLEMENTED(); UNIMPLEMENTED();
IoctlSubmitGpfifo params{}; IoctlSubmitGpfifo params{};
std::memcpy(&params, input.data(), sizeof(IoctlSubmitGpfifo)); std::memcpy(&params, input.data(), sizeof(IoctlSubmitGpfifo));
LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo=%" PRIx64 ", num_entries=%x, flags=%x", NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}",
params.gpfifo, params.num_entries, params.flags); params.gpfifo, params.num_entries, params.flags);
auto entries = std::vector<IoctlGpfifoEntry>(); auto entries = std::vector<IoctlGpfifoEntry>();

View file

@ -32,7 +32,7 @@ u32 nvmap::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& o
return IocParam(input, output); return IocParam(input, output);
} }
UNIMPLEMENTED(); UNIMPLEMENTED_MSG("Unimplemented ioctl");
return 0; return 0;
} }
@ -49,7 +49,7 @@ u32 nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) {
u32 handle = next_handle++; u32 handle = next_handle++;
handles[handle] = std::move(object); handles[handle] = std::move(object);
LOG_DEBUG(Service_NVDRV, "size=0x%08X", params.size); NGLOG_DEBUG(Service_NVDRV, "size={:#010X}", params.size);
params.handle = handle; params.handle = handle;
@ -70,7 +70,7 @@ u32 nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output) {
object->addr = params.addr; object->addr = params.addr;
object->status = Object::Status::Allocated; object->status = Object::Status::Allocated;
LOG_DEBUG(Service_NVDRV, "called, addr=0x%" PRIx64, params.addr); NGLOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.addr);
std::memcpy(output.data(), &params, sizeof(params)); std::memcpy(output.data(), &params, sizeof(params));
return 0; return 0;
@ -80,7 +80,7 @@ u32 nvmap::IocGetId(const std::vector<u8>& input, std::vector<u8>& output) {
IocGetIdParams params; IocGetIdParams params;
std::memcpy(&params, input.data(), sizeof(params)); std::memcpy(&params, input.data(), sizeof(params));
LOG_WARNING(Service_NVDRV, "called"); NGLOG_WARNING(Service_NVDRV, "called");
auto object = GetObject(params.handle); auto object = GetObject(params.handle);
ASSERT(object); ASSERT(object);
@ -95,7 +95,7 @@ u32 nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) {
IocFromIdParams params; IocFromIdParams params;
std::memcpy(&params, input.data(), sizeof(params)); std::memcpy(&params, input.data(), sizeof(params));
LOG_WARNING(Service_NVDRV, "(STUBBED) called"); NGLOG_WARNING(Service_NVDRV, "(STUBBED) called");
auto itr = std::find_if(handles.begin(), handles.end(), auto itr = std::find_if(handles.begin(), handles.end(),
[&](const auto& entry) { return entry.second->id == params.id; }); [&](const auto& entry) { return entry.second->id == params.id; });
@ -114,7 +114,7 @@ u32 nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) {
IocParamParams params; IocParamParams params;
std::memcpy(&params, input.data(), sizeof(params)); std::memcpy(&params, input.data(), sizeof(params));
LOG_WARNING(Service_NVDRV, "(STUBBED) called type=%u", params.type); NGLOG_WARNING(Service_NVDRV, "(STUBBED) called type={}", params.type);
auto object = GetObject(params.handle); auto object = GetObject(params.handle);
ASSERT(object); ASSERT(object);

View file

@ -12,7 +12,7 @@
namespace Service::Nvidia { namespace Service::Nvidia {
void NVDRV::Open(Kernel::HLERequestContext& ctx) { void NVDRV::Open(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NVDRV, "called"); NGLOG_DEBUG(Service_NVDRV, "called");
const auto& buffer = ctx.ReadBuffer(); const auto& buffer = ctx.ReadBuffer();
std::string device_name(buffer.begin(), buffer.end()); std::string device_name(buffer.begin(), buffer.end());
@ -25,7 +25,7 @@ void NVDRV::Open(Kernel::HLERequestContext& ctx) {
} }
void NVDRV::Ioctl(Kernel::HLERequestContext& ctx) { void NVDRV::Ioctl(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NVDRV, "called"); NGLOG_DEBUG(Service_NVDRV, "called");
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
u32 fd = rp.Pop<u32>(); u32 fd = rp.Pop<u32>();
@ -41,7 +41,7 @@ void NVDRV::Ioctl(Kernel::HLERequestContext& ctx) {
} }
void NVDRV::Close(Kernel::HLERequestContext& ctx) { void NVDRV::Close(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NVDRV, "called"); NGLOG_DEBUG(Service_NVDRV, "called");
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
u32 fd = rp.Pop<u32>(); u32 fd = rp.Pop<u32>();
@ -53,7 +53,7 @@ void NVDRV::Close(Kernel::HLERequestContext& ctx) {
} }
void NVDRV::Initialize(Kernel::HLERequestContext& ctx) { void NVDRV::Initialize(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NVDRV, "(STUBBED) called"); NGLOG_WARNING(Service_NVDRV, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0); rb.Push<u32>(0);
@ -63,7 +63,7 @@ void NVDRV::QueryEvent(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
u32 fd = rp.Pop<u32>(); u32 fd = rp.Pop<u32>();
u32 event_id = rp.Pop<u32>(); u32 event_id = rp.Pop<u32>();
LOG_WARNING(Service_NVDRV, "(STUBBED) called, fd=%x, event_id=%x", fd, event_id); NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, fd={:X}, event_id={:X}", fd, event_id);
IPC::ResponseBuilder rb{ctx, 3, 1}; IPC::ResponseBuilder rb{ctx, 3, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
@ -75,14 +75,14 @@ void NVDRV::SetClientPID(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
pid = rp.Pop<u64>(); pid = rp.Pop<u64>();
LOG_WARNING(Service_NVDRV, "(STUBBED) called, pid=0x%" PRIx64, pid); NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, pid={:#X}", pid);
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0); rb.Push<u32>(0);
} }
void NVDRV::FinishInitialize(Kernel::HLERequestContext& ctx) { void NVDRV::FinishInitialize(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NVDRV, "(STUBBED) called"); NGLOG_WARNING(Service_NVDRV, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
} }

View file

@ -9,7 +9,8 @@
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/hle/service/nvflinger/buffer_queue.h" #include "core/hle/service/nvflinger/buffer_queue.h"
namespace Service::NVFlinger { namespace Service {
namespace NVFlinger {
BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) { BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) {
native_handle = Kernel::Event::Create(Kernel::ResetType::OneShot, "BufferQueue NativeHandle"); native_handle = Kernel::Event::Create(Kernel::ResetType::OneShot, "BufferQueue NativeHandle");
@ -22,7 +23,7 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, IGBPBuffer& igbp_buffer) {
buffer.igbp_buffer = igbp_buffer; buffer.igbp_buffer = igbp_buffer;
buffer.status = Buffer::Status::Free; buffer.status = Buffer::Status::Free;
LOG_WARNING(Service, "Adding graphics buffer %u", slot); NGLOG_WARNING(Service, "Adding graphics buffer {}", slot);
queue.emplace_back(buffer); queue.emplace_back(buffer);
@ -93,7 +94,7 @@ void BufferQueue::ReleaseBuffer(u32 slot) {
} }
u32 BufferQueue::Query(QueryType type) { u32 BufferQueue::Query(QueryType type) {
LOG_WARNING(Service, "(STUBBED) called type=%u", static_cast<u32>(type)); NGLOG_WARNING(Service, "(STUBBED) called type={}", static_cast<u32>(type));
switch (type) { switch (type) {
case QueryType::NativeWindowFormat: case QueryType::NativeWindowFormat:
// TODO(Subv): Use an enum for this // TODO(Subv): Use an enum for this
@ -110,4 +111,5 @@ void BufferQueue::SetBufferWaitEvent(Kernel::SharedPtr<Kernel::Event>&& wait_eve
buffer_wait_event = std::move(wait_event); buffer_wait_event = std::move(wait_event);
} }
} // namespace Service::NVFlinger } // namespace NVFlinger
} // namespace Service

View file

@ -13,7 +13,8 @@ namespace CoreTiming {
struct EventType; struct EventType;
} }
namespace Service::NVFlinger { namespace Service {
namespace NVFlinger {
struct IGBPBuffer { struct IGBPBuffer {
u32_le magic; u32_le magic;
@ -97,4 +98,5 @@ private:
Kernel::SharedPtr<Kernel::Event> buffer_wait_event; Kernel::SharedPtr<Kernel::Event> buffer_wait_event;
}; };
} // namespace Service::NVFlinger } // namespace NVFlinger
} // namespace Service

View file

@ -48,7 +48,7 @@ NVFlinger::~NVFlinger() {
} }
u64 NVFlinger::OpenDisplay(const std::string& name) { u64 NVFlinger::OpenDisplay(const std::string& name) {
LOG_WARNING(Service, "Opening display %s", name.c_str()); NGLOG_WARNING(Service, "Opening display {}", name);
// TODO(Subv): Currently we only support the Default display. // TODO(Subv): Currently we only support the Default display.
ASSERT(name == "Default"); ASSERT(name == "Default");

View file

@ -4,7 +4,8 @@
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/hle/ipc_helpers.h" #include "core/hle/ipc_helpers.h"
#include "core/hle/service/pctl/pctl_a.h" #include "core/hle/service/pctl/module.h"
#include "core/hle/service/pctl/pctl.h"
namespace Service::PCTL { namespace Service::PCTL {
@ -12,7 +13,7 @@ class IParentalControlService final : public ServiceFramework<IParentalControlSe
public: public:
IParentalControlService() : ServiceFramework("IParentalControlService") { IParentalControlService() : ServiceFramework("IParentalControlService") {
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{1, nullptr, "Initialize"}, {1, &IParentalControlService::Initialize, "Initialize"},
{1001, nullptr, "CheckFreeCommunicationPermission"}, {1001, nullptr, "CheckFreeCommunicationPermission"},
{1002, nullptr, "ConfirmLaunchApplicationPermission"}, {1002, nullptr, "ConfirmLaunchApplicationPermission"},
{1003, nullptr, "ConfirmResumeApplicationPermission"}, {1003, nullptr, "ConfirmResumeApplicationPermission"},
@ -108,20 +109,38 @@ public:
}; };
RegisterHandlers(functions); RegisterHandlers(functions);
} }
private:
void Initialize(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_PCTL, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 0, 0};
rb.Push(RESULT_SUCCESS);
}
}; };
void PCTL_A::CreateService(Kernel::HLERequestContext& ctx) {
void Module::Interface::CreateService(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IParentalControlService>(); rb.PushIpcInterface<IParentalControlService>();
LOG_DEBUG(Service_PCTL, "called"); NGLOG_DEBUG(Service_PCTL, "called");
} }
PCTL_A::PCTL_A() : ServiceFramework("pctl:a") { void Module::Interface::CreateServiceWithoutInitialize(Kernel::HLERequestContext& ctx) {
static const FunctionInfo functions[] = { IPC::ResponseBuilder rb{ctx, 2, 0, 1};
{0, &PCTL_A::CreateService, "CreateService"}, rb.Push(RESULT_SUCCESS);
{1, nullptr, "CreateServiceWithoutInitialize"}, rb.PushIpcInterface<IParentalControlService>();
}; NGLOG_DEBUG(Service_PCTL, "called");
RegisterHandlers(functions); }
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
: ServiceFramework(name), module(std::move(module)) {}
void InstallInterfaces(SM::ServiceManager& service_manager) {
auto module = std::make_shared<Module>();
std::make_shared<PCTL>(module, "pctl")->InstallAsService(service_manager);
std::make_shared<PCTL>(module, "pctl:a")->InstallAsService(service_manager);
std::make_shared<PCTL>(module, "pctl:r")->InstallAsService(service_manager);
std::make_shared<PCTL>(module, "pctl:s")->InstallAsService(service_manager);
} }
} // namespace Service::PCTL } // namespace Service::PCTL

View file

@ -0,0 +1,28 @@
// 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::PCTL {
class Module final {
public:
class Interface : public ServiceFramework<Interface> {
public:
Interface(std::shared_ptr<Module> module, const char* name);
void CreateService(Kernel::HLERequestContext& ctx);
void CreateServiceWithoutInitialize(Kernel::HLERequestContext& ctx);
protected:
std::shared_ptr<Module> module;
};
};
/// Registers all PCTL services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace Service::PCTL

View file

@ -3,12 +3,15 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include "core/hle/service/pctl/pctl.h" #include "core/hle/service/pctl/pctl.h"
#include "core/hle/service/pctl/pctl_a.h"
namespace Service::PCTL { namespace Service::PCTL {
void InstallInterfaces(SM::ServiceManager& service_manager) { PCTL::PCTL(std::shared_ptr<Module> module, const char* name)
std::make_shared<PCTL_A>()->InstallAsService(service_manager); : Module::Interface(std::move(module), name) {
static const FunctionInfo functions[] = {
{0, &PCTL::CreateService, "CreateService"},
{1, &PCTL::CreateServiceWithoutInitialize, "CreateServiceWithoutInitialize"},
};
RegisterHandlers(functions);
} }
} // namespace Service::PCTL } // namespace Service::PCTL

View file

@ -4,11 +4,13 @@
#pragma once #pragma once
#include "core/hle/service/service.h" #include "core/hle/service/pctl/module.h"
namespace Service::PCTL { namespace Service::PCTL {
/// Registers all PCTL services with the specified service manager. class PCTL final : public Module::Interface {
void InstallInterfaces(SM::ServiceManager& service_manager); public:
explicit PCTL(std::shared_ptr<Module> module, const char* name);
};
} // namespace Service::PCTL } // namespace Service::PCTL

View file

@ -1,20 +0,0 @@
// 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::PCTL {
class PCTL_A final : public ServiceFramework<PCTL_A> {
public:
PCTL_A();
~PCTL_A() = default;
private:
void CreateService(Kernel::HLERequestContext& ctx);
};
} // namespace Service::PCTL

View file

@ -121,7 +121,7 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(Kernel::HLERequestContext
} }
buf.push_back('}'); buf.push_back('}');
LOG_ERROR(Service, "unknown / unimplemented %s", fmt::to_string(buf).c_str()); NGLOG_ERROR(Service, "unknown / unimplemented {}", fmt::to_string(buf));
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
@ -132,8 +132,8 @@ void ServiceFrameworkBase::InvokeRequest(Kernel::HLERequestContext& ctx) {
return ReportUnimplementedFunction(ctx, info); return ReportUnimplementedFunction(ctx, info);
} }
LOG_TRACE( NGLOG_TRACE(
Service, "%s", Service, "{}",
MakeFunctionString(info->name, GetServiceName().c_str(), ctx.CommandBuffer()).c_str()); MakeFunctionString(info->name, GetServiceName().c_str(), ctx.CommandBuffer()).c_str());
handler_invoker(this, info->handler_callback, ctx); handler_invoker(this, info->handler_callback, ctx);
} }
@ -201,12 +201,12 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm) {
VI::InstallInterfaces(*sm, nv_flinger); VI::InstallInterfaces(*sm, nv_flinger);
Set::InstallInterfaces(*sm); Set::InstallInterfaces(*sm);
LOG_DEBUG(Service, "initialized OK"); NGLOG_DEBUG(Service, "initialized OK");
} }
/// Shutdown ServiceManager /// Shutdown ServiceManager
void Shutdown() { void Shutdown() {
g_kernel_named_ports.clear(); g_kernel_named_ports.clear();
LOG_DEBUG(Service, "shutdown OK"); NGLOG_DEBUG(Service, "shutdown OK");
} }
} // namespace Service } // namespace Service

View file

@ -22,7 +22,7 @@ void SET::GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_SET, "(STUBBED) called"); NGLOG_WARNING(Service_SET, "(STUBBED) called");
} }
SET::SET() : ServiceFramework("set") { SET::SET() : ServiceFramework("set") {

View file

@ -16,7 +16,7 @@ void SET_SYS::GetColorSetId(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0); rb.Push<u32>(0);
LOG_WARNING(Service_SET, "(STUBBED) called"); NGLOG_WARNING(Service_SET, "(STUBBED) called");
} }
SET_SYS::SET_SYS() : ServiceFramework("set:sys") { SET_SYS::SET_SYS() : ServiceFramework("set:sys") {

View file

@ -17,7 +17,7 @@ void Controller::ConvertSessionToDomain(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push<u32>(1); // Converted sessions start with 1 request handler rb.Push<u32>(1); // Converted sessions start with 1 request handler
LOG_DEBUG(Service, "called, server_session=%d", ctx.Session()->GetObjectId()); NGLOG_DEBUG(Service, "called, server_session={}", ctx.Session()->GetObjectId());
} }
void Controller::DuplicateSession(Kernel::HLERequestContext& ctx) { void Controller::DuplicateSession(Kernel::HLERequestContext& ctx) {
@ -29,11 +29,11 @@ void Controller::DuplicateSession(Kernel::HLERequestContext& ctx) {
Kernel::SharedPtr<Kernel::ClientSession> session{ctx.Session()->parent->client}; Kernel::SharedPtr<Kernel::ClientSession> session{ctx.Session()->parent->client};
rb.PushMoveObjects(session); rb.PushMoveObjects(session);
LOG_DEBUG(Service, "called, session=%u", session->GetObjectId()); NGLOG_DEBUG(Service, "called, session={}", session->GetObjectId());
} }
void Controller::DuplicateSessionEx(Kernel::HLERequestContext& ctx) { void Controller::DuplicateSessionEx(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called, using DuplicateSession"); NGLOG_WARNING(Service, "(STUBBED) called, using DuplicateSession");
DuplicateSession(ctx); DuplicateSession(ctx);
} }
@ -43,7 +43,7 @@ void Controller::QueryPointerBufferSize(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0x500); rb.Push<u32>(0x500);
LOG_WARNING(Service, "(STUBBED) called"); NGLOG_WARNING(Service, "(STUBBED) called");
} }
Controller::Controller() : ServiceFramework("IpcController") { Controller::Controller() : ServiceFramework("IpcController") {

View file

@ -86,7 +86,7 @@ SM::~SM() = default;
void SM::Initialize(Kernel::HLERequestContext& ctx) { void SM::Initialize(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_SM, "called"); NGLOG_DEBUG(Service_SM, "called");
} }
void SM::GetService(Kernel::HLERequestContext& ctx) { void SM::GetService(Kernel::HLERequestContext& ctx) {
@ -102,7 +102,7 @@ void SM::GetService(Kernel::HLERequestContext& ctx) {
if (client_port.Failed()) { if (client_port.Failed()) {
IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0); IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
rb.Push(client_port.Code()); rb.Push(client_port.Code());
LOG_ERROR(Service_SM, "called service=%s -> error 0x%08X", name.c_str(), NGLOG_ERROR(Service_SM, "called service={} -> error {:#010X}", name,
client_port.Code().raw); client_port.Code().raw);
if (name.length() == 0) if (name.length() == 0)
return; // LibNX Fix return; // LibNX Fix
@ -113,8 +113,7 @@ void SM::GetService(Kernel::HLERequestContext& ctx) {
auto session = client_port.Unwrap()->Connect(); auto session = client_port.Unwrap()->Connect();
ASSERT(session.Succeeded()); ASSERT(session.Succeeded());
if (session.Succeeded()) { if (session.Succeeded()) {
LOG_DEBUG(Service_SM, "called service=%s -> session=%u", name.c_str(), NGLOG_DEBUG(Service_SM, "called service={} -> session={}", name, (*session)->GetObjectId());
(*session)->GetObjectId());
IPC::ResponseBuilder rb = IPC::ResponseBuilder rb =
rp.MakeBuilder(2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles); rp.MakeBuilder(2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles);
rb.Push(session.Code()); rb.Push(session.Code());

View file

@ -8,7 +8,7 @@
namespace Service::Sockets { namespace Service::Sockets {
void BSD::RegisterClient(Kernel::HLERequestContext& ctx) { void BSD::RegisterClient(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called"); NGLOG_WARNING(Service, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
@ -17,7 +17,7 @@ void BSD::RegisterClient(Kernel::HLERequestContext& ctx) {
} }
void BSD::StartMonitoring(Kernel::HLERequestContext& ctx) { void BSD::StartMonitoring(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called"); NGLOG_WARNING(Service, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
@ -32,7 +32,8 @@ void BSD::Socket(Kernel::HLERequestContext& ctx) {
u32 type = rp.Pop<u32>(); u32 type = rp.Pop<u32>();
u32 protocol = rp.Pop<u32>(); u32 protocol = rp.Pop<u32>();
LOG_WARNING(Service, "(STUBBED) called domain=%u type=%u protocol=%u", domain, type, protocol); NGLOG_WARNING(Service, "(STUBBED) called domain={} type={} protocol={}", domain, type,
protocol);
u32 fd = next_fd++; u32 fd = next_fd++;
@ -44,7 +45,7 @@ void BSD::Socket(Kernel::HLERequestContext& ctx) {
} }
void BSD::Connect(Kernel::HLERequestContext& ctx) { void BSD::Connect(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called"); NGLOG_WARNING(Service, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
@ -54,7 +55,7 @@ void BSD::Connect(Kernel::HLERequestContext& ctx) {
} }
void BSD::SendTo(Kernel::HLERequestContext& ctx) { void BSD::SendTo(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called"); NGLOG_WARNING(Service, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
@ -64,7 +65,7 @@ void BSD::SendTo(Kernel::HLERequestContext& ctx) {
} }
void BSD::Close(Kernel::HLERequestContext& ctx) { void BSD::Close(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called"); NGLOG_WARNING(Service, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};

View file

@ -10,7 +10,7 @@ namespace Service::Sockets {
void SFDNSRES::GetAddrInfo(Kernel::HLERequestContext& ctx) { void SFDNSRES::GetAddrInfo(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
LOG_WARNING(Service, "(STUBBED) called"); NGLOG_WARNING(Service, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};

View file

@ -28,7 +28,7 @@ void Module::Interface::GetRandomBytes(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_SPL, "called"); NGLOG_DEBUG(Service_SPL, "called");
} }
void InstallInterfaces(SM::ServiceManager& service_manager) { void InstallInterfaces(SM::ServiceManager& service_manager) {

View file

@ -65,7 +65,7 @@ public:
private: private:
void SetOption(Kernel::HLERequestContext& ctx) { void SetOption(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_SSL, "(STUBBED) called"); NGLOG_WARNING(Service_SSL, "(STUBBED) called");
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0); IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
@ -73,7 +73,7 @@ private:
} }
void CreateConnection(Kernel::HLERequestContext& ctx) { void CreateConnection(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_SSL, "(STUBBED) called"); NGLOG_WARNING(Service_SSL, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
@ -82,7 +82,7 @@ private:
}; };
void SSL::CreateContext(Kernel::HLERequestContext& ctx) { void SSL::CreateContext(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_SSL, "(STUBBED) called"); NGLOG_WARNING(Service_SSL, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);

View file

@ -32,14 +32,14 @@ private:
const s64 time_since_epoch{std::chrono::duration_cast<std::chrono::seconds>( const s64 time_since_epoch{std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch()) std::chrono::system_clock::now().time_since_epoch())
.count()}; .count()};
LOG_DEBUG(Service_Time, "called"); NGLOG_DEBUG(Service_Time, "called");
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push<u64>(time_since_epoch); rb.Push<u64>(time_since_epoch);
} }
void GetSystemClockContext(Kernel::HLERequestContext& ctx) { void GetSystemClockContext(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Time, "(STUBBED) called"); NGLOG_WARNING(Service_Time, "(STUBBED) called");
SystemClockContext system_clock_ontext{}; SystemClockContext system_clock_ontext{};
IPC::ResponseBuilder rb{ctx, (sizeof(SystemClockContext) / 4) + 2}; IPC::ResponseBuilder rb{ctx, (sizeof(SystemClockContext) / 4) + 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
@ -58,7 +58,7 @@ public:
private: private:
void GetCurrentTimePoint(Kernel::HLERequestContext& ctx) { void GetCurrentTimePoint(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called"); NGLOG_DEBUG(Service_Time, "called");
SteadyClockTimePoint steady_clock_time_point{cyclesToMs(CoreTiming::GetTicks()) / 1000}; SteadyClockTimePoint steady_clock_time_point{cyclesToMs(CoreTiming::GetTicks()) / 1000};
IPC::ResponseBuilder rb{ctx, (sizeof(SteadyClockTimePoint) / 4) + 2}; IPC::ResponseBuilder rb{ctx, (sizeof(SteadyClockTimePoint) / 4) + 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
@ -86,7 +86,7 @@ public:
private: private:
void GetDeviceLocationName(Kernel::HLERequestContext& ctx) { void GetDeviceLocationName(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Time, "(STUBBED) called"); NGLOG_WARNING(Service_Time, "(STUBBED) called");
LocationName location_name{}; LocationName location_name{};
IPC::ResponseBuilder rb{ctx, (sizeof(LocationName) / 4) + 2}; IPC::ResponseBuilder rb{ctx, (sizeof(LocationName) / 4) + 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
@ -94,14 +94,14 @@ private:
} }
void GetTotalLocationNameCount(Kernel::HLERequestContext& ctx) { void GetTotalLocationNameCount(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Time, "(STUBBED) called"); NGLOG_WARNING(Service_Time, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0); rb.Push<u32>(0);
} }
void LoadTimeZoneRule(Kernel::HLERequestContext& ctx) { void LoadTimeZoneRule(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Time, "(STUBBED) called"); NGLOG_WARNING(Service_Time, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
} }
@ -110,7 +110,7 @@ private:
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
u64 posix_time = rp.Pop<u64>(); u64 posix_time = rp.Pop<u64>();
LOG_WARNING(Service_Time, "(STUBBED) called, posix_time=0x%016lX", posix_time); NGLOG_WARNING(Service_Time, "(STUBBED) called, posix_time={:#018X}", posix_time);
CalendarTime calendar_time{2018, 1, 1, 0, 0, 0}; CalendarTime calendar_time{2018, 1, 1, 0, 0, 0};
CalendarAdditionalInfo additional_info{}; CalendarAdditionalInfo additional_info{};
@ -125,35 +125,35 @@ void Module::Interface::GetStandardUserSystemClock(Kernel::HLERequestContext& ct
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISystemClock>(); rb.PushIpcInterface<ISystemClock>();
LOG_DEBUG(Service_Time, "called"); NGLOG_DEBUG(Service_Time, "called");
} }
void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx) { void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISystemClock>(); rb.PushIpcInterface<ISystemClock>();
LOG_DEBUG(Service_Time, "called"); NGLOG_DEBUG(Service_Time, "called");
} }
void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) { void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISteadyClock>(); rb.PushIpcInterface<ISteadyClock>();
LOG_DEBUG(Service_Time, "called"); NGLOG_DEBUG(Service_Time, "called");
} }
void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) { void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ITimeZoneService>(); rb.PushIpcInterface<ITimeZoneService>();
LOG_DEBUG(Service_Time, "called"); NGLOG_DEBUG(Service_Time, "called");
} }
void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx) { void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISystemClock>(); rb.PushIpcInterface<ISystemClock>();
LOG_DEBUG(Service_Time, "called"); NGLOG_DEBUG(Service_Time, "called");
} }
Module::Interface::Interface(std::shared_ptr<Module> time, const char* name) Module::Interface::Interface(std::shared_ptr<Module> time, const char* name)

View file

@ -470,7 +470,7 @@ private:
u32 flags = rp.Pop<u32>(); u32 flags = rp.Pop<u32>();
auto buffer_queue = nv_flinger->GetBufferQueue(id); auto buffer_queue = nv_flinger->GetBufferQueue(id);
LOG_DEBUG(Service_VI, "called, transaction=%x", static_cast<u32>(transaction)); NGLOG_DEBUG(Service_VI, "called, transaction={:X}", static_cast<u32>(transaction));
if (transaction == TransactionId::Connect) { if (transaction == TransactionId::Connect) {
IGBPConnectRequestParcel request{ctx.ReadBuffer()}; IGBPConnectRequestParcel request{ctx.ReadBuffer()};
@ -532,7 +532,7 @@ private:
IGBPQueryResponseParcel response{value}; IGBPQueryResponseParcel response{value};
ctx.WriteBuffer(response.Serialize()); ctx.WriteBuffer(response.Serialize());
} else if (transaction == TransactionId::CancelBuffer) { } else if (transaction == TransactionId::CancelBuffer) {
LOG_WARNING(Service_VI, "(STUBBED) called, transaction=CancelBuffer"); NGLOG_WARNING(Service_VI, "(STUBBED) called, transaction=CancelBuffer");
} else { } else {
ASSERT_MSG(false, "Unimplemented"); ASSERT_MSG(false, "Unimplemented");
} }
@ -547,7 +547,8 @@ private:
s32 addval = rp.PopRaw<s32>(); s32 addval = rp.PopRaw<s32>();
u32 type = rp.Pop<u32>(); u32 type = rp.Pop<u32>();
LOG_WARNING(Service_VI, "(STUBBED) called id=%u, addval=%08X, type=%08X", id, addval, type); NGLOG_WARNING(Service_VI, "(STUBBED) called id={}, addval={:08X}, type={:08X}", id, addval,
type);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
} }
@ -561,7 +562,7 @@ private:
// TODO(Subv): Find out what this actually is. // TODO(Subv): Find out what this actually is.
LOG_WARNING(Service_VI, "(STUBBED) called id=%u, unknown=%08X", id, unknown); NGLOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown);
IPC::ResponseBuilder rb{ctx, 2, 1}; IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(buffer_queue->GetNativeHandle()); rb.PushCopyObjects(buffer_queue->GetNativeHandle());
@ -624,7 +625,7 @@ public:
private: private:
void SetLayerZ(Kernel::HLERequestContext& ctx) { void SetLayerZ(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called"); NGLOG_WARNING(Service_VI, "(STUBBED) called");
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
u64 layer_id = rp.Pop<u64>(); u64 layer_id = rp.Pop<u64>();
u64 z_value = rp.Pop<u64>(); u64 z_value = rp.Pop<u64>();
@ -639,7 +640,7 @@ private:
bool visibility = rp.Pop<bool>(); bool visibility = rp.Pop<bool>();
IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0); IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x%x, visibility=%u", layer_id, NGLOG_WARNING(Service_VI, "(STUBBED) called, layer_id={:#010X}, visibility={}", layer_id,
visibility); visibility);
} }
}; };
@ -722,7 +723,7 @@ public:
private: private:
void CloseDisplay(Kernel::HLERequestContext& ctx) { void CloseDisplay(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called"); NGLOG_WARNING(Service_VI, "(STUBBED) called");
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
u64 display = rp.Pop<u64>(); u64 display = rp.Pop<u64>();
@ -731,7 +732,7 @@ private:
} }
void CreateManagedLayer(Kernel::HLERequestContext& ctx) { void CreateManagedLayer(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called"); NGLOG_WARNING(Service_VI, "(STUBBED) called");
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
u32 unknown = rp.Pop<u32>(); u32 unknown = rp.Pop<u32>();
rp.Skip(1, false); rp.Skip(1, false);
@ -746,7 +747,7 @@ private:
} }
void AddToLayerStack(Kernel::HLERequestContext& ctx) { void AddToLayerStack(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called"); NGLOG_WARNING(Service_VI, "(STUBBED) called");
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
u32 stack = rp.Pop<u32>(); u32 stack = rp.Pop<u32>();
u64 layer_id = rp.Pop<u64>(); u64 layer_id = rp.Pop<u64>();
@ -761,7 +762,7 @@ private:
bool visibility = rp.Pop<bool>(); bool visibility = rp.Pop<bool>();
IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0); IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x%x, visibility=%u", layer_id, NGLOG_WARNING(Service_VI, "(STUBBED) called, layer_id={:#X}, visibility={}", layer_id,
visibility); visibility);
} }
@ -775,7 +776,7 @@ public:
private: private:
void GetRelayService(Kernel::HLERequestContext& ctx) { void GetRelayService(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called"); NGLOG_WARNING(Service_VI, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
@ -783,7 +784,7 @@ private:
} }
void GetSystemDisplayService(Kernel::HLERequestContext& ctx) { void GetSystemDisplayService(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called"); NGLOG_WARNING(Service_VI, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
@ -791,7 +792,7 @@ private:
} }
void GetManagerDisplayService(Kernel::HLERequestContext& ctx) { void GetManagerDisplayService(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called"); NGLOG_WARNING(Service_VI, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
@ -799,7 +800,7 @@ private:
} }
void GetIndirectDisplayTransactionService(Kernel::HLERequestContext& ctx) { void GetIndirectDisplayTransactionService(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called"); NGLOG_WARNING(Service_VI, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
@ -807,7 +808,7 @@ private:
} }
void OpenDisplay(Kernel::HLERequestContext& ctx) { void OpenDisplay(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called"); NGLOG_WARNING(Service_VI, "(STUBBED) called");
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
auto name_buf = rp.PopRaw<std::array<u8, 0x40>>(); auto name_buf = rp.PopRaw<std::array<u8, 0x40>>();
auto end = std::find(name_buf.begin(), name_buf.end(), '\0'); auto end = std::find(name_buf.begin(), name_buf.end(), '\0');
@ -822,7 +823,7 @@ private:
} }
void CloseDisplay(Kernel::HLERequestContext& ctx) { void CloseDisplay(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called"); NGLOG_WARNING(Service_VI, "(STUBBED) called");
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
u64 display_id = rp.Pop<u64>(); u64 display_id = rp.Pop<u64>();
@ -831,7 +832,7 @@ private:
} }
void GetDisplayResolution(Kernel::HLERequestContext& ctx) { void GetDisplayResolution(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called"); NGLOG_WARNING(Service_VI, "(STUBBED) called");
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
u64 display_id = rp.Pop<u64>(); u64 display_id = rp.Pop<u64>();
@ -848,7 +849,7 @@ private:
} }
void SetLayerScalingMode(Kernel::HLERequestContext& ctx) { void SetLayerScalingMode(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called"); NGLOG_WARNING(Service_VI, "(STUBBED) called");
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
u32 scaling_mode = rp.Pop<u32>(); u32 scaling_mode = rp.Pop<u32>();
u64 unknown = rp.Pop<u64>(); u64 unknown = rp.Pop<u64>();
@ -864,11 +865,11 @@ private:
IPC::ResponseBuilder rb = rp.MakeBuilder(4, 0, 0); IPC::ResponseBuilder rb = rp.MakeBuilder(4, 0, 0);
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push<u64>(1); rb.Push<u64>(1);
LOG_WARNING(Service_VI, "(STUBBED) called"); NGLOG_WARNING(Service_VI, "(STUBBED) called");
} }
void OpenLayer(Kernel::HLERequestContext& ctx) { void OpenLayer(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_VI, "called"); NGLOG_DEBUG(Service_VI, "called");
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
auto name_buf = rp.PopRaw<std::array<u8, 0x40>>(); auto name_buf = rp.PopRaw<std::array<u8, 0x40>>();
auto end = std::find(name_buf.begin(), name_buf.end(), '\0'); auto end = std::find(name_buf.begin(), name_buf.end(), '\0');
@ -888,7 +889,7 @@ private:
} }
void CreateStrayLayer(Kernel::HLERequestContext& ctx) { void CreateStrayLayer(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_VI, "called"); NGLOG_DEBUG(Service_VI, "called");
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
u32 flags = rp.Pop<u32>(); u32 flags = rp.Pop<u32>();
@ -908,7 +909,7 @@ private:
} }
void DestroyStrayLayer(Kernel::HLERequestContext& ctx) { void DestroyStrayLayer(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called"); NGLOG_WARNING(Service_VI, "(STUBBED) called");
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
u64 layer_id = rp.Pop<u64>(); u64 layer_id = rp.Pop<u64>();
@ -918,7 +919,7 @@ private:
} }
void GetDisplayVsyncEvent(Kernel::HLERequestContext& ctx) { void GetDisplayVsyncEvent(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called"); NGLOG_WARNING(Service_VI, "(STUBBED) called");
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
u64 display_id = rp.Pop<u64>(); u64 display_id = rp.Pop<u64>();
@ -967,7 +968,7 @@ Module::Interface::Interface(std::shared_ptr<Module> module, const char* name,
: ServiceFramework(name), module(std::move(module)), nv_flinger(std::move(nv_flinger)) {} : ServiceFramework(name), module(std::move(module)), nv_flinger(std::move(nv_flinger)) {}
void Module::Interface::GetDisplayService(Kernel::HLERequestContext& ctx) { void Module::Interface::GetDisplayService(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called"); NGLOG_WARNING(Service_VI, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);

View file

@ -33,7 +33,8 @@ inline void Read(T& var, const u32 addr) {
LCD::Read(var, addr); LCD::Read(var, addr);
break; break;
default: default:
LOG_ERROR(HW_Memory, "unknown Read%lu @ 0x%08X", sizeof(var) * 8, addr); NGLOG_ERROR(HW_Memory, "Unknown Read{} @ {:#010X}", sizeof(var) * 8, addr);
break;
} }
} }
@ -61,7 +62,8 @@ inline void Write(u32 addr, const T data) {
LCD::Write(addr, data); LCD::Write(addr, data);
break; break;
default: default:
LOG_ERROR(HW_Memory, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, addr); NGLOG_ERROR(HW_Memory, "Unknown Write{} {:#010X} @ {:#010X}", sizeof(data) * 8, data, addr);
break;
} }
} }
@ -83,12 +85,12 @@ void Update() {}
/// Initialize hardware /// Initialize hardware
void Init() { void Init() {
LCD::Init(); LCD::Init();
LOG_DEBUG(HW, "initialized OK"); NGLOG_DEBUG(HW, "Initialized OK");
} }
/// Shutdown hardware /// Shutdown hardware
void Shutdown() { void Shutdown() {
LCD::Shutdown(); LCD::Shutdown();
LOG_DEBUG(HW, "shutdown OK"); NGLOG_DEBUG(HW, "Shutdown OK");
} }
} // namespace HW } // namespace HW

View file

@ -20,7 +20,7 @@ inline void Read(T& var, const u32 raw_addr) {
// Reads other than u32 are untested, so I'd rather have them abort than silently fail // Reads other than u32 are untested, so I'd rather have them abort than silently fail
if (index >= 0x400 || !std::is_same<T, u32>::value) { if (index >= 0x400 || !std::is_same<T, u32>::value) {
LOG_ERROR(HW_LCD, "unknown Read%lu @ 0x%08X", sizeof(var) * 8, addr); NGLOG_ERROR(HW_LCD, "Unknown Read{} @ {:#010X}", sizeof(var) * 8, addr);
return; return;
} }
@ -34,7 +34,7 @@ inline void Write(u32 addr, const T data) {
// Writes other than u32 are untested, so I'd rather have them abort than silently fail // Writes other than u32 are untested, so I'd rather have them abort than silently fail
if (index >= 0x400 || !std::is_same<T, u32>::value) { if (index >= 0x400 || !std::is_same<T, u32>::value) {
LOG_ERROR(HW_LCD, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, addr); NGLOG_ERROR(HW_LCD, "Unknown Write{} {:#010X} @ {:#010X}", sizeof(data) * 8, data, addr);
return; return;
} }
@ -56,12 +56,12 @@ template void Write<u8>(u32 addr, const u8 data);
/// Initialize hardware /// Initialize hardware
void Init() { void Init() {
memset(&g_regs, 0, sizeof(g_regs)); memset(&g_regs, 0, sizeof(g_regs));
LOG_DEBUG(HW_LCD, "initialized OK"); NGLOG_DEBUG(HW_LCD, "Initialized OK");
} }
/// Shutdown hardware /// Shutdown hardware
void Shutdown() { void Shutdown() {
LOG_DEBUG(HW_LCD, "shutdown OK"); NGLOG_DEBUG(HW_LCD, "Shutdown OK");
} }
} // namespace LCD } // namespace LCD

View file

@ -132,7 +132,7 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
const VAddr load_addr = next_load_addr; const VAddr load_addr = next_load_addr;
next_load_addr = AppLoader_NSO::LoadModule(path, load_addr); next_load_addr = AppLoader_NSO::LoadModule(path, load_addr);
if (next_load_addr) { if (next_load_addr) {
LOG_DEBUG(Loader, "loaded module %s @ 0x%" PRIx64, module, load_addr); NGLOG_DEBUG(Loader, "loaded module {} @ {:#X}", module, load_addr);
} else { } else {
next_load_addr = load_addr; next_load_addr = load_addr;
} }
@ -163,7 +163,7 @@ ResultStatus AppLoader_DeconstructedRomDirectory::ReadRomFS(
std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) { std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) {
if (filepath_romfs.empty()) { if (filepath_romfs.empty()) {
LOG_DEBUG(Loader, "No RomFS available"); NGLOG_DEBUG(Loader, "No RomFS available");
return ResultStatus::ErrorNotUsed; return ResultStatus::ErrorNotUsed;
} }
@ -176,8 +176,8 @@ ResultStatus AppLoader_DeconstructedRomDirectory::ReadRomFS(
offset = 0; offset = 0;
size = romfs_file->GetSize(); size = romfs_file->GetSize();
LOG_DEBUG(Loader, "RomFS offset: 0x%016" PRIX64, offset); NGLOG_DEBUG(Loader, "RomFS offset: {:#018X}", offset);
LOG_DEBUG(Loader, "RomFS size: 0x%016" PRIX64, size); NGLOG_DEBUG(Loader, "RomFS size: {:#018X}", size);
// Reset read pointer // Reset read pointer
file.Seek(0, SEEK_SET); file.Seek(0, SEEK_SET);

View file

@ -273,18 +273,18 @@ const char* ElfReader::GetSectionName(int section) const {
} }
SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) { SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) {
LOG_DEBUG(Loader, "String section: %i", header->e_shstrndx); NGLOG_DEBUG(Loader, "String section: {}", header->e_shstrndx);
// Should we relocate? // Should we relocate?
relocate = (header->e_type != ET_EXEC); relocate = (header->e_type != ET_EXEC);
if (relocate) { if (relocate) {
LOG_DEBUG(Loader, "Relocatable module"); NGLOG_DEBUG(Loader, "Relocatable module");
entryPoint += vaddr; entryPoint += vaddr;
} else { } else {
LOG_DEBUG(Loader, "Prerelocated executable"); NGLOG_DEBUG(Loader, "Prerelocated executable");
} }
LOG_DEBUG(Loader, "%i segments:", header->e_phnum); NGLOG_DEBUG(Loader, "{} segments:", header->e_phnum);
// First pass : Get the bits into RAM // First pass : Get the bits into RAM
u32 base_addr = relocate ? vaddr : 0; u32 base_addr = relocate ? vaddr : 0;
@ -304,8 +304,8 @@ SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) {
for (unsigned int i = 0; i < header->e_phnum; ++i) { for (unsigned int i = 0; i < header->e_phnum; ++i) {
Elf32_Phdr* p = &segments[i]; Elf32_Phdr* p = &segments[i];
LOG_DEBUG(Loader, "Type: %i Vaddr: %08X Filesz: %8X Memsz: %8X ", p->p_type, p->p_vaddr, NGLOG_DEBUG(Loader, "Type: {} Vaddr: {:08X} Filesz: {:08X} Memsz: {:08X} ", p->p_type,
p->p_filesz, p->p_memsz); p->p_vaddr, p->p_filesz, p->p_memsz);
if (p->p_type == PT_LOAD) { if (p->p_type == PT_LOAD) {
CodeSet::Segment* codeset_segment; CodeSet::Segment* codeset_segment;
@ -317,15 +317,15 @@ SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) {
} else if (permission_flags == (PF_R | PF_W)) { } else if (permission_flags == (PF_R | PF_W)) {
codeset_segment = &codeset->data; codeset_segment = &codeset->data;
} else { } else {
LOG_ERROR(Loader, "Unexpected ELF PT_LOAD segment id %u with flags %X", i, NGLOG_ERROR(Loader, "Unexpected ELF PT_LOAD segment id {} with flags {:X}", i,
p->p_flags); p->p_flags);
continue; continue;
} }
if (codeset_segment->size != 0) { if (codeset_segment->size != 0) {
LOG_ERROR(Loader, NGLOG_ERROR(Loader,
"ELF has more than one segment of the same type. Skipping extra " "ELF has more than one segment of the same type. Skipping extra "
"segment (id %i)", "segment (id {})",
i); i);
continue; continue;
} }
@ -345,7 +345,7 @@ SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) {
codeset->entrypoint = base_addr + header->e_entry; codeset->entrypoint = base_addr + header->e_entry;
codeset->memory = std::make_shared<std::vector<u8>>(std::move(program_image)); codeset->memory = std::make_shared<std::vector<u8>>(std::move(program_image));
LOG_DEBUG(Loader, "Done loading."); NGLOG_DEBUG(Loader, "Done loading.");
return codeset; return codeset;
} }

View file

@ -84,7 +84,7 @@ void Linker::WriteRelocations(std::vector<u8>& program_image, const std::vector<
} }
break; break;
default: default:
LOG_CRITICAL(Loader, "Unknown relocation type: %d", static_cast<int>(rela.type)); NGLOG_CRITICAL(Loader, "Unknown relocation type: {}", static_cast<int>(rela.type));
break; break;
} }
} }
@ -141,7 +141,7 @@ void Linker::ResolveImports() {
if (search != exports.end()) { if (search != exports.end()) {
Memory::Write64(import.second.ea, search->second + import.second.addend); Memory::Write64(import.second.ea, search->second + import.second.addend);
} else { } else {
LOG_ERROR(Loader, "Unresolved import: %s", import.first.c_str()); NGLOG_ERROR(Loader, "Unresolved import: {}", import.first);
} }
} }
} }

View file

@ -41,7 +41,7 @@ FileType IdentifyFile(FileUtil::IOFile& file, const std::string& filepath) {
FileType IdentifyFile(const std::string& file_name) { FileType IdentifyFile(const std::string& file_name) {
FileUtil::IOFile file(file_name, "rb"); FileUtil::IOFile file(file_name, "rb");
if (!file.IsOpen()) { if (!file.IsOpen()) {
LOG_ERROR(Loader, "Failed to load file %s", file_name.c_str()); NGLOG_ERROR(Loader, "Failed to load file {}", file_name);
return FileType::Unknown; return FileType::Unknown;
} }
@ -116,7 +116,7 @@ static std::unique_ptr<AppLoader> GetFileLoader(FileUtil::IOFile&& file, FileTyp
std::unique_ptr<AppLoader> GetLoader(const std::string& filename) { std::unique_ptr<AppLoader> GetLoader(const std::string& filename) {
FileUtil::IOFile file(filename, "rb"); FileUtil::IOFile file(filename, "rb");
if (!file.IsOpen()) { if (!file.IsOpen()) {
LOG_ERROR(Loader, "Failed to load file %s", filename.c_str()); NGLOG_ERROR(Loader, "Failed to load file {}", filename);
return nullptr; return nullptr;
} }
@ -127,12 +127,12 @@ std::unique_ptr<AppLoader> GetLoader(const std::string& filename) {
FileType filename_type = GuessFromExtension(filename_extension); FileType filename_type = GuessFromExtension(filename_extension);
if (type != filename_type) { if (type != filename_type) {
LOG_WARNING(Loader, "File %s has a different type than its extension.", filename.c_str()); NGLOG_WARNING(Loader, "File {} has a different type than its extension.", filename);
if (FileType::Unknown == type) if (FileType::Unknown == type)
type = filename_type; type = filename_type;
} }
LOG_DEBUG(Loader, "Loading file %s as %s...", filename.c_str(), GetFileTypeString(type)); NGLOG_DEBUG(Loader, "Loading file {} as {}...", filename, GetFileTypeString(type));
return GetFileLoader(std::move(file), type, filename_filename, filename); return GetFileLoader(std::move(file), type, filename_filename, filename);
} }

View file

@ -137,7 +137,7 @@ ResultStatus AppLoader_NRO::Load(Kernel::SharedPtr<Kernel::Process>& process) {
process->address_mappings = default_address_mappings; process->address_mappings = default_address_mappings;
process->resource_limit = process->resource_limit =
Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
process->Run(base_addr, 48, Memory::DEFAULT_STACK_SIZE); process->Run(base_addr, THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE);
is_loaded = true; is_loaded = true;
return ResultStatus::Success; return ResultStatus::Success;

View file

@ -73,7 +73,7 @@ static std::vector<u8> ReadSegment(FileUtil::IOFile& file, const NsoSegmentHeade
file.Seek(header.offset, SEEK_SET); file.Seek(header.offset, SEEK_SET);
if (compressed_size != file.ReadBytes(compressed_data.data(), compressed_size)) { if (compressed_size != file.ReadBytes(compressed_data.data(), compressed_size)) {
LOG_CRITICAL(Loader, "Failed to read %d NSO LZ4 compressed bytes", compressed_size); NGLOG_CRITICAL(Loader, "Failed to read {} NSO LZ4 compressed bytes", compressed_size);
return {}; return {};
} }
@ -158,14 +158,13 @@ ResultStatus AppLoader_NSO::Load(Kernel::SharedPtr<Kernel::Process>& process) {
// Load module // Load module
LoadModule(filepath, Memory::PROCESS_IMAGE_VADDR); LoadModule(filepath, Memory::PROCESS_IMAGE_VADDR);
LOG_DEBUG(Loader, "loaded module %s @ 0x%" PRIx64, filepath.c_str(), NGLOG_DEBUG(Loader, "loaded module {} @ {:#X}", filepath, Memory::PROCESS_IMAGE_VADDR);
Memory::PROCESS_IMAGE_VADDR);
process->svc_access_mask.set(); process->svc_access_mask.set();
process->address_mappings = default_address_mappings; process->address_mappings = default_address_mappings;
process->resource_limit = process->resource_limit =
Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
process->Run(Memory::PROCESS_IMAGE_VADDR, 48, Memory::DEFAULT_STACK_SIZE); process->Run(Memory::PROCESS_IMAGE_VADDR, THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE);
is_loaded = true; is_loaded = true;
return ResultStatus::Success; return ResultStatus::Success;

View file

@ -39,7 +39,7 @@ PageTable* GetCurrentPageTable() {
} }
static void MapPages(PageTable& page_table, VAddr base, u64 size, u8* memory, PageType type) { static void MapPages(PageTable& page_table, VAddr base, u64 size, u8* memory, PageType type) {
LOG_DEBUG(HW_Memory, "Mapping %p onto %016" PRIX64 "-%016" PRIX64, memory, base * PAGE_SIZE, NGLOG_DEBUG(HW_Memory, "Mapping {} onto {:016X}-{:016X}", fmt::ptr(memory), base * PAGE_SIZE,
(base + size) * PAGE_SIZE); (base + size) * PAGE_SIZE);
RasterizerFlushVirtualRegion(base << PAGE_BITS, size * PAGE_SIZE, RasterizerFlushVirtualRegion(base << PAGE_BITS, size * PAGE_SIZE,
@ -169,10 +169,10 @@ T Read(const VAddr vaddr) {
PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; PageType type = current_page_table->attributes[vaddr >> PAGE_BITS];
switch (type) { switch (type) {
case PageType::Unmapped: case PageType::Unmapped:
LOG_ERROR(HW_Memory, "unmapped Read%lu @ 0x%08X", sizeof(T) * 8, vaddr); NGLOG_ERROR(HW_Memory, "Unmapped Read{} @ {:#010X}", sizeof(T) * 8, vaddr);
return 0; return 0;
case PageType::Memory: case PageType::Memory:
ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); ASSERT_MSG(false, "Mapped memory page without a pointer @ %016" PRIX64, vaddr);
break; break;
case PageType::RasterizerCachedMemory: { case PageType::RasterizerCachedMemory: {
RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Flush); RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Flush);
@ -201,11 +201,11 @@ void Write(const VAddr vaddr, const T data) {
PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; PageType type = current_page_table->attributes[vaddr >> PAGE_BITS];
switch (type) { switch (type) {
case PageType::Unmapped: case PageType::Unmapped:
LOG_ERROR(HW_Memory, "unmapped Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, NGLOG_ERROR(HW_Memory, "Unmapped Write{} {:#010X} @ {:#018X}", sizeof(data) * 8, (u32)data,
vaddr); vaddr);
return; return;
case PageType::Memory: case PageType::Memory:
ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); ASSERT_MSG(false, "Mapped memory page without a pointer @ %016" PRIX64, vaddr);
break; break;
case PageType::RasterizerCachedMemory: { case PageType::RasterizerCachedMemory: {
RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Invalidate); RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Invalidate);
@ -251,7 +251,7 @@ u8* GetPointer(const VAddr vaddr) {
return GetPointerFromVMA(vaddr); return GetPointerFromVMA(vaddr);
} }
LOG_ERROR(HW_Memory, "unknown GetPointer @ 0x%08x", vaddr); NGLOG_ERROR(HW_Memory, "Unknown GetPointer @ {:#018X}", vaddr);
return nullptr; return nullptr;
} }
@ -288,13 +288,12 @@ u8* GetPhysicalPointer(PAddr address) {
}); });
if (area == std::end(memory_areas)) { if (area == std::end(memory_areas)) {
LOG_ERROR(HW_Memory, "unknown GetPhysicalPointer @ 0x%016" PRIX64, address); NGLOG_ERROR(HW_Memory, "Unknown GetPhysicalPointer @ {:#018X}", address);
return nullptr; return nullptr;
} }
if (area->paddr_base == IO_AREA_PADDR) { if (area->paddr_base == IO_AREA_PADDR) {
LOG_ERROR(HW_Memory, "MMIO mappings are not supported yet. phys_addr=0x%016" PRIX64, NGLOG_ERROR(HW_Memory, "MMIO mappings are not supported yet. phys_addr={:018X}", address);
address);
return nullptr; return nullptr;
} }
@ -325,15 +324,29 @@ u8* GetPhysicalPointer(PAddr address) {
return target_pointer; return target_pointer;
} }
void RasterizerMarkRegionCached(VAddr start, u64 size, bool cached) { void RasterizerMarkRegionCached(Tegra::GPUVAddr gpu_addr, u64 size, bool cached) {
if (start == 0) { if (gpu_addr == 0) {
return; return;
} }
u64 num_pages = ((start + size - 1) >> PAGE_BITS) - (start >> PAGE_BITS) + 1; // Iterate over a contiguous CPU address space, which corresponds to the specified GPU address
VAddr vaddr = start; // space, marking the region as un/cached. The region is marked un/cached at a granularity of
// CPU pages, hence why we iterate on a CPU page basis (note: GPU page size is different). This
// assumes the specified GPU address region is contiguous as well.
u64 num_pages = ((gpu_addr + size - 1) >> PAGE_BITS) - (gpu_addr >> PAGE_BITS) + 1;
for (unsigned i = 0; i < num_pages; ++i, gpu_addr += PAGE_SIZE) {
boost::optional<VAddr> maybe_vaddr =
Core::System::GetInstance().GPU().memory_manager->GpuToCpuAddress(gpu_addr);
// The GPU <-> CPU virtual memory mapping is not 1:1
if (!maybe_vaddr) {
NGLOG_ERROR(HW_Memory,
"Trying to flush a cached region to an invalid physical address {:016X}",
gpu_addr);
continue;
}
VAddr vaddr = *maybe_vaddr;
for (unsigned i = 0; i < num_pages; ++i, vaddr += PAGE_SIZE) {
PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS]; PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS];
if (cached) { if (cached) {
@ -347,6 +360,10 @@ void RasterizerMarkRegionCached(VAddr start, u64 size, bool cached) {
page_type = PageType::RasterizerCachedMemory; page_type = PageType::RasterizerCachedMemory;
current_page_table->pointers[vaddr >> PAGE_BITS] = nullptr; current_page_table->pointers[vaddr >> PAGE_BITS] = nullptr;
break; break;
case PageType::RasterizerCachedMemory:
// There can be more than one GPU region mapped per CPU region, so it's common that
// this area is already marked as cached.
break;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
@ -357,6 +374,10 @@ void RasterizerMarkRegionCached(VAddr start, u64 size, bool cached) {
// It is not necessary for a process to have this region mapped into its address // It is not necessary for a process to have this region mapped into its address
// space, for example, a system module need not have a VRAM mapping. // space, for example, a system module need not have a VRAM mapping.
break; break;
case PageType::Memory:
// There can be more than one GPU region mapped per CPU region, so it's common that
// this area is already unmarked as cached.
break;
case PageType::RasterizerCachedMemory: { case PageType::RasterizerCachedMemory: {
u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK); u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK);
if (pointer == nullptr) { if (pointer == nullptr) {
@ -394,20 +415,30 @@ void RasterizerFlushVirtualRegion(VAddr start, u64 size, FlushMode mode) {
VAddr overlap_start = std::max(start, region_start); VAddr overlap_start = std::max(start, region_start);
VAddr overlap_end = std::min(end, region_end); VAddr overlap_end = std::min(end, region_end);
std::vector<Tegra::GPUVAddr> gpu_addresses =
Core::System::GetInstance().GPU().memory_manager->CpuToGpuAddress(overlap_start);
if (gpu_addresses.empty()) {
return;
}
u64 overlap_size = overlap_end - overlap_start; u64 overlap_size = overlap_end - overlap_start;
for (const auto& gpu_address : gpu_addresses) {
auto* rasterizer = VideoCore::g_renderer->Rasterizer(); auto* rasterizer = VideoCore::g_renderer->Rasterizer();
switch (mode) { switch (mode) {
case FlushMode::Flush: case FlushMode::Flush:
rasterizer->FlushRegion(overlap_start, overlap_size); rasterizer->FlushRegion(gpu_address, overlap_size);
break; break;
case FlushMode::Invalidate: case FlushMode::Invalidate:
rasterizer->InvalidateRegion(overlap_start, overlap_size); rasterizer->InvalidateRegion(gpu_address, overlap_size);
break; break;
case FlushMode::FlushAndInvalidate: case FlushMode::FlushAndInvalidate:
rasterizer->FlushAndInvalidateRegion(overlap_start, overlap_size); rasterizer->FlushAndInvalidateRegion(gpu_address, overlap_size);
break; break;
} }
}
}; };
CheckRegion(PROCESS_IMAGE_VADDR, PROCESS_IMAGE_VADDR_END); CheckRegion(PROCESS_IMAGE_VADDR, PROCESS_IMAGE_VADDR_END);
@ -445,7 +476,8 @@ void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_
switch (page_table.attributes[page_index]) { switch (page_table.attributes[page_index]) {
case PageType::Unmapped: { case PageType::Unmapped: {
LOG_ERROR(HW_Memory, "unmapped ReadBlock @ 0x%08X (start address = 0x%08X, size = %zu)", NGLOG_ERROR(HW_Memory,
"Unmapped ReadBlock @ {:#018X} (start address = {:#018X}, size = {})",
current_vaddr, src_addr, size); current_vaddr, src_addr, size);
std::memset(dest_buffer, 0, copy_amount); std::memset(dest_buffer, 0, copy_amount);
break; break;
@ -508,8 +540,8 @@ void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const voi
switch (page_table.attributes[page_index]) { switch (page_table.attributes[page_index]) {
case PageType::Unmapped: { case PageType::Unmapped: {
LOG_ERROR(HW_Memory, NGLOG_ERROR(HW_Memory,
"unmapped WriteBlock @ 0x%08X (start address = 0x%08X, size = %zu)", "Unmapped WriteBlock @ {:#018X} (start address = {:#018X}, size = {})",
current_vaddr, dest_addr, size); current_vaddr, dest_addr, size);
break; break;
} }
@ -556,7 +588,8 @@ void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const size
switch (page_table.attributes[page_index]) { switch (page_table.attributes[page_index]) {
case PageType::Unmapped: { case PageType::Unmapped: {
LOG_ERROR(HW_Memory, "unmapped ZeroBlock @ 0x%08X (start address = 0x%08X, size = %zu)", NGLOG_ERROR(HW_Memory,
"Unmapped ZeroBlock @ {:#018X} (start address = {#:018X}, size = {})",
current_vaddr, dest_addr, size); current_vaddr, dest_addr, size);
break; break;
} }
@ -596,7 +629,8 @@ void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr,
switch (page_table.attributes[page_index]) { switch (page_table.attributes[page_index]) {
case PageType::Unmapped: { case PageType::Unmapped: {
LOG_ERROR(HW_Memory, "unmapped CopyBlock @ 0x%08X (start address = 0x%08X, size = %zu)", NGLOG_ERROR(HW_Memory,
"Unmapped CopyBlock @ {:#018X} (start address = {:#018X}, size = {})",
current_vaddr, src_addr, size); current_vaddr, src_addr, size);
ZeroBlock(process, dest_addr, copy_amount); ZeroBlock(process, dest_addr, copy_amount);
break; break;
@ -625,6 +659,10 @@ void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr,
} }
} }
void CopyBlock(VAddr dest_addr, VAddr src_addr, size_t size) {
CopyBlock(*Core::CurrentProcess(), dest_addr, src_addr, size);
}
boost::optional<PAddr> TryVirtualToPhysicalAddress(const VAddr addr) { boost::optional<PAddr> TryVirtualToPhysicalAddress(const VAddr addr) {
if (addr == 0) { if (addr == 0) {
return 0; return 0;
@ -646,7 +684,7 @@ boost::optional<PAddr> TryVirtualToPhysicalAddress(const VAddr addr) {
PAddr VirtualToPhysicalAddress(const VAddr addr) { PAddr VirtualToPhysicalAddress(const VAddr addr) {
auto paddr = TryVirtualToPhysicalAddress(addr); auto paddr = TryVirtualToPhysicalAddress(addr);
if (!paddr) { if (!paddr) {
LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x%016" PRIX64, addr); NGLOG_ERROR(HW_Memory, "Unknown virtual address @ {:#018X}", addr);
// To help with debugging, set bit on address so that it's obviously invalid. // To help with debugging, set bit on address so that it's obviously invalid.
return addr | 0x80000000; return addr | 0x80000000;
} }

View file

@ -14,6 +14,7 @@
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include "common/common_types.h" #include "common/common_types.h"
#include "core/memory_hook.h" #include "core/memory_hook.h"
#include "video_core/memory_manager.h"
namespace Kernel { namespace Kernel {
class Process; class Process;
@ -258,7 +259,7 @@ enum class FlushMode {
/** /**
* Mark each page touching the region as cached. * Mark each page touching the region as cached.
*/ */
void RasterizerMarkRegionCached(VAddr start, u64 size, bool cached); void RasterizerMarkRegionCached(Tegra::GPUVAddr start, u64 size, bool cached);
/** /**
* Flushes and invalidates any externally cached rasterizer resources touching the given virtual * Flushes and invalidates any externally cached rasterizer resources touching the given virtual

View file

@ -24,41 +24,18 @@ namespace Tegra {
enum class BufferMethods { enum class BufferMethods {
BindObject = 0, BindObject = 0,
SetGraphMacroCode = 0x45, CountBufferMethods = 0x40,
SetGraphMacroCodeArg = 0x46,
SetGraphMacroEntry = 0x47,
CountBufferMethods = 0x100,
}; };
void GPU::WriteReg(u32 method, u32 subchannel, u32 value, u32 remaining_params) { void GPU::WriteReg(u32 method, u32 subchannel, u32 value, u32 remaining_params) {
LOG_WARNING(HW_GPU, "Processing method %08X on subchannel %u value %08X remaining params %u", NGLOG_WARNING(HW_GPU,
"Processing method {:08X} on subchannel {} value "
"{:08X} remaining params {}",
method, subchannel, value, remaining_params); method, subchannel, value, remaining_params);
if (method == static_cast<u32>(BufferMethods::SetGraphMacroEntry)) {
// Prepare to upload a new macro, reset the upload counter.
LOG_DEBUG(HW_GPU, "Uploading GPU macro %08X", value);
current_macro_entry = value;
current_macro_code.clear();
return;
}
if (method == static_cast<u32>(BufferMethods::SetGraphMacroCodeArg)) {
// Append a new code word to the current macro.
current_macro_code.push_back(value);
// There are no more params remaining, submit the code to the 3D engine.
if (remaining_params == 0) {
maxwell_3d->SubmitMacroCode(current_macro_entry, std::move(current_macro_code));
current_macro_entry = InvalidGraphMacroEntry;
current_macro_code.clear();
}
return;
}
if (method == static_cast<u32>(BufferMethods::BindObject)) { if (method == static_cast<u32>(BufferMethods::BindObject)) {
// Bind the current subchannel to the desired engine id. // Bind the current subchannel to the desired engine id.
LOG_DEBUG(HW_GPU, "Binding subchannel %u to engine %u", subchannel, value); NGLOG_DEBUG(HW_GPU, "Binding subchannel {} to engine {}", subchannel, value);
ASSERT(bound_engines.find(subchannel) == bound_engines.end()); ASSERT(bound_engines.find(subchannel) == bound_engines.end());
bound_engines[subchannel] = static_cast<EngineID>(value); bound_engines[subchannel] = static_cast<EngineID>(value);
return; return;
@ -66,7 +43,7 @@ void GPU::WriteReg(u32 method, u32 subchannel, u32 value, u32 remaining_params)
if (method < static_cast<u32>(BufferMethods::CountBufferMethods)) { if (method < static_cast<u32>(BufferMethods::CountBufferMethods)) {
// TODO(Subv): Research and implement these methods. // TODO(Subv): Research and implement these methods.
LOG_ERROR(HW_GPU, "Special buffer methods other than Bind are not implemented"); NGLOG_ERROR(HW_GPU, "Special buffer methods other than Bind are not implemented");
return; return;
} }
@ -90,11 +67,9 @@ void GPU::WriteReg(u32 method, u32 subchannel, u32 value, u32 remaining_params)
} }
void GPU::ProcessCommandList(GPUVAddr address, u32 size) { void GPU::ProcessCommandList(GPUVAddr address, u32 size) {
// TODO(Subv): PhysicalToVirtualAddress is a misnomer, it converts a GPU VAddr into an const boost::optional<VAddr> head_address = memory_manager->GpuToCpuAddress(address);
// application VAddr. VAddr current_addr = *head_address;
const VAddr head_address = memory_manager->PhysicalToVirtualAddress(address); while (current_addr < *head_address + size * sizeof(CommandHeader)) {
VAddr current_addr = head_address;
while (current_addr < head_address + size * sizeof(CommandHeader)) {
const CommandHeader header = {Memory::Read32(current_addr)}; const CommandHeader header = {Memory::Read32(current_addr)};
current_addr += sizeof(u32); current_addr += sizeof(u32);

View file

@ -2,12 +2,71 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include "core/memory.h"
#include "video_core/engines/fermi_2d.h" #include "video_core/engines/fermi_2d.h"
#include "video_core/textures/decoders.h"
namespace Tegra { namespace Tegra {
namespace Engines { namespace Engines {
void Fermi2D::WriteReg(u32 method, u32 value) {} Fermi2D::Fermi2D(MemoryManager& memory_manager) : memory_manager(memory_manager) {}
void Fermi2D::WriteReg(u32 method, u32 value) {
ASSERT_MSG(method < Regs::NUM_REGS,
"Invalid Fermi2D register, increase the size of the Regs structure");
regs.reg_array[method] = value;
switch (method) {
case FERMI2D_REG_INDEX(trigger): {
HandleSurfaceCopy();
break;
}
}
}
void Fermi2D::HandleSurfaceCopy() {
NGLOG_WARNING(HW_GPU, "Requested a surface copy with operation {}",
static_cast<u32>(regs.operation));
const GPUVAddr source = regs.src.Address();
const GPUVAddr dest = regs.dst.Address();
// TODO(Subv): Only same-format and same-size copies are allowed for now.
ASSERT(regs.src.format == regs.dst.format);
ASSERT(regs.src.width * regs.src.height == regs.dst.width * regs.dst.height);
// TODO(Subv): Only raw copies are implemented.
ASSERT(regs.operation == Regs::Operation::SrcCopy);
const VAddr source_cpu = *memory_manager.GpuToCpuAddress(source);
const VAddr dest_cpu = *memory_manager.GpuToCpuAddress(dest);
u32 src_bytes_per_pixel = RenderTargetBytesPerPixel(regs.src.format);
u32 dst_bytes_per_pixel = RenderTargetBytesPerPixel(regs.dst.format);
if (regs.src.linear == regs.dst.linear) {
// If the input layout and the output layout are the same, just perform a raw copy.
Memory::CopyBlock(dest_cpu, source_cpu,
src_bytes_per_pixel * regs.dst.width * regs.dst.height);
return;
}
u8* src_buffer = Memory::GetPointer(source_cpu);
u8* dst_buffer = Memory::GetPointer(dest_cpu);
if (!regs.src.linear && regs.dst.linear) {
// If the input is tiled and the output is linear, deswizzle the input and copy it over.
Texture::CopySwizzledData(regs.src.width, regs.src.height, src_bytes_per_pixel,
dst_bytes_per_pixel, src_buffer, dst_buffer, true,
regs.src.block_height);
} else {
// If the input is linear and the output is tiled, swizzle the input and copy it over.
Texture::CopySwizzledData(regs.src.width, regs.src.height, src_bytes_per_pixel,
dst_bytes_per_pixel, dst_buffer, src_buffer, false,
regs.dst.block_height);
}
}
} // namespace Engines } // namespace Engines
} // namespace Tegra } // namespace Tegra

View file

@ -4,19 +4,106 @@
#pragma once #pragma once
#include <array>
#include "common/assert.h"
#include "common/bit_field.h"
#include "common/common_funcs.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "video_core/gpu.h"
#include "video_core/memory_manager.h"
namespace Tegra { namespace Tegra {
namespace Engines { namespace Engines {
#define FERMI2D_REG_INDEX(field_name) \
(offsetof(Tegra::Engines::Fermi2D::Regs, field_name) / sizeof(u32))
class Fermi2D final { class Fermi2D final {
public: public:
Fermi2D() = default; explicit Fermi2D(MemoryManager& memory_manager);
~Fermi2D() = default; ~Fermi2D() = default;
/// Write the value to the register identified by method. /// Write the value to the register identified by method.
void WriteReg(u32 method, u32 value); void WriteReg(u32 method, u32 value);
struct Regs {
static constexpr size_t NUM_REGS = 0x258;
struct Surface {
RenderTargetFormat format;
BitField<0, 1, u32> linear;
union {
BitField<0, 4, u32> block_depth;
BitField<4, 4, u32> block_height;
BitField<8, 4, u32> block_width;
}; };
u32 depth;
u32 layer;
u32 pitch;
u32 width;
u32 height;
u32 address_high;
u32 address_low;
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
address_low);
}
};
static_assert(sizeof(Surface) == 0x28, "Surface has incorrect size");
enum class Operation : u32 {
SrcCopyAnd = 0,
ROPAnd = 1,
Blend = 2,
SrcCopy = 3,
ROP = 4,
SrcCopyPremult = 5,
BlendPremult = 6,
};
union {
struct {
INSERT_PADDING_WORDS(0x80);
Surface dst;
INSERT_PADDING_WORDS(2);
Surface src;
INSERT_PADDING_WORDS(0x15);
Operation operation;
INSERT_PADDING_WORDS(0x9);
// TODO(Subv): This is only a guess.
u32 trigger;
INSERT_PADDING_WORDS(0x1A3);
};
std::array<u32, NUM_REGS> reg_array;
};
} regs{};
MemoryManager& memory_manager;
private:
/// Performs the copy from the source surface to the destination surface as configured in the
/// registers.
void HandleSurfaceCopy();
};
#define ASSERT_REG_POSITION(field_name, position) \
static_assert(offsetof(Fermi2D::Regs, field_name) == position * 4, \
"Field " #field_name " has invalid position")
ASSERT_REG_POSITION(dst, 0x80);
ASSERT_REG_POSITION(src, 0x8C);
ASSERT_REG_POSITION(operation, 0xAB);
ASSERT_REG_POSITION(trigger, 0xB5);
#undef ASSERT_REG_POSITION
} // namespace Engines } // namespace Engines
} // namespace Tegra } // namespace Tegra

View file

@ -22,10 +22,6 @@ constexpr u32 MacroRegistersStart = 0xE00;
Maxwell3D::Maxwell3D(MemoryManager& memory_manager) Maxwell3D::Maxwell3D(MemoryManager& memory_manager)
: memory_manager(memory_manager), macro_interpreter(*this) {} : memory_manager(memory_manager), macro_interpreter(*this) {}
void Maxwell3D::SubmitMacroCode(u32 entry, std::vector<u32> code) {
uploaded_macros[entry * 2 + MacroRegistersStart] = std::move(code);
}
void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) { void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) {
auto macro_code = uploaded_macros.find(method); auto macro_code = uploaded_macros.find(method);
// The requested macro must have been uploaded already. // The requested macro must have been uploaded already.
@ -37,9 +33,6 @@ void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) {
} }
void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) { void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
ASSERT_MSG(method < Regs::NUM_REGS,
"Invalid Maxwell3D register, increase the size of the Regs structure");
auto debug_context = Core::System::GetInstance().GetGPUDebugContext(); auto debug_context = Core::System::GetInstance().GetGPUDebugContext();
// It is an error to write to a register other than the current macro's ARG register before it // It is an error to write to a register other than the current macro's ARG register before it
@ -68,6 +61,9 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
return; return;
} }
ASSERT_MSG(method < Regs::NUM_REGS,
"Invalid Maxwell3D register, increase the size of the Regs structure");
if (debug_context) { if (debug_context) {
debug_context->OnEvent(Tegra::DebugContext::Event::MaxwellCommandLoaded, nullptr); debug_context->OnEvent(Tegra::DebugContext::Event::MaxwellCommandLoaded, nullptr);
} }
@ -75,6 +71,10 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
regs.reg_array[method] = value; regs.reg_array[method] = value;
switch (method) { switch (method) {
case MAXWELL3D_REG_INDEX(macros.data): {
ProcessMacroUpload(value);
break;
}
case MAXWELL3D_REG_INDEX(code_address.code_address_high): case MAXWELL3D_REG_INDEX(code_address.code_address_high):
case MAXWELL3D_REG_INDEX(code_address.code_address_low): { 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 // Note: For some reason games (like Puyo Puyo Tetris) seem to write 0 to the CODE_ADDRESS
@ -141,17 +141,48 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
} }
} }
void Maxwell3D::ProcessMacroUpload(u32 data) {
// Store the uploaded macro code to interpret them when they're called.
auto& macro = uploaded_macros[regs.macros.entry * 2 + MacroRegistersStart];
macro.push_back(data);
}
void Maxwell3D::ProcessQueryGet() { void Maxwell3D::ProcessQueryGet() {
GPUVAddr sequence_address = regs.query.QueryAddress(); GPUVAddr sequence_address = regs.query.QueryAddress();
// Since the sequence address is given as a GPU VAddr, we have to convert it to an application // Since the sequence address is given as a GPU VAddr, we have to convert it to an application
// VAddr before writing. // VAddr before writing.
VAddr address = memory_manager.PhysicalToVirtualAddress(sequence_address); boost::optional<VAddr> address = memory_manager.GpuToCpuAddress(sequence_address);
// TODO(Subv): Support the other query units.
ASSERT_MSG(regs.query.query_get.unit == Regs::QueryUnit::Crop,
"Units other than CROP are unimplemented");
ASSERT_MSG(regs.query.query_get.short_query,
"Writing the entire query result structure is unimplemented");
u32 value = Memory::Read32(*address);
u32 result = 0;
// TODO(Subv): Support the other query variables
switch (regs.query.query_get.select) {
case Regs::QuerySelect::Zero:
result = 0;
break;
default:
UNIMPLEMENTED_MSG("Unimplemented query select type %u",
static_cast<u32>(regs.query.query_get.select.Value()));
}
// TODO(Subv): Research and implement how query sync conditions work.
switch (regs.query.query_get.mode) { switch (regs.query.query_get.mode) {
case Regs::QueryMode::Write: { case Regs::QueryMode::Write:
case Regs::QueryMode::Write2: {
// Write the current query sequence to the sequence address. // Write the current query sequence to the sequence address.
u32 sequence = regs.query.query_sequence; u32 sequence = regs.query.query_sequence;
Memory::Write32(address, sequence); Memory::Write32(*address, sequence);
// TODO(Subv): Write the proper query response structure to the address when not using short
// mode.
break; break;
} }
default: default:
@ -161,8 +192,8 @@ void Maxwell3D::ProcessQueryGet() {
} }
void Maxwell3D::DrawArrays() { void Maxwell3D::DrawArrays() {
LOG_DEBUG(HW_GPU, "called, topology=%d, count=%d", regs.draw.topology.Value(), NGLOG_DEBUG(HW_GPU, "called, topology={}, count={}",
regs.vertex_buffer.count); static_cast<u32>(regs.draw.topology.Value()), regs.vertex_buffer.count);
ASSERT_MSG(!(regs.index_array.count && regs.vertex_buffer.count), "Both indexed and direct?"); ASSERT_MSG(!(regs.index_array.count && regs.vertex_buffer.count), "Both indexed and direct?");
auto debug_context = Core::System::GetInstance().GetGPUDebugContext(); auto debug_context = Core::System::GetInstance().GetGPUDebugContext();
@ -200,10 +231,10 @@ void Maxwell3D::ProcessCBData(u32 value) {
// Don't allow writing past the end of the buffer. // Don't allow writing past the end of the buffer.
ASSERT(regs.const_buffer.cb_pos + sizeof(u32) <= regs.const_buffer.cb_size); ASSERT(regs.const_buffer.cb_pos + sizeof(u32) <= regs.const_buffer.cb_size);
VAddr address = boost::optional<VAddr> address =
memory_manager.PhysicalToVirtualAddress(buffer_address + regs.const_buffer.cb_pos); memory_manager.GpuToCpuAddress(buffer_address + regs.const_buffer.cb_pos);
Memory::Write32(address, value); Memory::Write32(*address, value);
// Increment the current buffer position. // Increment the current buffer position.
regs.const_buffer.cb_pos = regs.const_buffer.cb_pos + 4; regs.const_buffer.cb_pos = regs.const_buffer.cb_pos + 4;
@ -213,10 +244,10 @@ Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const {
GPUVAddr tic_base_address = regs.tic.TICAddress(); GPUVAddr tic_base_address = regs.tic.TICAddress();
GPUVAddr tic_address_gpu = tic_base_address + tic_index * sizeof(Texture::TICEntry); GPUVAddr tic_address_gpu = tic_base_address + tic_index * sizeof(Texture::TICEntry);
VAddr tic_address_cpu = memory_manager.PhysicalToVirtualAddress(tic_address_gpu); boost::optional<VAddr> tic_address_cpu = memory_manager.GpuToCpuAddress(tic_address_gpu);
Texture::TICEntry tic_entry; Texture::TICEntry tic_entry;
Memory::ReadBlock(tic_address_cpu, &tic_entry, sizeof(Texture::TICEntry)); Memory::ReadBlock(*tic_address_cpu, &tic_entry, sizeof(Texture::TICEntry));
ASSERT_MSG(tic_entry.header_version == Texture::TICHeaderVersion::BlockLinear || ASSERT_MSG(tic_entry.header_version == Texture::TICHeaderVersion::BlockLinear ||
tic_entry.header_version == Texture::TICHeaderVersion::Pitch, tic_entry.header_version == Texture::TICHeaderVersion::Pitch,
@ -243,10 +274,10 @@ Texture::TSCEntry Maxwell3D::GetTSCEntry(u32 tsc_index) const {
GPUVAddr tsc_base_address = regs.tsc.TSCAddress(); GPUVAddr tsc_base_address = regs.tsc.TSCAddress();
GPUVAddr tsc_address_gpu = tsc_base_address + tsc_index * sizeof(Texture::TSCEntry); GPUVAddr tsc_address_gpu = tsc_base_address + tsc_index * sizeof(Texture::TSCEntry);
VAddr tsc_address_cpu = memory_manager.PhysicalToVirtualAddress(tsc_address_gpu); boost::optional<VAddr> tsc_address_cpu = memory_manager.GpuToCpuAddress(tsc_address_gpu);
Texture::TSCEntry tsc_entry; Texture::TSCEntry tsc_entry;
Memory::ReadBlock(tsc_address_cpu, &tsc_entry, sizeof(Texture::TSCEntry)); Memory::ReadBlock(*tsc_address_cpu, &tsc_entry, sizeof(Texture::TSCEntry));
return tsc_entry; return tsc_entry;
} }
@ -268,7 +299,7 @@ std::vector<Texture::FullTextureInfo> Maxwell3D::GetStageTextures(Regs::ShaderSt
current_texture < tex_info_buffer_end; current_texture += sizeof(Texture::TextureHandle)) { current_texture < tex_info_buffer_end; current_texture += sizeof(Texture::TextureHandle)) {
Texture::TextureHandle tex_handle{ Texture::TextureHandle tex_handle{
Memory::Read32(memory_manager.PhysicalToVirtualAddress(current_texture))}; Memory::Read32(*memory_manager.GpuToCpuAddress(current_texture))};
Texture::FullTextureInfo tex_info{}; Texture::FullTextureInfo tex_info{};
// TODO(Subv): Use the shader to determine which textures are actually accessed. // TODO(Subv): Use the shader to determine which textures are actually accessed.

View file

@ -31,7 +31,7 @@ public:
/// Register structure of the Maxwell3D engine. /// Register structure of the Maxwell3D engine.
/// TODO(Subv): This structure will need to be made bigger as more registers are discovered. /// TODO(Subv): This structure will need to be made bigger as more registers are discovered.
struct Regs { struct Regs {
static constexpr size_t NUM_REGS = 0xE36; static constexpr size_t NUM_REGS = 0xE00;
static constexpr size_t NumRenderTargets = 8; static constexpr size_t NumRenderTargets = 8;
static constexpr size_t NumViewports = 16; static constexpr size_t NumViewports = 16;
@ -46,6 +46,29 @@ public:
enum class QueryMode : u32 { enum class QueryMode : u32 {
Write = 0, Write = 0,
Sync = 1, Sync = 1,
// TODO(Subv): It is currently unknown what the difference between method 2 and method 0
// is.
Write2 = 2,
};
enum class QueryUnit : u32 {
VFetch = 1,
VP = 2,
Rast = 4,
StrmOut = 5,
GP = 6,
ZCull = 7,
Prop = 10,
Crop = 15,
};
enum class QuerySelect : u32 {
Zero = 0,
};
enum class QuerySyncCondition : u32 {
NotEqual = 0,
GreaterThan = 1,
}; };
enum class ShaderProgram : u32 { enum class ShaderProgram : u32 {
@ -299,7 +322,15 @@ public:
union { union {
struct { struct {
INSERT_PADDING_WORDS(0x200); INSERT_PADDING_WORDS(0x45);
struct {
INSERT_PADDING_WORDS(1);
u32 data;
u32 entry;
} macros;
INSERT_PADDING_WORDS(0x1B8);
struct { struct {
u32 address_high; u32 address_high;
@ -476,7 +507,10 @@ public:
u32 raw; u32 raw;
BitField<0, 2, QueryMode> mode; BitField<0, 2, QueryMode> mode;
BitField<4, 1, u32> fence; BitField<4, 1, u32> fence;
BitField<12, 4, u32> unit; BitField<12, 4, QueryUnit> unit;
BitField<16, 1, QuerySyncCondition> sync_cond;
BitField<23, 5, QuerySelect> select;
BitField<28, 1, u32> short_query;
} query_get; } query_get;
GPUVAddr QueryAddress() const { GPUVAddr QueryAddress() const {
@ -500,6 +534,11 @@ public:
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(start_high) << 32) | return static_cast<GPUVAddr>((static_cast<GPUVAddr>(start_high) << 32) |
start_low); start_low);
} }
bool IsEnabled() const {
return enable != 0 && StartAddress() != 0;
}
} vertex_array[NumVertexArrays]; } vertex_array[NumVertexArrays];
Blend blend; Blend blend;
@ -574,7 +613,7 @@ public:
u32 size[MaxShaderStage]; u32 size[MaxShaderStage];
} tex_info_buffers; } tex_info_buffers;
INSERT_PADDING_WORDS(0x102); INSERT_PADDING_WORDS(0xCC);
}; };
std::array<u32, NUM_REGS> reg_array; std::array<u32, NUM_REGS> reg_array;
}; };
@ -606,9 +645,6 @@ public:
/// Write the value to the register identified by method. /// Write the value to the register identified by method.
void WriteReg(u32 method, u32 value, u32 remaining_params); void WriteReg(u32 method, u32 value, u32 remaining_params);
/// Uploads the code for a GPU macro program associated with the specified entry.
void SubmitMacroCode(u32 entry, std::vector<u32> code);
/// Returns a list of enabled textures for the specified shader stage. /// Returns a list of enabled textures for the specified shader stage.
std::vector<Texture::FullTextureInfo> GetStageTextures(Regs::ShaderStage stage) const; std::vector<Texture::FullTextureInfo> GetStageTextures(Regs::ShaderStage stage) const;
@ -639,6 +675,9 @@ private:
*/ */
void CallMacroMethod(u32 method, std::vector<u32> parameters); void CallMacroMethod(u32 method, std::vector<u32> parameters);
/// Handles writes to the macro uploading registers.
void ProcessMacroUpload(u32 data);
/// Handles a write to the QUERY_GET register. /// Handles a write to the QUERY_GET register.
void ProcessQueryGet(); void ProcessQueryGet();
@ -656,6 +695,7 @@ private:
static_assert(offsetof(Maxwell3D::Regs, field_name) == position * 4, \ static_assert(offsetof(Maxwell3D::Regs, field_name) == position * 4, \
"Field " #field_name " has invalid position") "Field " #field_name " has invalid position")
ASSERT_REG_POSITION(macros, 0x45);
ASSERT_REG_POSITION(rt, 0x200); ASSERT_REG_POSITION(rt, 0x200);
ASSERT_REG_POSITION(viewport_transform[0], 0x280); ASSERT_REG_POSITION(viewport_transform[0], 0x280);
ASSERT_REG_POSITION(viewport, 0x300); ASSERT_REG_POSITION(viewport, 0x300);

View file

@ -214,6 +214,20 @@ union Instruction {
BitField<56, 1, u64> neg_b; BitField<56, 1, u64> neg_b;
} fsetp; } fsetp;
union {
BitField<39, 3, u64> pred39;
BitField<42, 1, u64> neg_pred;
BitField<43, 1, u64> neg_a;
BitField<44, 1, u64> abs_b;
BitField<45, 2, PredOperation> op;
BitField<48, 4, PredCondition> cond;
BitField<53, 1, u64> neg_b;
BitField<54, 1, u64> abs_a;
BitField<52, 1, u64> bf;
BitField<55, 1, u64> ftz;
BitField<56, 1, u64> neg_imm;
} fset;
BitField<61, 1, u64> is_b_imm; BitField<61, 1, u64> is_b_imm;
BitField<60, 1, u64> is_b_gpr; BitField<60, 1, u64> is_b_gpr;
BitField<59, 1, u64> is_c_gpr; BitField<59, 1, u64> is_c_gpr;
@ -261,6 +275,9 @@ public:
I2F_C, I2F_C,
I2F_R, I2F_R,
I2F_IMM, I2F_IMM,
I2I_C,
I2I_R,
I2I_IMM,
LOP32I, LOP32I,
MOV_C, MOV_C,
MOV_R, MOV_R,
@ -272,6 +289,9 @@ public:
FSETP_C, // Set Predicate FSETP_C, // Set Predicate
FSETP_R, FSETP_R,
FSETP_IMM, FSETP_IMM,
FSET_C,
FSET_R,
FSET_IMM,
ISETP_C, ISETP_C,
ISETP_IMM, ISETP_IMM,
ISETP_R, ISETP_R,
@ -283,8 +303,9 @@ public:
Ffma, Ffma,
Flow, Flow,
Memory, Memory,
FloatPredicate, FloatSet,
IntegerPredicate, FloatSetPredicate,
IntegerSetPredicate,
Unknown, Unknown,
}; };
@ -409,6 +430,9 @@ private:
INST("0100110010111---", Id::I2F_C, Type::Arithmetic, "I2F_C"), INST("0100110010111---", Id::I2F_C, Type::Arithmetic, "I2F_C"),
INST("0101110010111---", Id::I2F_R, Type::Arithmetic, "I2F_R"), INST("0101110010111---", Id::I2F_R, Type::Arithmetic, "I2F_R"),
INST("0011100-10111---", Id::I2F_IMM, Type::Arithmetic, "I2F_IMM"), INST("0011100-10111---", Id::I2F_IMM, Type::Arithmetic, "I2F_IMM"),
INST("0100110011100---", Id::I2I_C, Type::Arithmetic, "I2I_C"),
INST("0101110011100---", Id::I2I_R, Type::Arithmetic, "I2I_R"),
INST("01110001-1000---", Id::I2I_IMM, Type::Arithmetic, "I2I_IMM"),
INST("000001----------", Id::LOP32I, Type::Arithmetic, "LOP32I"), INST("000001----------", Id::LOP32I, Type::Arithmetic, "LOP32I"),
INST("0100110010011---", Id::MOV_C, Type::Arithmetic, "MOV_C"), INST("0100110010011---", Id::MOV_C, Type::Arithmetic, "MOV_C"),
INST("0101110010011---", Id::MOV_R, Type::Arithmetic, "MOV_R"), INST("0101110010011---", Id::MOV_R, Type::Arithmetic, "MOV_R"),
@ -417,12 +441,15 @@ private:
INST("0100110000101---", Id::SHR_C, Type::Arithmetic, "SHR_C"), INST("0100110000101---", Id::SHR_C, Type::Arithmetic, "SHR_C"),
INST("0101110000101---", Id::SHR_R, Type::Arithmetic, "SHR_R"), INST("0101110000101---", Id::SHR_R, Type::Arithmetic, "SHR_R"),
INST("0011100-00101---", Id::SHR_IMM, Type::Arithmetic, "SHR_IMM"), INST("0011100-00101---", Id::SHR_IMM, Type::Arithmetic, "SHR_IMM"),
INST("010010111011----", Id::FSETP_C, Type::FloatPredicate, "FSETP_C"), INST("01011000--------", Id::FSET_R, Type::FloatSet, "FSET_R"),
INST("010110111011----", Id::FSETP_R, Type::FloatPredicate, "FSETP_R"), INST("0100100---------", Id::FSET_C, Type::FloatSet, "FSET_C"),
INST("0011011-1011----", Id::FSETP_IMM, Type::FloatPredicate, "FSETP_IMM"), INST("0011000---------", Id::FSET_IMM, Type::FloatSet, "FSET_IMM"),
INST("010010110110----", Id::ISETP_C, Type::IntegerPredicate, "ISETP_C"), INST("010010111011----", Id::FSETP_C, Type::FloatSetPredicate, "FSETP_C"),
INST("010110110110----", Id::ISETP_R, Type::IntegerPredicate, "ISETP_R"), INST("010110111011----", Id::FSETP_R, Type::FloatSetPredicate, "FSETP_R"),
INST("0011011-0110----", Id::ISETP_IMM, Type::IntegerPredicate, "ISETP_IMM"), INST("0011011-1011----", Id::FSETP_IMM, Type::FloatSetPredicate, "FSETP_IMM"),
INST("010010110110----", Id::ISETP_C, Type::IntegerSetPredicate, "ISETP_C"),
INST("010110110110----", Id::ISETP_R, Type::IntegerSetPredicate, "ISETP_R"),
INST("0011011-0110----", Id::ISETP_IMM, Type::IntegerSetPredicate, "ISETP_IMM"),
}; };
#undef INST #undef INST
std::stable_sort(table.begin(), table.end(), [](const auto& a, const auto& b) { std::stable_sort(table.begin(), table.end(), [](const auto& a, const auto& b) {

View file

@ -12,7 +12,7 @@ namespace Tegra {
GPU::GPU() { GPU::GPU() {
memory_manager = std::make_unique<MemoryManager>(); memory_manager = std::make_unique<MemoryManager>();
maxwell_3d = std::make_unique<Engines::Maxwell3D>(*memory_manager); maxwell_3d = std::make_unique<Engines::Maxwell3D>(*memory_manager);
fermi_2d = std::make_unique<Engines::Fermi2D>(); fermi_2d = std::make_unique<Engines::Fermi2D>(*memory_manager);
maxwell_compute = std::make_unique<Engines::MaxwellCompute>(); maxwell_compute = std::make_unique<Engines::MaxwellCompute>();
} }
@ -22,4 +22,16 @@ const Tegra::Engines::Maxwell3D& GPU::Get3DEngine() const {
return *maxwell_3d; return *maxwell_3d;
} }
u32 RenderTargetBytesPerPixel(RenderTargetFormat format) {
ASSERT(format != RenderTargetFormat::NONE);
switch (format) {
case RenderTargetFormat::RGBA8_UNORM:
case RenderTargetFormat::RGB10_A2_UNORM:
return 4;
default:
UNIMPLEMENTED_MSG("Unimplemented render target format %u", static_cast<u32>(format));
}
}
} // namespace Tegra } // namespace Tegra

View file

@ -21,6 +21,9 @@ enum class RenderTargetFormat : u32 {
RGBA8_SRGB = 0xD6, RGBA8_SRGB = 0xD6,
}; };
/// Returns the number of bytes per pixel of each rendertarget format.
u32 RenderTargetBytesPerPixel(RenderTargetFormat format);
class DebugContext; class DebugContext;
/** /**
@ -86,8 +89,6 @@ public:
} }
private: private:
static constexpr u32 InvalidGraphMacroEntry = 0xFFFFFFFF;
/// Writes a single register in the engine bound to the specified subchannel /// Writes a single register in the engine bound to the specified subchannel
void WriteReg(u32 method, u32 subchannel, u32 value, u32 remaining_params); void WriteReg(u32 method, u32 subchannel, u32 value, u32 remaining_params);
@ -100,11 +101,6 @@ private:
std::unique_ptr<Engines::Fermi2D> fermi_2d; std::unique_ptr<Engines::Fermi2D> fermi_2d;
/// Compute engine /// Compute engine
std::unique_ptr<Engines::MaxwellCompute> maxwell_compute; std::unique_ptr<Engines::MaxwellCompute> maxwell_compute;
/// Entry of the macro that is currently being uploaded
u32 current_macro_entry = InvalidGraphMacroEntry;
/// Code being uploaded for the current macro
std::vector<u32> current_macro_code;
}; };
} // namespace Tegra } // namespace Tegra

View file

@ -2,109 +2,118 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include "common/alignment.h"
#include "common/assert.h" #include "common/assert.h"
#include "video_core/memory_manager.h" #include "video_core/memory_manager.h"
namespace Tegra { namespace Tegra {
PAddr MemoryManager::AllocateSpace(u64 size, u64 align) { GPUVAddr MemoryManager::AllocateSpace(u64 size, u64 align) {
boost::optional<PAddr> paddr = FindFreeBlock(size, align); boost::optional<GPUVAddr> gpu_addr = FindFreeBlock(size, align);
ASSERT(paddr); ASSERT(gpu_addr);
for (u64 offset = 0; offset < size; offset += Memory::PAGE_SIZE) { for (u64 offset = 0; offset < size; offset += PAGE_SIZE) {
PageSlot(*paddr + offset) = static_cast<u64>(PageStatus::Allocated); ASSERT(PageSlot(*gpu_addr + offset) == static_cast<u64>(PageStatus::Unmapped));
PageSlot(*gpu_addr + offset) = static_cast<u64>(PageStatus::Allocated);
} }
return *paddr; return *gpu_addr;
} }
PAddr MemoryManager::AllocateSpace(PAddr paddr, u64 size, u64 align) { GPUVAddr MemoryManager::AllocateSpace(GPUVAddr gpu_addr, u64 size, u64 align) {
for (u64 offset = 0; offset < size; offset += Memory::PAGE_SIZE) { for (u64 offset = 0; offset < size; offset += PAGE_SIZE) {
if (IsPageMapped(paddr + offset)) { ASSERT(PageSlot(gpu_addr + offset) == static_cast<u64>(PageStatus::Unmapped));
return AllocateSpace(size, align); PageSlot(gpu_addr + offset) = static_cast<u64>(PageStatus::Allocated);
}
} }
for (u64 offset = 0; offset < size; offset += Memory::PAGE_SIZE) { return gpu_addr;
PageSlot(paddr + offset) = static_cast<u64>(PageStatus::Allocated);
} }
return paddr; GPUVAddr MemoryManager::MapBufferEx(VAddr cpu_addr, u64 size) {
boost::optional<GPUVAddr> gpu_addr = FindFreeBlock(size, PAGE_SIZE);
ASSERT(gpu_addr);
for (u64 offset = 0; offset < size; offset += PAGE_SIZE) {
ASSERT(PageSlot(*gpu_addr + offset) == static_cast<u64>(PageStatus::Unmapped));
PageSlot(*gpu_addr + offset) = cpu_addr + offset;
} }
PAddr MemoryManager::MapBufferEx(VAddr vaddr, u64 size) { MappedRegion region{cpu_addr, *gpu_addr, size};
vaddr &= ~Memory::PAGE_MASK; mapped_regions.push_back(region);
boost::optional<PAddr> paddr = FindFreeBlock(size); return *gpu_addr;
ASSERT(paddr);
for (u64 offset = 0; offset < size; offset += Memory::PAGE_SIZE) {
PageSlot(*paddr + offset) = vaddr + offset;
} }
return *paddr; GPUVAddr MemoryManager::MapBufferEx(VAddr cpu_addr, GPUVAddr gpu_addr, u64 size) {
ASSERT((gpu_addr & PAGE_MASK) == 0);
for (u64 offset = 0; offset < size; offset += PAGE_SIZE) {
ASSERT(PageSlot(gpu_addr + offset) == static_cast<u64>(PageStatus::Allocated));
PageSlot(gpu_addr + offset) = cpu_addr + offset;
} }
PAddr MemoryManager::MapBufferEx(VAddr vaddr, PAddr paddr, u64 size) { MappedRegion region{cpu_addr, gpu_addr, size};
vaddr &= ~Memory::PAGE_MASK; mapped_regions.push_back(region);
paddr &= ~Memory::PAGE_MASK;
for (u64 offset = 0; offset < size; offset += Memory::PAGE_SIZE) { return gpu_addr;
if (PageSlot(paddr + offset) != static_cast<u64>(PageStatus::Allocated)) {
return MapBufferEx(vaddr, size);
}
} }
for (u64 offset = 0; offset < size; offset += Memory::PAGE_SIZE) { boost::optional<GPUVAddr> MemoryManager::FindFreeBlock(u64 size, u64 align) {
PageSlot(paddr + offset) = vaddr + offset; GPUVAddr gpu_addr = 0;
} u64 free_space = 0;
align = (align + PAGE_MASK) & ~PAGE_MASK;
return paddr; while (gpu_addr + free_space < MAX_ADDRESS) {
} if (!IsPageMapped(gpu_addr + free_space)) {
free_space += PAGE_SIZE;
boost::optional<PAddr> MemoryManager::FindFreeBlock(u64 size, u64 align) {
PAddr paddr{};
u64 free_space{};
align = (align + Memory::PAGE_MASK) & ~Memory::PAGE_MASK;
while (paddr + free_space < MAX_ADDRESS) {
if (!IsPageMapped(paddr + free_space)) {
free_space += Memory::PAGE_SIZE;
if (free_space >= size) { if (free_space >= size) {
return paddr; return gpu_addr;
} }
} else { } else {
paddr += free_space + Memory::PAGE_SIZE; gpu_addr += free_space + PAGE_SIZE;
free_space = 0; free_space = 0;
const u64 remainder{paddr % align}; gpu_addr = Common::AlignUp(gpu_addr, align);
if (!remainder) {
paddr = (paddr - remainder) + align;
}
} }
} }
return {}; return {};
} }
VAddr MemoryManager::PhysicalToVirtualAddress(PAddr paddr) { boost::optional<VAddr> MemoryManager::GpuToCpuAddress(GPUVAddr gpu_addr) {
VAddr base_addr = PageSlot(paddr); VAddr base_addr = PageSlot(gpu_addr);
ASSERT(base_addr != static_cast<u64>(PageStatus::Unmapped)); ASSERT(base_addr != static_cast<u64>(PageStatus::Unmapped));
return base_addr + (paddr & Memory::PAGE_MASK);
if (base_addr == static_cast<u64>(PageStatus::Allocated)) {
return {};
} }
bool MemoryManager::IsPageMapped(PAddr paddr) { return base_addr + (gpu_addr & PAGE_MASK);
return PageSlot(paddr) != static_cast<u64>(PageStatus::Unmapped);
} }
VAddr& MemoryManager::PageSlot(PAddr paddr) { std::vector<GPUVAddr> MemoryManager::CpuToGpuAddress(VAddr cpu_addr) const {
auto& block = page_table[(paddr >> (Memory::PAGE_BITS + PAGE_TABLE_BITS)) & PAGE_TABLE_MASK]; std::vector<GPUVAddr> results;
for (const auto& region : mapped_regions) {
if (cpu_addr >= region.cpu_addr && cpu_addr < (region.cpu_addr + region.size)) {
u64 offset = cpu_addr - region.cpu_addr;
results.push_back(region.gpu_addr + offset);
}
}
return results;
}
bool MemoryManager::IsPageMapped(GPUVAddr gpu_addr) {
return PageSlot(gpu_addr) != static_cast<u64>(PageStatus::Unmapped);
}
VAddr& MemoryManager::PageSlot(GPUVAddr gpu_addr) {
auto& block = page_table[(gpu_addr >> (PAGE_BITS + PAGE_TABLE_BITS)) & PAGE_TABLE_MASK];
if (!block) { if (!block) {
block = std::make_unique<PageBlock>(); block = std::make_unique<PageBlock>();
for (unsigned index = 0; index < PAGE_BLOCK_SIZE; index++) { for (unsigned index = 0; index < PAGE_BLOCK_SIZE; index++) {
(*block)[index] = static_cast<u64>(PageStatus::Unmapped); (*block)[index] = static_cast<u64>(PageStatus::Unmapped);
} }
} }
return (*block)[(paddr >> Memory::PAGE_BITS) & PAGE_BLOCK_MASK]; return (*block)[(gpu_addr >> PAGE_BITS) & PAGE_BLOCK_MASK];
} }
} // namespace Tegra } // namespace Tegra

View file

@ -6,8 +6,11 @@
#include <array> #include <array>
#include <memory> #include <memory>
#include <vector>
#include <boost/optional.hpp>
#include "common/common_types.h" #include "common/common_types.h"
#include "core/memory.h"
namespace Tegra { namespace Tegra {
@ -18,16 +21,21 @@ class MemoryManager final {
public: public:
MemoryManager() = default; MemoryManager() = default;
PAddr AllocateSpace(u64 size, u64 align); GPUVAddr AllocateSpace(u64 size, u64 align);
PAddr AllocateSpace(PAddr paddr, u64 size, u64 align); GPUVAddr AllocateSpace(GPUVAddr gpu_addr, u64 size, u64 align);
PAddr MapBufferEx(VAddr vaddr, u64 size); GPUVAddr MapBufferEx(VAddr cpu_addr, u64 size);
PAddr MapBufferEx(VAddr vaddr, PAddr paddr, u64 size); GPUVAddr MapBufferEx(VAddr cpu_addr, GPUVAddr gpu_addr, u64 size);
VAddr PhysicalToVirtualAddress(PAddr paddr); boost::optional<VAddr> GpuToCpuAddress(GPUVAddr gpu_addr);
std::vector<GPUVAddr> CpuToGpuAddress(VAddr cpu_addr) const;
static constexpr u64 PAGE_BITS = 16;
static constexpr u64 PAGE_SIZE = 1 << PAGE_BITS;
static constexpr u64 PAGE_MASK = PAGE_SIZE - 1;
private: private:
boost::optional<PAddr> FindFreeBlock(u64 size, u64 align = 1); boost::optional<GPUVAddr> FindFreeBlock(u64 size, u64 align = 1);
bool IsPageMapped(PAddr paddr); bool IsPageMapped(GPUVAddr gpu_addr);
VAddr& PageSlot(PAddr paddr); VAddr& PageSlot(GPUVAddr gpu_addr);
enum class PageStatus : u64 { enum class PageStatus : u64 {
Unmapped = 0xFFFFFFFFFFFFFFFFULL, Unmapped = 0xFFFFFFFFFFFFFFFFULL,
@ -35,7 +43,7 @@ private:
}; };
static constexpr u64 MAX_ADDRESS{0x10000000000ULL}; static constexpr u64 MAX_ADDRESS{0x10000000000ULL};
static constexpr u64 PAGE_TABLE_BITS{14}; static constexpr u64 PAGE_TABLE_BITS{10};
static constexpr u64 PAGE_TABLE_SIZE{1 << PAGE_TABLE_BITS}; static constexpr u64 PAGE_TABLE_SIZE{1 << PAGE_TABLE_BITS};
static constexpr u64 PAGE_TABLE_MASK{PAGE_TABLE_SIZE - 1}; static constexpr u64 PAGE_TABLE_MASK{PAGE_TABLE_SIZE - 1};
static constexpr u64 PAGE_BLOCK_BITS{14}; static constexpr u64 PAGE_BLOCK_BITS{14};
@ -44,6 +52,14 @@ private:
using PageBlock = std::array<VAddr, PAGE_BLOCK_SIZE>; using PageBlock = std::array<VAddr, PAGE_BLOCK_SIZE>;
std::array<std::unique_ptr<PageBlock>, PAGE_TABLE_SIZE> page_table{}; std::array<std::unique_ptr<PageBlock>, PAGE_TABLE_SIZE> page_table{};
struct MappedRegion {
VAddr cpu_addr;
GPUVAddr gpu_addr;
u64 size;
};
std::vector<MappedRegion> mapped_regions;
}; };
} // namespace Tegra } // namespace Tegra

View file

@ -6,6 +6,7 @@
#include "common/common_types.h" #include "common/common_types.h"
#include "video_core/gpu.h" #include "video_core/gpu.h"
#include "video_core/memory_manager.h"
struct ScreenInfo; struct ScreenInfo;
@ -25,14 +26,14 @@ public:
virtual void FlushAll() = 0; virtual void FlushAll() = 0;
/// Notify rasterizer that any caches of the specified region should be flushed to Switch memory /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
virtual void FlushRegion(VAddr addr, u64 size) = 0; virtual void FlushRegion(Tegra::GPUVAddr addr, u64 size) = 0;
/// Notify rasterizer that any caches of the specified region should be invalidated /// Notify rasterizer that any caches of the specified region should be invalidated
virtual void InvalidateRegion(VAddr addr, u64 size) = 0; virtual void InvalidateRegion(Tegra::GPUVAddr addr, u64 size) = 0;
/// Notify rasterizer that any caches of the specified region should be flushed to Switch memory /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
/// and invalidated /// and invalidated
virtual void FlushAndInvalidateRegion(VAddr addr, u64 size) = 0; virtual void FlushAndInvalidateRegion(Tegra::GPUVAddr addr, u64 size) = 0;
/// Attempt to use a faster method to perform a display transfer with is_texture_copy = 0 /// Attempt to use a faster method to perform a display transfer with is_texture_copy = 0
virtual bool AccelerateDisplayTransfer(const void* config) { virtual bool AccelerateDisplayTransfer(const void* config) {

View file

@ -116,7 +116,7 @@ RasterizerOpenGL::RasterizerOpenGL() {
glEnable(GL_BLEND); glEnable(GL_BLEND);
LOG_CRITICAL(Render_OpenGL, "Sync fixed function OpenGL state here!"); NGLOG_CRITICAL(Render_OpenGL, "Sync fixed function OpenGL state here!");
} }
RasterizerOpenGL::~RasterizerOpenGL() { RasterizerOpenGL::~RasterizerOpenGL() {
@ -127,7 +127,8 @@ RasterizerOpenGL::~RasterizerOpenGL() {
} }
} }
void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset) { std::pair<u8*, GLintptr> RasterizerOpenGL::SetupVertexArrays(u8* array_ptr,
GLintptr buffer_offset) {
MICROPROFILE_SCOPE(OpenGL_VAO); MICROPROFILE_SCOPE(OpenGL_VAO);
const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs; const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
const auto& memory_manager = Core::System().GetInstance().GPU().memory_manager; const auto& memory_manager = Core::System().GetInstance().GPU().memory_manager;
@ -136,43 +137,58 @@ void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset) {
state.draw.vertex_buffer = stream_buffer->GetHandle(); state.draw.vertex_buffer = stream_buffer->GetHandle();
state.Apply(); state.Apply();
// TODO(bunnei): Add support for 1+ vertex arrays // Upload all guest vertex arrays sequentially to our buffer
const auto& vertex_array{regs.vertex_array[0]}; for (u32 index = 0; index < Maxwell::NumVertexArrays; ++index) {
const auto& vertex_array_limit{regs.vertex_array_limit[0]}; const auto& vertex_array = regs.vertex_array[index];
ASSERT_MSG(vertex_array.enable, "vertex array 0 is disabled?"); if (!vertex_array.IsEnabled())
ASSERT_MSG(!vertex_array.divisor, "vertex array 0 divisor is unimplemented!"); continue;
for (unsigned index = 1; index < Maxwell::NumVertexArrays; ++index) {
ASSERT_MSG(!regs.vertex_array[index].enable, "vertex array %d is unimplemented!", index); const Tegra::GPUVAddr start = vertex_array.StartAddress();
const Tegra::GPUVAddr end = regs.vertex_array_limit[index].LimitAddress();
ASSERT(end > start);
u64 size = end - start + 1;
// Copy vertex array data
res_cache.FlushRegion(start, size, nullptr);
Memory::ReadBlock(*memory_manager->GpuToCpuAddress(start), array_ptr, size);
// Bind the vertex array to the buffer at the current offset.
glBindVertexBuffer(index, stream_buffer->GetHandle(), buffer_offset, vertex_array.stride);
ASSERT_MSG(vertex_array.divisor == 0, "Vertex buffer divisor unimplemented");
array_ptr += size;
buffer_offset += size;
} }
// Use the vertex array as-is, assumes that the data is formatted correctly for OpenGL. // Use the vertex array as-is, assumes that the data is formatted correctly for OpenGL.
// Enables the first 16 vertex attributes always, as we don't know which ones are actually used // Enables the first 16 vertex attributes always, as we don't know which ones are actually used
// until shader time. Note, Tegra technically supports 32, but we're cappinig this to 16 for now // until shader time. Note, Tegra technically supports 32, but we're capping this to 16 for now
// to avoid OpenGL errors. // to avoid OpenGL errors.
// TODO(Subv): Analyze the shader to identify which attributes are actually used and don't
// assume every shader uses them all.
for (unsigned index = 0; index < 16; ++index) { for (unsigned index = 0; index < 16; ++index) {
auto& attrib = regs.vertex_attrib_format[index]; auto& attrib = regs.vertex_attrib_format[index];
NGLOG_DEBUG(HW_GPU, "vertex attrib {}, count={}, size={}, type={}, offset={}, normalize={}", NGLOG_DEBUG(HW_GPU, "vertex attrib {}, count={}, size={}, type={}, offset={}, normalize={}",
index, attrib.ComponentCount(), attrib.SizeString(), attrib.TypeString(), index, attrib.ComponentCount(), attrib.SizeString(), attrib.TypeString(),
attrib.offset.Value(), attrib.IsNormalized()); attrib.offset.Value(), attrib.IsNormalized());
glVertexAttribPointer(index, attrib.ComponentCount(), MaxwellToGL::VertexType(attrib), auto& buffer = regs.vertex_array[attrib.buffer];
attrib.IsNormalized() ? GL_TRUE : GL_FALSE, vertex_array.stride, ASSERT(buffer.IsEnabled());
reinterpret_cast<GLvoid*>(buffer_offset + attrib.offset));
glEnableVertexAttribArray(index); glEnableVertexAttribArray(index);
glVertexAttribFormat(index, attrib.ComponentCount(), MaxwellToGL::VertexType(attrib),
attrib.IsNormalized() ? GL_TRUE : GL_FALSE, attrib.offset);
glVertexAttribBinding(index, attrib.buffer);
hw_vao_enabled_attributes[index] = true; hw_vao_enabled_attributes[index] = true;
} }
// Copy vertex array data return {array_ptr, buffer_offset};
const u64 data_size{vertex_array_limit.LimitAddress() - vertex_array.StartAddress() + 1};
const VAddr data_addr{memory_manager->PhysicalToVirtualAddress(vertex_array.StartAddress())};
res_cache.FlushRegion(data_addr, data_size, nullptr);
Memory::ReadBlock(data_addr, array_ptr, data_size);
array_ptr += data_size;
buffer_offset += data_size;
} }
void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset, size_t ptr_pos) { void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset) {
// Helper function for uploading uniform data // Helper function for uploading uniform data
const auto copy_buffer = [&](GLuint handle, GLintptr offset, GLsizeiptr size) { const auto copy_buffer = [&](GLuint handle, GLintptr offset, GLsizeiptr size) {
if (has_ARB_direct_state_access) { if (has_ARB_direct_state_access) {
@ -190,8 +206,6 @@ void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset, size
u32 current_constbuffer_bindpoint = 0; u32 current_constbuffer_bindpoint = 0;
for (unsigned index = 1; index < Maxwell::MaxShaderProgram; ++index) { for (unsigned index = 1; index < Maxwell::MaxShaderProgram; ++index) {
ptr_pos += sizeof(GLShader::MaxwellUniformData);
auto& shader_config = gpu.regs.shader_config[index]; auto& shader_config = gpu.regs.shader_config[index];
const Maxwell::ShaderProgram program{static_cast<Maxwell::ShaderProgram>(index)}; const Maxwell::ShaderProgram program{static_cast<Maxwell::ShaderProgram>(index)};
@ -205,18 +219,21 @@ void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset, size
} }
// Upload uniform data as one UBO per stage // Upload uniform data as one UBO per stage
const GLintptr ubo_offset = buffer_offset + static_cast<GLintptr>(ptr_pos); const GLintptr ubo_offset = buffer_offset;
copy_buffer(uniform_buffers[stage].handle, ubo_offset, copy_buffer(uniform_buffers[stage].handle, ubo_offset,
sizeof(GLShader::MaxwellUniformData)); sizeof(GLShader::MaxwellUniformData));
GLShader::MaxwellUniformData* ub_ptr = GLShader::MaxwellUniformData* ub_ptr =
reinterpret_cast<GLShader::MaxwellUniformData*>(&buffer_ptr[ptr_pos]); reinterpret_cast<GLShader::MaxwellUniformData*>(buffer_ptr);
ub_ptr->SetFromRegs(gpu.state.shader_stages[stage]); ub_ptr->SetFromRegs(gpu.state.shader_stages[stage]);
buffer_ptr += sizeof(GLShader::MaxwellUniformData);
buffer_offset += sizeof(GLShader::MaxwellUniformData);
// Fetch program code from memory // Fetch program code from memory
GLShader::ProgramCode program_code; GLShader::ProgramCode program_code;
const u64 gpu_address{gpu.regs.code_address.CodeAddress() + shader_config.offset}; const u64 gpu_address{gpu.regs.code_address.CodeAddress() + shader_config.offset};
const VAddr cpu_address{gpu.memory_manager.PhysicalToVirtualAddress(gpu_address)}; const boost::optional<VAddr> cpu_address{gpu.memory_manager.GpuToCpuAddress(gpu_address)};
Memory::ReadBlock(cpu_address, program_code.data(), program_code.size() * sizeof(u64)); Memory::ReadBlock(*cpu_address, program_code.data(), program_code.size() * sizeof(u64));
GLShader::ShaderSetup setup{std::move(program_code)}; GLShader::ShaderSetup setup{std::move(program_code)};
GLShader::ShaderEntries shader_resources; GLShader::ShaderEntries shader_resources;
@ -235,8 +252,8 @@ void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset, size
break; break;
} }
default: default:
LOG_CRITICAL(HW_GPU, "Unimplemented shader index=%d, enable=%d, offset=0x%08X", index, NGLOG_CRITICAL(HW_GPU, "Unimplemented shader index={}, enable={}, offset={:#010X}",
shader_config.enable.Value(), shader_config.offset); index, shader_config.enable.Value(), shader_config.offset);
UNREACHABLE(); UNREACHABLE();
} }
@ -252,6 +269,24 @@ void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset, size
shader_program_manager->UseTrivialGeometryShader(); shader_program_manager->UseTrivialGeometryShader();
} }
size_t RasterizerOpenGL::CalculateVertexArraysSize() const {
const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
size_t size = 0;
for (u32 index = 0; index < Maxwell::NumVertexArrays; ++index) {
if (!regs.vertex_array[index].IsEnabled())
continue;
const Tegra::GPUVAddr start = regs.vertex_array[index].StartAddress();
const Tegra::GPUVAddr end = regs.vertex_array_limit[index].LimitAddress();
ASSERT(end > start);
size += end - start + 1;
}
return size;
}
bool RasterizerOpenGL::AccelerateDrawBatch(bool is_indexed) { bool RasterizerOpenGL::AccelerateDrawBatch(bool is_indexed) {
accelerate_draw = is_indexed ? AccelDraw::Indexed : AccelDraw::Arrays; accelerate_draw = is_indexed ? AccelDraw::Indexed : AccelDraw::Arrays;
DrawArrays(); DrawArrays();
@ -329,44 +364,49 @@ void RasterizerOpenGL::DrawArrays() {
const u64 index_buffer_size{regs.index_array.count * regs.index_array.FormatSizeInBytes()}; const u64 index_buffer_size{regs.index_array.count * regs.index_array.FormatSizeInBytes()};
const unsigned vertex_num{is_indexed ? regs.index_array.count : regs.vertex_buffer.count}; const unsigned vertex_num{is_indexed ? regs.index_array.count : regs.vertex_buffer.count};
// TODO(bunnei): Add support for 1+ vertex arrays
vs_input_size = vertex_num * regs.vertex_array[0].stride;
state.draw.vertex_buffer = stream_buffer->GetHandle(); state.draw.vertex_buffer = stream_buffer->GetHandle();
state.Apply(); state.Apply();
size_t buffer_size = static_cast<size_t>(vs_input_size); size_t buffer_size = CalculateVertexArraysSize();
if (is_indexed) { if (is_indexed) {
buffer_size = Common::AlignUp(buffer_size, 4) + index_buffer_size; buffer_size = Common::AlignUp<size_t>(buffer_size, 4) + index_buffer_size;
} }
// Uniform space for the 5 shader stages // Uniform space for the 5 shader stages
buffer_size += sizeof(GLShader::MaxwellUniformData) * Maxwell::MaxShaderStage; buffer_size = Common::AlignUp<size_t>(buffer_size, 4) +
sizeof(GLShader::MaxwellUniformData) * Maxwell::MaxShaderStage;
size_t ptr_pos = 0;
u8* buffer_ptr; u8* buffer_ptr;
GLintptr buffer_offset; GLintptr buffer_offset;
std::tie(buffer_ptr, buffer_offset) = std::tie(buffer_ptr, buffer_offset) =
stream_buffer->Map(static_cast<GLsizeiptr>(buffer_size), 4); stream_buffer->Map(static_cast<GLsizeiptr>(buffer_size), 4);
SetupVertexArray(buffer_ptr, buffer_offset); u8* offseted_buffer;
ptr_pos += vs_input_size; std::tie(offseted_buffer, buffer_offset) = SetupVertexArrays(buffer_ptr, buffer_offset);
offseted_buffer =
reinterpret_cast<u8*>(Common::AlignUp(reinterpret_cast<size_t>(offseted_buffer), 4));
buffer_offset = Common::AlignUp<size_t>(buffer_offset, 4);
// If indexed mode, copy the index buffer // If indexed mode, copy the index buffer
GLintptr index_buffer_offset = 0; GLintptr index_buffer_offset = 0;
if (is_indexed) { if (is_indexed) {
ptr_pos = Common::AlignUp(ptr_pos, 4);
const auto& memory_manager = Core::System().GetInstance().GPU().memory_manager; const auto& memory_manager = Core::System().GetInstance().GPU().memory_manager;
const VAddr index_data_addr{ const boost::optional<VAddr> index_data_addr{
memory_manager->PhysicalToVirtualAddress(regs.index_array.StartAddress())}; memory_manager->GpuToCpuAddress(regs.index_array.StartAddress())};
Memory::ReadBlock(index_data_addr, &buffer_ptr[ptr_pos], index_buffer_size); Memory::ReadBlock(*index_data_addr, offseted_buffer, index_buffer_size);
index_buffer_offset = buffer_offset + static_cast<GLintptr>(ptr_pos); index_buffer_offset = buffer_offset;
ptr_pos += index_buffer_size; offseted_buffer += index_buffer_size;
buffer_offset += index_buffer_size;
} }
SetupShaders(buffer_ptr, buffer_offset, ptr_pos); offseted_buffer =
reinterpret_cast<u8*>(Common::AlignUp(reinterpret_cast<size_t>(offseted_buffer), 4));
buffer_offset = Common::AlignUp<size_t>(buffer_offset, 4);
SetupShaders(offseted_buffer, buffer_offset);
stream_buffer->Unmap(); stream_buffer->Unmap();
@ -478,17 +518,17 @@ void RasterizerOpenGL::FlushAll() {
res_cache.FlushAll(); res_cache.FlushAll();
} }
void RasterizerOpenGL::FlushRegion(VAddr addr, u64 size) { void RasterizerOpenGL::FlushRegion(Tegra::GPUVAddr addr, u64 size) {
MICROPROFILE_SCOPE(OpenGL_CacheManagement); MICROPROFILE_SCOPE(OpenGL_CacheManagement);
res_cache.FlushRegion(addr, size); res_cache.FlushRegion(addr, size);
} }
void RasterizerOpenGL::InvalidateRegion(VAddr addr, u64 size) { void RasterizerOpenGL::InvalidateRegion(Tegra::GPUVAddr addr, u64 size) {
MICROPROFILE_SCOPE(OpenGL_CacheManagement); MICROPROFILE_SCOPE(OpenGL_CacheManagement);
res_cache.InvalidateRegion(addr, size, nullptr); res_cache.InvalidateRegion(addr, size, nullptr);
} }
void RasterizerOpenGL::FlushAndInvalidateRegion(VAddr addr, u64 size) { void RasterizerOpenGL::FlushAndInvalidateRegion(Tegra::GPUVAddr addr, u64 size) {
MICROPROFILE_SCOPE(OpenGL_CacheManagement); MICROPROFILE_SCOPE(OpenGL_CacheManagement);
res_cache.FlushRegion(addr, size); res_cache.FlushRegion(addr, size);
res_cache.InvalidateRegion(addr, size, nullptr); res_cache.InvalidateRegion(addr, size, nullptr);
@ -519,7 +559,8 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& framebu
MICROPROFILE_SCOPE(OpenGL_CacheManagement); MICROPROFILE_SCOPE(OpenGL_CacheManagement);
SurfaceParams src_params; SurfaceParams src_params;
src_params.addr = framebuffer_addr; src_params.cpu_addr = framebuffer_addr;
src_params.addr = res_cache.TryFindFramebufferGpuAddress(framebuffer_addr).get_value_or(0);
src_params.width = std::min(framebuffer.width, pixel_stride); src_params.width = std::min(framebuffer.width, pixel_stride);
src_params.height = framebuffer.height; src_params.height = framebuffer.height;
src_params.stride = pixel_stride; src_params.stride = pixel_stride;
@ -618,9 +659,9 @@ u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, GLuint progr
buffer_draw_state.enabled = true; buffer_draw_state.enabled = true;
buffer_draw_state.bindpoint = current_bindpoint + bindpoint; buffer_draw_state.bindpoint = current_bindpoint + bindpoint;
VAddr addr = gpu.memory_manager->PhysicalToVirtualAddress(buffer.address); boost::optional<VAddr> addr = gpu.memory_manager->GpuToCpuAddress(buffer.address);
std::vector<u8> data(used_buffer.GetSize() * sizeof(float)); std::vector<u8> data(used_buffer.GetSize() * sizeof(float));
Memory::ReadBlock(addr, data.data(), data.size()); Memory::ReadBlock(*addr, data.data(), data.size());
glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer_draw_state.ssbo); glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer_draw_state.ssbo);
glBufferData(GL_SHADER_STORAGE_BUFFER, data.size(), data.data(), GL_DYNAMIC_DRAW); glBufferData(GL_SHADER_STORAGE_BUFFER, data.size(), data.data(), GL_DYNAMIC_DRAW);

View file

@ -11,6 +11,7 @@
#include <glad/glad.h> #include <glad/glad.h>
#include "common/common_types.h" #include "common/common_types.h"
#include "video_core/engines/maxwell_3d.h" #include "video_core/engines/maxwell_3d.h"
#include "video_core/memory_manager.h"
#include "video_core/rasterizer_interface.h" #include "video_core/rasterizer_interface.h"
#include "video_core/renderer_opengl/gl_rasterizer_cache.h" #include "video_core/renderer_opengl/gl_rasterizer_cache.h"
#include "video_core/renderer_opengl/gl_resource_manager.h" #include "video_core/renderer_opengl/gl_resource_manager.h"
@ -29,9 +30,9 @@ public:
void DrawArrays() override; void DrawArrays() override;
void NotifyMaxwellRegisterChanged(u32 method) override; void NotifyMaxwellRegisterChanged(u32 method) override;
void FlushAll() override; void FlushAll() override;
void FlushRegion(VAddr addr, u64 size) override; void FlushRegion(Tegra::GPUVAddr addr, u64 size) override;
void InvalidateRegion(VAddr addr, u64 size) override; void InvalidateRegion(Tegra::GPUVAddr addr, u64 size) override;
void FlushAndInvalidateRegion(VAddr addr, u64 size) override; void FlushAndInvalidateRegion(Tegra::GPUVAddr addr, u64 size) override;
bool AccelerateDisplayTransfer(const void* config) override; bool AccelerateDisplayTransfer(const void* config) override;
bool AccelerateTextureCopy(const void* config) override; bool AccelerateTextureCopy(const void* config) override;
bool AccelerateFill(const void* config) override; bool AccelerateFill(const void* config) override;
@ -148,13 +149,13 @@ private:
static constexpr size_t STREAM_BUFFER_SIZE = 4 * 1024 * 1024; static constexpr size_t STREAM_BUFFER_SIZE = 4 * 1024 * 1024;
std::unique_ptr<OGLStreamBuffer> stream_buffer; std::unique_ptr<OGLStreamBuffer> stream_buffer;
GLsizeiptr vs_input_size; size_t CalculateVertexArraysSize() const;
void SetupVertexArray(u8* array_ptr, GLintptr buffer_offset); std::pair<u8*, GLintptr> SetupVertexArrays(u8* array_ptr, GLintptr buffer_offset);
std::array<OGLBuffer, Tegra::Engines::Maxwell3D::Regs::MaxShaderStage> uniform_buffers; std::array<OGLBuffer, Tegra::Engines::Maxwell3D::Regs::MaxShaderStage> uniform_buffers;
void SetupShaders(u8* buffer_ptr, GLintptr buffer_offset, size_t ptr_pos); void SetupShaders(u8* buffer_ptr, GLintptr buffer_offset);
enum class AccelDraw { Disabled, Arrays, Indexed }; enum class AccelDraw { Disabled, Arrays, Indexed };
AccelDraw accelerate_draw; AccelDraw accelerate_draw;

Some files were not shown because too many files have changed in this diff Show more