Compare commits

..

10 Commits

Author SHA1 Message Date
N00byKing
8c7d58eb3e Merge ea5b35a630 into 299f943202 2018-04-24 15:56:36 +00:00
N00byKing
ea5b35a630 Ran clang-format 2018-04-07 12:12:45 +02:00
N00byKing
91322e3bcd Add cinttypes Include for Source Files affected by Warning Cleanups 2018-04-07 12:12:45 +02:00
N00byKing
771e8cfd6b svc.cpp: Correct Variable Types 2018-04-07 12:10:19 +02:00
N00byKing
b94c495c23 nvdisp_disp0.cpp: Correct Variable Type 2018-04-07 12:10:19 +02:00
N00byKing
4f45534dec shared_memory.cpp: Correct Variable Types 2018-04-07 12:10:19 +02:00
N00byKing
493391818d object_address_table.cpp: Correct Variable Types 2018-04-07 12:09:00 +02:00
N00byKing
0236d34a72 arm_unicorn.cpp: Correct Variable Types 2018-04-07 12:09:00 +02:00
N00byKing
32b62d709a fsp_srv.cpp: Correct Log Variable type for "unk" 2018-04-07 12:08:59 +02:00
N00byKing
e00f7cdfc4 renderer_opengl.cpp: Cast framebuffer_transform_flags 2018-04-07 12:08:59 +02:00
184 changed files with 2736 additions and 4909 deletions

View File

@@ -23,7 +23,7 @@ matrix:
- os: osx
env: NAME="macos build"
sudo: false
osx_image: xcode9.3
osx_image: xcode9.2
install: "./.travis/macos/deps.sh"
script: "./.travis/macos/build.sh"
after_success: "./.travis/macos/upload.sh"

View File

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

View File

@@ -30,15 +30,14 @@ __declspec(noinline, noreturn)
#define ASSERT(_a_) \
do \
if (!(_a_)) { \
assert_noinline_call([] { NGLOG_CRITICAL(Debug, "Assertion Failed!"); }); \
assert_noinline_call([] { LOG_CRITICAL(Debug, "Assertion Failed!"); }); \
} \
while (0)
#define ASSERT_MSG(_a_, ...) \
do \
if (!(_a_)) { \
assert_noinline_call( \
[&] { NGLOG_CRITICAL(Debug, "Assertion Failed!\n" __VA_ARGS__); }); \
assert_noinline_call([&] { LOG_CRITICAL(Debug, "Assertion Failed!\n" __VA_ARGS__); }); \
} \
while (0)

623
src/common/chunk_file.h Normal file
View File

@@ -0,0 +1,623 @@
// 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

