Compare commits

...

57 Commits

Author SHA1 Message Date
N00byKing
d1d7582a5b rasterizer_interface.h: Update from citra to yuzu 2018-04-04 23:07:58 +02:00
N00byKing
1f37dd02ce default_ini.h: Update from citra to yuzu 2018-04-04 23:05:51 +02:00
N00byKing
27dbbd8227 gl_rasterizer_cache.cpp: Update from citra to yuzu 2018-04-04 23:05:10 +02:00
N00byKing
cfc28e0c1a gl_rasterizer_cache.h: Update from citra to yuzu 2018-04-04 23:04:24 +02:00
N00byKing
ca17f581f5 renderer_opengl.h: Update from citra to yuzu 2018-04-04 23:03:02 +02:00
bunnei
20bd26dc7d Merge pull request #308 from bunnei/misc-fixes-2
Implement and stub several SVC/VI/Audio/Friend/etc. funcs
2018-04-04 16:50:12 -04:00
bunnei
40bccd74d3 svc: Stub out SetThreadActivity, GetThreadContext. 2018-04-02 23:51:01 -04:00
bunnei
4c0cf3d5ff audren_u: Stub out GetActiveAudioDeviceName. 2018-04-02 23:51:00 -04:00
bunnei
3d4dfefaec audout_u: Implement GetAudioOutState. 2018-04-02 23:51:00 -04:00
bunnei
910b02d74b nifm: GetResult does not return a data field. 2018-04-02 23:50:59 -04:00
bunnei
9d08a11c1d vi: Implement GetDisplayResolution. 2018-04-02 23:50:59 -04:00
bunnei
99ae9dbf49 shared_memory: Remove incorrect 3ds-specific check. 2018-04-02 23:50:58 -04:00
bunnei
9eb485702f service: Add friend:u interface. 2018-04-02 23:50:57 -04:00
bunnei
b87a588c37 Merge pull request #306 from daniellimws/new-fmt-macros
logging: Use variadic template instead of FMT_VARIADIC
2018-04-02 22:48:17 -04:00
Daniel Lim Wee Soong
bb9093ed57 logging: Change FmtLogMessage to use variadic template instead of FMT_VARIADIC
Due to premature merging of #262 I think the build may be failing right now. Should merge this ASAP to fix it.
2018-04-03 10:31:54 +08:00
bunnei
c2e0820ac2 Merge pull request #262 from daniellimws/fmtlib-macros
Logging: Add fmtlib-based macros
2018-04-02 21:19:20 -04:00
bunnei
c824648db5 Merge pull request #267 from N00byKing/patch-1
Update Dialog from citra to yuzu
2018-04-02 18:33:52 -04:00
bunnei
6cd1482354 Merge pull request #276 from N00byKing/acctoyuzu
Change Telemetry Names to yuzu and remove links to citra
2018-04-02 18:30:04 -04:00
bunnei
c82a4df000 Merge pull request #304 from daniellimws/fix-openbsd
Fix build on OpenBSD
2018-04-02 18:27:19 -04:00
James Rowe
467858633f Merge pull request #305 from N00byKing/patch-2
deconstructed_rom_directory.cpp: Fix Typo
2018-04-02 16:21:03 -06:00
N00byKing
1aafb0f3a3 deconstructed_rom_directory.cpp: Fix Typo 2018-04-03 00:20:35 +02:00
bunnei
2863e1edb9 Merge pull request #66 from RiverCityRansomware/qtUpdate
Updates CMakeLists to use Qt 5.10.0 instead of Qt 5.7
2018-04-02 16:06:58 -04:00
Daniel Lim Wee Soong
c9845c486e externals: Update fmt to 4d35f94
Versions prior to this didn't compile on OpenBSD due to unconditional
use of the non-standard strtod_l() function.

The fmt::MemoryWriter API has been removed in the intervening
versions, so replace its use with fmt::memory_buffer and fmt::format_to.

The library also no longer provides the fmt::fmt ALIAS, so define
it in externals/CMakeLists.txt.
2018-04-03 02:49:58 +08:00
Daniel Lim Wee Soong
a66204eb5c common: fix swap functions on Bitrig and OpenBSD
swap{16,32,64} are defined as macros on the two, but client code
tries to invoke them as Common::swap{16,32,64}, which naturally
doesn't work. This hack redefines the macros as inline functions
in the Common namespace: the bodies of the functions are the
same as the original macros, but relying on OS-specific
implementation details like this is of course brittle.
2018-04-03 02:25:11 +08:00
bunnei
6022bc8394 Merge pull request #297 from bunnei/hid-touch-state
hid: Write empty touch screen state.
2018-04-02 13:05:34 -04:00
bunnei
f92594d744 Merge pull request #296 from bunnei/misc-mem-fsp-fixes
Fix stack region, implement FSP GetSize/SetSize, and some stubs
2018-04-02 13:05:25 -04:00
bunnei
3413f1f7ce Merge pull request #288 from Subv/macro_interpreter
GPU: Implemented a gpu macro interpreter
2018-04-02 10:04:19 -04:00
Subv
11b4ab9685 GPU: Use the MacroInterpreter class to execute the GPU macros instead of HLEing them. 2018-04-01 12:07:26 -05:00
Subv
1ec8d2123d GPU: Implemented a gpu macro interpreter.
The Ryujinx macro interpreter and envydis were used as reference.

Macros are programs that are uploaded by the games during boot and can later be called by writing to their method id in a GPU command buffer.
2018-04-01 12:07:26 -05:00
bunnei
72b90494e7 hid: Write empty touch screen state. 2018-04-01 00:12:07 -04:00
bunnei
f4ba523992 hle_ipc, fsp_srv: Cleanup logging. 2018-03-31 23:30:00 -04:00
bunnei
b6b7d78ded hid: Stub out GetSupportedNpadStyleSet. 2018-03-31 16:06:46 -04:00
bunnei
eef097bdc7 hle_ipc: Do not ensure write buffer size. 2018-03-31 16:06:46 -04:00
bunnei
88582b84a5 fsp_srv: Implement GetSize and SetSize. 2018-03-31 16:06:45 -04:00
bunnei
b27ab46bde memory: Fix stack region. 2018-03-31 16:06:45 -04:00
bunnei
b3298465cf Merge pull request #293 from N00byKing/drkthm
Add Dark Theme (And Theming in General + Icon Theming)
2018-03-31 00:46:18 -04:00
bunnei
9cba0f1794 Merge pull request #292 from bunnei/botw-progress
NFP, SVC, and AudRen progress
2018-03-30 14:18:57 -04:00
N00byKing
1b7dc84132 Port citra-emu/citra#3610 to yuzu 2018-03-30 17:38:34 +02:00
N00byKing
b55dc9c85e Remove whitespaces 2018-03-30 14:18:35 +02:00
N00byKing
78e974ba68 Add Dark theme, Icon theming
configure_general.ui: Add UI Option for Themes

