Compare commits

..

36 Commits

Author SHA1 Message Date
bunnei
6a3d59fdc1 Merge pull request #402 from lioncash/core
core: Replace remaining old non-generic logger usages with fmt-capable equivalents
2018-04-26 18:45:10 -04:00
bunnei
bc43946140 Merge pull request #399 from bunnei/shader-ints
Shader decompiler prep for integer instructions
2018-04-26 18:43:51 -04:00
bunnei
4ac9b47dca Merge pull request #403 from lioncash/common
common: Remove chunk_file.h and linear_disk_cache.h
2018-04-26 16:45:41 -04:00
Lioncash
c33755e2b9 core: Replace remaining old non-generic logger usages with fmt-capable equivalents
LOG_GENERIC usages will be amended in a follow-up to keep API changes separate from
interface changes, as it will require removing a parameter from the relevant function
in the VMManager class.
2018-04-26 15:37:16 -04:00
Lioncash
87a92ef062 common: Remove chunk_file.h and linear_disk_cache.h
These are unused (and given chunk_file references Dolphin's >SVN< I doubt they were going to be used).
2018-04-26 14:59:32 -04:00
bunnei
c9d7abe9c9 gl_shader_decompiler: Boilerplate for handling integer instructions. 2018-04-26 14:38:42 -04:00
bunnei
37fa9a15cd gl_shader_decompiler: Move color output to EXIT instruction. 2018-04-26 14:38:41 -04:00
bunnei
3dd3cdeafd Merge pull request #401 from lioncash/gdbstub
core/gdbstub: Move logging macros to new fmt-compatible ones
2018-04-26 14:25:57 -04:00
Lioncash
623d772476 core/gdbstub: Move logging macros to new fmt-compatible ones 2018-04-26 12:04:50 -04:00
bunnei
4f281b3829 Merge pull request #400 from lioncash/hw
core/hw: Move logging macros over to fmt-capable ones
2018-04-26 10:35:36 -04:00
Lioncash
08da0b7acc core/hw: Move logging macros over to fmt-capable ones 2018-04-26 09:32:45 -04:00
bunnei
f81b915fd8 Merge pull request #396 from Subv/shader_ops
Shaders: Implemented the FSET instruction.
2018-04-25 22:42:54 -04:00
bunnei
dd6c67c627 Merge pull request #398 from lioncash/kernel
kernel: Migrate logging macros to fmt-compatible ones
2018-04-25 22:42:34 -04:00
bunnei
42d43ea741 Merge pull request #387 from Subv/maxwell_2d
GPU: Partially implemented the 2D surface copy engine
2018-04-25 20:40:17 -04:00
bunnei
d0825c9519 Merge pull request #395 from lioncash/file-sys
file-sys: Move logging macros over to the new fmt-capable ones
2018-04-25 20:39:08 -04:00
Lioncash
1913cf4783 kernel/shared_memory: Remove unnecessary semicolon at end of ConvertPermissions()
Functions don't need to be terminated by semicolons.
2018-04-25 20:32:16 -04:00
Lioncash
40dee76c57 kernel: Migrate logging macros to fmt-compatible ones 2018-04-25 20:32:09 -04:00
bunnei
23d68a07dc Merge pull request #390 from mailwl/pctl-module
Service/PCTL: convert to module, add services, stub
2018-04-25 15:51:43 -04:00
bunnei
60746e4e52 Merge pull request #397 from lioncash/core
core/memory: Move logging macros over to the new fmt-capable ones
2018-04-25 15:25:03 -04:00
Subv
20d86d8a36 GPU: Partially implemented the Fermi2D surface copy operation.
The hardware allows for some rather complicated operations to be performed on the data during the copy, this is not implemented.
Only same-format same-size raw copies are implemented for now.
2018-04-25 12:54:26 -05:00
Subv
e9ad8e9185 Shaders: Added bit decodings for the I2I instruction. 2018-04-25 12:52:55 -05:00
Subv
1740aa5444 Shaders: Implemented the FSET instruction.
This instruction is similar to the FSETP instruction, but it doesn't set a predicate, it sets the destination register to 1.0 if the condition holds, and 0 otherwise.
2018-04-25 12:52:32 -05:00
Subv
5ab597041f Memory: Added a missing shortcut for Memory::CopyBlock for the current process. 2018-04-25 11:55:30 -05:00
Subv
1dd4861d38 GPU: Make the Textures::CopySwizzledData function accessible from the outside of the file. 2018-04-25 11:55:30 -05:00
Subv
a6da2b93c1 GPU: Added a function to retrieve the bytes per pixel of the render target formats. 2018-04-25 11:55:29 -05:00
Subv
378c881427 GPU: Added surface copy registers to Fermi2D 2018-04-25 11:55:29 -05:00
Subv
b1109931b9 GPU: Added boilerplate code for the Fermi2D engine 2018-04-25 11:55:29 -05:00
Subv
c16cfbbc6c GPU: Reduce the number of registers of Maxwell3D to 0xE00.
The rest are just macro shim registers.
2018-04-25 11:55:28 -05:00
Subv
a994446b6e GPU: Move the Maxwell3D macro uploading code to the inside of the Maxwell3D processor.
It doesn't belong in the PFIFO handler.
2018-04-25 11:55:27 -05:00
Subv
e2f2a49d2d GPU: Corrected the upper bound of the PFIFO method ids in the command processor. 2018-04-25 11:53:54 -05:00
Lioncash
3f78a61f09 file-sys: convert a StringFromFormat call into fmt::format in GetFullPath()
Lessens the amount to read and gets rid of the PRIX64 macro, allowing us to use a single string
for the whole path, making it easier to read.
2018-04-25 12:35:37 -04:00
Lioncash
5aafc83cc9 file-sys: Move logging macros over to the new fmt-capable ones 2018-04-25 12:35:33 -04:00
bunnei
22420612db Merge pull request #394 from lioncash/video-core
video-core: Move logging macros over to new fmt-capable ones
2018-04-25 11:42:59 -04:00
Lioncash
b7551e457b video-core: Move logging macros over to new fmt-capable ones 2018-04-25 09:13:57 -04:00
mailwl
2ba4e2263c Service/PCTL: convert to module, add services, stub
PCTL::CreateServiceWithoutInitialize and IParentalControlService::Initialize, required by Kirby Star Allies
2018-04-25 09:02:27 +03:00
Subv
0369ee7248 Shaders: Added decodings for the FSET instructions. 2018-04-24 22:42:54 -05:00
53 changed files with 746 additions and 1167 deletions

View File

@@ -31,7 +31,6 @@ add_library(common STATIC
bit_set.h
break_points.cpp
break_points.h
chunk_file.h
cityhash.cpp
cityhash.h
color.h
@@ -41,7 +40,6 @@ 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

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

View File

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

View File

@@ -181,10 +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/pctl/pctl_a.cpp
hle/service/pctl/pctl_a.h
hle/service/service.cpp
hle/service/service.h
hle/service/set/set.cpp

View File

@@ -55,8 +55,8 @@ public:
}
void InterpreterFallback(u64 pc, size_t num_instructions) override {
LOG_INFO(Core_ARM, "Unicorn fallback @ 0x%" PRIx64 " for %zu instructions (instr = %08x)",
pc, num_instructions, MemoryReadCode(pc));
NGLOG_INFO(Core_ARM, "Unicorn fallback @ {:#X} for {} instructions (instr = {:08X})", pc,
num_instructions, MemoryReadCode(pc));
ARM_Interface::ThreadContext ctx;
parent.SaveContext(ctx);

View File

@@ -55,7 +55,7 @@ System::ResultStatus System::RunLoop(bool tight_loop) {
// 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");
NGLOG_TRACE(Core_ARM, "Idling");
CoreTiming::Idle();
CoreTiming::Advance();
PrepareReschedule();
@@ -82,15 +82,15 @@ System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& file
app_loader = Loader::GetLoader(filepath);
if (!app_loader) {
LOG_CRITICAL(Core, "Failed to obtain loader for %s!", filepath.c_str());
NGLOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
return ResultStatus::ErrorGetLoader;
}
std::pair<boost::optional<u32>, Loader::ResultStatus> system_mode =
app_loader->LoadKernelSystemMode();
if (system_mode.second != Loader::ResultStatus::Success) {
LOG_CRITICAL(Core, "Failed to determine system mode (Error %i)!",
static_cast<int>(system_mode.second));
NGLOG_CRITICAL(Core, "Failed to determine system mode (Error {})!",
static_cast<int>(system_mode.second));
switch (system_mode.second) {
case Loader::ResultStatus::ErrorEncrypted:
@@ -106,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) {
LOG_CRITICAL(Core, "Failed to initialize system (Error %i)!",
static_cast<int>(init_result));
NGLOG_CRITICAL(Core, "Failed to initialize system (Error {})!",
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) {
LOG_CRITICAL(Core, "Failed to load ROM (Error %i)!", static_cast<int>(load_result));
NGLOG_CRITICAL(Core, "Failed to load ROM (Error {})!", static_cast<int>(load_result));
System::Shutdown();
switch (load_result) {
@@ -151,7 +151,7 @@ void System::Reschedule() {
}
System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
LOG_DEBUG(HW_Memory, "initialized OK");
NGLOG_DEBUG(HW_Memory, "initialized OK");
CoreTiming::Init();
@@ -162,7 +162,7 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
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");
NGLOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available");
#endif
} else {
cpu_core = std::make_shared<ARM_Unicorn>();
@@ -184,7 +184,7 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
return ResultStatus::ErrorVideoCore;
}
LOG_DEBUG(Core, "Initialized OK");
NGLOG_DEBUG(Core, "Initialized OK");
// Reset counters and set time origin to current frame
GetAndResetPerfStats();
@@ -218,7 +218,7 @@ void System::Shutdown() {
app_loader.reset();
LOG_DEBUG(Core, "Shutdown OK");
NGLOG_DEBUG(Core, "Shutdown OK");
}
Service::SM::ServiceManager& System::ServiceManager() {

View File

@@ -51,11 +51,11 @@ inline s64 usToCycles(int us) {
inline s64 usToCycles(s64 us) {
if (us / 1000000 > MAX_VALUE_TO_MULTIPLY) {
LOG_ERROR(Core_Timing, "Integer overflow, use max value");
NGLOG_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");
NGLOG_DEBUG(Core_Timing, "Time very big, do rounding");
return BASE_CLOCK_RATE * (us / 1000000);
}
return (BASE_CLOCK_RATE * us) / 1000000;
@@ -63,11 +63,11 @@ inline s64 usToCycles(s64 us) {
inline s64 usToCycles(u64 us) {
if (us / 1000000 > MAX_VALUE_TO_MULTIPLY) {
LOG_ERROR(Core_Timing, "Integer overflow, use max value");
NGLOG_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");
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;
@@ -83,11 +83,11 @@ inline s64 nsToCycles(int ns) {
inline s64 nsToCycles(s64 ns) {
if (ns / 1000000000 > MAX_VALUE_TO_MULTIPLY) {
LOG_ERROR(Core_Timing, "Integer overflow, use max value");
NGLOG_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");
NGLOG_DEBUG(Core_Timing, "Time very big, do rounding");
return BASE_CLOCK_RATE * (ns / 1000000000);
}
return (BASE_CLOCK_RATE * ns) / 1000000000;
@@ -95,11 +95,11 @@ inline s64 nsToCycles(s64 ns) {
inline s64 nsToCycles(u64 ns) {
if (ns / 1000000000 > MAX_VALUE_TO_MULTIPLY) {
LOG_ERROR(Core_Timing, "Integer overflow, use max value");
NGLOG_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");
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;

View File

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

View File

@@ -2,7 +2,6 @@
// 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"
@@ -40,7 +39,7 @@ Loader::ResultStatus PartitionFilesystem::Load(const std::string& file_path, siz
Loader::ResultStatus result = Load(file_data);
if (result != Loader::ResultStatus::Success)
LOG_ERROR(Service_FS, "Failed to load PFS from file %s!", file_path.c_str());
NGLOG_ERROR(Service_FS, "Failed to load PFS from file {}!", file_path);
return result;
}

View File

@@ -2,7 +2,6 @@
// 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"
@@ -22,7 +21,7 @@ Loader::ResultStatus ProgramMetadata::Load(const std::string& file_path) {
Loader::ResultStatus result = Load(file_data);
if (result != Loader::ResultStatus::Success)
LOG_ERROR(Service_FS, "Failed to load NPDM from file %s!", file_path.c_str());
NGLOG_ERROR(Service_FS, "Failed to load NPDM from file {}!", file_path);
return result;
}
@@ -77,14 +76,14 @@ u64 ProgramMetadata::GetFilesystemPermissions() const {
}
void ProgramMetadata::Print() const {
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");
NGLOG_DEBUG(Service_FS, "Magic: {:.4}", npdm_header.magic.data());
NGLOG_DEBUG(Service_FS, "Main thread priority: {:#04X}", 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: {:#X} bytes", npdm_header.main_stack_size);
NGLOG_DEBUG(Service_FS, "Process category: {}", npdm_header.process_category);
NGLOG_DEBUG(Service_FS, "Flags: {:02X}", npdm_header.flags);
NGLOG_DEBUG(Service_FS, " > 64-bit instructions: {}",
npdm_header.has_64_bit_instructions ? "YES" : "NO");
auto address_space = "Unknown";
switch (npdm_header.address_space_type) {
@@ -96,19 +95,19 @@ void ProgramMetadata::Print() const {
break;
}
LOG_DEBUG(Service_FS, " > Address space: %s\n", address_space);
NGLOG_DEBUG(Service_FS, " > Address space: {}\n", address_space);
// Begin ACID printing (potential perms, signed)
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);
NGLOG_DEBUG(Service_FS, "Magic: {:.4}", acid_header.magic.data());
NGLOG_DEBUG(Service_FS, "Flags: {:02X}", acid_header.flags);
NGLOG_DEBUG(Service_FS, " > Is Retail: {}", acid_header.is_retail ? "YES" : "NO");
NGLOG_DEBUG(Service_FS, "Title ID Min: {:016X}", acid_header.title_id_min);
NGLOG_DEBUG(Service_FS, "Title ID Max: {:016X}", acid_header.title_id_max);
NGLOG_DEBUG(Service_FS, "Filesystem Access: {:016X}\n", acid_file_access.permissions);
// Begin ACI0 printing (actual perms, unsigned)
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);
NGLOG_DEBUG(Service_FS, "Magic: {:.4}", aci_header.magic.data());
NGLOG_DEBUG(Service_FS, "Title ID: {:016X}", aci_header.title_id);
NGLOG_DEBUG(Service_FS, "Filesystem Access: {:016X}\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)) {
LOG_ERROR(Service_FS, "Unable to read RomFS!");
NGLOG_ERROR(Service_FS, "Unable to read RomFS!");
}
}
@@ -24,13 +24,13 @@ ResultVal<std::unique_ptr<FileSystemBackend>> RomFS_Factory::Open(const Path& pa
}
ResultCode RomFS_Factory::Format(const Path& path) {
LOG_ERROR(Service_FS, "Unimplemented Format archive %s", GetName().c_str());
NGLOG_ERROR(Service_FS, "Unimplemented Format archive {}", GetName());
// TODO(bunnei): Find the right error code for this
return ResultCode(-1);
}
ResultVal<ArchiveFormatInfo> RomFS_Factory::GetFormatInfo(const Path& path) const {
LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive %s", GetName().c_str());
NGLOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive {}", GetName());
// TODO(bunnei): Find the right error code for this
return ResultCode(-1);
}

View File

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

View File

@@ -2,11 +2,9 @@
// 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"
@@ -30,7 +28,7 @@ ResultVal<std::unique_ptr<FileSystemBackend>> SaveData_Factory::Open(const Path&
}
ResultCode SaveData_Factory::Format(const Path& path) {
LOG_WARNING(Service_FS, "Format archive %s", GetName().c_str());
NGLOG_WARNING(Service_FS, "Format archive {}", GetName());
// Create the save data directory.
if (!FileUtil::CreateFullPath(GetFullPath())) {
// TODO(Subv): Find the correct error code.
@@ -41,7 +39,7 @@ ResultCode SaveData_Factory::Format(const Path& path) {
}
ResultVal<ArchiveFormatInfo> SaveData_Factory::GetFormatInfo(const Path& path) const {
LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive %s", GetName().c_str());
NGLOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive {}", GetName());
// TODO(bunnei): Find the right error code for this
return ResultCode(-1);
}
@@ -50,8 +48,7 @@ std::string SaveData_Factory::GetFullPath() const {
u64 title_id = Core::CurrentProcess()->program_id;
// TODO(Subv): Somehow obtain this value.
u32 user = 0;
return Common::StringFromFormat("%ssave/%016" PRIX64 "/%08X/", nand_directory.c_str(), title_id,
user);
return fmt::format("{}save/{:016X}/{:08X}/", nand_directory, title_id, user);
}
} // namespace FileSys

View File

@@ -2,7 +2,6 @@
// 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"
@@ -26,13 +25,13 @@ ResultVal<std::unique_ptr<FileSystemBackend>> SDMC_Factory::Open(const Path& pat
}
ResultCode SDMC_Factory::Format(const Path& path) {
LOG_ERROR(Service_FS, "Unimplemented Format archive %s", GetName().c_str());
NGLOG_ERROR(Service_FS, "Unimplemented Format archive {}", GetName());
// TODO(Subv): Find the right error code for this
return ResultCode(-1);
}
ResultVal<ArchiveFormatInfo> SDMC_Factory::GetFormatInfo(const Path& path) const {
LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive %s", GetName().c_str());
NGLOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive {}", GetName());
// TODO(bunnei): Find the right error code for this
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) {
LOG_ERROR(Input, "Factory %s already registered", name.c_str());
NGLOG_ERROR(Input, "Factory '{}' already registered", name);
}
}
@@ -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) {
LOG_ERROR(Input, "Factory %s not registered", name.c_str());
NGLOG_ERROR(Input, "Factory '{}' not registered", name);
}
}
@@ -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") {
LOG_ERROR(Input, "Unknown engine name: %s", engine.c_str());
NGLOG_ERROR(Input, "Unknown engine name: {}", engine);
}
return std::make_unique<InputDeviceType>();
}

View File

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

View File

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

View File

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

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
LOG_WARNING(Loader, "ExHeader allowed interrupts list ignored");
NGLOG_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) {
LOG_WARNING(Loader, "Incomplete exheader memory range descriptor ignored.");
NGLOG_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;
LOG_INFO(Loader, "ExHeader kernel version: %d.%d", major, minor);
NGLOG_INFO(Loader, "ExHeader kernel version: {}.{}", major, minor);
} else {
LOG_ERROR(Loader, "Unhandled kernel caps descriptor: 0x%08X", descriptor);
NGLOG_ERROR(Loader, "Unhandled kernel caps descriptor: {:#010X}", descriptor);
}
}
}

View File

@@ -29,7 +29,7 @@ SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory cat
case ResourceLimitCategory::OTHER:
return resource_limits[static_cast<u8>(category)];
default:
LOG_CRITICAL(Kernel, "Unknown resource limit category");
NGLOG_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:
LOG_ERROR(Kernel, "Unknown resource type=%08X", static_cast<u32>(resource));
NGLOG_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:
LOG_ERROR(Kernel, "Unknown resource type=%08X", static_cast<u32>(resource));
NGLOG_ERROR(Kernel, "Unknown resource type={:08X}", static_cast<u32>(resource));
UNIMPLEMENTED();
return 0;
}

View File

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

View File

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

View File

@@ -107,16 +107,16 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
// Error out if the requested permissions don't match what the creator process allows.
if (static_cast<u32>(permissions) & ~static_cast<u32>(own_other_permissions)) {
LOG_ERROR(Kernel, "cannot map id=%u, address=0x%lx name=%s, permissions don't match",
GetObjectId(), address, name.c_str());
NGLOG_ERROR(Kernel, "cannot map id={}, address={:#X} name={}, permissions don't match",
GetObjectId(), address, name);
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)) {
LOG_ERROR(Kernel, "cannot map id=%u, address=0x%lx name=%s, permissions don't match",
GetObjectId(), address, name.c_str());
NGLOG_ERROR(Kernel, "cannot map id={}, address={:#X} name={}, permissions don't match",
GetObjectId(), address, name);
return ERR_WRONG_PERMISSION;
}
@@ -131,9 +131,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()) {
LOG_ERROR(Kernel,
"cannot map id=%u, target_address=0x%lx name=%s, error mapping to virtual memory",
GetObjectId(), target_address, name.c_str());
NGLOG_ERROR(
Kernel,
"cannot map id={}, target_address={:#X} name={}, error mapping to virtual memory",
GetObjectId(), target_address, name);
return result.Code();
}
@@ -151,7 +152,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) {
LOG_TRACE(Kernel_SVC, "called, heap_size=0x%llx", heap_size);
NGLOG_TRACE(Kernel_SVC, "called, heap_size={:#X}", heap_size);
auto& process = *Core::CurrentProcess();
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) {
LOG_WARNING(Kernel_SVC, "(STUBBED) called, addr=0x%lx", addr);
NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, addr={:#X}", addr);
return RESULT_SUCCESS;
}
/// Maps a memory range into a different range.
static ResultCode MapMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x%llx, src_addr=0x%llx, size=0x%llx", dst_addr,
src_addr, size);
NGLOG_TRACE(Kernel_SVC, "called, dst_addr={:#X}, src_addr={:#X}, size={:#X}", dst_addr,
src_addr, size);
return Core::CurrentProcess()->MirrorMemory(dst_addr, src_addr, size);
}
/// Unmaps a region that was previously mapped with svcMapMemory
static ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x%llx, src_addr=0x%llx, size=0x%llx", dst_addr,
src_addr, size);
NGLOG_TRACE(Kernel_SVC, "called, dst_addr={:#X}, src_addr={:#X}, size={:#X}", 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;
LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name.c_str());
NGLOG_TRACE(Kernel_SVC, "called port_name={}", port_name);
auto it = Service::g_kernel_named_ports.find(port_name);
if (it == Service::g_kernel_named_ports.end()) {
LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: %s", port_name.c_str());
NGLOG_WARNING(Kernel_SVC, "tried to connect to unknown port: {}", port_name);
return ERR_NOT_FOUND;
}
@@ -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) {
LOG_ERROR(Kernel_SVC, "called with invalid handle=0x%08X", handle);
NGLOG_ERROR(Kernel_SVC, "called with invalid handle={:#010X}", handle);
return ERR_INVALID_HANDLE;
}
LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s)", handle, session->GetName().c_str());
NGLOG_TRACE(Kernel_SVC, "called handle={:#010X}({})", handle, session->GetName());
Core::System::GetInstance().PrepareReschedule();
@@ -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) {
LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle);
NGLOG_TRACE(Kernel_SVC, "called thread={:#010X}", thread_handle);
const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
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) {
LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle);
NGLOG_TRACE(Kernel_SVC, "called process={:#010X}", process_handle);
const SharedPtr<Process> process = g_handle_table.Get<Process>(process_handle);
if (!process) {
@@ -178,8 +178,8 @@ static ResultCode WaitSynchronization1(
/// 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) {
LOG_TRACE(Kernel_SVC, "called handles_address=0x%llx, handle_count=%d, nano_seconds=%d",
handles_address, handle_count, nano_seconds);
NGLOG_TRACE(Kernel_SVC, "called handles_address={:#X}, handle_count={}, nano_seconds={}",
handles_address, handle_count, nano_seconds);
if (!Memory::IsValidVirtualAddress(handles_address))
return ERR_INVALID_POINTER;
@@ -239,7 +239,7 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64
/// Resumes a thread waiting on WaitSynchronization
static ResultCode CancelSynchronization(Handle thread_handle) {
LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle);
NGLOG_TRACE(Kernel_SVC, "called thread={:#X}", thread_handle);
const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
if (!thread) {
@@ -256,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) {
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);
NGLOG_TRACE(Kernel_SVC,
"called holding_thread_handle={:#010X}, mutex_addr={:#X}, "
"requesting_current_thread_handle={:#010X}",
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) {
LOG_TRACE(Kernel_SVC, "called mutex_addr=0x%llx", mutex_addr);
NGLOG_TRACE(Kernel_SVC, "called mutex_addr={:#X}", mutex_addr);
return Mutex::Release(mutex_addr);
}
/// Break program execution
static void Break(u64 unk_0, u64 unk_1, u64 unk_2) {
LOG_CRITICAL(Debug_Emulated, "Emulated program broke execution!");
NGLOG_CRITICAL(Debug_Emulated, "Emulated program broke execution!");
ASSERT(false);
}
/// Used to output a message on a debug hardware unit - does nothing on a retail unit
static void OutputDebugString(VAddr address, s32 len) {
std::vector<char> string(len);
Memory::ReadBlock(address, string.data(), len);
LOG_DEBUG(Debug_Emulated, "%.*s", len, string.data());
std::string str(len, '\0');
Memory::ReadBlock(address, str.data(), str.size());
NGLOG_DEBUG(Debug_Emulated, "{}", str);
}
/// Gets system/memory information for the current process
static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) {
LOG_TRACE(Kernel_SVC, "called info_id=0x%X, info_sub_id=0x%X, handle=0x%08X", info_id,
info_sub_id, handle);
NGLOG_TRACE(Kernel_SVC, "called info_id={:#X}, info_sub_id={:#X}, handle={:#010X}", info_id,
info_sub_id, handle);
auto& vm_manager = Core::CurrentProcess()->vm_manager;
@@ -338,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:
LOG_WARNING(Kernel_SVC, "(STUBBED) Attempted to query titleid, returned 0");
NGLOG_WARNING(Kernel_SVC, "(STUBBED) Attempted to query titleid, returned 0");
*result = 0;
break;
case GetInfoType::PrivilegedProcessId:
LOG_WARNING(Kernel_SVC,
"(STUBBED) Attempted to query priviledged process id bounds, returned 0");
NGLOG_WARNING(Kernel_SVC,
"(STUBBED) Attempted to query privileged process id bounds, returned 0");
*result = 0;
break;
default:
@@ -355,13 +355,14 @@ 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) {
LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x%08X, unknown=0x%08X", handle, unknown);
NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, handle={:#010X}, unknown={:#010X}", handle,
unknown);
return RESULT_SUCCESS;
}
/// Gets the thread context
static ResultCode GetThreadContext(Handle handle, VAddr addr) {
LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x%08X, addr=0x%" PRIx64, handle, addr);
NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, handle={:#010X}, addr={:#X}", handle, addr);
return RESULT_SUCCESS;
}
@@ -400,15 +401,15 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
/// Get which CPU core is executing the current thread
static u32 GetCurrentProcessorNumber() {
LOG_WARNING(Kernel_SVC, "(STUBBED) called, defaulting to processor 0");
NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, defaulting to processor 0");
return 0;
}
static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size,
u32 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);
NGLOG_TRACE(Kernel_SVC,
"called, shared_memory_handle={:#X}, addr={:#X}, size={:#X}, permissions={:#010X}",
shared_memory_handle, addr, size, permissions);
SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(shared_memory_handle);
if (!shared_memory) {
@@ -428,16 +429,15 @@ static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 s
return shared_memory->Map(Core::CurrentProcess().get(), addr, permissions_type,
MemoryPermission::DontCare);
default:
LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions);
NGLOG_ERROR(Kernel_SVC, "unknown permissions={:#010X}", permissions);
}
return RESULT_SUCCESS;
}
static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size) {
LOG_WARNING(Kernel_SVC,
"called, shared_memory_handle=0x%08X, addr=0x%" PRIx64 ", size=0x%" PRIx64 "",
shared_memory_handle, addr, size);
NGLOG_WARNING(Kernel_SVC, "called, shared_memory_handle={:#010X}, addr={:#X}, size={:#X}",
shared_memory_handle, addr, size);
SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(shared_memory_handle);
@@ -465,19 +465,19 @@ static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* /*page_i
memory_info->type = static_cast<u32>(vma->second.meminfo_state);
}
LOG_TRACE(Kernel_SVC, "called process=0x%08X addr=%llx", process_handle, addr);
NGLOG_TRACE(Kernel_SVC, "called process={:#010X} addr={:X}", process_handle, addr);
return RESULT_SUCCESS;
}
/// Query memory
static ResultCode QueryMemory(MemoryInfo* memory_info, PageInfo* page_info, VAddr addr) {
LOG_TRACE(Kernel_SVC, "called, addr=%llx", addr);
NGLOG_TRACE(Kernel_SVC, "called, addr={:X}", addr);
return QueryProcessMemory(memory_info, page_info, CurrentProcess, addr);
}
/// Exits the current process
static void ExitProcess() {
LOG_INFO(Kernel_SVC, "Process %u exiting", Core::CurrentProcess()->process_id);
NGLOG_INFO(Kernel_SVC, "Process {} exiting", Core::CurrentProcess()->process_id);
ASSERT_MSG(Core::CurrentProcess()->status == ProcessStatus::Running,
"Process has already exited");
@@ -534,9 +534,9 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
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);
NGLOG_ERROR(Kernel_SVC,
"Newly created thread must run in another thread ({}), unimplemented.",
processor_id);
break;
default:
ASSERT_MSG(false, "Unsupported thread processor ID: %d", processor_id);
@@ -551,17 +551,17 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
Core::System::GetInstance().PrepareReschedule();
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);
NGLOG_TRACE(Kernel_SVC,
"called entrypoint={:#010X} ({}), arg={:#010X}, stacktop={:#010X}, "
"threadpriority={:#010X}, processorid={:#010X} : created handle={:#010X}",
entry_point, name, arg, stack_top, priority, processor_id, *out_handle);
return RESULT_SUCCESS;
}
/// Starts the thread for the provided handle
static ResultCode StartThread(Handle thread_handle) {
LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle);
NGLOG_TRACE(Kernel_SVC, "called thread={:#010X}", thread_handle);
const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
if (!thread) {
@@ -575,7 +575,7 @@ static ResultCode StartThread(Handle thread_handle) {
/// Called when a thread exits
static void ExitThread() {
LOG_TRACE(Kernel_SVC, "called, pc=0x%08X", Core::CPU().GetPC());
NGLOG_TRACE(Kernel_SVC, "called, pc={:#010X}", Core::CPU().GetPC());
ExitCurrentThread();
Core::System::GetInstance().PrepareReschedule();
@@ -583,7 +583,7 @@ static void ExitThread() {
/// Sleep the current thread
static void SleepThread(s64 nanoseconds) {
LOG_TRACE(Kernel_SVC, "called nanoseconds=%lld", nanoseconds);
NGLOG_TRACE(Kernel_SVC, "called nanoseconds={}", nanoseconds);
// Don't attempt to yield execution if there are no available threads to run,
// this way we avoid a useless reschedule to the idle thread.
@@ -602,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) {
LOG_TRACE(
NGLOG_TRACE(
Kernel_SVC,
"called mutex_addr=%llx, condition_variable_addr=%llx, thread_handle=0x%08X, timeout=%d",
"called mutex_addr={:X}, condition_variable_addr={:X}, thread_handle={:#010X}, timeout={}",
mutex_addr, condition_variable_addr, thread_handle, nano_seconds);
SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
@@ -629,8 +629,8 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_var
/// Signal process wide key
static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target) {
LOG_TRACE(Kernel_SVC, "called, condition_variable_addr=0x%llx, target=0x%08x",
condition_variable_addr, target);
NGLOG_TRACE(Kernel_SVC, "called, condition_variable_addr={:#X}, target={:#010X}",
condition_variable_addr, target);
u32 processed = 0;
auto& thread_list = Core::System::GetInstance().Scheduler().GetThreadList();
@@ -696,13 +696,13 @@ static u64 GetSystemTick() {
/// Close a handle
static ResultCode CloseHandle(Handle handle) {
LOG_TRACE(Kernel_SVC, "Closing handle 0x%08X", handle);
NGLOG_TRACE(Kernel_SVC, "Closing handle {:#010X}", handle);
return g_handle_table.Close(handle);
}
/// Reset an event
static ResultCode ResetSignal(Handle handle) {
LOG_WARNING(Kernel_SVC, "(STUBBED) called handle 0x%08X", handle);
NGLOG_WARNING(Kernel_SVC, "(STUBBED) called handle {:#010X}", handle);
auto event = g_handle_table.Get<Event>(handle);
ASSERT(event != nullptr);
event->Clear();
@@ -711,29 +711,29 @@ static ResultCode ResetSignal(Handle handle) {
/// Creates a TransferMemory object
static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32 permissions) {
LOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x%lx, size=0x%lx, perms=%08X", addr, size,
permissions);
NGLOG_WARNING(Kernel_SVC, "(STUBBED) called addr={:#X}, size={:#X}, perms={:010X}", addr, size,
permissions);
*handle = 0;
return RESULT_SUCCESS;
}
static ResultCode GetThreadCoreMask(Handle handle, u32* mask, u64* unknown) {
LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x%08X", handle);
NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, handle={:010X}", handle);
*mask = 0x0;
*unknown = 0xf;
return RESULT_SUCCESS;
}
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);
NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, handle={:#010X}, mask={:#010X}, unknown={:#X}",
handle, mask, unknown);
return RESULT_SUCCESS;
}
static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permissions,
u32 remote_permissions) {
LOG_TRACE(Kernel_SVC, "called, size=0x%llx, localPerms=0x%08x, remotePerms=0x%08x", size,
local_permissions, remote_permissions);
NGLOG_TRACE(Kernel_SVC, "called, size={:#X}, localPerms={:#010X}, remotePerms={:#010X}", size,
local_permissions, remote_permissions);
auto sharedMemHandle =
SharedMemory::Create(g_handle_table.Get<Process>(KernelHandle::CurrentProcess), size,
static_cast<MemoryPermission>(local_permissions),
@@ -744,7 +744,7 @@ static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permiss
}
static ResultCode ClearEvent(Handle handle) {
LOG_TRACE(Kernel_SVC, "called, event=0xX", handle);
NGLOG_TRACE(Kernel_SVC, "called, event={:010X}", handle);
SharedPtr<Event> evt = g_handle_table.Get<Event>(handle);
if (evt == nullptr)
@@ -896,7 +896,7 @@ static const FunctionDef SVC_Table[] = {
static const FunctionDef* GetSVCInfo(u32 func_num) {
if (func_num >= std::size(SVC_Table)) {
LOG_ERROR(Kernel_SVC, "unknown svc=0x%02X", func_num);
NGLOG_ERROR(Kernel_SVC, "Unknown svc={:#04X}", func_num);
return nullptr;
}
return &SVC_Table[func_num];
@@ -915,10 +915,10 @@ void CallSVC(u32 immediate) {
if (info->func) {
info->func();
} else {
LOG_CRITICAL(Kernel_SVC, "unimplemented SVC function %s(..)", info->name);
NGLOG_CRITICAL(Kernel_SVC, "Unimplemented SVC function {}(..)", info->name);
}
} else {
LOG_CRITICAL(Kernel_SVC, "unknown SVC function 0x%x", immediate);
NGLOG_CRITICAL(Kernel_SVC, "Unknown SVC function {:#X}", immediate);
}
}

View File

@@ -101,9 +101,10 @@ 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) {
SharedPtr<Thread> thread = wakeup_callback_handle_table.Get<Thread>((Handle)thread_handle);
const auto proper_handle = static_cast<Handle>(thread_handle);
SharedPtr<Thread> thread = wakeup_callback_handle_table.Get<Thread>(proper_handle);
if (thread == nullptr) {
LOG_CRITICAL(Kernel, "Callback fired for invalid thread %08X", (Handle)thread_handle);
NGLOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", proper_handle);
return;
}
@@ -238,19 +239,19 @@ 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) {
LOG_ERROR(Kernel_SVC, "Invalid thread priority: %u", priority);
NGLOG_ERROR(Kernel_SVC, "Invalid thread priority: {}", priority);
return ERR_OUT_OF_RANGE;
}
if (processor_id > THREADPROCESSORID_MAX) {
LOG_ERROR(Kernel_SVC, "Invalid processor id: %d", processor_id);
NGLOG_ERROR(Kernel_SVC, "Invalid processor id: {}", processor_id);
return ERR_OUT_OF_RANGE_KERNEL;
}
// TODO(yuriks): Other checks, returning 0xD9001BEA
if (!Memory::IsValidVirtualAddress(*owner_process, entry_point)) {
LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %016" PRIx64, name.c_str(), entry_point);
NGLOG_ERROR(Kernel_SVC, "(name={}): invalid entry {:016X}", name, entry_point);
// TODO (bunnei): Find the correct error code to use here
return ResultCode(-1);
}
@@ -289,8 +290,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) {
LOG_ERROR(Kernel_SVC,
"Not enough space in region to allocate a new TLS page for thread");
NGLOG_ERROR(Kernel_SVC,
"Not enough space in region to allocate a new TLS page for thread");
return ERR_OUT_OF_MEMORY;
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,28 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "core/hle/service/service.h"
namespace Service::PCTL {
class Module final {
public:
class Interface : public ServiceFramework<Interface> {
public:
Interface(std::shared_ptr<Module> module, const char* name);
void CreateService(Kernel::HLERequestContext& ctx);
void CreateServiceWithoutInitialize(Kernel::HLERequestContext& ctx);
protected:
std::shared_ptr<Module> module;
};
};
/// Registers all PCTL services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace Service::PCTL

View File

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

View File

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

View File

@@ -1,20 +0,0 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "core/hle/service/service.h"
namespace Service::PCTL {
class PCTL_A final : public ServiceFramework<PCTL_A> {
public:
PCTL_A();
~PCTL_A() = default;
private:
void CreateService(Kernel::HLERequestContext& ctx);
};
} // namespace Service::PCTL

View File

@@ -29,7 +29,7 @@
#include "core/hle/service/nifm/nifm.h"
#include "core/hle/service/ns/ns.h"
#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/hle/service/pctl/pctl.h"
#include "core/hle/service/pctl/module.h"
#include "core/hle/service/service.h"
#include "core/hle/service/set/settings.h"
#include "core/hle/service/sm/controller.h"

View File

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

View File

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

View File

@@ -659,6 +659,10 @@ void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr,
}
}
void CopyBlock(VAddr dest_addr, VAddr src_addr, size_t size) {
CopyBlock(*Core::CurrentProcess(), dest_addr, src_addr, size);
}
boost::optional<PAddr> TryVirtualToPhysicalAddress(const VAddr addr) {
if (addr == 0) {
return 0;

View File

@@ -42,14 +42,14 @@ u64 GetTelemetryId() {
if (FileUtil::Exists(filename)) {
FileUtil::IOFile file(filename, "rb");
if (!file.IsOpen()) {
LOG_ERROR(Core, "failed to open telemetry_id: %s", filename.c_str());
NGLOG_ERROR(Core, "failed to open telemetry_id: {}", filename);
return {};
}
file.ReadBytes(&telemetry_id, sizeof(u64));
} else {
FileUtil::IOFile file(filename, "wb");
if (!file.IsOpen()) {
LOG_ERROR(Core, "failed to open telemetry_id: %s", filename.c_str());
NGLOG_ERROR(Core, "failed to open telemetry_id: {}", filename);
return {};
}
telemetry_id = GenerateTelemetryId();
@@ -65,7 +65,7 @@ u64 RegenerateTelemetryId() {
FileUtil::IOFile file(filename, "wb");
if (!file.IsOpen()) {
LOG_ERROR(Core, "failed to open telemetry_id: %s", filename.c_str());
NGLOG_ERROR(Core, "failed to open telemetry_id: {}", filename);
return {};
}
file.WriteBytes(&new_telemetry_id, sizeof(u64));

View File

@@ -159,7 +159,7 @@ void Recorder::Finish(const std::string& filename) {
throw "Failed to write stream element";
}
} catch (const char* str) {
LOG_ERROR(HW_GPU, "Writing CiTrace file failed: %s", str);
NGLOG_ERROR(HW_GPU, "Writing CiTrace file failed: {}", str);
}
}

View File

@@ -24,41 +24,18 @@ namespace Tegra {
enum class BufferMethods {
BindObject = 0,
SetGraphMacroCode = 0x45,
SetGraphMacroCodeArg = 0x46,
SetGraphMacroEntry = 0x47,
CountBufferMethods = 0x100,
CountBufferMethods = 0x40,
};
void GPU::WriteReg(u32 method, u32 subchannel, u32 value, u32 remaining_params) {
LOG_WARNING(HW_GPU, "Processing method %08X on subchannel %u value %08X remaining params %u",
method, subchannel, value, remaining_params);
if (method == static_cast<u32>(BufferMethods::SetGraphMacroEntry)) {
// Prepare to upload a new macro, reset the upload counter.
LOG_DEBUG(HW_GPU, "Uploading GPU macro %08X", value);
current_macro_entry = value;
current_macro_code.clear();
return;
}
if (method == static_cast<u32>(BufferMethods::SetGraphMacroCodeArg)) {
// Append a new code word to the current macro.
current_macro_code.push_back(value);
// There are no more params remaining, submit the code to the 3D engine.
if (remaining_params == 0) {
maxwell_3d->SubmitMacroCode(current_macro_entry, std::move(current_macro_code));
current_macro_entry = InvalidGraphMacroEntry;
current_macro_code.clear();
}
return;
}
NGLOG_WARNING(HW_GPU,
"Processing method {:08X} on subchannel {} value "
"{:08X} remaining params {}",
method, subchannel, value, remaining_params);
if (method == static_cast<u32>(BufferMethods::BindObject)) {
// Bind the current subchannel to the desired engine id.
LOG_DEBUG(HW_GPU, "Binding subchannel %u to engine %u", subchannel, value);
NGLOG_DEBUG(HW_GPU, "Binding subchannel {} to engine {}", subchannel, value);
ASSERT(bound_engines.find(subchannel) == bound_engines.end());
bound_engines[subchannel] = static_cast<EngineID>(value);
return;
@@ -66,7 +43,7 @@ void GPU::WriteReg(u32 method, u32 subchannel, u32 value, u32 remaining_params)
if (method < static_cast<u32>(BufferMethods::CountBufferMethods)) {
// TODO(Subv): Research and implement these methods.
LOG_ERROR(HW_GPU, "Special buffer methods other than Bind are not implemented");
NGLOG_ERROR(HW_GPU, "Special buffer methods other than Bind are not implemented");
return;
}

View File

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

View File

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

View File

@@ -22,10 +22,6 @@ constexpr u32 MacroRegistersStart = 0xE00;
Maxwell3D::Maxwell3D(MemoryManager& memory_manager)
: memory_manager(memory_manager), macro_interpreter(*this) {}
void Maxwell3D::SubmitMacroCode(u32 entry, std::vector<u32> code) {
uploaded_macros[entry * 2 + MacroRegistersStart] = std::move(code);
}
void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) {
auto macro_code = uploaded_macros.find(method);
// The requested macro must have been uploaded already.
@@ -37,9 +33,6 @@ void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) {
}
void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
ASSERT_MSG(method < Regs::NUM_REGS,
"Invalid Maxwell3D register, increase the size of the Regs structure");
auto debug_context = Core::System::GetInstance().GetGPUDebugContext();
// It is an error to write to a register other than the current macro's ARG register before it
@@ -68,6 +61,9 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
return;
}
ASSERT_MSG(method < Regs::NUM_REGS,
"Invalid Maxwell3D register, increase the size of the Regs structure");
if (debug_context) {
debug_context->OnEvent(Tegra::DebugContext::Event::MaxwellCommandLoaded, nullptr);
}
@@ -75,6 +71,10 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
regs.reg_array[method] = value;
switch (method) {
case MAXWELL3D_REG_INDEX(macros.data): {
ProcessMacroUpload(value);
break;
}
case MAXWELL3D_REG_INDEX(code_address.code_address_high):
case MAXWELL3D_REG_INDEX(code_address.code_address_low): {
// Note: For some reason games (like Puyo Puyo Tetris) seem to write 0 to the CODE_ADDRESS
@@ -141,6 +141,12 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
}
}
void Maxwell3D::ProcessMacroUpload(u32 data) {
// Store the uploaded macro code to interpret them when they're called.
auto& macro = uploaded_macros[regs.macros.entry * 2 + MacroRegistersStart];
macro.push_back(data);
}
void Maxwell3D::ProcessQueryGet() {
GPUVAddr sequence_address = regs.query.QueryAddress();
// Since the sequence address is given as a GPU VAddr, we have to convert it to an application
@@ -186,8 +192,8 @@ void Maxwell3D::ProcessQueryGet() {
}
void Maxwell3D::DrawArrays() {
LOG_DEBUG(HW_GPU, "called, topology=%d, count=%d", regs.draw.topology.Value(),
regs.vertex_buffer.count);
NGLOG_DEBUG(HW_GPU, "called, topology={}, count={}",
static_cast<u32>(regs.draw.topology.Value()), regs.vertex_buffer.count);
ASSERT_MSG(!(regs.index_array.count && regs.vertex_buffer.count), "Both indexed and direct?");
auto debug_context = Core::System::GetInstance().GetGPUDebugContext();

View File

@@ -31,7 +31,7 @@ public:
/// Register structure of the Maxwell3D engine.
/// TODO(Subv): This structure will need to be made bigger as more registers are discovered.
struct Regs {
static constexpr size_t NUM_REGS = 0xE36;
static constexpr size_t NUM_REGS = 0xE00;
static constexpr size_t NumRenderTargets = 8;
static constexpr size_t NumViewports = 16;
@@ -322,7 +322,15 @@ public:
union {
struct {
INSERT_PADDING_WORDS(0x200);
INSERT_PADDING_WORDS(0x45);
struct {
INSERT_PADDING_WORDS(1);
u32 data;
u32 entry;
} macros;
INSERT_PADDING_WORDS(0x1B8);
struct {
u32 address_high;
@@ -605,7 +613,7 @@ public:
u32 size[MaxShaderStage];
} tex_info_buffers;
INSERT_PADDING_WORDS(0x102);
INSERT_PADDING_WORDS(0xCC);
};
std::array<u32, NUM_REGS> reg_array;
};
@@ -637,9 +645,6 @@ public:
/// Write the value to the register identified by method.
void WriteReg(u32 method, u32 value, u32 remaining_params);
/// Uploads the code for a GPU macro program associated with the specified entry.
void SubmitMacroCode(u32 entry, std::vector<u32> code);
/// Returns a list of enabled textures for the specified shader stage.
std::vector<Texture::FullTextureInfo> GetStageTextures(Regs::ShaderStage stage) const;
@@ -670,6 +675,9 @@ private:
*/
void CallMacroMethod(u32 method, std::vector<u32> parameters);
/// Handles writes to the macro uploading registers.
void ProcessMacroUpload(u32 data);
/// Handles a write to the QUERY_GET register.
void ProcessQueryGet();
@@ -687,6 +695,7 @@ private:
static_assert(offsetof(Maxwell3D::Regs, field_name) == position * 4, \
"Field " #field_name " has invalid position")
ASSERT_REG_POSITION(macros, 0x45);
ASSERT_REG_POSITION(rt, 0x200);
ASSERT_REG_POSITION(viewport_transform[0], 0x280);
ASSERT_REG_POSITION(viewport, 0x300);

View File

@@ -19,7 +19,10 @@ namespace Tegra {
namespace Shader {
struct Register {
// Register 255 is special cased to always be 0
/// Number of registers
static constexpr size_t NumRegisters = 256;
/// Register 255 is special cased to always be 0
static constexpr size_t ZeroIndex = 255;
constexpr Register() = default;
@@ -48,6 +51,11 @@ struct Register {
return ~value;
}
u64 GetSwizzledIndex(u64 elem) const {
elem = (value + elem) & 3;
return (value & ~3) + elem;
}
private:
u64 value{};
};
@@ -214,6 +222,20 @@ union Instruction {
BitField<56, 1, u64> neg_b;
} fsetp;
union {
BitField<39, 3, u64> pred39;
BitField<42, 1, u64> neg_pred;
BitField<43, 1, u64> neg_a;
BitField<44, 1, u64> abs_b;
BitField<45, 2, PredOperation> op;
BitField<48, 4, PredCondition> cond;
BitField<53, 1, u64> neg_b;
BitField<54, 1, u64> abs_a;
BitField<52, 1, u64> bf;
BitField<55, 1, u64> ftz;
BitField<56, 1, u64> neg_imm;
} fset;
BitField<61, 1, u64> is_b_imm;
BitField<60, 1, u64> is_b_gpr;
BitField<59, 1, u64> is_c_gpr;
@@ -261,6 +283,9 @@ public:
I2F_C,
I2F_R,
I2F_IMM,
I2I_C,
I2I_R,
I2I_IMM,
LOP32I,
MOV_C,
MOV_R,
@@ -272,6 +297,9 @@ public:
FSETP_C, // Set Predicate
FSETP_R,
FSETP_IMM,
FSET_C,
FSET_R,
FSET_IMM,
ISETP_C,
ISETP_IMM,
ISETP_R,
@@ -283,8 +311,9 @@ public:
Ffma,
Flow,
Memory,
FloatPredicate,
IntegerPredicate,
FloatSet,
FloatSetPredicate,
IntegerSetPredicate,
Unknown,
};
@@ -409,6 +438,9 @@ private:
INST("0100110010111---", Id::I2F_C, Type::Arithmetic, "I2F_C"),
INST("0101110010111---", Id::I2F_R, Type::Arithmetic, "I2F_R"),
INST("0011100-10111---", Id::I2F_IMM, Type::Arithmetic, "I2F_IMM"),
INST("0100110011100---", Id::I2I_C, Type::Arithmetic, "I2I_C"),
INST("0101110011100---", Id::I2I_R, Type::Arithmetic, "I2I_R"),
INST("01110001-1000---", Id::I2I_IMM, Type::Arithmetic, "I2I_IMM"),
INST("000001----------", Id::LOP32I, Type::Arithmetic, "LOP32I"),
INST("0100110010011---", Id::MOV_C, Type::Arithmetic, "MOV_C"),
INST("0101110010011---", Id::MOV_R, Type::Arithmetic, "MOV_R"),
@@ -417,12 +449,15 @@ private:
INST("0100110000101---", Id::SHR_C, Type::Arithmetic, "SHR_C"),
INST("0101110000101---", Id::SHR_R, Type::Arithmetic, "SHR_R"),
INST("0011100-00101---", Id::SHR_IMM, Type::Arithmetic, "SHR_IMM"),
INST("010010111011----", Id::FSETP_C, Type::FloatPredicate, "FSETP_C"),
INST("010110111011----", Id::FSETP_R, Type::FloatPredicate, "FSETP_R"),
INST("0011011-1011----", Id::FSETP_IMM, Type::FloatPredicate, "FSETP_IMM"),
INST("010010110110----", Id::ISETP_C, Type::IntegerPredicate, "ISETP_C"),
INST("010110110110----", Id::ISETP_R, Type::IntegerPredicate, "ISETP_R"),
INST("0011011-0110----", Id::ISETP_IMM, Type::IntegerPredicate, "ISETP_IMM"),
INST("01011000--------", Id::FSET_R, Type::FloatSet, "FSET_R"),
INST("0100100---------", Id::FSET_C, Type::FloatSet, "FSET_C"),
INST("0011000---------", Id::FSET_IMM, Type::FloatSet, "FSET_IMM"),
INST("010010111011----", Id::FSETP_C, Type::FloatSetPredicate, "FSETP_C"),
INST("010110111011----", Id::FSETP_R, Type::FloatSetPredicate, "FSETP_R"),
INST("0011011-1011----", Id::FSETP_IMM, Type::FloatSetPredicate, "FSETP_IMM"),
INST("010010110110----", Id::ISETP_C, Type::IntegerSetPredicate, "ISETP_C"),
INST("010110110110----", Id::ISETP_R, Type::IntegerSetPredicate, "ISETP_R"),
INST("0011011-0110----", Id::ISETP_IMM, Type::IntegerSetPredicate, "ISETP_IMM"),
};
#undef INST
std::stable_sort(table.begin(), table.end(), [](const auto& a, const auto& b) {

View File

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

View File

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

View File

@@ -116,7 +116,7 @@ RasterizerOpenGL::RasterizerOpenGL() {
glEnable(GL_BLEND);
LOG_CRITICAL(Render_OpenGL, "Sync fixed function OpenGL state here!");
NGLOG_CRITICAL(Render_OpenGL, "Sync fixed function OpenGL state here!");
}
RasterizerOpenGL::~RasterizerOpenGL() {
@@ -252,8 +252,8 @@ void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset) {
break;
}
default:
LOG_CRITICAL(HW_GPU, "Unimplemented shader index=%d, enable=%d, offset=0x%08X", index,
shader_config.enable.Value(), shader_config.offset);
NGLOG_CRITICAL(HW_GPU, "Unimplemented shader index={}, enable={}, offset={:#010X}",
index, shader_config.enable.Value(), shader_config.offset);
UNREACHABLE();
}

View File

@@ -146,6 +146,90 @@ private:
std::string shader_source;
};
/**
* Represents an emulated shader register, used to track the state of that register for emulation
* with GLSL. At this time, a register can be used as a float or an integer. This class is used for
* bookkeeping within the GLSL program.
*/
class GLSLRegister {
public:
GLSLRegister(size_t index, ShaderWriter& shader)
: index{index}, shader{shader}, float_str{"freg_" + std::to_string(index)},
integer_str{"ireg_" + std::to_string(index)} {}
/// Returns a GLSL string representing the current state of the register
const std::string& GetActiveString() {
declr_type.insert(active_type);
switch (active_type) {
case Type::Float:
return float_str;
case Type::Integer:
return integer_str;
}
UNREACHABLE();
return float_str;
}
/// Returns a GLSL string representing the register as a float
const std::string& GetFloatString() const {
ASSERT(IsFloatUsed());
return float_str;
}
/// Returns a GLSL string representing the register as an integer
const std::string& GetIntegerString() const {
ASSERT(IsIntegerUsed());
return integer_str;
}
/// Convert the current register state from float to integer
void FloatToInteger() {
ASSERT(active_type == Type::Float);
const std::string src = GetActiveString();
active_type = Type::Integer;
const std::string dest = GetActiveString();
shader.AddLine(dest + " = floatBitsToInt(" + src + ");");
}
/// Convert the current register state from integer to float
void IntegerToFloat() {
ASSERT(active_type == Type::Integer);
const std::string src = GetActiveString();
active_type = Type::Float;
const std::string dest = GetActiveString();
shader.AddLine(dest + " = intBitsToFloat(" + src + ");");
}
/// Returns true if the register was ever used as a float, used for register declarations
bool IsFloatUsed() const {
return declr_type.find(Type::Float) != declr_type.end();
}
/// Returns true if the register was ever used as an integer, used for register declarations
bool IsIntegerUsed() const {
return declr_type.find(Type::Integer) != declr_type.end();
}
private:
enum class Type {
Float,
Integer,
};
const size_t index;
const std::string float_str;
const std::string integer_str;
ShaderWriter& shader;
Type active_type{Type::Float};
std::set<Type> declr_type;
};
class GLSLGenerator {
public:
GLSLGenerator(const std::set<Subroutine>& subroutines, const ProgramCode& program_code,
@@ -153,6 +237,7 @@ public:
: subroutines(subroutines), program_code(program_code), main_offset(main_offset),
stage(stage) {
BuildRegisterList();
Generate();
}
@@ -166,6 +251,13 @@ public:
}
private:
/// Build the GLSL register list
void BuildRegisterList() {
for (size_t index = 0; index < Register::NumRegisters; ++index) {
regs.emplace_back(index, shader);
}
}
/// Gets the Subroutine object corresponding to the specified address.
const Subroutine& GetSubroutine(u32 begin, u32 end) const {
auto iter = subroutines.find(Subroutine{begin, end});
@@ -221,14 +313,11 @@ private:
/// Generates code representing a temporary (GPR) register.
std::string GetRegister(const Register& reg, unsigned elem = 0) {
if (reg == Register::ZeroIndex)
if (reg == Register::ZeroIndex) {
return "0";
if (stage == Maxwell3D::Regs::ShaderStage::Fragment && reg < 4) {
// GPRs 0-3 are output color for the fragment shader
return std::string{"color."} + "rgba"[(reg + elem) & 3];
}
return *declr_register.insert("register_" + std::to_string(reg + elem)).first;
return regs[reg.GetSwizzledIndex(elem)].GetActiveString();
}
/// Generates code representing a uniform (C buffer) register.
@@ -519,7 +608,7 @@ private:
}
break;
}
case OpCode::Type::FloatPredicate: {
case OpCode::Type::FloatSetPredicate: {
std::string op_a = instr.fsetp.neg_a ? "-" : "";
op_a += GetRegister(instr.gpr8);
@@ -570,11 +659,73 @@ private:
}
break;
}
case OpCode::Type::FloatSet: {
std::string dest = GetRegister(instr.gpr0);
std::string op_a = instr.fset.neg_a ? "-" : "";
op_a += GetRegister(instr.gpr8);
if (instr.fset.abs_a) {
op_a = "abs(" + op_a + ')';
}
std::string op_b = instr.fset.neg_b ? "-" : "";
if (instr.is_b_imm) {
std::string imm = GetImmediate19(instr);
if (instr.fset.neg_imm)
op_b += "(-" + imm + ')';
else
op_b += imm;
} else {
if (instr.is_b_gpr) {
op_b += GetRegister(instr.gpr20);
} else {
op_b += GetUniform(instr.uniform);
}
}
if (instr.fset.abs_b) {
op_b = "abs(" + op_b + ")";
}
using Tegra::Shader::Pred;
ASSERT_MSG(instr.fset.pred39 == static_cast<u64>(Pred::UnusedIndex),
"Compound predicates are not implemented");
// The fset instruction sets a register to 1.0 if the condition is true, and to 0
// otherwise.
using Tegra::Shader::PredCondition;
switch (instr.fset.cond) {
case PredCondition::LessThan:
SetDest(0, dest, "((" + op_a + ") < (" + op_b + ")) ? 1.0 : 0", 1, 1);
break;
case PredCondition::Equal:
SetDest(0, dest, "((" + op_a + ") == (" + op_b + ")) ? 1.0 : 0", 1, 1);
break;
case PredCondition::GreaterThan:
SetDest(0, dest, "((" + op_a + ") > (" + op_b + ")) ? 1.0 : 0", 1, 1);
break;
default:
NGLOG_CRITICAL(HW_GPU, "Unhandled predicate condition: {} (a: {}, b: {})",
static_cast<unsigned>(instr.fset.cond.Value()), op_a, op_b);
UNREACHABLE();
}
break;
}
default: {
switch (opcode->GetId()) {
case OpCode::Id::EXIT: {
ASSERT_MSG(instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex),
"Predicated exits not implemented");
// Final color output is currently hardcoded to GPR0-3 for fragment shaders
if (stage == Maxwell3D::Regs::ShaderStage::Fragment) {
shader.AddLine("color.r = " + GetRegister(0) + ";");
shader.AddLine("color.g = " + GetRegister(1) + ";");
shader.AddLine("color.b = " + GetRegister(2) + ";");
shader.AddLine("color.a = " + GetRegister(3) + ";");
}
shader.AddLine("return true;");
offset = PROGRAM_END - 1;
break;
@@ -702,8 +853,13 @@ private:
/// Add declarations for registers
void GenerateDeclarations() {
for (const auto& reg : declr_register) {
declarations.AddLine("float " + reg + " = 0.0;");
for (const auto& reg : regs) {
if (reg.IsFloatUsed()) {
declarations.AddLine("float " + reg.GetFloatString() + " = 0.0;");
}
if (reg.IsIntegerUsed()) {
declarations.AddLine("int " + reg.GetIntegerString() + " = 0;");
}
}
declarations.AddNewLine();
@@ -750,9 +906,9 @@ private:
ShaderWriter shader;
ShaderWriter declarations;
std::vector<GLSLRegister> regs;
// Declarations
std::set<std::string> declr_register;
std::set<std::string> declr_predicates;
std::set<Attribute::Index> declr_input_attribute;
std::set<Attribute::Index> declr_output_attribute;

View File

@@ -302,8 +302,8 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x,
right = texcoords.left;
} else {
// Other transformations are unsupported
LOG_CRITICAL(Render_OpenGL, "Unsupported framebuffer_transform_flags=%d",
framebuffer_transform_flags);
NGLOG_CRITICAL(Render_OpenGL, "Unsupported framebuffer_transform_flags={}",
static_cast<u32>(framebuffer_transform_flags));
UNIMPLEMENTED();
}
}
@@ -428,9 +428,9 @@ bool RendererOpenGL::Init() {
const char* gpu_vendor{reinterpret_cast<char const*>(glGetString(GL_VENDOR))};
const char* gpu_model{reinterpret_cast<char const*>(glGetString(GL_RENDERER))};
LOG_INFO(Render_OpenGL, "GL_VERSION: %s", gl_version);
LOG_INFO(Render_OpenGL, "GL_VENDOR: %s", gpu_vendor);
LOG_INFO(Render_OpenGL, "GL_RENDERER: %s", gpu_model);
NGLOG_INFO(Render_OpenGL, "GL_VERSION: {}", gl_version);
NGLOG_INFO(Render_OpenGL, "GL_VENDOR: {}", gpu_vendor);
NGLOG_INFO(Render_OpenGL, "GL_RENDERER: {}", gpu_model);
Core::Telemetry().AddField(Telemetry::FieldType::UserSystem, "GPU_Vendor", gpu_vendor);
Core::Telemetry().AddField(Telemetry::FieldType::UserSystem, "GPU_Model", gpu_model);

View File

@@ -27,9 +27,8 @@ static u32 GetSwizzleOffset(u32 x, u32 y, u32 image_width, u32 bytes_per_pixel,
return address;
}
static void CopySwizzledData(u32 width, u32 height, u32 bytes_per_pixel, u32 out_bytes_per_pixel,
u8* swizzled_data, u8* unswizzled_data, bool unswizzle,
u32 block_height) {
void CopySwizzledData(u32 width, u32 height, u32 bytes_per_pixel, u32 out_bytes_per_pixel,
u8* swizzled_data, u8* unswizzled_data, bool unswizzle, u32 block_height) {
u8* data_ptrs[2];
for (unsigned y = 0; y < height; ++y) {
for (unsigned x = 0; x < width; ++x) {

View File

@@ -17,6 +17,10 @@ namespace Texture {
std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height,
u32 block_height = TICEntry::DefaultBlockHeight);
/// Copies texture data from a buffer and performs swizzling/unswizzling as necessary.
void CopySwizzledData(u32 width, u32 height, u32 bytes_per_pixel, u32 out_bytes_per_pixel,
u8* swizzled_data, u8* unswizzled_data, bool unswizzle, u32 block_height);
/**
* Decodes an unswizzled texture into a A8R8G8B8 texture.
*/

View File

@@ -24,9 +24,9 @@ bool Init(EmuWindow* emu_window) {
g_renderer = std::make_unique<RendererOpenGL>();
g_renderer->SetWindow(g_emu_window);
if (g_renderer->Init()) {
LOG_DEBUG(Render, "initialized OK");
NGLOG_DEBUG(Render, "initialized OK");
} else {
LOG_CRITICAL(Render, "initialization failed !");
NGLOG_CRITICAL(Render, "initialization failed !");
return false;
}
return true;
@@ -36,7 +36,7 @@ bool Init(EmuWindow* emu_window) {
void Shutdown() {
g_renderer.reset();
LOG_DEBUG(Render, "shutdown OK");
NGLOG_DEBUG(Render, "shutdown OK");
}
} // namespace VideoCore