@@ -118,7 +118,7 @@ bool IsDirectory(const std::string& filename) {
#endif
if (result < 0) {
NGLOG_DEBUG(Common_Filesystem, "stat failed on {}: {}", filename, GetLastErrorMsg());
LOG_DEBUG(Common_Filesystem, "stat failed on %s: %s", filename.c_str(), GetLastErrorMsg());
return false;
}
@@ -128,29 +128,31 @@ bool IsDirectory(const std::string& filename) {
// Deletes a given filename, return true on success
// Doesn't supports deleting a directory
bool Delete(const std::string& filename) {
NGLOG_TRACE(Common_Filesystem, "file {}", filename);
LOG_TRACE(Common_Filesystem, "file %s", filename.c_str());
// Return true because we care about the file no
// being there, not the actual delete.
if (!Exists(filename)) {
NGLOG_DEBUG(Common_Filesystem, "{} does not exist", filename);
LOG_DEBUG(Common_Filesystem, "%s does not exist", filename.c_str());
return true;
}
// We can't delete a directory
if (IsDirectory(filename)) {
NGLOG_ERROR(Common_Filesystem, "Failed: {} is a directory", filename);
LOG_ERROR(Common_Filesystem, "Failed: %s is a directory", filename.c_str());
return false;
}
#ifdef _WIN32
if (!DeleteFileW(Common::UTF8ToUTF16W(filename).c_str())) {
NGLOG_ERROR(Common_Filesystem, "DeleteFile failed on {}: {}", filename, GetLastErrorMsg());
LOG_ERROR(Common_Filesystem, "DeleteFile failed on %s: %s", filename.c_str(),
GetLastErrorMsg());
return false;
}
#else
if (unlink(filename.c_str()) == -1) {
NGLOG_ERROR(Common_Filesystem, "unlink failed on {}: {}", filename, GetLastErrorMsg());
LOG_ERROR(Common_Filesystem, "unlink failed on %s: %s", filename.c_str(),
GetLastErrorMsg());
return false;
}
#endif
@@ -160,16 +162,16 @@ bool Delete(const std::string& filename) {
// Returns true if successful, or path already exists.
bool CreateDir(const std::string& path) {
NGLOG_TRACE(Common_Filesystem, "directory {}", path);
LOG_TRACE(Common_Filesystem, "directory %s", path.c_str());
#ifdef _WIN32
if (::CreateDirectoryW(Common::UTF8ToUTF16W(path).c_str(), nullptr))
return true;
DWORD error = GetLastError();
if (error == ERROR_ALREADY_EXISTS) {
NGLOG_DEBUG(Common_Filesystem, "CreateDirectory failed on {}: already exists", path);
LOG_DEBUG(Common_Filesystem, "CreateDirectory failed on %s: already exists", path.c_str());
return true;
}
NGLOG_ERROR(Common_Filesystem, "CreateDirectory failed on {}: {}", path, error);
LOG_ERROR(Common_Filesystem, "CreateDirectory failed on %s: %i", path.c_str(), error);
return false;
#else
if (mkdir(path.c_str(), 0755) == 0)
@@ -178,11 +180,11 @@ bool CreateDir(const std::string& path) {
int err = errno;
if (err == EEXIST) {
NGLOG_DEBUG(Common_Filesystem, "mkdir failed on {}: already exists", path);
LOG_DEBUG(Common_Filesystem, "mkdir failed on %s: already exists", path.c_str());
return true;
}
NGLOG_ERROR(Common_Filesystem, "mkdir failed on {}: {}", path, strerror(err));
LOG_ERROR(Common_Filesystem, "mkdir failed on %s: %s", path.c_str(), strerror(err));
return false;
#endif
}
@@ -190,10 +192,10 @@ bool CreateDir(const std::string& path) {
// Creates the full path of fullPath returns true on success
bool CreateFullPath(const std::string& fullPath) {
int panicCounter = 100;
NGLOG_TRACE(Common_Filesystem, "path {}", fullPath);
LOG_TRACE(Common_Filesystem, "path %s", fullPath.c_str());
if (FileUtil::Exists(fullPath)) {
NGLOG_DEBUG(Common_Filesystem, "path exists {}", fullPath);
LOG_DEBUG(Common_Filesystem, "path exists %s", fullPath.c_str());
return true;
}
@@ -209,14 +211,14 @@ bool CreateFullPath(const std::string& fullPath) {
// Include the '/' so the first call is CreateDir("/") rather than CreateDir("")
std::string const subPath(fullPath.substr(0, position + 1));
if (!FileUtil::IsDirectory(subPath) && !FileUtil::CreateDir(subPath)) {
NGLOG_ERROR(Common, "CreateFullPath: directory creation failed");
LOG_ERROR(Common, "CreateFullPath: directory creation failed");
return false;
}
// A safety check
panicCounter--;
if (panicCounter <= 0) {
NGLOG_ERROR(Common, "CreateFullPath: directory structure is too deep");
LOG_ERROR(Common, "CreateFullPath: directory structure is too deep");
return false;
}
position++;
@@ -225,11 +227,11 @@ bool CreateFullPath(const std::string& fullPath) {
// Deletes a directory filename, returns true on success
bool DeleteDir(const std::string& filename) {
NGLOG_TRACE(Common_Filesystem, "directory {}", filename);
LOG_TRACE(Common_Filesystem, "directory %s", filename.c_str());
// check if a directory
if (!FileUtil::IsDirectory(filename)) {
NGLOG_ERROR(Common_Filesystem, "Not a directory {}", filename);
LOG_ERROR(Common_Filesystem, "Not a directory %s", filename.c_str());
return false;
}
@@ -240,14 +242,14 @@ bool DeleteDir(const std::string& filename) {
if (rmdir(filename.c_str()) == 0)
return true;
#endif
NGLOG_ERROR(Common_Filesystem, "failed {}: {}", filename, GetLastErrorMsg());
LOG_ERROR(Common_Filesystem, "failed %s: %s", filename.c_str(), GetLastErrorMsg());
return false;
}
// renames file srcFilename to destFilename, returns true on success
bool Rename(const std::string& srcFilename, const std::string& destFilename) {
NGLOG_TRACE(Common_Filesystem, "{} --> {}", srcFilename, destFilename);
LOG_TRACE(Common_Filesystem, "%s --> %s", srcFilename.c_str(), destFilename.c_str());
#ifdef _WIN32
if (_wrename(Common::UTF8ToUTF16W(srcFilename).c_str(),
Common::UTF8ToUTF16W(destFilename).c_str()) == 0)
@@ -256,21 +258,21 @@ bool Rename(const std::string& srcFilename, const std::string& destFilename) {
if (rename(srcFilename.c_str(), destFilename.c_str()) == 0)
return true;
#endif
NGLOG_ERROR(Common_Filesystem, "failed {} --> {}: {}", srcFilename, destFilename,
GetLastErrorMsg());
LOG_ERROR(Common_Filesystem, "failed %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(),
GetLastErrorMsg());
return false;
}
// copies file srcFilename to destFilename, returns true on success
bool Copy(const std::string& srcFilename, const std::string& destFilename) {
NGLOG_TRACE(Common_Filesystem, "{} --> {}", srcFilename, destFilename);
LOG_TRACE(Common_Filesystem, "%s --> %s", srcFilename.c_str(), destFilename.c_str());
#ifdef _WIN32
if (CopyFileW(Common::UTF8ToUTF16W(srcFilename).c_str(),
Common::UTF8ToUTF16W(destFilename).c_str(), FALSE))
return true;
NGLOG_ERROR(Common_Filesystem, "failed {} --> {}: {}", srcFilename, destFilename,
GetLastErrorMsg());
LOG_ERROR(Common_Filesystem, "failed %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(),
GetLastErrorMsg());
return false;
#else
@@ -282,8 +284,8 @@ bool Copy(const std::string& srcFilename, const std::string& destFilename) {
// Open input file
FILE* input = fopen(srcFilename.c_str(), "rb");
if (!input) {
NGLOG_ERROR(Common_Filesystem, "opening input failed {} --> {}: {}", srcFilename,
destFilename, GetLastErrorMsg());
LOG_ERROR(Common_Filesystem, "opening input failed %s --> %s: %s", srcFilename.c_str(),
destFilename.c_str(), GetLastErrorMsg());
return false;
}
@@ -291,8 +293,8 @@ bool Copy(const std::string& srcFilename, const std::string& destFilename) {
FILE* output = fopen(destFilename.c_str(), "wb");
if (!output) {
fclose(input);
NGLOG_ERROR(Common_Filesystem, "opening output failed {} --> {}: {}", srcFilename,
destFilename, GetLastErrorMsg());
LOG_ERROR(Common_Filesystem, "opening output failed %s --> %s: %s", srcFilename.c_str(),
destFilename.c_str(), GetLastErrorMsg());
return false;
}
@@ -302,8 +304,8 @@ bool Copy(const std::string& srcFilename, const std::string& destFilename) {
size_t rnum = fread(buffer, sizeof(char), BSIZE, input);
if (rnum != BSIZE) {
if (ferror(input) != 0) {
NGLOG_ERROR(Common_Filesystem, "failed reading from source, {} --> {}: {}",
srcFilename, destFilename, GetLastErrorMsg());
LOG_ERROR(Common_Filesystem, "failed reading from source, %s --> %s: %s",
srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg());
goto bail;
}
}
@@ -311,8 +313,8 @@ bool Copy(const std::string& srcFilename, const std::string& destFilename) {
// write output
size_t wnum = fwrite(buffer, sizeof(char), rnum, output);
if (wnum != rnum) {
NGLOG_ERROR(Common_Filesystem, "failed writing to output, {} --> {}: {}", srcFilename,
destFilename, GetLastErrorMsg());
LOG_ERROR(Common_Filesystem, "failed writing to output, %s --> %s: %s",
srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg());
goto bail;
}
}
@@ -332,12 +334,12 @@ bail:
// Returns the size of filename (64bit)
u64 GetSize(const std::string& filename) {
if (!Exists(filename)) {
NGLOG_ERROR(Common_Filesystem, "failed {}: No such file", filename);
LOG_ERROR(Common_Filesystem, "failed %s: No such file", filename.c_str());
return 0;
}
if (IsDirectory(filename)) {
NGLOG_ERROR(Common_Filesystem, "failed {}: is a directory", filename);
LOG_ERROR(Common_Filesystem, "failed %s: is a directory", filename.c_str());
return 0;
}
@@ -348,11 +350,11 @@ u64 GetSize(const std::string& filename) {
if (stat(filename.c_str(), &buf) == 0)
#endif
{
NGLOG_TRACE(Common_Filesystem, "{}: {}", filename, buf.st_size);
LOG_TRACE(Common_Filesystem, "%s: %lld", filename.c_str(), (long long)buf.st_size);
return buf.st_size;
}
NGLOG_ERROR(Common_Filesystem, "Stat failed {}: {}", filename, GetLastErrorMsg());
LOG_ERROR(Common_Filesystem, "Stat failed %s: %s", filename.c_str(), GetLastErrorMsg());
return 0;
}
@@ -360,7 +362,7 @@ u64 GetSize(const std::string& filename) {
u64 GetSize(const int fd) {
struct stat buf;
if (fstat(fd, &buf) != 0) {
NGLOG_ERROR(Common_Filesystem, "GetSize: stat failed {}: {}", fd, GetLastErrorMsg());
LOG_ERROR(Common_Filesystem, "GetSize: stat failed %i: %s", fd, GetLastErrorMsg());
return 0;
}
return buf.st_size;
@@ -371,14 +373,12 @@ u64 GetSize(FILE* f) {
// can't use off_t here because it can be 32-bit
u64 pos = ftello(f);
if (fseeko(f, 0, SEEK_END) != 0) {
NGLOG_ERROR(Common_Filesystem, "GetSize: seek failed {}: {}", fmt::ptr(f),
GetLastErrorMsg());
LOG_ERROR(Common_Filesystem, "GetSize: seek failed %p: %s", f, GetLastErrorMsg());
return 0;
}
u64 size = ftello(f);
if ((size != pos) && (fseeko(f, pos, SEEK_SET) != 0)) {
NGLOG_ERROR(Common_Filesystem, "GetSize: seek failed {}: {}", fmt::ptr(f),
GetLastErrorMsg());
LOG_ERROR(Common_Filesystem, "GetSize: seek failed %p: %s", f, GetLastErrorMsg());
return 0;
}
return size;
@@ -386,10 +386,10 @@ u64 GetSize(FILE* f) {
// creates an empty file filename, returns true on success
bool CreateEmptyFile(const std::string& filename) {
NGLOG_TRACE(Common_Filesystem, "{}", filename);
LOG_TRACE(Common_Filesystem, "%s", filename.c_str());
if (!FileUtil::IOFile(filename, "wb")) {
NGLOG_ERROR(Common_Filesystem, "failed {}: {}", filename, GetLastErrorMsg());
LOG_ERROR(Common_Filesystem, "failed %s: %s", filename.c_str(), GetLastErrorMsg());
return false;
}
@@ -398,7 +398,7 @@ bool CreateEmptyFile(const std::string& filename) {
bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string& directory,
DirectoryEntryCallable callback) {
NGLOG_TRACE(Common_Filesystem, "directory {}", directory);
LOG_TRACE(Common_Filesystem, "directory %s", directory.c_str());
// How many files + directories we found
unsigned found_entries = 0;
@@ -556,7 +556,7 @@ std::string GetCurrentDir() {
char* dir;
if (!(dir = getcwd(nullptr, 0))) {
#endif
NGLOG_ERROR(Common_Filesystem, "GetCurrentDirectory failed: {}", GetLastErrorMsg());
LOG_ERROR(Common_Filesystem, "GetCurrentDirectory failed: %s", GetLastErrorMsg());
return nullptr;
}
#ifdef _WIN32
@@ -653,12 +653,12 @@ static const std::string GetUserDirectory(const std::string& envvar) {
else if (envvar == "XDG_CACHE_HOME")
subdirectory = DIR_SEP ".cache";
else
ASSERT_MSG(false, "Unknown XDG variable {}.", envvar);
ASSERT_MSG(false, "Unknown XDG variable %s.", envvar.c_str());
user_dir = GetHomeDirectory() + subdirectory;
}
ASSERT_MSG(!user_dir.empty(), "User directory {} mustnt be empty.", envvar);
ASSERT_MSG(user_dir[0] == '/', "User directory {} must be absolute.", envvar);
ASSERT_MSG(!user_dir.empty(), "User directory %s musnt be empty.", envvar.c_str());
ASSERT_MSG(user_dir[0] == '/', "User directory %s must be absolute.", envvar.c_str());
return user_dir;
}
@@ -676,7 +676,7 @@ std::string GetSysDirectory() {
#endif
sysDir += DIR_SEP;
NGLOG_DEBUG(Common_Filesystem, "Setting to {}:", sysDir);
LOG_DEBUG(Common_Filesystem, "Setting to %s:", sysDir.c_str());
return sysDir;
}
@@ -692,7 +692,7 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string& new
if (!FileUtil::IsDirectory(paths[D_USER_IDX])) {
paths[D_USER_IDX] = AppDataRoamingDirectory() + DIR_SEP EMU_DATA_DIR DIR_SEP;
} else {
NGLOG_INFO(Common_Filesystem, "Using the local user directory");
LOG_INFO(Common_Filesystem, "Using the local user directory");
}
paths[D_CONFIG_IDX] = paths[D_USER_IDX] + CONFIG_DIR DIR_SEP;
@@ -719,7 +719,7 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string& new
if (!newPath.empty()) {
if (!FileUtil::IsDirectory(newPath)) {
NGLOG_ERROR(Common_Filesystem, "Invalid path specified {}", newPath);
LOG_ERROR(Common_Filesystem, "Invalid path specified %s", newPath.c_str());
return paths[DirIDX];
} else {
paths[DirIDX] = newPath;
@@ -809,16 +809,16 @@ IOFile::~IOFile() {
Close();
}
IOFile::IOFile(IOFile&& other) noexcept {
IOFile::IOFile(IOFile&& other) {
Swap(other);
}
IOFile& IOFile::operator=(IOFile&& other) noexcept {
IOFile& IOFile::operator=(IOFile&& other) {
Swap(other);
return *this;
}
void IOFile::Swap(IOFile& other) noexcept {
void IOFile::Swap(IOFile& other) {
std::swap(m_file, other.m_file);
std::swap(m_good, other.m_good);
}

View File

@@ -160,18 +160,22 @@ public:
~IOFile();
IOFile(IOFile&& other) noexcept;
IOFile& operator=(IOFile&& other) noexcept;
IOFile(IOFile&& other);
IOFile& operator=(IOFile&& other);
void Swap(IOFile& other) noexcept;
void Swap(IOFile& other);
bool Open(const std::string& filename, const char openmode[]);
bool Close();
template <typename T>
size_t ReadArray(T* data, size_t length) {
static_assert(std::is_standard_layout<T>(),
"Given array does not consist of standard layout objects");
#if (__GNUC__ >= 5) || defined(__clang__) || defined(_MSC_VER)
static_assert(std::is_trivially_copyable<T>(),
"Given array does not consist of trivially copyable objects");
#endif
if (!IsOpen()) {
m_good = false;
@@ -187,8 +191,12 @@ public:
template <typename T>
size_t WriteArray(const T* data, size_t length) {
static_assert(std::is_standard_layout<T>(),
"Given array does not consist of standard layout objects");
#if (__GNUC__ >= 5) || defined(__clang__) || defined(_MSC_VER)
static_assert(std::is_trivially_copyable<T>(),
"Given array does not consist of trivially copyable objects");
#endif
if (!IsOpen()) {
m_good = false;
@@ -202,15 +210,11 @@ public:
return items_written;
}
template <typename T>
size_t ReadBytes(T* data, size_t length) {
static_assert(std::is_trivially_copyable<T>(), "T must be trivially copyable");
size_t ReadBytes(void* data, size_t length) {
return ReadArray(reinterpret_cast<char*>(data), length);
}
template <typename T>
size_t WriteBytes(const T* data, size_t length) {
static_assert(std::is_trivially_copyable<T>(), "T must be trivially copyable");
size_t WriteBytes(const void* data, size_t length) {
return WriteArray(reinterpret_cast<const char*>(data), length);
}

View File

@@ -0,0 +1,167 @@
// 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

@@ -2,8 +2,11 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <utility>
#include <algorithm>
#include <array>
#include <cstdio>
#include "common/assert.h"
#include "common/common_funcs.h" // snprintf compatibility define
#include "common/logging/backend.h"
#include "common/logging/filter.h"
#include "common/logging/log.h"
@@ -35,7 +38,6 @@ namespace Log {
SUB(Service, AM) \
SUB(Service, AOC) \
SUB(Service, APM) \
SUB(Service, BCAT) \
SUB(Service, Fatal) \
SUB(Service, Friend) \
SUB(Service, FS) \
@@ -46,7 +48,6 @@ namespace Log {
SUB(Service, NS) \
SUB(Service, NVDRV) \
SUB(Service, PCTL) \
SUB(Service, PREPO) \
SUB(Service, SET) \
SUB(Service, SM) \
SUB(Service, SPL) \
@@ -130,6 +131,21 @@ void SetFilter(Filter* new_filter) {
filter = new_filter;
}
void LogMessage(Class log_class, Level log_level, const char* filename, unsigned int line_num,
const char* function, const char* format, ...) {
if (filter && !filter->CheckMessage(log_class, log_level))
return;
std::array<char, 4 * 1024> formatting_buffer;
va_list args;
va_start(args, format);
vsnprintf(formatting_buffer.data(), formatting_buffer.size(), format, args);
va_end(args);
Entry entry = CreateEntry(log_class, log_level, filename, line_num, function,
std::string(formatting_buffer.data()));
PrintColoredMessage(entry);
}
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
unsigned int line_num, const char* function, const char* format,
const fmt::format_args& args) {

View File

@@ -55,7 +55,6 @@ enum class Class : ClassType {
Service_AOC, ///< The AOC (AddOn Content) service
Service_APM, ///< The APM (Performance) service
Service_Audio, ///< The Audio (Audio control) service
Service_BCAT, ///< The BCAT service
Service_Fatal, ///< The Fatal service
Service_Friend, ///< The friend service
Service_FS, ///< The FS (Filesystem) service
@@ -66,7 +65,6 @@ enum class Class : ClassType {
Service_NS, ///< The NS services
Service_NVDRV, ///< The NVDRV (Nvidia driver) service
Service_PCTL, ///< The PCTL (Parental control) service
Service_PREPO, ///< The PREPO (Play report) service
Service_SET, ///< The SET (Settings) service
Service_SM, ///< The SM (Service manager) service
Service_SPL, ///< The SPL service
@@ -93,6 +91,19 @@ enum class Class : ClassType {
Count ///< Total number of logging classes
};
/// Logs a message to the global logger.
void LogMessage(Class log_class, Level log_level, const char* filename, unsigned int line_num,
const char* function,
#ifdef _MSC_VER
_Printf_format_string_
#endif
const char* format,
...)
#ifdef __GNUC__
__attribute__((format(printf, 6, 7)))
#endif
;
/// Logs a message to the global logger, using fmt
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
unsigned int line_num, const char* function, const char* format,
@@ -107,6 +118,28 @@ void FmtLogMessage(Class log_class, Level log_level, const char* filename, unsig
} // namespace Log
#define LOG_GENERIC(log_class, log_level, ...) \
::Log::LogMessage(log_class, log_level, __FILE__, __LINE__, __func__, __VA_ARGS__)
#ifdef _DEBUG
#define LOG_TRACE(log_class, ...) \
LOG_GENERIC(::Log::Class::log_class, ::Log::Level::Trace, __VA_ARGS__)
#else
#define LOG_TRACE(log_class, ...) (void(0))
#endif
#define LOG_DEBUG(log_class, ...) \
LOG_GENERIC(::Log::Class::log_class, ::Log::Level::Debug, __VA_ARGS__)
#define LOG_INFO(log_class, ...) \
LOG_GENERIC(::Log::Class::log_class, ::Log::Level::Info, __VA_ARGS__)
#define LOG_WARNING(log_class, ...) \
LOG_GENERIC(::Log::Class::log_class, ::Log::Level::Warning, __VA_ARGS__)
#define LOG_ERROR(log_class, ...) \
LOG_GENERIC(::Log::Class::log_class, ::Log::Level::Error, __VA_ARGS__)
#define LOG_CRITICAL(log_class, ...) \
LOG_GENERIC(::Log::Class::log_class, ::Log::Level::Critical, __VA_ARGS__)
// Define the fmt lib macros
#ifdef _DEBUG
#define NGLOG_TRACE(log_class, ...) \
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Trace, __FILE__, __LINE__, \

View File

@@ -55,7 +55,7 @@ void* AllocateExecutableMemory(size_t size, bool low) {
if (ptr == MAP_FAILED) {
ptr = nullptr;
#endif
NGLOG_ERROR(Common_Memory, "Failed to allocate executable memory");
LOG_ERROR(Common_Memory, "Failed to allocate executable memory");
}
#if !defined(_WIN32) && defined(ARCHITECTURE_X64) && !defined(MAP_32BIT)
else {
@@ -68,7 +68,7 @@ void* AllocateExecutableMemory(size_t size, bool low) {
#if EMU_ARCH_BITS == 64
if ((u64)ptr >= 0x80000000 && low == true)
NGLOG_ERROR(Common_Memory, "Executable memory ended up above 2GB!");
LOG_ERROR(Common_Memory, "Executable memory ended up above 2GB!");
#endif
return ptr;
@@ -85,7 +85,7 @@ void* AllocateMemoryPages(size_t size) {
#endif
if (ptr == nullptr)
NGLOG_ERROR(Common_Memory, "Failed to allocate raw memory");
LOG_ERROR(Common_Memory, "Failed to allocate raw memory");
return ptr;
}
@@ -99,12 +99,12 @@ void* AllocateAlignedMemory(size_t size, size_t alignment) {
ptr = memalign(alignment, size);
#else
if (posix_memalign(&ptr, alignment, size) != 0)
NGLOG_ERROR(Common_Memory, "Failed to allocate aligned memory");
LOG_ERROR(Common_Memory, "Failed to allocate aligned memory");
#endif
#endif
if (ptr == nullptr)
NGLOG_ERROR(Common_Memory, "Failed to allocate aligned memory");
LOG_ERROR(Common_Memory, "Failed to allocate aligned memory");
return ptr;
}
@@ -113,7 +113,7 @@ void FreeMemoryPages(void* ptr, size_t size) {
if (ptr) {
#ifdef _WIN32
if (!VirtualFree(ptr, 0, MEM_RELEASE))
NGLOG_ERROR(Common_Memory, "FreeMemoryPages failed!\n{}", GetLastErrorMsg());
LOG_ERROR(Common_Memory, "FreeMemoryPages failed!\n%s", GetLastErrorMsg());
#else
munmap(ptr, size);
#endif
@@ -134,7 +134,7 @@ void WriteProtectMemory(void* ptr, size_t size, bool allowExecute) {
#ifdef _WIN32
DWORD oldValue;
if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READ : PAGE_READONLY, &oldValue))
NGLOG_ERROR(Common_Memory, "WriteProtectMemory failed!\n{}", GetLastErrorMsg());
LOG_ERROR(Common_Memory, "WriteProtectMemory failed!\n%s", GetLastErrorMsg());
#else
mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_EXEC) : PROT_READ);
#endif
@@ -145,7 +145,7 @@ void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute) {
DWORD oldValue;
if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE,
&oldValue))
NGLOG_ERROR(Common_Memory, "UnWriteProtectMemory failed!\n{}", GetLastErrorMsg());
LOG_ERROR(Common_Memory, "UnWriteProtectMemory failed!\n%s", GetLastErrorMsg());
#else
mprotect(ptr, size,
allowExecute ? (PROT_READ | PROT_WRITE | PROT_EXEC) : PROT_WRITE | PROT_READ);
@@ -167,7 +167,8 @@ std::string MemUsage() {
return "MemUsage Error";
if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc)))
Ret = fmt::format("{} K", Common::ThousandSeparate(pmc.WorkingSetSize / 1024, 7));
Ret = Common::StringFromFormat(
"%s K", Common::ThousandSeparate(pmc.WorkingSetSize / 1024, 7).c_str());
CloseHandle(hProcess);
return Ret;

View File

@@ -25,7 +25,7 @@ ParamPackage::ParamPackage(const std::string& serialized) {
std::vector<std::string> key_value;
Common::SplitString(pair, KEY_VALUE_SEPARATOR, key_value);
if (key_value.size() != 2) {
NGLOG_ERROR(Common, "invalid key pair {}", pair);
LOG_ERROR(Common, "invalid key pair %s", pair.c_str());
continue;
}
@@ -64,7 +64,7 @@ std::string ParamPackage::Serialize() const {
std::string ParamPackage::Get(const std::string& key, const std::string& default_value) const {
auto pair = data.find(key);
if (pair == data.end()) {
NGLOG_DEBUG(Common, "key '{}' not found", key);
LOG_DEBUG(Common, "key %s not found", key.c_str());
return default_value;
}
@@ -74,14 +74,14 @@ std::string ParamPackage::Get(const std::string& key, const std::string& default
int ParamPackage::Get(const std::string& key, int default_value) const {
auto pair = data.find(key);
if (pair == data.end()) {
NGLOG_DEBUG(Common, "key '{}' not found", key);
LOG_DEBUG(Common, "key %s not found", key.c_str());
return default_value;
}
try {
return std::stoi(pair->second);
} catch (const std::logic_error&) {
NGLOG_ERROR(Common, "failed to convert {} to int", pair->second);
LOG_ERROR(Common, "failed to convert %s to int", pair->second.c_str());
return default_value;
}
}
@@ -89,14 +89,14 @@ int ParamPackage::Get(const std::string& key, int default_value) const {
float ParamPackage::Get(const std::string& key, float default_value) const {
auto pair = data.find(key);
if (pair == data.end()) {
NGLOG_DEBUG(Common, "key {} not found", key);
LOG_DEBUG(Common, "key %s not found", key.c_str());
return default_value;
}
try {
return std::stof(pair->second);
} catch (const std::logic_error&) {
NGLOG_ERROR(Common, "failed to convert {} to float", pair->second);
LOG_ERROR(Common, "failed to convert %s to float", pair->second.c_str());
return default_value;
}
}

View File

@@ -46,6 +46,76 @@ bool AsciiToHex(const char* _szValue, u32& result) {
return true;
}
bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list args) {
int writtenCount;
#ifdef _MSC_VER
// You would think *printf are simple, right? Iterate on each character,
// if it's a format specifier handle it properly, etc.
//
// Nooooo. Not according to the C standard.
//
// According to the C99 standard (7.19.6.1 "The fprintf function")
// The format shall be a multibyte character sequence
//
// Because some character encodings might have '%' signs in the middle of
// a multibyte sequence (SJIS for example only specifies that the first
// byte of a 2 byte sequence is "high", the second byte can be anything),
// printf functions have to decode the multibyte sequences and try their
// best to not screw up.
//
// Unfortunately, on Windows, the locale for most languages is not UTF-8
// as we would need. Notably, for zh_TW, Windows chooses EUC-CN as the
// locale, and completely fails when trying to decode UTF-8 as EUC-CN.
//
// On the other hand, the fix is simple: because we use UTF-8, no such
// multibyte handling is required as we can simply assume that no '%' char
// will be present in the middle of a multibyte sequence.
//
// This is why we lookup an ANSI (cp1252) locale here and use _vsnprintf_l.
static locale_t c_locale = nullptr;
if (!c_locale)
c_locale = _create_locale(LC_ALL, ".1252");
writtenCount = _vsnprintf_l(out, outsize, format, c_locale, args);
#else
writtenCount = vsnprintf(out, outsize, format, args);
#endif
if (writtenCount > 0 && writtenCount < outsize) {
out[writtenCount] = '\0';
return true;
} else {
out[outsize - 1] = '\0';
return false;
}
}
std::string StringFromFormat(const char* format, ...) {
va_list args;
char* buf = nullptr;
#ifdef _WIN32
int required = 0;
va_start(args, format);
required = _vscprintf(format, args);
buf = new char[required + 1];
CharArrayFromFormatV(buf, required + 1, format, args);
va_end(args);
std::string temp = buf;
delete[] buf;
#else
va_start(args, format);
if (vasprintf(&buf, format, args) < 0)
LOG_ERROR(Common, "Unable to allocate memory for string");
va_end(args);
std::string temp = buf;
free(buf);
#endif
return temp;
}
// For Debugging. Read out an u8 array.
std::string ArrayToString(const u8* data, size_t size, int line_len, bool spaces) {
std::ostringstream oss;
@@ -277,7 +347,7 @@ static std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>&
iconv_t const conv_desc = iconv_open("UTF-8", fromcode);
if ((iconv_t)(-1) == conv_desc) {
NGLOG_ERROR(Common, "Iconv initialization failure [{}]: {}", fromcode, strerror(errno));
LOG_ERROR(Common, "Iconv initialization failure [%s]: %s", fromcode, strerror(errno));
iconv_close(conv_desc);
return {};
}
@@ -306,7 +376,7 @@ static std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>&
++src_buffer;
}
} else {
NGLOG_ERROR(Common, "iconv failure [{}]: {}", fromcode, strerror(errno));
LOG_ERROR(Common, "iconv failure [%s]: %s", fromcode, strerror(errno));
break;
}
}
@@ -325,7 +395,7 @@ std::u16string UTF8ToUTF16(const std::string& input) {
iconv_t const conv_desc = iconv_open("UTF-16LE", "UTF-8");
if ((iconv_t)(-1) == conv_desc) {
NGLOG_ERROR(Common, "Iconv initialization failure [UTF-8]: {}", strerror(errno));
LOG_ERROR(Common, "Iconv initialization failure [UTF-8]: %s", strerror(errno));
iconv_close(conv_desc);
return {};
}
@@ -354,7 +424,7 @@ std::u16string UTF8ToUTF16(const std::string& input) {
++src_buffer;
}
} else {
NGLOG_ERROR(Common, "iconv failure [UTF-8]: {}", strerror(errno));
LOG_ERROR(Common, "iconv failure [UTF-8]: %s", strerror(errno));
break;
}
}

View File

@@ -4,6 +4,7 @@
#pragma once
#include <cstdarg>
#include <cstddef>
#include <iomanip>
#include <sstream>
@@ -19,6 +20,19 @@ std::string ToLower(std::string str);
/// Make a string uppercase
std::string ToUpper(std::string str);
std::string StringFromFormat(const char* format, ...);
// Cheap!
bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list args);
template <size_t Count>
inline void CharArrayFromFormat(char (&out)[Count], const char* format, ...) {
va_list args;
va_start(args, format);
CharArrayFromFormatV(out, Count, format, args);
va_end(args);
}
// Good
std::string ArrayToString(const u8* data, size_t size, int line_len = 20, bool spaces = true);
std::string StripSpaces(const std::string& s);

View File

@@ -2,10 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <ctime>
#include <fmt/format.h>
#include <time.h>
#ifdef _WIN32
#include <windows.h>
// windows.h needs to be included before other windows headers
@@ -107,8 +104,8 @@ std::string Timer::GetTimeElapsedFormatted() const {
// Hours
u32 Hours = Minutes / 60;
std::string TmpStr = fmt::format("{:02}:{:02}:{:02}:{:03}", Hours, Minutes % 60, Seconds % 60,
Milliseconds % 1000);
std::string TmpStr = StringFromFormat("%02i:%02i:%02i:%03i", Hours, Minutes % 60, Seconds % 60,
Milliseconds % 1000);
return TmpStr;
}
@@ -168,11 +165,11 @@ std::string Timer::GetTimeFormatted() {
#ifdef _WIN32
struct timeb tp;
(void)::ftime(&tp);
return fmt::format("{}:{:03}", tmp, tp.millitm);
return StringFromFormat("%s:%03i", tmp, tp.millitm);
#else
struct timeval t;
(void)gettimeofday(&t, nullptr);
return fmt::format("{}:{:03}", tmp, static_cast<int>(t.tv_usec / 1000));
return StringFromFormat("%s:%03d", tmp, (int)(t.tv_usec / 1000));
#endif
}

View File

@@ -52,8 +52,8 @@ static inline Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w);
template <typename T>
class Vec2 {
public:
T x{};
T y{};
T x;
T y;
Vec2() = default;
Vec2(const T& _x, const T& _y) : x(_x), y(_y) {}
@@ -192,9 +192,9 @@ inline float Vec2<float>::Normalize() {
template <typename T>
class Vec3 {
public:
T x{};
T y{};
T z{};
T x;
T y;
T z;
Vec3() = default;
Vec3(const T& _x, const T& _y, const T& _z) : x(_x), y(_y), z(_z) {}
@@ -392,10 +392,10 @@ typedef Vec3<float> Vec3f;
template <typename T>
class Vec4 {
public:
T x{};
T y{};
T z{};
T w{};
T x;
T y;
T z;
T w;
Vec4() = default;
Vec4(const T& _x, const T& _y, const T& _z, const T& _w) : x(_x), y(_y), z(_z), w(_w) {}

View File

@@ -4,8 +4,6 @@ add_library(core STATIC
arm/unicorn/arm_unicorn.h
core.cpp
core.h
core_cpu.cpp
core_cpu.h
core_timing.cpp
core_timing.h
file_sys/directory.h
@@ -124,10 +122,6 @@ add_library(core STATIC
hle/service/audio/audren_u.h
hle/service/audio/codecctl.cpp
hle/service/audio/codecctl.h
hle/service/bcat/module.cpp
hle/service/bcat/module.h
hle/service/bcat/bcat.cpp
hle/service/bcat/bcat.h
hle/service/fatal/fatal.cpp
hle/service/fatal/fatal.h
hle/service/fatal/fatal_p.cpp
@@ -175,8 +169,6 @@ add_library(core STATIC
hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
hle/service/nvdrv/devices/nvhost_gpu.cpp
hle/service/nvdrv/devices/nvhost_gpu.h
hle/service/nvdrv/devices/nvhost_nvdec.cpp
hle/service/nvdrv/devices/nvhost_nvdec.h
hle/service/nvdrv/devices/nvmap.cpp
hle/service/nvdrv/devices/nvmap.h
hle/service/nvdrv/interface.cpp
@@ -189,12 +181,10 @@ add_library(core STATIC
hle/service/nvflinger/buffer_queue.h
hle/service/nvflinger/nvflinger.cpp
hle/service/nvflinger/nvflinger.h
hle/service/pctl/module.cpp
hle/service/pctl/module.h
hle/service/pctl/pctl.cpp
hle/service/pctl/pctl.h
hle/service/prepo/prepo.cpp
hle/service/prepo/prepo.h
hle/service/pctl/pctl_a.cpp
hle/service/pctl/pctl_a.h
hle/service/service.cpp
hle/service/service.h
hle/service/set/set.cpp
@@ -261,7 +251,6 @@ add_library(core STATIC
loader/nso.h
memory.cpp
memory.h
memory_hook.cpp
memory_hook.h
memory_setup.h
perf_stats.cpp

View File

@@ -55,8 +55,8 @@ public:
}
void InterpreterFallback(u64 pc, size_t num_instructions) override {
NGLOG_INFO(Core_ARM, "Unicorn fallback @ 0x{:X} for {} instructions (instr = {:08X})", pc,
num_instructions, MemoryReadCode(pc));
LOG_INFO(Core_ARM, "Unicorn fallback @ 0x%" PRIx64 " for %zu instructions (instr = %08x)",
pc, num_instructions, MemoryReadCode(pc));
ARM_Interface::ThreadContext ctx;
parent.SaveContext(ctx);
@@ -76,7 +76,7 @@ public:
case Dynarmic::A64::Exception::Yield:
return;
default:
ASSERT_MSG(false, "ExceptionRaised(exception = {}, pc = {:X})",
ASSERT_MSG(false, "ExceptionRaised(exception = %zu, pc = %" PRIx64 ")",
static_cast<size_t>(exception), pc);
}
}

View File

@@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include <algorithm>
#include <cinttypes>
#include <unicorn/arm64.h>
#include "common/assert.h"
#include "common/microprofile.h"
@@ -30,7 +31,7 @@ LoadDll LoadDll::g_load_dll;
#define CHECKED(expr) \
do { \
if (auto _cerr = (expr)) { \
ASSERT_MSG(false, "Call " #expr " failed with error: {} ({})\n", _cerr, \
ASSERT_MSG(false, "Call " #expr " failed with error: %u (%s)\n", _cerr, \
uc_strerror(_cerr)); \
} \
} while (0)
@@ -52,9 +53,11 @@ static void InterruptHook(uc_engine* uc, u32 intNo, void* user_data) {
static bool UnmappedMemoryHook(uc_engine* uc, uc_mem_type type, u64 addr, int size, u64 value,
void* user_data) {
ARM_Interface::ThreadContext ctx{};
Core::CurrentArmInterface().SaveContext(ctx);
ASSERT_MSG(false, "Attempted to read from unmapped memory: 0x{:X}, pc=0x{:X}, lr=0x{:X}", addr,
ctx.pc, ctx.cpu_registers[30]);
Core::CPU().SaveContext(ctx);
ASSERT_MSG(false,
"Attempted to read from unmapped memory: 0x%" PRIx64 ", pc=0x%" PRIx64
", lr=0x%" PRIx64,
addr, ctx.pc, ctx.cpu_registers[30]);
return {};
}

View File

@@ -5,6 +5,10 @@
#include <memory>
#include <utility>
#include "common/logging/log.h"
#ifdef ARCHITECTURE_x86_64
#include "core/arm/dynarmic/arm_dynarmic.h"
#endif
#include "core/arm/unicorn/arm_unicorn.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/gdbstub/gdbstub.h"
@@ -27,31 +31,11 @@ namespace Core {
System::~System() = default;
/// Runs a CPU core while the system is powered on
static void RunCpuCore(std::shared_ptr<Cpu> cpu_state) {
while (Core::System().GetInstance().IsPoweredOn()) {
cpu_state->RunLoop(true);
}
}
Cpu& System::CurrentCpuCore() {
// If multicore is enabled, use host thread to figure out the current CPU core
if (Settings::values.use_multi_core) {
const auto& search = thread_to_cpu.find(std::this_thread::get_id());
ASSERT(search != thread_to_cpu.end());
ASSERT(search->second);
return *search->second;
}
// Otherwise, use single-threaded mode active_core variable
return *cpu_cores[active_core];
}
System::ResultStatus System::RunLoop(bool tight_loop) {
status = ResultStatus::Success;
// Update thread_to_cpu in case Core 0 is run from a different host thread
thread_to_cpu[std::this_thread::get_id()] = cpu_cores[0];
if (!cpu_core) {
return ResultStatus::ErrorNotInitialized;
}
if (GDBStub::IsServerEnabled()) {
GDBStub::HandlePacket();
@@ -68,14 +52,25 @@ System::ResultStatus System::RunLoop(bool tight_loop) {
}
}
for (active_core = 0; active_core < NUM_CPU_CORES; ++active_core) {
cpu_cores[active_core]->RunLoop(tight_loop);
if (Settings::values.use_multi_core) {
// Cores 1-3 are run on other threads in this mode
break;
// If we don't have a currently active thread then don't execute instructions,
// instead advance to the next event and try to yield to the next thread
if (Kernel::GetCurrentThread() == nullptr) {
LOG_TRACE(Core_ARM, "Idling");
CoreTiming::Idle();
CoreTiming::Advance();
PrepareReschedule();
} else {
CoreTiming::Advance();
if (tight_loop) {
cpu_core->Run();
} else {
cpu_core->Step();
}
}
HW::Update();
Reschedule();
return status;
}
@@ -87,15 +82,15 @@ System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& file
app_loader = Loader::GetLoader(filepath);
if (!app_loader) {
NGLOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
LOG_CRITICAL(Core, "Failed to obtain loader for %s!", filepath.c_str());
return ResultStatus::ErrorGetLoader;
}
std::pair<boost::optional<u32>, Loader::ResultStatus> system_mode =
app_loader->LoadKernelSystemMode();
if (system_mode.second != Loader::ResultStatus::Success) {
NGLOG_CRITICAL(Core, "Failed to determine system mode (Error {})!",
static_cast<int>(system_mode.second));
LOG_CRITICAL(Core, "Failed to determine system mode (Error %i)!",
static_cast<int>(system_mode.second));
switch (system_mode.second) {
case Loader::ResultStatus::ErrorEncrypted:
@@ -111,15 +106,15 @@ System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& file
ResultStatus init_result{Init(emu_window, system_mode.first.get())};
if (init_result != ResultStatus::Success) {
NGLOG_CRITICAL(Core, "Failed to initialize system (Error {})!",
static_cast<int>(init_result));
LOG_CRITICAL(Core, "Failed to initialize system (Error %i)!",
static_cast<int>(init_result));
System::Shutdown();
return init_result;
}
const Loader::ResultStatus load_result{app_loader->Load(current_process)};
if (Loader::ResultStatus::Success != load_result) {
NGLOG_CRITICAL(Core, "Failed to load ROM (Error {})!", static_cast<int>(load_result));
LOG_CRITICAL(Core, "Failed to load ROM (Error %i)!", static_cast<int>(load_result));
System::Shutdown();
switch (load_result) {
@@ -138,46 +133,50 @@ System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& file
}
void System::PrepareReschedule() {
CurrentCpuCore().PrepareReschedule();
cpu_core->PrepareReschedule();
reschedule_pending = true;
}
PerfStats::Results System::GetAndResetPerfStats() {
return perf_stats.GetAndResetStats(CoreTiming::GetGlobalTimeUs());
}
const std::shared_ptr<Kernel::Scheduler>& System::Scheduler(size_t core_index) {
ASSERT(core_index < NUM_CPU_CORES);
return cpu_cores[core_index]->Scheduler();
}
void System::Reschedule() {
if (!reschedule_pending) {
return;
}
ARM_Interface& System::ArmInterface(size_t core_index) {
ASSERT(core_index < NUM_CPU_CORES);
return cpu_cores[core_index]->ArmInterface();
}
Cpu& System::CpuCore(size_t core_index) {
ASSERT(core_index < NUM_CPU_CORES);
return *cpu_cores[core_index];
reschedule_pending = false;
Core::System::GetInstance().Scheduler().Reschedule();
}
System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
NGLOG_DEBUG(HW_Memory, "initialized OK");
LOG_DEBUG(HW_Memory, "initialized OK");
CoreTiming::Init();
current_process = Kernel::Process::Create("main");
cpu_barrier = std::make_shared<CpuBarrier>();
for (size_t index = 0; index < cpu_cores.size(); ++index) {
cpu_cores[index] = std::make_shared<Cpu>(cpu_barrier, index);
if (Settings::values.use_cpu_jit) {
#ifdef ARCHITECTURE_x86_64
cpu_core = std::make_shared<ARM_Dynarmic>();
#else
cpu_core = std::make_shared<ARM_Unicorn>();
LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available");
#endif
} else {
cpu_core = std::make_shared<ARM_Unicorn>();
}
gpu_core = std::make_unique<Tegra::GPU>();
telemetry_session = std::make_unique<Core::TelemetrySession>();
service_manager = std::make_shared<Service::SM::ServiceManager>();
HW::Init();
Kernel::Init(system_mode);
scheduler = std::make_unique<Kernel::Scheduler>(cpu_core.get());
Service::Init(service_manager);
GDBStub::Init();
@@ -185,18 +184,7 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
return ResultStatus::ErrorVideoCore;
}
// Create threads for CPU cores 1-3, and build thread_to_cpu map
// CPU core 0 is run on the main thread
thread_to_cpu[std::this_thread::get_id()] = cpu_cores[0];
if (Settings::values.use_multi_core) {
for (size_t index = 0; index < cpu_core_threads.size(); ++index) {
cpu_core_threads[index] =
std::make_unique<std::thread>(RunCpuCore, cpu_cores[index + 1]);
thread_to_cpu[cpu_core_threads[index]->get_id()] = cpu_cores[index + 1];
}
}
NGLOG_DEBUG(Core, "Initialized OK");
LOG_DEBUG(Core, "Initialized OK");
// Reset counters and set time origin to current frame
GetAndResetPerfStats();
@@ -219,33 +207,18 @@ void System::Shutdown() {
VideoCore::Shutdown();
GDBStub::Shutdown();
Service::Shutdown();
scheduler.reset();
Kernel::Shutdown();
HW::Shutdown();
service_manager.reset();
telemetry_session.reset();
gpu_core.reset();
// Close all CPU/threading state
cpu_barrier->NotifyEnd();
if (Settings::values.use_multi_core) {
for (auto& thread : cpu_core_threads) {
thread->join();
thread.reset();
}
}
thread_to_cpu.clear();
for (auto& cpu_core : cpu_cores) {
cpu_core.reset();
}
cpu_barrier.reset();
// Close core timing
cpu_core.reset();
CoreTiming::Shutdown();
// Close app loader
app_loader.reset();
NGLOG_DEBUG(Core, "Shutdown OK");
LOG_DEBUG(Core, "Shutdown OK");
}
Service::SM::ServiceManager& System::ServiceManager() {

View File

@@ -4,12 +4,9 @@
#pragma once
#include <array>
#include <memory>
#include <string>
#include <thread>
#include "common/common_types.h"
#include "core/core_cpu.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/scheduler.h"
#include "core/loader/loader.h"
@@ -92,7 +89,7 @@ public:
* @returns True if the emulated system is powered on, otherwise false.
*/
bool IsPoweredOn() const {
return cpu_barrier && cpu_barrier->IsAlive();
return cpu_core != nullptr;
}
/**
@@ -106,34 +103,24 @@ public:
/// Prepare the core emulation for a reschedule
void PrepareReschedule();
/// Gets and resets core performance statistics
PerfStats::Results GetAndResetPerfStats();
/// Gets an ARM interface to the CPU core that is currently running
ARM_Interface& CurrentArmInterface() {
return CurrentCpuCore().ArmInterface();
/**
* Gets a reference to the emulated CPU.
* @returns A reference to the emulated CPU.
*/
ARM_Interface& CPU() {
return *cpu_core;
}
/// Gets an ARM interface to the CPU core with the specified index
ARM_Interface& ArmInterface(size_t core_index);
/// Gets a CPU interface to the CPU core with the specified index
Cpu& CpuCore(size_t core_index);
/// Gets the GPU interface
Tegra::GPU& GPU() {
return *gpu_core;
}
/// Gets the scheduler for the CPU core that is currently running
Kernel::Scheduler& CurrentScheduler() {
return *CurrentCpuCore().Scheduler();
Kernel::Scheduler& Scheduler() {
return *scheduler;
}
/// Gets the scheduler for the CPU core with the specified index
const std::shared_ptr<Kernel::Scheduler>& Scheduler(size_t core_index);
/// Gets the current process
Kernel::SharedPtr<Kernel::Process>& CurrentProcess() {
return current_process;
}
@@ -168,9 +155,6 @@ public:
}
private:
/// Returns the currently running CPU core
Cpu& CurrentCpuCore();
/**
* Initialize the emulated system.
* @param emu_window Pointer to the host-system window used for video output and keyboard input.
@@ -179,15 +163,22 @@ private:
*/
ResultStatus Init(EmuWindow* emu_window, u32 system_mode);
/// Reschedule the core emulation
void Reschedule();
/// AppLoader used to load the current executing application
std::unique_ptr<Loader::AppLoader> app_loader;
std::shared_ptr<ARM_Interface> cpu_core;
std::unique_ptr<Kernel::Scheduler> scheduler;
std::unique_ptr<Tegra::GPU> gpu_core;
std::shared_ptr<Tegra::DebugContext> debug_context;
Kernel::SharedPtr<Kernel::Process> current_process;
std::shared_ptr<CpuBarrier> cpu_barrier;
std::array<std::shared_ptr<Cpu>, NUM_CPU_CORES> cpu_cores;
std::array<std::unique_ptr<std::thread>, NUM_CPU_CORES - 1> cpu_core_threads;
size_t active_core{}; ///< Active core, only used in single thread mode
/// When true, signals that a reschedule should happen
bool reschedule_pending{};
/// Service manager
std::shared_ptr<Service::SM::ServiceManager> service_manager;
@@ -199,13 +190,10 @@ private:
ResultStatus status = ResultStatus::Success;
std::string status_details = "";
/// Map of guest threads to CPU cores
std::map<std::thread::id, std::shared_ptr<Cpu>> thread_to_cpu;
};
inline ARM_Interface& CurrentArmInterface() {
return System::GetInstance().CurrentArmInterface();
inline ARM_Interface& CPU() {
return System::GetInstance().CPU();
}
inline TelemetrySession& Telemetry() {

View File

@@ -1,119 +0,0 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <condition_variable>
#include <mutex>
#include "common/logging/log.h"
#ifdef ARCHITECTURE_x86_64
#include "core/arm/dynarmic/arm_dynarmic.h"
#endif
#include "core/arm/unicorn/arm_unicorn.h"
#include "core/core_cpu.h"
#include "core/core_timing.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/scheduler.h"
#include "core/hle/kernel/thread.h"
#include "core/settings.h"
namespace Core {
void CpuBarrier::NotifyEnd() {
std::unique_lock<std::mutex> lock(mutex);
end = true;
condition.notify_all();
}
bool CpuBarrier::Rendezvous() {
if (!Settings::values.use_multi_core) {
// Meaningless when running in single-core mode
return true;
}
if (!end) {
std::unique_lock<std::mutex> lock(mutex);
--cores_waiting;
if (!cores_waiting) {
cores_waiting = NUM_CPU_CORES;
condition.notify_all();
return true;
}
condition.wait(lock);
return true;
}
return false;
}
Cpu::Cpu(std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index)
: cpu_barrier{std::move(cpu_barrier)}, core_index{core_index} {
if (Settings::values.use_cpu_jit) {
#ifdef ARCHITECTURE_x86_64
arm_interface = std::make_shared<ARM_Dynarmic>();
#else
cpu_core = std::make_shared<ARM_Unicorn>();
NGLOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available");
#endif
} else {
arm_interface = std::make_shared<ARM_Unicorn>();
}
scheduler = std::make_shared<Kernel::Scheduler>(arm_interface.get());
}
void Cpu::RunLoop(bool tight_loop) {
// Wait for all other CPU cores to complete the previous slice, such that they run in lock-step
if (!cpu_barrier->Rendezvous()) {
// If rendezvous failed, session has been killed
return;
}
// If we don't have a currently active thread then don't execute instructions,
// instead advance to the next event and try to yield to the next thread
if (Kernel::GetCurrentThread() == nullptr) {
NGLOG_TRACE(Core, "Core-{} idling", core_index);
if (IsMainCore()) {
CoreTiming::Idle();
CoreTiming::Advance();
}
PrepareReschedule();
} else {
if (IsMainCore()) {
CoreTiming::Advance();
}
if (tight_loop) {
arm_interface->Run();
} else {
arm_interface->Step();
}
}
Reschedule();
}
void Cpu::SingleStep() {
return RunLoop(false);
}
void Cpu::PrepareReschedule() {
arm_interface->PrepareReschedule();
reschedule_pending = true;
}
void Cpu::Reschedule() {
if (!reschedule_pending) {
return;
}
reschedule_pending = false;
scheduler->Reschedule();
}
} // namespace Core

View File

@@ -1,78 +0,0 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <atomic>
#include <condition_variable>
#include <memory>
#include <mutex>
#include <string>
#include "common/common_types.h"
class ARM_Interface;
namespace Kernel {
class Scheduler;
}
namespace Core {
constexpr unsigned NUM_CPU_CORES{4};
class CpuBarrier {
public:
bool IsAlive() const {
return !end;
}
void NotifyEnd();
bool Rendezvous();
private:
unsigned cores_waiting{NUM_CPU_CORES};
std::mutex mutex;
std::condition_variable condition;
std::atomic<bool> end{};
};
class Cpu {
public:
Cpu(std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index);
void RunLoop(bool tight_loop = true);
void SingleStep();
void PrepareReschedule();
ARM_Interface& ArmInterface() {
return *arm_interface;
}
const ARM_Interface& ArmInterface() const {
return *arm_interface;
}
const std::shared_ptr<Kernel::Scheduler>& Scheduler() const {
return scheduler;
}
bool IsMainCore() const {
return core_index == 0;
}
private:
void Reschedule();
std::shared_ptr<ARM_Interface> arm_interface;
std::shared_ptr<CpuBarrier> cpu_barrier;
std::shared_ptr<Kernel::Scheduler> scheduler;
bool reschedule_pending{};
size_t core_index;
};
} // namespace Core

View File

@@ -6,7 +6,6 @@
#include <algorithm>
#include <cinttypes>
#include <limits>
#include <mutex>
#include <string>
#include <tuple>
@@ -58,8 +57,7 @@ static u64 event_fifo_id;
// to the event_queue by the emu thread
static Common::MPSCQueue<Event, false> ts_queue;
constexpr int MAX_SLICE_LENGTH = 20000;
constexpr u64 MAX_VALUE_TO_MULTIPLY = std::numeric_limits<s64>::max() / BASE_CLOCK_RATE;
static constexpr int MAX_SLICE_LENGTH = 20000;
static s64 idled_cycles;
@@ -72,59 +70,11 @@ static EventType* ev_lost = nullptr;
static void EmptyTimedCallback(u64 userdata, s64 cyclesLate) {}
s64 usToCycles(s64 us) {
if (us / 1000000 > MAX_VALUE_TO_MULTIPLY) {
NGLOG_ERROR(Core_Timing, "Integer overflow, use max value");
return std::numeric_limits<s64>::max();
}
if (us > MAX_VALUE_TO_MULTIPLY) {
NGLOG_DEBUG(Core_Timing, "Time very big, do rounding");
return BASE_CLOCK_RATE * (us / 1000000);
}
return (BASE_CLOCK_RATE * us) / 1000000;
}
s64 usToCycles(u64 us) {
if (us / 1000000 > MAX_VALUE_TO_MULTIPLY) {
NGLOG_ERROR(Core_Timing, "Integer overflow, use max value");
return std::numeric_limits<s64>::max();
}
if (us > MAX_VALUE_TO_MULTIPLY) {
NGLOG_DEBUG(Core_Timing, "Time very big, do rounding");
return BASE_CLOCK_RATE * static_cast<s64>(us / 1000000);
}
return (BASE_CLOCK_RATE * static_cast<s64>(us)) / 1000000;
}
s64 nsToCycles(s64 ns) {
if (ns / 1000000000 > MAX_VALUE_TO_MULTIPLY) {
NGLOG_ERROR(Core_Timing, "Integer overflow, use max value");
return std::numeric_limits<s64>::max();
}
if (ns > MAX_VALUE_TO_MULTIPLY) {
NGLOG_DEBUG(Core_Timing, "Time very big, do rounding");
return BASE_CLOCK_RATE * (ns / 1000000000);
}
return (BASE_CLOCK_RATE * ns) / 1000000000;
}
s64 nsToCycles(u64 ns) {
if (ns / 1000000000 > MAX_VALUE_TO_MULTIPLY) {
NGLOG_ERROR(Core_Timing, "Integer overflow, use max value");
return std::numeric_limits<s64>::max();
}
if (ns > MAX_VALUE_TO_MULTIPLY) {
NGLOG_DEBUG(Core_Timing, "Time very big, do rounding");
return BASE_CLOCK_RATE * (static_cast<s64>(ns) / 1000000000);
}
return (BASE_CLOCK_RATE * static_cast<s64>(ns)) / 1000000000;
}
EventType* RegisterEvent(const std::string& name, TimedCallback callback) {
// check for existing type with same name.
// we want event type names to remain unique so that we can use them for serialization.
ASSERT_MSG(event_types.find(name) == event_types.end(),
"CoreTiming Event \"{}\" is already registered. Events should only be registered "
"CoreTiming Event \"%s\" is already registered. Events should only be registered "
"during Init to avoid breaking save states.",
name.c_str());

View File

@@ -18,14 +18,15 @@
*/
#include <functional>
#include <limits>
#include <string>
#include "common/common_types.h"
namespace CoreTiming {
#include "common/logging/log.h"
// The below clock rate is based on Switch's clockspeed being widely known as 1.020GHz
// The exact value used is of course unverified.
constexpr u64 BASE_CLOCK_RATE = 1019215872; // Switch clock speed is 1020MHz un/docked
constexpr u64 MAX_VALUE_TO_MULTIPLY = std::numeric_limits<s64>::max() / BASE_CLOCK_RATE;
inline s64 msToCycles(int ms) {
// since ms is int there is no way to overflow
@@ -48,9 +49,29 @@ inline s64 usToCycles(int us) {
return (BASE_CLOCK_RATE * static_cast<s64>(us) / 1000000);
}
s64 usToCycles(s64 us);
inline s64 usToCycles(s64 us) {
if (us / 1000000 > MAX_VALUE_TO_MULTIPLY) {
LOG_ERROR(Core_Timing, "Integer overflow, use max value");
return std::numeric_limits<s64>::max();
}
if (us > MAX_VALUE_TO_MULTIPLY) {
LOG_DEBUG(Core_Timing, "Time very big, do rounding");
return BASE_CLOCK_RATE * (us / 1000000);
}
return (BASE_CLOCK_RATE * us) / 1000000;
}
s64 usToCycles(u64 us);
inline s64 usToCycles(u64 us) {
if (us / 1000000 > MAX_VALUE_TO_MULTIPLY) {
LOG_ERROR(Core_Timing, "Integer overflow, use max value");
return std::numeric_limits<s64>::max();
}
if (us > MAX_VALUE_TO_MULTIPLY) {
LOG_DEBUG(Core_Timing, "Time very big, do rounding");
return BASE_CLOCK_RATE * static_cast<s64>(us / 1000000);
}
return (BASE_CLOCK_RATE * static_cast<s64>(us)) / 1000000;
}
inline s64 nsToCycles(float ns) {
return static_cast<s64>(BASE_CLOCK_RATE * (0.000000001f) * ns);
@@ -60,9 +81,29 @@ inline s64 nsToCycles(int ns) {
return BASE_CLOCK_RATE * static_cast<s64>(ns) / 1000000000;
}
s64 nsToCycles(s64 ns);
inline s64 nsToCycles(s64 ns) {
if (ns / 1000000000 > MAX_VALUE_TO_MULTIPLY) {
LOG_ERROR(Core_Timing, "Integer overflow, use max value");
return std::numeric_limits<s64>::max();
}
if (ns > MAX_VALUE_TO_MULTIPLY) {
LOG_DEBUG(Core_Timing, "Time very big, do rounding");
return BASE_CLOCK_RATE * (ns / 1000000000);
}
return (BASE_CLOCK_RATE * ns) / 1000000000;
}
s64 nsToCycles(u64 ns);
inline s64 nsToCycles(u64 ns) {
if (ns / 1000000000 > MAX_VALUE_TO_MULTIPLY) {
LOG_ERROR(Core_Timing, "Integer overflow, use max value");
return std::numeric_limits<s64>::max();
}
if (ns > MAX_VALUE_TO_MULTIPLY) {
LOG_DEBUG(Core_Timing, "Time very big, do rounding");
return BASE_CLOCK_RATE * (static_cast<s64>(ns) / 1000000000);
}
return (BASE_CLOCK_RATE * static_cast<s64>(ns)) / 1000000000;
}
inline u64 cyclesToNs(s64 cycles) {
return cycles * 1000000000 / BASE_CLOCK_RATE;
@@ -76,6 +117,8 @@ inline u64 cyclesToMs(s64 cycles) {
return cycles * 1000 / BASE_CLOCK_RATE;
}
namespace CoreTiming {
/**
* CoreTiming begins at the boundary of timing slice -1. An initial call to Advance() is
* required to end slice -1 and start slice 0 before the first cycle of code is executed.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -59,7 +59,7 @@ template <typename InputDeviceType>
void RegisterFactory(const std::string& name, std::shared_ptr<Factory<InputDeviceType>> factory) {
auto pair = std::make_pair(name, std::move(factory));
if (!Impl::FactoryList<InputDeviceType>::list.insert(std::move(pair)).second) {
NGLOG_ERROR(Input, "Factory '{}' already registered", name);
LOG_ERROR(Input, "Factory %s already registered", name.c_str());
}
}
@@ -71,7 +71,7 @@ void RegisterFactory(const std::string& name, std::shared_ptr<Factory<InputDevic
template <typename InputDeviceType>
void UnregisterFactory(const std::string& name) {
if (Impl::FactoryList<InputDeviceType>::list.erase(name) == 0) {
NGLOG_ERROR(Input, "Factory '{}' not registered", name);
LOG_ERROR(Input, "Factory %s not registered", name.c_str());
}
}
@@ -88,7 +88,7 @@ std::unique_ptr<InputDeviceType> CreateDevice(const std::string& params) {
const auto pair = factory_list.find(engine);
if (pair == factory_list.end()) {
if (engine != "null") {
NGLOG_ERROR(Input, "Unknown engine name: {}", engine);
LOG_ERROR(Input, "Unknown engine name: %s", engine.c_str());
}
return std::make_unique<InputDeviceType>();
}

View File

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

View File

@@ -29,14 +29,9 @@ enum class ControlCommand : u32 {
};
enum class CommandType : u32 {
Invalid = 0,
LegacyRequest = 1,
Close = 2,
LegacyControl = 3,
Request = 4,
Control = 5,
RequestWithContext = 6,
ControlWithContext = 7,
Unspecified,
};
@@ -172,7 +167,6 @@ struct DomainMessageHeader {
struct {
union {
BitField<0, 8, CommandType> command;
BitField<8, 8, u32_le> input_object_count;
BitField<16, 16, u32_le> size;
};
u32_le object_id;

View File

@@ -298,13 +298,6 @@ public:
template <typename T>
Kernel::SharedPtr<T> GetCopyObject(size_t index);
template <class T>
std::shared_ptr<T> PopIpcInterface() {
ASSERT(context->Session()->IsDomain());
ASSERT(context->GetDomainMessageHeader()->input_object_count > 0);
return context->GetDomainRequestHandler<T>(Pop<u32>() - 1);
}
};
/// Pop ///

View File

@@ -21,9 +21,7 @@ enum {
// Confirmed Switch OS error codes
MisalignedAddress = 102,
InvalidProcessorId = 113,
InvalidHandle = 114,
InvalidCombination = 116,
Timeout = 117,
SynchronizationCanceled = 118,
TooLarge = 119,

View File

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

View File

@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <cinttypes>
#include <boost/range/algorithm_ext/erase.hpp>
#include "common/assert.h"
#include "common/common_funcs.h"
@@ -110,9 +111,7 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) {
// Padding to align to 16 bytes
rp.AlignWithPadding();
if (Session()->IsDomain() && ((command_header->type == IPC::CommandType::Request ||
command_header->type == IPC::CommandType::RequestWithContext) ||
!incoming)) {
if (Session()->IsDomain() && (command_header->type == IPC::CommandType::Request || !incoming)) {
// If this is an incoming message, only CommandType "Request" has a domain header
// All outgoing domain messages have the domain header, if only incoming has it
if (incoming || domain_message_header) {
@@ -120,7 +119,7 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) {
std::make_shared<IPC::DomainMessageHeader>(rp.PopRaw<IPC::DomainMessageHeader>());
} else {
if (Session()->IsDomain())
NGLOG_WARNING(IPC, "Domain request has no DomainMessageHeader!");
LOG_WARNING(IPC, "Domain request has no DomainMessageHeader!");
}
}
@@ -253,55 +252,50 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(Thread& thread) {
return RESULT_SUCCESS;
}
std::vector<u8> HLERequestContext::ReadBuffer(int buffer_index) const {
std::vector<u8> HLERequestContext::ReadBuffer() const {
std::vector<u8> buffer;
const bool is_buffer_a{BufferDescriptorA().size() && BufferDescriptorA()[buffer_index].Size()};
const bool is_buffer_a{BufferDescriptorA().size() && BufferDescriptorA()[0].Size()};
if (is_buffer_a) {
buffer.resize(BufferDescriptorA()[buffer_index].Size());
Memory::ReadBlock(BufferDescriptorA()[buffer_index].Address(), buffer.data(),
buffer.size());
buffer.resize(BufferDescriptorA()[0].Size());
Memory::ReadBlock(BufferDescriptorA()[0].Address(), buffer.data(), buffer.size());
} else {
buffer.resize(BufferDescriptorX()[buffer_index].Size());
Memory::ReadBlock(BufferDescriptorX()[buffer_index].Address(), buffer.data(),
buffer.size());
buffer.resize(BufferDescriptorX()[0].Size());
Memory::ReadBlock(BufferDescriptorX()[0].Address(), buffer.data(), buffer.size());
}
return buffer;
}
size_t HLERequestContext::WriteBuffer(const void* buffer, size_t size, int buffer_index) const {
const bool is_buffer_b{BufferDescriptorB().size() && BufferDescriptorB()[buffer_index].Size()};
const size_t buffer_size{GetWriteBufferSize(buffer_index)};
size_t HLERequestContext::WriteBuffer(const void* buffer, size_t size) const {
const bool is_buffer_b{BufferDescriptorB().size() && BufferDescriptorB()[0].Size()};
const size_t buffer_size{GetWriteBufferSize()};
if (size > buffer_size) {
NGLOG_CRITICAL(Core, "size ({:016X}) is greater than buffer_size ({:016X})", size,
buffer_size);
LOG_CRITICAL(Core, "size (%016zx) is greater than buffer_size (%016zx)", size, buffer_size);
size = buffer_size; // TODO(bunnei): This needs to be HW tested
}
if (is_buffer_b) {
Memory::WriteBlock(BufferDescriptorB()[buffer_index].Address(), buffer, size);
Memory::WriteBlock(BufferDescriptorB()[0].Address(), buffer, size);
} else {
Memory::WriteBlock(BufferDescriptorC()[buffer_index].Address(), buffer, size);
Memory::WriteBlock(BufferDescriptorC()[0].Address(), buffer, size);
}
return size;
}
size_t HLERequestContext::WriteBuffer(const std::vector<u8>& buffer, int buffer_index) const {
size_t HLERequestContext::WriteBuffer(const std::vector<u8>& buffer) const {
return WriteBuffer(buffer.data(), buffer.size());
}
size_t HLERequestContext::GetReadBufferSize(int buffer_index) const {
const bool is_buffer_a{BufferDescriptorA().size() && BufferDescriptorA()[buffer_index].Size()};
return is_buffer_a ? BufferDescriptorA()[buffer_index].Size()
: BufferDescriptorX()[buffer_index].Size();
size_t HLERequestContext::GetReadBufferSize() const {
const bool is_buffer_a{BufferDescriptorA().size() && BufferDescriptorA()[0].Size()};
return is_buffer_a ? BufferDescriptorA()[0].Size() : BufferDescriptorX()[0].Size();
}
size_t HLERequestContext::GetWriteBufferSize(int buffer_index) const {
const bool is_buffer_b{BufferDescriptorB().size() && BufferDescriptorB()[buffer_index].Size()};
return is_buffer_b ? BufferDescriptorB()[buffer_index].Size()
: BufferDescriptorC()[buffer_index].Size();
size_t HLERequestContext::GetWriteBufferSize() const {
const bool is_buffer_b{BufferDescriptorB().size() && BufferDescriptorB()[0].Size()};
return is_buffer_b ? BufferDescriptorB()[0].Size() : BufferDescriptorC()[0].Size();
}
std::string HLERequestContext::Description() const {

View File

@@ -164,19 +164,19 @@ public:
}
/// Helper function to read a buffer using the appropriate buffer descriptor
std::vector<u8> ReadBuffer(int buffer_index = 0) const;
std::vector<u8> ReadBuffer() const;
/// Helper function to write a buffer using the appropriate buffer descriptor
size_t WriteBuffer(const void* buffer, size_t size, int buffer_index = 0) const;
size_t WriteBuffer(const void* buffer, size_t size) const;
/// Helper function to write a buffer using the appropriate buffer descriptor
size_t WriteBuffer(const std::vector<u8>& buffer, int buffer_index = 0) const;
size_t WriteBuffer(const std::vector<u8>& buffer) const;
/// Helper function to get the size of the input buffer
size_t GetReadBufferSize(int buffer_index = 0) const;
size_t GetReadBufferSize() const;
/// Helper function to get the size of the output buffer
size_t GetWriteBufferSize(int buffer_index = 0) const;
size_t GetWriteBufferSize() const;
template <typename T>
SharedPtr<T> GetCopyObject(size_t index) {
@@ -202,16 +202,6 @@ public:
domain_objects.emplace_back(std::move(object));
}
template <typename T>
std::shared_ptr<T> GetDomainRequestHandler(size_t index) const {
return std::static_pointer_cast<T>(domain_request_handlers[index]);
}
void SetDomainRequestHandlers(
const std::vector<std::shared_ptr<SessionRequestHandler>>& handlers) {
domain_request_handlers = handlers;
}
/// Clears the list of objects so that no lingering objects are written accidentally to the
/// response buffer.
void ClearIncomingObjects() {
@@ -255,8 +245,6 @@ private:
unsigned data_payload_offset{};
unsigned buffer_c_offset{};
u32_le command{};
std::vector<std::shared_ptr<SessionRequestHandler>> domain_request_handlers;
};
} // namespace Kernel

View File

@@ -104,6 +104,7 @@ ResultCode Mutex::Release(VAddr address) {
// There are no more threads waiting for the mutex, release it completely.
if (thread == nullptr) {
ASSERT(GetCurrentThread()->wait_mutex_threads.empty());
Memory::Write32(address, 0);
return RESULT_SUCCESS;
}

View File

@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <cinttypes>
#include "common/assert.h"
#include "core/hle/kernel/object_address_table.h"
@@ -10,12 +11,14 @@ namespace Kernel {
ObjectAddressTable g_object_address_table;
void ObjectAddressTable::Insert(VAddr addr, SharedPtr<Object> obj) {
ASSERT_MSG(objects.find(addr) == objects.end(), "Object already exists with addr=0x{:X}", addr);
ASSERT_MSG(objects.find(addr) == objects.end(), "Object already exists with addr=0x%" PRIx64,
addr);
objects[addr] = obj;
}
void ObjectAddressTable::Close(VAddr addr) {
ASSERT_MSG(objects.find(addr) != objects.end(), "Object does not exist with addr=0x{:X}", addr);
ASSERT_MSG(objects.find(addr) != objects.end(), "Object does not exist with addr=0x%" PRIx64,
addr);
objects.erase(addr);
}

View File

@@ -54,7 +54,7 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
continue;
} else if ((type & 0xF00) == 0xE00) { // 0x0FFF
// Allowed interrupts list
NGLOG_WARNING(Loader, "ExHeader allowed interrupts list ignored");
LOG_WARNING(Loader, "ExHeader allowed interrupts list ignored");
} else if ((type & 0xF80) == 0xF00) { // 0x07FF
// Allowed syscalls mask
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
// Mapped memory range
if (i + 1 >= len || ((kernel_caps[i + 1] >> 20) & 0xFFE) != 0xFF8) {
NGLOG_WARNING(Loader, "Incomplete exheader memory range descriptor ignored.");
LOG_WARNING(Loader, "Incomplete exheader memory range descriptor ignored.");
continue;
}
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 major = (kernel_version >> 8) & 0xFF;
NGLOG_INFO(Loader, "ExHeader kernel version: {}.{}", major, minor);
LOG_INFO(Loader, "ExHeader kernel version: %d.%d", major, minor);
} else {
NGLOG_ERROR(Loader, "Unhandled kernel caps descriptor: 0x{:08X}", descriptor);
LOG_ERROR(Loader, "Unhandled kernel caps descriptor: 0x%08X", descriptor);
}
}
}
@@ -134,7 +134,7 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) {
HandleSpecialMapping(vm_manager, mapping);
}
vm_manager.LogLayout();
vm_manager.LogLayout(Log::Level::Debug);
status = ProcessStatus::Running;
Kernel::SetupMainThread(entry_point, main_thread_priority, this);

View File

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

View File

@@ -9,8 +9,6 @@
namespace Kernel {
std::mutex Scheduler::scheduler_mutex;
Scheduler::Scheduler(ARM_Interface* cpu_core) : cpu_core(cpu_core) {}
Scheduler::~Scheduler() {
@@ -20,7 +18,6 @@ Scheduler::~Scheduler() {
}
bool Scheduler::HaveReadyThreads() {
std::lock_guard<std::mutex> lock(scheduler_mutex);
return ready_queue.get_first() != nullptr;
}
@@ -93,53 +90,41 @@ void Scheduler::SwitchContext(Thread* new_thread) {
}
void Scheduler::Reschedule() {
std::lock_guard<std::mutex> lock(scheduler_mutex);
Thread* cur = GetCurrentThread();
Thread* next = PopNextReadyThread();
if (cur && next) {
NGLOG_TRACE(Kernel, "context switch {} -> {}", cur->GetObjectId(), next->GetObjectId());
LOG_TRACE(Kernel, "context switch %u -> %u", cur->GetObjectId(), next->GetObjectId());
} else if (cur) {
NGLOG_TRACE(Kernel, "context switch {} -> idle", cur->GetObjectId());
LOG_TRACE(Kernel, "context switch %u -> idle", cur->GetObjectId());
} else if (next) {
NGLOG_TRACE(Kernel, "context switch idle -> {}", next->GetObjectId());
LOG_TRACE(Kernel, "context switch idle -> %u", next->GetObjectId());
}
SwitchContext(next);
}
void Scheduler::AddThread(SharedPtr<Thread> thread, u32 priority) {
std::lock_guard<std::mutex> lock(scheduler_mutex);
thread_list.push_back(thread);
ready_queue.prepare(priority);
}
void Scheduler::RemoveThread(Thread* thread) {
std::lock_guard<std::mutex> lock(scheduler_mutex);
thread_list.erase(std::remove(thread_list.begin(), thread_list.end(), thread),
thread_list.end());
}
void Scheduler::ScheduleThread(Thread* thread, u32 priority) {
std::lock_guard<std::mutex> lock(scheduler_mutex);
ASSERT(thread->status == THREADSTATUS_READY);
ready_queue.push_back(priority, thread);
}
void Scheduler::UnscheduleThread(Thread* thread, u32 priority) {
std::lock_guard<std::mutex> lock(scheduler_mutex);
ASSERT(thread->status == THREADSTATUS_READY);
ready_queue.remove(priority, thread);
}
void Scheduler::SetThreadPriority(Thread* thread, u32 priority) {
std::lock_guard<std::mutex> lock(scheduler_mutex);
// If thread was ready, adjust queues
if (thread->status == THREADSTATUS_READY)
ready_queue.move(thread, thread->current_priority, priority);

View File

@@ -4,7 +4,6 @@
#pragma once
#include <mutex>
#include <vector>
#include "common/common_types.h"
#include "common/thread_queue_list.h"
@@ -69,8 +68,6 @@ private:
SharedPtr<Thread> current_thread = nullptr;
ARM_Interface* cpu_core;
static std::mutex scheduler_mutex;
};
} // namespace Kernel

View File

@@ -61,9 +61,6 @@ void ServerSession::Acquire(Thread* thread) {
ResultCode ServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& context) {
auto& domain_message_header = context.GetDomainMessageHeader();
if (domain_message_header) {
// Set domain handlers in HLE context, used for domain objects (IPC interfaces) as inputs
context.SetDomainRequestHandlers(domain_request_handlers);
// If there is a DomainMessageHeader, then this is CommandType "Request"
const u32 object_id{context.GetDomainMessageHeader()->object_id};
switch (domain_message_header->command) {
@@ -71,7 +68,7 @@ ResultCode ServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& con
return domain_request_handlers[object_id - 1]->HandleSyncRequest(context);
case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: {
NGLOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id);
LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x%08X", object_id);
domain_request_handlers[object_id - 1] = nullptr;
@@ -81,8 +78,8 @@ ResultCode ServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& con
}
}
NGLOG_CRITICAL(IPC, "Unknown domain command={}",
static_cast<int>(domain_message_header->command.Value()));
LOG_CRITICAL(IPC, "Unknown domain command=%d",
static_cast<int>(domain_message_header->command.Value()));
ASSERT(false);
}

View File

@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <cinttypes>
#include <cstring>
#include "common/logging/log.h"
#include "core/core.h"
@@ -107,16 +108,18 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
// 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)) {
NGLOG_ERROR(Kernel, "cannot map id={}, address=0x{:X} name={}, permissions don't match",
GetObjectId(), address, name);
LOG_ERROR(Kernel,
"cannot map id=%u, address=0x%" PRIx64 " name=%s, permissions don't match",
GetObjectId(), address, name.c_str());
return ERR_INVALID_COMBINATION;
}
// Error out if the provided permissions are not compatible with what the creator process needs.
if (other_permissions != MemoryPermission::DontCare &&
static_cast<u32>(this->permissions) & ~static_cast<u32>(other_permissions)) {
NGLOG_ERROR(Kernel, "cannot map id={}, address=0x{:X} name={}, permissions don't match",
GetObjectId(), address, name);
LOG_ERROR(Kernel,
"cannot map id=%u, address=0x%" PRIx64 " name=%s, permissions don't match",
GetObjectId(), address, name.c_str());
return ERR_WRONG_PERMISSION;
}
@@ -131,10 +134,10 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
auto result = target_process->vm_manager.MapMemoryBlock(
target_address, backing_block, backing_block_offset, size, MemoryState::Shared);
if (result.Failed()) {
NGLOG_ERROR(
Kernel,
"cannot map id={}, target_address=0x{:X} name={}, error mapping to virtual memory",
GetObjectId(), target_address, name);
LOG_ERROR(Kernel,
"cannot map id=%u, target_address=0x%" PRIx64
" name=%s, error mapping to virtual memory",
GetObjectId(), target_address, name.c_str());
return result.Code();
}
@@ -152,7 +155,7 @@ VMAPermission SharedMemory::ConvertPermissions(MemoryPermission permission) {
u32 masked_permissions =
static_cast<u32>(permission) & static_cast<u32>(MemoryPermission::ReadWriteExecute);
return static_cast<VMAPermission>(masked_permissions);
}
};
u8* SharedMemory::GetPointer(u32 offset) {
return backing_block->data() + backing_block_offset + offset;

View File

@@ -31,7 +31,7 @@ namespace Kernel {
/// Set the process heap to a given Size. It can both extend and shrink the heap.
static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) {
NGLOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", heap_size);
LOG_TRACE(Kernel_SVC, "called, heap_size=0x%llx", heap_size);
auto& process = *Core::CurrentProcess();
CASCADE_RESULT(*heap_addr,
process.HeapAllocate(Memory::HEAP_VADDR, heap_size, VMAPermission::ReadWrite));
@@ -39,21 +39,21 @@ static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) {
}
static ResultCode SetMemoryAttribute(VAddr addr, u64 size, u32 state0, u32 state1) {
NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, addr=0x{:X}", addr);
LOG_WARNING(Kernel_SVC, "(STUBBED) called, addr=0x%" PRIx64, addr);
return RESULT_SUCCESS;
}
/// Maps a memory range into a different range.
static ResultCode MapMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
NGLOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
src_addr, size);
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x%llx, src_addr=0x%llx, size=0x%llx", dst_addr,
src_addr, size);
return Core::CurrentProcess()->MirrorMemory(dst_addr, src_addr, size);
}
/// Unmaps a region that was previously mapped with svcMapMemory
static ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
NGLOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
src_addr, size);
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x%llx, src_addr=0x%llx, size=0x%llx", dst_addr,
src_addr, size);
return Core::CurrentProcess()->UnmapMemory(dst_addr, src_addr, size);
}
@@ -68,11 +68,11 @@ static ResultCode ConnectToNamedPort(Handle* out_handle, VAddr port_name_address
if (port_name.size() > PortNameMaxLength)
return ERR_PORT_NAME_TOO_LONG;
NGLOG_TRACE(Kernel_SVC, "called port_name={}", port_name);
LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name.c_str());
auto it = Service::g_kernel_named_ports.find(port_name);
if (it == Service::g_kernel_named_ports.end()) {
NGLOG_WARNING(Kernel_SVC, "tried to connect to unknown port: {}", port_name);
LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: %s", port_name.c_str());
return ERR_NOT_FOUND;
}
@@ -90,11 +90,11 @@ static ResultCode ConnectToNamedPort(Handle* out_handle, VAddr port_name_address
static ResultCode SendSyncRequest(Handle handle) {
SharedPtr<ClientSession> session = g_handle_table.Get<ClientSession>(handle);
if (!session) {
NGLOG_ERROR(Kernel_SVC, "called with invalid handle=0x{:08X}", handle);
LOG_ERROR(Kernel_SVC, "called with invalid handle=0x%08X", handle);
return ERR_INVALID_HANDLE;
}
NGLOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName());
LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s)", handle, session->GetName().c_str());
Core::System::GetInstance().PrepareReschedule();
@@ -105,7 +105,7 @@ static ResultCode SendSyncRequest(Handle handle) {
/// Get the ID for the specified thread.
static ResultCode GetThreadId(u32* thread_id, Handle thread_handle) {
NGLOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle);
const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
if (!thread) {
@@ -118,7 +118,7 @@ static ResultCode GetThreadId(u32* thread_id, Handle thread_handle) {
/// Get the ID of the specified process
static ResultCode GetProcessId(u32* process_id, Handle process_handle) {
NGLOG_TRACE(Kernel_SVC, "called process=0x{:08X}", process_handle);
LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle);
const SharedPtr<Process> process = g_handle_table.Get<Process>(process_handle);
if (!process) {
@@ -145,11 +145,41 @@ static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thr
return true;
};
/// Wait for a kernel object to synchronize, timeout after the specified nanoseconds
static ResultCode WaitSynchronization1(
SharedPtr<WaitObject> object, Thread* thread, s64 nano_seconds = -1,
std::function<Thread::WakeupCallback> wakeup_callback = DefaultThreadWakeupCallback) {
if (!object) {
return ERR_INVALID_HANDLE;
}
if (object->ShouldWait(thread)) {
if (nano_seconds == 0) {
return RESULT_TIMEOUT;
}
thread->wait_objects = {object};
object->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 = wakeup_callback;
Core::System::GetInstance().PrepareReschedule();
} else {
object->Acquire(thread);
}
return RESULT_SUCCESS;
}
/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64 handle_count,
s64 nano_seconds) {
NGLOG_TRACE(Kernel_SVC, "called handles_address=0x{:X}, handle_count={}, nano_seconds={}",
handles_address, handle_count, nano_seconds);
LOG_TRACE(Kernel_SVC, "called handles_address=0x%llx, handle_count=%d, nano_seconds=%d",
handles_address, handle_count, nano_seconds);
if (!Memory::IsValidVirtualAddress(handles_address))
return ERR_INVALID_POINTER;
@@ -202,14 +232,14 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64
thread->WakeAfterDelay(nano_seconds);
thread->wakeup_callback = DefaultThreadWakeupCallback;
Core::System::GetInstance().CpuCore(thread->processor_id).PrepareReschedule();
Core::System::GetInstance().PrepareReschedule();
return RESULT_TIMEOUT;
}
/// Resumes a thread waiting on WaitSynchronization
static ResultCode CancelSynchronization(Handle thread_handle) {
NGLOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle);
LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle);
const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
if (!thread) {
@@ -226,38 +256,38 @@ static ResultCode CancelSynchronization(Handle thread_handle) {
/// Attempts to locks a mutex, creating it if it does not already exist
static ResultCode ArbitrateLock(Handle holding_thread_handle, VAddr mutex_addr,
Handle requesting_thread_handle) {
NGLOG_TRACE(Kernel_SVC,
"called holding_thread_handle=0x{:08X}, mutex_addr=0x{:X}, "
"requesting_current_thread_handle=0x{:08X}",
holding_thread_handle, mutex_addr, requesting_thread_handle);
LOG_TRACE(Kernel_SVC,
"called holding_thread_handle=0x%08X, mutex_addr=0x%llx, "
"requesting_current_thread_handle=0x%08X",
holding_thread_handle, mutex_addr, requesting_thread_handle);
return Mutex::TryAcquire(mutex_addr, holding_thread_handle, requesting_thread_handle);
}
/// Unlock a mutex
static ResultCode ArbitrateUnlock(VAddr mutex_addr) {
NGLOG_TRACE(Kernel_SVC, "called mutex_addr=0x{:X}", mutex_addr);
LOG_TRACE(Kernel_SVC, "called mutex_addr=0x%llx", mutex_addr);
return Mutex::Release(mutex_addr);
}
/// Break program execution
static void Break(u64 unk_0, u64 unk_1, u64 unk_2) {
NGLOG_CRITICAL(Debug_Emulated, "Emulated program broke execution!");
LOG_CRITICAL(Debug_Emulated, "Emulated program broke execution!");
ASSERT(false);
}
/// Used to output a message on a debug hardware unit - does nothing on a retail unit
static void OutputDebugString(VAddr address, s32 len) {
std::string str(len, '\0');
Memory::ReadBlock(address, str.data(), str.size());
NGLOG_DEBUG(Debug_Emulated, "{}", str);
std::vector<char> string(len);
Memory::ReadBlock(address, string.data(), len);
LOG_DEBUG(Debug_Emulated, "%.*s", len, string.data());
}
/// Gets system/memory information for the current process
static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) {
NGLOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id,
info_sub_id, handle);
LOG_TRACE(Kernel_SVC, "called info_id=0x%X, info_sub_id=0x%X, handle=0x%08X", info_id,
info_sub_id, handle);
auto& vm_manager = Core::CurrentProcess()->vm_manager;
@@ -308,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;
break;
case GetInfoType::TitleId:
NGLOG_WARNING(Kernel_SVC, "(STUBBED) Attempted to query titleid, returned 0");
LOG_WARNING(Kernel_SVC, "(STUBBED) Attempted to query titleid, returned 0");
*result = 0;
break;
case GetInfoType::PrivilegedProcessId:
NGLOG_WARNING(Kernel_SVC,
"(STUBBED) Attempted to query privileged process id bounds, returned 0");
LOG_WARNING(Kernel_SVC,
"(STUBBED) Attempted to query priviledged process id bounds, returned 0");
*result = 0;
break;
default:
@@ -325,14 +355,13 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
/// Sets the thread activity
static ResultCode SetThreadActivity(Handle handle, u32 unknown) {
NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x{:08X}, unknown=0x{:08X}", handle,
unknown);
LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x%08X, unknown=0x%08X", handle, unknown);
return RESULT_SUCCESS;
}
/// Gets the thread context
static ResultCode GetThreadContext(Handle handle, VAddr addr) {
NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x{:08X}, addr=0x{:X}", handle, addr);
LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x%08X, addr=0x%" PRIx64, handle, addr);
return RESULT_SUCCESS;
}
@@ -365,22 +394,21 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
thread->SetPriority(priority);
Core::System::GetInstance().CpuCore(thread->processor_id).PrepareReschedule();
Core::System::GetInstance().PrepareReschedule();
return RESULT_SUCCESS;
}
/// Get which CPU core is executing the current thread
static u32 GetCurrentProcessorNumber() {
NGLOG_TRACE(Kernel_SVC, "called");
return GetCurrentThread()->processor_id;
LOG_WARNING(Kernel_SVC, "(STUBBED) called, defaulting to processor 0");
return 0;
}
static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size,
u32 permissions) {
NGLOG_TRACE(
Kernel_SVC,
"called, shared_memory_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}",
shared_memory_handle, addr, size, permissions);
LOG_TRACE(Kernel_SVC,
"called, shared_memory_handle=0x%08X, addr=0x%llx, size=0x%llx, permissions=0x%08X",
shared_memory_handle, addr, size, permissions);
SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(shared_memory_handle);
if (!shared_memory) {
@@ -400,15 +428,16 @@ static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 s
return shared_memory->Map(Core::CurrentProcess().get(), addr, permissions_type,
MemoryPermission::DontCare);
default:
NGLOG_ERROR(Kernel_SVC, "unknown permissions=0x{:08X}", permissions);
LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions);
}
return RESULT_SUCCESS;
}
static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size) {
NGLOG_WARNING(Kernel_SVC, "called, shared_memory_handle=0x{:08X}, addr=0x{:X}, size=0x{:X}",
shared_memory_handle, addr, size);
LOG_WARNING(Kernel_SVC,
"called, shared_memory_handle=0x%08X, addr=0x%" PRIx64 ", size=0x%" PRIx64 "",
shared_memory_handle, addr, size);
SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(shared_memory_handle);
@@ -436,47 +465,41 @@ static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* /*page_i
memory_info->type = static_cast<u32>(vma->second.meminfo_state);
}
NGLOG_TRACE(Kernel_SVC, "called process=0x{:08X} addr={:X}", process_handle, addr);
LOG_TRACE(Kernel_SVC, "called process=0x%08X addr=%llx", process_handle, addr);
return RESULT_SUCCESS;
}
/// Query memory
static ResultCode QueryMemory(MemoryInfo* memory_info, PageInfo* page_info, VAddr addr) {
NGLOG_TRACE(Kernel_SVC, "called, addr={:X}", addr);
LOG_TRACE(Kernel_SVC, "called, addr=%llx", addr);
return QueryProcessMemory(memory_info, page_info, CurrentProcess, addr);
}
/// Exits the current process
static void ExitProcess() {
NGLOG_INFO(Kernel_SVC, "Process {} exiting", Core::CurrentProcess()->process_id);
LOG_INFO(Kernel_SVC, "Process %u exiting", Core::CurrentProcess()->process_id);
ASSERT_MSG(Core::CurrentProcess()->status == ProcessStatus::Running,
"Process has already exited");
Core::CurrentProcess()->status = ProcessStatus::Exited;
auto stop_threads = [](const std::vector<SharedPtr<Thread>>& thread_list) {
for (auto& thread : thread_list) {
if (thread->owner_process != Core::CurrentProcess())
continue;
// Stop all the process threads that are currently waiting for objects.
auto& thread_list = Core::System::GetInstance().Scheduler().GetThreadList();
for (auto& thread : thread_list) {
if (thread->owner_process != Core::CurrentProcess())
continue;
if (thread == GetCurrentThread())
continue;
if (thread == GetCurrentThread())
continue;
// TODO(Subv): When are the other running/ready threads terminated?
ASSERT_MSG(thread->status == THREADSTATUS_WAIT_SYNCH_ANY ||
thread->status == THREADSTATUS_WAIT_SYNCH_ALL,
"Exiting processes with non-waiting threads is currently unimplemented");
// TODO(Subv): When are the other running/ready threads terminated?
ASSERT_MSG(thread->status == THREADSTATUS_WAIT_SYNCH_ANY ||
thread->status == THREADSTATUS_WAIT_SYNCH_ALL,
"Exiting processes with non-waiting threads is currently unimplemented");
thread->Stop();
}
};
auto& system = Core::System::GetInstance();
stop_threads(system.Scheduler(0)->GetThreadList());
stop_threads(system.Scheduler(1)->GetThreadList());
stop_threads(system.Scheduler(2)->GetThreadList());
stop_threads(system.Scheduler(3)->GetThreadList());
thread->Stop();
}
// Kill the current thread
GetCurrentThread()->Stop();
@@ -487,7 +510,7 @@ static void ExitProcess() {
/// Creates a new thread
static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, VAddr stack_top,
u32 priority, s32 processor_id) {
std::string name = fmt::format("unknown-{:X}", entry_point);
std::string name = Common::StringFromFormat("unknown-%llx", entry_point);
if (priority > THREADPRIO_LOWEST) {
return ERR_OUT_OF_RANGE;
@@ -506,12 +529,17 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
switch (processor_id) {
case THREADPROCESSORID_0:
break;
case THREADPROCESSORID_1:
case THREADPROCESSORID_2:
case THREADPROCESSORID_3:
// TODO(bunnei): Implement support for other processor IDs
LOG_ERROR(Kernel_SVC,
"Newly created thread must run in another thread (%u), unimplemented.",
processor_id);
break;
default:
ASSERT_MSG(false, "Unsupported thread processor ID: {}", processor_id);
ASSERT_MSG(false, "Unsupported thread processor ID: %d", processor_id);
break;
}
@@ -522,36 +550,32 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
*out_handle = thread->guest_handle;
Core::System::GetInstance().PrepareReschedule();
Core::System::GetInstance().CpuCore(thread->processor_id).PrepareReschedule();
NGLOG_TRACE(Kernel_SVC,
"called entrypoint=0x{:08X} ({}), arg=0x{:08X}, stacktop=0x{:08X}, "
"threadpriority=0x{:08X}, processorid=0x{:08X} : created handle=0x{:08X}",
entry_point, name, arg, stack_top, priority, processor_id, *out_handle);
LOG_TRACE(Kernel_SVC,
"called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, "
"threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X",
entry_point, name.c_str(), arg, stack_top, priority, processor_id, *out_handle);
return RESULT_SUCCESS;
}
/// Starts the thread for the provided handle
static ResultCode StartThread(Handle thread_handle) {
NGLOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle);
const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
if (!thread) {
return ERR_INVALID_HANDLE;
}
ASSERT(thread->status == THREADSTATUS_DORMANT);
thread->ResumeFromWait();
Core::System::GetInstance().CpuCore(thread->processor_id).PrepareReschedule();
return RESULT_SUCCESS;
}
/// Called when a thread exits
static void ExitThread() {
NGLOG_TRACE(Kernel_SVC, "called, pc=0x{:08X}", Core::CurrentArmInterface().GetPC());
LOG_TRACE(Kernel_SVC, "called, pc=0x%08X", Core::CPU().GetPC());
ExitCurrentThread();
Core::System::GetInstance().PrepareReschedule();
@@ -559,11 +583,11 @@ static void ExitThread() {
/// Sleep the current thread
static void SleepThread(s64 nanoseconds) {
NGLOG_TRACE(Kernel_SVC, "called nanoseconds={}", nanoseconds);
LOG_TRACE(Kernel_SVC, "called nanoseconds=%lld", nanoseconds);
// 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.
if (nanoseconds == 0 && !Core::System::GetInstance().CurrentScheduler().HaveReadyThreads())
if (nanoseconds == 0 && !Core::System::GetInstance().Scheduler().HaveReadyThreads())
return;
// Sleep current thread and check for next thread to schedule
@@ -578,9 +602,9 @@ static void SleepThread(s64 nanoseconds) {
/// Signal process wide key atomic
static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_variable_addr,
Handle thread_handle, s64 nano_seconds) {
NGLOG_TRACE(
LOG_TRACE(
Kernel_SVC,
"called mutex_addr={:X}, condition_variable_addr={:X}, thread_handle=0x{:08X}, timeout={}",
"called mutex_addr=%llx, condition_variable_addr=%llx, thread_handle=0x%08X, timeout=%d",
mutex_addr, condition_variable_addr, thread_handle, nano_seconds);
SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
@@ -599,52 +623,26 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_var
// Note: Deliberately don't attempt to inherit the lock owner's priority.
Core::System::GetInstance().CpuCore(current_thread->processor_id).PrepareReschedule();
Core::System::GetInstance().PrepareReschedule();
return RESULT_SUCCESS;
}
/// Signal process wide key
static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target) {
NGLOG_TRACE(Kernel_SVC, "called, condition_variable_addr=0x{:X}, target=0x{:08X}",
condition_variable_addr, target);
LOG_TRACE(Kernel_SVC, "called, condition_variable_addr=0x%llx, target=0x%08x",
condition_variable_addr, target);
auto RetrieveWaitingThreads =
[](size_t core_index, std::vector<SharedPtr<Thread>>& waiting_threads, VAddr condvar_addr) {
const auto& scheduler = Core::System::GetInstance().Scheduler(core_index);
auto& thread_list = scheduler->GetThreadList();
u32 processed = 0;
auto& thread_list = Core::System::GetInstance().Scheduler().GetThreadList();
for (auto& thread : thread_list) {
if (thread->condvar_wait_address == condvar_addr)
waiting_threads.push_back(thread);
}
};
for (auto& thread : thread_list) {
if (thread->condvar_wait_address != condition_variable_addr)
continue;
// Retrieve a list of all threads that are waiting for this condition variable.
std::vector<SharedPtr<Thread>> waiting_threads;
RetrieveWaitingThreads(0, waiting_threads, condition_variable_addr);
RetrieveWaitingThreads(1, waiting_threads, condition_variable_addr);
RetrieveWaitingThreads(2, waiting_threads, condition_variable_addr);
RetrieveWaitingThreads(3, waiting_threads, condition_variable_addr);
// Sort them by priority, such that the highest priority ones come first.
std::sort(waiting_threads.begin(), waiting_threads.end(),
[](const SharedPtr<Thread>& lhs, const SharedPtr<Thread>& rhs) {
return lhs->current_priority < rhs->current_priority;
});
// Only process up to 'target' threads, unless 'target' is -1, in which case process
// them all.
size_t last = waiting_threads.size();
if (target != -1)
last = target;
// If there are no threads waiting on this condition variable, just exit
if (last > waiting_threads.size())
return RESULT_SUCCESS;
for (size_t index = 0; index < last; ++index) {
auto& thread = waiting_threads[index];
ASSERT(thread->condvar_wait_address == condition_variable_addr);
// Only process up to 'target' threads, unless 'target' is -1, in which case process
// them all.
if (target != -1 && processed >= target)
break;
// If the mutex is not yet acquired, acquire it.
u32 mutex_val = Memory::Read32(thread->mutex_wait_address);
@@ -677,8 +675,10 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
owner->AddMutexWaiter(thread);
Core::System::GetInstance().CpuCore(thread->processor_id).PrepareReschedule();
Core::System::GetInstance().PrepareReschedule();
}
++processed;
}
return RESULT_SUCCESS;
@@ -696,13 +696,13 @@ static u64 GetSystemTick() {
/// Close a handle
static ResultCode CloseHandle(Handle handle) {
NGLOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle);
LOG_TRACE(Kernel_SVC, "Closing handle 0x%08X", handle);
return g_handle_table.Close(handle);
}
/// Reset an event
static ResultCode ResetSignal(Handle handle) {
NGLOG_WARNING(Kernel_SVC, "(STUBBED) called handle 0x{:08X}", handle);
LOG_WARNING(Kernel_SVC, "(STUBBED) called handle 0x%08X", handle);
auto event = g_handle_table.Get<Event>(handle);
ASSERT(event != nullptr);
event->Clear();
@@ -711,69 +711,29 @@ static ResultCode ResetSignal(Handle handle) {
/// Creates a TransferMemory object
static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32 permissions) {
NGLOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x{:X}, size=0x{:X}, perms=0x{:08X}", addr,
size, permissions);
LOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x%" PRIx64 ", size=0x%" PRIx64 ", perms=%08X",
addr, size, permissions);
*handle = 0;
return RESULT_SUCCESS;
}
static ResultCode GetThreadCoreMask(Handle thread_handle, u32* core, u64* mask) {
NGLOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle);
const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
if (!thread) {
return ERR_INVALID_HANDLE;
}
*core = thread->ideal_core;
*mask = thread->affinity_mask;
static ResultCode GetThreadCoreMask(Handle handle, u32* mask, u64* unknown) {
LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x%08X", handle);
*mask = 0x0;
*unknown = 0xf;
return RESULT_SUCCESS;
}
static ResultCode SetThreadCoreMask(Handle thread_handle, u32 core, u64 mask) {
NGLOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, mask=0x{:16X}, core=0x{:X}", thread_handle,
mask, core);
const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
if (!thread) {
return ERR_INVALID_HANDLE;
}
if (core == THREADPROCESSORID_DEFAULT) {
ASSERT(thread->owner_process->ideal_processor != THREADPROCESSORID_DEFAULT);
// Set the target CPU to the one specified in the process' exheader.
core = thread->owner_process->ideal_processor;
mask = 1 << core;
}
if (mask == 0) {
return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidCombination);
}
/// This value is used to only change the affinity mask without changing the current ideal core.
static constexpr u32 OnlyChangeMask = static_cast<u32>(-3);
if (core == OnlyChangeMask) {
core = thread->ideal_core;
} else if (core >= Core::NUM_CPU_CORES && core != -1) {
return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidProcessorId);
}
// Error out if the input core isn't enabled in the input mask.
if (core < Core::NUM_CPU_CORES && (mask & (1 << core)) == 0) {
return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidCombination);
}
thread->ChangeCore(core, mask);
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,
mask, unknown);
return RESULT_SUCCESS;
}
static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permissions,
u32 remote_permissions) {
NGLOG_TRACE(Kernel_SVC, "called, size=0x{:X}, localPerms=0x{:08X}, remotePerms=0x{:08X}", size,
local_permissions, remote_permissions);
LOG_TRACE(Kernel_SVC, "called, size=0x%llx, localPerms=0x%08x, remotePerms=0x%08x", size,
local_permissions, remote_permissions);
auto sharedMemHandle =
SharedMemory::Create(g_handle_table.Get<Process>(KernelHandle::CurrentProcess), size,
static_cast<MemoryPermission>(local_permissions),
@@ -784,7 +744,7 @@ static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permiss
}
static ResultCode ClearEvent(Handle handle) {
NGLOG_TRACE(Kernel_SVC, "called, event=0x{:08X}", handle);
LOG_TRACE(Kernel_SVC, "called, event=0xX", handle);
SharedPtr<Event> evt = g_handle_table.Get<Event>(handle);
if (evt == nullptr)
@@ -936,7 +896,7 @@ static const FunctionDef SVC_Table[] = {
static const FunctionDef* GetSVCInfo(u32 func_num) {
if (func_num >= std::size(SVC_Table)) {
NGLOG_ERROR(Kernel_SVC, "Unknown svc=0x{:02X}", func_num);
LOG_ERROR(Kernel_SVC, "unknown svc=0x%02X", func_num);
return nullptr;
}
return &SVC_Table[func_num];
@@ -955,10 +915,10 @@ void CallSVC(u32 immediate) {
if (info->func) {
info->func();
} else {
NGLOG_CRITICAL(Kernel_SVC, "Unimplemented SVC function {}(..)", info->name);
LOG_CRITICAL(Kernel_SVC, "unimplemented SVC function %s(..)", info->name);
}
} else {
NGLOG_CRITICAL(Kernel_SVC, "Unknown SVC function 0x{:X}", immediate);
LOG_CRITICAL(Kernel_SVC, "unknown SVC function 0x%x", immediate);
}
}

View File

@@ -47,12 +47,9 @@ enum class GetInfoType : u64 {
NewMapRegionSize = 15,
// 3.0.0+
IsVirtualAddressMemoryEnabled = 16,
PersonalMmHeapUsage = 17,
TitleId = 18,
// 4.0.0+
PrivilegedProcessId = 19,
// 5.0.0+
UserExceptionContextAddr = 20,
};
void CallSVC(u32 immediate);

View File

@@ -13,14 +13,14 @@
namespace Kernel {
#define PARAM(n) Core::CurrentArmInterface().GetReg(n)
#define PARAM(n) Core::CPU().GetReg(n)
/**
* HLE a function return from the current ARM userland process
* @param res Result to return
*/
static inline void FuncReturn(u64 res) {
Core::CurrentArmInterface().SetReg(0, res);
Core::CPU().SetReg(0, res);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -45,7 +45,7 @@ template <ResultCode func(u32*, u32)>
void SvcWrap() {
u32 param_1 = 0;
u32 retval = func(&param_1, (u32)PARAM(1)).raw;
Core::CurrentArmInterface().SetReg(1, param_1);
Core::CPU().SetReg(1, param_1);
FuncReturn(retval);
}
@@ -53,7 +53,7 @@ template <ResultCode func(u32*, u64)>
void SvcWrap() {
u32 param_1 = 0;
u32 retval = func(&param_1, PARAM(1)).raw;
Core::CurrentArmInterface().SetReg(1, param_1);
Core::CPU().SetReg(1, param_1);
FuncReturn(retval);
}
@@ -66,7 +66,7 @@ template <ResultCode func(u64*, u64)>
void SvcWrap() {
u64 param_1 = 0;
u32 retval = func(&param_1, PARAM(1)).raw;
Core::CurrentArmInterface().SetReg(1, param_1);
Core::CPU().SetReg(1, param_1);
FuncReturn(retval);
}
@@ -85,8 +85,8 @@ void SvcWrap() {
u32 param_1 = 0;
u64 param_2 = 0;
ResultCode retval = func((u32)(PARAM(2) & 0xFFFFFFFF), &param_1, &param_2);
Core::CurrentArmInterface().SetReg(1, param_1);
Core::CurrentArmInterface().SetReg(2, param_2);
Core::CPU().SetReg(1, param_1);
Core::CPU().SetReg(2, param_2);
FuncReturn(retval.raw);
}
@@ -120,7 +120,7 @@ template <ResultCode func(u32*, u64, u64, s64)>
void SvcWrap() {
u32 param_1 = 0;
ResultCode retval = func(&param_1, PARAM(1), (u32)(PARAM(2) & 0xFFFFFFFF), (s64)PARAM(3));
Core::CurrentArmInterface().SetReg(1, param_1);
Core::CPU().SetReg(1, param_1);
FuncReturn(retval.raw);
}
@@ -133,7 +133,7 @@ template <ResultCode func(u64*, u64, u64, u64)>
void SvcWrap() {
u64 param_1 = 0;
u32 retval = func(&param_1, PARAM(1), PARAM(2), PARAM(3)).raw;
Core::CurrentArmInterface().SetReg(1, param_1);
Core::CPU().SetReg(1, param_1);
FuncReturn(retval);
}
@@ -143,7 +143,7 @@ void SvcWrap() {
u32 retval =
func(&param_1, PARAM(1), PARAM(2), PARAM(3), (u32)PARAM(4), (s32)(PARAM(5) & 0xFFFFFFFF))
.raw;
Core::CurrentArmInterface().SetReg(1, param_1);
Core::CPU().SetReg(1, param_1);
FuncReturn(retval);
}
@@ -166,7 +166,7 @@ template <ResultCode func(u32*, u64, u64, u32)>
void SvcWrap() {
u32 param_1 = 0;
u32 retval = func(&param_1, PARAM(1), PARAM(2), (u32)(PARAM(3) & 0xFFFFFFFF)).raw;
Core::CurrentArmInterface().SetReg(1, param_1);
Core::CPU().SetReg(1, param_1);
FuncReturn(retval);
}
@@ -175,7 +175,7 @@ void SvcWrap() {
u32 param_1 = 0;
u32 retval =
func(&param_1, PARAM(1), (u32)(PARAM(2) & 0xFFFFFFFF), (u32)(PARAM(3) & 0xFFFFFFFF)).raw;
Core::CurrentArmInterface().SetReg(1, param_1);
Core::CPU().SetReg(1, param_1);
FuncReturn(retval);
}

View File

@@ -64,7 +64,7 @@ void Thread::Stop() {
// Clean up thread from ready queue
// This is only needed when the thread is termintated forcefully (SVC TerminateProcess)
if (status == THREADSTATUS_READY) {
scheduler->UnscheduleThread(this, current_priority);
Core::System::GetInstance().Scheduler().UnscheduleThread(this, current_priority);
}
status = THREADSTATUS_DEAD;
@@ -92,7 +92,7 @@ void WaitCurrentThread_Sleep() {
void ExitCurrentThread() {
Thread* thread = GetCurrentThread();
thread->Stop();
Core::System::GetInstance().CurrentScheduler().RemoveThread(thread);
Core::System::GetInstance().Scheduler().RemoveThread(thread);
}
/**
@@ -101,10 +101,9 @@ void ExitCurrentThread() {
* @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) {
const auto proper_handle = static_cast<Handle>(thread_handle);
SharedPtr<Thread> thread = wakeup_callback_handle_table.Get<Thread>(proper_handle);
SharedPtr<Thread> thread = wakeup_callback_handle_table.Get<Thread>((Handle)thread_handle);
if (thread == nullptr) {
NGLOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", proper_handle);
LOG_CRITICAL(Kernel, "Callback fired for invalid thread %08X", (Handle)thread_handle);
return;
}
@@ -133,11 +132,8 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
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 unless SignalProcessWideKey was called first and the thread
// wasn't awakened due to the mutex already being acquired.
if (lock_owner) {
lock_owner->RemoveMutexWaiter(thread);
}
// and don't have a lock owner.
ASSERT(lock_owner == nullptr);
}
if (resume)
@@ -149,26 +145,13 @@ void Thread::WakeAfterDelay(s64 nanoseconds) {
if (nanoseconds == -1)
return;
CoreTiming::ScheduleEvent(CoreTiming::nsToCycles(nanoseconds), ThreadWakeupEventType,
callback_handle);
CoreTiming::ScheduleEvent(nsToCycles(nanoseconds), ThreadWakeupEventType, callback_handle);
}
void Thread::CancelWakeupTimer() {
CoreTiming::UnscheduleEvent(ThreadWakeupEventType, callback_handle);
}
static boost::optional<s32> GetNextProcessorId(u64 mask) {
for (s32 index = 0; index < Core::NUM_CPU_CORES; ++index) {
if (mask & (1ULL << index)) {
if (!Core::System().GetInstance().Scheduler(index)->GetCurrentThread()) {
// Core is enabled and not running any threads, use this one
return index;
}
}
}
return {};
}
void Thread::ResumeFromWait() {
ASSERT_MSG(wait_objects.empty(), "Thread is waking up while waiting for objects");
@@ -191,11 +174,11 @@ void Thread::ResumeFromWait() {
return;
case THREADSTATUS_RUNNING:
DEBUG_ASSERT_MSG(false, "Thread with object id {} has already resumed.", GetObjectId());
DEBUG_ASSERT_MSG(false, "Thread with object id %u has already resumed.", GetObjectId());
return;
case THREADSTATUS_DEAD:
// This should never happen, as threads must complete before being stopped.
DEBUG_ASSERT_MSG(false, "Thread with object id {} cannot be resumed because it's DEAD.",
DEBUG_ASSERT_MSG(false, "Thread with object id %u cannot be resumed because it's DEAD.",
GetObjectId());
return;
}
@@ -203,37 +186,8 @@ void Thread::ResumeFromWait() {
wakeup_callback = nullptr;
status = THREADSTATUS_READY;
boost::optional<s32> new_processor_id = GetNextProcessorId(affinity_mask);
if (!new_processor_id) {
new_processor_id = processor_id;
}
if (ideal_core != -1 &&
Core::System().GetInstance().Scheduler(ideal_core)->GetCurrentThread() == nullptr) {
new_processor_id = ideal_core;
}
ASSERT(*new_processor_id < 4);
// Add thread to new core's scheduler
auto& next_scheduler = Core::System().GetInstance().Scheduler(*new_processor_id);
if (*new_processor_id != processor_id) {
// Remove thread from previous core's scheduler
scheduler->RemoveThread(this);
next_scheduler->AddThread(this, current_priority);
}
processor_id = *new_processor_id;
// If the thread was ready, unschedule from the previous core and schedule on the new core
scheduler->UnscheduleThread(this, current_priority);
next_scheduler->ScheduleThread(this, current_priority);
// Change thread's scheduler
scheduler = next_scheduler;
Core::System::GetInstance().CpuCore(processor_id).PrepareReschedule();
Core::System::GetInstance().Scheduler().ScheduleThread(this, current_priority);
Core::System::GetInstance().PrepareReschedule();
}
/**
@@ -284,25 +238,27 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
SharedPtr<Process> owner_process) {
// Check if priority is in ranged. Lowest priority -> highest priority id.
if (priority > THREADPRIO_LOWEST) {
NGLOG_ERROR(Kernel_SVC, "Invalid thread priority: {}", priority);
LOG_ERROR(Kernel_SVC, "Invalid thread priority: %u", priority);
return ERR_OUT_OF_RANGE;
}
if (processor_id > THREADPROCESSORID_MAX) {
NGLOG_ERROR(Kernel_SVC, "Invalid processor id: {}", processor_id);
LOG_ERROR(Kernel_SVC, "Invalid processor id: %d", processor_id);
return ERR_OUT_OF_RANGE_KERNEL;
}
// TODO(yuriks): Other checks, returning 0xD9001BEA
if (!Memory::IsValidVirtualAddress(*owner_process, entry_point)) {
NGLOG_ERROR(Kernel_SVC, "(name={}): invalid entry {:016X}", name, entry_point);
LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %016" PRIx64, name.c_str(), entry_point);
// TODO (bunnei): Find the correct error code to use here
return ResultCode(-1);
}
SharedPtr<Thread> thread(new Thread);
Core::System::GetInstance().Scheduler().AddThread(thread, priority);
thread->thread_id = NewThreadId();
thread->status = THREADSTATUS_DORMANT;
thread->entry_point = entry_point;
@@ -310,8 +266,6 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
thread->nominal_priority = thread->current_priority = priority;
thread->last_running_ticks = CoreTiming::GetTicks();
thread->processor_id = processor_id;
thread->ideal_core = processor_id;
thread->affinity_mask = 1ULL << processor_id;
thread->wait_objects.clear();
thread->mutex_wait_address = 0;
thread->condvar_wait_address = 0;
@@ -319,8 +273,6 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
thread->name = std::move(name);
thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap();
thread->owner_process = owner_process;
thread->scheduler = Core::System().GetInstance().Scheduler(processor_id);
thread->scheduler->AddThread(thread, priority);
// Find the next available TLS index, and mark it as used
auto& tls_slots = owner_process->tls_slots;
@@ -337,8 +289,8 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
auto& linheap_memory = memory_region->linear_heap_memory;
if (linheap_memory->size() + Memory::PAGE_SIZE > memory_region->size) {
NGLOG_ERROR(Kernel_SVC,
"Not enough space in region to allocate a new TLS page for thread");
LOG_ERROR(Kernel_SVC,
"Not enough space in region to allocate a new TLS page for thread");
return ERR_OUT_OF_MEMORY;
}
@@ -383,7 +335,7 @@ void Thread::SetPriority(u32 priority) {
}
void Thread::BoostPriority(u32 priority) {
scheduler->SetThreadPriority(this, priority);
Core::System::GetInstance().Scheduler().SetThreadPriority(this, priority);
current_priority = priority;
}
@@ -452,7 +404,7 @@ void Thread::UpdatePriority() {
if (new_priority == current_priority)
return;
scheduler->SetThreadPriority(this, new_priority);
Core::System::GetInstance().Scheduler().SetThreadPriority(this, new_priority);
current_priority = new_priority;
@@ -461,54 +413,13 @@ void Thread::UpdatePriority() {
lock_owner->UpdatePriority();
}
void Thread::ChangeCore(u32 core, u64 mask) {
ideal_core = core;
affinity_mask = mask;
if (status != THREADSTATUS_READY) {
return;
}
boost::optional<s32> new_processor_id{GetNextProcessorId(affinity_mask)};
if (!new_processor_id) {
new_processor_id = processor_id;
}
if (ideal_core != -1 &&
Core::System().GetInstance().Scheduler(ideal_core)->GetCurrentThread() == nullptr) {
new_processor_id = ideal_core;
}
ASSERT(*new_processor_id < 4);
// Add thread to new core's scheduler
auto& next_scheduler = Core::System().GetInstance().Scheduler(*new_processor_id);
if (*new_processor_id != processor_id) {
// Remove thread from previous core's scheduler
scheduler->RemoveThread(this);
next_scheduler->AddThread(this, current_priority);
}
processor_id = *new_processor_id;
// If the thread was ready, unschedule from the previous core and schedule on the new core
scheduler->UnscheduleThread(this, current_priority);
next_scheduler->ScheduleThread(this, current_priority);
// Change thread's scheduler
scheduler = next_scheduler;
Core::System::GetInstance().CpuCore(processor_id).PrepareReschedule();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Gets the current thread
*/
Thread* GetCurrentThread() {
return Core::System::GetInstance().CurrentScheduler().GetCurrentThread();
return Core::System::GetInstance().Scheduler().GetCurrentThread();
}
void ThreadingInit() {

View File

@@ -4,7 +4,6 @@
#pragma once
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
@@ -57,7 +56,6 @@ enum class ThreadWakeupReason {
namespace Kernel {
class Process;
class Scheduler;
class Thread final : public WaitObject {
public:
@@ -120,9 +118,6 @@ public:
/// Recalculates the current priority taking into account priority inheritance.
void UpdatePriority();
/// Changes the core that the thread is running or scheduled to run on.
void ChangeCore(u32 core, u64 mask);
/**
* Gets the thread's thread ID
* @return The thread's ID
@@ -245,11 +240,6 @@ public:
// available. In case of a timeout, the object will be nullptr.
std::function<WakeupCallback> wakeup_callback;
std::shared_ptr<Scheduler> scheduler;
u32 ideal_core{0xFFFFFFFF};
u64 affinity_mask{0x1};
private:
Thread();
~Thread() override;

View File

@@ -57,8 +57,7 @@ void Timer::Set(s64 initial, s64 interval) {
// Immediately invoke the callback
Signal(0);
} else {
CoreTiming::ScheduleEvent(CoreTiming::nsToCycles(initial), timer_callback_event_type,
callback_handle);
CoreTiming::ScheduleEvent(nsToCycles(initial), timer_callback_event_type, callback_handle);
}
}
@@ -78,7 +77,7 @@ void Timer::WakeupAllWaitingThreads() {
}
void Timer::Signal(int cycles_late) {
NGLOG_TRACE(Kernel, "Timer {} fired", GetObjectId());
LOG_TRACE(Kernel, "Timer %u fired", GetObjectId());
signaled = true;
@@ -87,7 +86,7 @@ void Timer::Signal(int cycles_late) {
if (interval_delay != 0) {
// Reschedule the timer with the interval delay
CoreTiming::ScheduleEvent(CoreTiming::nsToCycles(interval_delay) - cycles_late,
CoreTiming::ScheduleEvent(nsToCycles(interval_delay) - cycles_late,
timer_callback_event_type, callback_handle);
}
}
@@ -98,7 +97,7 @@ static void TimerCallback(u64 timer_handle, int cycles_late) {
timer_callback_handle_table.Get<Timer>(static_cast<Handle>(timer_handle));
if (timer == nullptr) {
NGLOG_CRITICAL(Kernel, "Callback fired for invalid timer {:016X}", timer_handle);
LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08" PRIx64, timer_handle);
return;
}

View File

@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <cinttypes>
#include <iterator>
#include "common/assert.h"
#include "common/logging/log.h"
@@ -104,15 +105,8 @@ ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target,
VirtualMemoryArea& final_vma = vma_handle->second;
ASSERT(final_vma.size == size);
auto& system = Core::System::GetInstance();
system.ArmInterface(0).MapBackingMemory(target, size, block->data() + offset,
VMAPermission::ReadWriteExecute);
system.ArmInterface(1).MapBackingMemory(target, size, block->data() + offset,
VMAPermission::ReadWriteExecute);
system.ArmInterface(2).MapBackingMemory(target, size, block->data() + offset,
VMAPermission::ReadWriteExecute);
system.ArmInterface(3).MapBackingMemory(target, size, block->data() + offset,
VMAPermission::ReadWriteExecute);
Core::CPU().MapBackingMemory(target, size, block->data() + offset,
VMAPermission::ReadWriteExecute);
final_vma.type = VMAType::AllocatedMemoryBlock;
final_vma.permissions = VMAPermission::ReadWrite;
@@ -133,11 +127,7 @@ ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* me
VirtualMemoryArea& final_vma = vma_handle->second;
ASSERT(final_vma.size == size);
auto& system = Core::System::GetInstance();
system.ArmInterface(0).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute);
system.ArmInterface(1).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute);
system.ArmInterface(2).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute);
system.ArmInterface(3).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute);
Core::CPU().MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute);
final_vma.type = VMAType::BackingMemory;
final_vma.permissions = VMAPermission::ReadWrite;
@@ -195,11 +185,7 @@ ResultCode VMManager::UnmapRange(VAddr target, u64 size) {
ASSERT(FindVMA(target)->second.size >= size);
auto& system = Core::System::GetInstance();
system.ArmInterface(0).UnmapMemory(target, size);
system.ArmInterface(1).UnmapMemory(target, size);
system.ArmInterface(2).UnmapMemory(target, size);
system.ArmInterface(3).UnmapMemory(target, size);
Core::CPU().UnmapMemory(target, size);
return RESULT_SUCCESS;
}
@@ -239,10 +225,11 @@ void VMManager::RefreshMemoryBlockMappings(const std::vector<u8>* block) {
}
}
void VMManager::LogLayout() const {
void VMManager::LogLayout(Log::Level log_level) const {
for (const auto& p : vma_map) {
const VirtualMemoryArea& vma = p.second;
NGLOG_DEBUG(Kernel, "{:016X} - {:016X} size: {:016X} {}{}{} {}", vma.base,
LOG_GENERIC(Log::Class::Kernel, log_level,
"%016" PRIx64 " - %016" PRIx64 " size: %16" PRIx64 " %c%c%c %s", vma.base,
vma.base + vma.size, vma.size,
(u8)vma.permissions & (u8)VMAPermission::Read ? 'R' : '-',
(u8)vma.permissions & (u8)VMAPermission::Write ? 'W' : '-',
@@ -258,8 +245,8 @@ VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle& iter) {
}
ResultVal<VMManager::VMAIter> VMManager::CarveVMA(VAddr base, u64 size) {
ASSERT_MSG((size & Memory::PAGE_MASK) == 0, "non-page aligned size: 0x{:016X}", size);
ASSERT_MSG((base & Memory::PAGE_MASK) == 0, "non-page aligned base: 0x{:016X}", base);
ASSERT_MSG((size & Memory::PAGE_MASK) == 0, "non-page aligned size: 0x%16" PRIx64, size);
ASSERT_MSG((base & Memory::PAGE_MASK) == 0, "non-page aligned base: 0x%016" PRIx64, base);
VMAIter vma_handle = StripIterConstness(FindVMA(base));
if (vma_handle == vma_map.end()) {
@@ -294,8 +281,8 @@ ResultVal<VMManager::VMAIter> VMManager::CarveVMA(VAddr base, u64 size) {
}
ResultVal<VMManager::VMAIter> VMManager::CarveVMARange(VAddr target, u64 size) {
ASSERT_MSG((size & Memory::PAGE_MASK) == 0, "non-page aligned size: 0x{:016X}", size);
ASSERT_MSG((target & Memory::PAGE_MASK) == 0, "non-page aligned base: 0x{:016X}", target);
ASSERT_MSG((size & Memory::PAGE_MASK) == 0, "non-page aligned size: 0x%16" PRIx64, size);
ASSERT_MSG((target & Memory::PAGE_MASK) == 0, "non-page aligned base: 0x%016" PRIx64, target);
VAddr target_end = target + size;
ASSERT(target_end >= target);
@@ -392,22 +379,22 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) {
}
u64 VMManager::GetTotalMemoryUsage() {
NGLOG_WARNING(Kernel, "(STUBBED) called");
LOG_WARNING(Kernel, "(STUBBED) called");
return 0xF8000000;
}
u64 VMManager::GetTotalHeapUsage() {
NGLOG_WARNING(Kernel, "(STUBBED) called");
LOG_WARNING(Kernel, "(STUBBED) called");
return 0x0;
}
VAddr VMManager::GetAddressSpaceBaseAddr() {
NGLOG_WARNING(Kernel, "(STUBBED) called");
LOG_WARNING(Kernel, "(STUBBED) called");
return 0x8000000;
}
u64 VMManager::GetAddressSpaceSize() {
NGLOG_WARNING(Kernel, "(STUBBED) called");
LOG_WARNING(Kernel, "(STUBBED) called");
return MAX_ADDRESS;
}

View File

@@ -187,7 +187,7 @@ public:
void RefreshMemoryBlockMappings(const std::vector<u8>* block);
/// Dumps the address space layout to the log, for debugging
void LogLayout() const;
void LogLayout(Log::Level log_level) const;
/// Gets the total memory usage, used by svcGetInfo
u64 GetTotalMemoryUsage();

View File

@@ -32,8 +32,7 @@ enum class ErrorModule : u32 {
Common = 0,
Kernel = 1,
FS = 2,
OS = 3, // used for Memory, Thread, Mutex, Nvidia
HTCS = 4,
NvidiaTransferMemory = 3,
NCM = 5,
DD = 6,
LR = 8,
@@ -43,80 +42,41 @@ enum class ErrorModule : u32 {
PM = 15,
NS = 16,
HTC = 18,
NCMContent = 20,
SM = 21,
RO = 22,
SDMMC = 24,
OVLN = 25,
SPL = 26,
ETHC = 100,
I2C = 101,
GPIO = 102,
UART = 103,
Settings = 105,
WLAN = 107,
XCD = 108,
NIFM = 110,
Hwopus = 111,
Bluetooth = 113,
VI = 114,
NFP = 115,
Time = 116,
Display = 114,
NTC = 116,
FGM = 117,
OE = 118,
PCIe = 120,
PCIE = 120,
Friends = 121,
BCAT = 122,
SSL = 123,
Account = 124,
News = 125,
Mii = 126,
NFC = 127,
AM = 128,
PlayReport = 129,
AHID = 130,
Qlaunch = 132,
PCV = 133,
OMM = 134,
BPC = 135,
PSM = 136,
NIM = 137,
PSC = 138,
TC = 139,
USB = 140,
NSD = 141,
PCTL = 142,
BTM = 143,
ETicket = 145,
NGC = 146,
ERPT = 147,
APM = 148,
Profiler = 150,
ErrorUpload = 151,
Audio = 153,
NPNS = 154,
NPNSHTTPSTREAM = 155,
ARP = 157,
SWKBD = 158,
BOOT = 159,
NFCMifare = 161,
BOOT = 158,
NFC = 161,
UserlandAssert = 162,
Fatal = 163,
NIMShop = 164,
SPSM = 165,
BGTC = 167,
UserlandCrash = 168,
SREPO = 180,
Dauth = 181,
HID = 202,
LDN = 203,
Irsensor = 205,
HID = 203,
Capture = 206,
Manu = 208,
ATK = 209,
GRC = 212,
Migration = 216,
MigrationLdcServ = 217,
TC = 651,
GeneralWebApplet = 800,
WifiWebAuthApplet = 809,
WhitelistedApplet = 810,

View File

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

View File

@@ -3,7 +3,6 @@
// Refer to the license.txt file included.
#include <cinttypes>
#include <stack>
#include "core/file_sys/filesystem.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
@@ -13,7 +12,6 @@
#include "core/hle/service/apm/apm.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/nvflinger/nvflinger.h"
#include "core/hle/service/set/set.h"
#include "core/settings.h"
namespace Service::AM {
@@ -30,14 +28,14 @@ IWindowController::IWindowController() : ServiceFramework("IWindowController") {
}
void IWindowController::GetAppletResourceUserId(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_AM, "(STUBBED) called");
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(0);
}
void IWindowController::AcquireForegroundRights(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_AM, "(STUBBED) called");
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
@@ -56,59 +54,26 @@ IAudioController::IAudioController() : ServiceFramework("IAudioController") {
}
void IAudioController::SetExpectedMasterVolume(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_AM, "(STUBBED) called");
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void IAudioController::GetMainAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_AM, "(STUBBED) called");
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(volume);
}
void IAudioController::GetLibraryAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_AM, "(STUBBED) called");
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(volume);
}
IDisplayController::IDisplayController() : ServiceFramework("IDisplayController") {
static const FunctionInfo functions[] = {
{0, nullptr, "GetLastForegroundCaptureImage"},
{1, nullptr, "UpdateLastForegroundCaptureImage"},
{2, nullptr, "GetLastApplicationCaptureImage"},
{3, nullptr, "GetCallerAppletCaptureImage"},
{4, nullptr, "UpdateCallerAppletCaptureImage"},
{5, nullptr, "GetLastForegroundCaptureImageEx"},
{6, nullptr, "GetLastApplicationCaptureImageEx"},
{7, nullptr, "GetCallerAppletCaptureImageEx"},
{8, nullptr, "TakeScreenShotOfOwnLayer"}, // 2.0.0+
{9, nullptr, "CopyBetweenCaptureBuffers"}, // 5.0.0+
{10, nullptr, "AcquireLastApplicationCaptureBuffer"},
{11, nullptr, "ReleaseLastApplicationCaptureBuffer"},
{12, nullptr, "AcquireLastForegroundCaptureBuffer"},
{13, nullptr, "ReleaseLastForegroundCaptureBuffer"},
{14, nullptr, "AcquireCallerAppletCaptureBuffer"},
{15, nullptr, "ReleaseCallerAppletCaptureBuffer"},
{16, nullptr, "AcquireLastApplicationCaptureBufferEx"},
{17, nullptr, "AcquireLastForegroundCaptureBufferEx"},
{18, nullptr, "AcquireCallerAppletCaptureBufferEx"},
// 2.0.0+
{20, nullptr, "ClearCaptureBuffer"},
{21, nullptr, "ClearAppletTransitionBuffer"},
// 4.0.0+
{22, nullptr, "AcquireLastApplicationCaptureSharedBuffer"},
{23, nullptr, "ReleaseLastApplicationCaptureSharedBuffer"},
{24, nullptr, "AcquireLastForegroundCaptureSharedBuffer"},
{25, nullptr, "ReleaseLastForegroundCaptureSharedBuffer"},
{26, nullptr, "AcquireCallerAppletCaptureSharedBuffer"},
{27, nullptr, "ReleaseCallerAppletCaptureSharedBuffer"},
};
RegisterHandlers(functions);
}
IDisplayController::IDisplayController() : ServiceFramework("IDisplayController") {}
IDebugFunctions::IDebugFunctions() : ServiceFramework("IDebugFunctions") {}
@@ -137,7 +102,7 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger
{40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"},
{41, nullptr, "IsSystemBufferSharingEnabled"},
{42, nullptr, "GetSystemSharedLayerHandle"},
{50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"},
{50, nullptr, "SetHandlesRequestToDisplay"},
{51, nullptr, "ApproveToDisplay"},
{60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"},
{61, nullptr, "SetMediaPlaybackState"},
@@ -174,14 +139,14 @@ void ISelfController::SetFocusHandlingMode(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_AM, "(STUBBED) called");
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void ISelfController::SetRestartMessageEnabled(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_AM, "(STUBBED) called");
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) {
@@ -192,14 +157,14 @@ void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestCo
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
LOG_WARNING(Service_AM, "(STUBBED) called flag=%u", static_cast<u32>(flag));
}
void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_AM, "(STUBBED) called");
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void ISelfController::SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx) {
@@ -210,7 +175,7 @@ void ISelfController::SetOperationModeChangedNotification(Kernel::HLERequestCont
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
LOG_WARNING(Service_AM, "(STUBBED) called flag=%u", static_cast<u32>(flag));
}
void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) {
@@ -223,21 +188,21 @@ void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext&
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled);
LOG_WARNING(Service_AM, "(STUBBED) called enabled=%u", static_cast<u32>(enabled));
}
void ISelfController::LockExit(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_AM, "(STUBBED) called");
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_AM, "(STUBBED) called");
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) {
@@ -247,7 +212,7 @@ void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext&
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(launchable_event);
NGLOG_WARNING(Service_AM, "(STUBBED) called");
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx) {
@@ -260,14 +225,7 @@ void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx)
rb.Push(RESULT_SUCCESS);
rb.Push(layer_id);
NGLOG_WARNING(Service_AM, "(STUBBED) called");
}
void ISelfController::SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_AM, "(STUBBED) called");
LOG_WARNING(Service_AM, "(STUBBED) called");
}
ICommonStateGetter::ICommonStateGetter() : ServiceFramework("ICommonStateGetter") {
@@ -311,7 +269,7 @@ void ICommonStateGetter::GetEventHandle(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(event);
NGLOG_WARNING(Service_AM, "(STUBBED) called");
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void ICommonStateGetter::ReceiveMessage(Kernel::HLERequestContext& ctx) {
@@ -319,7 +277,7 @@ void ICommonStateGetter::ReceiveMessage(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(15);
NGLOG_WARNING(Service_AM, "(STUBBED) called");
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) {
@@ -327,7 +285,7 @@ void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
rb.Push(static_cast<u8>(FocusState::InFocus));
NGLOG_WARNING(Service_AM, "(STUBBED) called");
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) {
@@ -336,7 +294,7 @@ void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
rb.Push(static_cast<u8>(use_docked_mode ? OperationMode::Docked : OperationMode::Handheld));
NGLOG_WARNING(Service_AM, "(STUBBED) called");
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) {
@@ -346,90 +304,9 @@ void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) {
rb.Push(static_cast<u32>(use_docked_mode ? APM::PerformanceMode::Docked
: APM::PerformanceMode::Handheld));
NGLOG_WARNING(Service_AM, "(STUBBED) called");
LOG_WARNING(Service_AM, "(STUBBED) called");
}
class IStorageAccessor final : public ServiceFramework<IStorageAccessor> {
public:
explicit IStorageAccessor(std::vector<u8> buffer)
: ServiceFramework("IStorageAccessor"), buffer(std::move(buffer)) {
static const FunctionInfo functions[] = {
{0, &IStorageAccessor::GetSize, "GetSize"},
{10, &IStorageAccessor::Write, "Write"},
{11, &IStorageAccessor::Read, "Read"},
};
RegisterHandlers(functions);
}
private:
std::vector<u8> buffer;
void GetSize(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push(static_cast<u64>(buffer.size()));
NGLOG_DEBUG(Service_AM, "called");
}
void Write(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 offset{rp.Pop<u64>()};
const std::vector<u8> data{ctx.ReadBuffer()};
ASSERT(offset + data.size() <= buffer.size());
std::memcpy(&buffer[offset], data.data(), data.size());
IPC::ResponseBuilder rb{rp.MakeBuilder(2, 0, 0)};
rb.Push(RESULT_SUCCESS);
NGLOG_DEBUG(Service_AM, "called, offset={}", offset);
}
void Read(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 offset{rp.Pop<u64>()};
const size_t size{ctx.GetWriteBufferSize()};
ASSERT(offset + size <= buffer.size());
ctx.WriteBuffer(buffer.data() + offset, size);
IPC::ResponseBuilder rb{rp.MakeBuilder(2, 0, 0)};
rb.Push(RESULT_SUCCESS);
NGLOG_DEBUG(Service_AM, "called, offset={}", offset);
}
};
class IStorage final : public ServiceFramework<IStorage> {
public:
explicit IStorage(std::vector<u8> buffer)
: ServiceFramework("IStorage"), buffer(std::move(buffer)) {
static const FunctionInfo functions[] = {
{0, &IStorage::Open, "Open"},
{1, nullptr, "OpenTransferStorage"},
};
RegisterHandlers(functions);
}
private:
std::vector<u8> buffer;
void Open(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<AM::IStorageAccessor>(buffer);
NGLOG_DEBUG(Service_AM, "called");
}
};
class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> {
public:
explicit ILibraryAppletAccessor() : ServiceFramework("ILibraryAppletAccessor") {
@@ -441,7 +318,7 @@ public:
{25, nullptr, "Terminate"},
{30, nullptr, "GetResult"},
{50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"},
{100, &ILibraryAppletAccessor::PushInData, "PushInData"},
{100, nullptr, "PushInData"},
{101, nullptr, "PopOutData"},
{102, nullptr, "PushExtraStorage"},
{103, nullptr, "PushInteractiveInData"},
@@ -467,20 +344,9 @@ private:
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(state_changed_event);
NGLOG_WARNING(Service_AM, "(STUBBED) called");
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void PushInData(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
storage_stack.push(rp.PopIpcInterface<AM::IStorage>());
IPC::ResponseBuilder rb{rp.MakeBuilder(2, 0, 0)};
rb.Push(RESULT_SUCCESS);
NGLOG_DEBUG(Service_AM, "called");
}
std::stack<std::shared_ptr<AM::IStorage>> storage_stack;
Kernel::SharedPtr<Kernel::Event> state_changed_event;
};
@@ -489,7 +355,7 @@ ILibraryAppletCreator::ILibraryAppletCreator() : ServiceFramework("ILibraryApple
{0, &ILibraryAppletCreator::CreateLibraryApplet, "CreateLibraryApplet"},
{1, nullptr, "TerminateAllLibraryApplets"},
{2, nullptr, "AreAnyLibraryAppletsLeft"},
{10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"},
{10, nullptr, "CreateStorage"},
{11, nullptr, "CreateTransferMemoryStorage"},
{12, nullptr, "CreateHandleStorage"},
};
@@ -502,20 +368,75 @@ void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx)
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<AM::ILibraryAppletAccessor>();
NGLOG_DEBUG(Service_AM, "called");
LOG_DEBUG(Service_AM, "called");
}
void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 size{rp.Pop<u64>()};
std::vector<u8> buffer(size);
class IStorageAccessor final : public ServiceFramework<IStorageAccessor> {
public:
explicit IStorageAccessor(std::vector<u8> buffer)
: ServiceFramework("IStorageAccessor"), buffer(std::move(buffer)) {
static const FunctionInfo functions[] = {
{0, &IStorageAccessor::GetSize, "GetSize"},
{10, nullptr, "Write"},
{11, &IStorageAccessor::Read, "Read"},
};
RegisterHandlers(functions);
}
IPC::ResponseBuilder rb{rp.MakeBuilder(2, 0, 1)};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<AM::IStorage>(std::move(buffer));
private:
std::vector<u8> buffer;
NGLOG_DEBUG(Service_AM, "called, size={}", size);
}
void GetSize(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push(static_cast<u64>(buffer.size()));
LOG_DEBUG(Service_AM, "called");
}
void Read(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
u64 offset = rp.Pop<u64>();
const size_t size{ctx.GetWriteBufferSize()};
ASSERT(offset + size <= buffer.size());
ctx.WriteBuffer(buffer.data() + offset, size);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_AM, "called");
}
};
class IStorage final : public ServiceFramework<IStorage> {
public:
explicit IStorage(std::vector<u8> buffer)
: ServiceFramework("IStorage"), buffer(std::move(buffer)) {
static const FunctionInfo functions[] = {
{0, &IStorage::Open, "Open"},
{1, nullptr, "OpenTransferStorage"},
};
RegisterHandlers(functions);
}
private:
std::vector<u8> buffer;
void Open(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<AM::IStorageAccessor>(buffer);
LOG_DEBUG(Service_AM, "called");
}
};
IApplicationFunctions::IApplicationFunctions() : ServiceFramework("IApplicationFunctions") {
static const FunctionInfo functions[] = {
@@ -523,12 +444,11 @@ IApplicationFunctions::IApplicationFunctions() : ServiceFramework("IApplicationF
{10, nullptr, "CreateApplicationAndPushAndRequestToStart"},
{11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"},
{12, nullptr, "CreateApplicationAndRequestToStart"},
{13, &IApplicationFunctions::CreateApplicationAndRequestToStartForQuest,
"CreateApplicationAndRequestToStartForQuest"},
{13, nullptr, "CreateApplicationAndRequestToStartForQuest"},
{20, &IApplicationFunctions::EnsureSaveData, "EnsureSaveData"},
{21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"},
{22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"},
{23, &IApplicationFunctions::GetDisplayVersion, "GetDisplayVersion"},
{23, nullptr, "GetDisplayVersion"},
{24, nullptr, "GetLaunchStorageInfoForDebug"},
{25, nullptr, "ExtendSaveData"},
{26, nullptr, "GetSaveDataSize"},
@@ -578,21 +498,14 @@ void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<AM::IStorage>(buffer);
NGLOG_DEBUG(Service_AM, "called");
}
void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(
Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_AM, "(STUBBED) called");
LOG_DEBUG(Service_AM, "called");
}
void IApplicationFunctions::EnsureSaveData(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
u128 uid = rp.PopRaw<u128>();
NGLOG_WARNING(Service, "(STUBBED) called uid = {:016X}{:016X}", uid[1], uid[0]);
LOG_WARNING(Service, "(STUBBED) called uid = %016" PRIX64 "%016" PRIX64, uid[1], uid[0]);
IPC::ResponseBuilder rb{ctx, 4};
@@ -620,36 +533,27 @@ void IApplicationFunctions::SetTerminateResult(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_AM, "(STUBBED) called, result=0x{:08X}", result);
}
void IApplicationFunctions::GetDisplayVersion(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(1);
rb.Push<u64>(0);
NGLOG_WARNING(Service_AM, "(STUBBED) called");
LOG_WARNING(Service_AM, "(STUBBED) called, result=0x%08X", result);
}
void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) {
// TODO(bunnei): This should be configurable
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push(static_cast<u64>(Service::Set::LanguageCode::EN_US));
NGLOG_DEBUG(Service_AM, "called");
rb.Push<u64>(SystemLanguage::English);
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void IApplicationFunctions::InitializeGamePlayRecording(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_AM, "(STUBBED) called");
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void IApplicationFunctions::SetGamePlayRecordingState(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_AM, "(STUBBED) called");
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void IApplicationFunctions::NotifyRunning(Kernel::HLERequestContext& ctx) {
@@ -657,7 +561,7 @@ void IApplicationFunctions::NotifyRunning(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
rb.Push<u8>(0); // Unknown, seems to be ignored by official processes
NGLOG_WARNING(Service_AM, "(STUBBED) called");
LOG_WARNING(Service_AM, "(STUBBED) called");
}
void InstallInterfaces(SM::ServiceManager& service_manager,
@@ -666,64 +570,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager,
std::make_shared<AppletOE>(nvflinger)->InstallAsService(service_manager);
}
IHomeMenuFunctions::IHomeMenuFunctions() : ServiceFramework("IHomeMenuFunctions") {
static const FunctionInfo functions[] = {
{10, &IHomeMenuFunctions::RequestToGetForeground, "RequestToGetForeground"},
{11, nullptr, "LockForeground"},
{12, nullptr, "UnlockForeground"},
{20, nullptr, "PopFromGeneralChannel"},
{21, nullptr, "GetPopFromGeneralChannelEvent"},
{30, nullptr, "GetHomeButtonWriterLockAccessor"},
{31, nullptr, "GetWriterLockAccessorEx"},
};
RegisterHandlers(functions);
}
void IHomeMenuFunctions::RequestToGetForeground(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_AM, "(STUBBED) called");
}
IGlobalStateController::IGlobalStateController() : ServiceFramework("IGlobalStateController") {
static const FunctionInfo functions[] = {
{0, nullptr, "RequestToEnterSleep"},
{1, nullptr, "EnterSleep"},
{2, nullptr, "StartSleepSequence"},
{3, nullptr, "StartShutdownSequence"},
{4, nullptr, "StartRebootSequence"},
{10, nullptr, "LoadAndApplyIdlePolicySettings"},
{11, nullptr, "NotifyCecSettingsChanged"},
{12, nullptr, "SetDefaultHomeButtonLongPressTime"},
{13, nullptr, "UpdateDefaultDisplayResolution"},
{14, nullptr, "ShouldSleepOnBoot"},
{15, nullptr, "GetHdcpAuthenticationFailedEvent"},
};
RegisterHandlers(functions);
}
IApplicationCreator::IApplicationCreator() : ServiceFramework("IApplicationCreator") {
static const FunctionInfo functions[] = {
{0, nullptr, "CreateApplication"},
{1, nullptr, "PopLaunchRequestedApplication"},
{10, nullptr, "CreateSystemApplication"},
{100, nullptr, "PopFloatingApplicationForDevelopment"},
};
RegisterHandlers(functions);
}
IProcessWindingController::IProcessWindingController()
: ServiceFramework("IProcessWindingController") {
static const FunctionInfo functions[] = {
{0, nullptr, "GetLaunchReason"},
{11, nullptr, "OpenCallingLibraryApplet"},
{21, nullptr, "PushContext"},
{22, nullptr, "PopContext"},
{23, nullptr, "CancelWindingReservation"},
{30, nullptr, "WindAndDoReserved"},
{40, nullptr, "ReserveToStartAndWaitAndUnwindThis"},
{41, nullptr, "ReserveToStartAndWait"},
};
RegisterHandlers(functions);
}
} // namespace Service::AM

View File

@@ -18,25 +18,10 @@ class NVFlinger;
namespace AM {
// TODO: Add more languages
enum SystemLanguage {
Japanese = 0,
English = 1, // en-US
French = 2,
German = 3,
Italian = 4,
Spanish = 5,
Chinese = 6,
Korean = 7,
Dutch = 8,
Portuguese = 9,
Russian = 10,
Taiwanese = 11,
BritishEnglish = 12, // en-GB
CanadianFrench = 13,
LatinAmericanSpanish = 14, // es-419
// 4.0.0+
SimplifiedChinese = 15,
TraditionalChinese = 16,
English = 1,
};
class IWindowController final : public ServiceFramework<IWindowController> {
@@ -85,7 +70,6 @@ private:
void GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx);
void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx);
void SetScreenShotPermission(Kernel::HLERequestContext& ctx);
void SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx);
std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
Kernel::SharedPtr<Kernel::Event> launchable_event;
@@ -121,7 +105,6 @@ public:
private:
void CreateLibraryApplet(Kernel::HLERequestContext& ctx);
void CreateStorage(Kernel::HLERequestContext& ctx);
};
class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
@@ -130,39 +113,14 @@ public:
private:
void PopLaunchParameter(Kernel::HLERequestContext& ctx);
void CreateApplicationAndRequestToStartForQuest(Kernel::HLERequestContext& ctx);
void EnsureSaveData(Kernel::HLERequestContext& ctx);
void SetTerminateResult(Kernel::HLERequestContext& ctx);
void GetDisplayVersion(Kernel::HLERequestContext& ctx);
void GetDesiredLanguage(Kernel::HLERequestContext& ctx);
void InitializeGamePlayRecording(Kernel::HLERequestContext& ctx);
void SetGamePlayRecordingState(Kernel::HLERequestContext& ctx);
void NotifyRunning(Kernel::HLERequestContext& ctx);
};
class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> {
public:
IHomeMenuFunctions();
private:
void RequestToGetForeground(Kernel::HLERequestContext& ctx);
};
class IGlobalStateController final : public ServiceFramework<IGlobalStateController> {
public:
IGlobalStateController();
};
class IApplicationCreator final : public ServiceFramework<IApplicationCreator> {
public:
IApplicationCreator();
};
class IProcessWindingController final : public ServiceFramework<IProcessWindingController> {
public:
IProcessWindingController();
};
/// Registers all AM services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager,
std::shared_ptr<NVFlinger::NVFlinger> nvflinger);

View File

@@ -20,7 +20,7 @@ public:
{2, &ILibraryAppletProxy::GetWindowController, "GetWindowController"},
{3, &ILibraryAppletProxy::GetAudioController, "GetAudioController"},
{4, &ILibraryAppletProxy::GetDisplayController, "GetDisplayController"},
{10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"},
{10, nullptr, "GetProcessWindingController"},
{11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
{20, &ILibraryAppletProxy::GetApplicationFunctions, "GetApplicationFunctions"},
{1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
@@ -33,188 +33,74 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ICommonStateGetter>();
NGLOG_DEBUG(Service_AM, "called");
LOG_DEBUG(Service_AM, "called");
}
void GetSelfController(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISelfController>(nvflinger);
NGLOG_DEBUG(Service_AM, "called");
LOG_DEBUG(Service_AM, "called");
}
void GetWindowController(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IWindowController>();
NGLOG_DEBUG(Service_AM, "called");
LOG_DEBUG(Service_AM, "called");
}
void GetAudioController(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IAudioController>();
NGLOG_DEBUG(Service_AM, "called");
LOG_DEBUG(Service_AM, "called");
}
void GetDisplayController(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IDisplayController>();
NGLOG_DEBUG(Service_AM, "called");
}
void GetProcessWindingController(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IProcessWindingController>();
NGLOG_DEBUG(Service_AM, "called");
LOG_DEBUG(Service_AM, "called");
}
void GetDebugFunctions(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IDebugFunctions>();
NGLOG_DEBUG(Service_AM, "called");
LOG_DEBUG(Service_AM, "called");
}
void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ILibraryAppletCreator>();
NGLOG_DEBUG(Service_AM, "called");
LOG_DEBUG(Service_AM, "called");
}
void GetApplicationFunctions(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IApplicationFunctions>();
NGLOG_DEBUG(Service_AM, "called");
LOG_DEBUG(Service_AM, "called");
}
std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
};
class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> {
public:
explicit ISystemAppletProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
: ServiceFramework("ISystemAppletProxy"), nvflinger(std::move(nvflinger)) {
static const FunctionInfo functions[] = {
{0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
{1, &ISystemAppletProxy::GetSelfController, "GetSelfController"},
{2, &ISystemAppletProxy::GetWindowController, "GetWindowController"},
{3, &ISystemAppletProxy::GetAudioController, "GetAudioController"},
{4, &ISystemAppletProxy::GetDisplayController, "GetDisplayController"},
{10, nullptr, "GetProcessWindingController"},
{11, &ISystemAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
{20, &ISystemAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"},
{21, &ISystemAppletProxy::GetGlobalStateController, "GetGlobalStateController"},
{22, &ISystemAppletProxy::GetApplicationCreator, "GetApplicationCreator"},
{1000, &ISystemAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
};
RegisterHandlers(functions);
}
private:
void GetCommonStateGetter(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ICommonStateGetter>();
NGLOG_DEBUG(Service_AM, "called");
}
void GetSelfController(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISelfController>(nvflinger);
NGLOG_DEBUG(Service_AM, "called");
}
void GetWindowController(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IWindowController>();
NGLOG_DEBUG(Service_AM, "called");
}
void GetAudioController(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IAudioController>();
NGLOG_DEBUG(Service_AM, "called");
}
void GetDisplayController(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IDisplayController>();
NGLOG_DEBUG(Service_AM, "called");
}
void GetDebugFunctions(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IDebugFunctions>();
NGLOG_DEBUG(Service_AM, "called");
}
void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ILibraryAppletCreator>();
NGLOG_DEBUG(Service_AM, "called");
}
void GetHomeMenuFunctions(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IHomeMenuFunctions>();
NGLOG_DEBUG(Service_AM, "called");
}
void GetGlobalStateController(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IGlobalStateController>();
NGLOG_DEBUG(Service_AM, "called");
}
void GetApplicationCreator(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IApplicationCreator>();
NGLOG_DEBUG(Service_AM, "called");
}
std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
};
void AppletAE::OpenSystemAppletProxy(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISystemAppletProxy>(nvflinger);
NGLOG_DEBUG(Service_AM, "called");
}
void AppletAE::OpenLibraryAppletProxy(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger);
NGLOG_DEBUG(Service_AM, "called");
}
void AppletAE::OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger);
NGLOG_DEBUG(Service_AM, "called");
LOG_DEBUG(Service_AM, "called");
}
AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
: ServiceFramework("appletAE"), nvflinger(std::move(nvflinger)) {
static const FunctionInfo functions[] = {
{100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"},
{100, nullptr, "OpenSystemAppletProxy"},
{200, &AppletAE::OpenLibraryAppletProxyOld, "OpenLibraryAppletProxyOld"},
{201, &AppletAE::OpenLibraryAppletProxy, "OpenLibraryAppletProxy"},
{201, nullptr, "OpenLibraryAppletProxy"},
{300, nullptr, "OpenOverlayAppletProxy"},
{350, nullptr, "OpenSystemApplicationProxy"},
{400, nullptr, "CreateSelfLibraryAppletCreatorForDevelop"},

View File

@@ -21,8 +21,6 @@ public:
~AppletAE() = default;
private:
void OpenSystemAppletProxy(Kernel::HLERequestContext& ctx);
void OpenLibraryAppletProxy(Kernel::HLERequestContext& ctx);
void OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx);
std::shared_ptr<NVFlinger::NVFlinger> nvflinger;

View File

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

View File

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

View File

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

View File

@@ -35,8 +35,10 @@ public:
AudInU::AudInU() : ServiceFramework("audin:u") {
static const FunctionInfo functions[] = {
{0, nullptr, "ListAudioIns"}, {1, nullptr, "OpenAudioIn"}, {2, nullptr, "Unknown"},
{3, nullptr, "OpenAudioInAuto"}, {4, nullptr, "ListAudioInsAuto"},
{0, nullptr, "ListAudioIns"},
{1, nullptr, "OpenAudioIn"},
{3, nullptr, "OpenAudioInAuto"},
{4, nullptr, "ListAudioInsAuto"},
};
RegisterHandlers(functions);
}

View File

@@ -18,7 +18,7 @@ constexpr u32 sample_rate{48000};
/// to more audio channels (probably when Docked I guess)
constexpr u32 audio_channels{2};
/// TODO(st4rk): find a proper value for the audio_ticks
constexpr u64 audio_ticks{static_cast<u64>(CoreTiming::BASE_CLOCK_RATE / 500)};
constexpr u64 audio_ticks{static_cast<u64>(BASE_CLOCK_RATE / 500)};
class IAudioOut final : public ServiceFramework<IAudioOut> {
public:
@@ -60,14 +60,14 @@ public:
private:
void GetAudioOutState(Kernel::HLERequestContext& ctx) {
NGLOG_DEBUG(Service_Audio, "called");
LOG_DEBUG(Service_Audio, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(static_cast<u32>(audio_out_state));
}
void StartAudioOut(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
LOG_WARNING(Service_Audio, "(STUBBED) called");
// Start audio
audio_out_state = AudioState::Started;
@@ -77,7 +77,7 @@ private:
}
void StopAudioOut(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
LOG_WARNING(Service_Audio, "(STUBBED) called");
// Stop audio
audio_out_state = AudioState::Stopped;
@@ -89,7 +89,7 @@ private:
}
void RegisterBufferEvent(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
LOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
@@ -97,7 +97,7 @@ private:
}
void AppendAudioOutBuffer(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
LOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const u64 key{rp.Pop<u64>()};
@@ -108,7 +108,7 @@ private:
}
void GetReleasedAudioOutBuffer(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
LOG_WARNING(Service_Audio, "(STUBBED) called");
// TODO(st4rk): This is how libtransistor currently implements the
// 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) {
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
LOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const std::string audio_interface = "AudioInterface";
@@ -180,7 +180,7 @@ void AudOutU::ListAudioOuts(Kernel::HLERequestContext& ctx) {
}
void AudOutU::OpenAudioOut(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
LOG_WARNING(Service_Audio, "(STUBBED) called");
if (!audio_out_interface) {
audio_out_interface = std::make_shared<IAudioOut>();
@@ -196,10 +196,10 @@ void AudOutU::OpenAudioOut(Kernel::HLERequestContext& ctx) {
}
AudOutU::AudOutU() : ServiceFramework("audout:u") {
static const FunctionInfo functions[] = {{0, &AudOutU::ListAudioOuts, "ListAudioOuts"},
{1, &AudOutU::OpenAudioOut, "OpenAudioOut"},
{2, nullptr, "ListAudioOutsAuto"},
{3, nullptr, "OpenAudioOutAuto"}};
static const FunctionInfo functions[] = {{0x00000000, &AudOutU::ListAudioOuts, "ListAudioOuts"},
{0x00000001, &AudOutU::OpenAudioOut, "OpenAudioOut"},
{0x00000002, nullptr, "ListAudioOutsAuto"},
{0x00000003, nullptr, "OpenAudioOutAuto"}};
RegisterHandlers(functions);
}

View File

@@ -20,7 +20,6 @@ public:
{4, nullptr, "RegisterBufferEvent"},
{5, nullptr, "GetReleasedFinalOutputRecorderBuffer"},
{6, nullptr, "ContainsFinalOutputRecorderBuffer"},
{7, nullptr, "Unknown"},
{8, nullptr, "AppendFinalOutputRecorderBufferAuto"},
{9, nullptr, "GetReleasedFinalOutputRecorderBufferAuto"},
};
@@ -31,7 +30,7 @@ public:
AudRecU::AudRecU() : ServiceFramework("audrec:u") {
static const FunctionInfo functions[] = {
{0, nullptr, "OpenFinalOutputRecorder"},
{0x00000000, nullptr, "OpenFinalOutputRecorder"},
};
RegisterHandlers(functions);
}

View File

@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/alignment.h"
#include "common/logging/log.h"
#include "core/core_timing.h"
#include "core/hle/ipc_helpers.h"
@@ -13,7 +12,7 @@
namespace Service::Audio {
/// TODO(bunnei): Find a proper value for the audio_ticks
constexpr u64 audio_ticks{static_cast<u64>(CoreTiming::BASE_CLOCK_RATE / 200)};
constexpr u64 audio_ticks{static_cast<u64>(BASE_CLOCK_RATE / 200)};
class IAudioRenderer final : public ServiceFramework<IAudioRenderer> {
public:
@@ -57,7 +56,7 @@ private:
}
void RequestUpdateAudioRenderer(Kernel::HLERequestContext& ctx) {
NGLOG_DEBUG(Service_Audio, "{}", ctx.Description());
LOG_DEBUG(Service_Audio, "%s", ctx.Description().c_str());
AudioRendererResponseData response_data{};
response_data.section_0_size =
@@ -80,7 +79,7 @@ private:
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
LOG_WARNING(Service_Audio, "(STUBBED) called");
}
void StartAudioRenderer(Kernel::HLERequestContext& ctx) {
@@ -88,7 +87,7 @@ private:
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
LOG_WARNING(Service_Audio, "(STUBBED) called");
}
void StopAudioRenderer(Kernel::HLERequestContext& ctx) {
@@ -96,7 +95,7 @@ private:
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
LOG_WARNING(Service_Audio, "(STUBBED) called");
}
void QuerySystemEvent(Kernel::HLERequestContext& ctx) {
@@ -106,7 +105,7 @@ private:
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(system_event);
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
LOG_WARNING(Service_Audio, "(STUBBED) called");
}
struct AudioRendererStateEntry {
@@ -157,20 +156,18 @@ class IAudioDevice final : public ServiceFramework<IAudioDevice> {
public:
IAudioDevice() : ServiceFramework("IAudioDevice") {
static const FunctionInfo functions[] = {
{0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"},
{1, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolume"},
{2, nullptr, "GetAudioDeviceOutputVolume"},
{3, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceName"},
{4, &IAudioDevice::QueryAudioDeviceSystemEvent, "QueryAudioDeviceSystemEvent"},
{5, &IAudioDevice::GetActiveChannelCount, "GetActiveChannelCount"},
{6, &IAudioDevice::ListAudioDeviceName,
"ListAudioDeviceNameAuto"}, // TODO(ogniK): Confirm if autos are identical to non auto
{7, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolumeAuto"},
{8, nullptr, "GetAudioDeviceOutputVolumeAuto"},
{10, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceNameAuto"},
{11, nullptr, "QueryAudioDeviceInputEvent"},
{12, nullptr, "QueryAudioDeviceOutputEvent"},
};
{0x0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"},
{0x1, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolume"},
{0x2, nullptr, "GetAudioDeviceOutputVolume"},
{0x3, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceName"},
{0x4, &IAudioDevice::QueryAudioDeviceSystemEvent, "QueryAudioDeviceSystemEvent"},
{0x5, &IAudioDevice::GetActiveChannelCount, "GetActiveChannelCount"},
{0x6, nullptr, "ListAudioDeviceNameAuto"},
{0x7, nullptr, "SetAudioDeviceOutputVolumeAuto"},
{0x8, nullptr, "GetAudioDeviceOutputVolumeAuto"},
{0x10, nullptr, "GetActiveAudioDeviceNameAuto"},
{0x11, nullptr, "QueryAudioDeviceInputEvent"},
{0x12, nullptr, "QueryAudioDeviceOutputEvent"}};
RegisterHandlers(functions);
buffer_event =
@@ -179,7 +176,7 @@ public:
private:
void ListAudioDeviceName(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
LOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const std::string audio_interface = "AudioInterface";
@@ -191,7 +188,7 @@ private:
}
void SetAudioDeviceOutputVolume(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
LOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::RequestParser rp{ctx};
f32 volume = static_cast<f32>(rp.Pop<u32>());
@@ -204,7 +201,7 @@ private:
}
void GetActiveAudioDeviceName(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
LOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const std::string audio_interface = "AudioDevice";
@@ -216,7 +213,7 @@ private:
}
void QueryAudioDeviceSystemEvent(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
LOG_WARNING(Service_Audio, "(STUBBED) called");
buffer_event->Signal();
@@ -226,7 +223,7 @@ private:
}
void GetActiveChannelCount(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
LOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(1);
@@ -253,66 +250,16 @@ void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<Audio::IAudioRenderer>();
NGLOG_DEBUG(Service_Audio, "called");
LOG_DEBUG(Service_Audio, "called");
}
void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
auto params = rp.PopRaw<WorkerBufferParameters>();
u64 buffer_sz = Common::AlignUp(4 * params.unknown8, 0x40);
buffer_sz += params.unknownC * 1024;
buffer_sz += 0x940 * (params.unknownC + 1);
buffer_sz += 0x3F0 * params.voice_count;
buffer_sz += Common::AlignUp(8 * (params.unknownC + 1), 0x10);
buffer_sz += Common::AlignUp(8 * params.voice_count, 0x10);
buffer_sz +=
Common::AlignUp((0x3C0 * (params.sink_count + params.unknownC) + 4 * params.sample_count) *
(params.unknown8 + 6),
0x40);
if (IsFeatureSupported(AudioFeatures::Splitter, params.magic)) {
u32 count = params.unknownC + 1;
u64 node_count = Common::AlignUp(count, 0x40);
u64 node_state_buffer_sz =
4 * (node_count * node_count) + 0xC * node_count + 2 * (node_count / 8);
u64 edge_matrix_buffer_sz = 0;
node_count = Common::AlignUp(count * count, 0x40);
if (node_count >> 31 != 0) {
edge_matrix_buffer_sz = (node_count | 7) / 8;
} else {
edge_matrix_buffer_sz = node_count / 8;
}
buffer_sz += Common::AlignUp(node_state_buffer_sz + edge_matrix_buffer_sz, 0x10);
}
buffer_sz += 0x20 * (params.effect_count + 4 * params.voice_count) + 0x50;
if (IsFeatureSupported(AudioFeatures::Splitter, params.magic)) {
buffer_sz += 0xE0 * params.unknown2c;
buffer_sz += 0x20 * params.splitter_count;
buffer_sz += Common::AlignUp(4 * params.unknown2c, 0x10);
}
buffer_sz = Common::AlignUp(buffer_sz, 0x40) + 0x170 * params.sink_count;
u64 output_sz = buffer_sz + 0x280 * params.sink_count + 0x4B0 * params.effect_count +
((params.voice_count * 256) | 0x40);
if (params.unknown1c >= 1) {
output_sz = Common::AlignUp(((16 * params.sink_count + 16 * params.effect_count +
16 * params.voice_count + 16) +
0x658) *
(params.unknown1c + 1) +
0xc0,
0x40) +
output_sz;
}
output_sz = Common::AlignUp(output_sz + 0x1807e, 0x1000);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(output_sz);
rb.Push<u64>(0x400);
NGLOG_DEBUG(Service_Audio, "called, buffer_size=0x{:X}", output_sz);
LOG_WARNING(Service_Audio, "(STUBBED) called");
}
void AudRenU::GetAudioDevice(Kernel::HLERequestContext& ctx) {
@@ -321,17 +268,7 @@ void AudRenU::GetAudioDevice(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<Audio::IAudioDevice>();
NGLOG_DEBUG(Service_Audio, "called");
}
bool AudRenU::IsFeatureSupported(AudioFeatures feature, u32_le revision) const {
u32_be version_num = (revision - Common::MakeMagic('R', 'E', 'V', '0')); // Byte swap
switch (feature) {
case AudioFeatures::Splitter:
return version_num >= 2;
default:
return false;
}
LOG_DEBUG(Service_Audio, "called");
}
} // namespace Service::Audio

View File

@@ -21,31 +21,6 @@ private:
void OpenAudioRenderer(Kernel::HLERequestContext& ctx);
void GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx);
void GetAudioDevice(Kernel::HLERequestContext& ctx);
struct WorkerBufferParameters {
u32_le sample_rate;
u32_le sample_count;
u32_le unknown8;
u32_le unknownC;
u32_le voice_count;
u32_le sink_count;
u32_le effect_count;
u32_le unknown1c;
u8 unknown20;
u8 padding1[3];
u32_le splitter_count;
u32_le unknown2c;
u8 padding2[4];
u32_le magic;
};
static_assert(sizeof(WorkerBufferParameters) == 52,
"WorkerBufferParameters is an invalid size");
enum class AudioFeatures : u32 {
Splitter,
};
bool IsFeatureSupported(AudioFeatures feature, u32_le revision) const;
};
} // namespace Service::Audio

View File

@@ -11,19 +11,19 @@ namespace Service::Audio {
CodecCtl::CodecCtl() : ServiceFramework("codecctl") {
static const FunctionInfo functions[] = {
{0, nullptr, "InitializeCodecController"},
{1, nullptr, "FinalizeCodecController"},
{2, nullptr, "SleepCodecController"},
{3, nullptr, "WakeCodecController"},
{4, nullptr, "SetCodecVolume"},
{5, nullptr, "GetCodecVolumeMax"},
{6, nullptr, "GetCodecVolumeMin"},
{7, nullptr, "SetCodecActiveTarget"},
{8, nullptr, "GetCodecActiveTarget"},
{9, nullptr, "BindCodecHeadphoneMicJackInterrupt"},
{10, nullptr, "IsCodecHeadphoneMicJackInserted"},
{11, nullptr, "ClearCodecHeadphoneMicJackInterrupt"},
{12, nullptr, "IsCodecDeviceRequested"},
{0x00000000, nullptr, "InitializeCodecController"},
{0x00000001, nullptr, "FinalizeCodecController"},
{0x00000002, nullptr, "SleepCodecController"},
{0x00000003, nullptr, "WakeCodecController"},
{0x00000004, nullptr, "SetCodecVolume"},
{0x00000005, nullptr, "GetCodecVolumeMax"},
{0x00000006, nullptr, "GetCodecVolumeMin"},
{0x00000007, nullptr, "SetCodecActiveTarget"},
{0x00000008, nullptr, "Unknown"},
{0x00000009, nullptr, "BindCodecHeadphoneMicJackInterrupt"},
{0x00000010, nullptr, "IsCodecHeadphoneMicJackInserted"},
{0x00000011, nullptr, "ClearCodecHeadphoneMicJackInterrupt"},
{0x00000012, nullptr, "IsCodecDeviceRequested"},
};
RegisterHandlers(functions);
}

View File

@@ -1,16 +0,0 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "core/hle/service/bcat/bcat.h"
namespace Service::BCAT {
BCAT::BCAT(std::shared_ptr<Module> module, const char* name)
: Module::Interface(std::move(module), name) {
static const FunctionInfo functions[] = {
{0, &BCAT::CreateBcatService, "CreateBcatService"},
};
RegisterHandlers(functions);
}
} // namespace Service::BCAT

View File

@@ -1,16 +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/bcat/module.h"
namespace Service::BCAT {
class BCAT final : public Module::Interface {
public:
explicit BCAT(std::shared_ptr<Module> module, const char* name);
};
} // namespace Service::BCAT

View File

@@ -1,53 +0,0 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/logging/log.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/service/bcat/bcat.h"
#include "core/hle/service/bcat/module.h"
namespace Service::BCAT {
class IBcatService final : public ServiceFramework<IBcatService> {
public:
IBcatService() : ServiceFramework("IBcatService") {
static const FunctionInfo functions[] = {
{10100, nullptr, "RequestSyncDeliveryCache"},
{10101, nullptr, "RequestSyncDeliveryCacheWithDirectoryName"},
{10200, nullptr, "CancelSyncDeliveryCacheRequest"},
{20100, nullptr, "RequestSyncDeliveryCacheWithApplicationId"},
{20101, nullptr, "RequestSyncDeliveryCacheWithApplicationIdAndDirectoryName"},
{30100, nullptr, "SetPassphrase"},
{30200, nullptr, "RegisterBackgroundDeliveryTask"},
{30201, nullptr, "UnregisterBackgroundDeliveryTask"},
{30202, nullptr, "BlockDeliveryTask"},
{30203, nullptr, "UnblockDeliveryTask"},
{90100, nullptr, "EnumerateBackgroundDeliveryTask"},
{90200, nullptr, "GetDeliveryList"},
{90201, nullptr, "ClearDeliveryCacheStorage"},
{90300, nullptr, "GetPushNotificationLog"},
};
RegisterHandlers(functions);
}
};
void Module::Interface::CreateBcatService(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IBcatService>();
NGLOG_DEBUG(Service_BCAT, "called");
}
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<BCAT>(module, "bcat:a")->InstallAsService(service_manager);
std::make_shared<BCAT>(module, "bcat:m")->InstallAsService(service_manager);
std::make_shared<BCAT>(module, "bcat:u")->InstallAsService(service_manager);
std::make_shared<BCAT>(module, "bcat:s")->InstallAsService(service_manager);
}
} // namespace Service::BCAT

View File

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

View File

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

View File

@@ -14,8 +14,8 @@ public:
public:
Interface(std::shared_ptr<Module> module, const char* name);
void ThrowFatalWithPolicy(Kernel::HLERequestContext& ctx);
void ThrowFatalWithCpuContext(Kernel::HLERequestContext& ctx);
void FatalSimple(Kernel::HLERequestContext& ctx);
void TransitionToFatalError(Kernel::HLERequestContext& ctx);
protected:
std::shared_ptr<Module> module;

View File

@@ -8,9 +8,8 @@ namespace Service::Fatal {
Fatal_U::Fatal_U(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "fatal:u") {
static const FunctionInfo functions[] = {
{0, nullptr, "ThrowFatal"},
{1, &Fatal_U::ThrowFatalWithPolicy, "ThrowFatalWithPolicy"},
{2, &Fatal_U::ThrowFatalWithCpuContext, "ThrowFatalWithCpuContext"},
{1, &Fatal_U::FatalSimple, "FatalSimple"},
{2, &Fatal_U::TransitionToFatalError, "TransitionToFatalError"},
};
RegisterHandlers(functions);
}

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");
auto& filesystem = result.first->second;
NGLOG_DEBUG(Service_FS, "Registered file system {} with id code 0x{:08X}",
filesystem->GetName(), static_cast<u32>(type));
LOG_DEBUG(Service_FS, "Registered file system %s with id code 0x%08X",
filesystem->GetName().c_str(), static_cast<u32>(type));
return RESULT_SUCCESS;
}
ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenFileSystem(Type type,
FileSys::Path& path) {
NGLOG_TRACE(Service_FS, "Opening FileSystem with type={}", static_cast<u32>(type));
LOG_TRACE(Service_FS, "Opening FileSystem with type=%d", type);
auto itr = filesystem_map.find(type);
if (itr == filesystem_map.end()) {
@@ -44,7 +44,7 @@ ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenFileSystem(Type type,
}
ResultCode FormatFileSystem(Type type) {
NGLOG_TRACE(Service_FS, "Formatting FileSystem with type={}", static_cast<u32>(type));
LOG_TRACE(Service_FS, "Formatting FileSystem with type=%d", type);
auto itr = filesystem_map.find(type);
if (itr == filesystem_map.end()) {

View File

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

View File

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

View File

@@ -18,9 +18,9 @@ namespace Service::HID {
// Updating period for each HID device.
// TODO(shinyquagsire23): These need better values.
constexpr u64 pad_update_ticks = CoreTiming::BASE_CLOCK_RATE / 10000;
constexpr u64 accelerometer_update_ticks = CoreTiming::BASE_CLOCK_RATE / 10000;
constexpr u64 gyroscope_update_ticks = CoreTiming::BASE_CLOCK_RATE / 10000;
constexpr u64 pad_update_ticks = BASE_CLOCK_RATE / 10000;
constexpr u64 accelerometer_update_ticks = BASE_CLOCK_RATE / 10000;
constexpr u64 gyroscope_update_ticks = BASE_CLOCK_RATE / 10000;
class IAppletResource final : public ServiceFramework<IAppletResource> {
public:
@@ -53,17 +53,14 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(shared_mem);
NGLOG_DEBUG(Service_HID, "called");
LOG_DEBUG(Service_HID, "called");
}
void LoadInputDevices() {
std::transform(Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_END,
buttons.begin(), Input::CreateDevice<Input::ButtonDevice>);
std::transform(Settings::values.analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN,
Settings::values.analogs.begin() + Settings::NativeAnalog::STICK_HID_END,
sticks.begin(), Input::CreateDevice<Input::AnalogDevice>);
// TODO(shinyquagsire23): gyro, touch, mouse, keyboard
// TODO(shinyquagsire23): sticks, gyro, touch, mouse, keyboard
}
void UpdatePadCallback(u64 userdata, int cycles_late) {
@@ -82,70 +79,61 @@ private:
controller_header.left_color_body = JOYCON_BODY_NEON_BLUE;
controller_header.left_color_buttons = JOYCON_BUTTONS_NEON_BLUE;
for (size_t controller = 0; controller < mem.controllers.size(); controller++) {
for (int index = 0; index < HID_NUM_LAYOUTS; index++) {
ControllerLayout& layout = mem.controllers[controller].layouts[index];
layout.header.num_entries = HID_NUM_ENTRIES;
layout.header.max_entry_index = HID_NUM_ENTRIES - 1;
for (int index = 0; index < HID_NUM_LAYOUTS; index++) {
ControllerLayout& layout = mem.controllers[Controller_Handheld].layouts[index];
layout.header.num_entries = HID_NUM_ENTRIES;
layout.header.max_entry_index = HID_NUM_ENTRIES - 1;
// HID shared memory stores the state of the past 17 samples in a circlular buffer,
// each with a timestamp in number of samples since boot.
layout.header.timestamp_ticks = CoreTiming::GetTicks();
layout.header.latest_entry = (layout.header.latest_entry + 1) % HID_NUM_ENTRIES;
// HID shared memory stores the state of the past 17 samples in a circlular buffer,
// each with a timestamp in number of samples since boot.
layout.header.timestamp_ticks = CoreTiming::GetTicks();
layout.header.latest_entry = (layout.header.latest_entry + 1) % HID_NUM_ENTRIES;
ControllerInputEntry& entry = layout.entries[layout.header.latest_entry];
entry.connection_state = ConnectionState_Connected | ConnectionState_Wired;
entry.timestamp++;
// TODO(shinyquagsire23): Is this always identical to timestamp?
entry.timestamp_2++;
ControllerInputEntry& entry = layout.entries[layout.header.latest_entry];
entry.connection_state = ConnectionState_Connected | ConnectionState_Wired;
entry.timestamp++;
entry.timestamp_2++; // TODO(shinyquagsire23): Is this always identical to timestamp?
// TODO(shinyquagsire23): More than just handheld input
if (controller != Controller_Handheld)
continue;
// TODO(shinyquagsire23): Set up some LUTs for each layout mapping in the future?
// For now everything is just the default handheld layout, but split Joy-Con will
// rotate the face buttons and directions for certain layouts.
ControllerPadState& state = entry.buttons;
using namespace Settings::NativeButton;
state.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus());
state.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus());
state.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus());
state.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus());
state.lstick.Assign(buttons[LStick - BUTTON_HID_BEGIN]->GetStatus());
state.rstick.Assign(buttons[RStick - BUTTON_HID_BEGIN]->GetStatus());
state.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus());
state.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus());
state.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus());
state.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus());
state.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus());
state.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus());
// TODO(shinyquagsire23): Set up some LUTs for each layout mapping in the future?
// For now everything is just the default handheld layout, but split Joy-Con will
// rotate the face buttons and directions for certain layouts.
ControllerPadState& state = entry.buttons;
using namespace Settings::NativeButton;
state.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus());
state.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus());
state.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus());
state.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus());
state.lstick.Assign(buttons[LStick - BUTTON_HID_BEGIN]->GetStatus());
state.rstick.Assign(buttons[RStick - BUTTON_HID_BEGIN]->GetStatus());
state.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus());
state.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus());
state.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus());
state.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus());
state.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus());
state.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus());
state.dleft.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus());
state.dup.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus());
state.dright.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus());
state.ddown.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus());
state.dleft.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus());
state.dup.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus());
state.dright.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus());
state.ddown.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus());
state.lstick_left.Assign(buttons[LStick_Left - BUTTON_HID_BEGIN]->GetStatus());
state.lstick_up.Assign(buttons[LStick_Up - BUTTON_HID_BEGIN]->GetStatus());
state.lstick_right.Assign(buttons[LStick_Right - BUTTON_HID_BEGIN]->GetStatus());
state.lstick_down.Assign(buttons[LStick_Down - BUTTON_HID_BEGIN]->GetStatus());
state.lstick_left.Assign(buttons[LStick_Left - BUTTON_HID_BEGIN]->GetStatus());
state.lstick_up.Assign(buttons[LStick_Up - BUTTON_HID_BEGIN]->GetStatus());
state.lstick_right.Assign(buttons[LStick_Right - BUTTON_HID_BEGIN]->GetStatus());
state.lstick_down.Assign(buttons[LStick_Down - BUTTON_HID_BEGIN]->GetStatus());
state.rstick_left.Assign(buttons[RStick_Left - BUTTON_HID_BEGIN]->GetStatus());
state.rstick_up.Assign(buttons[RStick_Up - BUTTON_HID_BEGIN]->GetStatus());
state.rstick_right.Assign(buttons[RStick_Right - BUTTON_HID_BEGIN]->GetStatus());
state.rstick_down.Assign(buttons[RStick_Down - BUTTON_HID_BEGIN]->GetStatus());
state.rstick_left.Assign(buttons[RStick_Left - BUTTON_HID_BEGIN]->GetStatus());
state.rstick_up.Assign(buttons[RStick_Up - BUTTON_HID_BEGIN]->GetStatus());
state.rstick_right.Assign(buttons[RStick_Right - BUTTON_HID_BEGIN]->GetStatus());
state.rstick_down.Assign(buttons[RStick_Down - BUTTON_HID_BEGIN]->GetStatus());
state.sl.Assign(buttons[SL - BUTTON_HID_BEGIN]->GetStatus());
state.sr.Assign(buttons[SR - BUTTON_HID_BEGIN]->GetStatus());
state.sl.Assign(buttons[SL - BUTTON_HID_BEGIN]->GetStatus());
state.sr.Assign(buttons[SR - BUTTON_HID_BEGIN]->GetStatus());
// TODO(shinyquagsire23): Analog stick vals
const auto [stick_l_x_f, stick_l_y_f] = sticks[Joystick_Left]->GetStatus();
const auto [stick_r_x_f, stick_r_y_f] = sticks[Joystick_Right]->GetStatus();
entry.joystick_left_x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX);
entry.joystick_left_y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX);
entry.joystick_right_x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX);
entry.joystick_right_y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX);
}
// TODO(shinyquagsire23): Update pad info proper, (circular buffers, timestamps,
// layouts)
}
// TODO(bunnei): Properly implement the touch screen, the below will just write empty data
@@ -163,71 +151,6 @@ private:
touchscreen.entries[curr_entry].header.timestamp = sample_counter;
touchscreen.entries[curr_entry].header.num_touches = 0;
// TODO(shinyquagsire23): Properly implement mouse
Mouse& mouse = mem.mouse;
const u64 last_mouse_entry = mouse.header.latest_entry;
const u64 curr_mouse_entry = (mouse.header.latest_entry + 1) % mouse.entries.size();
const u64 mouse_sample_counter = mouse.entries[last_mouse_entry].timestamp + 1;
mouse.header.timestamp_ticks = timestamp;
mouse.header.num_entries = mouse.entries.size();
mouse.header.max_entry_index = mouse.entries.size();
mouse.header.latest_entry = curr_mouse_entry;
mouse.entries[curr_mouse_entry].timestamp = mouse_sample_counter;
mouse.entries[curr_mouse_entry].timestamp_2 = mouse_sample_counter;
// TODO(shinyquagsire23): Properly implement keyboard
Keyboard& keyboard = mem.keyboard;
const u64 last_keyboard_entry = keyboard.header.latest_entry;
const u64 curr_keyboard_entry =
(keyboard.header.latest_entry + 1) % keyboard.entries.size();
const u64 keyboard_sample_counter = keyboard.entries[last_keyboard_entry].timestamp + 1;
keyboard.header.timestamp_ticks = timestamp;
keyboard.header.num_entries = keyboard.entries.size();
keyboard.header.latest_entry = last_keyboard_entry;
keyboard.header.max_entry_index = keyboard.entries.size();
keyboard.entries[curr_keyboard_entry].timestamp = keyboard_sample_counter;
keyboard.entries[curr_keyboard_entry].timestamp_2 = keyboard_sample_counter;
// TODO(shinyquagsire23): Figure out what any of these are
for (size_t i = 0; i < mem.unk_input_1.size(); i++) {
UnkInput1& input = mem.unk_input_1[i];
const u64 last_input_entry = input.header.latest_entry;
const u64 curr_input_entry = (input.header.latest_entry + 1) % input.entries.size();
const u64 input_sample_counter = input.entries[last_input_entry].timestamp + 1;
input.header.timestamp_ticks = timestamp;
input.header.num_entries = input.entries.size();
input.header.latest_entry = last_input_entry;
input.header.max_entry_index = input.entries.size();
input.entries[curr_input_entry].timestamp = input_sample_counter;
input.entries[curr_input_entry].timestamp_2 = input_sample_counter;
}
for (size_t i = 0; i < mem.unk_input_2.size(); i++) {
UnkInput2& input = mem.unk_input_2[i];
input.header.timestamp_ticks = timestamp;
input.header.num_entries = 17;
input.header.latest_entry = 0;
input.header.max_entry_index = 0;
}
UnkInput3& input = mem.unk_input_3;
const u64 last_input_entry = input.header.latest_entry;
const u64 curr_input_entry = (input.header.latest_entry + 1) % input.entries.size();
const u64 input_sample_counter = input.entries[last_input_entry].timestamp + 1;
input.header.timestamp_ticks = timestamp;
input.header.num_entries = input.entries.size();
input.header.latest_entry = last_input_entry;
input.header.max_entry_index = input.entries.size();
input.entries[curr_input_entry].timestamp = input_sample_counter;
input.entries[curr_input_entry].timestamp_2 = input_sample_counter;
// TODO(shinyquagsire23): Signal events
std::memcpy(shared_mem->GetPointer(), &mem, sizeof(SharedMemory));
@@ -246,7 +169,6 @@ private:
std::atomic<bool> is_device_reload_pending{true};
std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>
buttons;
std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID> sticks;
};
class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> {
@@ -262,7 +184,7 @@ private:
void ActivateVibrationDevice(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_HID, "(STUBBED) called");
LOG_WARNING(Service_HID, "(STUBBED) called");
}
};
@@ -329,7 +251,6 @@ public:
{130, nullptr, "SwapNpadAssignment"},
{131, nullptr, "IsUnintendedHomeButtonInputProtectionEnabled"},
{132, nullptr, "EnableUnintendedHomeButtonInputProtection"},
{133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"},
{200, &Hid::GetVibrationDeviceInfo, "GetVibrationDeviceInfo"},
{201, &Hid::SendVibrationValue, "SendVibrationValue"},
{202, &Hid::GetActualVibrationValue, "GetActualVibrationValue"},
@@ -337,41 +258,12 @@ public:
{204, nullptr, "PermitVibration"},
{205, nullptr, "IsVibrationPermitted"},
{206, &Hid::SendVibrationValues, "SendVibrationValues"},
{207, nullptr, "SendVibrationGcErmCommand"},
{208, nullptr, "GetActualVibrationGcErmCommand"},
{209, nullptr, "BeginPermitVibrationSession"},
{210, nullptr, "EndPermitVibrationSession"},
{300, nullptr, "ActivateConsoleSixAxisSensor"},
{301, nullptr, "StartConsoleSixAxisSensor"},
{302, nullptr, "StopConsoleSixAxisSensor"},
{303, nullptr, "ActivateSevenSixAxisSensor"},
{304, nullptr, "StartSevenSixAxisSensor"},
{305, nullptr, "StopSevenSixAxisSensor"},
{306, nullptr, "InitializeSevenSixAxisSensor"},
{307, nullptr, "FinalizeSevenSixAxisSensor"},
{308, nullptr, "SetSevenSixAxisSensorFusionStrength"},
{309, nullptr, "GetSevenSixAxisSensorFusionStrength"},
{400, nullptr, "IsUsbFullKeyControllerEnabled"},
{401, nullptr, "EnableUsbFullKeyController"},
{402, nullptr, "IsUsbFullKeyControllerConnected"},
{403, nullptr, "HasBattery"},
{404, nullptr, "HasLeftRightBattery"},
{405, nullptr, "GetNpadInterfaceType"},
{406, nullptr, "GetNpadLeftRightInterfaceType"},
{500, nullptr, "GetPalmaConnectionHandle"},
{501, nullptr, "InitializePalma"},
{502, nullptr, "AcquirePalmaOperationCompleteEvent"},
{503, nullptr, "GetPalmaOperationInfo"},
{504, nullptr, "PlayPalmaActivity"},
{505, nullptr, "SetPalmaFrModeType"},
{506, nullptr, "ReadPalmaStep"},
{507, nullptr, "EnablePalmaStep"},
{508, nullptr, "SuspendPalmaStep"},
{509, nullptr, "ResetPalmaStep"},
{510, nullptr, "ReadPalmaApplicationSection"},
{511, nullptr, "WritePalmaApplicationSection"},
{512, nullptr, "ReadPalmaUniqueCode"},
{513, nullptr, "SetPalmaUniqueCodeInvalid"},
{1000, nullptr, "SetNpadCommunicationMode"},
{1001, nullptr, "GetNpadCommunicationMode"},
};
@@ -394,144 +286,144 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IAppletResource>(applet_resource);
NGLOG_DEBUG(Service_HID, "called");
LOG_DEBUG(Service_HID, "called");
}
void ActivateDebugPad(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_HID, "(STUBBED) called");
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void ActivateTouchScreen(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_HID, "(STUBBED) called");
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void ActivateMouse(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_HID, "(STUBBED) called");
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void ActivateKeyboard(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_HID, "(STUBBED) called");
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void StartSixAxisSensor(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_HID, "(STUBBED) called");
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_HID, "(STUBBED) called");
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_HID, "(STUBBED) called");
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0);
NGLOG_WARNING(Service_HID, "(STUBBED) called");
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_HID, "(STUBBED) called");
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void ActivateNpad(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_HID, "(STUBBED) called");
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(event);
NGLOG_WARNING(Service_HID, "(STUBBED) called");
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void GetPlayerLedPattern(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_HID, "(STUBBED) called");
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_HID, "(STUBBED) called");
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(joy_hold_type);
NGLOG_WARNING(Service_HID, "(STUBBED) called");
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_HID, "(STUBBED) called");
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void SendVibrationValue(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_HID, "(STUBBED) called");
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void GetActualVibrationValue(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_HID, "(STUBBED) called");
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_HID, "(STUBBED) called");
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_HID, "(STUBBED) called");
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(0);
NGLOG_WARNING(Service_HID, "(STUBBED) called");
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IActiveVibrationDeviceList>();
NGLOG_DEBUG(Service_HID, "called");
LOG_DEBUG(Service_HID, "called");
}
void SendVibrationValues(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
NGLOG_WARNING(Service_HID, "(STUBBED) called");
LOG_WARNING(Service_HID, "(STUBBED) called");
}
};

View File

@@ -12,7 +12,7 @@ namespace Service::HID {
// Begin enums and output structs
constexpr u32 HID_NUM_ENTRIES = 17;
constexpr u32 HID_NUM_LAYOUTS = 2;
constexpr u32 HID_NUM_LAYOUTS = 7;
constexpr s32 HID_JOYSTICK_MAX = 0x8000;
constexpr s32 HID_JOYSTICK_MIN = -0x8000;
@@ -48,11 +48,6 @@ enum ControllerConnectionState {
ConnectionState_Wired = 1 << 1,
};
enum ControllerJoystick {
Joystick_Left = 0,
Joystick_Right = 1,
};
enum ControllerID {
Controller_Player1 = 0,
Controller_Player2 = 1,
@@ -68,34 +63,6 @@ enum ControllerID {
// End enums and output structs
// Begin UnkInput3
struct UnkInput3Header {
u64 timestamp_ticks;
u64 num_entries;
u64 latest_entry;
u64 max_entry_index;
};
static_assert(sizeof(UnkInput3Header) == 0x20, "HID UnkInput3 header structure has incorrect size");
struct UnkInput3Entry {
u64 timestamp;
u64 timestamp_2;
u64 unk_8;
u64 unk_10;
u64 unk_18;
};
static_assert(sizeof(UnkInput3Entry) == 0x28, "HID UnkInput3 entry structure has incorrect size");
struct UnkInput3 {
UnkInput3Header header;
std::array<UnkInput3Entry, 17> entries;
std::array<u8, 0x138> padding;
};
static_assert(sizeof(UnkInput3) == 0x400, "HID UnkInput3 structure has incorrect size");
// End UnkInput3
// Begin TouchScreen
struct TouchScreenHeader {
@@ -237,52 +204,6 @@ static_assert(sizeof(Keyboard) == 0x400, "HID keyboard structure has incorrect s
// End Keyboard
// Begin UnkInput1
struct UnkInput1Header {
u64 timestamp_ticks;
u64 num_entries;
u64 latest_entry;
u64 max_entry_index;
};
static_assert(sizeof(UnkInput1Header) == 0x20, "HID UnkInput1 header structure has incorrect size");
struct UnkInput1Entry {
u64 timestamp;
u64 timestamp_2;
u64 unk_8;
u64 unk_10;
u64 unk_18;
};
static_assert(sizeof(UnkInput1Entry) == 0x28, "HID UnkInput1 entry structure has incorrect size");
struct UnkInput1 {
UnkInput1Header header;
std::array<UnkInput1Entry, 17> entries;
std::array<u8, 0x138> padding;
};
static_assert(sizeof(UnkInput1) == 0x400, "HID UnkInput1 structure has incorrect size");
// End UnkInput1
// Begin UnkInput2
struct UnkInput2Header {
u64 timestamp_ticks;
u64 num_entries;
u64 latest_entry;
u64 max_entry_index;
};
static_assert(sizeof(UnkInput2Header) == 0x20, "HID UnkInput2 header structure has incorrect size");
struct UnkInput2 {
UnkInput2Header header;
std::array<u8, 0x1E0> padding;
};
static_assert(sizeof(UnkInput2) == 0x200, "HID UnkInput2 structure has incorrect size");
// End UnkInput2
// Begin Controller
struct ControllerMAC {
@@ -362,10 +283,10 @@ struct ControllerInputEntry {
u64 timestamp;
u64 timestamp_2;
ControllerPadState buttons;
s32 joystick_left_x;
s32 joystick_left_y;
s32 joystick_right_x;
s32 joystick_right_y;
u32 joystick_left_x;
u32 joystick_left_y;
u32 joystick_right_x;
u32 joystick_right_y;
u64 connection_state;
};
static_assert(sizeof(ControllerInputEntry) == 0x30,
@@ -391,12 +312,17 @@ static_assert(sizeof(Controller) == 0x5000, "HID controller structure has incorr
// End Controller
struct SharedMemory {
UnkInput3 unk_input_3;
std::array<u8, 0x400> header;
TouchScreen touchscreen;
Mouse mouse;
Keyboard keyboard;
std::array<UnkInput1, 4> unk_input_1;
std::array<UnkInput2, 3> unk_input_2;
std::array<u8, 0x400> unk_section_1;
std::array<u8, 0x400> unk_section_2;
std::array<u8, 0x400> unk_section_3;
std::array<u8, 0x400> unk_section_4;
std::array<u8, 0x200> unk_section_5;
std::array<u8, 0x200> unk_section_6;
std::array<u8, 0x200> unk_section_7;
std::array<u8, 0x800> unk_section_8;
std::array<u8, 0x4000> controller_serials;
std::array<Controller, 10> controllers;

View File

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

View File

@@ -4,8 +4,6 @@
#include "common/logging/log.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/service/hid/hid.h"
#include "core/hle/service/nfp/nfp.h"
#include "core/hle/service/nfp/nfp_user.h"
@@ -14,144 +12,10 @@ namespace Service::NFP {
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
: ServiceFramework(name), module(std::move(module)) {}
class IUser final : public ServiceFramework<IUser> {
public:
IUser() : ServiceFramework("IUser") {
static const FunctionInfo functions[] = {
{0, &IUser::Initialize, "Initialize"},
{1, nullptr, "Finalize"},
{2, &IUser::ListDevices, "ListDevices"},
{3, nullptr, "StartDetection"},
{4, nullptr, "StopDetection"},
{5, nullptr, "Mount"},
{6, nullptr, "Unmount"},
{7, nullptr, "OpenApplicationArea"},
{8, nullptr, "GetApplicationArea"},
{9, nullptr, "SetApplicationArea"},
{10, nullptr, "Flush"},
{11, nullptr, "Restore"},
{12, nullptr, "CreateApplicationArea"},
{13, nullptr, "GetTagInfo"},
{14, nullptr, "GetRegisterInfo"},
{15, nullptr, "GetCommonInfo"},
{16, nullptr, "GetModelInfo"},
{17, &IUser::AttachActivateEvent, "AttachActivateEvent"},
{18, &IUser::AttachDeactivateEvent, "AttachDeactivateEvent"},
{19, &IUser::GetState, "GetState"},
{20, &IUser::GetDeviceState, "GetDeviceState"},
{21, &IUser::GetNpadId, "GetNpadId"},
{22, nullptr, "GetApplicationArea2"},
{23, &IUser::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"},
{24, nullptr, "RecreateApplicationArea"},
};
RegisterHandlers(functions);
activate_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "IUser:ActivateEvent");
deactivate_event =
Kernel::Event::Create(Kernel::ResetType::OneShot, "IUser:DeactivateEvent");
availability_change_event =
Kernel::Event::Create(Kernel::ResetType::OneShot, "IUser:AvailabilityChangeEvent");
}
private:
enum class State : u32 {
NonInitialized = 0,
Initialized = 1,
};
enum class DeviceState : u32 {
Initialized = 0,
};
void Initialize(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_NFP, "(STUBBED) called");
state = State::Initialized;
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void ListDevices(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u32 array_size = rp.Pop<u32>();
ctx.WriteBuffer(&device_handle, sizeof(device_handle));
NGLOG_WARNING(Service_NFP, "(STUBBED) called, array_size={}", array_size);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0);
}
void AttachActivateEvent(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 dev_handle = rp.Pop<u64>();
NGLOG_WARNING(Service_NFP, "(STUBBED) called, dev_handle=0x{:X}", dev_handle);
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(activate_event);
}
void AttachDeactivateEvent(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 dev_handle = rp.Pop<u64>();
NGLOG_WARNING(Service_NFP, "(STUBBED) called, dev_handle=0x{:X}", dev_handle);
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(deactivate_event);
}
void GetState(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_NFP, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(static_cast<u32>(state));
}
void GetDeviceState(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_NFP, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(static_cast<u32>(device_state));
}
void GetNpadId(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 dev_handle = rp.Pop<u64>();
NGLOG_WARNING(Service_NFP, "(STUBBED) called, dev_handle=0x{:X}", dev_handle);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(npad_id);
}
void AttachAvailabilityChangeEvent(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 dev_handle = rp.Pop<u64>();
NGLOG_WARNING(Service_NFP, "(STUBBED) called, dev_handle=0x{:X}", dev_handle);
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(availability_change_event);
}
const u64 device_handle{0xDEAD};
const HID::ControllerID npad_id{HID::Controller_Player1};
State state{State::NonInitialized};
DeviceState device_state{DeviceState::Initialized};
Kernel::SharedPtr<Kernel::Event> activate_event;
Kernel::SharedPtr<Kernel::Event> deactivate_event;
Kernel::SharedPtr<Kernel::Event> availability_change_event;
};
void Module::Interface::CreateUserInterface(Kernel::HLERequestContext& ctx) {
NGLOG_DEBUG(Service_NFP, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
void Module::Interface::Unknown(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NFP, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IUser>();
}
void InstallInterfaces(SM::ServiceManager& service_manager) {

View File

@@ -14,7 +14,7 @@ public:
public:
Interface(std::shared_ptr<Module> module, const char* name);
void CreateUserInterface(Kernel::HLERequestContext& ctx);
void Unknown(Kernel::HLERequestContext& ctx);
protected:
std::shared_ptr<Module> module;

View File

@@ -9,7 +9,7 @@ namespace Service::NFP {
NFP_User::NFP_User(std::shared_ptr<Module> module)
: Module::Interface(std::move(module), "nfp:user") {
static const FunctionInfo functions[] = {
{0, &NFP_User::CreateUserInterface, "CreateUserInterface"},
{0, &NFP_User::Unknown, "Unknown"},
};
RegisterHandlers(functions);
}

View File

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

View File

@@ -37,7 +37,7 @@ PL_U::PL_U() : ServiceFramework("pl:u") {
{2, &PL_U::GetSize, "GetSize"},
{3, &PL_U::GetSharedMemoryAddressOffset, "GetSharedMemoryAddressOffset"},
{4, &PL_U::GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"},
{5, &PL_U::GetSharedFontInOrderOfPriority, "GetSharedFontInOrderOfPriority"},
{5, nullptr, "GetSharedFontInOrderOfPriority"},
};
RegisterHandlers(functions);
@@ -52,7 +52,7 @@ PL_U::PL_U() : ServiceFramework("pl:u") {
ASSERT(file.GetSize() == SHARED_FONT_MEM_SIZE);
file.ReadBytes(shared_font->data(), shared_font->size());
} else {
NGLOG_WARNING(Service_NS, "Unable to load shared font: {}", filepath);
LOG_WARNING(Service_NS, "Unable to load shared font: %s", filepath.c_str());
}
}
@@ -60,7 +60,7 @@ void PL_U::RequestLoad(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u32 shared_font_type{rp.Pop<u32>()};
NGLOG_DEBUG(Service_NS, "called, shared_font_type={}", shared_font_type);
LOG_DEBUG(Service_NS, "called, shared_font_type=%d", shared_font_type);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
@@ -69,7 +69,7 @@ void PL_U::GetLoadState(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u32 font_id{rp.Pop<u32>()};
NGLOG_DEBUG(Service_NS, "called, font_id={}", font_id);
LOG_DEBUG(Service_NS, "called, font_id=%d", font_id);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(static_cast<u32>(LoadState::Done));
@@ -79,7 +79,7 @@ void PL_U::GetSize(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u32 font_id{rp.Pop<u32>()};
NGLOG_DEBUG(Service_NS, "called, font_id={}", font_id);
LOG_DEBUG(Service_NS, "called, font_id=%d", font_id);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(SHARED_FONT_REGIONS[font_id].size);
@@ -89,7 +89,7 @@ void PL_U::GetSharedMemoryAddressOffset(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u32 font_id{rp.Pop<u32>()};
NGLOG_DEBUG(Service_NS, "called, font_id={}", font_id);
LOG_DEBUG(Service_NS, "called, font_id=%d", font_id);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(SHARED_FONT_REGIONS[font_id].offset);
@@ -110,35 +110,10 @@ void PL_U::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) {
Kernel::MemoryPermission::Read, SHARED_FONT_MEM_VADDR, Kernel::MemoryRegion::BASE,
"PL_U:shared_font_mem");
NGLOG_DEBUG(Service_NS, "called");
LOG_DEBUG(Service_NS, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(shared_font_mem);
}
void PL_U::GetSharedFontInOrderOfPriority(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 language_code{rp.Pop<u64>()}; // TODO(ogniK): Find out what this is used for
NGLOG_DEBUG(Service_NS, "called, language_code=%lx", language_code);
IPC::ResponseBuilder rb{ctx, 4};
std::vector<u32> font_codes;
std::vector<u32> font_offsets;
std::vector<u32> font_sizes;
// TODO(ogniK): Have actual priority order
for (size_t i = 0; i < SHARED_FONT_REGIONS.size(); i++) {
font_codes.push_back(static_cast<u32>(i));
font_offsets.push_back(SHARED_FONT_REGIONS[i].offset);
font_sizes.push_back(SHARED_FONT_REGIONS[i].size);
}
ctx.WriteBuffer(font_codes.data(), font_codes.size(), 0);
ctx.WriteBuffer(font_offsets.data(), font_offsets.size(), 1);
ctx.WriteBuffer(font_sizes.data(), font_sizes.size(), 2);
rb.Push(RESULT_SUCCESS);
rb.Push<u8>(static_cast<u8>(LoadState::Done)); // Fonts Loaded
rb.Push<u32>(static_cast<u32>(font_codes.size()));
}
} // namespace Service::NS

View File

@@ -21,7 +21,6 @@ private:
void GetSize(Kernel::HLERequestContext& ctx);
void GetSharedMemoryAddressOffset(Kernel::HLERequestContext& ctx);
void GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx);
void GetSharedFontInOrderOfPriority(Kernel::HLERequestContext& ctx);
/// Handle to shared memory region designated for a shared font
Kernel::SharedPtr<Kernel::SharedMemory> shared_font_mem;

View File

@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <cinttypes>
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
@@ -20,9 +21,10 @@ u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector<u8>& input, std::vector
void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height,
u32 stride, NVFlinger::BufferQueue::BufferTransformFlags transform) {
VAddr addr = nvmap_dev->GetObjectAddress(buffer_handle);
NGLOG_WARNING(Service,
"Drawing from address {:X} offset {:08X} Width {} Height {} Stride {} Format {}",
addr, offset, width, height, stride, format);
LOG_WARNING(Service,
"Drawing from address %" PRIx64
" offset %08X Width %u Height %u Stride %u Format %u",
addr, offset, width, height, stride, format);
using PixelFormat = Tegra::FramebufferConfig::PixelFormat;
const Tegra::FramebufferConfig framebuffer{

View File

@@ -12,8 +12,8 @@
namespace Service::Nvidia::Devices {
u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
NGLOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
command.raw, input.size(), output.size());
LOG_DEBUG(Service_NVDRV, "called, command=0x%08x, input_size=0x%zx, output_size=0x%zx",
command.raw, input.size(), output.size());
switch (static_cast<IoctlCommand>(command.raw)) {
case IoctlCommand::IocInitalizeExCommand:
@@ -26,8 +26,6 @@ u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vecto
return BindChannel(input, output);
case IoctlCommand::IocGetVaRegionsCommand:
return GetVARegions(input, output);
case IoctlCommand::IocUnmapBufferCommand:
return UnmapBuffer(input, output);
}
if (static_cast<IoctlCommand>(command.cmd.Value()) == IoctlCommand::IocRemapCommand)
@@ -40,15 +38,16 @@ u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vecto
u32 nvhost_as_gpu::InitalizeEx(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlInitalizeEx params{};
std::memcpy(&params, input.data(), input.size());
NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, big_page_size=0x{:X}", params.big_page_size);
LOG_WARNING(Service_NVDRV, "(STUBBED) called, big_page_size=0x%x", params.big_page_size);
std::memcpy(output.data(), &params, output.size());
return 0;
}
u32 nvhost_as_gpu::AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlAllocSpace params{};
std::memcpy(&params, input.data(), input.size());
NGLOG_DEBUG(Service_NVDRV, "called, pages={:X}, page_size={:X}, flags={:X}", params.pages,
params.page_size, params.flags);
LOG_DEBUG(Service_NVDRV, "called, pages=%x, page_size=%x, flags=%x", params.pages,
params.page_size, params.flags);
auto& gpu = Core::System::GetInstance().GPU();
const u64 size{static_cast<u64>(params.pages) * static_cast<u64>(params.page_size)};
@@ -96,11 +95,11 @@ u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& ou
IoctlMapBufferEx params{};
std::memcpy(&params, input.data(), input.size());
NGLOG_DEBUG(Service_NVDRV,
"called, flags={:X}, nvmap_handle={:X}, buffer_offset={}, mapping_size={}"
", offset={}",
params.flags, params.nvmap_handle, params.buffer_offset, params.mapping_size,
params.offset);
LOG_DEBUG(Service_NVDRV,
"called, flags=%x, nvmap_handle=%x, buffer_offset=%" PRIu64 ", mapping_size=%" PRIu64
", offset=%" PRIu64,
params.flags, params.nvmap_handle, params.buffer_offset, params.mapping_size,
params.offset);
if (!params.nvmap_handle) {
return 0;
@@ -127,37 +126,6 @@ u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& ou
params.offset = gpu.memory_manager->MapBufferEx(object->addr, object->size);
}
// Create a new mapping entry for this operation.
ASSERT_MSG(buffer_mappings.find(params.offset) == buffer_mappings.end(),
"Offset is already mapped");
BufferMapping mapping{};
mapping.nvmap_handle = params.nvmap_handle;
mapping.offset = params.offset;
mapping.size = object->size;
buffer_mappings[params.offset] = mapping;
std::memcpy(output.data(), &params, output.size());
return 0;
}
u32 nvhost_as_gpu::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlUnmapBuffer params{};
std::memcpy(&params, input.data(), input.size());
NGLOG_DEBUG(Service_NVDRV, "called, offset=0x{:X}", params.offset);
auto& gpu = Core::System::GetInstance().GPU();
auto itr = buffer_mappings.find(params.offset);
ASSERT_MSG(itr != buffer_mappings.end(), "Tried to unmap invalid mapping");
params.offset = gpu.memory_manager->UnmapBuffer(params.offset, itr->second.size);
buffer_mappings.erase(itr->second.offset);
std::memcpy(output.data(), &params, output.size());
return 0;
}
@@ -165,16 +133,17 @@ u32 nvhost_as_gpu::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& ou
u32 nvhost_as_gpu::BindChannel(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlBindChannel params{};
std::memcpy(&params, input.data(), input.size());
NGLOG_DEBUG(Service_NVDRV, "called, fd={:X}", params.fd);
LOG_DEBUG(Service_NVDRV, "called, fd=%x", params.fd);
channel = params.fd;
std::memcpy(output.data(), &params, output.size());
return 0;
}
u32 nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlGetVaRegions params{};
std::memcpy(&params, input.data(), input.size());
NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, buf_addr={:X}, buf_size={:X}", params.buf_addr,
params.buf_size);
LOG_WARNING(Service_NVDRV, "(STUBBED) called, buf_addr=%" PRIu64 ", buf_size=%x",
params.buf_addr, params.buf_size);
params.buf_size = 0x30;
params.regions[0].offset = 0x04000000;

View File

@@ -5,7 +5,6 @@
#pragma once
#include <memory>
#include <unordered_map>
#include <utility>
#include <vector>
#include "common/common_types.h"
@@ -31,7 +30,6 @@ private:
IocMapBufferExCommand = 0xC0284106,
IocBindChannelCommand = 0x40044101,
IocGetVaRegionsCommand = 0xC0404108,
IocUnmapBufferCommand = 0xC0084105,
};
struct IoctlInitalizeEx {
@@ -78,11 +76,6 @@ private:
};
static_assert(sizeof(IoctlMapBufferEx) == 40, "IoctlMapBufferEx is incorrect size");
struct IoctlUnmapBuffer {
u64_le offset;
};
static_assert(sizeof(IoctlUnmapBuffer) == 8, "IoctlUnmapBuffer is incorrect size");
struct IoctlBindChannel {
u32_le fd;
};
@@ -105,22 +98,12 @@ private:
static_assert(sizeof(IoctlGetVaRegions) == 16 + sizeof(IoctlVaRegion) * 2,
"IoctlGetVaRegions is incorrect size");
struct BufferMapping {
u64 offset;
u64 size;
u32 nvmap_handle;
};
/// Map containing the nvmap object mappings in GPU memory.
std::unordered_map<u64, BufferMapping> buffer_mappings;
u32 channel{};
u32 InitalizeEx(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 UnmapBuffer(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);

View File

@@ -9,18 +9,14 @@
namespace Service::Nvidia::Devices {
u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
NGLOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
command.raw, input.size(), output.size());
LOG_DEBUG(Service_NVDRV, "called, command=0x%08x, input_size=0x%zx, output_size=0x%zx",
command.raw, input.size(), output.size());
switch (static_cast<IoctlCommand>(command.raw)) {
case IoctlCommand::IocGetConfigCommand:
return NvOsGetConfigU32(input, output);
case IoctlCommand::IocCtrlEventWaitCommand:
return IocCtrlEventWait(input, output, false);
case IoctlCommand::IocCtrlEventWaitAsyncCommand:
return IocCtrlEventWait(input, output, true);
case IoctlCommand::IocCtrlEventRegisterCommand:
return IocCtrlEventRegister(input, output);
return IocCtrlEventWait(input, output);
}
UNIMPLEMENTED_MSG("Unimplemented ioctl");
return 0;
@@ -29,8 +25,8 @@ u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<
u32 nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output) {
IocGetConfigParams params{};
std::memcpy(&params, input.data(), sizeof(params));
NGLOG_DEBUG(Service_NVDRV, "called, setting={}!{}", params.domain_str.data(),
params.param_str.data());
LOG_DEBUG(Service_NVDRV, "called, setting=%s!%s", params.domain_str.data(),
params.param_str.data());
if (!strcmp(params.domain_str.data(), "nv")) {
if (!strcmp(params.param_str.data(), "NV_MEMORY_PROFILER")) {
@@ -40,7 +36,7 @@ u32 nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>&
} else if (!strcmp(params.param_str.data(), "NVRM_GPU_PREVENT_USE")) {
params.config_str[0] = '0';
} else {
params.config_str[0] = '\0';
params.config_str[0] = '0';
}
} else {
UNIMPLEMENTED(); // unknown domain? Only nv has been seen so far on hardware
@@ -49,13 +45,11 @@ u32 nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>&
return 0;
}
u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output,
bool is_async) {
u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output) {
IocCtrlEventWaitParams params{};
std::memcpy(&params, input.data(), sizeof(params));
NGLOG_WARNING(Service_NVDRV,
"(STUBBED) called, syncpt_id={}, threshold={}, timeout={}, is_async={}",
params.syncpt_id, params.threshold, params.timeout, is_async);
LOG_WARNING(Service_NVDRV, "(STUBBED) called, syncpt_id=%u threshold=%u timeout=%d",
params.syncpt_id, params.threshold, params.timeout);
// TODO(Subv): Implement actual syncpt waiting.
params.value = 0;
@@ -63,10 +57,4 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>&
return 0;
}
u32 nvhost_ctrl::IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output) {
NGLOG_WARNING(Service_NVDRV, "(STUBBED) called");
// TODO(bunnei): Implement this.
return 0;
}
} // namespace Service::Nvidia::Devices

View File

@@ -26,64 +26,12 @@ private:
IocSyncptIncrCommand = 0x40040015,
IocSyncptWaitCommand = 0xC00C0016,
IocModuleMutexCommand = 0x40080017,
IocModuleRegRDWRCommand = 0xC0180018,
IocModuleRegRDWRCommand = 0xC008010E,
IocSyncptWaitexCommand = 0xC0100019,
IocSyncptReadMaxCommand = 0xC008001A,
IocGetConfigCommand = 0xC183001B,
IocCtrlEventSignalCommand = 0xC004001C,
IocCtrlEventWaitCommand = 0xC010001D,
IocCtrlEventWaitAsyncCommand = 0xC010001E,
IocCtrlEventRegisterCommand = 0xC004001F,
IocCtrlEventUnregisterCommand = 0xC0040020,
IocCtrlEventKillCommand = 0x40080021,
IocGetConfigCommand = 0xC183001B,
};
struct IocSyncptReadParams {
u32_le id;
u32_le value;
};
static_assert(sizeof(IocSyncptReadParams) == 8, "IocSyncptReadParams is incorrect size");
struct IocSyncptIncrParams {
u32_le id;
};
static_assert(sizeof(IocSyncptIncrParams) == 4, "IocSyncptIncrParams is incorrect size");
struct IocSyncptWaitParams {
u32_le id;
u32_le thresh;
s32_le timeout;
};
static_assert(sizeof(IocSyncptWaitParams) == 12, "IocSyncptWaitParams is incorrect size");
struct IocModuleMutexParams {
u32_le id;
u32_le lock; // (0 = unlock and 1 = lock)
};
static_assert(sizeof(IocModuleMutexParams) == 8, "IocModuleMutexParams is incorrect size");
struct IocModuleRegRDWRParams {
u32_le id;
u32_le num_offsets;
u32_le block_size;
u32_le offsets;
u32_le values;
u32_le write;
};
static_assert(sizeof(IocModuleRegRDWRParams) == 24, "IocModuleRegRDWRParams is incorrect size");
struct IocSyncptWaitexParams {
u32_le id;
u32_le thresh;
s32_le timeout;
u32_le value;
};
static_assert(sizeof(IocSyncptWaitexParams) == 16, "IocSyncptWaitexParams is incorrect size");
struct IocSyncptReadMaxParams {
u32_le id;
u32_le value;
};
static_assert(sizeof(IocSyncptReadMaxParams) == 8, "IocSyncptReadMaxParams is incorrect size");
struct IocGetConfigParams {
std::array<char, 0x41> domain_str;
@@ -92,12 +40,6 @@ private:
};
static_assert(sizeof(IocGetConfigParams) == 387, "IocGetConfigParams is incorrect size");
struct IocCtrlEventSignalParams {
u32_le user_event_id;
};
static_assert(sizeof(IocCtrlEventSignalParams) == 4,
"IocCtrlEventSignalParams is incorrect size");
struct IocCtrlEventWaitParams {
u32_le syncpt_id;
u32_le threshold;
@@ -106,37 +48,9 @@ private:
};
static_assert(sizeof(IocCtrlEventWaitParams) == 16, "IocCtrlEventWaitParams is incorrect size");
struct IocCtrlEventWaitAsyncParams {
u32_le syncpt_id;
u32_le threshold;
u32_le timeout;
u32_le value;
};
static_assert(sizeof(IocCtrlEventWaitAsyncParams) == 16,
"IocCtrlEventWaitAsyncParams is incorrect size");
struct IocCtrlEventRegisterParams {
u32_le user_event_id;
};
static_assert(sizeof(IocCtrlEventRegisterParams) == 4,
"IocCtrlEventRegisterParams is incorrect size");
struct IocCtrlEventUnregisterParams {
u32_le user_event_id;
};
static_assert(sizeof(IocCtrlEventUnregisterParams) == 4,
"IocCtrlEventUnregisterParams is incorrect size");
struct IocCtrlEventKill {
u64_le user_events;
};
static_assert(sizeof(IocCtrlEventKill) == 8, "IocCtrlEventKill is incorrect size");
u32 NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output);
u32 IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output, bool is_async);
u32 IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output);
u32 IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output);
};
} // namespace Service::Nvidia::Devices

View File

@@ -10,8 +10,8 @@
namespace Service::Nvidia::Devices {
u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
NGLOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
command.raw, input.size(), output.size());
LOG_DEBUG(Service_NVDRV, "called, command=0x%08x, input_size=0x%zx, output_size=0x%zx",
command.raw, input.size(), output.size());
switch (static_cast<IoctlCommand>(command.raw)) {
case IoctlCommand::IocGetCharacteristicsCommand:
@@ -24,15 +24,13 @@ u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vec
return ZCullGetCtxSize(input, output);
case IoctlCommand::IocZcullGetInfo:
return ZCullGetInfo(input, output);
case IoctlCommand::IocZbcSetTable:
return ZBCSetTable(input, output);
}
UNIMPLEMENTED_MSG("Unimplemented ioctl");
return 0;
}
u32 nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output) {
NGLOG_DEBUG(Service_NVDRV, "called");
LOG_DEBUG(Service_NVDRV, "called");
IoctlCharacteristics params{};
std::memcpy(&params, input.data(), input.size());
params.gc.arch = 0x120;
@@ -79,19 +77,14 @@ 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) {
IoctlGpuGetTpcMasksArgs params{};
std::memcpy(&params, input.data(), input.size());
NGLOG_INFO(Service_NVDRV, "called, mask=0x{:X}, mask_buf_addr=0x{:X}", params.mask_buf_size,
params.mask_buf_addr);
// TODO(ogniK): Confirm value on hardware
if (params.mask_buf_size)
params.tpc_mask_size = 4 * 1; // 4 * num_gpc
else
params.tpc_mask_size = 0;
LOG_WARNING(Service_NVDRV, "(STUBBED) called, mask=0x%x, mask_buf_addr=0x%" PRIx64,
params.mask_buf_size, params.mask_buf_addr);
std::memcpy(output.data(), &params, sizeof(params));
return 0;
}
u32 nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output) {
NGLOG_DEBUG(Service_NVDRV, "called");
LOG_DEBUG(Service_NVDRV, "called");
IoctlActiveSlotMask params{};
std::memcpy(&params, input.data(), input.size());
params.slot = 0x07;
@@ -101,7 +94,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) {
NGLOG_DEBUG(Service_NVDRV, "called");
LOG_DEBUG(Service_NVDRV, "called");
IoctlZcullGetCtxSize params{};
std::memcpy(&params, input.data(), input.size());
params.size = 0x1;
@@ -110,7 +103,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) {
NGLOG_DEBUG(Service_NVDRV, "called");
LOG_DEBUG(Service_NVDRV, "called");
IoctlNvgpuGpuZcullGetInfoArgs params{};
std::memcpy(&params, input.data(), input.size());
params.width_align_pixels = 0x20;
@@ -127,13 +120,4 @@ u32 nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>&
return 0;
}
u32 nvhost_ctrl_gpu::ZBCSetTable(const std::vector<u8>& input, std::vector<u8>& output) {
NGLOG_WARNING(Service_NVDRV, "(STUBBED) called");
IoctlZbcSetTable params{};
std::memcpy(&params, input.data(), input.size());
// TODO(ogniK): What does this even actually do?
std::memcpy(output.data(), &params, output.size());
return 0;
}
} // namespace Service::Nvidia::Devices

View File

@@ -25,7 +25,6 @@ private:
IocGetActiveSlotMaskCommand = 0x80084714,
IocZcullGetCtxSizeCommand = 0x80044701,
IocZcullGetInfo = 0x80284702,
IocZbcSetTable = 0x402C4703,
};
struct IoctlGpuCharacteristics {
@@ -87,7 +86,7 @@ private:
/// [in] pointer to TPC mask buffer. It will receive one 32-bit TPC mask per GPC or 0 if
/// GPC is not enabled or not present. This parameter is ignored if mask_buf_size is 0.
u64_le mask_buf_addr;
u64_le tpc_mask_size; // Nintendo add this?
u64_le unk; // Nintendo add this?
};
static_assert(sizeof(IoctlGpuGetTpcMasksArgs) == 24,
"IoctlGpuGetTpcMasksArgs is incorrect size");
@@ -118,21 +117,11 @@ private:
static_assert(sizeof(IoctlNvgpuGpuZcullGetInfoArgs) == 40,
"IoctlNvgpuGpuZcullGetInfoArgs is incorrect size");
struct IoctlZbcSetTable {
u32_le color_ds[4];
u32_le color_l2[4];
u32_le depth;
u32_le format;
u32_le type;
};
static_assert(sizeof(IoctlZbcSetTable) == 44, "IoctlZbcSetTable is incorrect size");
u32 GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output);
u32 GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output);
u32 GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output);
u32 ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output);
u32 ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output);
u32 ZBCSetTable(const std::vector<u8>& input, std::vector<u8>& output);
};
} // namespace Service::Nvidia::Devices

View File

@@ -12,8 +12,8 @@
namespace Service::Nvidia::Devices {
u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
NGLOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
command.raw, input.size(), output.size());
LOG_DEBUG(Service_NVDRV, "called, command=0x%08x, input_size=0x%zx, output_size=0x%zx",
command.raw, input.size(), output.size());
switch (static_cast<IoctlCommand>(command.raw)) {
case IoctlCommand::IocSetNVMAPfdCommand:
@@ -32,10 +32,6 @@ u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u
return AllocGPFIFOEx2(input, output);
case IoctlCommand::IocAllocObjCtxCommand:
return AllocateObjectContext(input, output);
case IoctlCommand::IocChannelGetWaitbaseCommand:
return GetWaitbase(input, output);
case IoctlCommand::IocChannelSetTimeoutCommand:
return ChannelSetTimeout(input, output);
}
if (command.group == NVGPU_IOCTL_MAGIC) {
@@ -51,21 +47,23 @@ u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u
u32 nvhost_gpu::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlSetNvmapFD params{};
std::memcpy(&params, input.data(), input.size());
NGLOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
LOG_DEBUG(Service_NVDRV, "called, fd=%x", params.nvmap_fd);
nvmap_fd = params.nvmap_fd;
std::memcpy(output.data(), &params, output.size());
return 0;
}
u32 nvhost_gpu::SetClientData(const std::vector<u8>& input, std::vector<u8>& output) {
NGLOG_DEBUG(Service_NVDRV, "called");
LOG_DEBUG(Service_NVDRV, "called");
IoctlClientData params{};
std::memcpy(&params, input.data(), input.size());
user_data = params.data;
std::memcpy(output.data(), &params, output.size());
return 0;
}
u32 nvhost_gpu::GetClientData(const std::vector<u8>& input, std::vector<u8>& output) {
NGLOG_DEBUG(Service_NVDRV, "called");
LOG_DEBUG(Service_NVDRV, "called");
IoctlClientData params{};
std::memcpy(&params, input.data(), input.size());
params.data = user_data;
@@ -75,8 +73,8 @@ 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) {
std::memcpy(&zcull_params, input.data(), input.size());
NGLOG_DEBUG(Service_NVDRV, "called, gpu_va={:X}, mode={:X}", zcull_params.gpu_va,
zcull_params.mode);
LOG_DEBUG(Service_NVDRV, "called, gpu_va=%" PRIx64 ", mode=%x", zcull_params.gpu_va,
zcull_params.mode);
std::memcpy(output.data(), &zcull_params, output.size());
return 0;
}
@@ -84,26 +82,26 @@ 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) {
IoctlSetErrorNotifier params{};
std::memcpy(&params, input.data(), input.size());
NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, offset={:X}, size={:X}, mem={:X}",
params.offset, params.size, params.mem);
LOG_WARNING(Service_NVDRV, "(STUBBED) called, offset=%" PRIx64 ", size=%" PRIx64 ", mem=%x",
params.offset, params.size, params.mem);
std::memcpy(output.data(), &params, output.size());
return 0;
}
u32 nvhost_gpu::SetChannelPriority(const std::vector<u8>& input, std::vector<u8>& output) {
std::memcpy(&channel_priority, input.data(), input.size());
NGLOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority={:X}", channel_priority);
LOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority=%x", channel_priority);
std::memcpy(output.data(), &channel_priority, output.size());
return 0;
}
u32 nvhost_gpu::AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlAllocGpfifoEx2 params{};
std::memcpy(&params, input.data(), input.size());
NGLOG_WARNING(Service_NVDRV,
"(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.unk3);
LOG_WARNING(Service_NVDRV,
"(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.unk3);
params.fence_out.id = 0;
params.fence_out.value = 0;
std::memcpy(output.data(), &params, output.size());
@@ -113,8 +111,8 @@ 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) {
IoctlAllocObjCtx params{};
std::memcpy(&params, input.data(), input.size());
NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, class_num={:X}, flags={:X}", params.class_num,
params.flags);
LOG_WARNING(Service_NVDRV, "(STUBBED) called, class_num=%x, flags=%x", params.class_num,
params.flags);
params.obj_id = 0x0;
std::memcpy(output.data(), &params, output.size());
return 0;
@@ -125,8 +123,8 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp
UNIMPLEMENTED();
IoctlSubmitGpfifo params{};
std::memcpy(&params, input.data(), sizeof(IoctlSubmitGpfifo));
NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}",
params.gpfifo, params.num_entries, params.flags);
LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo=%" PRIx64 ", num_entries=%x, flags=%x",
params.gpfifo, params.num_entries, params.flags);
auto entries = std::vector<IoctlGpfifoEntry>();
entries.resize(params.num_entries);
@@ -142,20 +140,4 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp
return 0;
}
u32 nvhost_gpu::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlGetWaitbase params{};
std::memcpy(&params, input.data(), sizeof(IoctlGetWaitbase));
NGLOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown);
params.value = 0; // Seems to be hard coded at 0
std::memcpy(output.data(), &params, output.size());
return 0;
}
u32 nvhost_gpu::ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlChannelSetTimeout params{};
std::memcpy(&params, input.data(), sizeof(IoctlChannelSetTimeout));
NGLOG_INFO(Service_NVDRV, "called, timeout=0x{:X}", params.timeout);
return 0;
}
} // namespace Service::Nvidia::Devices

View File

@@ -33,8 +33,6 @@ private:
IocChannelSetPriorityCommand = 0x4004480D,
IocAllocGPFIFOEx2Command = 0xC020481A,
IocAllocObjCtxCommand = 0xC0104809,
IocChannelGetWaitbaseCommand = 0xC0080003,
IocChannelSetTimeoutCommand = 0x40044803,
};
enum class CtxObjects : u32_le {
@@ -51,11 +49,6 @@ private:
};
static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size");
struct IoctlChannelSetTimeout {
u32_le timeout;
};
static_assert(sizeof(IoctlChannelSetTimeout) == 4, "IoctlChannelSetTimeout is incorrect size");
struct IoctlClientData {
u64_le data;
};
@@ -124,13 +117,7 @@ private:
IoctlFence fence_out; // returned new fence object for others to wait on
};
static_assert(sizeof(IoctlSubmitGpfifo) == 16 + sizeof(IoctlFence),
"IoctlSubmitGpfifo is incorrect size");
struct IoctlGetWaitbase {
u32 unknown; // seems to be ignored? Nintendo added this
u32 value;
};
static_assert(sizeof(IoctlGetWaitbase) == 8, "IoctlGetWaitbase is incorrect size");
"submit_gpfifo is incorrect size");
u32_le nvmap_fd{};
u64_le user_data{};
@@ -146,8 +133,6 @@ private:
u32 AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output);
u32 AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output);
u32 SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& output);
u32 GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output);
u32 ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output);
std::shared_ptr<nvmap> nvmap_dev;
};

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