config.cpp: Save Theme Settings
2018-03-30 14:14:37 +02:00
bunnei
86095e62cc audren_u: Stub QueryAudioDeviceSystemEvent and GetActiveChannelCount. 2018-03-29 21:23:24 -04:00
bunnei
f6893969b3 svc: Stub GetThreadCoreMask. 2018-03-29 21:23:15 -04:00
bunnei
deaf6f9e35 service: Add NFP module interface.
service: Initialize NFP service.

Log: Add NFP service as a log subtype.
2018-03-29 21:22:44 -04:00
bunnei
cf643df792 Merge pull request #290 from MerryMage/dfix-20180329
dynarmic: Update to 9cc12d8
2018-03-29 09:06:52 -04:00
bunnei
4900c51864 Merge pull request #289 from lioncash/self-assign
result: Check against self-assignment in ResultVal's copy assignment operator
2018-03-29 09:03:41 -04:00
MerryMage
57eca6374a dynarmic: Update to 9cc12d8
9cc12d8 abi: Missing includes
ac35ad5 emit_x64_floating_point: Near jump instead of short jump in FPMinNumberic{32,64}
6f03fdd A64: system: Use an enum class for MRS/MSR register encodings
2018-03-29 12:49:21 +01:00
N00byKing
aa0f596a6e telemetry.h: Reword comment from citra to yuzu 2018-03-27 11:16:59 +02:00
N00byKing
98f0352728 telemetry_session.h: Reword Documentation Comment from citra to yuzu 2018-03-27 11:16:59 +02:00
N00byKing
10738588a4 Remove Links to citra Services 2018-03-27 11:16:59 +02:00
N00byKing
8004af0d05 Change Telemetry Names to yuzu 2018-03-27 11:16:59 +02:00
N00byKing
10d6b07161 yuzu.cpp: Update Link from citra to yuzu 2018-03-26 21:48:18 +02:00
N00byKing
91e67ed430 main.cpp: Replace Citra with yuzu Wiki Links 2018-03-25 11:44:04 +02:00
N00byKing
d248b90c85 main.cpp: Update Dialog from citra to yuzu 2018-03-25 11:42:46 +02:00
Daniel Lim Wee Soong
8529d84f31 Remove dependency chrono
Earlier chrono was included but after some code changed it was no longer needed

Forgot to remove it so I'm removing it now
2018-03-22 21:53:51 +08:00
Daniel Lim Wee Soong
47f96fe13a Change "yuzu starting..." to be logged with the new macro
Just as a proof that it works
2018-03-22 18:26:43 +08:00
Daniel Lim Wee Soong
3b558eebee Logging: Create logging macros based on fmtlib
Add a new set of logging macros based on fmtlib
Similar but not exactly the same as https://github.com/citra-emu/citra/pull/3533

Citra currently uses a different version of fmt, which does not support FMT_VARIADIC so
make_args is used instead. On the other hand, yuzu uses fmt 4.1.0 which doesn't have make_args yet
so FMT_VARIADIC is used.
2018-03-22 18:21:29 +08:00
River City Ransomware
ec204a27dc Update qt
Updates qt from 5.7 to 5.10.0, fixing some errors relating to setting the process dpi
2018-01-17 09:20:53 -05:00
114 changed files with 2388 additions and 288 deletions

View File

@@ -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()

View File

@@ -1,5 +0,0 @@
<RCC>
<qresource prefix="icons">
<file>yuzu.png</file>
</qresource>
</RCC>

BIN
dist/icons/yuzu.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

11
dist/qt_themes/default/default.qrc vendored Normal file
View File

@@ -0,0 +1,11 @@
<RCC>
<qresource prefix="icons/default">
<file alias="index.theme">icons/index.theme</file>
<file alias="16x16/checked.png">icons/16x16/checked.png</file>
<file alias="16x16/failed.png">icons/16x16/failed.png</file>
<file alias="256x256/yuzu.png">icons/256x256/yuzu.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 428 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

@@ -0,0 +1,10 @@
[Icon Theme]
Name=default
Comment=default theme
Directories=16x16,256x256
[16x16]
Size=16
[256x256]
Size=256

View File

@@ -0,0 +1,11 @@
[Icon Theme]
Name=qdarkstyle
Comment=dark theme
Inherits=default
Directories=16x16,256x256
[16x16]
Size=16
[256x256]
Size=256

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 493 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 464 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 464 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 598 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 598 B

BIN
dist/qt_themes/qdarkstyle/rc/close.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 940 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 972 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 846 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 728 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 760 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 646 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

BIN
dist/qt_themes/qdarkstyle/rc/undock.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 B

49
dist/qt_themes/qdarkstyle/style.qrc vendored Normal file
View File

