Compare commits
39 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03341861c2 | ||
|
|
35f022ba5c | ||
|
|
37041ea12c | ||
|
|
358050cfc6 | ||
|
|
68183e7b5a | ||
|
|
f9945f8a3b | ||
|
|
d1d7582a5b | ||
|
|
1f37dd02ce | ||
|
|
27dbbd8227 | ||
|
|
cfc28e0c1a | ||
|
|
ca17f581f5 | ||
|
|
20bd26dc7d | ||
|
|
40bccd74d3 | ||
|
|
4c0cf3d5ff | ||
|
|
3d4dfefaec | ||
|
|
910b02d74b | ||
|
|
9d08a11c1d | ||
|
|
99ae9dbf49 | ||
|
|
9eb485702f | ||
|
|
b87a588c37 | ||
|
|
bb9093ed57 | ||
|
|
c2e0820ac2 | ||
|
|
c824648db5 | ||
|
|
6cd1482354 | ||
|
|
c82a4df000 | ||
|
|
467858633f | ||
|
|
1aafb0f3a3 | ||
|
|
2863e1edb9 | ||
|
|
aa0f596a6e | ||
|
|
98f0352728 | ||
|
|
10738588a4 | ||
|
|
8004af0d05 | ||
|
|
10d6b07161 | ||
|
|
91e67ed430 | ||
|
|
d248b90c85 | ||
|
|
8529d84f31 | ||
|
|
47f96fe13a | ||
|
|
3b558eebee | ||
|
|
ec204a27dc |
@@ -278,7 +278,7 @@ endif()
|
||||
if (ENABLE_QT)
|
||||
if (YUZU_USE_BUNDLED_QT)
|
||||
if (MSVC14 AND ARCHITECTURE_x86_64)
|
||||
set(QT_VER qt-5.7-msvc2015_64)
|
||||
set(QT_VER qt-5.10.0-msvc2015_64)
|
||||
else()
|
||||
message(FATAL_ERROR "No bundled Qt binaries for your toolchain. Disable YUZU_USE_BUNDLED_QT and provide your own.")
|
||||
endif()
|
||||
|
||||
2
externals/fmt
vendored
2
externals/fmt
vendored
Submodule externals/fmt updated: 4d35f94133...5859e58ba1
@@ -89,7 +89,7 @@ endif()
|
||||
|
||||
create_target_directory_groups(common)
|
||||
|
||||
target_link_libraries(common PUBLIC Boost::boost microprofile)
|
||||
target_link_libraries(common PUBLIC Boost::boost fmt microprofile)
|
||||
if (ARCHITECTURE_x86_64)
|
||||
target_link_libraries(common PRIVATE xbyak)
|
||||
endif()
|
||||
|
||||
@@ -52,5 +52,5 @@ __declspec(noinline, noreturn)
|
||||
#define DEBUG_ASSERT_MSG(_a_, _desc_, ...)
|
||||
#endif
|
||||
|
||||
#define UNIMPLEMENTED() DEBUG_ASSERT_MSG(false, "Unimplemented code!")
|
||||
#define UNIMPLEMENTED() LOG_CRITICAL(Debug, "Unimplemented code!")
|
||||
#define UNIMPLEMENTED_MSG(...) ASSERT_MSG(false, __VA_ARGS__)
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "common/logging/filter.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/logging/text_formatter.h"
|
||||
#include "common/string_util.h"
|
||||
|
||||
namespace Log {
|
||||
|
||||
@@ -106,25 +107,20 @@ const char* GetLevelName(Level log_level) {
|
||||
}
|
||||
|
||||
Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr,
|
||||
const char* function, const char* format, va_list args) {
|
||||
const char* function, std::string message) {
|
||||
using std::chrono::duration_cast;
|
||||
using std::chrono::steady_clock;
|
||||
|
||||
static steady_clock::time_point time_origin = steady_clock::now();
|
||||
|
||||
std::array<char, 4 * 1024> formatting_buffer;
|
||||
|
||||
Entry entry;
|
||||
entry.timestamp = duration_cast<std::chrono::microseconds>(steady_clock::now() - time_origin);
|
||||
entry.log_class = log_class;
|
||||
entry.log_level = log_level;
|
||||
|
||||
snprintf(formatting_buffer.data(), formatting_buffer.size(), "%s:%s:%u", filename, function,
|
||||
line_nr);
|
||||
entry.location = std::string(formatting_buffer.data());
|
||||
|
||||
vsnprintf(formatting_buffer.data(), formatting_buffer.size(), format, args);
|
||||
entry.message = std::string(formatting_buffer.data());
|
||||
entry.filename = Common::TrimSourcePath(filename);
|
||||
entry.line_num = line_nr;
|
||||
entry.function = function;
|
||||
entry.message = std::move(message);
|
||||
|
||||
return entry;
|
||||
}
|
||||
@@ -135,15 +131,28 @@ void SetFilter(Filter* new_filter) {
|
||||
filter = new_filter;
|
||||
}
|
||||
|
||||
void LogMessage(Class log_class, Level log_level, const char* filename, unsigned int line_nr,
|
||||
void LogMessage(Class log_class, Level log_level, const char* filename, unsigned int line_num,
|
||||
const char* function, const char* format, ...) {
|
||||
if (filter != nullptr && !filter->CheckMessage(log_class, log_level))
|
||||
if (filter && !filter->CheckMessage(log_class, log_level))
|
||||
return;
|
||||
|
||||
std::array<char, 4 * 1024> formatting_buffer;
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
Entry entry = CreateEntry(log_class, log_level, filename, line_nr, function, format, args);
|
||||
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) {
|
||||
if (filter && !filter->CheckMessage(log_class, log_level))
|
||||
return;
|
||||
Entry entry =
|
||||
CreateEntry(log_class, log_level, filename, line_num, function, fmt::vformat(format, args));
|
||||
|
||||
PrintColoredMessage(entry);
|
||||
}
|
||||
|
||||
@@ -22,13 +22,16 @@ struct Entry {
|
||||
std::chrono::microseconds timestamp;
|
||||
Class log_class;
|
||||
Level log_level;
|
||||
std::string location;
|
||||
std::string filename;
|
||||
unsigned int line_num;
|
||||
std::string function;
|
||||
std::string message;
|
||||
|
||||
Entry() = default;
|
||||
Entry(Entry&& o) = default;
|
||||
|
||||
Entry& operator=(Entry&& o) = default;
|
||||
Entry& operator=(const Entry& o) = default;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -44,7 +47,7 @@ const char* GetLevelName(Level log_level);
|
||||
|
||||
/// Creates a log entry by formatting the given source location, and message.
|
||||
Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr,
|
||||
const char* function, const char* format, va_list args);
|
||||
const char* function, std::string message);
|
||||
|
||||
void SetFilter(Filter* filter);
|
||||
} // namespace Log
|
||||
|
||||
@@ -65,14 +65,14 @@ bool Filter::ParseFilterRule(const std::string::const_iterator begin,
|
||||
const std::string::const_iterator end) {
|
||||
auto level_separator = std::find(begin, end, ':');
|
||||
if (level_separator == end) {
|
||||
LOG_ERROR(Log, "Invalid log filter. Must specify a log level after `:`: %s",
|
||||
std::string(begin, end).c_str());
|
||||
NGLOG_ERROR(Log, "Invalid log filter. Must specify a log level after `:`: %s",
|
||||
std::string(begin, end).c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
const Level level = GetLevelByName(level_separator + 1, end);
|
||||
if (level == Level::Count) {
|
||||
LOG_ERROR(Log, "Unknown log level in filter: %s", std::string(begin, end).c_str());
|
||||
NGLOG_ERROR(Log, "Unknown log level in filter: %s", std::string(begin, end).c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ bool Filter::ParseFilterRule(const std::string::const_iterator begin,
|
||||
|
||||
const Class log_class = GetClassByName(begin, level_separator);
|
||||
if (log_class == Class::Count) {
|
||||
LOG_ERROR(Log, "Unknown log class in filter: %s", std::string(begin, end).c_str());
|
||||
NGLOG_ERROR(Log, "Unknown log class in filter: %s", std::string(begin, end).c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Log {
|
||||
class Filter {
|
||||
public:
|
||||
/// Initializes the filter with all classes having `default_level` as the minimum level.
|
||||
Filter(Level default_level);
|
||||
Filter(Level default_level = Level::Info);
|
||||
|
||||
/// Resets the filter so that all classes have `level` as the minimum displayed level.
|
||||
void ResetAll(Level level);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Log {
|
||||
@@ -91,7 +92,7 @@ enum class Class : ClassType {
|
||||
};
|
||||
|
||||
/// Logs a message to the global logger.
|
||||
void LogMessage(Class log_class, Level log_level, const char* filename, unsigned int line_nr,
|
||||
void LogMessage(Class log_class, Level log_level, const char* filename, unsigned int line_num,
|
||||
const char* function,
|
||||
#ifdef _MSC_VER
|
||||
_Printf_format_string_
|
||||
@@ -103,6 +104,18 @@ void LogMessage(Class log_class, Level log_level, const char* filename, unsigned
|
||||
#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,
|
||||
const fmt::format_args& args);
|
||||
|
||||
template <typename... Args>
|
||||
void FmtLogMessage(Class log_class, Level log_level, const char* filename, unsigned int line_num,
|
||||
const char* function, const char* format, const Args&... args) {
|
||||
FmtLogMessageImpl(log_class, log_level, filename, line_num, function, format,
|
||||
fmt::make_args(args...));
|
||||
}
|
||||
|
||||
} // namespace Log
|
||||
|
||||
#define LOG_GENERIC(log_class, log_level, ...) \
|
||||
@@ -125,3 +138,28 @@ void LogMessage(Class log_class, Level log_level, const char* filename, unsigned
|
||||
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__, \
|
||||
__func__, __VA_ARGS__)
|
||||
#else
|
||||
#define NGLOG_TRACE(log_class, fmt, ...) (void(0))
|
||||
#endif
|
||||
|
||||
#define NGLOG_DEBUG(log_class, ...) \
|
||||
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Debug, __FILE__, __LINE__, \
|
||||
__func__, __VA_ARGS__)
|
||||
#define NGLOG_INFO(log_class, ...) \
|
||||
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Info, __FILE__, __LINE__, \
|
||||
__func__, __VA_ARGS__)
|
||||
#define NGLOG_WARNING(log_class, ...) \
|
||||
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Warning, __FILE__, __LINE__, \
|
||||
__func__, __VA_ARGS__)
|
||||
#define NGLOG_ERROR(log_class, ...) \
|
||||
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Error, __FILE__, __LINE__, \
|
||||
__func__, __VA_ARGS__)
|
||||
#define NGLOG_CRITICAL(log_class, ...) \
|
||||
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Critical, __FILE__, __LINE__, \
|
||||
__func__, __VA_ARGS__)
|
||||
|
||||
@@ -18,50 +18,29 @@
|
||||
|
||||
namespace Log {
|
||||
|
||||
// TODO(bunnei): This should be moved to a generic path manipulation library
|
||||
const char* TrimSourcePath(const char* path, const char* root) {
|
||||
const char* p = path;
|
||||
|
||||
while (*p != '\0') {
|
||||
const char* next_slash = p;
|
||||
while (*next_slash != '\0' && *next_slash != '/' && *next_slash != '\\') {
|
||||
++next_slash;
|
||||
}
|
||||
|
||||
bool is_src = Common::ComparePartialString(p, next_slash, root);
|
||||
p = next_slash;
|
||||
|
||||
if (*p != '\0') {
|
||||
++p;
|
||||
}
|
||||
if (is_src) {
|
||||
path = p;
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
void FormatLogMessage(const Entry& entry, char* out_text, size_t text_len) {
|
||||
std::string FormatLogMessage(const Entry& entry) {
|
||||
unsigned int time_seconds = static_cast<unsigned int>(entry.timestamp.count() / 1000000);
|
||||
unsigned int time_fractional = static_cast<unsigned int>(entry.timestamp.count() % 1000000);
|
||||
|
||||
const char* class_name = GetLogClassName(entry.log_class);
|
||||
const char* level_name = GetLevelName(entry.log_level);
|
||||
|
||||
snprintf(out_text, text_len, "[%4u.%06u] %s <%s> %s: %s", time_seconds, time_fractional,
|
||||
class_name, level_name, TrimSourcePath(entry.location.c_str()), entry.message.c_str());
|
||||
return fmt::format("[{:4d}.{:06d}] {} <{}> {}:{}:{}: {}", time_seconds, time_fractional,
|
||||
class_name, level_name, entry.filename, entry.function, entry.line_num,
|
||||
entry.message);
|
||||
}
|
||||
|
||||
void PrintMessage(const Entry& entry) {
|
||||
std::array<char, 4 * 1024> format_buffer;
|
||||
FormatLogMessage(entry, format_buffer.data(), format_buffer.size());
|
||||
fputs(format_buffer.data(), stderr);
|
||||
fputc('\n', stderr);
|
||||
auto str = FormatLogMessage(entry) + '\n';
|
||||
fputs(str.c_str(), stderr);
|
||||
}
|
||||
|
||||
void PrintColoredMessage(const Entry& entry) {
|
||||
#ifdef _WIN32
|
||||
static HANDLE console_handle = GetStdHandle(STD_ERROR_HANDLE);
|
||||
HANDLE console_handle = GetStdHandle(STD_ERROR_HANDLE);
|
||||
if (console_handle == INVALID_HANDLE_VALUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
CONSOLE_SCREEN_BUFFER_INFO original_info = {0};
|
||||
GetConsoleScreenBufferInfo(console_handle, &original_info);
|
||||
|
||||
@@ -10,20 +10,8 @@ namespace Log {
|
||||
|
||||
struct Entry;
|
||||
|
||||
/**
|
||||
* Attempts to trim an arbitrary prefix from `path`, leaving only the part starting at `root`. It's
|
||||
* intended to be used to strip a system-specific build directory from the `__FILE__` macro,
|
||||
* leaving only the path relative to the sources root.
|
||||
*
|
||||
* @param path The input file path as a null-terminated string
|
||||
* @param root The name of the root source directory as a null-terminated string. Path up to and
|
||||
* including the last occurrence of this name will be stripped
|
||||
* @return A pointer to the same string passed as `path`, but starting at the trimmed portion
|
||||
*/
|
||||
const char* TrimSourcePath(const char* path, const char* root = "src");
|
||||
|
||||
/// Formats a log entry into the provided text buffer.
|
||||
void FormatLogMessage(const Entry& entry, char* out_text, size_t text_len);
|
||||
std::string FormatLogMessage(const Entry& entry);
|
||||
/// Formats and prints a log entry to stderr.
|
||||
void PrintMessage(const Entry& entry);
|
||||
/// Prints the same message as `PrintMessage`, but colored acoording to the severity level.
|
||||
|
||||
@@ -462,4 +462,27 @@ std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, size_t max_l
|
||||
|
||||
return std::string(buffer, len);
|
||||
}
|
||||
|
||||
const char* TrimSourcePath(const char* path, const char* root) {
|
||||
const char* p = path;
|
||||
|
||||
while (*p != '\0') {
|
||||
const char* next_slash = p;
|
||||
while (*next_slash != '\0' && *next_slash != '/' && *next_slash != '\\') {
|
||||
++next_slash;
|
||||
}
|
||||
|
||||
bool is_src = Common::ComparePartialString(p, next_slash, root);
|
||||
p = next_slash;
|
||||
|
||||
if (*p != '\0') {
|
||||
++p;
|
||||
}
|
||||
if (is_src) {
|
||||
path = p;
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
|
||||
@@ -134,4 +134,17 @@ bool ComparePartialString(InIt begin, InIt end, const char* other) {
|
||||
* NUL-terminated then the string ends at max_len characters.
|
||||
*/
|
||||
std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, size_t max_len);
|
||||
|
||||
/**
|
||||
* Attempts to trim an arbitrary prefix from `path`, leaving only the part starting at `root`. It's
|
||||
* intended to be used to strip a system-specific build directory from the `__FILE__` macro,
|
||||
* leaving only the path relative to the sources root.
|
||||
*
|
||||
* @param path The input file path as a null-terminated string
|
||||
* @param root The name of the root source directory as a null-terminated string. Path up to and
|
||||
* including the last occurrence of this name will be stripped
|
||||
* @return A pointer to the same string passed as `path`, but starting at the trimmed portion
|
||||
*/
|
||||
const char* TrimSourcePath(const char* path, const char* root = "src");
|
||||
|
||||
} // namespace Common
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Telemetry {
|
||||
/// Field type, used for grouping fields together in the final submitted telemetry log
|
||||
enum class FieldType : u8 {
|
||||
None = 0, ///< No specified field group
|
||||
App, ///< Citra application fields (e.g. version, branch, etc.)
|
||||
App, ///< yuzu application fields (e.g. version, branch, etc.)
|
||||
Session, ///< Emulated session fields (e.g. title ID, log, etc.)
|
||||
Performance, ///< Emulated performance (e.g. fps, emulated CPU speed, etc.)
|
||||
UserFeedback, ///< User submitted feedback (e.g. star rating, user notes, etc.)
|
||||
|
||||
@@ -130,6 +130,8 @@ add_library(core STATIC
|
||||
hle/service/friend/friend.h
|
||||
hle/service/friend/friend_a.cpp
|
||||
hle/service/friend/friend_a.h
|
||||
hle/service/friend/friend_u.cpp
|
||||
hle/service/friend/friend_u.h
|
||||
hle/service/hid/hid.cpp
|
||||
hle/service/hid/hid.h
|
||||
hle/service/lm/lm.cpp
|
||||
|
||||
@@ -92,6 +92,8 @@ System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& file
|
||||
return ResultStatus::ErrorLoader_ErrorEncrypted;
|
||||
case Loader::ResultStatus::ErrorInvalidFormat:
|
||||
return ResultStatus::ErrorLoader_ErrorInvalidFormat;
|
||||
case Loader::ResultStatus::ErrorUnsupportedArch:
|
||||
return ResultStatus::ErrorUnsupportedArch;
|
||||
default:
|
||||
return ResultStatus::ErrorSystemMode;
|
||||
}
|
||||
@@ -115,6 +117,8 @@ System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& file
|
||||
return ResultStatus::ErrorLoader_ErrorEncrypted;
|
||||
case Loader::ResultStatus::ErrorInvalidFormat:
|
||||
return ResultStatus::ErrorLoader_ErrorInvalidFormat;
|
||||
case Loader::ResultStatus::ErrorUnsupportedArch:
|
||||
return ResultStatus::ErrorUnsupportedArch;
|
||||
default:
|
||||
return ResultStatus::ErrorLoader;
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ public:
|
||||
ErrorSystemFiles, ///< Error in finding system files
|
||||
ErrorSharedFont, ///< Error in finding shared font
|
||||
ErrorVideoCore, ///< Error in the video core
|
||||
ErrorUnsupportedArch, ///< Unsupported Architecture (32-Bit ROMs)
|
||||
ErrorUnknown ///< Any other error
|
||||
};
|
||||
|
||||
|
||||
@@ -120,18 +120,6 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
|
||||
return ERR_WRONG_PERMISSION;
|
||||
}
|
||||
|
||||
// TODO(Subv): The same process that created a SharedMemory object
|
||||
// can not map it in its own address space unless it was created with addr=0, result 0xD900182C.
|
||||
|
||||
if (address != 0) {
|
||||
// TODO(shinyquagsire23): Check for virtual/mappable memory here too?
|
||||
if (address >= Memory::HEAP_VADDR && address < Memory::HEAP_VADDR_END) {
|
||||
LOG_ERROR(Kernel, "cannot map id=%u, address=0x%lx name=%s, invalid address",
|
||||
GetObjectId(), address, name.c_str());
|
||||
return ERR_INVALID_ADDRESS;
|
||||
}
|
||||
}
|
||||
|
||||
VAddr target_address = address;
|
||||
|
||||
if (base_address == 0 && target_address == 0) {
|
||||
|
||||
@@ -371,6 +371,18 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/// Sets the thread activity
|
||||
static ResultCode SetThreadActivity(Handle handle, u32 unknown) {
|
||||
LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x%08X, unknown=0x%08X", handle, unknown);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/// Gets the thread context
|
||||
static ResultCode GetThreadContext(Handle handle, VAddr addr) {
|
||||
LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x%08X, addr=0x%" PRIx64, handle, addr);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/// Gets the priority for the specified thread
|
||||
static ResultCode GetThreadPriority(u32* priority, Handle handle) {
|
||||
const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(handle);
|
||||
@@ -853,8 +865,8 @@ static const FunctionDef SVC_Table[] = {
|
||||
{0x2F, nullptr, "GetLastThreadInfo"},
|
||||
{0x30, nullptr, "GetResourceLimitLimitValue"},
|
||||
{0x31, nullptr, "GetResourceLimitCurrentValue"},
|
||||
{0x32, nullptr, "SetThreadActivity"},
|
||||
{0x33, nullptr, "GetThreadContext"},
|
||||
{0x32, SvcWrap<SetThreadActivity>, "SetThreadActivity"},
|
||||
{0x33, SvcWrap<GetThreadContext>, "GetThreadContext"},
|
||||
{0x34, nullptr, "Unknown"},
|
||||
{0x35, nullptr, "Unknown"},
|
||||
{0x36, nullptr, "Unknown"},
|
||||
|
||||
@@ -70,6 +70,11 @@ void SvcWrap() {
|
||||
FuncReturn(retval);
|
||||
}
|
||||
|
||||
template <ResultCode func(u32, u64)>
|
||||
void SvcWrap() {
|
||||
FuncReturn(func((u32)(PARAM(0) & 0xFFFFFFFF), PARAM(1)).raw);
|
||||
}
|
||||
|
||||
template <ResultCode func(u32, u32, u64)>
|
||||
void SvcWrap() {
|
||||
FuncReturn(func((u32)(PARAM(0) & 0xFFFFFFFF), (u32)(PARAM(1) & 0xFFFFFFFF), PARAM(2)).raw);
|
||||
|
||||
@@ -25,7 +25,7 @@ class IAudioOut final : public ServiceFramework<IAudioOut> {
|
||||
public:
|
||||
IAudioOut() : ServiceFramework("IAudioOut"), audio_out_state(AudioState::Stopped) {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0x0, nullptr, "GetAudioOutState"},
|
||||
{0x0, &IAudioOut::GetAudioOutState, "GetAudioOutState"},
|
||||
{0x1, &IAudioOut::StartAudioOut, "StartAudioOut"},
|
||||
{0x2, &IAudioOut::StopAudioOut, "StopAudioOut"},
|
||||
{0x3, &IAudioOut::AppendAudioOutBuffer_1, "AppendAudioOutBuffer_1"},
|
||||
@@ -57,6 +57,13 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void GetAudioOutState(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Audio, "called");
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push(static_cast<u32>(audio_out_state));
|
||||
}
|
||||
|
||||
void StartAudioOut(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_Audio, "(STUBBED) called");
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ public:
|
||||
{0x0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"},
|
||||
{0x1, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolume"},
|
||||
{0x2, nullptr, "GetAudioDeviceOutputVolume"},
|
||||
{0x3, nullptr, "GetActiveAudioDeviceName"},
|
||||
{0x3, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceName"},
|
||||
{0x4, &IAudioDevice::QueryAudioDeviceSystemEvent, "QueryAudioDeviceSystemEvent"},
|
||||
{0x5, &IAudioDevice::GetActiveChannelCount, "GetActiveChannelCount"},
|
||||
{0x6, nullptr, "ListAudioDeviceNameAuto"},
|
||||
@@ -199,6 +199,18 @@ private:
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void GetActiveAudioDeviceName(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_Audio, "(STUBBED) called");
|
||||
IPC::RequestParser rp{ctx};
|
||||
|
||||
const std::string audio_interface = "AudioDevice";
|
||||
ctx.WriteBuffer(audio_interface.c_str(), audio_interface.size());
|
||||
|
||||
IPC::ResponseBuilder rb = rp.MakeBuilder(3, 0, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u32>(1);
|
||||
}
|
||||
|
||||
void QueryAudioDeviceSystemEvent(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_Audio, "(STUBBED) called");
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/service/friend/friend.h"
|
||||
#include "core/hle/service/friend/friend_a.h"
|
||||
#include "core/hle/service/friend/friend_u.h"
|
||||
|
||||
namespace Service {
|
||||
namespace Friend {
|
||||
@@ -22,6 +23,7 @@ Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager) {
|
||||
auto module = std::make_shared<Module>();
|
||||
std::make_shared<Friend_A>(module)->InstallAsService(service_manager);
|
||||
std::make_shared<Friend_U>(module)->InstallAsService(service_manager);
|
||||
}
|
||||
|
||||
} // namespace Friend
|
||||
|
||||
19
src/core/hle/service/friend/friend_u.cpp
Normal file
19
src/core/hle/service/friend/friend_u.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/service/friend/friend_u.h"
|
||||
|
||||
namespace Service {
|
||||
namespace Friend {
|
||||
|
||||
Friend_U::Friend_U(std::shared_ptr<Module> module)
|
||||
: Module::Interface(std::move(module), "friend:u") {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &Friend_U::Unknown, "Unknown"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
} // namespace Friend
|
||||
} // namespace Service
|
||||
18
src/core/hle/service/friend/friend_u.h
Normal file
18
src/core/hle/service/friend/friend_u.h
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/friend/friend.h"
|
||||
|
||||
namespace Service {
|
||||
namespace Friend {
|
||||
|
||||
class Friend_U final : public Module::Interface {
|
||||
public:
|
||||
explicit Friend_U(std::shared_ptr<Module> module);
|
||||
};
|
||||
|
||||
} // namespace Friend
|
||||
} // namespace Service
|
||||
@@ -70,9 +70,8 @@ private:
|
||||
}
|
||||
void GetResult(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_NIFM, "(STUBBED) called");
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u32>(0);
|
||||
}
|
||||
void GetSystemEventReadableHandles(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_NIFM, "(STUBBED) called");
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "core/hle/service/vi/vi_m.h"
|
||||
#include "core/hle/service/vi/vi_s.h"
|
||||
#include "core/hle/service/vi/vi_u.h"
|
||||
#include "core/settings.h"
|
||||
#include "video_core/renderer_base.h"
|
||||
#include "video_core/video_core.h"
|
||||
|
||||
@@ -711,6 +712,23 @@ private:
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void GetDisplayResolution(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_VI, "(STUBBED) called");
|
||||
IPC::RequestParser rp{ctx};
|
||||
u64 display_id = rp.Pop<u64>();
|
||||
|
||||
IPC::ResponseBuilder rb = rp.MakeBuilder(6, 0, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
if (Settings::values.use_docked_mode) {
|
||||
rb.Push(static_cast<u32>(DisplayResolution::DockedWidth));
|
||||
rb.Push(static_cast<u32>(DisplayResolution::DockedHeight));
|
||||
} else {
|
||||
rb.Push(static_cast<u32>(DisplayResolution::UndockedWidth));
|
||||
rb.Push(static_cast<u32>(DisplayResolution::UndockedHeight));
|
||||
}
|
||||
}
|
||||
|
||||
void SetLayerScalingMode(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_VI, "(STUBBED) called");
|
||||
IPC::RequestParser rp{ctx};
|
||||
@@ -808,6 +826,7 @@ IApplicationDisplayService::IApplicationDisplayService(
|
||||
{1000, &IApplicationDisplayService::ListDisplays, "ListDisplays"},
|
||||
{1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"},
|
||||
{1020, &IApplicationDisplayService::CloseDisplay, "CloseDisplay"},
|
||||
{1102, &IApplicationDisplayService::GetDisplayResolution, "GetDisplayResolution"},
|
||||
{2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"},
|
||||
{2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"},
|
||||
{2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"},
|
||||
|
||||
@@ -14,6 +14,13 @@ struct EventType;
|
||||
namespace Service {
|
||||
namespace VI {
|
||||
|
||||
enum class DisplayResolution : u32 {
|
||||
DockedWidth = 1920,
|
||||
DockedHeight = 1080,
|
||||
UndockedWidth = 1280,
|
||||
UndockedHeight = 720,
|
||||
};
|
||||
|
||||
class Module final {
|
||||
public:
|
||||
class Interface : public ServiceFramework<Interface> {
|
||||
|
||||
@@ -76,7 +76,7 @@ FileType AppLoader_DeconstructedRomDirectory::IdentifyType(FileUtil::IOFile& fil
|
||||
} else if (Common::ToLower(virtual_name) == "sdk") {
|
||||
is_sdk_found = true;
|
||||
} else {
|
||||
// Contrinue searching
|
||||
// Continue searching
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -119,6 +119,11 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
|
||||
}
|
||||
metadata.Print();
|
||||
|
||||
const FileSys::ProgramAddressSpaceType arch_bits{metadata.GetAddressSpaceType()};
|
||||
if (arch_bits == FileSys::ProgramAddressSpaceType::Is32Bit) {
|
||||
return ResultStatus::ErrorUnsupportedArch;
|
||||
}
|
||||
|
||||
// Load NSO modules
|
||||
VAddr next_load_addr{Memory::PROCESS_IMAGE_VADDR};
|
||||
for (const auto& module : {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3",
|
||||
|
||||
@@ -72,6 +72,7 @@ enum class ResultStatus {
|
||||
ErrorAlreadyLoaded,
|
||||
ErrorMemoryAllocationFailed,
|
||||
ErrorEncrypted,
|
||||
ErrorUnsupportedArch,
|
||||
};
|
||||
|
||||
/// Interface for loading an application
|
||||
|
||||
@@ -87,8 +87,8 @@ TelemetrySession::TelemetrySession() {
|
||||
#ifdef ENABLE_WEB_SERVICE
|
||||
if (Settings::values.enable_telemetry) {
|
||||
backend = std::make_unique<WebService::TelemetryJson>(
|
||||
Settings::values.telemetry_endpoint_url, Settings::values.citra_username,
|
||||
Settings::values.citra_token);
|
||||
Settings::values.telemetry_endpoint_url, Settings::values.yuzu_username,
|
||||
Settings::values.yuzu_token);
|
||||
} else {
|
||||
backend = std::make_unique<Telemetry::NullVisitor>();
|
||||
}
|
||||
|
||||
@@ -50,8 +50,8 @@ u64 RegenerateTelemetryId();
|
||||
|
||||
/**
|
||||
* Verifies the username and token.
|
||||
* @param username Citra username to use for authentication.
|
||||
* @param token Citra token to use for authentication.
|
||||
* @param username yuzu username to use for authentication.
|
||||
* @param token yuzu token to use for authentication.
|
||||
* @param func A function that gets exectued when the verification is finished
|
||||
* @returns Future with bool indicating whether the verification succeeded
|
||||
*/
|
||||
|
||||
@@ -21,16 +21,16 @@ public:
|
||||
/// Notify rasterizer that the specified Maxwell register has been changed
|
||||
virtual void NotifyMaxwellRegisterChanged(u32 id) = 0;
|
||||
|
||||
/// Notify rasterizer that all caches should be flushed to 3DS memory
|
||||
/// Notify rasterizer that all caches should be flushed to Switch memory
|
||||
virtual void FlushAll() = 0;
|
||||
|
||||
/// Notify rasterizer that any caches of the specified region should be flushed to 3DS memory
|
||||
/// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
|
||||
virtual void FlushRegion(VAddr addr, u64 size) = 0;
|
||||
|
||||
/// Notify rasterizer that any caches of the specified region should be invalidated
|
||||
virtual void InvalidateRegion(VAddr addr, u64 size) = 0;
|
||||
|
||||
/// Notify rasterizer that any caches of the specified region should be flushed to 3DS memory
|
||||
/// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
|
||||
/// and invalidated
|
||||
virtual void FlushAndInvalidateRegion(VAddr addr, u64 size) = 0;
|
||||
|
||||
|
||||
@@ -1261,7 +1261,7 @@ void RasterizerCacheOpenGL::ValidateSurface(const Surface& surface, VAddr addr,
|
||||
}
|
||||
}
|
||||
|
||||
// Load data from 3DS memory
|
||||
// Load data from Switch memory
|
||||
FlushRegion(params.addr, params.size);
|
||||
surface->LoadGLBuffer(params.addr, params.end);
|
||||
surface->UploadGLTexture(surface->GetSubRect(params), read_framebuffer.handle,
|
||||
|
||||
@@ -303,12 +303,12 @@ public:
|
||||
void CopySurface(const Surface& src_surface, const Surface& dst_surface,
|
||||
SurfaceInterval copy_interval);
|
||||
|
||||
/// Load a texture from 3DS memory to OpenGL and cache it (if not already cached)
|
||||
/// Load a texture from Switch memory to OpenGL and cache it (if not already cached)
|
||||
Surface GetSurface(const SurfaceParams& params, ScaleMatch match_res_scale,
|
||||
bool load_if_create);
|
||||
|
||||
/// Attempt to find a subrect (resolution scaled) of a surface, otherwise loads a texture from
|
||||
/// 3DS memory to OpenGL and caches it (if not already cached)
|
||||
/// Switch memory to OpenGL and caches it (if not already cached)
|
||||
SurfaceRect_Tuple GetSurfaceSubRect(const SurfaceParams& params, ScaleMatch match_res_scale,
|
||||
bool load_if_create);
|
||||
|
||||
@@ -328,7 +328,7 @@ public:
|
||||
/// Write any cached resources overlapping the region back to memory (if dirty)
|
||||
void FlushRegion(VAddr addr, u64 size, Surface flush_surface = nullptr);
|
||||
|
||||
/// Mark region as being invalidated by region_owner (nullptr if 3DS memory)
|
||||
/// Mark region as being invalidated by region_owner (nullptr if Switch memory)
|
||||
void InvalidateRegion(VAddr addr, u64 size, const Surface& region_owner);
|
||||
|
||||
/// Flush all cached resources tracked by this cache manager
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
class EmuWindow;
|
||||
|
||||
/// Structure used for storing information about the textures for each 3DS screen
|
||||
/// Structure used for storing information about the textures for the Switch screen
|
||||
struct TextureInfo {
|
||||
OGLTexture resource;
|
||||
GLsizei width;
|
||||
@@ -24,7 +24,7 @@ struct TextureInfo {
|
||||
Tegra::FramebufferConfig::PixelFormat pixel_format;
|
||||
};
|
||||
|
||||
/// Structure used for storing information about the display target for each 3DS screen
|
||||
/// Structure used for storing information about the display target for the Switch screen
|
||||
struct ScreenInfo {
|
||||
GLuint display_texture;
|
||||
MathUtil::Rectangle<float> display_texcoords;
|
||||
|
||||
@@ -357,7 +357,12 @@ bool GMainWindow::LoadROM(const QString& filename) {
|
||||
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());
|
||||
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!");
|
||||
QMessageBox::critical(this, tr("Error while loading ROM!"),
|
||||
@@ -371,9 +376,9 @@ bool GMainWindow::LoadROM(const QString& filename) {
|
||||
"yuzu. A real Switch is required.<br/><br/>"
|
||||
"For more information on dumping and decrypting games, please see the following "
|
||||
"wiki pages: <ul>"
|
||||
"<li><a href='https://citra-emu.org/wiki/dumping-game-cartridges/'>Dumping Game "
|
||||
"<li><a href='https://yuzu-emu.org/wiki/dumping-game-cartridges/'>Dumping Game "
|
||||
"Cartridges</a></li>"
|
||||
"<li><a href='https://citra-emu.org/wiki/dumping-installed-titles/'>Dumping "
|
||||
"<li><a href='https://yuzu-emu.org/wiki/dumping-installed-titles/'>Dumping "
|
||||
"Installed Titles</a></li>"
|
||||
"</ul>"));
|
||||
break;
|
||||
@@ -408,7 +413,7 @@ bool GMainWindow::LoadROM(const QString& filename) {
|
||||
}
|
||||
|
||||
void GMainWindow::BootGame(const QString& filename) {
|
||||
LOG_INFO(Frontend, "yuzu starting...");
|
||||
NGLOG_INFO(Frontend, "yuzu starting...");
|
||||
StoreRecentFile(filename); // Put the filename on top of the list
|
||||
|
||||
if (!LoadROM(filename))
|
||||
@@ -695,18 +700,18 @@ void GMainWindow::UpdateStatusBar() {
|
||||
void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string details) {
|
||||
QMessageBox::StandardButton answer;
|
||||
QString status_message;
|
||||
const QString common_message =
|
||||
tr("The game you are trying to load requires additional files from your 3DS to be dumped "
|
||||
"before playing.<br/><br/>For more information on dumping these files, please see the "
|
||||
"following wiki page: <a "
|
||||
"href='https://citra-emu.org/wiki/"
|
||||
"dumping-system-archives-and-the-shared-fonts-from-a-3ds-console/'>Dumping System "
|
||||
"Archives and the Shared Fonts from a 3DS Console</a>.<br/><br/>Would you like to quit "
|
||||
"back to the game list? Continuing emulation may result in crashes, corrupted save "
|
||||
"data, or other bugs.");
|
||||
const QString common_message = tr(
|
||||
"The game you are trying to load requires additional files from your Switch to be dumped "
|
||||
"before playing.<br/><br/>For more information on dumping these files, please see the "
|
||||
"following wiki page: <a "
|
||||
"href='https://yuzu-emu.org/wiki/"
|
||||
"dumping-system-archives-and-the-shared-fonts-from-a-switch-console/'>Dumping System "
|
||||
"Archives and the Shared Fonts from a Switch Console</a>.<br/><br/>Would you like to quit "
|
||||
"back to the game list? Continuing emulation may result in crashes, corrupted save "
|
||||
"data, or other bugs.");
|
||||
switch (result) {
|
||||
case Core::System::ResultStatus::ErrorSystemFiles: {
|
||||
QString message = "Citra was unable to locate a 3DS system archive";
|
||||
QString message = "yuzu was unable to locate a Switch system archive";
|
||||
if (!details.empty()) {
|
||||
message.append(tr(": %1. ").arg(details.c_str()));
|
||||
} else {
|
||||
@@ -721,7 +726,7 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string det
|
||||
}
|
||||
|
||||
case Core::System::ResultStatus::ErrorSharedFont: {
|
||||
QString message = tr("Citra was unable to locate the 3DS shared fonts. ");
|
||||
QString message = tr("yuzu was unable to locate the Switch shared fonts. ");
|
||||
message.append(common_message);
|
||||
answer = QMessageBox::question(this, tr("Shared Fonts Not Found"), message,
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace DefaultINI {
|
||||
|
||||
const char* sdl2_config_file = R"(
|
||||
[Controls]
|
||||
# The input devices and parameters for each 3DS native input
|
||||
# The input devices and parameters for each Switch native input
|
||||
# It should be in the format of "engine:[engine_name],[param1]:[value1],[param2]:[value2]..."
|
||||
# Escape characters $0 (for ':'), $1 (for ',') and $2 (for '$') can be used in values
|
||||
|
||||
@@ -177,12 +177,12 @@ gdbstub_port=24689
|
||||
# 0: No, 1 (default): Yes
|
||||
enable_telemetry =
|
||||
# Endpoint URL for submitting telemetry data
|
||||
telemetry_endpoint_url = https://services.citra-emu.org/api/telemetry
|
||||
telemetry_endpoint_url =
|
||||
# Endpoint URL to verify the username and token
|
||||
verify_endpoint_url = https://services.citra-emu.org/api/profile
|
||||
# Username and token for Citra Web Service
|
||||
verify_endpoint_url =
|
||||
# Username and token for yuzu Web Service
|
||||
# See https://services.citra-emu.org/ for more info
|
||||
citra_username =
|
||||
citra_token =
|
||||
yuzu_username =
|
||||
yuzu_token =
|
||||
)";
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ int main(int argc, char** argv) {
|
||||
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://citra-emu.org/wiki/dumping-game-cartridges/");
|
||||
"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.");
|
||||
|
||||
Reference in New Issue
Block a user