Compare commits
54 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d9ee12b1a | ||
|
|
bad00085ca | ||
|
|
99ac33de20 | ||
|
|
d43c49264f | ||
|
|
6b365f7703 | ||
|
|
41dde2394b | ||
|
|
5a579f66a0 | ||
|
|
16198f979e | ||
|
|
843dd62c81 | ||
|
|
e6242ab5e6 | ||
|
|
acede1f1d3 | ||
|
|
8475496630 | ||
|
|
3c40496409 | ||
|
|
abc23416e8 | ||
|
|
4f120a9ec0 | ||
|
|
18f8012233 | ||
|
|
3e0ec3dbd7 | ||
|
|
3cfe77ae75 | ||
|
|
3062eb52f4 | ||
|
|
376f6397c6 | ||
|
|
6a3d59fdc1 | ||
|
|
bc43946140 | ||
|
|
7391741a20 | ||
|
|
f1f7f2cba9 | ||
|
|
4ac9b47dca | ||
|
|
c33755e2b9 | ||
|
|
87a92ef062 | ||
|
|
c9d7abe9c9 | ||
|
|
37fa9a15cd | ||
|
|
3dd3cdeafd | ||
|
|
623d772476 | ||
|
|
4f281b3829 | ||
|
|
08da0b7acc | ||
|
|
f81b915fd8 | ||
|
|
dd6c67c627 | ||
|
|
42d43ea741 | ||
|
|
d0825c9519 | ||
|
|
20d86d8a36 | ||
|
|
e9ad8e9185 | ||
|
|
1740aa5444 | ||
|
|
5ab597041f | ||
|
|
1dd4861d38 | ||
|
|
a6da2b93c1 | ||
|
|
378c881427 | ||
|
|
b1109931b9 | ||
|
|
c16cfbbc6c | ||
|
|
a994446b6e | ||
|
|
e2f2a49d2d | ||
|
|
3f78a61f09 | ||
|
|
5aafc83cc9 | ||
|
|
0369ee7248 | ||
|
|
27650499bc | ||
|
|
df669bc540 | ||
|
|
f3137d3bc1 |
@@ -23,7 +23,7 @@ matrix:
|
||||
- os: osx
|
||||
env: NAME="macos build"
|
||||
sudo: false
|
||||
osx_image: xcode9.2
|
||||
osx_image: xcode9.3
|
||||
install: "./.travis/macos/deps.sh"
|
||||
script: "./.travis/macos/build.sh"
|
||||
after_success: "./.travis/macos/upload.sh"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -30,14 +30,15 @@ __declspec(noinline, noreturn)
|
||||
#define ASSERT(_a_) \
|
||||
do \
|
||||
if (!(_a_)) { \
|
||||
assert_noinline_call([] { LOG_CRITICAL(Debug, "Assertion Failed!"); }); \
|
||||
assert_noinline_call([] { NGLOG_CRITICAL(Debug, "Assertion Failed!"); }); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define ASSERT_MSG(_a_, ...) \
|
||||
do \
|
||||
if (!(_a_)) { \
|
||||
assert_noinline_call([&] { LOG_CRITICAL(Debug, "Assertion Failed!\n" __VA_ARGS__); }); \
|
||||
assert_noinline_call( \
|
||||
[&] { NGLOG_CRITICAL(Debug, "Assertion Failed!\n" __VA_ARGS__); }); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
|
||||
@@ -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_);
|
||||
}
|
||||
}
|
||||
@@ -118,7 +118,7 @@ bool IsDirectory(const std::string& filename) {
|
||||
#endif
|
||||
|
||||
if (result < 0) {
|
||||
LOG_DEBUG(Common_Filesystem, "stat failed on %s: %s", filename.c_str(), GetLastErrorMsg());
|
||||
NGLOG_DEBUG(Common_Filesystem, "stat failed on {}: {}", filename, GetLastErrorMsg());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -128,31 +128,29 @@ bool IsDirectory(const std::string& filename) {
|
||||
// Deletes a given filename, return true on success
|
||||
// Doesn't supports deleting a directory
|
||||
bool Delete(const std::string& filename) {
|
||||
LOG_TRACE(Common_Filesystem, "file %s", filename.c_str());
|
||||
NGLOG_TRACE(Common_Filesystem, "file {}", filename);
|
||||
|
||||
// Return true because we care about the file no
|
||||
// being there, not the actual delete.
|
||||
if (!Exists(filename)) {
|
||||
LOG_DEBUG(Common_Filesystem, "%s does not exist", filename.c_str());
|
||||
NGLOG_DEBUG(Common_Filesystem, "{} does not exist", filename);
|
||||
return true;
|
||||
}
|
||||
|
||||
// We can't delete a directory
|
||||
if (IsDirectory(filename)) {
|
||||
LOG_ERROR(Common_Filesystem, "Failed: %s is a directory", filename.c_str());
|
||||
NGLOG_ERROR(Common_Filesystem, "Failed: {} is a directory", filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
if (!DeleteFileW(Common::UTF8ToUTF16W(filename).c_str())) {
|
||||
LOG_ERROR(Common_Filesystem, "DeleteFile failed on %s: %s", filename.c_str(),
|
||||
GetLastErrorMsg());
|
||||
NGLOG_ERROR(Common_Filesystem, "DeleteFile failed on {}: {}", filename, GetLastErrorMsg());
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
if (unlink(filename.c_str()) == -1) {
|
||||
LOG_ERROR(Common_Filesystem, "unlink failed on %s: %s", filename.c_str(),
|
||||
GetLastErrorMsg());
|
||||
NGLOG_ERROR(Common_Filesystem, "unlink failed on {}: {}", filename, GetLastErrorMsg());
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@@ -162,16 +160,16 @@ bool Delete(const std::string& filename) {
|
||||
|
||||
// Returns true if successful, or path already exists.
|
||||
bool CreateDir(const std::string& path) {
|
||||
LOG_TRACE(Common_Filesystem, "directory %s", path.c_str());
|
||||
NGLOG_TRACE(Common_Filesystem, "directory {}", path);
|
||||
#ifdef _WIN32
|
||||
if (::CreateDirectoryW(Common::UTF8ToUTF16W(path).c_str(), nullptr))
|
||||
return true;
|
||||
DWORD error = GetLastError();
|
||||
if (error == ERROR_ALREADY_EXISTS) {
|
||||
LOG_DEBUG(Common_Filesystem, "CreateDirectory failed on %s: already exists", path.c_str());
|
||||
NGLOG_DEBUG(Common_Filesystem, "CreateDirectory failed on {}: already exists", path);
|
||||
return true;
|
||||
}
|
||||
LOG_ERROR(Common_Filesystem, "CreateDirectory failed on %s: %i", path.c_str(), error);
|
||||
NGLOG_ERROR(Common_Filesystem, "CreateDirectory failed on {}: {}", path, error);
|
||||
return false;
|
||||
#else
|
||||
if (mkdir(path.c_str(), 0755) == 0)
|
||||
@@ -180,11 +178,11 @@ bool CreateDir(const std::string& path) {
|
||||
int err = errno;
|
||||
|
||||
if (err == EEXIST) {
|
||||
LOG_DEBUG(Common_Filesystem, "mkdir failed on %s: already exists", path.c_str());
|
||||
NGLOG_DEBUG(Common_Filesystem, "mkdir failed on {}: already exists", path);
|
||||
return true;
|
||||
}
|
||||
|
||||
LOG_ERROR(Common_Filesystem, "mkdir failed on %s: %s", path.c_str(), strerror(err));
|
||||
NGLOG_ERROR(Common_Filesystem, "mkdir failed on {}: {}", path, strerror(err));
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
@@ -192,10 +190,10 @@ bool CreateDir(const std::string& path) {
|
||||
// Creates the full path of fullPath returns true on success
|
||||
bool CreateFullPath(const std::string& fullPath) {
|
||||
int panicCounter = 100;
|
||||
LOG_TRACE(Common_Filesystem, "path %s", fullPath.c_str());
|
||||
NGLOG_TRACE(Common_Filesystem, "path {}", fullPath);
|
||||
|
||||
if (FileUtil::Exists(fullPath)) {
|
||||
LOG_DEBUG(Common_Filesystem, "path exists %s", fullPath.c_str());
|
||||
NGLOG_DEBUG(Common_Filesystem, "path exists {}", fullPath);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -211,14 +209,14 @@ bool CreateFullPath(const std::string& fullPath) {
|
||||
// Include the '/' so the first call is CreateDir("/") rather than CreateDir("")
|
||||
std::string const subPath(fullPath.substr(0, position + 1));
|
||||
if (!FileUtil::IsDirectory(subPath) && !FileUtil::CreateDir(subPath)) {
|
||||
LOG_ERROR(Common, "CreateFullPath: directory creation failed");
|
||||
NGLOG_ERROR(Common, "CreateFullPath: directory creation failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
// A safety check
|
||||
panicCounter--;
|
||||
if (panicCounter <= 0) {
|
||||
LOG_ERROR(Common, "CreateFullPath: directory structure is too deep");
|
||||
NGLOG_ERROR(Common, "CreateFullPath: directory structure is too deep");
|
||||
return false;
|
||||
}
|
||||
position++;
|
||||
@@ -227,11 +225,11 @@ bool CreateFullPath(const std::string& fullPath) {
|
||||
|
||||
// Deletes a directory filename, returns true on success
|
||||
bool DeleteDir(const std::string& filename) {
|
||||
LOG_TRACE(Common_Filesystem, "directory %s", filename.c_str());
|
||||
NGLOG_TRACE(Common_Filesystem, "directory {}", filename);
|
||||
|
||||
// check if a directory
|
||||
if (!FileUtil::IsDirectory(filename)) {
|
||||
LOG_ERROR(Common_Filesystem, "Not a directory %s", filename.c_str());
|
||||
NGLOG_ERROR(Common_Filesystem, "Not a directory {}", filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -242,14 +240,14 @@ bool DeleteDir(const std::string& filename) {
|
||||
if (rmdir(filename.c_str()) == 0)
|
||||
return true;
|
||||
#endif
|
||||
LOG_ERROR(Common_Filesystem, "failed %s: %s", filename.c_str(), GetLastErrorMsg());
|
||||
NGLOG_ERROR(Common_Filesystem, "failed {}: {}", filename, GetLastErrorMsg());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// renames file srcFilename to destFilename, returns true on success
|
||||
bool Rename(const std::string& srcFilename, const std::string& destFilename) {
|
||||
LOG_TRACE(Common_Filesystem, "%s --> %s", srcFilename.c_str(), destFilename.c_str());
|
||||
NGLOG_TRACE(Common_Filesystem, "{} --> {}", srcFilename, destFilename);
|
||||
#ifdef _WIN32
|
||||
if (_wrename(Common::UTF8ToUTF16W(srcFilename).c_str(),
|
||||
Common::UTF8ToUTF16W(destFilename).c_str()) == 0)
|
||||
@@ -258,21 +256,21 @@ bool Rename(const std::string& srcFilename, const std::string& destFilename) {
|
||||
if (rename(srcFilename.c_str(), destFilename.c_str()) == 0)
|
||||
return true;
|
||||
#endif
|
||||
LOG_ERROR(Common_Filesystem, "failed %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(),
|
||||
GetLastErrorMsg());
|
||||
NGLOG_ERROR(Common_Filesystem, "failed {} --> {}: {}", srcFilename, destFilename,
|
||||
GetLastErrorMsg());
|
||||
return false;
|
||||
}
|
||||
|
||||
// copies file srcFilename to destFilename, returns true on success
|
||||
bool Copy(const std::string& srcFilename, const std::string& destFilename) {
|
||||
LOG_TRACE(Common_Filesystem, "%s --> %s", srcFilename.c_str(), destFilename.c_str());
|
||||
NGLOG_TRACE(Common_Filesystem, "{} --> {}", srcFilename, destFilename);
|
||||
#ifdef _WIN32
|
||||
if (CopyFileW(Common::UTF8ToUTF16W(srcFilename).c_str(),
|
||||
Common::UTF8ToUTF16W(destFilename).c_str(), FALSE))
|
||||
return true;
|
||||
|
||||
LOG_ERROR(Common_Filesystem, "failed %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(),
|
||||
GetLastErrorMsg());
|
||||
NGLOG_ERROR(Common_Filesystem, "failed {} --> {}: {}", srcFilename, destFilename,
|
||||
GetLastErrorMsg());
|
||||
return false;
|
||||
#else
|
||||
|
||||
@@ -284,8 +282,8 @@ bool Copy(const std::string& srcFilename, const std::string& destFilename) {
|
||||
// Open input file
|
||||
FILE* input = fopen(srcFilename.c_str(), "rb");
|
||||
if (!input) {
|
||||
LOG_ERROR(Common_Filesystem, "opening input failed %s --> %s: %s", srcFilename.c_str(),
|
||||
destFilename.c_str(), GetLastErrorMsg());
|
||||
NGLOG_ERROR(Common_Filesystem, "opening input failed {} --> {}: {}", srcFilename,
|
||||
destFilename, GetLastErrorMsg());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -293,8 +291,8 @@ bool Copy(const std::string& srcFilename, const std::string& destFilename) {
|
||||
FILE* output = fopen(destFilename.c_str(), "wb");
|
||||
if (!output) {
|
||||
fclose(input);
|
||||
LOG_ERROR(Common_Filesystem, "opening output failed %s --> %s: %s", srcFilename.c_str(),
|
||||
destFilename.c_str(), GetLastErrorMsg());
|
||||
NGLOG_ERROR(Common_Filesystem, "opening output failed {} --> {}: {}", srcFilename,
|
||||
destFilename, GetLastErrorMsg());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -304,8 +302,8 @@ bool Copy(const std::string& srcFilename, const std::string& destFilename) {
|
||||
size_t rnum = fread(buffer, sizeof(char), BSIZE, input);
|
||||
if (rnum != BSIZE) {
|
||||
if (ferror(input) != 0) {
|
||||
LOG_ERROR(Common_Filesystem, "failed reading from source, %s --> %s: %s",
|
||||
srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg());
|
||||
NGLOG_ERROR(Common_Filesystem, "failed reading from source, {} --> {}: {}",
|
||||
srcFilename, destFilename, GetLastErrorMsg());
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
@@ -313,8 +311,8 @@ bool Copy(const std::string& srcFilename, const std::string& destFilename) {
|
||||
// write output
|
||||
size_t wnum = fwrite(buffer, sizeof(char), rnum, output);
|
||||
if (wnum != rnum) {
|
||||
LOG_ERROR(Common_Filesystem, "failed writing to output, %s --> %s: %s",
|
||||
srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg());
|
||||
NGLOG_ERROR(Common_Filesystem, "failed writing to output, {} --> {}: {}", srcFilename,
|
||||
destFilename, GetLastErrorMsg());
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
@@ -334,12 +332,12 @@ bail:
|
||||
// Returns the size of filename (64bit)
|
||||
u64 GetSize(const std::string& filename) {
|
||||
if (!Exists(filename)) {
|
||||
LOG_ERROR(Common_Filesystem, "failed %s: No such file", filename.c_str());
|
||||
NGLOG_ERROR(Common_Filesystem, "failed {}: No such file", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (IsDirectory(filename)) {
|
||||
LOG_ERROR(Common_Filesystem, "failed %s: is a directory", filename.c_str());
|
||||
NGLOG_ERROR(Common_Filesystem, "failed {}: is a directory", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -350,11 +348,11 @@ u64 GetSize(const std::string& filename) {
|
||||
if (stat(filename.c_str(), &buf) == 0)
|
||||
#endif
|
||||
{
|
||||
LOG_TRACE(Common_Filesystem, "%s: %lld", filename.c_str(), (long long)buf.st_size);
|
||||
NGLOG_TRACE(Common_Filesystem, "{}: {}", filename, buf.st_size);
|
||||
return buf.st_size;
|
||||
}
|
||||
|
||||
LOG_ERROR(Common_Filesystem, "Stat failed %s: %s", filename.c_str(), GetLastErrorMsg());
|
||||
NGLOG_ERROR(Common_Filesystem, "Stat failed {}: {}", filename, GetLastErrorMsg());
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -362,7 +360,7 @@ u64 GetSize(const std::string& filename) {
|
||||
u64 GetSize(const int fd) {
|
||||
struct stat buf;
|
||||
if (fstat(fd, &buf) != 0) {
|
||||
LOG_ERROR(Common_Filesystem, "GetSize: stat failed %i: %s", fd, GetLastErrorMsg());
|
||||
NGLOG_ERROR(Common_Filesystem, "GetSize: stat failed {}: {}", fd, GetLastErrorMsg());
|
||||
return 0;
|
||||
}
|
||||
return buf.st_size;
|
||||
@@ -373,12 +371,14 @@ u64 GetSize(FILE* f) {
|
||||
// can't use off_t here because it can be 32-bit
|
||||
u64 pos = ftello(f);
|
||||
if (fseeko(f, 0, SEEK_END) != 0) {
|
||||
LOG_ERROR(Common_Filesystem, "GetSize: seek failed %p: %s", f, GetLastErrorMsg());
|
||||
NGLOG_ERROR(Common_Filesystem, "GetSize: seek failed {}: {}", fmt::ptr(f),
|
||||
GetLastErrorMsg());
|
||||
return 0;
|
||||
}
|
||||
u64 size = ftello(f);
|
||||
if ((size != pos) && (fseeko(f, pos, SEEK_SET) != 0)) {
|
||||
LOG_ERROR(Common_Filesystem, "GetSize: seek failed %p: %s", f, GetLastErrorMsg());
|
||||
NGLOG_ERROR(Common_Filesystem, "GetSize: seek failed {}: {}", fmt::ptr(f),
|
||||
GetLastErrorMsg());
|
||||
return 0;
|
||||
}
|
||||
return size;
|
||||
@@ -386,10 +386,10 @@ u64 GetSize(FILE* f) {
|
||||
|
||||
// creates an empty file filename, returns true on success
|
||||
bool CreateEmptyFile(const std::string& filename) {
|
||||
LOG_TRACE(Common_Filesystem, "%s", filename.c_str());
|
||||
NGLOG_TRACE(Common_Filesystem, "{}", filename);
|
||||
|
||||
if (!FileUtil::IOFile(filename, "wb")) {
|
||||
LOG_ERROR(Common_Filesystem, "failed %s: %s", filename.c_str(), GetLastErrorMsg());
|
||||
NGLOG_ERROR(Common_Filesystem, "failed {}: {}", filename, GetLastErrorMsg());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -398,7 +398,7 @@ bool CreateEmptyFile(const std::string& filename) {
|
||||
|
||||
bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string& directory,
|
||||
DirectoryEntryCallable callback) {
|
||||
LOG_TRACE(Common_Filesystem, "directory %s", directory.c_str());
|
||||
NGLOG_TRACE(Common_Filesystem, "directory {}", directory);
|
||||
|
||||
// How many files + directories we found
|
||||
unsigned found_entries = 0;
|
||||
@@ -556,7 +556,7 @@ std::string GetCurrentDir() {
|
||||
char* dir;
|
||||
if (!(dir = getcwd(nullptr, 0))) {
|
||||
#endif
|
||||
LOG_ERROR(Common_Filesystem, "GetCurrentDirectory failed: %s", GetLastErrorMsg());
|
||||
NGLOG_ERROR(Common_Filesystem, "GetCurrentDirectory failed: {}", GetLastErrorMsg());
|
||||
return nullptr;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
@@ -653,12 +653,12 @@ static const std::string GetUserDirectory(const std::string& envvar) {
|
||||
else if (envvar == "XDG_CACHE_HOME")
|
||||
subdirectory = DIR_SEP ".cache";
|
||||
else
|
||||
ASSERT_MSG(false, "Unknown XDG variable %s.", envvar.c_str());
|
||||
ASSERT_MSG(false, "Unknown XDG variable {}.", envvar);
|
||||
user_dir = GetHomeDirectory() + subdirectory;
|
||||
}
|
||||
|
||||
ASSERT_MSG(!user_dir.empty(), "User directory %s musn’t be empty.", envvar.c_str());
|
||||
ASSERT_MSG(user_dir[0] == '/', "User directory %s must be absolute.", envvar.c_str());
|
||||
ASSERT_MSG(!user_dir.empty(), "User directory {} mustn’t be empty.", envvar);
|
||||
ASSERT_MSG(user_dir[0] == '/', "User directory {} must be absolute.", envvar);
|
||||
|
||||
return user_dir;
|
||||
}
|
||||
@@ -676,7 +676,7 @@ std::string GetSysDirectory() {
|
||||
#endif
|
||||
sysDir += DIR_SEP;
|
||||
|
||||
LOG_DEBUG(Common_Filesystem, "Setting to %s:", sysDir.c_str());
|
||||
NGLOG_DEBUG(Common_Filesystem, "Setting to {}:", sysDir);
|
||||
return sysDir;
|
||||
}
|
||||
|
||||
@@ -692,7 +692,7 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string& new
|
||||
if (!FileUtil::IsDirectory(paths[D_USER_IDX])) {
|
||||
paths[D_USER_IDX] = AppDataRoamingDirectory() + DIR_SEP EMU_DATA_DIR DIR_SEP;
|
||||
} else {
|
||||
LOG_INFO(Common_Filesystem, "Using the local user directory");
|
||||
NGLOG_INFO(Common_Filesystem, "Using the local user directory");
|
||||
}
|
||||
|
||||
paths[D_CONFIG_IDX] = paths[D_USER_IDX] + CONFIG_DIR DIR_SEP;
|
||||
@@ -719,7 +719,7 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string& new
|
||||
|
||||
if (!newPath.empty()) {
|
||||
if (!FileUtil::IsDirectory(newPath)) {
|
||||
LOG_ERROR(Common_Filesystem, "Invalid path specified %s", newPath.c_str());
|
||||
NGLOG_ERROR(Common_Filesystem, "Invalid path specified {}", newPath);
|
||||
return paths[DirIDX];
|
||||
} else {
|
||||
paths[DirIDX] = newPath;
|
||||
|
||||
@@ -170,12 +170,8 @@ public:
|
||||
|
||||
template <typename T>
|
||||
size_t ReadArray(T* data, size_t length) {
|
||||
static_assert(std::is_standard_layout<T>(),
|
||||
"Given array does not consist of standard layout objects");
|
||||
#if (__GNUC__ >= 5) || defined(__clang__) || defined(_MSC_VER)
|
||||
static_assert(std::is_trivially_copyable<T>(),
|
||||
"Given array does not consist of trivially copyable objects");
|
||||
#endif
|
||||
|
||||
if (!IsOpen()) {
|
||||
m_good = false;
|
||||
@@ -191,12 +187,8 @@ public:
|
||||
|
||||
template <typename T>
|
||||
size_t WriteArray(const T* data, size_t length) {
|
||||
static_assert(std::is_standard_layout<T>(),
|
||||
"Given array does not consist of standard layout objects");
|
||||
#if (__GNUC__ >= 5) || defined(__clang__) || defined(_MSC_VER)
|
||||
static_assert(std::is_trivially_copyable<T>(),
|
||||
"Given array does not consist of trivially copyable objects");
|
||||
#endif
|
||||
|
||||
if (!IsOpen()) {
|
||||
m_good = false;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
@@ -2,11 +2,8 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
#include <utility>
|
||||
#include "common/assert.h"
|
||||
#include "common/common_funcs.h" // snprintf compatibility define
|
||||
#include "common/logging/backend.h"
|
||||
#include "common/logging/filter.h"
|
||||
#include "common/logging/log.h"
|
||||
@@ -48,6 +45,7 @@ namespace Log {
|
||||
SUB(Service, NS) \
|
||||
SUB(Service, NVDRV) \
|
||||
SUB(Service, PCTL) \
|
||||
SUB(Service, PREPO) \
|
||||
SUB(Service, SET) \
|
||||
SUB(Service, SM) \
|
||||
SUB(Service, SPL) \
|
||||
@@ -131,21 +129,6 @@ void SetFilter(Filter* new_filter) {
|
||||
filter = new_filter;
|
||||
}
|
||||
|
||||
void LogMessage(Class log_class, Level log_level, const char* filename, unsigned int line_num,
|
||||
const char* function, const char* format, ...) {
|
||||
if (filter && !filter->CheckMessage(log_class, log_level))
|
||||
return;
|
||||
std::array<char, 4 * 1024> formatting_buffer;
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vsnprintf(formatting_buffer.data(), formatting_buffer.size(), format, args);
|
||||
va_end(args);
|
||||
Entry entry = CreateEntry(log_class, log_level, filename, line_num, function,
|
||||
std::string(formatting_buffer.data()));
|
||||
|
||||
PrintColoredMessage(entry);
|
||||
}
|
||||
|
||||
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
|
||||
unsigned int line_num, const char* function, const char* format,
|
||||
const fmt::format_args& args) {
|
||||
|
||||
@@ -65,6 +65,7 @@ enum class Class : ClassType {
|
||||
Service_NS, ///< The NS services
|
||||
Service_NVDRV, ///< The NVDRV (Nvidia driver) service
|
||||
Service_PCTL, ///< The PCTL (Parental control) service
|
||||
Service_PREPO, ///< The PREPO (Play report) service
|
||||
Service_SET, ///< The SET (Settings) service
|
||||
Service_SM, ///< The SM (Service manager) service
|
||||
Service_SPL, ///< The SPL service
|
||||
@@ -91,19 +92,6 @@ enum class Class : ClassType {
|
||||
Count ///< Total number of logging classes
|
||||
};
|
||||
|
||||
/// Logs a message to the global logger.
|
||||
void LogMessage(Class log_class, Level log_level, const char* filename, unsigned int line_num,
|
||||
const char* function,
|
||||
#ifdef _MSC_VER
|
||||
_Printf_format_string_
|
||||
#endif
|
||||
const char* format,
|
||||
...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__((format(printf, 6, 7)))
|
||||
#endif
|
||||
;
|
||||
|
||||
/// Logs a message to the global logger, using fmt
|
||||
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
|
||||
unsigned int line_num, const char* function, const char* format,
|
||||
@@ -118,28 +106,6 @@ void FmtLogMessage(Class log_class, Level log_level, const char* filename, unsig
|
||||
|
||||
} // namespace Log
|
||||
|
||||
#define LOG_GENERIC(log_class, log_level, ...) \
|
||||
::Log::LogMessage(log_class, log_level, __FILE__, __LINE__, __func__, __VA_ARGS__)
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define LOG_TRACE(log_class, ...) \
|
||||
LOG_GENERIC(::Log::Class::log_class, ::Log::Level::Trace, __VA_ARGS__)
|
||||
#else
|
||||
#define LOG_TRACE(log_class, ...) (void(0))
|
||||
#endif
|
||||
|
||||
#define LOG_DEBUG(log_class, ...) \
|
||||
LOG_GENERIC(::Log::Class::log_class, ::Log::Level::Debug, __VA_ARGS__)
|
||||
#define LOG_INFO(log_class, ...) \
|
||||
LOG_GENERIC(::Log::Class::log_class, ::Log::Level::Info, __VA_ARGS__)
|
||||
#define LOG_WARNING(log_class, ...) \
|
||||
LOG_GENERIC(::Log::Class::log_class, ::Log::Level::Warning, __VA_ARGS__)
|
||||
#define LOG_ERROR(log_class, ...) \
|
||||
LOG_GENERIC(::Log::Class::log_class, ::Log::Level::Error, __VA_ARGS__)
|
||||
#define LOG_CRITICAL(log_class, ...) \
|
||||
LOG_GENERIC(::Log::Class::log_class, ::Log::Level::Critical, __VA_ARGS__)
|
||||
|
||||
// Define the fmt lib macros
|
||||
#ifdef _DEBUG
|
||||
#define NGLOG_TRACE(log_class, ...) \
|
||||
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Trace, __FILE__, __LINE__, \
|
||||
|
||||
@@ -55,7 +55,7 @@ void* AllocateExecutableMemory(size_t size, bool low) {
|
||||
if (ptr == MAP_FAILED) {
|
||||
ptr = nullptr;
|
||||
#endif
|
||||
LOG_ERROR(Common_Memory, "Failed to allocate executable memory");
|
||||
NGLOG_ERROR(Common_Memory, "Failed to allocate executable memory");
|
||||
}
|
||||
#if !defined(_WIN32) && defined(ARCHITECTURE_X64) && !defined(MAP_32BIT)
|
||||
else {
|
||||
@@ -68,7 +68,7 @@ void* AllocateExecutableMemory(size_t size, bool low) {
|
||||
|
||||
#if EMU_ARCH_BITS == 64
|
||||
if ((u64)ptr >= 0x80000000 && low == true)
|
||||
LOG_ERROR(Common_Memory, "Executable memory ended up above 2GB!");
|
||||
NGLOG_ERROR(Common_Memory, "Executable memory ended up above 2GB!");
|
||||
#endif
|
||||
|
||||
return ptr;
|
||||
@@ -85,7 +85,7 @@ void* AllocateMemoryPages(size_t size) {
|
||||
#endif
|
||||
|
||||
if (ptr == nullptr)
|
||||
LOG_ERROR(Common_Memory, "Failed to allocate raw memory");
|
||||
NGLOG_ERROR(Common_Memory, "Failed to allocate raw memory");
|
||||
|
||||
return ptr;
|
||||
}
|
||||
@@ -99,12 +99,12 @@ void* AllocateAlignedMemory(size_t size, size_t alignment) {
|
||||
ptr = memalign(alignment, size);
|
||||
#else
|
||||
if (posix_memalign(&ptr, alignment, size) != 0)
|
||||
LOG_ERROR(Common_Memory, "Failed to allocate aligned memory");
|
||||
NGLOG_ERROR(Common_Memory, "Failed to allocate aligned memory");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (ptr == nullptr)
|
||||
LOG_ERROR(Common_Memory, "Failed to allocate aligned memory");
|
||||
NGLOG_ERROR(Common_Memory, "Failed to allocate aligned memory");
|
||||
|
||||
return ptr;
|
||||
}
|
||||
@@ -113,7 +113,7 @@ void FreeMemoryPages(void* ptr, size_t size) {
|
||||
if (ptr) {
|
||||
#ifdef _WIN32
|
||||
if (!VirtualFree(ptr, 0, MEM_RELEASE))
|
||||
LOG_ERROR(Common_Memory, "FreeMemoryPages failed!\n%s", GetLastErrorMsg());
|
||||
NGLOG_ERROR(Common_Memory, "FreeMemoryPages failed!\n{}", GetLastErrorMsg());
|
||||
#else
|
||||
munmap(ptr, size);
|
||||
#endif
|
||||
@@ -134,7 +134,7 @@ void WriteProtectMemory(void* ptr, size_t size, bool allowExecute) {
|
||||
#ifdef _WIN32
|
||||
DWORD oldValue;
|
||||
if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READ : PAGE_READONLY, &oldValue))
|
||||
LOG_ERROR(Common_Memory, "WriteProtectMemory failed!\n%s", GetLastErrorMsg());
|
||||
NGLOG_ERROR(Common_Memory, "WriteProtectMemory failed!\n{}", GetLastErrorMsg());
|
||||
#else
|
||||
mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_EXEC) : PROT_READ);
|
||||
#endif
|
||||
@@ -145,7 +145,7 @@ void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute) {
|
||||
DWORD oldValue;
|
||||
if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE,
|
||||
&oldValue))
|
||||
LOG_ERROR(Common_Memory, "UnWriteProtectMemory failed!\n%s", GetLastErrorMsg());
|
||||
NGLOG_ERROR(Common_Memory, "UnWriteProtectMemory failed!\n{}", GetLastErrorMsg());
|
||||
#else
|
||||
mprotect(ptr, size,
|
||||
allowExecute ? (PROT_READ | PROT_WRITE | PROT_EXEC) : PROT_WRITE | PROT_READ);
|
||||
|
||||
@@ -25,7 +25,7 @@ ParamPackage::ParamPackage(const std::string& serialized) {
|
||||
std::vector<std::string> key_value;
|
||||
Common::SplitString(pair, KEY_VALUE_SEPARATOR, key_value);
|
||||
if (key_value.size() != 2) {
|
||||
LOG_ERROR(Common, "invalid key pair %s", pair.c_str());
|
||||
NGLOG_ERROR(Common, "invalid key pair {}", pair);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ std::string ParamPackage::Serialize() const {
|
||||
std::string ParamPackage::Get(const std::string& key, const std::string& default_value) const {
|
||||
auto pair = data.find(key);
|
||||
if (pair == data.end()) {
|
||||
LOG_DEBUG(Common, "key %s not found", key.c_str());
|
||||
NGLOG_DEBUG(Common, "key '{}' not found", key);
|
||||
return default_value;
|
||||
}
|
||||
|
||||
@@ -74,14 +74,14 @@ std::string ParamPackage::Get(const std::string& key, const std::string& default
|
||||
int ParamPackage::Get(const std::string& key, int default_value) const {
|
||||
auto pair = data.find(key);
|
||||
if (pair == data.end()) {
|
||||
LOG_DEBUG(Common, "key %s not found", key.c_str());
|
||||
NGLOG_DEBUG(Common, "key '{}' not found", key);
|
||||
return default_value;
|
||||
}
|
||||
|
||||
try {
|
||||
return std::stoi(pair->second);
|
||||
} catch (const std::logic_error&) {
|
||||
LOG_ERROR(Common, "failed to convert %s to int", pair->second.c_str());
|
||||
NGLOG_ERROR(Common, "failed to convert {} to int", pair->second);
|
||||
return default_value;
|
||||
}
|
||||
}
|
||||
@@ -89,14 +89,14 @@ int ParamPackage::Get(const std::string& key, int default_value) const {
|
||||
float ParamPackage::Get(const std::string& key, float default_value) const {
|
||||
auto pair = data.find(key);
|
||||
if (pair == data.end()) {
|
||||
LOG_DEBUG(Common, "key %s not found", key.c_str());
|
||||
NGLOG_DEBUG(Common, "key {} not found", key);
|
||||
return default_value;
|
||||
}
|
||||
|
||||
try {
|
||||
return std::stof(pair->second);
|
||||
} catch (const std::logic_error&) {
|
||||
LOG_ERROR(Common, "failed to convert %s to float", pair->second.c_str());
|
||||
NGLOG_ERROR(Common, "failed to convert {} to float", pair->second);
|
||||
return default_value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ std::string StringFromFormat(const char* format, ...) {
|
||||
#else
|
||||
va_start(args, format);
|
||||
if (vasprintf(&buf, format, args) < 0)
|
||||
LOG_ERROR(Common, "Unable to allocate memory for string");
|
||||
NGLOG_ERROR(Common, "Unable to allocate memory for string");
|
||||
va_end(args);
|
||||
|
||||
std::string temp = buf;
|
||||
@@ -347,7 +347,7 @@ static std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>&
|
||||
|
||||
iconv_t const conv_desc = iconv_open("UTF-8", fromcode);
|
||||
if ((iconv_t)(-1) == conv_desc) {
|
||||
LOG_ERROR(Common, "Iconv initialization failure [%s]: %s", fromcode, strerror(errno));
|
||||
NGLOG_ERROR(Common, "Iconv initialization failure [{}]: {}", fromcode, strerror(errno));
|
||||
iconv_close(conv_desc);
|
||||
return {};
|
||||
}
|
||||
@@ -376,7 +376,7 @@ static std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>&
|
||||
++src_buffer;
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR(Common, "iconv failure [%s]: %s", fromcode, strerror(errno));
|
||||
NGLOG_ERROR(Common, "iconv failure [{}]: {}", fromcode, strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -395,7 +395,7 @@ std::u16string UTF8ToUTF16(const std::string& input) {
|
||||
|
||||
iconv_t const conv_desc = iconv_open("UTF-16LE", "UTF-8");
|
||||
if ((iconv_t)(-1) == conv_desc) {
|
||||
LOG_ERROR(Common, "Iconv initialization failure [UTF-8]: %s", strerror(errno));
|
||||
NGLOG_ERROR(Common, "Iconv initialization failure [UTF-8]: {}", strerror(errno));
|
||||
iconv_close(conv_desc);
|
||||
return {};
|
||||
}
|
||||
@@ -424,7 +424,7 @@ std::u16string UTF8ToUTF16(const std::string& input) {
|
||||
++src_buffer;
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR(Common, "iconv failure [UTF-8]: %s", strerror(errno));
|
||||
NGLOG_ERROR(Common, "iconv failure [UTF-8]: {}", strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,6 +185,8 @@ add_library(core STATIC
|
||||
hle/service/pctl/module.h
|
||||
hle/service/pctl/pctl.cpp
|
||||
hle/service/pctl/pctl.h
|
||||
hle/service/prepo/prepo.cpp
|
||||
hle/service/prepo/prepo.h
|
||||
hle/service/service.cpp
|
||||
hle/service/service.h
|
||||
hle/service/set/set.cpp
|
||||
|
||||
@@ -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);
|
||||
@@ -76,7 +76,7 @@ public:
|
||||
case Dynarmic::A64::Exception::Yield:
|
||||
return;
|
||||
default:
|
||||
ASSERT_MSG(false, "ExceptionRaised(exception = %zu, pc = %" PRIx64 ")",
|
||||
ASSERT_MSG(false, "ExceptionRaised(exception = {}, pc = {:X})",
|
||||
static_cast<size_t>(exception), pc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ LoadDll LoadDll::g_load_dll;
|
||||
#define CHECKED(expr) \
|
||||
do { \
|
||||
if (auto _cerr = (expr)) { \
|
||||
ASSERT_MSG(false, "Call " #expr " failed with error: %u (%s)\n", _cerr, \
|
||||
ASSERT_MSG(false, "Call " #expr " failed with error: {} ({})\n", _cerr, \
|
||||
uc_strerror(_cerr)); \
|
||||
} \
|
||||
} while (0)
|
||||
@@ -53,7 +53,7 @@ static bool UnmappedMemoryHook(uc_engine* uc, uc_mem_type type, u64 addr, int si
|
||||
void* user_data) {
|
||||
ARM_Interface::ThreadContext ctx{};
|
||||
Core::CPU().SaveContext(ctx);
|
||||
ASSERT_MSG(false, "Attempted to read from unmapped memory: 0x%lx, pc=0x%lx, lr=0x%lx", addr,
|
||||
ASSERT_MSG(false, "Attempted to read from unmapped memory: {:#X}, pc={:#X}, lr={:#X}", addr,
|
||||
ctx.pc, ctx.cpu_registers[30]);
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -74,7 +74,7 @@ EventType* RegisterEvent(const std::string& name, TimedCallback callback) {
|
||||
// check for existing type with same name.
|
||||
// we want event type names to remain unique so that we can use them for serialization.
|
||||
ASSERT_MSG(event_types.find(name) == event_types.end(),
|
||||
"CoreTiming Event \"%s\" is already registered. Events should only be registered "
|
||||
"CoreTiming Event \"{}\" is already registered. Events should only be registered "
|
||||
"during Init to avoid breaking save states.",
|
||||
name.c_str());
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>();
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -10,12 +10,12 @@ namespace Kernel {
|
||||
ObjectAddressTable g_object_address_table;
|
||||
|
||||
void ObjectAddressTable::Insert(VAddr addr, SharedPtr<Object> obj) {
|
||||
ASSERT_MSG(objects.find(addr) == objects.end(), "Object already exists with addr=0x%lx", addr);
|
||||
ASSERT_MSG(objects.find(addr) == objects.end(), "Object already exists with addr={:#X}", addr);
|
||||
objects[addr] = obj;
|
||||
}
|
||||
|
||||
void ObjectAddressTable::Close(VAddr addr) {
|
||||
ASSERT_MSG(objects.find(addr) != objects.end(), "Object does not exist with addr=0x%lx", addr);
|
||||
ASSERT_MSG(objects.find(addr) != objects.end(), "Object does not exist with addr={:#X}", addr);
|
||||
objects.erase(addr);
|
||||
}
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) {
|
||||
HandleSpecialMapping(vm_manager, mapping);
|
||||
}
|
||||
|
||||
vm_manager.LogLayout(Log::Level::Debug);
|
||||
vm_manager.LogLayout();
|
||||
status = ProcessStatus::Running;
|
||||
|
||||
Kernel::SetupMainThread(entry_point, main_thread_priority, this);
|
||||
|
||||
@@ -539,7 +539,7 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
|
||||
processor_id);
|
||||
break;
|
||||
default:
|
||||
ASSERT_MSG(false, "Unsupported thread processor ID: %d", processor_id);
|
||||
ASSERT_MSG(false, "Unsupported thread processor ID: {}", processor_id);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -175,11 +175,11 @@ void Thread::ResumeFromWait() {
|
||||
return;
|
||||
|
||||
case THREADSTATUS_RUNNING:
|
||||
DEBUG_ASSERT_MSG(false, "Thread with object id %u has already resumed.", GetObjectId());
|
||||
DEBUG_ASSERT_MSG(false, "Thread with object id {} has already resumed.", GetObjectId());
|
||||
return;
|
||||
case THREADSTATUS_DEAD:
|
||||
// This should never happen, as threads must complete before being stopped.
|
||||
DEBUG_ASSERT_MSG(false, "Thread with object id %u cannot be resumed because it's DEAD.",
|
||||
DEBUG_ASSERT_MSG(false, "Thread with object id {} cannot be resumed because it's DEAD.",
|
||||
GetObjectId());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cinttypes>
|
||||
#include <iterator>
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
@@ -225,11 +224,10 @@ void VMManager::RefreshMemoryBlockMappings(const std::vector<u8>* block) {
|
||||
}
|
||||
}
|
||||
|
||||
void VMManager::LogLayout(Log::Level log_level) const {
|
||||
void VMManager::LogLayout() const {
|
||||
for (const auto& p : vma_map) {
|
||||
const VirtualMemoryArea& vma = p.second;
|
||||
LOG_GENERIC(Log::Class::Kernel, log_level,
|
||||
"%016" PRIx64 " - %016" PRIx64 " size: %16" PRIx64 " %c%c%c %s", vma.base,
|
||||
NGLOG_DEBUG(Kernel, "{:016X} - {:016X} size: {:016X} {}{}{} {}", vma.base,
|
||||
vma.base + vma.size, vma.size,
|
||||
(u8)vma.permissions & (u8)VMAPermission::Read ? 'R' : '-',
|
||||
(u8)vma.permissions & (u8)VMAPermission::Write ? 'W' : '-',
|
||||
@@ -245,8 +243,8 @@ VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle& iter) {
|
||||
}
|
||||
|
||||
ResultVal<VMManager::VMAIter> VMManager::CarveVMA(VAddr base, u64 size) {
|
||||
ASSERT_MSG((size & Memory::PAGE_MASK) == 0, "non-page aligned size: 0x%16" PRIx64, size);
|
||||
ASSERT_MSG((base & Memory::PAGE_MASK) == 0, "non-page aligned base: 0x%016" PRIx64, base);
|
||||
ASSERT_MSG((size & Memory::PAGE_MASK) == 0, "non-page aligned size: {:#018X}", size);
|
||||
ASSERT_MSG((base & Memory::PAGE_MASK) == 0, "non-page aligned base: {:#018X}", base);
|
||||
|
||||
VMAIter vma_handle = StripIterConstness(FindVMA(base));
|
||||
if (vma_handle == vma_map.end()) {
|
||||
@@ -281,8 +279,8 @@ ResultVal<VMManager::VMAIter> VMManager::CarveVMA(VAddr base, u64 size) {
|
||||
}
|
||||
|
||||
ResultVal<VMManager::VMAIter> VMManager::CarveVMARange(VAddr target, u64 size) {
|
||||
ASSERT_MSG((size & Memory::PAGE_MASK) == 0, "non-page aligned size: 0x%16" PRIx64, size);
|
||||
ASSERT_MSG((target & Memory::PAGE_MASK) == 0, "non-page aligned base: 0x%016" PRIx64, target);
|
||||
ASSERT_MSG((size & Memory::PAGE_MASK) == 0, "non-page aligned size: {:#018X}", size);
|
||||
ASSERT_MSG((target & Memory::PAGE_MASK) == 0, "non-page aligned base: {:#018X}", target);
|
||||
|
||||
VAddr target_end = target + size;
|
||||
ASSERT(target_end >= target);
|
||||
|
||||
@@ -187,7 +187,7 @@ public:
|
||||
void RefreshMemoryBlockMappings(const std::vector<u8>* block);
|
||||
|
||||
/// Dumps the address space layout to the log, for debugging
|
||||
void LogLayout(Log::Level log_level) const;
|
||||
void LogLayout() const;
|
||||
|
||||
/// Gets the total memory usage, used by svcGetInfo
|
||||
u64 GetTotalMemoryUsage();
|
||||
|
||||
@@ -162,12 +162,13 @@ public:
|
||||
{0x3, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceName"},
|
||||
{0x4, &IAudioDevice::QueryAudioDeviceSystemEvent, "QueryAudioDeviceSystemEvent"},
|
||||
{0x5, &IAudioDevice::GetActiveChannelCount, "GetActiveChannelCount"},
|
||||
{0x6, nullptr, "ListAudioDeviceNameAuto"},
|
||||
{0x7, nullptr, "SetAudioDeviceOutputVolumeAuto"},
|
||||
{0x6, &IAudioDevice::ListAudioDeviceName,
|
||||
"ListAudioDeviceNameAuto"}, // TODO(ogniK): Confirm if autos are identical to non auto
|
||||
{0x7, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolumeAuto"},
|
||||
{0x8, nullptr, "GetAudioDeviceOutputVolumeAuto"},
|
||||
{0x10, nullptr, "GetActiveAudioDeviceNameAuto"},
|
||||
{0x11, nullptr, "QueryAudioDeviceInputEvent"},
|
||||
{0x12, nullptr, "QueryAudioDeviceOutputEvent"}};
|
||||
{0xa, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceNameAuto"},
|
||||
{0xb, nullptr, "QueryAudioDeviceInputEvent"},
|
||||
{0xc, nullptr, "QueryAudioDeviceOutputEvent"}};
|
||||
RegisterHandlers(functions);
|
||||
|
||||
buffer_event =
|
||||
@@ -257,7 +258,7 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u64>(0x400);
|
||||
rb.Push<u64>(0x4000);
|
||||
|
||||
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
|
||||
}
|
||||
|
||||
@@ -12,10 +12,52 @@ namespace Service::NFP {
|
||||
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
|
||||
: ServiceFramework(name), module(std::move(module)) {}
|
||||
|
||||
void Module::Interface::Unknown(Kernel::HLERequestContext& ctx) {
|
||||
NGLOG_WARNING(Service_NFP, "(STUBBED) called");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
class IUser final : public ServiceFramework<IUser> {
|
||||
public:
|
||||
IUser() : ServiceFramework("IUser") {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &IUser::Initialize, "Initialize"},
|
||||
{1, nullptr, "Unknown1"},
|
||||
{2, nullptr, "Unknown2"},
|
||||
{3, nullptr, "Unknown3"},
|
||||
{4, nullptr, "Unknown4"},
|
||||
{5, nullptr, "Unknown5"},
|
||||
{6, nullptr, "Unknown6"},
|
||||
{7, nullptr, "Unknown7"},
|
||||
{8, nullptr, "Unknown8"},
|
||||
{9, nullptr, "Unknown9"},
|
||||
{10, nullptr, "Unknown10"},
|
||||
{11, nullptr, "Unknown11"},
|
||||
{12, nullptr, "Unknown12"},
|
||||
{13, nullptr, "Unknown13"},
|
||||
{14, nullptr, "Unknown14"},
|
||||
{15, nullptr, "Unknown15"},
|
||||
{16, nullptr, "Unknown16"},
|
||||
{17, nullptr, "Unknown17"},
|
||||
{18, nullptr, "Unknown18"},
|
||||
{19, nullptr, "Unknown19"},
|
||||
{20, nullptr, "Unknown20"},
|
||||
{21, nullptr, "Unknown21"},
|
||||
{22, nullptr, "Unknown22"},
|
||||
{23, nullptr, "Unknown23"},
|
||||
{24, nullptr, "Unknown24"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
private:
|
||||
void Initialize(Kernel::HLERequestContext& ctx) {
|
||||
NGLOG_WARNING(Service_NFP, "(STUBBED) called");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
};
|
||||
|
||||
void Module::Interface::CreateUserInterface(Kernel::HLERequestContext& ctx) {
|
||||
NGLOG_DEBUG(Service_NFP, "called");
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<IUser>();
|
||||
}
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager) {
|
||||
|
||||
@@ -14,7 +14,7 @@ public:
|
||||
public:
|
||||
Interface(std::shared_ptr<Module> module, const char* name);
|
||||
|
||||
void Unknown(Kernel::HLERequestContext& ctx);
|
||||
void CreateUserInterface(Kernel::HLERequestContext& ctx);
|
||||
|
||||
protected:
|
||||
std::shared_ptr<Module> module;
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Service::NFP {
|
||||
NFP_User::NFP_User(std::shared_ptr<Module> module)
|
||||
: Module::Interface(std::move(module), "nfp:user") {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &NFP_User::Unknown, "Unknown"},
|
||||
{0, &NFP_User::CreateUserInterface, "CreateUserInterface"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
@@ -79,6 +79,7 @@ u32 nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<u8>&
|
||||
std::memcpy(¶ms, input.data(), input.size());
|
||||
NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, mask={:#X}, mask_buf_addr={:#X}",
|
||||
params.mask_buf_size, params.mask_buf_addr);
|
||||
params.unk = 0xcafe; // TODO(ogniK): Needs to be non 0, what does this actually do?
|
||||
std::memcpy(output.data(), ¶ms, sizeof(params));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -39,8 +39,8 @@ Module::Module() {
|
||||
}
|
||||
|
||||
u32 Module::Open(std::string device_name) {
|
||||
ASSERT_MSG(devices.find(device_name) != devices.end(), "Trying to open unknown device %s",
|
||||
device_name.c_str());
|
||||
ASSERT_MSG(devices.find(device_name) != devices.end(), "Trying to open unknown device {}",
|
||||
device_name);
|
||||
|
||||
auto device = devices[device_name];
|
||||
u32 fd = next_fd++;
|
||||
|
||||
43
src/core/hle/service/prepo/prepo.cpp
Normal file
43
src/core/hle/service/prepo/prepo.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#include <cinttypes>
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/event.h"
|
||||
#include "core/hle/service/prepo/prepo.h"
|
||||
|
||||
namespace Service::PlayReport {
|
||||
PlayReport::PlayReport(const char* name) : ServiceFramework(name) {
|
||||
static const FunctionInfo functions[] = {
|
||||
{10100, nullptr, "SaveReport"},
|
||||
{10101, &PlayReport::SaveReportWithUser, "SaveReportWithUser"},
|
||||
{10200, nullptr, "RequestImmediateTransmission"},
|
||||
{10300, nullptr, "GetTransmissionStatus"},
|
||||
{20100, nullptr, "SaveSystemReport"},
|
||||
{20200, nullptr, "SetOperationMode"},
|
||||
{20101, nullptr, "SaveSystemReportWithUser"},
|
||||
{30100, nullptr, "ClearStorage"},
|
||||
{40100, nullptr, "IsUserAgreementCheckEnabled"},
|
||||
{40101, nullptr, "SetUserAgreementCheckEnabled"},
|
||||
{90100, nullptr, "GetStorageUsage"},
|
||||
{90200, nullptr, "GetStatistics"},
|
||||
{90201, nullptr, "GetThroughputHistory"},
|
||||
{90300, nullptr, "GetLastUploadError"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
};
|
||||
|
||||
void PlayReport::SaveReportWithUser(Kernel::HLERequestContext& ctx) {
|
||||
// TODO(ogniK): Do we want to add play report?
|
||||
NGLOG_WARNING(Service_PREPO, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
};
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager) {
|
||||
std::make_shared<PlayReport>("prepo:a")->InstallAsService(service_manager);
|
||||
std::make_shared<PlayReport>("prepo:m")->InstallAsService(service_manager);
|
||||
std::make_shared<PlayReport>("prepo:s")->InstallAsService(service_manager);
|
||||
std::make_shared<PlayReport>("prepo:u")->InstallAsService(service_manager);
|
||||
}
|
||||
|
||||
} // namespace Service::PlayReport
|
||||
23
src/core/hle/service/prepo/prepo.h
Normal file
23
src/core/hle/service/prepo/prepo.h
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include "core/hle/kernel/event.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::PlayReport {
|
||||
|
||||
class PlayReport final : public ServiceFramework<PlayReport> {
|
||||
public:
|
||||
explicit PlayReport(const char* name);
|
||||
~PlayReport() = default;
|
||||
|
||||
private:
|
||||
void SaveReportWithUser(Kernel::HLERequestContext& ctx);
|
||||
};
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager);
|
||||
|
||||
} // namespace Service::PlayReport
|
||||
@@ -29,7 +29,8 @@
|
||||
#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/module.h"
|
||||
#include "core/hle/service/pctl/pctl.h"
|
||||
#include "core/hle/service/prepo/prepo.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/set/settings.h"
|
||||
#include "core/hle/service/sm/controller.h"
|
||||
@@ -153,7 +154,7 @@ ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& co
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("command_type=%d", static_cast<int>(context.GetCommandType()));
|
||||
UNIMPLEMENTED_MSG("command_type={}", static_cast<int>(context.GetCommandType()));
|
||||
}
|
||||
|
||||
context.WriteToOutgoingCommandBuffer(*Kernel::GetCurrentThread());
|
||||
@@ -192,6 +193,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm) {
|
||||
NS::InstallInterfaces(*sm);
|
||||
Nvidia::InstallInterfaces(*sm);
|
||||
PCTL::InstallInterfaces(*sm);
|
||||
PlayReport::InstallInterfaces(*sm);
|
||||
Sockets::InstallInterfaces(*sm);
|
||||
SPL::InstallInterfaces(*sm);
|
||||
SSL::InstallInterfaces(*sm);
|
||||
|
||||
@@ -96,12 +96,22 @@ SSL::SSL() : ServiceFramework("ssl") {
|
||||
{2, nullptr, "GetCertificates"},
|
||||
{3, nullptr, "GetCertificateBufSize"},
|
||||
{4, nullptr, "DebugIoctl"},
|
||||
{5, nullptr, "SetInterfaceVersion"},
|
||||
{5, &SSL::SetInterfaceVersion, "SetInterfaceVersion"},
|
||||
{6, nullptr, "FlushSessionCache"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
void SSL::SetInterfaceVersion(Kernel::HLERequestContext& ctx) {
|
||||
NGLOG_WARNING(Service_SSL, "(STUBBED) called");
|
||||
IPC::RequestParser rp{ctx};
|
||||
u32 unk1 = rp.Pop<u32>(); // Probably minor/major?
|
||||
u32 unk2 = rp.Pop<u32>(); // TODO(ogniK): Figure out what this does
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager) {
|
||||
std::make_shared<SSL>()->InstallAsService(service_manager);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ public:
|
||||
|
||||
private:
|
||||
void CreateContext(Kernel::HLERequestContext& ctx);
|
||||
void SetInterfaceVersion(Kernel::HLERequestContext& ctx);
|
||||
};
|
||||
|
||||
/// Registers all SSL services with the specified service manager.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -84,7 +84,7 @@ static std::vector<u8> ReadSegment(FileUtil::IOFile& file, const NsoSegmentHeade
|
||||
reinterpret_cast<char*>(uncompressed_data.data()), compressed_size, header.size);
|
||||
|
||||
ASSERT_MSG(bytes_uncompressed == header.size && bytes_uncompressed == uncompressed_data.size(),
|
||||
"%d != %u != %zu", bytes_uncompressed, header.size, uncompressed_data.size());
|
||||
"{} != {} != {}", bytes_uncompressed, header.size, uncompressed_data.size());
|
||||
|
||||
return uncompressed_data;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cinttypes>
|
||||
#include <cstring>
|
||||
#include <boost/optional.hpp>
|
||||
#include "common/assert.h"
|
||||
@@ -47,7 +46,7 @@ static void MapPages(PageTable& page_table, VAddr base, u64 size, u8* memory, Pa
|
||||
|
||||
VAddr end = base + size;
|
||||
while (base != end) {
|
||||
ASSERT_MSG(base < PAGE_TABLE_NUM_ENTRIES, "out of range mapping at %016" PRIX64, base);
|
||||
ASSERT_MSG(base < PAGE_TABLE_NUM_ENTRIES, "out of range mapping at {:016X}", base);
|
||||
|
||||
page_table.attributes[base] = type;
|
||||
page_table.pointers[base] = memory;
|
||||
@@ -59,14 +58,14 @@ static void MapPages(PageTable& page_table, VAddr base, u64 size, u8* memory, Pa
|
||||
}
|
||||
|
||||
void MapMemoryRegion(PageTable& page_table, VAddr base, u64 size, u8* target) {
|
||||
ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: %016" PRIX64, size);
|
||||
ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: %016" PRIX64, base);
|
||||
ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size);
|
||||
ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base);
|
||||
MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, target, PageType::Memory);
|
||||
}
|
||||
|
||||
void MapIoRegion(PageTable& page_table, VAddr base, u64 size, MemoryHookPointer mmio_handler) {
|
||||
ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: %016" PRIX64, size);
|
||||
ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: %016" PRIX64, base);
|
||||
ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size);
|
||||
ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base);
|
||||
MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, nullptr, PageType::Special);
|
||||
|
||||
auto interval = boost::icl::discrete_interval<VAddr>::closed(base, base + size - 1);
|
||||
@@ -75,8 +74,8 @@ void MapIoRegion(PageTable& page_table, VAddr base, u64 size, MemoryHookPointer
|
||||
}
|
||||
|
||||
void UnmapRegion(PageTable& page_table, VAddr base, u64 size) {
|
||||
ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: %016" PRIX64, size);
|
||||
ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: %016" PRIX64, base);
|
||||
ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size);
|
||||
ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base);
|
||||
MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, nullptr, PageType::Unmapped);
|
||||
|
||||
auto interval = boost::icl::discrete_interval<VAddr>::closed(base, base + size - 1);
|
||||
@@ -172,7 +171,7 @@ T Read(const VAddr vaddr) {
|
||||
NGLOG_ERROR(HW_Memory, "Unmapped Read{} @ {:#010X}", sizeof(T) * 8, vaddr);
|
||||
return 0;
|
||||
case PageType::Memory:
|
||||
ASSERT_MSG(false, "Mapped memory page without a pointer @ %016" PRIX64, vaddr);
|
||||
ASSERT_MSG(false, "Mapped memory page without a pointer @ {:016X}", vaddr);
|
||||
break;
|
||||
case PageType::RasterizerCachedMemory: {
|
||||
RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Flush);
|
||||
@@ -205,7 +204,7 @@ void Write(const VAddr vaddr, const T data) {
|
||||
vaddr);
|
||||
return;
|
||||
case PageType::Memory:
|
||||
ASSERT_MSG(false, "Mapped memory page without a pointer @ %016" PRIX64, vaddr);
|
||||
ASSERT_MSG(false, "Mapped memory page without a pointer @ {:016X}", vaddr);
|
||||
break;
|
||||
case PageType::RasterizerCachedMemory: {
|
||||
RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Invalidate);
|
||||
@@ -659,6 +658,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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
explicit SDLJoystick(int joystick_index)
|
||||
: joystick{SDL_JoystickOpen(joystick_index), SDL_JoystickClose} {
|
||||
if (!joystick) {
|
||||
LOG_ERROR(Input, "failed to open joystick %d", joystick_index);
|
||||
NGLOG_ERROR(Input, "failed to open joystick {}", joystick_index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ public:
|
||||
trigger_if_greater = false;
|
||||
} else {
|
||||
trigger_if_greater = true;
|
||||
LOG_ERROR(Input, "Unknown direction %s", direction_name.c_str());
|
||||
NGLOG_ERROR(Input, "Unknown direction '{}'", direction_name);
|
||||
}
|
||||
return std::make_unique<SDLAxisButton>(GetJoystick(joystick_index), axis, threshold,
|
||||
trigger_if_greater);
|
||||
@@ -235,7 +235,7 @@ public:
|
||||
|
||||
void Init() {
|
||||
if (SDL_Init(SDL_INIT_JOYSTICK) < 0) {
|
||||
LOG_CRITICAL(Input, "SDL_Init(SDL_INIT_JOYSTICK) failed with: %s", SDL_GetError());
|
||||
NGLOG_CRITICAL(Input, "SDL_Init(SDL_INIT_JOYSTICK) failed with: {}", SDL_GetError());
|
||||
} else {
|
||||
using namespace Input;
|
||||
RegisterFactory<ButtonDevice>("sdl", std::make_shared<SDLButtonFactory>());
|
||||
|
||||
@@ -24,10 +24,7 @@ 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) {
|
||||
@@ -36,28 +33,6 @@ void GPU::WriteReg(u32 method, u32 subchannel, u32 value, u32 remaining_params)
|
||||
"{:08X} remaining params {}",
|
||||
method, subchannel, value, remaining_params);
|
||||
|
||||
if (method == static_cast<u32>(BufferMethods::SetGraphMacroEntry)) {
|
||||
// Prepare to upload a new macro, reset the upload counter.
|
||||
NGLOG_DEBUG(HW_GPU, "Uploading GPU macro {:08X}", value);
|
||||
current_macro_entry = value;
|
||||
current_macro_code.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if (method == static_cast<u32>(BufferMethods::SetGraphMacroCodeArg)) {
|
||||
// Append a new code word to the current macro.
|
||||
current_macro_code.push_back(value);
|
||||
|
||||
// There are no more params remaining, submit the code to the 3D engine.
|
||||
if (remaining_params == 0) {
|
||||
maxwell_3d->SubmitMacroCode(current_macro_entry, std::move(current_macro_code));
|
||||
current_macro_entry = InvalidGraphMacroEntry;
|
||||
current_macro_code.clear();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (method == static_cast<u32>(BufferMethods::BindObject)) {
|
||||
// Bind the current subchannel to the desired engine id.
|
||||
NGLOG_DEBUG(HW_GPU, "Binding subchannel {} to engine {}", subchannel, value);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -162,7 +168,7 @@ void Maxwell3D::ProcessQueryGet() {
|
||||
result = 0;
|
||||
break;
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Unimplemented query select type %u",
|
||||
UNIMPLEMENTED_MSG("Unimplemented query select type {}",
|
||||
static_cast<u32>(regs.query.query_get.select.Value()));
|
||||
}
|
||||
|
||||
@@ -180,7 +186,7 @@ void Maxwell3D::ProcessQueryGet() {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Query mode %u not implemented",
|
||||
UNIMPLEMENTED_MSG("Query mode {} not implemented",
|
||||
static_cast<u32>(regs.query.query_get.mode.Value()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {}", static_cast<u32>(format));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Tegra
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -113,7 +113,7 @@ bool MacroInterpreter::Step(const std::vector<u32>& code, bool is_delay_slot) {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Unimplemented macro operation %u",
|
||||
UNIMPLEMENTED_MSG("Unimplemented macro operation {}",
|
||||
static_cast<u32>(opcode.operation.Value()));
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ u32 MacroInterpreter::GetALUResult(ALUOperation operation, u32 src_a, u32 src_b)
|
||||
return ~(src_a & src_b);
|
||||
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Unimplemented ALU operation %u", static_cast<u32>(operation));
|
||||
UNIMPLEMENTED_MSG("Unimplemented ALU operation {}", static_cast<u32>(operation));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ void MacroInterpreter::ProcessResult(ResultOperation operation, u32 reg, u32 res
|
||||
Send((result >> 12) & 0b111111);
|
||||
break;
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Unimplemented result operation %u", static_cast<u32>(operation));
|
||||
UNIMPLEMENTED_MSG("Unimplemented result operation {}", static_cast<u32>(operation));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ enum class ExitMethod {
|
||||
struct Subroutine {
|
||||
/// Generates a name suitable for GLSL source code.
|
||||
std::string GetName() const {
|
||||
return "sub_" + std::to_string(begin) + "_" + std::to_string(end);
|
||||
return "sub_" + std::to_string(begin) + '_' + std::to_string(end);
|
||||
}
|
||||
|
||||
u32 begin; ///< Entry point of the subroutine.
|
||||
@@ -146,31 +146,260 @@ private:
|
||||
std::string shader_source;
|
||||
};
|
||||
|
||||
class GLSLGenerator {
|
||||
/**
|
||||
* 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:
|
||||
GLSLGenerator(const std::set<Subroutine>& subroutines, const ProgramCode& program_code,
|
||||
u32 main_offset, Maxwell3D::Regs::ShaderStage stage)
|
||||
: subroutines(subroutines), program_code(program_code), main_offset(main_offset),
|
||||
stage(stage) {
|
||||
GLSLRegister(size_t index, ShaderWriter& shader)
|
||||
: index{index}, shader{shader}, float_str{"freg_" + std::to_string(index)},
|
||||
integer_str{"ireg_" + std::to_string(index)} {}
|
||||
|
||||
Generate();
|
||||
/// 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;
|
||||
}
|
||||
|
||||
std::string GetShaderCode() {
|
||||
return declarations.GetResult() + shader.GetResult();
|
||||
/// Returns a GLSL string representing the register as a float
|
||||
const std::string& GetFloatString() const {
|
||||
ASSERT(IsFloatUsed());
|
||||
return float_str;
|
||||
}
|
||||
|
||||
/// Returns entries in the shader that are useful for external functions
|
||||
ShaderEntries GetEntries() const {
|
||||
return {GetConstBuffersDeclarations()};
|
||||
/// 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();
|
||||
}
|
||||
|
||||
/// Returns true if the active type is float
|
||||
bool IsFloat() const {
|
||||
return active_type == Type::Float;
|
||||
}
|
||||
|
||||
/// Returns true if the active type is integer
|
||||
bool IsInteger() const {
|
||||
return active_type == Type::Integer;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Gets the Subroutine object corresponding to the specified address.
|
||||
const Subroutine& GetSubroutine(u32 begin, u32 end) const {
|
||||
auto iter = subroutines.find(Subroutine{begin, end});
|
||||
ASSERT(iter != subroutines.end());
|
||||
return *iter;
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
* Used to manage shader registers that are emulated with GLSL. This class keeps track of the state
|
||||
* of all registers (e.g. whether they are currently being used as Floats or Integers), and
|
||||
* generates the necessary GLSL code to perform conversions as needed. This class is used for
|
||||
* bookkeeping within the GLSL program.
|
||||
*/
|
||||
class GLSLRegisterManager {
|
||||
public:
|
||||
GLSLRegisterManager(ShaderWriter& shader, ShaderWriter& declarations,
|
||||
const Maxwell3D::Regs::ShaderStage& stage)
|
||||
: shader{shader}, declarations{declarations}, stage{stage} {
|
||||
BuildRegisterList();
|
||||
}
|
||||
|
||||
/// Generates code representing a temporary (GPR) register.
|
||||
std::string GetRegister(const Register& reg, unsigned elem = 0) {
|
||||
if (reg == Register::ZeroIndex) {
|
||||
return "0";
|
||||
}
|
||||
|
||||
return regs[reg.GetSwizzledIndex(elem)].GetActiveString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes code that does a register assignment to float value operation. Should only be used
|
||||
* with shader instructions that deal with floats.
|
||||
* @param reg The destination register to use.
|
||||
* @param elem The element to use for the operation.
|
||||
* @param value The code representing the value to assign.
|
||||
* @param dest_num_components Number of components in the destination.
|
||||
* @param value_num_components Number of components in the value.
|
||||
* @param is_abs Optional, when True, applies absolute value to output.
|
||||
* @param dest_elem Optional, the destination element to use for the operation.
|
||||
*/
|
||||
void SetRegisterToFloat(const Register& reg, u64 elem, const std::string& value,
|
||||
u64 dest_num_components, u64 value_num_components, bool is_abs = false,
|
||||
u64 dest_elem = 0) {
|
||||
ASSERT(regs[reg].IsFloat());
|
||||
|
||||
std::string dest = GetRegister(reg, dest_elem);
|
||||
if (dest_num_components > 1) {
|
||||
dest += GetSwizzle(elem);
|
||||
}
|
||||
|
||||
std::string src = '(' + value + ')';
|
||||
if (value_num_components > 1) {
|
||||
src += GetSwizzle(elem);
|
||||
}
|
||||
|
||||
src = is_abs ? "abs(" + src + ')' : src;
|
||||
|
||||
shader.AddLine(dest + " = " + src + ';');
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes code that does a register assignment to input attribute operation. Input attributes
|
||||
* are stored as floats, so this may require conversion.
|
||||
* @param reg The destination register to use.
|
||||
* @param elem The element to use for the operation.
|
||||
* @param attribute The input attibute to use as the source value.
|
||||
*/
|
||||
void SetRegisterToInputAttibute(const Register& reg, u64 elem, Attribute::Index attribute) {
|
||||
std::string dest = GetRegister(reg);
|
||||
std::string src = GetInputAttribute(attribute) + GetSwizzle(elem);
|
||||
|
||||
if (regs[reg].IsFloat()) {
|
||||
shader.AddLine(dest + " = " + src + ';');
|
||||
} else if (regs[reg].IsInteger()) {
|
||||
shader.AddLine(dest + " = floatBitsToInt(" + src + ");");
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes code that does a output attribute assignment to register operation. Output attributes
|
||||
* are stored as floats, so this may require conversion.
|
||||
* @param attribute The destination output attribute.
|
||||
* @param elem The element to use for the operation.
|
||||
* @param reg The register to use as the source value.
|
||||
*/
|
||||
void SetOutputAttributeToRegister(Attribute::Index attribute, u64 elem, const Register& reg) {
|
||||
std::string dest = GetOutputAttribute(attribute) + GetSwizzle(elem);
|
||||
std::string src = GetRegister(reg);
|
||||
ASSERT_MSG(regs[reg].IsFloat(), "Output attributes must be set to a float");
|
||||
shader.AddLine(dest + " = " + src + ';');
|
||||
}
|
||||
|
||||
/// Generates code representing a uniform (C buffer) register.
|
||||
std::string GetUniform(const Uniform& uniform, const Register& dest_reg) {
|
||||
declr_const_buffers[uniform.index].MarkAsUsed(static_cast<unsigned>(uniform.index),
|
||||
static_cast<unsigned>(uniform.offset), stage);
|
||||
std::string value =
|
||||
'c' + std::to_string(uniform.index) + '[' + std::to_string(uniform.offset) + ']';
|
||||
|
||||
if (regs[dest_reg].IsFloat()) {
|
||||
return value;
|
||||
} else if (regs[dest_reg].IsInteger()) {
|
||||
return "floatBitsToInt(" + value + ')';
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
/// Add declarations for registers
|
||||
void GenerateDeclarations() {
|
||||
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();
|
||||
|
||||
for (const auto& index : declr_input_attribute) {
|
||||
// TODO(bunnei): Use proper number of elements for these
|
||||
declarations.AddLine("layout(location = " +
|
||||
std::to_string(static_cast<u32>(index) -
|
||||
static_cast<u32>(Attribute::Index::Attribute_0)) +
|
||||
") in vec4 " + GetInputAttribute(index) + ';');
|
||||
}
|
||||
declarations.AddNewLine();
|
||||
|
||||
for (const auto& index : declr_output_attribute) {
|
||||
// TODO(bunnei): Use proper number of elements for these
|
||||
declarations.AddLine("layout(location = " +
|
||||
std::to_string(static_cast<u32>(index) -
|
||||
static_cast<u32>(Attribute::Index::Attribute_0)) +
|
||||
") out vec4 " + GetOutputAttribute(index) + ';');
|
||||
}
|
||||
declarations.AddNewLine();
|
||||
|
||||
unsigned const_buffer_layout = 0;
|
||||
for (const auto& entry : GetConstBuffersDeclarations()) {
|
||||
declarations.AddLine("layout(std430) buffer " + entry.GetName());
|
||||
declarations.AddLine('{');
|
||||
declarations.AddLine(" float c" + std::to_string(entry.GetIndex()) + "[];");
|
||||
declarations.AddLine("};");
|
||||
declarations.AddNewLine();
|
||||
++const_buffer_layout;
|
||||
}
|
||||
declarations.AddNewLine();
|
||||
}
|
||||
|
||||
/// Returns a list of constant buffer declarations
|
||||
std::vector<ConstBufferEntry> GetConstBuffersDeclarations() const {
|
||||
std::vector<ConstBufferEntry> result;
|
||||
std::copy_if(declr_const_buffers.begin(), declr_const_buffers.end(),
|
||||
std::back_inserter(result), [](const auto& entry) { return entry.IsUsed(); });
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Build the GLSL register list.
|
||||
void BuildRegisterList() {
|
||||
for (size_t index = 0; index < Register::NumRegisters; ++index) {
|
||||
regs.emplace_back(index, shader);
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates code representing an input attribute register.
|
||||
@@ -209,6 +438,50 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates code to use for a swizzle operation.
|
||||
static std::string GetSwizzle(u64 elem) {
|
||||
ASSERT(elem <= 3);
|
||||
std::string swizzle = ".";
|
||||
swizzle += "xyzw"[elem];
|
||||
return swizzle;
|
||||
}
|
||||
|
||||
ShaderWriter& shader;
|
||||
ShaderWriter& declarations;
|
||||
std::vector<GLSLRegister> regs;
|
||||
std::set<Attribute::Index> declr_input_attribute;
|
||||
std::set<Attribute::Index> declr_output_attribute;
|
||||
std::array<ConstBufferEntry, Maxwell3D::Regs::MaxConstBuffers> declr_const_buffers;
|
||||
const Maxwell3D::Regs::ShaderStage& stage;
|
||||
};
|
||||
|
||||
class GLSLGenerator {
|
||||
public:
|
||||
GLSLGenerator(const std::set<Subroutine>& subroutines, const ProgramCode& program_code,
|
||||
u32 main_offset, Maxwell3D::Regs::ShaderStage stage)
|
||||
: subroutines(subroutines), program_code(program_code), main_offset(main_offset),
|
||||
stage(stage) {
|
||||
|
||||
Generate();
|
||||
}
|
||||
|
||||
std::string GetShaderCode() {
|
||||
return declarations.GetResult() + shader.GetResult();
|
||||
}
|
||||
|
||||
/// Returns entries in the shader that are useful for external functions
|
||||
ShaderEntries GetEntries() const {
|
||||
return {regs.GetConstBuffersDeclarations()};
|
||||
}
|
||||
|
||||
private:
|
||||
/// Gets the Subroutine object corresponding to the specified address.
|
||||
const Subroutine& GetSubroutine(u32 begin, u32 end) const {
|
||||
auto iter = subroutines.find(Subroutine{begin, end});
|
||||
ASSERT(iter != subroutines.end());
|
||||
return *iter;
|
||||
}
|
||||
|
||||
/// Generates code representing a 19-bit immediate value
|
||||
static std::string GetImmediate19(const Instruction& instr) {
|
||||
return std::to_string(instr.alu.GetImm20_19());
|
||||
@@ -219,32 +492,13 @@ private:
|
||||
return std::to_string(instr.alu.GetImm20_32());
|
||||
}
|
||||
|
||||
/// Generates code representing a temporary (GPR) register.
|
||||
std::string GetRegister(const Register& reg, unsigned elem = 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
/// Generates code representing a uniform (C buffer) register.
|
||||
std::string GetUniform(const Uniform& reg) {
|
||||
declr_const_buffers[reg.index].MarkAsUsed(static_cast<unsigned>(reg.index),
|
||||
static_cast<unsigned>(reg.offset), stage);
|
||||
return 'c' + std::to_string(reg.index) + '[' + std::to_string(reg.offset) + ']';
|
||||
}
|
||||
|
||||
/// Generates code representing a texture sampler.
|
||||
std::string GetSampler(const Sampler& sampler) const {
|
||||
// TODO(Subv): Support more than just texture sampler 0
|
||||
ASSERT_MSG(sampler.index == Sampler::Index::Sampler_0, "unsupported");
|
||||
const unsigned index{static_cast<unsigned>(sampler.index.Value()) -
|
||||
static_cast<unsigned>(Sampler::Index::Sampler_0)};
|
||||
return "tex[" + std::to_string(index) + "]";
|
||||
return "tex[" + std::to_string(index) + ']';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -262,23 +516,6 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes code that does an assignment operation.
|
||||
* @param reg the destination register code.
|
||||
* @param value the code representing the value to assign.
|
||||
*/
|
||||
void SetDest(u64 elem, const std::string& reg, const std::string& value,
|
||||
u64 dest_num_components, u64 value_num_components, bool is_abs = false) {
|
||||
std::string swizzle = ".";
|
||||
swizzle += "xyzw"[elem];
|
||||
|
||||
std::string dest = reg + (dest_num_components != 1 ? swizzle : "");
|
||||
std::string src = "(" + value + ")" + (value_num_components != 1 ? swizzle : "");
|
||||
src = is_abs ? "abs(" + src + ")" : src;
|
||||
|
||||
shader.AddLine(dest + " = " + src + ";");
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes code that assigns a predicate boolean variable.
|
||||
* @param pred The id of the predicate to write to.
|
||||
@@ -360,11 +597,10 @@ private:
|
||||
|
||||
switch (opcode->GetType()) {
|
||||
case OpCode::Type::Arithmetic: {
|
||||
std::string dest = GetRegister(instr.gpr0);
|
||||
std::string op_a = instr.alu.negate_a ? "-" : "";
|
||||
op_a += GetRegister(instr.gpr8);
|
||||
op_a += regs.GetRegister(instr.gpr8);
|
||||
if (instr.alu.abs_a) {
|
||||
op_a = "abs(" + op_a + ")";
|
||||
op_a = "abs(" + op_a + ')';
|
||||
}
|
||||
|
||||
std::string op_b = instr.alu.negate_b ? "-" : "";
|
||||
@@ -373,56 +609,64 @@ private:
|
||||
op_b += GetImmediate19(instr);
|
||||
} else {
|
||||
if (instr.is_b_gpr) {
|
||||
op_b += GetRegister(instr.gpr20);
|
||||
op_b += regs.GetRegister(instr.gpr20);
|
||||
} else {
|
||||
op_b += GetUniform(instr.uniform);
|
||||
op_b += regs.GetUniform(instr.uniform, instr.gpr0);
|
||||
}
|
||||
}
|
||||
|
||||
if (instr.alu.abs_b) {
|
||||
op_b = "abs(" + op_b + ")";
|
||||
op_b = "abs(" + op_b + ')';
|
||||
}
|
||||
|
||||
switch (opcode->GetId()) {
|
||||
case OpCode::Id::FMUL_C:
|
||||
case OpCode::Id::FMUL_R:
|
||||
case OpCode::Id::FMUL_IMM: {
|
||||
SetDest(0, dest, op_a + " * " + op_b, 1, 1, instr.alu.abs_d);
|
||||
regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " * " + op_b, 1, 1, instr.alu.abs_d);
|
||||
break;
|
||||
}
|
||||
case OpCode::Id::FMUL32_IMM: {
|
||||
// fmul32i doesn't have abs or neg bits.
|
||||
SetDest(0, dest, GetRegister(instr.gpr8) + " * " + GetImmediate32(instr), 1, 1);
|
||||
regs.SetRegisterToFloat(
|
||||
instr.gpr0, 0, regs.GetRegister(instr.gpr8) + " * " + GetImmediate32(instr), 1,
|
||||
1);
|
||||
break;
|
||||
}
|
||||
case OpCode::Id::FADD_C:
|
||||
case OpCode::Id::FADD_R:
|
||||
case OpCode::Id::FADD_IMM: {
|
||||
SetDest(0, dest, op_a + " + " + op_b, 1, 1, instr.alu.abs_d);
|
||||
regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " + " + op_b, 1, 1, instr.alu.abs_d);
|
||||
break;
|
||||
}
|
||||
case OpCode::Id::MUFU: {
|
||||
switch (instr.sub_op) {
|
||||
case SubOp::Cos:
|
||||
SetDest(0, dest, "cos(" + op_a + ")", 1, 1, instr.alu.abs_d);
|
||||
regs.SetRegisterToFloat(instr.gpr0, 0, "cos(" + op_a + ')', 1, 1,
|
||||
instr.alu.abs_d);
|
||||
break;
|
||||
case SubOp::Sin:
|
||||
SetDest(0, dest, "sin(" + op_a + ")", 1, 1, instr.alu.abs_d);
|
||||
regs.SetRegisterToFloat(instr.gpr0, 0, "sin(" + op_a + ')', 1, 1,
|
||||
instr.alu.abs_d);
|
||||
break;
|
||||
case SubOp::Ex2:
|
||||
SetDest(0, dest, "exp2(" + op_a + ")", 1, 1, instr.alu.abs_d);
|
||||
regs.SetRegisterToFloat(instr.gpr0, 0, "exp2(" + op_a + ')', 1, 1,
|
||||
instr.alu.abs_d);
|
||||
break;
|
||||
case SubOp::Lg2:
|
||||
SetDest(0, dest, "log2(" + op_a + ")", 1, 1, instr.alu.abs_d);
|
||||
regs.SetRegisterToFloat(instr.gpr0, 0, "log2(" + op_a + ')', 1, 1,
|
||||
instr.alu.abs_d);
|
||||
break;
|
||||
case SubOp::Rcp:
|
||||
SetDest(0, dest, "1.0 / " + op_a, 1, 1, instr.alu.abs_d);
|
||||
regs.SetRegisterToFloat(instr.gpr0, 0, "1.0 / " + op_a, 1, 1, instr.alu.abs_d);
|
||||
break;
|
||||
case SubOp::Rsq:
|
||||
SetDest(0, dest, "inversesqrt(" + op_a + ")", 1, 1, instr.alu.abs_d);
|
||||
regs.SetRegisterToFloat(instr.gpr0, 0, "inversesqrt(" + op_a + ')', 1, 1,
|
||||
instr.alu.abs_d);
|
||||
break;
|
||||
case SubOp::Min:
|
||||
SetDest(0, dest, "min(" + op_a + "," + op_b + ")", 1, 1, instr.alu.abs_d);
|
||||
regs.SetRegisterToFloat(instr.gpr0, 0, "min(" + op_a + "," + op_b + ')', 1, 1,
|
||||
instr.alu.abs_d);
|
||||
break;
|
||||
default:
|
||||
NGLOG_CRITICAL(HW_GPU, "Unhandled MUFU sub op: {0:x}",
|
||||
@@ -443,30 +687,29 @@ private:
|
||||
break;
|
||||
}
|
||||
case OpCode::Type::Ffma: {
|
||||
std::string dest = GetRegister(instr.gpr0);
|
||||
std::string op_a = GetRegister(instr.gpr8);
|
||||
std::string op_a = regs.GetRegister(instr.gpr8);
|
||||
std::string op_b = instr.ffma.negate_b ? "-" : "";
|
||||
std::string op_c = instr.ffma.negate_c ? "-" : "";
|
||||
|
||||
switch (opcode->GetId()) {
|
||||
case OpCode::Id::FFMA_CR: {
|
||||
op_b += GetUniform(instr.uniform);
|
||||
op_c += GetRegister(instr.gpr39);
|
||||
op_b += regs.GetUniform(instr.uniform, instr.gpr0);
|
||||
op_c += regs.GetRegister(instr.gpr39);
|
||||
break;
|
||||
}
|
||||
case OpCode::Id::FFMA_RR: {
|
||||
op_b += GetRegister(instr.gpr20);
|
||||
op_c += GetRegister(instr.gpr39);
|
||||
op_b += regs.GetRegister(instr.gpr20);
|
||||
op_c += regs.GetRegister(instr.gpr39);
|
||||
break;
|
||||
}
|
||||
case OpCode::Id::FFMA_RC: {
|
||||
op_b += GetRegister(instr.gpr39);
|
||||
op_c += GetUniform(instr.uniform);
|
||||
op_b += regs.GetRegister(instr.gpr39);
|
||||
op_c += regs.GetUniform(instr.uniform, instr.gpr0);
|
||||
break;
|
||||
}
|
||||
case OpCode::Id::FFMA_IMM: {
|
||||
op_b += GetImmediate19(instr);
|
||||
op_c += GetRegister(instr.gpr39);
|
||||
op_c += regs.GetRegister(instr.gpr39);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -475,28 +718,29 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
SetDest(0, dest, op_a + " * " + op_b + " + " + op_c, 1, 1);
|
||||
regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " * " + op_b + " + " + op_c, 1, 1);
|
||||
break;
|
||||
}
|
||||
case OpCode::Type::Memory: {
|
||||
std::string gpr0 = GetRegister(instr.gpr0);
|
||||
const Attribute::Index attribute = instr.attribute.fmt20.index;
|
||||
|
||||
switch (opcode->GetId()) {
|
||||
case OpCode::Id::LD_A: {
|
||||
ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested");
|
||||
SetDest(instr.attribute.fmt20.element, gpr0, GetInputAttribute(attribute), 1, 4);
|
||||
regs.SetRegisterToInputAttibute(instr.gpr0, instr.attribute.fmt20.element,
|
||||
attribute);
|
||||
break;
|
||||
}
|
||||
case OpCode::Id::ST_A: {
|
||||
ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested");
|
||||
SetDest(instr.attribute.fmt20.element, GetOutputAttribute(attribute), gpr0, 4, 1);
|
||||
regs.SetOutputAttributeToRegister(attribute, instr.attribute.fmt20.element,
|
||||
instr.gpr0);
|
||||
break;
|
||||
}
|
||||
case OpCode::Id::TEXS: {
|
||||
ASSERT_MSG(instr.attribute.fmt20.size == 4, "untested");
|
||||
const std::string op_a = GetRegister(instr.gpr8);
|
||||
const std::string op_b = GetRegister(instr.gpr20);
|
||||
const std::string op_a = regs.GetRegister(instr.gpr8);
|
||||
const std::string op_b = regs.GetRegister(instr.gpr20);
|
||||
const std::string sampler = GetSampler(instr.sampler);
|
||||
const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");";
|
||||
// Add an extra scope and declare the texture coords inside to prevent overwriting
|
||||
@@ -506,7 +750,7 @@ private:
|
||||
shader.AddLine(coord);
|
||||
const std::string texture = "texture(" + sampler + ", coords)";
|
||||
for (unsigned elem = 0; elem < instr.attribute.fmt20.size; ++elem) {
|
||||
SetDest(elem, GetRegister(instr.gpr0, elem), texture, 1, 4);
|
||||
regs.SetRegisterToFloat(instr.gpr0, elem, texture, 1, 4, false, elem);
|
||||
}
|
||||
--shader.scope;
|
||||
shader.AddLine("}");
|
||||
@@ -519,9 +763,9 @@ private:
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OpCode::Type::FloatPredicate: {
|
||||
case OpCode::Type::FloatSetPredicate: {
|
||||
std::string op_a = instr.fsetp.neg_a ? "-" : "";
|
||||
op_a += GetRegister(instr.gpr8);
|
||||
op_a += regs.GetRegister(instr.gpr8);
|
||||
|
||||
if (instr.fsetp.abs_a) {
|
||||
op_a = "abs(" + op_a + ')';
|
||||
@@ -537,9 +781,9 @@ private:
|
||||
op_b += '(' + GetImmediate19(instr) + ')';
|
||||
} else {
|
||||
if (instr.is_b_gpr) {
|
||||
op_b += GetRegister(instr.gpr20);
|
||||
op_b += regs.GetRegister(instr.gpr20);
|
||||
} else {
|
||||
op_b += GetUniform(instr.uniform);
|
||||
op_b += regs.GetUniform(instr.uniform, instr.gpr0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -570,11 +814,75 @@ private:
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OpCode::Type::FloatSet: {
|
||||
std::string op_a = instr.fset.neg_a ? "-" : "";
|
||||
op_a += regs.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 += regs.GetRegister(instr.gpr20);
|
||||
} else {
|
||||
op_b += regs.GetUniform(instr.uniform, instr.gpr0);
|
||||
}
|
||||
}
|
||||
|
||||
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:
|
||||
regs.SetRegisterToFloat(instr.gpr0, 0,
|
||||
"((" + op_a + ") < (" + op_b + ")) ? 1.0 : 0", 1, 1);
|
||||
break;
|
||||
case PredCondition::Equal:
|
||||
regs.SetRegisterToFloat(instr.gpr0, 0,
|
||||
"((" + op_a + ") == (" + op_b + ")) ? 1.0 : 0", 1, 1);
|
||||
break;
|
||||
case PredCondition::GreaterThan:
|
||||
regs.SetRegisterToFloat(instr.gpr0, 0,
|
||||
"((" + 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 = " + regs.GetRegister(0) + ';');
|
||||
shader.AddLine("color.g = " + regs.GetRegister(1) + ';');
|
||||
shader.AddLine("color.b = " + regs.GetRegister(2) + ';');
|
||||
shader.AddLine("color.a = " + regs.GetRegister(3) + ';');
|
||||
}
|
||||
|
||||
shader.AddLine("return true;");
|
||||
offset = PROGRAM_END - 1;
|
||||
break;
|
||||
@@ -585,8 +893,7 @@ private:
|
||||
}
|
||||
case OpCode::Id::IPA: {
|
||||
const auto& attribute = instr.attribute.fmt28;
|
||||
std::string dest = GetRegister(instr.gpr0);
|
||||
SetDest(attribute.element, dest, GetInputAttribute(attribute.index), 1, 4);
|
||||
regs.SetRegisterToInputAttibute(instr.gpr0, attribute.element, attribute.index);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -692,50 +999,10 @@ private:
|
||||
GenerateDeclarations();
|
||||
}
|
||||
|
||||
/// Returns a list of constant buffer declarations
|
||||
std::vector<ConstBufferEntry> GetConstBuffersDeclarations() const {
|
||||
std::vector<ConstBufferEntry> result;
|
||||
std::copy_if(declr_const_buffers.begin(), declr_const_buffers.end(),
|
||||
std::back_inserter(result), [](const auto& entry) { return entry.IsUsed(); });
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Add declarations for registers
|
||||
void GenerateDeclarations() {
|
||||
for (const auto& reg : declr_register) {
|
||||
declarations.AddLine("float " + reg + " = 0.0;");
|
||||
}
|
||||
declarations.AddNewLine();
|
||||
regs.GenerateDeclarations();
|
||||
|
||||
for (const auto& index : declr_input_attribute) {
|
||||
// TODO(bunnei): Use proper number of elements for these
|
||||
declarations.AddLine("layout(location = " +
|
||||
std::to_string(static_cast<u32>(index) -
|
||||
static_cast<u32>(Attribute::Index::Attribute_0)) +
|
||||
") in vec4 " + GetInputAttribute(index) + ";");
|
||||
}
|
||||
declarations.AddNewLine();
|
||||
|
||||
for (const auto& index : declr_output_attribute) {
|
||||
// TODO(bunnei): Use proper number of elements for these
|
||||
declarations.AddLine("layout(location = " +
|
||||
std::to_string(static_cast<u32>(index) -
|
||||
static_cast<u32>(Attribute::Index::Attribute_0)) +
|
||||
") out vec4 " + GetOutputAttribute(index) + ";");
|
||||
}
|
||||
declarations.AddNewLine();
|
||||
|
||||
unsigned const_buffer_layout = 0;
|
||||
for (const auto& entry : GetConstBuffersDeclarations()) {
|
||||
declarations.AddLine("layout(std430) buffer " + entry.GetName());
|
||||
declarations.AddLine('{');
|
||||
declarations.AddLine(" float c" + std::to_string(entry.GetIndex()) + "[];");
|
||||
declarations.AddLine("};");
|
||||
declarations.AddNewLine();
|
||||
++const_buffer_layout;
|
||||
}
|
||||
|
||||
declarations.AddNewLine();
|
||||
for (const auto& pred : declr_predicates) {
|
||||
declarations.AddLine("bool " + pred + " = false;");
|
||||
}
|
||||
@@ -750,13 +1017,10 @@ private:
|
||||
|
||||
ShaderWriter shader;
|
||||
ShaderWriter declarations;
|
||||
GLSLRegisterManager regs{shader, declarations, stage};
|
||||
|
||||
// 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;
|
||||
std::array<ConstBufferEntry, Maxwell3D::Regs::MaxConstBuffers> declr_const_buffers;
|
||||
}; // namespace Decompiler
|
||||
|
||||
std::string GetCommonDeclarations() {
|
||||
|
||||
@@ -17,7 +17,7 @@ void SetShaderUniformBlockBinding(GLuint shader, const char* name,
|
||||
GLint ub_size = 0;
|
||||
glGetActiveUniformBlockiv(shader, ub_index, GL_UNIFORM_BLOCK_DATA_SIZE, &ub_size);
|
||||
ASSERT_MSG(ub_size == expected_size,
|
||||
"Uniform block size did not match! Got %d, expected %zu",
|
||||
"Uniform block size did not match! Got {}, expected {}",
|
||||
static_cast<int>(ub_size), expected_size);
|
||||
glUniformBlockBinding(shader, ub_index, static_cast<GLuint>(binding));
|
||||
}
|
||||
|
||||
@@ -398,21 +398,22 @@ static const char* GetType(GLenum type) {
|
||||
|
||||
static void APIENTRY DebugHandler(GLenum source, GLenum type, GLuint id, GLenum severity,
|
||||
GLsizei length, const GLchar* message, const void* user_param) {
|
||||
Log::Level level;
|
||||
const char format[] = "{} {} {}: {}";
|
||||
const char* const str_source = GetSource(source);
|
||||
const char* const str_type = GetType(type);
|
||||
|
||||
switch (severity) {
|
||||
case GL_DEBUG_SEVERITY_HIGH:
|
||||
level = Log::Level::Error;
|
||||
NGLOG_ERROR(Render_OpenGL, format, str_source, str_type, id, message);
|
||||
break;
|
||||
case GL_DEBUG_SEVERITY_MEDIUM:
|
||||
level = Log::Level::Warning;
|
||||
NGLOG_WARNING(Render_OpenGL, format, str_source, str_type, id, message);
|
||||
break;
|
||||
case GL_DEBUG_SEVERITY_NOTIFICATION:
|
||||
case GL_DEBUG_SEVERITY_LOW:
|
||||
level = Log::Level::Debug;
|
||||
NGLOG_DEBUG(Render_OpenGL, format, str_source, str_type, id, message);
|
||||
break;
|
||||
}
|
||||
LOG_GENERIC(Log::Class::Render_OpenGL, level, "%s %s %d: %s", GetSource(source), GetType(type),
|
||||
id, message);
|
||||
}
|
||||
|
||||
/// Initialize the renderer
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -315,7 +315,8 @@ void GameList::PopupContextMenu(const QPoint& menu_location) {
|
||||
void GameList::PopulateAsync(const QString& dir_path, bool deep_scan) {
|
||||
if (!FileUtil::Exists(dir_path.toStdString()) ||
|
||||
!FileUtil::IsDirectory(dir_path.toStdString())) {
|
||||
LOG_ERROR(Frontend, "Could not find game list folder at %s", dir_path.toLocal8Bit().data());
|
||||
NGLOG_ERROR(Frontend, "Could not find game list folder at {}",
|
||||
dir_path.toLocal8Bit().data());
|
||||
search_field->setFilterResult(0, 0);
|
||||
return;
|
||||
}
|
||||
@@ -364,7 +365,7 @@ static bool HasSupportedFileExtension(const std::string& file_name) {
|
||||
|
||||
void GameList::RefreshGameDirectory() {
|
||||
if (!UISettings::values.gamedir.isEmpty() && current_worker != nullptr) {
|
||||
LOG_INFO(Frontend, "Change detected in the games directory. Reloading game list.");
|
||||
NGLOG_INFO(Frontend, "Change detected in the games directory. Reloading game list.");
|
||||
search_field->clear();
|
||||
PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan);
|
||||
}
|
||||
|
||||
@@ -359,19 +359,17 @@ bool GMainWindow::LoadROM(const QString& filename) {
|
||||
if (result != Core::System::ResultStatus::Success) {
|
||||
switch (result) {
|
||||
case Core::System::ResultStatus::ErrorGetLoader:
|
||||
LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!",
|
||||
filename.toStdString().c_str());
|
||||
NGLOG_CRITICAL(Frontend, "Failed to obtain loader for {}!", filename.toStdString());
|
||||
QMessageBox::critical(this, tr("Error while loading ROM!"),
|
||||
tr("The ROM format is not supported."));
|
||||
break;
|
||||
case Core::System::ResultStatus::ErrorUnsupportedArch:
|
||||
LOG_CRITICAL(Frontend, "Unsupported architecture detected!",
|
||||
filename.toStdString().c_str());
|
||||
NGLOG_CRITICAL(Frontend, "Unsupported architecture detected!", filename.toStdString());
|
||||
QMessageBox::critical(this, tr("Error while loading ROM!"),
|
||||
tr("The ROM uses currently unusable 32-bit architecture"));
|
||||
break;
|
||||
case Core::System::ResultStatus::ErrorSystemMode:
|
||||
LOG_CRITICAL(Frontend, "Failed to load ROM!");
|
||||
NGLOG_CRITICAL(Frontend, "Failed to load ROM!");
|
||||
QMessageBox::critical(this, tr("Error while loading ROM!"),
|
||||
tr("Could not determine the system mode."));
|
||||
break;
|
||||
@@ -859,7 +857,7 @@ void GMainWindow::UpdateUITheme() {
|
||||
QString theme_uri(":" + UISettings::values.theme + "/style.qss");
|
||||
QFile f(theme_uri);
|
||||
if (!f.exists()) {
|
||||
LOG_ERROR(Frontend, "Unable to set style, stylesheet file not found");
|
||||
NGLOG_ERROR(Frontend, "Unable to set style, stylesheet file not found");
|
||||
} else {
|
||||
f.open(QFile::ReadOnly | QFile::Text);
|
||||
QTextStream ts(&f);
|
||||
|
||||
@@ -27,17 +27,17 @@ bool Config::LoadINI(const std::string& default_contents, bool retry) {
|
||||
const char* location = this->sdl2_config_loc.c_str();
|
||||
if (sdl2_config->ParseError() < 0) {
|
||||
if (retry) {
|
||||
LOG_WARNING(Config, "Failed to load %s. Creating file from defaults...", location);
|
||||
NGLOG_WARNING(Config, "Failed to load {}. Creating file from defaults...", location);
|
||||
FileUtil::CreateFullPath(location);
|
||||
FileUtil::WriteStringToFile(true, default_contents, location);
|
||||
sdl2_config = std::make_unique<INIReader>(location); // Reopen file
|
||||
|
||||
return LoadINI(default_contents, false);
|
||||
}
|
||||
LOG_ERROR(Config, "Failed.");
|
||||
NGLOG_ERROR(Config, "Failed.");
|
||||
return false;
|
||||
}
|
||||
LOG_INFO(Config, "Successfully loaded %s", location);
|
||||
NGLOG_INFO(Config, "Successfully loaded {}", location);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ EmuWindow_SDL2::EmuWindow_SDL2(bool fullscreen) {
|
||||
|
||||
// Initialize the window
|
||||
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||
LOG_CRITICAL(Frontend, "Failed to initialize SDL2! Exiting...");
|
||||
NGLOG_CRITICAL(Frontend, "Failed to initialize SDL2! Exiting...");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ EmuWindow_SDL2::EmuWindow_SDL2(bool fullscreen) {
|
||||
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
|
||||
if (render_window == nullptr) {
|
||||
LOG_CRITICAL(Frontend, "Failed to create SDL2 window! Exiting...");
|
||||
NGLOG_CRITICAL(Frontend, "Failed to create SDL2 window! Exiting...");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -118,12 +118,12 @@ EmuWindow_SDL2::EmuWindow_SDL2(bool fullscreen) {
|
||||
gl_context = SDL_GL_CreateContext(render_window);
|
||||
|
||||
if (gl_context == nullptr) {
|
||||
LOG_CRITICAL(Frontend, "Failed to create SDL2 GL context! Exiting...");
|
||||
NGLOG_CRITICAL(Frontend, "Failed to create SDL2 GL context! Exiting...");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!gladLoadGLLoader(static_cast<GLADloadproc>(SDL_GL_GetProcAddress))) {
|
||||
LOG_CRITICAL(Frontend, "Failed to initialize GL functions! Exiting...");
|
||||
NGLOG_CRITICAL(Frontend, "Failed to initialize GL functions! Exiting...");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ int main(int argc, char** argv) {
|
||||
auto argv_w = CommandLineToArgvW(GetCommandLineW(), &argc_w);
|
||||
|
||||
if (argv_w == nullptr) {
|
||||
LOG_CRITICAL(Frontend, "Failed to get command line arguments");
|
||||
NGLOG_CRITICAL(Frontend, "Failed to get command line arguments");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
@@ -134,7 +134,7 @@ int main(int argc, char** argv) {
|
||||
SCOPE_EXIT({ MicroProfileShutdown(); });
|
||||
|
||||
if (filepath.empty()) {
|
||||
LOG_CRITICAL(Frontend, "Failed to load ROM: No ROM specified");
|
||||
NGLOG_CRITICAL(Frontend, "Failed to load ROM: No ROM specified");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -155,28 +155,28 @@ int main(int argc, char** argv) {
|
||||
|
||||
switch (load_result) {
|
||||
case Core::System::ResultStatus::ErrorGetLoader:
|
||||
LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", filepath.c_str());
|
||||
NGLOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", filepath.c_str());
|
||||
return -1;
|
||||
case Core::System::ResultStatus::ErrorLoader:
|
||||
LOG_CRITICAL(Frontend, "Failed to load ROM!");
|
||||
NGLOG_CRITICAL(Frontend, "Failed to load ROM!");
|
||||
return -1;
|
||||
case Core::System::ResultStatus::ErrorLoader_ErrorEncrypted:
|
||||
LOG_CRITICAL(Frontend, "The game that you are trying to load must be decrypted before "
|
||||
"being used with yuzu. \n\n For more information on dumping and "
|
||||
"decrypting games, please refer to: "
|
||||
"https://yuzu-emu.org/wiki/dumping-game-cartridges/");
|
||||
NGLOG_CRITICAL(Frontend, "The game that you are trying to load must be decrypted before "
|
||||
"being used with yuzu. \n\n For more information on dumping and "
|
||||
"decrypting games, please refer to: "
|
||||
"https://yuzu-emu.org/wiki/dumping-game-cartridges/");
|
||||
return -1;
|
||||
case Core::System::ResultStatus::ErrorLoader_ErrorInvalidFormat:
|
||||
LOG_CRITICAL(Frontend, "Error while loading ROM: The ROM format is not supported.");
|
||||
NGLOG_CRITICAL(Frontend, "Error while loading ROM: The ROM format is not supported.");
|
||||
return -1;
|
||||
case Core::System::ResultStatus::ErrorNotInitialized:
|
||||
LOG_CRITICAL(Frontend, "CPUCore not initialized");
|
||||
NGLOG_CRITICAL(Frontend, "CPUCore not initialized");
|
||||
return -1;
|
||||
case Core::System::ResultStatus::ErrorSystemMode:
|
||||
LOG_CRITICAL(Frontend, "Failed to determine system mode!");
|
||||
NGLOG_CRITICAL(Frontend, "Failed to determine system mode!");
|
||||
return -1;
|
||||
case Core::System::ResultStatus::ErrorVideoCore:
|
||||
LOG_CRITICAL(Frontend, "VideoCore not initialized");
|
||||
NGLOG_CRITICAL(Frontend, "VideoCore not initialized");
|
||||
return -1;
|
||||
case Core::System::ResultStatus::Success:
|
||||
break; // Expected case
|
||||
|
||||
Reference in New Issue
Block a user