@@ -0,0 +1,49 @@
<RCC>
<qresource prefix="icons/qdarkstyle">
<file alias="index.theme">icons/index.theme</file>
</qresource>
<qresource prefix="qss_icons">
<file>rc/up_arrow_disabled.png</file>
<file>rc/Hmovetoolbar.png</file>
<file>rc/stylesheet-branch-end.png</file>
<file>rc/branch_closed-on.png</file>
<file>rc/stylesheet-vline.png</file>
<file>rc/branch_closed.png</file>
<file>rc/branch_open-on.png</file>
<file>rc/transparent.png</file>
<file>rc/right_arrow_disabled.png</file>
<file>rc/sizegrip.png</file>
<file>rc/close.png</file>
<file>rc/close-hover.png</file>
<file>rc/close-pressed.png</file>
<file>rc/down_arrow.png</file>
<file>rc/Vmovetoolbar.png</file>
<file>rc/left_arrow.png</file>
<file>rc/stylesheet-branch-more.png</file>
<file>rc/up_arrow.png</file>
<file>rc/right_arrow.png</file>
<file>rc/left_arrow_disabled.png</file>
<file>rc/Hsepartoolbar.png</file>
<file>rc/branch_open.png</file>
<file>rc/Vsepartoolbar.png</file>
<file>rc/down_arrow_disabled.png</file>
<file>rc/undock.png</file>
<file>rc/checkbox_checked_disabled.png</file>
<file>rc/checkbox_checked_focus.png</file>
<file>rc/checkbox_checked.png</file>
<file>rc/checkbox_indeterminate.png</file>
<file>rc/checkbox_indeterminate_focus.png</file>
<file>rc/checkbox_unchecked_disabled.png</file>
<file>rc/checkbox_unchecked_focus.png</file>
<file>rc/checkbox_unchecked.png</file>
<file>rc/radio_checked_disabled.png</file>
<file>rc/radio_checked_focus.png</file>
<file>rc/radio_checked.png</file>
<file>rc/radio_unchecked_disabled.png</file>
<file>rc/radio_unchecked_focus.png</file>
<file>rc/radio_unchecked.png</file>
</qresource>
<qresource prefix="qdarkstyle">
<file>style.qss</file>
</qresource>
</RCC>

1268
dist/qt_themes/qdarkstyle/style.qss vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -17,6 +17,7 @@ endif()
# libfmt
add_subdirectory(fmt)
add_library(fmt::fmt ALIAS fmt)
# getopt
if (MSVC)

2
externals/fmt vendored

View File

@@ -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()

View File

@@ -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 {
@@ -42,6 +43,7 @@ namespace Log {
SUB(Service, FS) \
SUB(Service, HID) \
SUB(Service, LM) \
SUB(Service, NFP) \
SUB(Service, NIFM) \
SUB(Service, NS) \
SUB(Service, NVDRV) \
@@ -105,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;
}
@@ -134,15 +131,27 @@ 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 LogMessage(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);
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -4,6 +4,7 @@
#pragma once
#include <fmt/format.h>
#include "common/common_types.h"
namespace Log {
@@ -59,6 +60,7 @@ enum class Class : ClassType {
Service_FS, ///< The FS (Filesystem) service
Service_HID, ///< The HID (Human interface device) service
Service_LM, ///< The LM (Logger) service
Service_NFP, ///< The NFP service
Service_NIFM, ///< The NIFM (Network interface) service
Service_NS, ///< The NS services
Service_NVDRV, ///< The NVDRV (Nvidia driver) service
@@ -90,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_
@@ -102,6 +104,16 @@ void LogMessage(Class log_class, Level log_level, const char* filename, unsigned
#endif
;
/// Logs a message to the global logger, using fmt
void LogMessage(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) {
LogMessage(log_class, log_level, filename, line_num, function, format, fmt::make_args(args...));
}
} // namespace Log
#define LOG_GENERIC(log_class, log_level, ...) \
@@ -124,3 +136,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__)

View File

@@ -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);

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -103,7 +103,19 @@ inline __attribute__((always_inline)) u64 swap64(u64 _data) {
return __builtin_bswap64(_data);
}
#elif defined(__Bitrig__) || defined(__OpenBSD__)
// swap16, swap32, swap64 are left as is
// redefine swap16, swap32, swap64 as inline functions
#undef swap16
#undef swap32
#undef swap64
inline u16 swap16(u16 _data) {
return __swap16(_data);
}
inline u32 swap32(u32 _data) {
return __swap32(_data);
}
inline u64 swap64(u64 _data) {
return __swap64(_data);
}
#elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__)
inline u16 swap16(u16 _data) {
return bswap16(_data);

View File

@@ -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.)

View File

@@ -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
@@ -142,6 +144,10 @@ add_library(core STATIC
hle/service/nifm/nifm_s.h
hle/service/nifm/nifm_u.cpp
hle/service/nifm/nifm_u.h
hle/service/nfp/nfp.cpp
hle/service/nfp/nfp.h
hle/service/nfp/nfp_user.cpp
hle/service/nfp/nfp_user.h
hle/service/ns/ns.cpp
hle/service/ns/ns.h
hle/service/ns/pl_u.cpp

View File

@@ -174,8 +174,9 @@ u64 Disk_Storage::GetSize() const {
}
bool Disk_Storage::SetSize(const u64 size) const {
LOG_WARNING(Service_FS, "(STUBBED) called");
return false;
file->Resize(size);
file->Flush();
return true;
}
Disk_Directory::Disk_Directory(const std::string& path) : directory() {

View File

@@ -268,8 +268,11 @@ std::vector<u8> HLERequestContext::ReadBuffer() const {
size_t HLERequestContext::WriteBuffer(const void* buffer, size_t size) const {
const bool is_buffer_b{BufferDescriptorB().size() && BufferDescriptorB()[0].Size()};
ASSERT_MSG(size <= GetWriteBufferSize(), "Size %lx is too big", size);
const size_t buffer_size{GetWriteBufferSize()};
if (size > buffer_size) {
LOG_CRITICAL(Core, "size (%016zx) is greater than buffer_size (%016zx)", size, buffer_size);
size = buffer_size; // TODO(bunnei): This needs to be HW tested
}
if (is_buffer_b) {
Memory::WriteBlock(BufferDescriptorB()[0].Address(), buffer, size);

View File

@@ -121,8 +121,9 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) {
// TODO(bunnei): This is heap area that should be allocated by the kernel and not mapped as part
// of the user address space.
vm_manager
.MapMemoryBlock(Memory::STACK_VADDR, std::make_shared<std::vector<u8>>(stack_size, 0), 0,
stack_size, MemoryState::Mapped)
.MapMemoryBlock(Memory::STACK_AREA_VADDR_END - stack_size,
std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size,
MemoryState::Mapped)
.Unwrap();
misc_memory_used += stack_size;
memory_region->used += stack_size;

View File

@@ -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) {

View File

@@ -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);
@@ -756,8 +768,16 @@ static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32
return RESULT_SUCCESS;
}
static ResultCode SetThreadCoreMask(u64, u64, u64) {
LOG_WARNING(Kernel_SVC, "(STUBBED) called");
static ResultCode GetThreadCoreMask(Handle handle, u32* mask, u64* unknown) {
LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x%08X", handle);
*mask = 0x0;
*unknown = 0xf;
return RESULT_SUCCESS;
}
static ResultCode SetThreadCoreMask(Handle handle, u32 mask, u64 unknown) {
LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x%08X, mask=0x%08X, unknown=0x%lx", handle,
mask, unknown);
return RESULT_SUCCESS;
}
@@ -809,7 +829,7 @@ static const FunctionDef SVC_Table[] = {
{0x0B, SvcWrap<SleepThread>, "SleepThread"},
{0x0C, SvcWrap<GetThreadPriority>, "GetThreadPriority"},
{0x0D, SvcWrap<SetThreadPriority>, "SetThreadPriority"},
{0x0E, nullptr, "GetThreadCoreMask"},
{0x0E, SvcWrap<GetThreadCoreMask>, "GetThreadCoreMask"},
{0x0F, SvcWrap<SetThreadCoreMask>, "SetThreadCoreMask"},
{0x10, SvcWrap<GetCurrentProcessorNumber>, "GetCurrentProcessorNumber"},
{0x11, nullptr, "SignalEvent"},
@@ -845,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"},

View File

@@ -70,6 +70,26 @@ 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);
}
template <ResultCode func(u32, u32*, u64*)>
void SvcWrap() {
u32 param_1 = 0;
u64 param_2 = 0;
ResultCode retval = func((u32)(PARAM(2) & 0xFFFFFFFF), &param_1, &param_2);
Core::CPU().SetReg(1, param_1);
Core::CPU().SetReg(2, param_2);
FuncReturn(retval.raw);
}
template <ResultCode func(u64, u64, u32, u32)>
void SvcWrap() {
FuncReturn(

View File

@@ -342,7 +342,7 @@ SharedPtr<Thread> SetupMainThread(VAddr entry_point, u32 priority,
// Initialize new "main" thread
auto thread_res = Thread::Create("main", entry_point, priority, 0, THREADPROCESSORID_0,
Memory::STACK_VADDR_END, owner_process);
Memory::STACK_AREA_VADDR_END, owner_process);
SharedPtr<Thread> thread = std::move(thread_res).Unwrap();

View File

@@ -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");

View File

@@ -59,12 +59,12 @@ private:
AudioRendererResponseData response_data{};
response_data.section_0_size =
response_data.state_entries.size() * sizeof(AudioRendererStateEntry);
response_data.section_1_size = response_data.section_1.size();
response_data.section_2_size = response_data.section_2.size();
response_data.section_3_size = response_data.section_3.size();
response_data.section_4_size = response_data.section_4.size();
response_data.section_5_size = response_data.section_5.size();
static_cast<u32>(response_data.state_entries.size() * sizeof(AudioRendererStateEntry));
response_data.section_1_size = static_cast<u32>(response_data.section_1.size());
response_data.section_2_size = static_cast<u32>(response_data.section_2.size());
response_data.section_3_size = static_cast<u32>(response_data.section_3.size());
response_data.section_4_size = static_cast<u32>(response_data.section_4.size());
response_data.section_5_size = static_cast<u32>(response_data.section_5.size());
response_data.total_size = sizeof(AudioRendererResponseData);
for (unsigned i = 0; i < response_data.state_entries.size(); i++) {
@@ -156,7 +156,17 @@ public:
IAudioDevice() : ServiceFramework("IAudioDevice") {
static const FunctionInfo functions[] = {
{0x0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"},
{0x1, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolume"}};
{0x1, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolume"},
{0x2, nullptr, "GetAudioDeviceOutputVolume"},
{0x3, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceName"},
{0x4, &IAudioDevice::QueryAudioDeviceSystemEvent, "QueryAudioDeviceSystemEvent"},
{0x5, &IAudioDevice::GetActiveChannelCount, "GetActiveChannelCount"},
{0x6, nullptr, "ListAudioDeviceNameAuto"},
{0x7, nullptr, "SetAudioDeviceOutputVolumeAuto"},
{0x8, nullptr, "GetAudioDeviceOutputVolumeAuto"},
{0x10, nullptr, "GetActiveAudioDeviceNameAuto"},
{0x11, nullptr, "QueryAudioDeviceInputEvent"},
{0x12, nullptr, "QueryAudioDeviceOutputEvent"}};
RegisterHandlers(functions);
buffer_event =
@@ -189,8 +199,38 @@ 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");
buffer_event->Signal();
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(buffer_event);
}
void GetActiveChannelCount(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(1);
}
Kernel::SharedPtr<Kernel::Event> buffer_event;
};
}; // namespace Audio
AudRenU::AudRenU() : ServiceFramework("audren:u") {
static const FunctionInfo functions[] = {

View File

@@ -72,8 +72,8 @@ public:
explicit IFile(std::unique_ptr<FileSys::StorageBackend>&& backend)
: ServiceFramework("IFile"), backend(std::move(backend)) {
static const FunctionInfo functions[] = {
{0, &IFile::Read, "Read"}, {1, &IFile::Write, "Write"}, {2, nullptr, "Flush"},
{3, nullptr, "SetSize"}, {4, nullptr, "GetSize"},
{0, &IFile::Read, "Read"}, {1, &IFile::Write, "Write"}, {2, nullptr, "Flush"},
{3, &IFile::SetSize, "SetSize"}, {4, &IFile::GetSize, "GetSize"},
};
RegisterHandlers(functions);
}
@@ -150,6 +150,25 @@ private:
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void SetSize(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 size = rp.Pop<u64>();
backend->SetSize(size);
LOG_DEBUG(Service_FS, "called, size=%" PRIu64, size);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void GetSize(Kernel::HLERequestContext& ctx) {
const u64 size = backend->GetSize();
LOG_DEBUG(Service_FS, "called, size=%" PRIu64, size);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(size);
}
};
class IDirectory final : public ServiceFramework<IDirectory> {

View File

@@ -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

View 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

View 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

View File

@@ -65,13 +65,14 @@ private:
}
void UpdatePadCallback(u64 userdata, int cycles_late) {
SharedMemory* mem = reinterpret_cast<SharedMemory*>(shared_mem->GetPointer());
SharedMemory mem{};
std::memcpy(&mem, shared_mem->GetPointer(), sizeof(SharedMemory));
if (is_device_reload_pending.exchange(false))
LoadInputDevices();
// Set up controllers as neon red+blue Joy-Con attached to console
ControllerHeader& controller_header = mem->controllers[Controller_Handheld].header;
ControllerHeader& controller_header = mem.controllers[Controller_Handheld].header;
controller_header.type = ControllerType_Handheld | ControllerType_JoyconPair;
controller_header.single_colors_descriptor = ColorDesc_ColorsNonexistent;
controller_header.right_color_body = JOYCON_BODY_NEON_RED;
@@ -79,8 +80,8 @@ private:
controller_header.left_color_body = JOYCON_BODY_NEON_BLUE;
controller_header.left_color_buttons = JOYCON_BUTTONS_NEON_BLUE;
for (int layoutIdx = 0; layoutIdx < HID_NUM_LAYOUTS; layoutIdx++) {
ControllerLayout& layout = mem->controllers[Controller_Handheld].layouts[layoutIdx];
for (int index = 0; index < HID_NUM_LAYOUTS; index++) {
ControllerLayout& layout = mem.controllers[Controller_Handheld].layouts[index];
layout.header.num_entries = HID_NUM_ENTRIES;
layout.header.max_entry_index = HID_NUM_ENTRIES - 1;
@@ -136,10 +137,25 @@ private:
// layouts)
}
// TODO(shinyquagsire23): Update touch info
// TODO(bunnei): Properly implement the touch screen, the below will just write empty data
TouchScreen& touchscreen = mem.touchscreen;
const u64 last_entry = touchscreen.header.latest_entry;
const u64 curr_entry = (last_entry + 1) % touchscreen.entries.size();
const u64 timestamp = CoreTiming::GetTicks();
const u64 sample_counter = touchscreen.entries[last_entry].header.timestamp + 1;
touchscreen.header.timestamp_ticks = timestamp;
touchscreen.header.num_entries = touchscreen.entries.size();
touchscreen.header.latest_entry = curr_entry;
touchscreen.header.max_entry_index = touchscreen.entries.size();
touchscreen.header.timestamp = timestamp;
touchscreen.entries[curr_entry].header.timestamp = sample_counter;
touchscreen.entries[curr_entry].header.num_touches = 0;
// TODO(shinyquagsire23): Signal events
std::memcpy(shared_mem->GetPointer(), &mem, sizeof(SharedMemory));
// Reschedule recurrent event
CoreTiming::ScheduleEvent(pad_update_ticks - cycles_late, pad_update_event);
}
@@ -185,6 +201,7 @@ public:
{66, &Hid::StartSixAxisSensor, "StartSixAxisSensor"},
{79, &Hid::SetGyroscopeZeroDriftMode, "SetGyroscopeZeroDriftMode"},
{100, &Hid::SetSupportedNpadStyleSet, "SetSupportedNpadStyleSet"},
{101, &Hid::GetSupportedNpadStyleSet, "GetSupportedNpadStyleSet"},
{102, &Hid::SetSupportedNpadIdType, "SetSupportedNpadIdType"},
{103, &Hid::ActivateNpad, "ActivateNpad"},
{106, &Hid::AcquireNpadStyleSetUpdateEventHandle,
@@ -265,6 +282,13 @@ private:
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0);
LOG_WARNING(Service_HID, "(STUBBED) called");
}
void SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);

View File

@@ -0,0 +1,28 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/logging/log.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/service/nfp/nfp.h"
#include "core/hle/service/nfp/nfp_user.h"
namespace Service {
namespace 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) {
LOG_WARNING(Service_NFP, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void InstallInterfaces(SM::ServiceManager& service_manager) {
auto module = std::make_shared<Module>();
std::make_shared<NFP_User>(module)->InstallAsService(service_manager);
}
} // namespace NFP
} // namespace Service

View File

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

View 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/nfp/nfp_user.h"
namespace Service {
namespace 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"},
};
RegisterHandlers(functions);
}
} // namespace NFP
} // namespace Service

View 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/nfp/nfp.h"
namespace Service {
namespace NFP {
class NFP_User final : public Module::Interface {
public:
explicit NFP_User(std::shared_ptr<Module> module);
};
} // namespace NFP
} // namespace Service

View File

@@ -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");

View File

@@ -25,6 +25,7 @@
#include "core/hle/service/friend/friend.h"
#include "core/hle/service/hid/hid.h"
#include "core/hle/service/lm/lm.h"
#include "core/hle/service/nfp/nfp.h"
#include "core/hle/service/nifm/nifm.h"
#include "core/hle/service/ns/ns.h"
#include "core/hle/service/nvdrv/nvdrv.h"
@@ -111,15 +112,15 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(Kernel::HLERequestContext
auto cmd_buf = ctx.CommandBuffer();
std::string function_name = info == nullptr ? fmt::format("{}", ctx.GetCommand()) : info->name;
fmt::MemoryWriter w;
w.write("function '{}': port='{}' cmd_buf={{[0]={:#x}", function_name, service_name,
cmd_buf[0]);
fmt::memory_buffer buf;
fmt::format_to(buf, "function '{}': port='{}' cmd_buf={{[0]={:#x}", function_name, service_name,
cmd_buf[0]);
for (int i = 1; i <= 8; ++i) {
w.write(", [{}]={:#x}", i, cmd_buf[i]);
fmt::format_to(buf, ", [{}]={:#x}", i, cmd_buf[i]);
}
w << '}';
buf.push_back('}');
LOG_ERROR(Service, "unknown / unimplemented %s", w.c_str());
LOG_ERROR(Service, "unknown / unimplemented %s", fmt::to_string(buf).c_str());
UNIMPLEMENTED();
}
@@ -187,6 +188,7 @@ void Init() {
Friend::InstallInterfaces(*SM::g_service_manager);
HID::InstallInterfaces(*SM::g_service_manager);
LM::InstallInterfaces(*SM::g_service_manager);
NFP::InstallInterfaces(*SM::g_service_manager);
NIFM::InstallInterfaces(*SM::g_service_manager);
NS::InstallInterfaces(*SM::g_service_manager);
Nvidia::InstallInterfaces(*SM::g_service_manager);

View File

@@ -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"},

View File

@@ -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> {

View File

@@ -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;
}

View File

@@ -414,7 +414,7 @@ ResultStatus AppLoader_ELF::Load(Kernel::SharedPtr<Kernel::Process>& process) {
process->resource_limit =
Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
process->Run(codeset->entrypoint, 48, Memory::STACK_SIZE);
process->Run(codeset->entrypoint, 48, Memory::DEFAULT_STACK_SIZE);
is_loaded = true;
return ResultStatus::Success;

View File

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

View File

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

View File

@@ -162,12 +162,13 @@ enum : VAddr {
TLS_AREA_VADDR = NEW_LINEAR_HEAP_VADDR_END,
TLS_ENTRY_SIZE = 0x200,
TLS_AREA_SIZE = 0x10000000,
TLS_ADREA_VADDR_END = TLS_AREA_VADDR + TLS_AREA_SIZE,
TLS_AREA_VADDR_END = TLS_AREA_VADDR + TLS_AREA_SIZE,
/// Application stack
STACK_VADDR = TLS_ADREA_VADDR_END,
STACK_SIZE = 0x10000,
STACK_VADDR_END = STACK_VADDR + STACK_SIZE,
STACK_AREA_VADDR = TLS_AREA_VADDR_END,
STACK_AREA_SIZE = 0x10000000,
STACK_AREA_VADDR_END = STACK_AREA_VADDR + STACK_AREA_SIZE,
DEFAULT_STACK_SIZE = 0x100000,
/// Application heap
/// Size is confirmed to be a static value on fw 3.0.0

View File

@@ -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>();
}

View File

@@ -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
*/

View File

@@ -11,6 +11,8 @@ add_library(video_core STATIC
engines/maxwell_compute.h
gpu.cpp
gpu.h
macro_interpreter.cpp
macro_interpreter.h
memory_manager.cpp
memory_manager.h
rasterizer_interface.h

View File

@@ -19,35 +19,21 @@ namespace Engines {
/// First register id that is actually a Macro call.
constexpr u32 MacroRegistersStart = 0xE00;
const std::unordered_map<u32, Maxwell3D::MethodInfo> Maxwell3D::method_handlers = {
{0xE1A, {"BindTextureInfoBuffer", 1, &Maxwell3D::BindTextureInfoBuffer}},
{0xE24, {"SetShader", 5, &Maxwell3D::SetShader}},
{0xE2A, {"BindStorageBuffer", 1, &Maxwell3D::BindStorageBuffer}},
};
Maxwell3D::Maxwell3D(MemoryManager& memory_manager) : memory_manager(memory_manager) {}
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, const std::vector<u32>& parameters) {
// TODO(Subv): Write an interpreter for the macros uploaded via registers 0x45 and 0x47
void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) {
auto macro_code = uploaded_macros.find(method);
// The requested macro must have been uploaded already.
ASSERT_MSG(uploaded_macros.find(method) != uploaded_macros.end(), "Macro %08X was not uploaded",
method);
ASSERT_MSG(macro_code != uploaded_macros.end(), "Macro %08X was not uploaded", method);
auto itr = method_handlers.find(method);
ASSERT_MSG(itr != method_handlers.end(), "Unhandled method call %08X", method);
ASSERT(itr->second.arguments == parameters.size());
(this->*itr->second.handler)(parameters);
// Reset the current macro and its parameters.
// Reset the current macro and execute it.
executing_macro = 0;
macro_params.clear();
macro_interpreter.Execute(macro_code->second, std::move(parameters));
}
void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
@@ -77,7 +63,7 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
// Call the macro when there are no more parameters in the command buffer
if (remaining_params == 0) {
CallMacroMethod(executing_macro, macro_params);
CallMacroMethod(executing_macro, std::move(macro_params));
}
return;
}
@@ -193,84 +179,6 @@ void Maxwell3D::DrawArrays() {
VideoCore::g_renderer->Rasterizer()->AccelerateDrawBatch(false /*is_indexed*/);
}
void Maxwell3D::BindTextureInfoBuffer(const std::vector<u32>& parameters) {
/**
* Parameters description:
* [0] = Shader stage, usually 4 for FragmentShader
*/
u32 stage = parameters[0];
// Perform the same operations as the real macro code.
GPUVAddr address = static_cast<GPUVAddr>(regs.tex_info_buffers.address[stage]) << 8;
u32 size = regs.tex_info_buffers.size[stage];
regs.const_buffer.cb_size = size;
regs.const_buffer.cb_address_high = address >> 32;
regs.const_buffer.cb_address_low = address & 0xFFFFFFFF;
}
void Maxwell3D::SetShader(const std::vector<u32>& parameters) {
/**
* Parameters description:
* [0] = Shader Program.
* [1] = Unknown, presumably the shader id.
* [2] = Offset to the start of the shader, after the 0x30 bytes header.
* [3] = Shader Stage.
* [4] = Const Buffer Address >> 8.
*/
auto shader_program = static_cast<Regs::ShaderProgram>(parameters[0]);
// TODO(Subv): This address is probably an offset from the CODE_ADDRESS register.
GPUVAddr address = parameters[2];
auto shader_stage = static_cast<Regs::ShaderStage>(parameters[3]);
GPUVAddr cb_address = parameters[4] << 8;
auto& shader = state.shader_programs[static_cast<size_t>(shader_program)];
shader.program = shader_program;
shader.stage = shader_stage;
shader.address = address;
// Perform the same operations as the real macro code.
// TODO(Subv): Early exit if register 0xD1C + shader_program contains the same as params[1].
auto& shader_regs = regs.shader_config[static_cast<size_t>(shader_program)];
shader_regs.start_id = address;
// TODO(Subv): Write params[1] to register 0xD1C + shader_program.
// TODO(Subv): Write params[2] to register 0xD22 + shader_program.
// Note: This value is hardcoded in the macro's code.
static constexpr u32 DefaultCBSize = 0x10000;
regs.const_buffer.cb_size = DefaultCBSize;
regs.const_buffer.cb_address_high = cb_address >> 32;
regs.const_buffer.cb_address_low = cb_address & 0xFFFFFFFF;
// Write a hardcoded 0x11 to CB_BIND, this binds the current const buffer to buffer c1[] in the
// shader. It's likely that these are the constants for the shader.
regs.cb_bind[static_cast<size_t>(shader_stage)].valid.Assign(1);
regs.cb_bind[static_cast<size_t>(shader_stage)].index.Assign(1);
ProcessCBBind(shader_stage);
}
void Maxwell3D::BindStorageBuffer(const std::vector<u32>& parameters) {
/**
* Parameters description:
* [0] = Buffer offset >> 2
*/
u32 buffer_offset = parameters[0] << 2;
// Perform the same operations as the real macro code.
// Note: This value is hardcoded in the macro's code.
static constexpr u32 DefaultCBSize = 0x5F00;
regs.const_buffer.cb_size = DefaultCBSize;
GPUVAddr address = regs.ssbo_info.BufferAddress();
regs.const_buffer.cb_address_high = address >> 32;
regs.const_buffer.cb_address_low = address & 0xFFFFFFFF;
regs.const_buffer.cb_pos = buffer_offset;
}
void Maxwell3D::ProcessCBBind(Regs::ShaderStage stage) {
// Bind the buffer currently in CB_ADDRESS to the specified index in the desired shader stage.
auto& shader = state.shader_stages[static_cast<size_t>(stage)];
@@ -386,5 +294,10 @@ std::vector<Texture::FullTextureInfo> Maxwell3D::GetStageTextures(Regs::ShaderSt
return textures;
}
u32 Maxwell3D::GetRegisterValue(u32 method) const {
ASSERT_MSG(method < Regs::NUM_REGS, "Invalid Maxwell3D register");
return regs.reg_array[method];
}
} // namespace Engines
} // namespace Tegra

View File

@@ -13,6 +13,7 @@
#include "common/common_types.h"
#include "common/math_util.h"
#include "video_core/gpu.h"
#include "video_core/macro_interpreter.h"
#include "video_core/memory_manager.h"
#include "video_core/textures/texture.h"
@@ -498,22 +499,18 @@ public:
bool enabled;
};
struct ShaderProgramInfo {
Regs::ShaderStage stage;
Regs::ShaderProgram program;
GPUVAddr address;
};
struct ShaderStageInfo {
std::array<ConstBufferInfo, Regs::MaxConstBuffers> const_buffers;
};
std::array<ShaderStageInfo, Regs::MaxShaderStage> shader_stages;
std::array<ShaderProgramInfo, Regs::MaxShaderProgram> shader_programs;
};
State state{};
/// Reads a register value located at the input method address
u32 GetRegisterValue(u32 method) const;
/// Write the value to the register identified by method.
void WriteReg(u32 method, u32 value, u32 remaining_params);
@@ -533,6 +530,9 @@ private:
/// Parameters that have been submitted to the macro call so far.
std::vector<u32> macro_params;
/// Interpreter for the macro codes uploaded to the GPU.
MacroInterpreter macro_interpreter;
/// Retrieves information about a specific TIC entry from the TIC buffer.
Texture::TICEntry GetTICEntry(u32 tic_index) const;
@@ -544,7 +544,7 @@ private:
* @param method Method to call
* @param parameters Arguments to the method call
*/
void CallMacroMethod(u32 method, const std::vector<u32>& parameters);
void CallMacroMethod(u32 method, std::vector<u32> parameters);
/// Handles a write to the QUERY_GET register.
void ProcessQueryGet();
@@ -557,19 +557,6 @@ private:
/// Handles a write to the VERTEX_END_GL register, triggering a draw.
void DrawArrays();
/// Method call handlers
void BindTextureInfoBuffer(const std::vector<u32>& parameters);
void SetShader(const std::vector<u32>& parameters);
void BindStorageBuffer(const std::vector<u32>& parameters);
struct MethodInfo {
const char* name;
u32 arguments;
void (Maxwell3D::*handler)(const std::vector<u32>& parameters);
};
static const std::unordered_map<u32, MethodInfo> method_handlers;
};
#define ASSERT_REG_POSITION(field_name, position) \

View File

@@ -0,0 +1,257 @@
// Copyright 2018 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/assert.h"
#include "common/logging/log.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/macro_interpreter.h"
namespace Tegra {
MacroInterpreter::MacroInterpreter(Engines::Maxwell3D& maxwell3d) : maxwell3d(maxwell3d) {}
void MacroInterpreter::Execute(const std::vector<u32>& code, std::vector<u32> parameters) {
Reset();
registers[1] = parameters[0];
this->parameters = std::move(parameters);
// Execute the code until we hit an exit condition.
bool keep_executing = true;
while (keep_executing) {
keep_executing = Step(code, false);
}
// Assert the the macro used all the input parameters
ASSERT(next_parameter_index == this->parameters.size());
}
void MacroInterpreter::Reset() {
registers = {};
pc = 0;
delayed_pc = boost::none;
method_address.raw = 0;
parameters.clear();
// The next parameter index starts at 1, because $r1 already has the value of the first
// parameter.
next_parameter_index = 1;
}
bool MacroInterpreter::Step(const std::vector<u32>& code, bool is_delay_slot) {
u32 base_address = pc;
Opcode opcode = GetOpcode(code);
pc += 4;
// Update the program counter if we were delayed
if (delayed_pc != boost::none) {
ASSERT(is_delay_slot);
pc = *delayed_pc;
delayed_pc = boost::none;
}
switch (opcode.operation) {
case Operation::ALU: {
u32 result = GetALUResult(opcode.alu_operation, GetRegister(opcode.src_a),
GetRegister(opcode.src_b));
ProcessResult(opcode.result_operation, opcode.dst, result);
break;
}
case Operation::AddImmediate: {
ProcessResult(opcode.result_operation, opcode.dst,
GetRegister(opcode.src_a) + opcode.immediate);
break;
}
case Operation::ExtractInsert: {
u32 dst = GetRegister(opcode.src_a);
u32 src = GetRegister(opcode.src_b);
src = (src >> opcode.bf_src_bit) & opcode.GetBitfieldMask();
dst &= ~(opcode.GetBitfieldMask() << opcode.bf_dst_bit);
dst |= src << opcode.bf_dst_bit;
ProcessResult(opcode.result_operation, opcode.dst, dst);
break;
}
case Operation::ExtractShiftLeftImmediate: {
u32 dst = GetRegister(opcode.src_a);
u32 src = GetRegister(opcode.src_b);
u32 result = ((src >> dst) & opcode.GetBitfieldMask()) << opcode.bf_dst_bit;
ProcessResult(opcode.result_operation, opcode.dst, result);
break;
}
case Operation::ExtractShiftLeftRegister: {
u32 dst = GetRegister(opcode.src_a);
u32 src = GetRegister(opcode.src_b);
u32 result = ((src >> opcode.bf_src_bit) & opcode.GetBitfieldMask()) << dst;
ProcessResult(opcode.result_operation, opcode.dst, result);
break;
}
case Operation::Read: {
u32 result = Read(GetRegister(opcode.src_a) + opcode.immediate);
ProcessResult(opcode.result_operation, opcode.dst, result);
break;
}
case Operation::Branch: {
ASSERT_MSG(!is_delay_slot, "Executing a branch in a delay slot is not valid");
u32 value = GetRegister(opcode.src_a);
bool taken = EvaluateBranchCondition(opcode.branch_condition, value);
if (taken) {
// Ignore the delay slot if the branch has the annul bit.
if (opcode.branch_annul) {
pc = base_address + (opcode.immediate << 2);
return true;
}
delayed_pc = base_address + (opcode.immediate << 2);
// Execute one more instruction due to the delay slot.
return Step(code, true);
}
break;
}
default:
UNIMPLEMENTED_MSG("Unimplemented macro operation %u",
static_cast<u32>(opcode.operation.Value()));
}
if (opcode.is_exit) {
// Exit has a delay slot, execute the next instruction
// Note: Executing an exit during a branch delay slot will cause the instruction at the
// branch target to be executed before exiting.
Step(code, true);
return false;
}
return true;
}
MacroInterpreter::Opcode MacroInterpreter::GetOpcode(const std::vector<u32>& code) const {
ASSERT((pc % sizeof(u32)) == 0);
ASSERT(pc < code.size() * sizeof(u32));
return {code[pc / sizeof(u32)]};
}
u32 MacroInterpreter::GetALUResult(ALUOperation operation, u32 src_a, u32 src_b) const {
switch (operation) {
case ALUOperation::Add:
return src_a + src_b;
// TODO(Subv): Implement AddWithCarry
case ALUOperation::Subtract:
return src_a - src_b;
// TODO(Subv): Implement SubtractWithBorrow
case ALUOperation::Xor:
return src_a ^ src_b;
case ALUOperation::Or:
return src_a | src_b;
case ALUOperation::And:
return src_a & src_b;
case ALUOperation::AndNot:
return src_a & ~src_b;
case ALUOperation::Nand:
return ~(src_a & src_b);
default:
UNIMPLEMENTED_MSG("Unimplemented ALU operation %u", static_cast<u32>(operation));
}
}
void MacroInterpreter::ProcessResult(ResultOperation operation, u32 reg, u32 result) {
switch (operation) {
case ResultOperation::IgnoreAndFetch:
// Fetch parameter and ignore result.
SetRegister(reg, FetchParameter());
break;
case ResultOperation::Move:
// Move result.
SetRegister(reg, result);
break;
case ResultOperation::MoveAndSetMethod:
// Move result and use as Method Address.
SetRegister(reg, result);
SetMethodAddress(result);
break;
case ResultOperation::FetchAndSend:
// Fetch parameter and send result.
SetRegister(reg, FetchParameter());
Send(result);
break;
case ResultOperation::MoveAndSend:
// Move and send result.
SetRegister(reg, result);
Send(result);
break;
case ResultOperation::FetchAndSetMethod:
// Fetch parameter and use result as Method Address.
SetRegister(reg, FetchParameter());
SetMethodAddress(result);
break;
case ResultOperation::MoveAndSetMethodFetchAndSend:
// Move result and use as Method Address, then fetch and send parameter.
SetRegister(reg, result);
SetMethodAddress(result);
Send(FetchParameter());
break;
case ResultOperation::MoveAndSetMethodSend:
// Move result and use as Method Address, then send bits 12:17 of result.
SetRegister(reg, result);
SetMethodAddress(result);
Send((result >> 12) & 0b111111);
break;
default:
UNIMPLEMENTED_MSG("Unimplemented result operation %u", static_cast<u32>(operation));
}
}
u32 MacroInterpreter::FetchParameter() {
ASSERT(next_parameter_index < parameters.size());
return parameters[next_parameter_index++];
}
u32 MacroInterpreter::GetRegister(u32 register_id) const {
// Register 0 is supposed to always return 0.
if (register_id == 0)
return 0;
ASSERT(register_id < registers.size());
return registers[register_id];
}
void MacroInterpreter::SetRegister(u32 register_id, u32 value) {
// Register 0 is supposed to always return 0. NOP is implemented as a store to the zero
// register.
if (register_id == 0)
return;
ASSERT(register_id < registers.size());
registers[register_id] = value;
}
void MacroInterpreter::SetMethodAddress(u32 address) {
method_address.raw = address;
}
void MacroInterpreter::Send(u32 value) {
maxwell3d.WriteReg(method_address.address, value, 0);
// Increment the method address by the method increment.
method_address.address.Assign(method_address.address.Value() +
method_address.increment.Value());
}
u32 MacroInterpreter::Read(u32 method) const {
return maxwell3d.GetRegisterValue(method);
}
bool MacroInterpreter::EvaluateBranchCondition(BranchCondition cond, u32 value) const {
switch (cond) {
case BranchCondition::Zero:
return value == 0;
case BranchCondition::NotZero:
return value != 0;
}
UNREACHABLE();
}
} // namespace Tegra

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