Compare commits
264 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d993f1b72 | ||
|
|
0d4ca5a8fc | ||
|
|
e1bd89e1c2 | ||
|
|
825a6e2615 | ||
|
|
baf91c920c | ||
|
|
f22f6b72c3 | ||
|
|
27dd542c60 | ||
|
|
5c90d060d8 | ||
|
|
0eb37de98f | ||
|
|
11774308d3 | ||
|
|
7fe52ef77f | ||
|
|
3a63ae0658 | ||
|
|
397f53dea1 | ||
|
|
affee77b70 | ||
|
|
d85ca0ab33 | ||
|
|
151ddcf419 | ||
|
|
224a75d839 | ||
|
|
b03c0536ce | ||
|
|
5b95a01463 | ||
|
|
c19425ed69 | ||
|
|
238c35b2c9 | ||
|
|
defb9642da | ||
|
|
69728e8ad5 | ||
|
|
4c72190a06 | ||
|
|
f1da3ec584 | ||
|
|
cb0a4151f8 | ||
|
|
c2665ec9c2 | ||
|
|
4f7bea403a | ||
|
|
c8f6d9effd | ||
|
|
972485ff18 | ||
|
|
93cac0d294 | ||
|
|
3dc09a6250 | ||
|
|
a2cc80b605 | ||
|
|
552f0ff267 | ||
|
|
2c780db5b9 | ||
|
|
c119473c40 | ||
|
|
2c9879d2eb | ||
|
|
5e2f8e30e7 | ||
|
|
ffe1e2b5ec | ||
|
|
997a802bd6 | ||
|
|
b6c9fba81c | ||
|
|
5300a918c6 | ||
|
|
75795a9a63 | ||
|
|
9bd9980372 | ||
|
|
6286b8dedd | ||
|
|
8ba06aa4e1 | ||
|
|
523a709bf1 | ||
|
|
796b3319e6 | ||
|
|
dd236c6c1d | ||
|
|
10ba8d16be | ||
|
|
7a2f60df26 | ||
|
|
8a6a25e4b6 | ||
|
|
a60f34a850 | ||
|
|
a429644672 | ||
|
|
2694552b7f | ||
|
|
7413b30923 | ||
|
|
d8d392b39a | ||
|
|
60f351084a | ||
|
|
a9e4528d10 | ||
|
|
3f0b7673f0 | ||
|
|
f5cee0e885 | ||
|
|
92c8d783b3 | ||
|
|
cedbe925cd | ||
|
|
e84b760016 | ||
|
|
744b207d92 | ||
|
|
950b6dbc80 | ||
|
|
cf9c94d401 | ||
|
|
46791c464a | ||
|
|
3194f14aca | ||
|
|
8244536f7a | ||
|
|
7617e88fb2 | ||
|
|
c310cef615 | ||
|
|
23c7dda710 | ||
|
|
e6aff11057 | ||
|
|
282adfc70b | ||
|
|
aa41fcc04e | ||
|
|
ac4154bfde | ||
|
|
f8382c9d9d | ||
|
|
6ca8637d4c | ||
|
|
497f593525 | ||
|
|
7981910746 | ||
|
|
dc4415811c | ||
|
|
4afebf26b6 | ||
|
|
5d3b228409 | ||
|
|
5a5c6d4ed8 | ||
|
|
e731c4b991 | ||
|
|
fc37672f26 | ||
|
|
977418c65b | ||
|
|
f66743cd0c | ||
|
|
d4e93cf38c | ||
|
|
bdcedc8506 | ||
|
|
22f4268c2f | ||
|
|
7051dc1902 | ||
|
|
01af036c1f | ||
|
|
63c2635e6f | ||
|
|
dbfbe352e0 | ||
|
|
e5bb5d13c4 | ||
|
|
e70451d967 | ||
|
|
81fa492825 | ||
|
|
bdddbe2daa | ||
|
|
06dea163fa | ||
|
|
bc681dc555 | ||
|
|
9418b983bd | ||
|
|
76d6178e4a | ||
|
|
38c1e77f01 | ||
|
|
b6b2e31e5e | ||
|
|
fc51ece7bf | ||
|
|
98d85cdc20 | ||
|
|
dab450ec46 | ||
|
|
351816ac38 | ||
|
|
acf328a71f | ||
|
|
9f46066bda | ||
|
|
ba9674862d | ||
|
|
ac7ee21331 | ||
|
|
56ea0f8acb | ||
|
|
716d6aee30 | ||
|
|
664fa4ea06 | ||
|
|
f5658a9fda | ||
|
|
edb9cccb36 | ||
|
|
f54d2d3114 | ||
|
|
d787856621 | ||
|
|
9fdfd58f9f | ||
|
|
cdeadd448b | ||
|
|
1c45c8086e | ||
|
|
2fd3b328ae | ||
|
|
230ac6a4e8 | ||
|
|
eae2ed6b07 | ||
|
|
38036eb1c8 | ||
|
|
e8ded20d24 | ||
|
|
53d673a7d3 | ||
|
|
311d2fc768 | ||
|
|
b16c8e0e8d | ||
|
|
7cc46a6faa | ||
|
|
ddafc99776 | ||
|
|
d64edf21bb | ||
|
|
5afc397d52 | ||
|
|
6442e02c5d | ||
|
|
8e6e55d6f8 | ||
|
|
464bd5fad7 | ||
|
|
86b1f15d9a | ||
|
|
52acb7f9a0 | ||
|
|
d91a880f11 | ||
|
|
71cc772988 | ||
|
|
f91046bf8d | ||
|
|
a7131af7d6 | ||
|
|
8baf98e439 | ||
|
|
c5afe93dcc | ||
|
|
4373fa8042 | ||
|
|
4dfd5c84ea | ||
|
|
380fc8d2e1 | ||
|
|
c51dbf8038 | ||
|
|
41905ee467 | ||
|
|
35145bd529 | ||
|
|
27cbb75e7c | ||
|
|
42cb8f1124 | ||
|
|
9b8fb3c756 | ||
|
|
d71d7d917e | ||
|
|
134f3ff9b4 | ||
|
|
3287b1247d | ||
|
|
240d45830d | ||
|
|
3377b78ea7 | ||
|
|
801fd04f75 | ||
|
|
e183820956 | ||
|
|
70a31eda62 | ||
|
|
5ed377b989 | ||
|
|
e7d97605e8 | ||
|
|
835a3d09c6 | ||
|
|
731a9a322e | ||
|
|
d3dc4e399c | ||
|
|
69c7a01f88 | ||
|
|
62560f1e63 | ||
|
|
afebdda203 | ||
|
|
4bc4851d45 | ||
|
|
47459f6a36 | ||
|
|
2fae1e6205 | ||
|
|
b67360c0f8 | ||
|
|
8d5bdcb17b | ||
|
|
c320702092 | ||
|
|
ae6189d7c2 | ||
|
|
7acebd7eb6 | ||
|
|
8e9f23f393 | ||
|
|
4d711dface | ||
|
|
3dcaa84ba4 | ||
|
|
666d431ad8 | ||
|
|
244fe13219 | ||
|
|
b30b1f741d | ||
|
|
829f424618 | ||
|
|
a166217480 | ||
|
|
753bc2026f | ||
|
|
54681909be | ||
|
|
00607fe1e0 | ||
|
|
325977c0c6 | ||
|
|
70ff82f72d | ||
|
|
96a4abe12d | ||
|
|
93547cac68 | ||
|
|
911c56ccef | ||
|
|
465ba30d08 | ||
|
|
e24197bb3f | ||
|
|
00e9ba0603 | ||
|
|
f159a12820 | ||
|
|
3a10016e38 | ||
|
|
4dcca90ef4 | ||
|
|
e22816a5bb | ||
|
|
daae6a323b | ||
|
|
38fe070d78 | ||
|
|
ca2d228c9d | ||
|
|
c21dc36cda | ||
|
|
95b804ff05 | ||
|
|
448856695a | ||
|
|
825d629565 | ||
|
|
fce33adcf1 | ||
|
|
e891ff9a0c | ||
|
|
8357908099 | ||
|
|
503ebe9b96 | ||
|
|
e4bc3c3342 | ||
|
|
eb5861e0a2 | ||
|
|
b1acb4f73f | ||
|
|
b1061afed9 | ||
|
|
e612242977 | ||
|
|
978172530e | ||
|
|
120f688272 | ||
|
|
e1932351a9 | ||
|
|
66a8a3e887 | ||
|
|
0528be5c92 | ||
|
|
e8efd5a901 | ||
|
|
bd8b9bbcee | ||
|
|
22e825a3bc | ||
|
|
c281173df6 | ||
|
|
1aa75b1081 | ||
|
|
59d0d34dce | ||
|
|
84e9f9f395 | ||
|
|
16cfbb068c | ||
|
|
662feb8c1c | ||
|
|
e4f9ce0379 | ||
|
|
aa6fe3f1aa | ||
|
|
49eff536d0 | ||
|
|
4a8fe67964 | ||
|
|
0361aa1915 | ||
|
|
fa1d625eed | ||
|
|
1e84d22275 | ||
|
|
002d9508a0 | ||
|
|
67e7186d79 | ||
|
|
fc205a1bc5 | ||
|
|
2cdda8c564 | ||
|
|
dba112e510 | ||
|
|
c083ea7d78 | ||
|
|
6fc485a607 | ||
|
|
64facb403e | ||
|
|
08c638f249 | ||
|
|
dfa2e336ba | ||
|
|
6af8ff24c9 | ||
|
|
85a4222a8c | ||
|
|
ca7618684c | ||
|
|
1326e326f5 | ||
|
|
6c0c2dfabc | ||
|
|
1c385362f5 | ||
|
|
7ee6065178 | ||
|
|
0aaa69e4d7 | ||
|
|
f3d4d4eaa8 | ||
|
|
7cbe6748c3 | ||
|
|
1e9213632a | ||
|
|
1dda77d392 | ||
|
|
e2dd59e341 | ||
|
|
1989e1b9ac |
@@ -6,9 +6,9 @@ function(copy_yuzu_Qt5_deps target_dir)
|
||||
set(Qt5_STYLES_DIR "${Qt5_DIR}/../../../plugins/styles/")
|
||||
set(Qt5_IMAGEFORMATS_DIR "${Qt5_DIR}/../../../plugins/imageformats/")
|
||||
set(Qt5_RESOURCES_DIR "${Qt5_DIR}/../../../resources/")
|
||||
set(PLATFORMS ${DLL_DEST}platforms/)
|
||||
set(STYLES ${DLL_DEST}styles/)
|
||||
set(IMAGEFORMATS ${DLL_DEST}imageformats/)
|
||||
set(PLATFORMS ${DLL_DEST}plugins/platforms/)
|
||||
set(STYLES ${DLL_DEST}plugins/styles/)
|
||||
set(IMAGEFORMATS ${DLL_DEST}plugins/imageformats/)
|
||||
windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST}
|
||||
icudt*.dll
|
||||
icuin*.dll
|
||||
@@ -42,11 +42,15 @@ function(copy_yuzu_Qt5_deps target_dir)
|
||||
icudtl.dat
|
||||
)
|
||||
endif ()
|
||||
|
||||
windows_copy_files(yuzu ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.*)
|
||||
windows_copy_files(yuzu ${Qt5_STYLES_DIR} ${STYLES} qwindowsvistastyle$<$<CONFIG:Debug>:d>.*)
|
||||
windows_copy_files(yuzu ${Qt5_IMAGEFORMATS_DIR} ${IMAGEFORMATS}
|
||||
qjpeg$<$<CONFIG:Debug>:d>.*
|
||||
qgif$<$<CONFIG:Debug>:d>.*
|
||||
)
|
||||
# Create an empty qt.conf file. Qt will detect that this file exists, and use the folder that its in as the root folder.
|
||||
# This way it'll look for plugins in the root/plugins/ folder
|
||||
add_custom_command(TARGET yuzu POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E touch ${DLL_DEST}qt.conf
|
||||
)
|
||||
endfunction(copy_yuzu_Qt5_deps)
|
||||
|
||||
@@ -57,8 +57,6 @@ set(HASH_FILES
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_shader_decompiler.h"
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_shader_disk_cache.cpp"
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_shader_disk_cache.h"
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_shader_gen.cpp"
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_shader_gen.h"
|
||||
"${VIDEO_CORE}/shader/decode/arithmetic.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/arithmetic_half.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/arithmetic_half_immediate.cpp"
|
||||
@@ -91,8 +89,6 @@ set(HASH_FILES
|
||||
"${VIDEO_CORE}/shader/ast.h"
|
||||
"${VIDEO_CORE}/shader/compiler_settings.cpp"
|
||||
"${VIDEO_CORE}/shader/compiler_settings.h"
|
||||
"${VIDEO_CORE}/shader/const_buffer_locker.cpp"
|
||||
"${VIDEO_CORE}/shader/const_buffer_locker.h"
|
||||
"${VIDEO_CORE}/shader/control_flow.cpp"
|
||||
"${VIDEO_CORE}/shader/control_flow.h"
|
||||
"${VIDEO_CORE}/shader/decode.cpp"
|
||||
@@ -101,9 +97,13 @@ set(HASH_FILES
|
||||
"${VIDEO_CORE}/shader/node.h"
|
||||
"${VIDEO_CORE}/shader/node_helper.cpp"
|
||||
"${VIDEO_CORE}/shader/node_helper.h"
|
||||
"${VIDEO_CORE}/shader/registry.cpp"
|
||||
"${VIDEO_CORE}/shader/registry.h"
|
||||
"${VIDEO_CORE}/shader/shader_ir.cpp"
|
||||
"${VIDEO_CORE}/shader/shader_ir.h"
|
||||
"${VIDEO_CORE}/shader/track.cpp"
|
||||
"${VIDEO_CORE}/shader/transform_feedback.cpp"
|
||||
"${VIDEO_CORE}/shader/transform_feedback.h"
|
||||
)
|
||||
set(COMBINED "")
|
||||
foreach (F IN LISTS HASH_FILES)
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
yuzu emulator
|
||||
=============
|
||||
[](https://travis-ci.org/yuzu-emu/yuzu)
|
||||
[](https://travis-ci.com/yuzu-emu/yuzu)
|
||||
[](https://dev.azure.com/yuzu-emu/yuzu/)
|
||||
[](https://discord.gg/XQV6dn9)
|
||||
|
||||
yuzu is an experimental open-source emulator for the Nintendo Switch from the creators of [Citra](https://citra-emu.org/).
|
||||
|
||||
@@ -21,7 +22,7 @@ For development discussion, please join us on [Discord](https://discord.gg/XQV6d
|
||||
|
||||
Most of the development happens on GitHub. It's also where [our central repository](https://github.com/yuzu-emu/yuzu) is hosted.
|
||||
|
||||
If you want to contribute please take a look at the [Contributor's Guide](CONTRIBUTING.md) and [Developer Information](https://github.com/yuzu-emu/yuzu/wiki/Developer-Information). You should as well contact any of the developers on Discord in order to know about the current state of the emulator.
|
||||
If you want to contribute please take a look at the [Contributor's Guide](https://github.com/yuzu-emu/yuzu/wiki/Contributing) and [Developer Information](https://github.com/yuzu-emu/yuzu/wiki/Developer-Information). You should also contact any of the developers on Discord in order to know about the current state of the emulator.
|
||||
|
||||
### Building
|
||||
|
||||
|
||||
6
dist/license.md
vendored
6
dist/license.md
vendored
@@ -2,8 +2,8 @@ The icons in this folder and its subfolders have the following licenses:
|
||||
|
||||
Icon Name | License | Origin/Author
|
||||
--- | --- | ---
|
||||
qt_themes/default/icons/16x16/checked.png | Free for non-commercial use
|
||||
qt_themes/default/icons/16x16/failed.png | Free for non-commercial use
|
||||
qt_themes/default/icons/16x16/checked.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/default/icons/16x16/failed.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/default/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/default/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/default/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||
@@ -11,8 +11,6 @@ qt_themes/default/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/default/icons/48x48/folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/default/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team
|
||||
qt_themes/default/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/qdarkstyle/icons/16x16/checked.png | Free for non-commercial use
|
||||
qt_themes/qdarkstyle/icons/16x16/failed.png | Free for non-commercial use
|
||||
qt_themes/qdarkstyle/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/qdarkstyle/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/qdarkstyle/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||
|
||||
BIN
dist/qt_themes/default/icons/16x16/checked.png
vendored
BIN
dist/qt_themes/default/icons/16x16/checked.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 451 B After Width: | Height: | Size: 657 B |
BIN
dist/qt_themes/default/icons/16x16/failed.png
vendored
BIN
dist/qt_themes/default/icons/16x16/failed.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 428 B After Width: | Height: | Size: 524 B |
7
externals/microprofile/microprofile.h
vendored
7
externals/microprofile/microprofile.h
vendored
@@ -243,6 +243,7 @@ typedef uint32_t ThreadIdType;
|
||||
#define MICROPROFILE_DEFINE_GPU(var, name, color) MicroProfileToken g_mp_##var = MicroProfileGetToken("GPU", name, color, MicroProfileTokenTypeGpu)
|
||||
#define MICROPROFILE_TOKEN_PASTE0(a, b) a ## b
|
||||
#define MICROPROFILE_TOKEN_PASTE(a, b) MICROPROFILE_TOKEN_PASTE0(a,b)
|
||||
#define MICROPROFILE_TOKEN(var) g_mp_##var
|
||||
#define MICROPROFILE_SCOPE(var) MicroProfileScopeHandler MICROPROFILE_TOKEN_PASTE(foo, __LINE__)(g_mp_##var)
|
||||
#define MICROPROFILE_SCOPE_TOKEN(token) MicroProfileScopeHandler MICROPROFILE_TOKEN_PASTE(foo, __LINE__)(token)
|
||||
#define MICROPROFILE_SCOPEI(group, name, color) static MicroProfileToken MICROPROFILE_TOKEN_PASTE(g_mp,__LINE__) = MicroProfileGetToken(group, name, color, MicroProfileTokenTypeCpu); MicroProfileScopeHandler MICROPROFILE_TOKEN_PASTE(foo,__LINE__)( MICROPROFILE_TOKEN_PASTE(g_mp,__LINE__))
|
||||
@@ -827,7 +828,7 @@ inline MicroProfileLogEntry MicroProfileMakeLogIndex(uint64_t nBegin, MicroProfi
|
||||
MicroProfileLogEntry Entry = (nBegin<<62) | ((0x3fff&nToken)<<48) | (MP_LOG_TICK_MASK&nTick);
|
||||
int t = MicroProfileLogType(Entry);
|
||||
uint64_t nTimerIndex = MicroProfileLogTimerIndex(Entry);
|
||||
MP_ASSERT(t == nBegin);
|
||||
MP_ASSERT((uint64_t)t == nBegin);
|
||||
MP_ASSERT(nTimerIndex == (nToken&0x3fff));
|
||||
return Entry;
|
||||
|
||||
@@ -1555,10 +1556,10 @@ void MicroProfileFlip()
|
||||
|
||||
pFramePut->nFrameStartCpu = MP_TICK();
|
||||
pFramePut->nFrameStartGpu = (uint32_t)MicroProfileGpuInsertTimeStamp();
|
||||
if(pFrameNext->nFrameStartGpu != (uint64_t)-1)
|
||||
if(pFrameNext->nFrameStartGpu != -1)
|
||||
pFrameNext->nFrameStartGpu = MicroProfileGpuGetTimeStamp((uint32_t)pFrameNext->nFrameStartGpu);
|
||||
|
||||
if(pFrameCurrent->nFrameStartGpu == (uint64_t)-1)
|
||||
if(pFrameCurrent->nFrameStartGpu == -1)
|
||||
pFrameCurrent->nFrameStartGpu = pFrameNext->nFrameStartGpu + 1;
|
||||
|
||||
uint64_t nFrameStartCpu = pFrameCurrent->nFrameStartCpu;
|
||||
|
||||
@@ -343,8 +343,8 @@ The icons used in this project have the following licenses:
|
||||
|
||||
Icon Name | License | Origin/Author
|
||||
--- | --- | ---
|
||||
checked.png | Free for non-commercial use
|
||||
failed.png | Free for non-commercial use
|
||||
checked.png | CC BY-ND 3.0 | https://icons8.com
|
||||
failed.png | CC BY-ND 3.0 | https://icons8.com
|
||||
lock.png | CC BY-ND 3.0 | https://icons8.com
|
||||
plus_folder.png (Default, Dark) | CC BY-ND 3.0 | https://icons8.com
|
||||
bad_folder.png (Default, Dark) | CC BY-ND 3.0 | https://icons8.com
|
||||
|
||||
@@ -8,13 +8,14 @@
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
#include "audio_core/algorithm/interpolate.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging/log.h"
|
||||
|
||||
namespace AudioCore {
|
||||
|
||||
constexpr std::array<s16, 512> curve_lut0 = {
|
||||
constexpr std::array<s16, 512> curve_lut0{
|
||||
6600, 19426, 6722, 3, 6479, 19424, 6845, 9, 6359, 19419, 6968, 15, 6239,
|
||||
19412, 7093, 22, 6121, 19403, 7219, 28, 6004, 19391, 7345, 34, 5888, 19377,
|
||||
7472, 41, 5773, 19361, 7600, 48, 5659, 19342, 7728, 55, 5546, 19321, 7857,
|
||||
@@ -56,7 +57,7 @@ constexpr std::array<s16, 512> curve_lut0 = {
|
||||
19403, 6121, 22, 7093, 19412, 6239, 15, 6968, 19419, 6359, 9, 6845, 19424,
|
||||
6479, 3, 6722, 19426, 6600};
|
||||
|
||||
constexpr std::array<s16, 512> curve_lut1 = {
|
||||
constexpr std::array<s16, 512> curve_lut1{
|
||||
-68, 32639, 69, -5, -200, 32630, 212, -15, -328, 32613, 359, -26, -450,
|
||||
32586, 512, -36, -568, 32551, 669, -47, -680, 32507, 832, -58, -788, 32454,
|
||||
1000, -69, -891, 32393, 1174, -80, -990, 32323, 1352, -92, -1084, 32244, 1536,
|
||||
@@ -98,7 +99,7 @@ constexpr std::array<s16, 512> curve_lut1 = {
|
||||
32551, -568, -36, 512, 32586, -450, -26, 359, 32613, -328, -15, 212, 32630,
|
||||
-200, -5, 69, 32639, -68};
|
||||
|
||||
constexpr std::array<s16, 512> curve_lut2 = {
|
||||
constexpr std::array<s16, 512> curve_lut2{
|
||||
3195, 26287, 3329, -32, 3064, 26281, 3467, -34, 2936, 26270, 3608, -38, 2811,
|
||||
26253, 3751, -42, 2688, 26230, 3897, -46, 2568, 26202, 4046, -50, 2451, 26169,
|
||||
4199, -54, 2338, 26130, 4354, -58, 2227, 26085, 4512, -63, 2120, 26035, 4673,
|
||||
@@ -146,10 +147,10 @@ std::vector<s16> Interpolate(InterpolationState& state, std::vector<s16> input,
|
||||
|
||||
if (ratio <= 0) {
|
||||
LOG_CRITICAL(Audio, "Nonsensical interpolation ratio {}", ratio);
|
||||
ratio = 1.0;
|
||||
return input;
|
||||
}
|
||||
|
||||
const int step = static_cast<int>(ratio * 0x8000);
|
||||
const s32 step{static_cast<s32>(ratio * 0x8000)};
|
||||
const std::array<s16, 512>& lut = [step] {
|
||||
if (step > 0xaaaa) {
|
||||
return curve_lut0;
|
||||
@@ -160,28 +161,37 @@ std::vector<s16> Interpolate(InterpolationState& state, std::vector<s16> input,
|
||||
return curve_lut2;
|
||||
}();
|
||||
|
||||
std::vector<s16> output(static_cast<std::size_t>(input.size() / ratio));
|
||||
int in_offset = 0;
|
||||
for (std::size_t out_offset = 0; out_offset < output.size(); out_offset += 2) {
|
||||
const int lut_index = (state.fraction >> 8) * 4;
|
||||
const std::size_t num_frames{input.size() / 2};
|
||||
|
||||
const int l = input[(in_offset + 0) * 2 + 0] * lut[lut_index + 0] +
|
||||
input[(in_offset + 1) * 2 + 0] * lut[lut_index + 1] +
|
||||
input[(in_offset + 2) * 2 + 0] * lut[lut_index + 2] +
|
||||
input[(in_offset + 3) * 2 + 0] * lut[lut_index + 3];
|
||||
std::vector<s16> output;
|
||||
output.reserve(static_cast<std::size_t>(input.size() / ratio + InterpolationState::taps));
|
||||
|
||||
const int r = input[(in_offset + 0) * 2 + 1] * lut[lut_index + 0] +
|
||||
input[(in_offset + 1) * 2 + 1] * lut[lut_index + 1] +
|
||||
input[(in_offset + 2) * 2 + 1] * lut[lut_index + 2] +
|
||||
input[(in_offset + 3) * 2 + 1] * lut[lut_index + 3];
|
||||
for (std::size_t frame{}; frame < num_frames; ++frame) {
|
||||
const std::size_t lut_index{(state.fraction >> 8) * InterpolationState::taps};
|
||||
|
||||
const int new_offset = state.fraction + step;
|
||||
std::rotate(state.history.begin(), state.history.end() - 1, state.history.end());
|
||||
state.history[0][0] = input[frame * 2 + 0];
|
||||
state.history[0][1] = input[frame * 2 + 1];
|
||||
|
||||
in_offset += new_offset >> 15;
|
||||
state.fraction = new_offset & 0x7fff;
|
||||
while (state.position <= 1.0) {
|
||||
const s32 left{state.history[0][0] * lut[lut_index + 0] +
|
||||
state.history[1][0] * lut[lut_index + 1] +
|
||||
state.history[2][0] * lut[lut_index + 2] +
|
||||
state.history[3][0] * lut[lut_index + 3]};
|
||||
const s32 right{state.history[0][1] * lut[lut_index + 0] +
|
||||
state.history[1][1] * lut[lut_index + 1] +
|
||||
state.history[2][1] * lut[lut_index + 2] +
|
||||
state.history[3][1] * lut[lut_index + 3]};
|
||||
const s32 new_offset{state.fraction + step};
|
||||
|
||||
output[out_offset + 0] = static_cast<s16>(std::clamp(l >> 15, SHRT_MIN, SHRT_MAX));
|
||||
output[out_offset + 1] = static_cast<s16>(std::clamp(r >> 15, SHRT_MIN, SHRT_MAX));
|
||||
state.fraction = new_offset & 0x7fff;
|
||||
|
||||
output.emplace_back(static_cast<s16>(std::clamp(left >> 15, SHRT_MIN, SHRT_MAX)));
|
||||
output.emplace_back(static_cast<s16>(std::clamp(right >> 15, SHRT_MIN, SHRT_MAX)));
|
||||
|
||||
state.position += ratio;
|
||||
}
|
||||
state.position -= 1.0;
|
||||
}
|
||||
|
||||
return output;
|
||||
|
||||
@@ -6,12 +6,17 @@
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace AudioCore {
|
||||
|
||||
struct InterpolationState {
|
||||
int fraction = 0;
|
||||
static constexpr std::size_t taps{4};
|
||||
static constexpr std::size_t history_size{taps * 2 - 1};
|
||||
std::array<std::array<s16, 2>, history_size> history{};
|
||||
double position{};
|
||||
s32 fraction{};
|
||||
};
|
||||
|
||||
/// Interpolates input signal to produce output signal.
|
||||
|
||||
@@ -189,7 +189,7 @@ struct UpdateDataHeader {
|
||||
UpdateDataHeader() {}
|
||||
|
||||
explicit UpdateDataHeader(const AudioRendererParameter& config) {
|
||||
revision = Common::MakeMagic('R', 'E', 'V', '4'); // 5.1.0 Revision
|
||||
revision = Common::MakeMagic('R', 'E', 'V', '8'); // 9.2.0 Revision
|
||||
behavior_size = 0xb0;
|
||||
memory_pools_size = (config.effect_count + (config.voice_count * 4)) * 0x10;
|
||||
voices_size = config.voice_count * 0x10;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "audio_core/cubeb_sink.h"
|
||||
#include "audio_core/stream.h"
|
||||
#include "audio_core/time_stretch.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/ring_buffer.h"
|
||||
#include "core/settings.h"
|
||||
@@ -65,12 +66,25 @@ public:
|
||||
void EnqueueSamples(u32 source_num_channels, const std::vector<s16>& samples) override {
|
||||
if (source_num_channels > num_channels) {
|
||||
// Downsample 6 channels to 2
|
||||
ASSERT_MSG(source_num_channels == 6, "Channel count must be 6");
|
||||
|
||||
std::vector<s16> buf;
|
||||
buf.reserve(samples.size() * num_channels / source_num_channels);
|
||||
for (std::size_t i = 0; i < samples.size(); i += source_num_channels) {
|
||||
for (std::size_t ch = 0; ch < num_channels; ch++) {
|
||||
buf.push_back(samples[i + ch]);
|
||||
}
|
||||
// Downmixing implementation taken from the ATSC standard
|
||||
const s16 left{samples[i + 0]};
|
||||
const s16 right{samples[i + 1]};
|
||||
const s16 center{samples[i + 2]};
|
||||
const s16 surround_left{samples[i + 4]};
|
||||
const s16 surround_right{samples[i + 5]};
|
||||
// Not used in the ATSC reference implementation
|
||||
[[maybe_unused]] const s16 low_frequency_effects { samples[i + 3] };
|
||||
|
||||
constexpr s32 clev{707}; // center mixing level coefficient
|
||||
constexpr s32 slev{707}; // surround mixing level coefficient
|
||||
|
||||
buf.push_back(left + (clev * center / 1000) + (slev * surround_left / 1000));
|
||||
buf.push_back(right + (clev * center / 1000) + (slev * surround_right / 1000));
|
||||
}
|
||||
queue.Push(buf);
|
||||
return;
|
||||
|
||||
@@ -38,8 +38,6 @@ add_custom_command(OUTPUT scm_rev.cpp
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_shader_decompiler.h"
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_shader_disk_cache.cpp"
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_shader_disk_cache.h"
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_shader_gen.cpp"
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_shader_gen.h"
|
||||
"${VIDEO_CORE}/shader/decode/arithmetic.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/arithmetic_half.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/arithmetic_half_immediate.cpp"
|
||||
@@ -72,8 +70,6 @@ add_custom_command(OUTPUT scm_rev.cpp
|
||||
"${VIDEO_CORE}/shader/ast.h"
|
||||
"${VIDEO_CORE}/shader/compiler_settings.cpp"
|
||||
"${VIDEO_CORE}/shader/compiler_settings.h"
|
||||
"${VIDEO_CORE}/shader/const_buffer_locker.cpp"
|
||||
"${VIDEO_CORE}/shader/const_buffer_locker.h"
|
||||
"${VIDEO_CORE}/shader/control_flow.cpp"
|
||||
"${VIDEO_CORE}/shader/control_flow.h"
|
||||
"${VIDEO_CORE}/shader/decode.cpp"
|
||||
@@ -82,9 +78,13 @@ add_custom_command(OUTPUT scm_rev.cpp
|
||||
"${VIDEO_CORE}/shader/node.h"
|
||||
"${VIDEO_CORE}/shader/node_helper.cpp"
|
||||
"${VIDEO_CORE}/shader/node_helper.h"
|
||||
"${VIDEO_CORE}/shader/registry.cpp"
|
||||
"${VIDEO_CORE}/shader/registry.h"
|
||||
"${VIDEO_CORE}/shader/shader_ir.cpp"
|
||||
"${VIDEO_CORE}/shader/shader_ir.h"
|
||||
"${VIDEO_CORE}/shader/track.cpp"
|
||||
"${VIDEO_CORE}/shader/transform_feedback.cpp"
|
||||
"${VIDEO_CORE}/shader/transform_feedback.h"
|
||||
# and also check that the scm_rev files haven't changed
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.cpp.in"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.h"
|
||||
|
||||
@@ -30,20 +30,19 @@ __declspec(noinline, noreturn)
|
||||
#define ASSERT(_a_) \
|
||||
do \
|
||||
if (!(_a_)) { \
|
||||
assert_noinline_call([] { LOG_CRITICAL(Debug, "Assertion Failed!"); }); \
|
||||
LOG_CRITICAL(Debug, "Assertion Failed!"); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define ASSERT_MSG(_a_, ...) \
|
||||
do \
|
||||
if (!(_a_)) { \
|
||||
assert_noinline_call([&] { LOG_CRITICAL(Debug, "Assertion Failed!\n" __VA_ARGS__); }); \
|
||||
LOG_CRITICAL(Debug, "Assertion Failed! " __VA_ARGS__); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define UNREACHABLE() assert_noinline_call([] { LOG_CRITICAL(Debug, "Unreachable code!"); })
|
||||
#define UNREACHABLE_MSG(...) \
|
||||
assert_noinline_call([&] { LOG_CRITICAL(Debug, "Unreachable code!\n" __VA_ARGS__); })
|
||||
#define UNREACHABLE() LOG_CRITICAL(Debug, "Unreachable code!");
|
||||
#define UNREACHABLE_MSG(...) LOG_CRITICAL(Debug, "Unreachable code! " __VA_ARGS__);
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define DEBUG_ASSERT(_a_) ASSERT(_a_)
|
||||
|
||||
@@ -16,7 +16,6 @@ void PageTable::Resize(std::size_t address_space_width_in_bits) {
|
||||
|
||||
pointers.resize(num_page_table_entries);
|
||||
attributes.resize(num_page_table_entries);
|
||||
backing_addr.resize(num_page_table_entries);
|
||||
|
||||
// The default is a 39-bit address space, which causes an initial 1GB allocation size. If the
|
||||
// vector size is subsequently decreased (via resize), the vector might not automatically
|
||||
@@ -25,6 +24,17 @@ void PageTable::Resize(std::size_t address_space_width_in_bits) {
|
||||
|
||||
pointers.shrink_to_fit();
|
||||
attributes.shrink_to_fit();
|
||||
}
|
||||
|
||||
BackingPageTable::BackingPageTable(std::size_t page_size_in_bits) : PageTable{page_size_in_bits} {}
|
||||
|
||||
BackingPageTable::~BackingPageTable() = default;
|
||||
|
||||
void BackingPageTable::Resize(std::size_t address_space_width_in_bits) {
|
||||
PageTable::Resize(address_space_width_in_bits);
|
||||
const std::size_t num_page_table_entries = 1ULL
|
||||
<< (address_space_width_in_bits - page_size_in_bits);
|
||||
backing_addr.resize(num_page_table_entries);
|
||||
backing_addr.shrink_to_fit();
|
||||
}
|
||||
|
||||
|
||||
@@ -76,9 +76,20 @@ struct PageTable {
|
||||
*/
|
||||
std::vector<PageType> attributes;
|
||||
|
||||
std::vector<u64> backing_addr;
|
||||
|
||||
const std::size_t page_size_in_bits{};
|
||||
};
|
||||
|
||||
/**
|
||||
* A more advanced Page Table with the ability to save a backing address when using it
|
||||
* depends on another MMU.
|
||||
*/
|
||||
struct BackingPageTable : PageTable {
|
||||
explicit BackingPageTable(std::size_t page_size_in_bits);
|
||||
~BackingPageTable();
|
||||
|
||||
void Resize(std::size_t address_space_width_in_bits);
|
||||
|
||||
std::vector<u64> backing_addr;
|
||||
};
|
||||
|
||||
} // namespace Common
|
||||
|
||||
@@ -131,8 +131,6 @@ add_library(core STATIC
|
||||
frontend/framebuffer_layout.cpp
|
||||
frontend/framebuffer_layout.h
|
||||
frontend/input.h
|
||||
frontend/scope_acquire_context.cpp
|
||||
frontend/scope_acquire_context.h
|
||||
gdbstub/gdbstub.cpp
|
||||
gdbstub/gdbstub.h
|
||||
hardware_interrupt_manager.cpp
|
||||
@@ -287,6 +285,18 @@ add_library(core STATIC
|
||||
hle/service/btm/btm.h
|
||||
hle/service/caps/caps.cpp
|
||||
hle/service/caps/caps.h
|
||||
hle/service/caps/caps_a.cpp
|
||||
hle/service/caps/caps_a.h
|
||||
hle/service/caps/caps_c.cpp
|
||||
hle/service/caps/caps_c.h
|
||||
hle/service/caps/caps_u.cpp
|
||||
hle/service/caps/caps_u.h
|
||||
hle/service/caps/caps_sc.cpp
|
||||
hle/service/caps/caps_sc.h
|
||||
hle/service/caps/caps_ss.cpp
|
||||
hle/service/caps/caps_ss.h
|
||||
hle/service/caps/caps_su.cpp
|
||||
hle/service/caps/caps_su.h
|
||||
hle/service/erpt/erpt.cpp
|
||||
hle/service/erpt/erpt.h
|
||||
hle/service/es/es.cpp
|
||||
@@ -595,8 +605,12 @@ endif()
|
||||
|
||||
if (ARCHITECTURE_x86_64)
|
||||
target_sources(core PRIVATE
|
||||
arm/dynarmic/arm_dynarmic.cpp
|
||||
arm/dynarmic/arm_dynarmic.h
|
||||
arm/dynarmic/arm_dynarmic_32.cpp
|
||||
arm/dynarmic/arm_dynarmic_32.h
|
||||
arm/dynarmic/arm_dynarmic_64.cpp
|
||||
arm/dynarmic/arm_dynarmic_64.h
|
||||
arm/dynarmic/arm_dynarmic_cp15.cpp
|
||||
arm/dynarmic/arm_dynarmic_cp15.h
|
||||
)
|
||||
target_link_libraries(core PRIVATE dynarmic)
|
||||
endif()
|
||||
|
||||
@@ -25,7 +25,20 @@ public:
|
||||
explicit ARM_Interface(System& system_) : system{system_} {}
|
||||
virtual ~ARM_Interface() = default;
|
||||
|
||||
struct ThreadContext {
|
||||
struct ThreadContext32 {
|
||||
std::array<u32, 16> cpu_registers;
|
||||
u32 cpsr;
|
||||
std::array<u8, 4> padding;
|
||||
std::array<u64, 32> fprs;
|
||||
u32 fpscr;
|
||||
u32 fpexc;
|
||||
u32 tpidr;
|
||||
};
|
||||
// Internally within the kernel, it expects the AArch32 version of the
|
||||
// thread context to be 344 bytes in size.
|
||||
static_assert(sizeof(ThreadContext32) == 0x158);
|
||||
|
||||
struct ThreadContext64 {
|
||||
std::array<u64, 31> cpu_registers;
|
||||
u64 sp;
|
||||
u64 pc;
|
||||
@@ -38,7 +51,7 @@ public:
|
||||
};
|
||||
// Internally within the kernel, it expects the AArch64 version of the
|
||||
// thread context to be 800 bytes in size.
|
||||
static_assert(sizeof(ThreadContext) == 0x320);
|
||||
static_assert(sizeof(ThreadContext64) == 0x320);
|
||||
|
||||
/// Runs the CPU until an event happens
|
||||
virtual void Run() = 0;
|
||||
@@ -130,17 +143,10 @@ public:
|
||||
*/
|
||||
virtual void SetTPIDR_EL0(u64 value) = 0;
|
||||
|
||||
/**
|
||||
* Saves the current CPU context
|
||||
* @param ctx Thread context to save
|
||||
*/
|
||||
virtual void SaveContext(ThreadContext& ctx) = 0;
|
||||
|
||||
/**
|
||||
* Loads a CPU context
|
||||
* @param ctx Thread context to load
|
||||
*/
|
||||
virtual void LoadContext(const ThreadContext& ctx) = 0;
|
||||
virtual void SaveContext(ThreadContext32& ctx) = 0;
|
||||
virtual void SaveContext(ThreadContext64& ctx) = 0;
|
||||
virtual void LoadContext(const ThreadContext32& ctx) = 0;
|
||||
virtual void LoadContext(const ThreadContext64& ctx) = 0;
|
||||
|
||||
/// Clears the exclusive monitor's state.
|
||||
virtual void ClearExclusiveState() = 0;
|
||||
|
||||
208
src/core/arm/dynarmic/arm_dynarmic_32.cpp
Normal file
208
src/core/arm/dynarmic/arm_dynarmic_32.cpp
Normal file
@@ -0,0 +1,208 @@
|
||||
// Copyright 2020 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cinttypes>
|
||||
#include <memory>
|
||||
#include <dynarmic/A32/a32.h>
|
||||
#include <dynarmic/A32/config.h>
|
||||
#include <dynarmic/A32/context.h>
|
||||
#include "common/microprofile.h"
|
||||
#include "core/arm/dynarmic/arm_dynarmic_32.h"
|
||||
#include "core/arm/dynarmic/arm_dynarmic_64.h"
|
||||
#include "core/arm/dynarmic/arm_dynarmic_cp15.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_manager.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/svc.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
namespace Core {
|
||||
|
||||
class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks {
|
||||
public:
|
||||
explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent) : parent(parent) {}
|
||||
|
||||
u8 MemoryRead8(u32 vaddr) override {
|
||||
return parent.system.Memory().Read8(vaddr);
|
||||
}
|
||||
u16 MemoryRead16(u32 vaddr) override {
|
||||
return parent.system.Memory().Read16(vaddr);
|
||||
}
|
||||
u32 MemoryRead32(u32 vaddr) override {
|
||||
return parent.system.Memory().Read32(vaddr);
|
||||
}
|
||||
u64 MemoryRead64(u32 vaddr) override {
|
||||
return parent.system.Memory().Read64(vaddr);
|
||||
}
|
||||
|
||||
void MemoryWrite8(u32 vaddr, u8 value) override {
|
||||
parent.system.Memory().Write8(vaddr, value);
|
||||
}
|
||||
void MemoryWrite16(u32 vaddr, u16 value) override {
|
||||
parent.system.Memory().Write16(vaddr, value);
|
||||
}
|
||||
void MemoryWrite32(u32 vaddr, u32 value) override {
|
||||
parent.system.Memory().Write32(vaddr, value);
|
||||
}
|
||||
void MemoryWrite64(u32 vaddr, u64 value) override {
|
||||
parent.system.Memory().Write64(vaddr, value);
|
||||
}
|
||||
|
||||
void InterpreterFallback(u32 pc, std::size_t num_instructions) override {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override {
|
||||
switch (exception) {
|
||||
case Dynarmic::A32::Exception::UndefinedInstruction:
|
||||
case Dynarmic::A32::Exception::UnpredictableInstruction:
|
||||
break;
|
||||
case Dynarmic::A32::Exception::Breakpoint:
|
||||
break;
|
||||
}
|
||||
LOG_CRITICAL(HW_GPU, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})",
|
||||
static_cast<std::size_t>(exception), pc, MemoryReadCode(pc));
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
void CallSVC(u32 swi) override {
|
||||
Kernel::CallSVC(parent.system, swi);
|
||||
}
|
||||
|
||||
void AddTicks(u64 ticks) override {
|
||||
// Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a
|
||||
// rough approximation of the amount of executed ticks in the system, it may be thrown off
|
||||
// if not all cores are doing a similar amount of work. Instead of doing this, we should
|
||||
// device a way so that timing is consistent across all cores without increasing the ticks 4
|
||||
// times.
|
||||
u64 amortized_ticks = (ticks - num_interpreted_instructions) / Core::NUM_CPU_CORES;
|
||||
// Always execute at least one tick.
|
||||
amortized_ticks = std::max<u64>(amortized_ticks, 1);
|
||||
|
||||
parent.system.CoreTiming().AddTicks(amortized_ticks);
|
||||
num_interpreted_instructions = 0;
|
||||
}
|
||||
u64 GetTicksRemaining() override {
|
||||
return std::max(parent.system.CoreTiming().GetDowncount(), {});
|
||||
}
|
||||
|
||||
ARM_Dynarmic_32& parent;
|
||||
std::size_t num_interpreted_instructions{};
|
||||
u64 tpidrro_el0{};
|
||||
u64 tpidr_el0{};
|
||||
};
|
||||
|
||||
std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable& page_table,
|
||||
std::size_t address_space_bits) const {
|
||||
Dynarmic::A32::UserConfig config;
|
||||
config.callbacks = cb.get();
|
||||
// TODO(bunnei): Implement page table for 32-bit
|
||||
// config.page_table = &page_table.pointers;
|
||||
config.coprocessors[15] = std::make_shared<DynarmicCP15>((u32*)&CP15_regs[0]);
|
||||
config.define_unpredictable_behaviour = true;
|
||||
return std::make_unique<Dynarmic::A32::Jit>(config);
|
||||
}
|
||||
|
||||
MICROPROFILE_DEFINE(ARM_Jit_Dynarmic_32, "ARM JIT", "Dynarmic", MP_RGB(255, 64, 64));
|
||||
|
||||
void ARM_Dynarmic_32::Run() {
|
||||
MICROPROFILE_SCOPE(ARM_Jit_Dynarmic_32);
|
||||
jit->Run();
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_32::Step() {
|
||||
cb->InterpreterFallback(jit->Regs()[15], 1);
|
||||
}
|
||||
|
||||
ARM_Dynarmic_32::ARM_Dynarmic_32(System& system, ExclusiveMonitor& exclusive_monitor,
|
||||
std::size_t core_index)
|
||||
: ARM_Interface{system},
|
||||
cb(std::make_unique<DynarmicCallbacks32>(*this)), core_index{core_index},
|
||||
exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {}
|
||||
|
||||
ARM_Dynarmic_32::~ARM_Dynarmic_32() = default;
|
||||
|
||||
void ARM_Dynarmic_32::SetPC(u64 pc) {
|
||||
jit->Regs()[15] = static_cast<u32>(pc);
|
||||
}
|
||||
|
||||
u64 ARM_Dynarmic_32::GetPC() const {
|
||||
return jit->Regs()[15];
|
||||
}
|
||||
|
||||
u64 ARM_Dynarmic_32::GetReg(int index) const {
|
||||
return jit->Regs()[index];
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_32::SetReg(int index, u64 value) {
|
||||
jit->Regs()[index] = static_cast<u32>(value);
|
||||
}
|
||||
|
||||
u128 ARM_Dynarmic_32::GetVectorReg(int index) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_32::SetVectorReg(int index, u128 value) {}
|
||||
|
||||
u32 ARM_Dynarmic_32::GetPSTATE() const {
|
||||
return jit->Cpsr();
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_32::SetPSTATE(u32 cpsr) {
|
||||
jit->SetCpsr(cpsr);
|
||||
}
|
||||
|
||||
u64 ARM_Dynarmic_32::GetTlsAddress() const {
|
||||
return CP15_regs[static_cast<std::size_t>(CP15Register::CP15_THREAD_URO)];
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_32::SetTlsAddress(VAddr address) {
|
||||
CP15_regs[static_cast<std::size_t>(CP15Register::CP15_THREAD_URO)] = static_cast<u32>(address);
|
||||
}
|
||||
|
||||
u64 ARM_Dynarmic_32::GetTPIDR_EL0() const {
|
||||
return cb->tpidr_el0;
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_32::SetTPIDR_EL0(u64 value) {
|
||||
cb->tpidr_el0 = value;
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) {
|
||||
Dynarmic::A32::Context context;
|
||||
jit->SaveContext(context);
|
||||
ctx.cpu_registers = context.Regs();
|
||||
ctx.cpsr = context.Cpsr();
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_32::LoadContext(const ThreadContext32& ctx) {
|
||||
Dynarmic::A32::Context context;
|
||||
context.Regs() = ctx.cpu_registers;
|
||||
context.SetCpsr(ctx.cpsr);
|
||||
jit->LoadContext(context);
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_32::PrepareReschedule() {
|
||||
jit->HaltExecution();
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_32::ClearInstructionCache() {
|
||||
jit->ClearCache();
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_32::ClearExclusiveState() {}
|
||||
|
||||
void ARM_Dynarmic_32::PageTableChanged(Common::PageTable& page_table,
|
||||
std::size_t new_address_space_size_in_bits) {
|
||||
auto key = std::make_pair(&page_table, new_address_space_size_in_bits);
|
||||
auto iter = jit_cache.find(key);
|
||||
if (iter != jit_cache.end()) {
|
||||
jit = iter->second;
|
||||
return;
|
||||
}
|
||||
jit = MakeJit(page_table, new_address_space_size_in_bits);
|
||||
jit_cache.emplace(key, jit);
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
77
src/core/arm/dynarmic/arm_dynarmic_32.h
Normal file
77
src/core/arm/dynarmic/arm_dynarmic_32.h
Normal file
@@ -0,0 +1,77 @@
|
||||
// Copyright 2020 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <dynarmic/A32/a32.h>
|
||||
#include <dynarmic/A64/a64.h>
|
||||
#include <dynarmic/A64/exclusive_monitor.h>
|
||||
#include "common/common_types.h"
|
||||
#include "common/hash.h"
|
||||
#include "core/arm/arm_interface.h"
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
|
||||
namespace Memory {
|
||||
class Memory;
|
||||
}
|
||||
|
||||
namespace Core {
|
||||
|
||||
class DynarmicCallbacks32;
|
||||
class DynarmicExclusiveMonitor;
|
||||
class System;
|
||||
|
||||
class ARM_Dynarmic_32 final : public ARM_Interface {
|
||||
public:
|
||||
ARM_Dynarmic_32(System& system, ExclusiveMonitor& exclusive_monitor, std::size_t core_index);
|
||||
~ARM_Dynarmic_32() override;
|
||||
|
||||
void SetPC(u64 pc) override;
|
||||
u64 GetPC() const override;
|
||||
u64 GetReg(int index) const override;
|
||||
void SetReg(int index, u64 value) override;
|
||||
u128 GetVectorReg(int index) const override;
|
||||
void SetVectorReg(int index, u128 value) override;
|
||||
u32 GetPSTATE() const override;
|
||||
void SetPSTATE(u32 pstate) override;
|
||||
void Run() override;
|
||||
void Step() override;
|
||||
VAddr GetTlsAddress() const override;
|
||||
void SetTlsAddress(VAddr address) override;
|
||||
void SetTPIDR_EL0(u64 value) override;
|
||||
u64 GetTPIDR_EL0() const override;
|
||||
|
||||
void SaveContext(ThreadContext32& ctx) override;
|
||||
void SaveContext(ThreadContext64& ctx) override {}
|
||||
void LoadContext(const ThreadContext32& ctx) override;
|
||||
void LoadContext(const ThreadContext64& ctx) override {}
|
||||
|
||||
void PrepareReschedule() override;
|
||||
void ClearExclusiveState() override;
|
||||
|
||||
void ClearInstructionCache() override;
|
||||
void PageTableChanged(Common::PageTable& new_page_table,
|
||||
std::size_t new_address_space_size_in_bits) override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<Dynarmic::A32::Jit> MakeJit(Common::PageTable& page_table,
|
||||
std::size_t address_space_bits) const;
|
||||
|
||||
using JitCacheKey = std::pair<Common::PageTable*, std::size_t>;
|
||||
using JitCacheType =
|
||||
std::unordered_map<JitCacheKey, std::shared_ptr<Dynarmic::A32::Jit>, Common::PairHash>;
|
||||
|
||||
friend class DynarmicCallbacks32;
|
||||
std::unique_ptr<DynarmicCallbacks32> cb;
|
||||
JitCacheType jit_cache;
|
||||
std::shared_ptr<Dynarmic::A32::Jit> jit;
|
||||
std::size_t core_index;
|
||||
DynarmicExclusiveMonitor& exclusive_monitor;
|
||||
std::array<u32, 84> CP15_regs{};
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <dynarmic/A64/config.h>
|
||||
#include "common/logging/log.h"
|
||||
#include "common/microprofile.h"
|
||||
#include "core/arm/dynarmic/arm_dynarmic.h"
|
||||
#include "core/arm/dynarmic/arm_dynarmic_64.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_manager.h"
|
||||
#include "core/core_timing.h"
|
||||
@@ -25,9 +25,9 @@ namespace Core {
|
||||
|
||||
using Vector = Dynarmic::A64::Vector;
|
||||
|
||||
class ARM_Dynarmic_Callbacks : public Dynarmic::A64::UserCallbacks {
|
||||
class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
|
||||
public:
|
||||
explicit ARM_Dynarmic_Callbacks(ARM_Dynarmic& parent) : parent(parent) {}
|
||||
explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent) : parent(parent) {}
|
||||
|
||||
u8 MemoryRead8(u64 vaddr) override {
|
||||
return parent.system.Memory().Read8(vaddr);
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
LOG_INFO(Core_ARM, "Unicorn fallback @ 0x{:X} for {} instructions (instr = {:08X})", pc,
|
||||
num_instructions, MemoryReadCode(pc));
|
||||
|
||||
ARM_Interface::ThreadContext ctx;
|
||||
ARM_Interface::ThreadContext64 ctx;
|
||||
parent.SaveContext(ctx);
|
||||
parent.inner_unicorn.LoadContext(ctx);
|
||||
parent.inner_unicorn.ExecuteInstructions(num_instructions);
|
||||
@@ -90,7 +90,7 @@ public:
|
||||
parent.jit->HaltExecution();
|
||||
parent.SetPC(pc);
|
||||
Kernel::Thread* const thread = parent.system.CurrentScheduler().GetCurrentThread();
|
||||
parent.SaveContext(thread->GetContext());
|
||||
parent.SaveContext(thread->GetContext64());
|
||||
GDBStub::Break();
|
||||
GDBStub::SendTrap(thread, 5);
|
||||
return;
|
||||
@@ -126,14 +126,14 @@ public:
|
||||
return Timing::CpuCyclesToClockCycles(parent.system.CoreTiming().GetTicks());
|
||||
}
|
||||
|
||||
ARM_Dynarmic& parent;
|
||||
ARM_Dynarmic_64& parent;
|
||||
std::size_t num_interpreted_instructions = 0;
|
||||
u64 tpidrro_el0 = 0;
|
||||
u64 tpidr_el0 = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit(Common::PageTable& page_table,
|
||||
std::size_t address_space_bits) const {
|
||||
std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable& page_table,
|
||||
std::size_t address_space_bits) const {
|
||||
Dynarmic::A64::UserConfig config;
|
||||
|
||||
// Callbacks
|
||||
@@ -159,79 +159,79 @@ std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit(Common::PageTable& pag
|
||||
// Unpredictable instructions
|
||||
config.define_unpredictable_behaviour = true;
|
||||
|
||||
return std::make_unique<Dynarmic::A64::Jit>(config);
|
||||
return std::make_shared<Dynarmic::A64::Jit>(config);
|
||||
}
|
||||
|
||||
MICROPROFILE_DEFINE(ARM_Jit_Dynarmic, "ARM JIT", "Dynarmic", MP_RGB(255, 64, 64));
|
||||
MICROPROFILE_DEFINE(ARM_Jit_Dynarmic_64, "ARM JIT", "Dynarmic", MP_RGB(255, 64, 64));
|
||||
|
||||
void ARM_Dynarmic::Run() {
|
||||
MICROPROFILE_SCOPE(ARM_Jit_Dynarmic);
|
||||
void ARM_Dynarmic_64::Run() {
|
||||
MICROPROFILE_SCOPE(ARM_Jit_Dynarmic_64);
|
||||
|
||||
jit->Run();
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::Step() {
|
||||
void ARM_Dynarmic_64::Step() {
|
||||
cb->InterpreterFallback(jit->GetPC(), 1);
|
||||
}
|
||||
|
||||
ARM_Dynarmic::ARM_Dynarmic(System& system, ExclusiveMonitor& exclusive_monitor,
|
||||
std::size_t core_index)
|
||||
ARM_Dynarmic_64::ARM_Dynarmic_64(System& system, ExclusiveMonitor& exclusive_monitor,
|
||||
std::size_t core_index)
|
||||
: ARM_Interface{system},
|
||||
cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), inner_unicorn{system},
|
||||
cb(std::make_unique<DynarmicCallbacks64>(*this)), inner_unicorn{system},
|
||||
core_index{core_index}, exclusive_monitor{
|
||||
dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {}
|
||||
|
||||
ARM_Dynarmic::~ARM_Dynarmic() = default;
|
||||
ARM_Dynarmic_64::~ARM_Dynarmic_64() = default;
|
||||
|
||||
void ARM_Dynarmic::SetPC(u64 pc) {
|
||||
void ARM_Dynarmic_64::SetPC(u64 pc) {
|
||||
jit->SetPC(pc);
|
||||
}
|
||||
|
||||
u64 ARM_Dynarmic::GetPC() const {
|
||||
u64 ARM_Dynarmic_64::GetPC() const {
|
||||
return jit->GetPC();
|
||||
}
|
||||
|
||||
u64 ARM_Dynarmic::GetReg(int index) const {
|
||||
u64 ARM_Dynarmic_64::GetReg(int index) const {
|
||||
return jit->GetRegister(index);
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::SetReg(int index, u64 value) {
|
||||
void ARM_Dynarmic_64::SetReg(int index, u64 value) {
|
||||
jit->SetRegister(index, value);
|
||||
}
|
||||
|
||||
u128 ARM_Dynarmic::GetVectorReg(int index) const {
|
||||
u128 ARM_Dynarmic_64::GetVectorReg(int index) const {
|
||||
return jit->GetVector(index);
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::SetVectorReg(int index, u128 value) {
|
||||
void ARM_Dynarmic_64::SetVectorReg(int index, u128 value) {
|
||||
jit->SetVector(index, value);
|
||||
}
|
||||
|
||||
u32 ARM_Dynarmic::GetPSTATE() const {
|
||||
u32 ARM_Dynarmic_64::GetPSTATE() const {
|
||||
return jit->GetPstate();
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::SetPSTATE(u32 pstate) {
|
||||
void ARM_Dynarmic_64::SetPSTATE(u32 pstate) {
|
||||
jit->SetPstate(pstate);
|
||||
}
|
||||
|
||||
u64 ARM_Dynarmic::GetTlsAddress() const {
|
||||
u64 ARM_Dynarmic_64::GetTlsAddress() const {
|
||||
return cb->tpidrro_el0;
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::SetTlsAddress(VAddr address) {
|
||||
void ARM_Dynarmic_64::SetTlsAddress(VAddr address) {
|
||||
cb->tpidrro_el0 = address;
|
||||
}
|
||||
|
||||
u64 ARM_Dynarmic::GetTPIDR_EL0() const {
|
||||
u64 ARM_Dynarmic_64::GetTPIDR_EL0() const {
|
||||
return cb->tpidr_el0;
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::SetTPIDR_EL0(u64 value) {
|
||||
void ARM_Dynarmic_64::SetTPIDR_EL0(u64 value) {
|
||||
cb->tpidr_el0 = value;
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::SaveContext(ThreadContext& ctx) {
|
||||
void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) {
|
||||
ctx.cpu_registers = jit->GetRegisters();
|
||||
ctx.sp = jit->GetSP();
|
||||
ctx.pc = jit->GetPC();
|
||||
@@ -242,7 +242,7 @@ void ARM_Dynarmic::SaveContext(ThreadContext& ctx) {
|
||||
ctx.tpidr = cb->tpidr_el0;
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::LoadContext(const ThreadContext& ctx) {
|
||||
void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) {
|
||||
jit->SetRegisters(ctx.cpu_registers);
|
||||
jit->SetSP(ctx.sp);
|
||||
jit->SetPC(ctx.pc);
|
||||
@@ -253,25 +253,32 @@ void ARM_Dynarmic::LoadContext(const ThreadContext& ctx) {
|
||||
SetTPIDR_EL0(ctx.tpidr);
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::PrepareReschedule() {
|
||||
void ARM_Dynarmic_64::PrepareReschedule() {
|
||||
jit->HaltExecution();
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::ClearInstructionCache() {
|
||||
void ARM_Dynarmic_64::ClearInstructionCache() {
|
||||
jit->ClearCache();
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::ClearExclusiveState() {
|
||||
void ARM_Dynarmic_64::ClearExclusiveState() {
|
||||
jit->ClearExclusiveState();
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::PageTableChanged(Common::PageTable& page_table,
|
||||
std::size_t new_address_space_size_in_bits) {
|
||||
void ARM_Dynarmic_64::PageTableChanged(Common::PageTable& page_table,
|
||||
std::size_t new_address_space_size_in_bits) {
|
||||
auto key = std::make_pair(&page_table, new_address_space_size_in_bits);
|
||||
auto iter = jit_cache.find(key);
|
||||
if (iter != jit_cache.end()) {
|
||||
jit = iter->second;
|
||||
return;
|
||||
}
|
||||
jit = MakeJit(page_table, new_address_space_size_in_bits);
|
||||
jit_cache.emplace(key, jit);
|
||||
}
|
||||
|
||||
DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(Memory::Memory& memory_, std::size_t core_count)
|
||||
: monitor(core_count), memory{memory_} {}
|
||||
DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(Memory::Memory& memory, std::size_t core_count)
|
||||
: monitor(core_count), memory{memory} {}
|
||||
|
||||
DynarmicExclusiveMonitor::~DynarmicExclusiveMonitor() = default;
|
||||
|
||||
@@ -5,9 +5,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <dynarmic/A64/a64.h>
|
||||
#include <dynarmic/A64/exclusive_monitor.h>
|
||||
#include "common/common_types.h"
|
||||
#include "common/hash.h"
|
||||
#include "core/arm/arm_interface.h"
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/arm/unicorn/arm_unicorn.h"
|
||||
@@ -18,14 +21,14 @@ class Memory;
|
||||
|
||||
namespace Core {
|
||||
|
||||
class ARM_Dynarmic_Callbacks;
|
||||
class DynarmicCallbacks64;
|
||||
class DynarmicExclusiveMonitor;
|
||||
class System;
|
||||
|
||||
class ARM_Dynarmic final : public ARM_Interface {
|
||||
class ARM_Dynarmic_64 final : public ARM_Interface {
|
||||
public:
|
||||
ARM_Dynarmic(System& system, ExclusiveMonitor& exclusive_monitor, std::size_t core_index);
|
||||
~ARM_Dynarmic() override;
|
||||
ARM_Dynarmic_64(System& system, ExclusiveMonitor& exclusive_monitor, std::size_t core_index);
|
||||
~ARM_Dynarmic_64() override;
|
||||
|
||||
void SetPC(u64 pc) override;
|
||||
u64 GetPC() const override;
|
||||
@@ -42,8 +45,10 @@ public:
|
||||
void SetTPIDR_EL0(u64 value) override;
|
||||
u64 GetTPIDR_EL0() const override;
|
||||
|
||||
void SaveContext(ThreadContext& ctx) override;
|
||||
void LoadContext(const ThreadContext& ctx) override;
|
||||
void SaveContext(ThreadContext32& ctx) override {}
|
||||
void SaveContext(ThreadContext64& ctx) override;
|
||||
void LoadContext(const ThreadContext32& ctx) override {}
|
||||
void LoadContext(const ThreadContext64& ctx) override;
|
||||
|
||||
void PrepareReschedule() override;
|
||||
void ClearExclusiveState() override;
|
||||
@@ -53,12 +58,17 @@ public:
|
||||
std::size_t new_address_space_size_in_bits) override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable& page_table,
|
||||
std::shared_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable& page_table,
|
||||
std::size_t address_space_bits) const;
|
||||
|
||||
friend class ARM_Dynarmic_Callbacks;
|
||||
std::unique_ptr<ARM_Dynarmic_Callbacks> cb;
|
||||
std::unique_ptr<Dynarmic::A64::Jit> jit;
|
||||
using JitCacheKey = std::pair<Common::PageTable*, std::size_t>;
|
||||
using JitCacheType =
|
||||
std::unordered_map<JitCacheKey, std::shared_ptr<Dynarmic::A64::Jit>, Common::PairHash>;
|
||||
|
||||
friend class DynarmicCallbacks64;
|
||||
std::unique_ptr<DynarmicCallbacks64> cb;
|
||||
JitCacheType jit_cache;
|
||||
std::shared_ptr<Dynarmic::A64::Jit> jit;
|
||||
ARM_Unicorn inner_unicorn;
|
||||
|
||||
std::size_t core_index;
|
||||
@@ -67,7 +77,7 @@ private:
|
||||
|
||||
class DynarmicExclusiveMonitor final : public ExclusiveMonitor {
|
||||
public:
|
||||
explicit DynarmicExclusiveMonitor(Memory::Memory& memory_, std::size_t core_count);
|
||||
explicit DynarmicExclusiveMonitor(Memory::Memory& memory, std::size_t core_count);
|
||||
~DynarmicExclusiveMonitor() override;
|
||||
|
||||
void SetExclusive(std::size_t core_index, VAddr addr) override;
|
||||
@@ -80,7 +90,7 @@ public:
|
||||
bool ExclusiveWrite128(std::size_t core_index, VAddr vaddr, u128 value) override;
|
||||
|
||||
private:
|
||||
friend class ARM_Dynarmic;
|
||||
friend class ARM_Dynarmic_64;
|
||||
Dynarmic::A64::ExclusiveMonitor monitor;
|
||||
Memory::Memory& memory;
|
||||
};
|
||||
80
src/core/arm/dynarmic/arm_dynarmic_cp15.cpp
Normal file
80
src/core/arm/dynarmic/arm_dynarmic_cp15.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
// Copyright 2017 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/arm/dynarmic/arm_dynarmic_cp15.h"
|
||||
|
||||
using Callback = Dynarmic::A32::Coprocessor::Callback;
|
||||
using CallbackOrAccessOneWord = Dynarmic::A32::Coprocessor::CallbackOrAccessOneWord;
|
||||
using CallbackOrAccessTwoWords = Dynarmic::A32::Coprocessor::CallbackOrAccessTwoWords;
|
||||
|
||||
std::optional<Callback> DynarmicCP15::CompileInternalOperation(bool two, unsigned opc1,
|
||||
CoprocReg CRd, CoprocReg CRn,
|
||||
CoprocReg CRm, unsigned opc2) {
|
||||
return {};
|
||||
}
|
||||
|
||||
CallbackOrAccessOneWord DynarmicCP15::CompileSendOneWord(bool two, unsigned opc1, CoprocReg CRn,
|
||||
CoprocReg CRm, unsigned opc2) {
|
||||
// TODO(merry): Privileged CP15 registers
|
||||
|
||||
if (!two && CRn == CoprocReg::C7 && opc1 == 0 && CRm == CoprocReg::C5 && opc2 == 4) {
|
||||
// This is a dummy write, we ignore the value written here.
|
||||
return &CP15[static_cast<std::size_t>(CP15Register::CP15_FLUSH_PREFETCH_BUFFER)];
|
||||
}
|
||||
|
||||
if (!two && CRn == CoprocReg::C7 && opc1 == 0 && CRm == CoprocReg::C10) {
|
||||
switch (opc2) {
|
||||
case 4:
|
||||
// This is a dummy write, we ignore the value written here.
|
||||
return &CP15[static_cast<std::size_t>(CP15Register::CP15_DATA_SYNC_BARRIER)];
|
||||
case 5:
|
||||
// This is a dummy write, we ignore the value written here.
|
||||
return &CP15[static_cast<std::size_t>(CP15Register::CP15_DATA_MEMORY_BARRIER)];
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
if (!two && CRn == CoprocReg::C13 && opc1 == 0 && CRm == CoprocReg::C0 && opc2 == 2) {
|
||||
return &CP15[static_cast<std::size_t>(CP15Register::CP15_THREAD_UPRW)];
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
CallbackOrAccessTwoWords DynarmicCP15::CompileSendTwoWords(bool two, unsigned opc, CoprocReg CRm) {
|
||||
return {};
|
||||
}
|
||||
|
||||
CallbackOrAccessOneWord DynarmicCP15::CompileGetOneWord(bool two, unsigned opc1, CoprocReg CRn,
|
||||
CoprocReg CRm, unsigned opc2) {
|
||||
// TODO(merry): Privileged CP15 registers
|
||||
|
||||
if (!two && CRn == CoprocReg::C13 && opc1 == 0 && CRm == CoprocReg::C0) {
|
||||
switch (opc2) {
|
||||
case 2:
|
||||
return &CP15[static_cast<std::size_t>(CP15Register::CP15_THREAD_UPRW)];
|
||||
case 3:
|
||||
return &CP15[static_cast<std::size_t>(CP15Register::CP15_THREAD_URO)];
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
CallbackOrAccessTwoWords DynarmicCP15::CompileGetTwoWords(bool two, unsigned opc, CoprocReg CRm) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::optional<Callback> DynarmicCP15::CompileLoadWords(bool two, bool long_transfer, CoprocReg CRd,
|
||||
std::optional<u8> option) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::optional<Callback> DynarmicCP15::CompileStoreWords(bool two, bool long_transfer, CoprocReg CRd,
|
||||
std::optional<u8> option) {
|
||||
return {};
|
||||
}
|
||||
152
src/core/arm/dynarmic/arm_dynarmic_cp15.h
Normal file
152
src/core/arm/dynarmic/arm_dynarmic_cp15.h
Normal file
@@ -0,0 +1,152 @@
|
||||
// Copyright 2017 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include <dynarmic/A32/coprocessor.h>
|
||||
#include "common/common_types.h"
|
||||
|
||||
enum class CP15Register {
|
||||
// c0 - Information registers
|
||||
CP15_MAIN_ID,
|
||||
CP15_CACHE_TYPE,
|
||||
CP15_TCM_STATUS,
|
||||
CP15_TLB_TYPE,
|
||||
CP15_CPU_ID,
|
||||
CP15_PROCESSOR_FEATURE_0,
|
||||
CP15_PROCESSOR_FEATURE_1,
|
||||
CP15_DEBUG_FEATURE_0,
|
||||
CP15_AUXILIARY_FEATURE_0,
|
||||
CP15_MEMORY_MODEL_FEATURE_0,
|
||||
CP15_MEMORY_MODEL_FEATURE_1,
|
||||
CP15_MEMORY_MODEL_FEATURE_2,
|
||||
CP15_MEMORY_MODEL_FEATURE_3,
|
||||
CP15_ISA_FEATURE_0,
|
||||
CP15_ISA_FEATURE_1,
|
||||
CP15_ISA_FEATURE_2,
|
||||
CP15_ISA_FEATURE_3,
|
||||
CP15_ISA_FEATURE_4,
|
||||
|
||||
// c1 - Control registers
|
||||
CP15_CONTROL,
|
||||
CP15_AUXILIARY_CONTROL,
|
||||
CP15_COPROCESSOR_ACCESS_CONTROL,
|
||||
|
||||
// c2 - Translation table registers
|
||||
CP15_TRANSLATION_BASE_TABLE_0,
|
||||
CP15_TRANSLATION_BASE_TABLE_1,
|
||||
CP15_TRANSLATION_BASE_CONTROL,
|
||||
CP15_DOMAIN_ACCESS_CONTROL,
|
||||
CP15_RESERVED,
|
||||
|
||||
// c5 - Fault status registers
|
||||
CP15_FAULT_STATUS,
|
||||
CP15_INSTR_FAULT_STATUS,
|
||||
CP15_COMBINED_DATA_FSR = CP15_FAULT_STATUS,
|
||||
CP15_INST_FSR,
|
||||
|
||||
// c6 - Fault Address registers
|
||||
CP15_FAULT_ADDRESS,
|
||||
CP15_COMBINED_DATA_FAR = CP15_FAULT_ADDRESS,
|
||||
CP15_WFAR,
|
||||
CP15_IFAR,
|
||||
|
||||
// c7 - Cache operation registers
|
||||
CP15_WAIT_FOR_INTERRUPT,
|
||||
CP15_PHYS_ADDRESS,
|
||||
CP15_INVALIDATE_INSTR_CACHE,
|
||||
CP15_INVALIDATE_INSTR_CACHE_USING_MVA,
|
||||
CP15_INVALIDATE_INSTR_CACHE_USING_INDEX,
|
||||
CP15_FLUSH_PREFETCH_BUFFER,
|
||||
CP15_FLUSH_BRANCH_TARGET_CACHE,
|
||||
CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY,
|
||||
CP15_INVALIDATE_DATA_CACHE,
|
||||
CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA,
|
||||
CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX,
|
||||
CP15_INVALIDATE_DATA_AND_INSTR_CACHE,
|
||||
CP15_CLEAN_DATA_CACHE,
|
||||
CP15_CLEAN_DATA_CACHE_LINE_USING_MVA,
|
||||
CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX,
|
||||
CP15_DATA_SYNC_BARRIER,
|
||||
CP15_DATA_MEMORY_BARRIER,
|
||||
CP15_CLEAN_AND_INVALIDATE_DATA_CACHE,
|
||||
CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_MVA,
|
||||
CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX,
|
||||
|
||||
// c8 - TLB operations
|
||||
CP15_INVALIDATE_ITLB,
|
||||
CP15_INVALIDATE_ITLB_SINGLE_ENTRY,
|
||||
CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH,
|
||||
CP15_INVALIDATE_ITLB_ENTRY_ON_MVA,
|
||||
CP15_INVALIDATE_DTLB,
|
||||
CP15_INVALIDATE_DTLB_SINGLE_ENTRY,
|
||||
CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH,
|
||||
CP15_INVALIDATE_DTLB_ENTRY_ON_MVA,
|
||||
CP15_INVALIDATE_UTLB,
|
||||
CP15_INVALIDATE_UTLB_SINGLE_ENTRY,
|
||||
CP15_INVALIDATE_UTLB_ENTRY_ON_ASID_MATCH,
|
||||
CP15_INVALIDATE_UTLB_ENTRY_ON_MVA,
|
||||
|
||||
// c9 - Data cache lockdown register
|
||||
CP15_DATA_CACHE_LOCKDOWN,
|
||||
|
||||
// c10 - TLB/Memory map registers
|
||||
CP15_TLB_LOCKDOWN,
|
||||
CP15_PRIMARY_REGION_REMAP,
|
||||
CP15_NORMAL_REGION_REMAP,
|
||||
|
||||
// c13 - Thread related registers
|
||||
CP15_PID,
|
||||
CP15_CONTEXT_ID,
|
||||
CP15_THREAD_UPRW, // Thread ID register - User/Privileged Read/Write
|
||||
CP15_THREAD_URO, // Thread ID register - User Read Only (Privileged R/W)
|
||||
CP15_THREAD_PRW, // Thread ID register - Privileged R/W only.
|
||||
|
||||
// c15 - Performance and TLB lockdown registers
|
||||
CP15_PERFORMANCE_MONITOR_CONTROL,
|
||||
CP15_CYCLE_COUNTER,
|
||||
CP15_COUNT_0,
|
||||
CP15_COUNT_1,
|
||||
CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY,
|
||||
CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY,
|
||||
CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS,
|
||||
CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS,
|
||||
CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE,
|
||||
CP15_TLB_DEBUG_CONTROL,
|
||||
|
||||
// Skyeye defined
|
||||
CP15_TLB_FAULT_ADDR,
|
||||
CP15_TLB_FAULT_STATUS,
|
||||
|
||||
// Not an actual register.
|
||||
// All registers should be defined above this.
|
||||
CP15_REGISTER_COUNT,
|
||||
};
|
||||
|
||||
class DynarmicCP15 final : public Dynarmic::A32::Coprocessor {
|
||||
public:
|
||||
using CoprocReg = Dynarmic::A32::CoprocReg;
|
||||
|
||||
explicit DynarmicCP15(u32* cp15) : CP15(cp15){};
|
||||
|
||||
std::optional<Callback> CompileInternalOperation(bool two, unsigned opc1, CoprocReg CRd,
|
||||
CoprocReg CRn, CoprocReg CRm,
|
||||
unsigned opc2) override;
|
||||
CallbackOrAccessOneWord CompileSendOneWord(bool two, unsigned opc1, CoprocReg CRn,
|
||||
CoprocReg CRm, unsigned opc2) override;
|
||||
CallbackOrAccessTwoWords CompileSendTwoWords(bool two, unsigned opc, CoprocReg CRm) override;
|
||||
CallbackOrAccessOneWord CompileGetOneWord(bool two, unsigned opc1, CoprocReg CRn, CoprocReg CRm,
|
||||
unsigned opc2) override;
|
||||
CallbackOrAccessTwoWords CompileGetTwoWords(bool two, unsigned opc, CoprocReg CRm) override;
|
||||
std::optional<Callback> CompileLoadWords(bool two, bool long_transfer, CoprocReg CRd,
|
||||
std::optional<u8> option) override;
|
||||
std::optional<Callback> CompileStoreWords(bool two, bool long_transfer, CoprocReg CRd,
|
||||
std::optional<u8> option) override;
|
||||
|
||||
private:
|
||||
u32* CP15{};
|
||||
};
|
||||
@@ -3,7 +3,7 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
#include "core/arm/dynarmic/arm_dynarmic.h"
|
||||
#include "core/arm/dynarmic/arm_dynarmic_64.h"
|
||||
#endif
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
@@ -53,7 +53,7 @@ static bool UnmappedMemoryHook(uc_engine* uc, uc_mem_type type, u64 addr, int si
|
||||
void* user_data) {
|
||||
auto* const system = static_cast<System*>(user_data);
|
||||
|
||||
ARM_Interface::ThreadContext ctx{};
|
||||
ARM_Interface::ThreadContext64 ctx{};
|
||||
system->CurrentArmInterface().SaveContext(ctx);
|
||||
ASSERT_MSG(false, "Attempted to read from unmapped memory: 0x{:X}, pc=0x{:X}, lr=0x{:X}", addr,
|
||||
ctx.pc, ctx.cpu_registers[30]);
|
||||
@@ -179,7 +179,7 @@ void ARM_Unicorn::ExecuteInstructions(std::size_t num_instructions) {
|
||||
}
|
||||
|
||||
Kernel::Thread* const thread = system.CurrentScheduler().GetCurrentThread();
|
||||
SaveContext(thread->GetContext());
|
||||
SaveContext(thread->GetContext64());
|
||||
if (last_bkpt_hit || GDBStub::IsMemoryBreak() || GDBStub::GetCpuStepFlag()) {
|
||||
last_bkpt_hit = false;
|
||||
GDBStub::Break();
|
||||
@@ -188,7 +188,7 @@ void ARM_Unicorn::ExecuteInstructions(std::size_t num_instructions) {
|
||||
}
|
||||
}
|
||||
|
||||
void ARM_Unicorn::SaveContext(ThreadContext& ctx) {
|
||||
void ARM_Unicorn::SaveContext(ThreadContext64& ctx) {
|
||||
int uregs[32];
|
||||
void* tregs[32];
|
||||
|
||||
@@ -215,7 +215,7 @@ void ARM_Unicorn::SaveContext(ThreadContext& ctx) {
|
||||
CHECKED(uc_reg_read_batch(uc, uregs, tregs, 32));
|
||||
}
|
||||
|
||||
void ARM_Unicorn::LoadContext(const ThreadContext& ctx) {
|
||||
void ARM_Unicorn::LoadContext(const ThreadContext64& ctx) {
|
||||
int uregs[32];
|
||||
void* tregs[32];
|
||||
|
||||
|
||||
@@ -30,8 +30,6 @@ public:
|
||||
void SetTlsAddress(VAddr address) override;
|
||||
void SetTPIDR_EL0(u64 value) override;
|
||||
u64 GetTPIDR_EL0() const override;
|
||||
void SaveContext(ThreadContext& ctx) override;
|
||||
void LoadContext(const ThreadContext& ctx) override;
|
||||
void PrepareReschedule() override;
|
||||
void ClearExclusiveState() override;
|
||||
void ExecuteInstructions(std::size_t num_instructions);
|
||||
@@ -41,6 +39,11 @@ public:
|
||||
void PageTableChanged(Common::PageTable&, std::size_t) override {}
|
||||
void RecordBreak(GDBStub::BreakpointAddress bkpt);
|
||||
|
||||
void SaveContext(ThreadContext32& ctx) override {}
|
||||
void SaveContext(ThreadContext64& ctx) override;
|
||||
void LoadContext(const ThreadContext32& ctx) override {}
|
||||
void LoadContext(const ThreadContext64& ctx) override;
|
||||
|
||||
private:
|
||||
static void InterruptHook(uc_engine* uc, u32 int_no, void* user_data);
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "core/file_sys/sdmc_factory.h"
|
||||
#include "core/file_sys/vfs_concat.h"
|
||||
#include "core/file_sys/vfs_real.h"
|
||||
#include "core/frontend/scope_acquire_context.h"
|
||||
#include "core/gdbstub/gdbstub.h"
|
||||
#include "core/hardware_interrupt_manager.h"
|
||||
#include "core/hle/kernel/client_port.h"
|
||||
@@ -166,15 +165,14 @@ struct System::Impl {
|
||||
service_manager = std::make_shared<Service::SM::ServiceManager>();
|
||||
|
||||
Service::Init(service_manager, system);
|
||||
GDBStub::Init();
|
||||
GDBStub::DeferStart();
|
||||
|
||||
renderer = VideoCore::CreateRenderer(emu_window, system);
|
||||
if (!renderer->Init()) {
|
||||
interrupt_manager = std::make_unique<Core::Hardware::InterruptManager>(system);
|
||||
gpu_core = VideoCore::CreateGPU(emu_window, system);
|
||||
if (!gpu_core) {
|
||||
return ResultStatus::ErrorVideoCore;
|
||||
}
|
||||
interrupt_manager = std::make_unique<Core::Hardware::InterruptManager>(system);
|
||||
gpu_core = VideoCore::CreateGPU(system);
|
||||
renderer->Rasterizer().SetupDirtyFlags();
|
||||
gpu_core->Renderer().Rasterizer().SetupDirtyFlags();
|
||||
|
||||
is_powered_on = true;
|
||||
exit_lock = false;
|
||||
@@ -186,8 +184,6 @@ struct System::Impl {
|
||||
|
||||
ResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
|
||||
const std::string& filepath) {
|
||||
Core::Frontend::ScopeAcquireContext acquire_context{emu_window};
|
||||
|
||||
app_loader = Loader::GetLoader(GetGameFileFromPath(virtual_filesystem, filepath));
|
||||
if (!app_loader) {
|
||||
LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
|
||||
@@ -216,10 +212,6 @@ struct System::Impl {
|
||||
AddGlueRegistrationForProcess(*app_loader, *main_process);
|
||||
kernel.MakeCurrentProcess(main_process.get());
|
||||
|
||||
// Main process has been loaded and been made current.
|
||||
// Begin GPU and CPU execution.
|
||||
gpu_core->Start();
|
||||
|
||||
// Initialize cheat engine
|
||||
if (cheat_engine) {
|
||||
cheat_engine->Initialize();
|
||||
@@ -277,7 +269,6 @@ struct System::Impl {
|
||||
}
|
||||
|
||||
// Shutdown emulation session
|
||||
renderer.reset();
|
||||
GDBStub::Shutdown();
|
||||
Service::Shutdown();
|
||||
service_manager.reset();
|
||||
@@ -353,7 +344,6 @@ struct System::Impl {
|
||||
Service::FileSystem::FileSystemController fs_controller;
|
||||
/// AppLoader used to load the current executing application
|
||||
std::unique_ptr<Loader::AppLoader> app_loader;
|
||||
std::unique_ptr<VideoCore::RendererBase> renderer;
|
||||
std::unique_ptr<Tegra::GPU> gpu_core;
|
||||
std::unique_ptr<Hardware::InterruptManager> interrupt_manager;
|
||||
Memory::Memory memory;
|
||||
@@ -536,11 +526,11 @@ const Core::Hardware::InterruptManager& System::InterruptManager() const {
|
||||
}
|
||||
|
||||
VideoCore::RendererBase& System::Renderer() {
|
||||
return *impl->renderer;
|
||||
return impl->gpu_core->Renderer();
|
||||
}
|
||||
|
||||
const VideoCore::RendererBase& System::Renderer() const {
|
||||
return *impl->renderer;
|
||||
return impl->gpu_core->Renderer();
|
||||
}
|
||||
|
||||
Kernel::KernelCore& System::Kernel() {
|
||||
|
||||
@@ -6,9 +6,6 @@
|
||||
#include <mutex>
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
#include "core/arm/dynarmic/arm_dynarmic.h"
|
||||
#endif
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/arm/unicorn/arm_unicorn.h"
|
||||
#include "core/core.h"
|
||||
|
||||
@@ -13,19 +13,39 @@
|
||||
namespace Core::Frontend {
|
||||
|
||||
/**
|
||||
* Represents a graphics context that can be used for background computation or drawing. If the
|
||||
* graphics backend doesn't require the context, then the implementation of these methods can be
|
||||
* stubs
|
||||
* Represents a drawing context that supports graphics operations.
|
||||
*/
|
||||
class GraphicsContext {
|
||||
public:
|
||||
virtual ~GraphicsContext();
|
||||
|
||||
/// Inform the driver to swap the front/back buffers and present the current image
|
||||
virtual void SwapBuffers() {}
|
||||
|
||||
/// Makes the graphics context current for the caller thread
|
||||
virtual void MakeCurrent() = 0;
|
||||
virtual void MakeCurrent() {}
|
||||
|
||||
/// Releases (dunno if this is the "right" word) the context from the caller thread
|
||||
virtual void DoneCurrent() = 0;
|
||||
virtual void DoneCurrent() {}
|
||||
|
||||
class Scoped {
|
||||
public:
|
||||
explicit Scoped(GraphicsContext& context_) : context(context_) {
|
||||
context.MakeCurrent();
|
||||
}
|
||||
~Scoped() {
|
||||
context.DoneCurrent();
|
||||
}
|
||||
|
||||
private:
|
||||
GraphicsContext& context;
|
||||
};
|
||||
|
||||
/// Calls MakeCurrent on the context and calls DoneCurrent when the scope for the returned value
|
||||
/// ends
|
||||
Scoped Acquire() {
|
||||
return Scoped{*this};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -46,7 +66,7 @@ public:
|
||||
* - DO NOT TREAT THIS CLASS AS A GUI TOOLKIT ABSTRACTION LAYER. That's not what it is. Please
|
||||
* re-read the upper points again and think about it if you don't see this.
|
||||
*/
|
||||
class EmuWindow : public GraphicsContext {
|
||||
class EmuWindow {
|
||||
public:
|
||||
/// Data structure to store emuwindow configuration
|
||||
struct WindowConfig {
|
||||
@@ -60,17 +80,9 @@ public:
|
||||
virtual void PollEvents() = 0;
|
||||
|
||||
/**
|
||||
* Returns a GraphicsContext that the frontend provides that is shared with the emu window. This
|
||||
* context can be used from other threads for background graphics computation. If the frontend
|
||||
* is using a graphics backend that doesn't need anything specific to run on a different thread,
|
||||
* then it can use a stubbed implemenation for GraphicsContext.
|
||||
*
|
||||
* If the return value is null, then the core should assume that the frontend cannot provide a
|
||||
* Shared Context
|
||||
* Returns a GraphicsContext that the frontend provides to be used for rendering.
|
||||
*/
|
||||
virtual std::unique_ptr<GraphicsContext> CreateSharedContext() const {
|
||||
return nullptr;
|
||||
}
|
||||
virtual std::unique_ptr<GraphicsContext> CreateSharedContext() const = 0;
|
||||
|
||||
/// Returns if window is shown (not minimized)
|
||||
virtual bool IsShown() const = 0;
|
||||
|
||||
@@ -48,8 +48,8 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale) {
|
||||
u32 width, height;
|
||||
|
||||
if (Settings::values.use_docked_mode) {
|
||||
width = ScreenDocked::WidthDocked * res_scale;
|
||||
height = ScreenDocked::HeightDocked * res_scale;
|
||||
width = ScreenDocked::Width * res_scale;
|
||||
height = ScreenDocked::Height * res_scale;
|
||||
} else {
|
||||
width = ScreenUndocked::Width * res_scale;
|
||||
height = ScreenUndocked::Height * res_scale;
|
||||
|
||||
@@ -8,15 +8,15 @@
|
||||
|
||||
namespace Layout {
|
||||
|
||||
enum ScreenUndocked : u32 {
|
||||
Width = 1280,
|
||||
Height = 720,
|
||||
};
|
||||
namespace ScreenUndocked {
|
||||
constexpr u32 Width = 1280;
|
||||
constexpr u32 Height = 720;
|
||||
} // namespace ScreenUndocked
|
||||
|
||||
enum ScreenDocked : u32 {
|
||||
WidthDocked = 1920,
|
||||
HeightDocked = 1080,
|
||||
};
|
||||
namespace ScreenDocked {
|
||||
constexpr u32 Width = 1920;
|
||||
constexpr u32 Height = 1080;
|
||||
} // namespace ScreenDocked
|
||||
|
||||
enum class AspectRatio {
|
||||
Default,
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
// Copyright 2019 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/frontend/emu_window.h"
|
||||
#include "core/frontend/scope_acquire_context.h"
|
||||
|
||||
namespace Core::Frontend {
|
||||
|
||||
ScopeAcquireContext::ScopeAcquireContext(Core::Frontend::GraphicsContext& context)
|
||||
: context{context} {
|
||||
context.MakeCurrent();
|
||||
}
|
||||
ScopeAcquireContext::~ScopeAcquireContext() {
|
||||
context.DoneCurrent();
|
||||
}
|
||||
|
||||
} // namespace Core::Frontend
|
||||
@@ -1,23 +0,0 @@
|
||||
// Copyright 2019 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Core::Frontend {
|
||||
|
||||
class GraphicsContext;
|
||||
|
||||
/// Helper class to acquire/release window context within a given scope
|
||||
class ScopeAcquireContext : NonCopyable {
|
||||
public:
|
||||
explicit ScopeAcquireContext(Core::Frontend::GraphicsContext& context);
|
||||
~ScopeAcquireContext();
|
||||
|
||||
private:
|
||||
Core::Frontend::GraphicsContext& context;
|
||||
};
|
||||
|
||||
} // namespace Core::Frontend
|
||||
@@ -141,6 +141,7 @@ constexpr char target_xml[] =
|
||||
)";
|
||||
|
||||
int gdbserver_socket = -1;
|
||||
bool defer_start = false;
|
||||
|
||||
u8 command_buffer[GDB_BUFFER_SIZE];
|
||||
u32 command_length;
|
||||
@@ -217,7 +218,7 @@ static u64 RegRead(std::size_t id, Kernel::Thread* thread = nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const auto& thread_context = thread->GetContext();
|
||||
const auto& thread_context = thread->GetContext64();
|
||||
|
||||
if (id < SP_REGISTER) {
|
||||
return thread_context.cpu_registers[id];
|
||||
@@ -239,7 +240,7 @@ static void RegWrite(std::size_t id, u64 val, Kernel::Thread* thread = nullptr)
|
||||
return;
|
||||
}
|
||||
|
||||
auto& thread_context = thread->GetContext();
|
||||
auto& thread_context = thread->GetContext64();
|
||||
|
||||
if (id < SP_REGISTER) {
|
||||
thread_context.cpu_registers[id] = val;
|
||||
@@ -259,7 +260,7 @@ static u128 FpuRead(std::size_t id, Kernel::Thread* thread = nullptr) {
|
||||
return u128{0};
|
||||
}
|
||||
|
||||
auto& thread_context = thread->GetContext();
|
||||
auto& thread_context = thread->GetContext64();
|
||||
|
||||
if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {
|
||||
return thread_context.vector_registers[id - UC_ARM64_REG_Q0];
|
||||
@@ -275,7 +276,7 @@ static void FpuWrite(std::size_t id, u128 val, Kernel::Thread* thread = nullptr)
|
||||
return;
|
||||
}
|
||||
|
||||
auto& thread_context = thread->GetContext();
|
||||
auto& thread_context = thread->GetContext64();
|
||||
|
||||
if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {
|
||||
thread_context.vector_registers[id - UC_ARM64_REG_Q0] = val;
|
||||
@@ -916,7 +917,7 @@ static void WriteRegister() {
|
||||
// Update ARM context, skipping scheduler - no running threads at this point
|
||||
Core::System::GetInstance()
|
||||
.ArmInterface(current_core)
|
||||
.LoadContext(current_thread->GetContext());
|
||||
.LoadContext(current_thread->GetContext64());
|
||||
|
||||
SendReply("OK");
|
||||
}
|
||||
@@ -947,7 +948,7 @@ static void WriteRegisters() {
|
||||
// Update ARM context, skipping scheduler - no running threads at this point
|
||||
Core::System::GetInstance()
|
||||
.ArmInterface(current_core)
|
||||
.LoadContext(current_thread->GetContext());
|
||||
.LoadContext(current_thread->GetContext64());
|
||||
|
||||
SendReply("OK");
|
||||
}
|
||||
@@ -1019,7 +1020,7 @@ static void Step() {
|
||||
// Update ARM context, skipping scheduler - no running threads at this point
|
||||
Core::System::GetInstance()
|
||||
.ArmInterface(current_core)
|
||||
.LoadContext(current_thread->GetContext());
|
||||
.LoadContext(current_thread->GetContext64());
|
||||
}
|
||||
step_loop = true;
|
||||
halt_loop = true;
|
||||
@@ -1166,6 +1167,9 @@ static void RemoveBreakpoint() {
|
||||
|
||||
void HandlePacket() {
|
||||
if (!IsConnected()) {
|
||||
if (defer_start) {
|
||||
ToggleServer(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1256,6 +1260,10 @@ void ToggleServer(bool status) {
|
||||
}
|
||||
}
|
||||
|
||||
void DeferStart() {
|
||||
defer_start = true;
|
||||
}
|
||||
|
||||
static void Init(u16 port) {
|
||||
if (!server_enabled) {
|
||||
// Set the halt loop to false in case the user enabled the gdbstub mid-execution.
|
||||
@@ -1341,6 +1349,7 @@ void Shutdown() {
|
||||
if (!server_enabled) {
|
||||
return;
|
||||
}
|
||||
defer_start = false;
|
||||
|
||||
LOG_INFO(Debug_GDBStub, "Stopping GDB ...");
|
||||
if (gdbserver_socket != -1) {
|
||||
|
||||
@@ -43,6 +43,13 @@ void ToggleServer(bool status);
|
||||
/// Start the gdbstub server.
|
||||
void Init();
|
||||
|
||||
/**
|
||||
* Defer initialization of the gdbstub to the first packet processing functions.
|
||||
* This avoids a case where the gdbstub thread is frozen after initialization
|
||||
* and fails to respond in time to packets.
|
||||
*/
|
||||
void DeferStart();
|
||||
|
||||
/// Stop gdbstub server.
|
||||
void Shutdown();
|
||||
|
||||
|
||||
@@ -186,6 +186,10 @@ struct KernelCore::Impl {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& core : cores) {
|
||||
core.SetIs64Bit(process->Is64BitProcess());
|
||||
}
|
||||
|
||||
system.Memory().SetCurrentPageTable(*process);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
#include "common/logging/log.h"
|
||||
#include "core/arm/arm_interface.h"
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
#include "core/arm/dynarmic/arm_dynarmic.h"
|
||||
#include "core/arm/dynarmic/arm_dynarmic_32.h"
|
||||
#include "core/arm/dynarmic/arm_dynarmic_64.h"
|
||||
#endif
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/arm/unicorn/arm_unicorn.h"
|
||||
@@ -20,13 +21,17 @@ PhysicalCore::PhysicalCore(Core::System& system, std::size_t id,
|
||||
Core::ExclusiveMonitor& exclusive_monitor)
|
||||
: core_index{id} {
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
arm_interface = std::make_unique<Core::ARM_Dynarmic>(system, exclusive_monitor, core_index);
|
||||
arm_interface_32 =
|
||||
std::make_unique<Core::ARM_Dynarmic_32>(system, exclusive_monitor, core_index);
|
||||
arm_interface_64 =
|
||||
std::make_unique<Core::ARM_Dynarmic_64>(system, exclusive_monitor, core_index);
|
||||
|
||||
#else
|
||||
arm_interface = std::make_shared<Core::ARM_Unicorn>(system);
|
||||
LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available");
|
||||
#endif
|
||||
|
||||
scheduler = std::make_unique<Kernel::Scheduler>(system, *arm_interface, core_index);
|
||||
scheduler = std::make_unique<Kernel::Scheduler>(system, core_index);
|
||||
}
|
||||
|
||||
PhysicalCore::~PhysicalCore() = default;
|
||||
@@ -48,4 +53,12 @@ void PhysicalCore::Shutdown() {
|
||||
scheduler->Shutdown();
|
||||
}
|
||||
|
||||
void PhysicalCore::SetIs64Bit(bool is_64_bit) {
|
||||
if (is_64_bit) {
|
||||
arm_interface = arm_interface_64.get();
|
||||
} else {
|
||||
arm_interface = arm_interface_32.get();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
@@ -68,10 +68,14 @@ public:
|
||||
return *scheduler;
|
||||
}
|
||||
|
||||
void SetIs64Bit(bool is_64_bit);
|
||||
|
||||
private:
|
||||
std::size_t core_index;
|
||||
std::unique_ptr<Core::ARM_Interface> arm_interface;
|
||||
std::unique_ptr<Core::ARM_Interface> arm_interface_32;
|
||||
std::unique_ptr<Core::ARM_Interface> arm_interface_64;
|
||||
std::unique_ptr<Kernel::Scheduler> scheduler;
|
||||
Core::ARM_Interface* arm_interface{};
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
@@ -42,7 +42,8 @@ void SetupMainThread(Process& owner_process, KernelCore& kernel, u32 priority) {
|
||||
|
||||
// Register 1 must be a handle to the main thread
|
||||
const Handle thread_handle = owner_process.GetHandleTable().Create(thread).Unwrap();
|
||||
thread->GetContext().cpu_registers[1] = thread_handle;
|
||||
thread->GetContext32().cpu_registers[1] = thread_handle;
|
||||
thread->GetContext64().cpu_registers[1] = thread_handle;
|
||||
|
||||
// Threads by default are dormant, wake up the main thread so it runs when the scheduler fires
|
||||
thread->ResumeFromWait();
|
||||
|
||||
@@ -383,8 +383,8 @@ void GlobalScheduler::Unlock() {
|
||||
// TODO(Blinkhawk): Setup the interrupts and change context on current core.
|
||||
}
|
||||
|
||||
Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, std::size_t core_id)
|
||||
: system(system), cpu_core(cpu_core), core_id(core_id) {}
|
||||
Scheduler::Scheduler(Core::System& system, std::size_t core_id)
|
||||
: system{system}, core_id{core_id} {}
|
||||
|
||||
Scheduler::~Scheduler() = default;
|
||||
|
||||
@@ -422,9 +422,10 @@ void Scheduler::UnloadThread() {
|
||||
|
||||
// Save context for previous thread
|
||||
if (previous_thread) {
|
||||
cpu_core.SaveContext(previous_thread->GetContext());
|
||||
system.ArmInterface(core_id).SaveContext(previous_thread->GetContext32());
|
||||
system.ArmInterface(core_id).SaveContext(previous_thread->GetContext64());
|
||||
// Save the TPIDR_EL0 system register in case it was modified.
|
||||
previous_thread->SetTPIDR_EL0(cpu_core.GetTPIDR_EL0());
|
||||
previous_thread->SetTPIDR_EL0(system.ArmInterface(core_id).GetTPIDR_EL0());
|
||||
|
||||
if (previous_thread->GetStatus() == ThreadStatus::Running) {
|
||||
// This is only the case when a reschedule is triggered without the current thread
|
||||
@@ -451,9 +452,10 @@ void Scheduler::SwitchContext() {
|
||||
|
||||
// Save context for previous thread
|
||||
if (previous_thread) {
|
||||
cpu_core.SaveContext(previous_thread->GetContext());
|
||||
system.ArmInterface(core_id).SaveContext(previous_thread->GetContext32());
|
||||
system.ArmInterface(core_id).SaveContext(previous_thread->GetContext64());
|
||||
// Save the TPIDR_EL0 system register in case it was modified.
|
||||
previous_thread->SetTPIDR_EL0(cpu_core.GetTPIDR_EL0());
|
||||
previous_thread->SetTPIDR_EL0(system.ArmInterface(core_id).GetTPIDR_EL0());
|
||||
|
||||
if (previous_thread->GetStatus() == ThreadStatus::Running) {
|
||||
// This is only the case when a reschedule is triggered without the current thread
|
||||
@@ -481,9 +483,10 @@ void Scheduler::SwitchContext() {
|
||||
system.Kernel().MakeCurrentProcess(thread_owner_process);
|
||||
}
|
||||
|
||||
cpu_core.LoadContext(new_thread->GetContext());
|
||||
cpu_core.SetTlsAddress(new_thread->GetTLSAddress());
|
||||
cpu_core.SetTPIDR_EL0(new_thread->GetTPIDR_EL0());
|
||||
system.ArmInterface(core_id).LoadContext(new_thread->GetContext32());
|
||||
system.ArmInterface(core_id).LoadContext(new_thread->GetContext64());
|
||||
system.ArmInterface(core_id).SetTlsAddress(new_thread->GetTLSAddress());
|
||||
system.ArmInterface(core_id).SetTPIDR_EL0(new_thread->GetTPIDR_EL0());
|
||||
} else {
|
||||
current_thread = nullptr;
|
||||
// Note: We do not reset the current process and current page table when idling because
|
||||
|
||||
@@ -181,7 +181,7 @@ private:
|
||||
|
||||
class Scheduler final {
|
||||
public:
|
||||
explicit Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, std::size_t core_id);
|
||||
explicit Scheduler(Core::System& system, std::size_t core_id);
|
||||
~Scheduler();
|
||||
|
||||
/// Returns whether there are any threads that are ready to run.
|
||||
@@ -235,7 +235,6 @@ private:
|
||||
std::shared_ptr<Thread> selected_thread = nullptr;
|
||||
|
||||
Core::System& system;
|
||||
Core::ARM_Interface& cpu_core;
|
||||
u64 last_context_switch_time = 0;
|
||||
u64 idle_selection_count = 0;
|
||||
const std::size_t core_id;
|
||||
|
||||
@@ -187,6 +187,13 @@ static ResultCode SetHeapSize(Core::System& system, VAddr* heap_addr, u64 heap_s
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static ResultCode SetHeapSize32(Core::System& system, u32* heap_addr, u32 heap_size) {
|
||||
VAddr temp_heap_addr{};
|
||||
const ResultCode result{SetHeapSize(system, &temp_heap_addr, heap_size)};
|
||||
*heap_addr = static_cast<u32>(temp_heap_addr);
|
||||
return result;
|
||||
}
|
||||
|
||||
static ResultCode SetMemoryPermission(Core::System& system, VAddr addr, u64 size, u32 prot) {
|
||||
LOG_TRACE(Kernel_SVC, "called, addr=0x{:X}, size=0x{:X}, prot=0x{:X}", addr, size, prot);
|
||||
|
||||
@@ -371,6 +378,12 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle,
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static ResultCode ConnectToNamedPort32(Core::System& system, Handle* out_handle,
|
||||
u32 port_name_address) {
|
||||
|
||||
return ConnectToNamedPort(system, out_handle, port_name_address);
|
||||
}
|
||||
|
||||
/// Makes a blocking IPC call to an OS service.
|
||||
static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
|
||||
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
|
||||
@@ -390,6 +403,10 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
|
||||
return session->SendSyncRequest(SharedFrom(thread), system.Memory());
|
||||
}
|
||||
|
||||
static ResultCode SendSyncRequest32(Core::System& system, Handle handle) {
|
||||
return SendSyncRequest(system, handle);
|
||||
}
|
||||
|
||||
/// Get the ID for the specified thread.
|
||||
static ResultCode GetThreadId(Core::System& system, u64* thread_id, Handle thread_handle) {
|
||||
LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
|
||||
@@ -405,6 +422,17 @@ static ResultCode GetThreadId(Core::System& system, u64* thread_id, Handle threa
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static ResultCode GetThreadId32(Core::System& system, u32* thread_id_low, u32* thread_id_high,
|
||||
Handle thread_handle) {
|
||||
u64 thread_id{};
|
||||
const ResultCode result{GetThreadId(system, &thread_id, thread_handle)};
|
||||
|
||||
*thread_id_low = static_cast<u32>(thread_id >> 32);
|
||||
*thread_id_high = static_cast<u32>(thread_id & std::numeric_limits<u32>::max());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Gets the ID of the specified process or a specified thread's owning process.
|
||||
static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle handle) {
|
||||
LOG_DEBUG(Kernel_SVC, "called handle=0x{:08X}", handle);
|
||||
@@ -479,6 +507,12 @@ static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr
|
||||
return result;
|
||||
}
|
||||
|
||||
static ResultCode WaitSynchronization32(Core::System& system, u32 timeout_low, u32 handles_address,
|
||||
s32 handle_count, u32 timeout_high, Handle* index) {
|
||||
const s64 nano_seconds{(static_cast<s64>(timeout_high) << 32) | static_cast<s64>(timeout_low)};
|
||||
return WaitSynchronization(system, index, handles_address, handle_count, nano_seconds);
|
||||
}
|
||||
|
||||
/// Resumes a thread waiting on WaitSynchronization
|
||||
static ResultCode CancelSynchronization(Core::System& system, Handle thread_handle) {
|
||||
LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle);
|
||||
@@ -917,6 +951,18 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
|
||||
}
|
||||
}
|
||||
|
||||
static ResultCode GetInfo32(Core::System& system, u32* result_low, u32* result_high, u32 sub_id_low,
|
||||
u32 info_id, u32 handle, u32 sub_id_high) {
|
||||
const u64 sub_id{static_cast<u64>(sub_id_low | (static_cast<u64>(sub_id_high) << 32))};
|
||||
u64 res_value{};
|
||||
|
||||
const ResultCode result{GetInfo(system, &res_value, info_id, handle, sub_id)};
|
||||
*result_high = static_cast<u32>(res_value >> 32);
|
||||
*result_low = static_cast<u32>(res_value & std::numeric_limits<u32>::max());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Maps memory at a desired address
|
||||
static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {
|
||||
LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size);
|
||||
@@ -1058,7 +1104,7 @@ static ResultCode GetThreadContext(Core::System& system, VAddr thread_context, H
|
||||
return ERR_BUSY;
|
||||
}
|
||||
|
||||
Core::ARM_Interface::ThreadContext ctx = thread->GetContext();
|
||||
Core::ARM_Interface::ThreadContext64 ctx = thread->GetContext64();
|
||||
// Mask away mode bits, interrupt bits, IL bit, and other reserved bits.
|
||||
ctx.pstate &= 0xFF0FFE20;
|
||||
|
||||
@@ -1088,6 +1134,10 @@ static ResultCode GetThreadPriority(Core::System& system, u32* priority, Handle
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static ResultCode GetThreadPriority32(Core::System& system, u32* priority, Handle handle) {
|
||||
return GetThreadPriority(system, priority, handle);
|
||||
}
|
||||
|
||||
/// Sets the priority for the specified thread
|
||||
static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 priority) {
|
||||
LOG_TRACE(Kernel_SVC, "called");
|
||||
@@ -1259,6 +1309,11 @@ static ResultCode QueryMemory(Core::System& system, VAddr memory_info_address,
|
||||
query_address);
|
||||
}
|
||||
|
||||
static ResultCode QueryMemory32(Core::System& system, u32 memory_info_address,
|
||||
u32 page_info_address, u32 query_address) {
|
||||
return QueryMemory(system, memory_info_address, page_info_address, query_address);
|
||||
}
|
||||
|
||||
static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address,
|
||||
u64 src_address, u64 size) {
|
||||
LOG_DEBUG(Kernel_SVC,
|
||||
@@ -1675,6 +1730,10 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_
|
||||
}
|
||||
}
|
||||
|
||||
static void SignalProcessWideKey32(Core::System& system, u32 condition_variable_addr, s32 target) {
|
||||
SignalProcessWideKey(system, condition_variable_addr, target);
|
||||
}
|
||||
|
||||
// Wait for an address (via Address Arbiter)
|
||||
static ResultCode WaitForAddress(Core::System& system, VAddr address, u32 type, s32 value,
|
||||
s64 timeout) {
|
||||
@@ -1760,6 +1819,10 @@ static ResultCode CloseHandle(Core::System& system, Handle handle) {
|
||||
return handle_table.Close(handle);
|
||||
}
|
||||
|
||||
static ResultCode CloseHandle32(Core::System& system, Handle handle) {
|
||||
return CloseHandle(system, handle);
|
||||
}
|
||||
|
||||
/// Clears the signaled state of an event or process.
|
||||
static ResultCode ResetSignal(Core::System& system, Handle handle) {
|
||||
LOG_DEBUG(Kernel_SVC, "called handle 0x{:08X}", handle);
|
||||
@@ -2317,69 +2380,196 @@ struct FunctionDef {
|
||||
};
|
||||
} // namespace
|
||||
|
||||
static const FunctionDef SVC_Table[] = {
|
||||
static const FunctionDef SVC_Table_32[] = {
|
||||
{0x00, nullptr, "Unknown"},
|
||||
{0x01, SvcWrap<SetHeapSize>, "SetHeapSize"},
|
||||
{0x02, SvcWrap<SetMemoryPermission>, "SetMemoryPermission"},
|
||||
{0x03, SvcWrap<SetMemoryAttribute>, "SetMemoryAttribute"},
|
||||
{0x04, SvcWrap<MapMemory>, "MapMemory"},
|
||||
{0x05, SvcWrap<UnmapMemory>, "UnmapMemory"},
|
||||
{0x06, SvcWrap<QueryMemory>, "QueryMemory"},
|
||||
{0x07, SvcWrap<ExitProcess>, "ExitProcess"},
|
||||
{0x08, SvcWrap<CreateThread>, "CreateThread"},
|
||||
{0x09, SvcWrap<StartThread>, "StartThread"},
|
||||
{0x0A, SvcWrap<ExitThread>, "ExitThread"},
|
||||
{0x0B, SvcWrap<SleepThread>, "SleepThread"},
|
||||
{0x0C, SvcWrap<GetThreadPriority>, "GetThreadPriority"},
|
||||
{0x0D, SvcWrap<SetThreadPriority>, "SetThreadPriority"},
|
||||
{0x0E, SvcWrap<GetThreadCoreMask>, "GetThreadCoreMask"},
|
||||
{0x0F, SvcWrap<SetThreadCoreMask>, "SetThreadCoreMask"},
|
||||
{0x10, SvcWrap<GetCurrentProcessorNumber>, "GetCurrentProcessorNumber"},
|
||||
{0x11, SvcWrap<SignalEvent>, "SignalEvent"},
|
||||
{0x12, SvcWrap<ClearEvent>, "ClearEvent"},
|
||||
{0x13, SvcWrap<MapSharedMemory>, "MapSharedMemory"},
|
||||
{0x14, SvcWrap<UnmapSharedMemory>, "UnmapSharedMemory"},
|
||||
{0x15, SvcWrap<CreateTransferMemory>, "CreateTransferMemory"},
|
||||
{0x16, SvcWrap<CloseHandle>, "CloseHandle"},
|
||||
{0x17, SvcWrap<ResetSignal>, "ResetSignal"},
|
||||
{0x18, SvcWrap<WaitSynchronization>, "WaitSynchronization"},
|
||||
{0x19, SvcWrap<CancelSynchronization>, "CancelSynchronization"},
|
||||
{0x1A, SvcWrap<ArbitrateLock>, "ArbitrateLock"},
|
||||
{0x1B, SvcWrap<ArbitrateUnlock>, "ArbitrateUnlock"},
|
||||
{0x1C, SvcWrap<WaitProcessWideKeyAtomic>, "WaitProcessWideKeyAtomic"},
|
||||
{0x1D, SvcWrap<SignalProcessWideKey>, "SignalProcessWideKey"},
|
||||
{0x1E, SvcWrap<GetSystemTick>, "GetSystemTick"},
|
||||
{0x1F, SvcWrap<ConnectToNamedPort>, "ConnectToNamedPort"},
|
||||
{0x01, SvcWrap32<SetHeapSize32>, "SetHeapSize32"},
|
||||
{0x02, nullptr, "Unknown"},
|
||||
{0x03, nullptr, "SetMemoryAttribute32"},
|
||||
{0x04, nullptr, "MapMemory32"},
|
||||
{0x05, nullptr, "UnmapMemory32"},
|
||||
{0x06, SvcWrap32<QueryMemory32>, "QueryMemory32"},
|
||||
{0x07, nullptr, "ExitProcess32"},
|
||||
{0x08, nullptr, "CreateThread32"},
|
||||
{0x09, nullptr, "StartThread32"},
|
||||
{0x0a, nullptr, "ExitThread32"},
|
||||
{0x0b, nullptr, "SleepThread32"},
|
||||
{0x0c, SvcWrap32<GetThreadPriority32>, "GetThreadPriority32"},
|
||||
{0x0d, nullptr, "SetThreadPriority32"},
|
||||
{0x0e, nullptr, "GetThreadCoreMask32"},
|
||||
{0x0f, nullptr, "SetThreadCoreMask32"},
|
||||
{0x10, nullptr, "GetCurrentProcessorNumber32"},
|
||||
{0x11, nullptr, "SignalEvent32"},
|
||||
{0x12, nullptr, "ClearEvent32"},
|
||||
{0x13, nullptr, "MapSharedMemory32"},
|
||||
{0x14, nullptr, "UnmapSharedMemory32"},
|
||||
{0x15, nullptr, "CreateTransferMemory32"},
|
||||
{0x16, SvcWrap32<CloseHandle32>, "CloseHandle32"},
|
||||
{0x17, nullptr, "ResetSignal32"},
|
||||
{0x18, SvcWrap32<WaitSynchronization32>, "WaitSynchronization32"},
|
||||
{0x19, nullptr, "CancelSynchronization32"},
|
||||
{0x1a, nullptr, "ArbitrateLock32"},
|
||||
{0x1b, nullptr, "ArbitrateUnlock32"},
|
||||
{0x1c, nullptr, "WaitProcessWideKeyAtomic32"},
|
||||
{0x1d, SvcWrap32<SignalProcessWideKey32>, "SignalProcessWideKey32"},
|
||||
{0x1e, nullptr, "GetSystemTick32"},
|
||||
{0x1f, SvcWrap32<ConnectToNamedPort32>, "ConnectToNamedPort32"},
|
||||
{0x20, nullptr, "Unknown"},
|
||||
{0x21, SvcWrap32<SendSyncRequest32>, "SendSyncRequest32"},
|
||||
{0x22, nullptr, "SendSyncRequestWithUserBuffer32"},
|
||||
{0x23, nullptr, "Unknown"},
|
||||
{0x24, nullptr, "GetProcessId32"},
|
||||
{0x25, SvcWrap32<GetThreadId32>, "GetThreadId32"},
|
||||
{0x26, nullptr, "Break32"},
|
||||
{0x27, nullptr, "OutputDebugString32"},
|
||||
{0x28, nullptr, "Unknown"},
|
||||
{0x29, SvcWrap32<GetInfo32>, "GetInfo32"},
|
||||
{0x2a, nullptr, "Unknown"},
|
||||
{0x2b, nullptr, "Unknown"},
|
||||
{0x2c, nullptr, "MapPhysicalMemory32"},
|
||||
{0x2d, nullptr, "UnmapPhysicalMemory32"},
|
||||
{0x2e, nullptr, "Unknown"},
|
||||
{0x2f, nullptr, "Unknown"},
|
||||
{0x30, nullptr, "Unknown"},
|
||||
{0x31, nullptr, "Unknown"},
|
||||
{0x32, nullptr, "SetThreadActivity32"},
|
||||
{0x33, nullptr, "GetThreadContext32"},
|
||||
{0x34, nullptr, "WaitForAddress32"},
|
||||
{0x35, nullptr, "SignalToAddress32"},
|
||||
{0x36, nullptr, "Unknown"},
|
||||
{0x37, nullptr, "Unknown"},
|
||||
{0x38, nullptr, "Unknown"},
|
||||
{0x39, nullptr, "Unknown"},
|
||||
{0x3a, nullptr, "Unknown"},
|
||||
{0x3b, nullptr, "Unknown"},
|
||||
{0x3c, nullptr, "Unknown"},
|
||||
{0x3d, nullptr, "Unknown"},
|
||||
{0x3e, nullptr, "Unknown"},
|
||||
{0x3f, nullptr, "Unknown"},
|
||||
{0x40, nullptr, "CreateSession32"},
|
||||
{0x41, nullptr, "AcceptSession32"},
|
||||
{0x42, nullptr, "Unknown"},
|
||||
{0x43, nullptr, "ReplyAndReceive32"},
|
||||
{0x44, nullptr, "Unknown"},
|
||||
{0x45, nullptr, "CreateEvent32"},
|
||||
{0x46, nullptr, "Unknown"},
|
||||
{0x47, nullptr, "Unknown"},
|
||||
{0x48, nullptr, "Unknown"},
|
||||
{0x49, nullptr, "Unknown"},
|
||||
{0x4a, nullptr, "Unknown"},
|
||||
{0x4b, nullptr, "Unknown"},
|
||||
{0x4c, nullptr, "Unknown"},
|
||||
{0x4d, nullptr, "Unknown"},
|
||||
{0x4e, nullptr, "Unknown"},
|
||||
{0x4f, nullptr, "Unknown"},
|
||||
{0x50, nullptr, "Unknown"},
|
||||
{0x51, nullptr, "Unknown"},
|
||||
{0x52, nullptr, "Unknown"},
|
||||
{0x53, nullptr, "Unknown"},
|
||||
{0x54, nullptr, "Unknown"},
|
||||
{0x55, nullptr, "Unknown"},
|
||||
{0x56, nullptr, "Unknown"},
|
||||
{0x57, nullptr, "Unknown"},
|
||||
{0x58, nullptr, "Unknown"},
|
||||
{0x59, nullptr, "Unknown"},
|
||||
{0x5a, nullptr, "Unknown"},
|
||||
{0x5b, nullptr, "Unknown"},
|
||||
{0x5c, nullptr, "Unknown"},
|
||||
{0x5d, nullptr, "Unknown"},
|
||||
{0x5e, nullptr, "Unknown"},
|
||||
{0x5F, nullptr, "FlushProcessDataCache32"},
|
||||
{0x60, nullptr, "Unknown"},
|
||||
{0x61, nullptr, "Unknown"},
|
||||
{0x62, nullptr, "Unknown"},
|
||||
{0x63, nullptr, "Unknown"},
|
||||
{0x64, nullptr, "Unknown"},
|
||||
{0x65, nullptr, "GetProcessList32"},
|
||||
{0x66, nullptr, "Unknown"},
|
||||
{0x67, nullptr, "Unknown"},
|
||||
{0x68, nullptr, "Unknown"},
|
||||
{0x69, nullptr, "Unknown"},
|
||||
{0x6A, nullptr, "Unknown"},
|
||||
{0x6B, nullptr, "Unknown"},
|
||||
{0x6C, nullptr, "Unknown"},
|
||||
{0x6D, nullptr, "Unknown"},
|
||||
{0x6E, nullptr, "Unknown"},
|
||||
{0x6f, nullptr, "GetSystemInfo32"},
|
||||
{0x70, nullptr, "CreatePort32"},
|
||||
{0x71, nullptr, "ManageNamedPort32"},
|
||||
{0x72, nullptr, "ConnectToPort32"},
|
||||
{0x73, nullptr, "SetProcessMemoryPermission32"},
|
||||
{0x74, nullptr, "Unknown"},
|
||||
{0x75, nullptr, "Unknown"},
|
||||
{0x76, nullptr, "Unknown"},
|
||||
{0x77, nullptr, "MapProcessCodeMemory32"},
|
||||
{0x78, nullptr, "UnmapProcessCodeMemory32"},
|
||||
{0x79, nullptr, "Unknown"},
|
||||
{0x7A, nullptr, "Unknown"},
|
||||
{0x7B, nullptr, "TerminateProcess32"},
|
||||
};
|
||||
|
||||
static const FunctionDef SVC_Table_64[] = {
|
||||
{0x00, nullptr, "Unknown"},
|
||||
{0x01, SvcWrap64<SetHeapSize>, "SetHeapSize"},
|
||||
{0x02, SvcWrap64<SetMemoryPermission>, "SetMemoryPermission"},
|
||||
{0x03, SvcWrap64<SetMemoryAttribute>, "SetMemoryAttribute"},
|
||||
{0x04, SvcWrap64<MapMemory>, "MapMemory"},
|
||||
{0x05, SvcWrap64<UnmapMemory>, "UnmapMemory"},
|
||||
{0x06, SvcWrap64<QueryMemory>, "QueryMemory"},
|
||||
{0x07, SvcWrap64<ExitProcess>, "ExitProcess"},
|
||||
{0x08, SvcWrap64<CreateThread>, "CreateThread"},
|
||||
{0x09, SvcWrap64<StartThread>, "StartThread"},
|
||||
{0x0A, SvcWrap64<ExitThread>, "ExitThread"},
|
||||
{0x0B, SvcWrap64<SleepThread>, "SleepThread"},
|
||||
{0x0C, SvcWrap64<GetThreadPriority>, "GetThreadPriority"},
|
||||
{0x0D, SvcWrap64<SetThreadPriority>, "SetThreadPriority"},
|
||||
{0x0E, SvcWrap64<GetThreadCoreMask>, "GetThreadCoreMask"},
|
||||
{0x0F, SvcWrap64<SetThreadCoreMask>, "SetThreadCoreMask"},
|
||||
{0x10, SvcWrap64<GetCurrentProcessorNumber>, "GetCurrentProcessorNumber"},
|
||||
{0x11, SvcWrap64<SignalEvent>, "SignalEvent"},
|
||||
{0x12, SvcWrap64<ClearEvent>, "ClearEvent"},
|
||||
{0x13, SvcWrap64<MapSharedMemory>, "MapSharedMemory"},
|
||||
{0x14, SvcWrap64<UnmapSharedMemory>, "UnmapSharedMemory"},
|
||||
{0x15, SvcWrap64<CreateTransferMemory>, "CreateTransferMemory"},
|
||||
{0x16, SvcWrap64<CloseHandle>, "CloseHandle"},
|
||||
{0x17, SvcWrap64<ResetSignal>, "ResetSignal"},
|
||||
{0x18, SvcWrap64<WaitSynchronization>, "WaitSynchronization"},
|
||||
{0x19, SvcWrap64<CancelSynchronization>, "CancelSynchronization"},
|
||||
{0x1A, SvcWrap64<ArbitrateLock>, "ArbitrateLock"},
|
||||
{0x1B, SvcWrap64<ArbitrateUnlock>, "ArbitrateUnlock"},
|
||||
{0x1C, SvcWrap64<WaitProcessWideKeyAtomic>, "WaitProcessWideKeyAtomic"},
|
||||
{0x1D, SvcWrap64<SignalProcessWideKey>, "SignalProcessWideKey"},
|
||||
{0x1E, SvcWrap64<GetSystemTick>, "GetSystemTick"},
|
||||
{0x1F, SvcWrap64<ConnectToNamedPort>, "ConnectToNamedPort"},
|
||||
{0x20, nullptr, "SendSyncRequestLight"},
|
||||
{0x21, SvcWrap<SendSyncRequest>, "SendSyncRequest"},
|
||||
{0x21, SvcWrap64<SendSyncRequest>, "SendSyncRequest"},
|
||||
{0x22, nullptr, "SendSyncRequestWithUserBuffer"},
|
||||
{0x23, nullptr, "SendAsyncRequestWithUserBuffer"},
|
||||
{0x24, SvcWrap<GetProcessId>, "GetProcessId"},
|
||||
{0x25, SvcWrap<GetThreadId>, "GetThreadId"},
|
||||
{0x26, SvcWrap<Break>, "Break"},
|
||||
{0x27, SvcWrap<OutputDebugString>, "OutputDebugString"},
|
||||
{0x24, SvcWrap64<GetProcessId>, "GetProcessId"},
|
||||
{0x25, SvcWrap64<GetThreadId>, "GetThreadId"},
|
||||
{0x26, SvcWrap64<Break>, "Break"},
|
||||
{0x27, SvcWrap64<OutputDebugString>, "OutputDebugString"},
|
||||
{0x28, nullptr, "ReturnFromException"},
|
||||
{0x29, SvcWrap<GetInfo>, "GetInfo"},
|
||||
{0x29, SvcWrap64<GetInfo>, "GetInfo"},
|
||||
{0x2A, nullptr, "FlushEntireDataCache"},
|
||||
{0x2B, nullptr, "FlushDataCache"},
|
||||
{0x2C, SvcWrap<MapPhysicalMemory>, "MapPhysicalMemory"},
|
||||
{0x2D, SvcWrap<UnmapPhysicalMemory>, "UnmapPhysicalMemory"},
|
||||
{0x2C, SvcWrap64<MapPhysicalMemory>, "MapPhysicalMemory"},
|
||||
{0x2D, SvcWrap64<UnmapPhysicalMemory>, "UnmapPhysicalMemory"},
|
||||
{0x2E, nullptr, "GetFutureThreadInfo"},
|
||||
{0x2F, nullptr, "GetLastThreadInfo"},
|
||||
{0x30, SvcWrap<GetResourceLimitLimitValue>, "GetResourceLimitLimitValue"},
|
||||
{0x31, SvcWrap<GetResourceLimitCurrentValue>, "GetResourceLimitCurrentValue"},
|
||||
{0x32, SvcWrap<SetThreadActivity>, "SetThreadActivity"},
|
||||
{0x33, SvcWrap<GetThreadContext>, "GetThreadContext"},
|
||||
{0x34, SvcWrap<WaitForAddress>, "WaitForAddress"},
|
||||
{0x35, SvcWrap<SignalToAddress>, "SignalToAddress"},
|
||||
{0x30, SvcWrap64<GetResourceLimitLimitValue>, "GetResourceLimitLimitValue"},
|
||||
{0x31, SvcWrap64<GetResourceLimitCurrentValue>, "GetResourceLimitCurrentValue"},
|
||||
{0x32, SvcWrap64<SetThreadActivity>, "SetThreadActivity"},
|
||||
{0x33, SvcWrap64<GetThreadContext>, "GetThreadContext"},
|
||||
{0x34, SvcWrap64<WaitForAddress>, "WaitForAddress"},
|
||||
{0x35, SvcWrap64<SignalToAddress>, "SignalToAddress"},
|
||||
{0x36, nullptr, "SynchronizePreemptionState"},
|
||||
{0x37, nullptr, "Unknown"},
|
||||
{0x38, nullptr, "Unknown"},
|
||||
{0x39, nullptr, "Unknown"},
|
||||
{0x3A, nullptr, "Unknown"},
|
||||
{0x3B, nullptr, "Unknown"},
|
||||
{0x3C, SvcWrap<KernelDebug>, "KernelDebug"},
|
||||
{0x3D, SvcWrap<ChangeKernelTraceState>, "ChangeKernelTraceState"},
|
||||
{0x3C, SvcWrap64<KernelDebug>, "KernelDebug"},
|
||||
{0x3D, SvcWrap64<ChangeKernelTraceState>, "ChangeKernelTraceState"},
|
||||
{0x3E, nullptr, "Unknown"},
|
||||
{0x3F, nullptr, "Unknown"},
|
||||
{0x40, nullptr, "CreateSession"},
|
||||
@@ -2387,7 +2577,7 @@ static const FunctionDef SVC_Table[] = {
|
||||
{0x42, nullptr, "ReplyAndReceiveLight"},
|
||||
{0x43, nullptr, "ReplyAndReceive"},
|
||||
{0x44, nullptr, "ReplyAndReceiveWithUserBuffer"},
|
||||
{0x45, SvcWrap<CreateEvent>, "CreateEvent"},
|
||||
{0x45, SvcWrap64<CreateEvent>, "CreateEvent"},
|
||||
{0x46, nullptr, "Unknown"},
|
||||
{0x47, nullptr, "Unknown"},
|
||||
{0x48, nullptr, "MapPhysicalMemoryUnsafe"},
|
||||
@@ -2398,9 +2588,9 @@ static const FunctionDef SVC_Table[] = {
|
||||
{0x4D, nullptr, "SleepSystem"},
|
||||
{0x4E, nullptr, "ReadWriteRegister"},
|
||||
{0x4F, nullptr, "SetProcessActivity"},
|
||||
{0x50, SvcWrap<CreateSharedMemory>, "CreateSharedMemory"},
|
||||
{0x51, SvcWrap<MapTransferMemory>, "MapTransferMemory"},
|
||||
{0x52, SvcWrap<UnmapTransferMemory>, "UnmapTransferMemory"},
|
||||
{0x50, SvcWrap64<CreateSharedMemory>, "CreateSharedMemory"},
|
||||
{0x51, SvcWrap64<MapTransferMemory>, "MapTransferMemory"},
|
||||
{0x52, SvcWrap64<UnmapTransferMemory>, "UnmapTransferMemory"},
|
||||
{0x53, nullptr, "CreateInterruptEvent"},
|
||||
{0x54, nullptr, "QueryPhysicalAddress"},
|
||||
{0x55, nullptr, "QueryIoMapping"},
|
||||
@@ -2419,8 +2609,8 @@ static const FunctionDef SVC_Table[] = {
|
||||
{0x62, nullptr, "TerminateDebugProcess"},
|
||||
{0x63, nullptr, "GetDebugEvent"},
|
||||
{0x64, nullptr, "ContinueDebugEvent"},
|
||||
{0x65, SvcWrap<GetProcessList>, "GetProcessList"},
|
||||
{0x66, SvcWrap<GetThreadList>, "GetThreadList"},
|
||||
{0x65, SvcWrap64<GetProcessList>, "GetProcessList"},
|
||||
{0x66, SvcWrap64<GetThreadList>, "GetThreadList"},
|
||||
{0x67, nullptr, "GetDebugThreadContext"},
|
||||
{0x68, nullptr, "SetDebugThreadContext"},
|
||||
{0x69, nullptr, "QueryDebugProcessMemory"},
|
||||
@@ -2436,24 +2626,32 @@ static const FunctionDef SVC_Table[] = {
|
||||
{0x73, nullptr, "SetProcessMemoryPermission"},
|
||||
{0x74, nullptr, "MapProcessMemory"},
|
||||
{0x75, nullptr, "UnmapProcessMemory"},
|
||||
{0x76, SvcWrap<QueryProcessMemory>, "QueryProcessMemory"},
|
||||
{0x77, SvcWrap<MapProcessCodeMemory>, "MapProcessCodeMemory"},
|
||||
{0x78, SvcWrap<UnmapProcessCodeMemory>, "UnmapProcessCodeMemory"},
|
||||
{0x76, SvcWrap64<QueryProcessMemory>, "QueryProcessMemory"},
|
||||
{0x77, SvcWrap64<MapProcessCodeMemory>, "MapProcessCodeMemory"},
|
||||
{0x78, SvcWrap64<UnmapProcessCodeMemory>, "UnmapProcessCodeMemory"},
|
||||
{0x79, nullptr, "CreateProcess"},
|
||||
{0x7A, nullptr, "StartProcess"},
|
||||
{0x7B, nullptr, "TerminateProcess"},
|
||||
{0x7C, SvcWrap<GetProcessInfo>, "GetProcessInfo"},
|
||||
{0x7D, SvcWrap<CreateResourceLimit>, "CreateResourceLimit"},
|
||||
{0x7E, SvcWrap<SetResourceLimitLimitValue>, "SetResourceLimitLimitValue"},
|
||||
{0x7C, SvcWrap64<GetProcessInfo>, "GetProcessInfo"},
|
||||
{0x7D, SvcWrap64<CreateResourceLimit>, "CreateResourceLimit"},
|
||||
{0x7E, SvcWrap64<SetResourceLimitLimitValue>, "SetResourceLimitLimitValue"},
|
||||
{0x7F, nullptr, "CallSecureMonitor"},
|
||||
};
|
||||
|
||||
static const FunctionDef* GetSVCInfo(u32 func_num) {
|
||||
if (func_num >= std::size(SVC_Table)) {
|
||||
static const FunctionDef* GetSVCInfo32(u32 func_num) {
|
||||
if (func_num >= std::size(SVC_Table_32)) {
|
||||
LOG_ERROR(Kernel_SVC, "Unknown svc=0x{:02X}", func_num);
|
||||
return nullptr;
|
||||
}
|
||||
return &SVC_Table[func_num];
|
||||
return &SVC_Table_32[func_num];
|
||||
}
|
||||
|
||||
static const FunctionDef* GetSVCInfo64(u32 func_num) {
|
||||
if (func_num >= std::size(SVC_Table_64)) {
|
||||
LOG_ERROR(Kernel_SVC, "Unknown svc=0x{:02X}", func_num);
|
||||
return nullptr;
|
||||
}
|
||||
return &SVC_Table_64[func_num];
|
||||
}
|
||||
|
||||
MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70));
|
||||
@@ -2464,7 +2662,8 @@ void CallSVC(Core::System& system, u32 immediate) {
|
||||
// Lock the global kernel mutex when we enter the kernel HLE.
|
||||
std::lock_guard lock{HLE::g_hle_lock};
|
||||
|
||||
const FunctionDef* info = GetSVCInfo(immediate);
|
||||
const FunctionDef* info = system.CurrentProcess()->Is64BitProcess() ? GetSVCInfo64(immediate)
|
||||
: GetSVCInfo32(immediate);
|
||||
if (info) {
|
||||
if (info->func) {
|
||||
info->func(system);
|
||||
|
||||
@@ -15,6 +15,10 @@ static inline u64 Param(const Core::System& system, int n) {
|
||||
return system.CurrentArmInterface().GetReg(n);
|
||||
}
|
||||
|
||||
static inline u32 Param32(const Core::System& system, int n) {
|
||||
return static_cast<u32>(system.CurrentArmInterface().GetReg(n));
|
||||
}
|
||||
|
||||
/**
|
||||
* HLE a function return from the current ARM userland process
|
||||
* @param system System context
|
||||
@@ -24,40 +28,44 @@ static inline void FuncReturn(Core::System& system, u64 result) {
|
||||
system.CurrentArmInterface().SetReg(0, result);
|
||||
}
|
||||
|
||||
static inline void FuncReturn32(Core::System& system, u32 result) {
|
||||
system.CurrentArmInterface().SetReg(0, (u64)result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Function wrappers that return type ResultCode
|
||||
|
||||
template <ResultCode func(Core::System&, u64)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
FuncReturn(system, func(system, Param(system, 0)).raw);
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u64, u64)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
FuncReturn(system, func(system, Param(system, 0), Param(system, 1)).raw);
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u32)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
FuncReturn(system, func(system, static_cast<u32>(Param(system, 0))).raw);
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u32, u32)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
FuncReturn(
|
||||
system,
|
||||
func(system, static_cast<u32>(Param(system, 0)), static_cast<u32>(Param(system, 1))).raw);
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u32, u64, u64, u64)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1),
|
||||
Param(system, 2), Param(system, 3))
|
||||
.raw);
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u32*)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
u32 param = 0;
|
||||
const u32 retval = func(system, ¶m).raw;
|
||||
system.CurrentArmInterface().SetReg(1, param);
|
||||
@@ -65,7 +73,7 @@ void SvcWrap(Core::System& system) {
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u32*, u32)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
u32 param_1 = 0;
|
||||
const u32 retval = func(system, ¶m_1, static_cast<u32>(Param(system, 1))).raw;
|
||||
system.CurrentArmInterface().SetReg(1, param_1);
|
||||
@@ -73,7 +81,7 @@ void SvcWrap(Core::System& system) {
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u32*, u32*)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
u32 param_1 = 0;
|
||||
u32 param_2 = 0;
|
||||
const u32 retval = func(system, ¶m_1, ¶m_2).raw;
|
||||
@@ -86,7 +94,7 @@ void SvcWrap(Core::System& system) {
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u32*, u64)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
u32 param_1 = 0;
|
||||
const u32 retval = func(system, ¶m_1, Param(system, 1)).raw;
|
||||
system.CurrentArmInterface().SetReg(1, param_1);
|
||||
@@ -94,7 +102,7 @@ void SvcWrap(Core::System& system) {
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u32*, u64, u32)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
u32 param_1 = 0;
|
||||
const u32 retval =
|
||||
func(system, ¶m_1, Param(system, 1), static_cast<u32>(Param(system, 2))).raw;
|
||||
@@ -104,7 +112,7 @@ void SvcWrap(Core::System& system) {
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u64*, u32)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
u64 param_1 = 0;
|
||||
const u32 retval = func(system, ¶m_1, static_cast<u32>(Param(system, 1))).raw;
|
||||
|
||||
@@ -113,12 +121,12 @@ void SvcWrap(Core::System& system) {
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u64, u32)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
FuncReturn(system, func(system, Param(system, 0), static_cast<u32>(Param(system, 1))).raw);
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u64*, u64)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
u64 param_1 = 0;
|
||||
const u32 retval = func(system, ¶m_1, Param(system, 1)).raw;
|
||||
|
||||
@@ -127,7 +135,7 @@ void SvcWrap(Core::System& system) {
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u64*, u32, u32)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
u64 param_1 = 0;
|
||||
const u32 retval = func(system, ¶m_1, static_cast<u32>(Param(system, 1)),
|
||||
static_cast<u32>(Param(system, 2)))
|
||||
@@ -138,19 +146,19 @@ void SvcWrap(Core::System& system) {
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u32, u64)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1)).raw);
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u32, u32, u64)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)),
|
||||
static_cast<u32>(Param(system, 1)), Param(system, 2))
|
||||
.raw);
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u32, u32*, u64*)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
u32 param_1 = 0;
|
||||
u64 param_2 = 0;
|
||||
const ResultCode retval = func(system, static_cast<u32>(Param(system, 2)), ¶m_1, ¶m_2);
|
||||
@@ -161,54 +169,54 @@ void SvcWrap(Core::System& system) {
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u64, u64, u32, u32)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
FuncReturn(system, func(system, Param(system, 0), Param(system, 1),
|
||||
static_cast<u32>(Param(system, 2)), static_cast<u32>(Param(system, 3)))
|
||||
.raw);
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u64, u64, u32, u64)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
FuncReturn(system, func(system, Param(system, 0), Param(system, 1),
|
||||
static_cast<u32>(Param(system, 2)), Param(system, 3))
|
||||
.raw);
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u32, u64, u32)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1),
|
||||
static_cast<u32>(Param(system, 2)))
|
||||
.raw);
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u64, u64, u64)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
FuncReturn(system, func(system, Param(system, 0), Param(system, 1), Param(system, 2)).raw);
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u64, u64, u32)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
FuncReturn(
|
||||
system,
|
||||
func(system, Param(system, 0), Param(system, 1), static_cast<u32>(Param(system, 2))).raw);
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u32, u64, u64, u32)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1),
|
||||
Param(system, 2), static_cast<u32>(Param(system, 3)))
|
||||
.raw);
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u32, u64, u64)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
FuncReturn(
|
||||
system,
|
||||
func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), Param(system, 2)).raw);
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u32*, u64, u64, s64)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
u32 param_1 = 0;
|
||||
const u32 retval = func(system, ¶m_1, Param(system, 1), static_cast<u32>(Param(system, 2)),
|
||||
static_cast<s64>(Param(system, 3)))
|
||||
@@ -219,14 +227,14 @@ void SvcWrap(Core::System& system) {
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u64, u64, u32, s64)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
FuncReturn(system, func(system, Param(system, 0), Param(system, 1),
|
||||
static_cast<u32>(Param(system, 2)), static_cast<s64>(Param(system, 3)))
|
||||
.raw);
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u64*, u64, u64, u64)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
u64 param_1 = 0;
|
||||
const u32 retval =
|
||||
func(system, ¶m_1, Param(system, 1), Param(system, 2), Param(system, 3)).raw;
|
||||
@@ -236,7 +244,7 @@ void SvcWrap(Core::System& system) {
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u32*, u64, u64, u64, u32, s32)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
u32 param_1 = 0;
|
||||
const u32 retval = func(system, ¶m_1, Param(system, 1), Param(system, 2), Param(system, 3),
|
||||
static_cast<u32>(Param(system, 4)), static_cast<s32>(Param(system, 5)))
|
||||
@@ -247,7 +255,7 @@ void SvcWrap(Core::System& system) {
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u32*, u64, u64, u32)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
u32 param_1 = 0;
|
||||
const u32 retval = func(system, ¶m_1, Param(system, 1), Param(system, 2),
|
||||
static_cast<u32>(Param(system, 3)))
|
||||
@@ -258,7 +266,7 @@ void SvcWrap(Core::System& system) {
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, Handle*, u64, u32, u32)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
u32 param_1 = 0;
|
||||
const u32 retval = func(system, ¶m_1, Param(system, 1), static_cast<u32>(Param(system, 2)),
|
||||
static_cast<u32>(Param(system, 3)))
|
||||
@@ -269,14 +277,14 @@ void SvcWrap(Core::System& system) {
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u64, u32, s32, s64)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
FuncReturn(system, func(system, Param(system, 0), static_cast<u32>(Param(system, 1)),
|
||||
static_cast<s32>(Param(system, 2)), static_cast<s64>(Param(system, 3)))
|
||||
.raw);
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u64, u32, s32, s32)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
FuncReturn(system, func(system, Param(system, 0), static_cast<u32>(Param(system, 1)),
|
||||
static_cast<s32>(Param(system, 2)), static_cast<s32>(Param(system, 3)))
|
||||
.raw);
|
||||
@@ -286,7 +294,7 @@ void SvcWrap(Core::System& system) {
|
||||
// Function wrappers that return type u32
|
||||
|
||||
template <u32 func(Core::System&)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
FuncReturn(system, func(system));
|
||||
}
|
||||
|
||||
@@ -294,7 +302,7 @@ void SvcWrap(Core::System& system) {
|
||||
// Function wrappers that return type u64
|
||||
|
||||
template <u64 func(Core::System&)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
FuncReturn(system, func(system));
|
||||
}
|
||||
|
||||
@@ -302,44 +310,110 @@ void SvcWrap(Core::System& system) {
|
||||
/// Function wrappers that return type void
|
||||
|
||||
template <void func(Core::System&)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
func(system);
|
||||
}
|
||||
|
||||
template <void func(Core::System&, u32)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
func(system, static_cast<u32>(Param(system, 0)));
|
||||
}
|
||||
|
||||
template <void func(Core::System&, u32, u64, u64, u64)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), Param(system, 2),
|
||||
Param(system, 3));
|
||||
}
|
||||
|
||||
template <void func(Core::System&, s64)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
func(system, static_cast<s64>(Param(system, 0)));
|
||||
}
|
||||
|
||||
template <void func(Core::System&, u64, s32)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
func(system, Param(system, 0), static_cast<s32>(Param(system, 1)));
|
||||
}
|
||||
|
||||
template <void func(Core::System&, u64, u64)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
func(system, Param(system, 0), Param(system, 1));
|
||||
}
|
||||
|
||||
template <void func(Core::System&, u64, u64, u64)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
func(system, Param(system, 0), Param(system, 1), Param(system, 2));
|
||||
}
|
||||
|
||||
template <void func(Core::System&, u32, u64, u64)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
void SvcWrap64(Core::System& system) {
|
||||
func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), Param(system, 2));
|
||||
}
|
||||
|
||||
// Used by QueryMemory32
|
||||
template <ResultCode func(Core::System&, u32, u32, u32)>
|
||||
void SvcWrap32(Core::System& system) {
|
||||
FuncReturn32(system,
|
||||
func(system, Param32(system, 0), Param32(system, 1), Param32(system, 2)).raw);
|
||||
}
|
||||
|
||||
// Used by GetInfo32
|
||||
template <ResultCode func(Core::System&, u32*, u32*, u32, u32, u32, u32)>
|
||||
void SvcWrap32(Core::System& system) {
|
||||
u32 param_1 = 0;
|
||||
u32 param_2 = 0;
|
||||
|
||||
const u32 retval = func(system, ¶m_1, ¶m_2, Param32(system, 0), Param32(system, 1),
|
||||
Param32(system, 2), Param32(system, 3))
|
||||
.raw;
|
||||
|
||||
system.CurrentArmInterface().SetReg(1, param_1);
|
||||
system.CurrentArmInterface().SetReg(2, param_2);
|
||||
FuncReturn(system, retval);
|
||||
}
|
||||
|
||||
// Used by GetThreadPriority32, ConnectToNamedPort32
|
||||
template <ResultCode func(Core::System&, u32*, u32)>
|
||||
void SvcWrap32(Core::System& system) {
|
||||
u32 param_1 = 0;
|
||||
const u32 retval = func(system, ¶m_1, Param32(system, 1)).raw;
|
||||
system.CurrentArmInterface().SetReg(1, param_1);
|
||||
FuncReturn(system, retval);
|
||||
}
|
||||
|
||||
// Used by GetThreadId32
|
||||
template <ResultCode func(Core::System&, u32*, u32*, u32)>
|
||||
void SvcWrap32(Core::System& system) {
|
||||
u32 param_1 = 0;
|
||||
u32 param_2 = 0;
|
||||
|
||||
const u32 retval = func(system, ¶m_1, ¶m_2, Param32(system, 1)).raw;
|
||||
system.CurrentArmInterface().SetReg(1, param_1);
|
||||
system.CurrentArmInterface().SetReg(2, param_2);
|
||||
FuncReturn(system, retval);
|
||||
}
|
||||
|
||||
// Used by SignalProcessWideKey32
|
||||
template <void func(Core::System&, u32, s32)>
|
||||
void SvcWrap32(Core::System& system) {
|
||||
func(system, static_cast<u32>(Param(system, 0)), static_cast<s32>(Param(system, 1)));
|
||||
}
|
||||
|
||||
// Used by SendSyncRequest32
|
||||
template <ResultCode func(Core::System&, u32)>
|
||||
void SvcWrap32(Core::System& system) {
|
||||
FuncReturn(system, func(system, static_cast<u32>(Param(system, 0))).raw);
|
||||
}
|
||||
|
||||
// Used by WaitSynchronization32
|
||||
template <ResultCode func(Core::System&, u32, u32, s32, u32, Handle*)>
|
||||
void SvcWrap32(Core::System& system) {
|
||||
u32 param_1 = 0;
|
||||
const u32 retval = func(system, Param32(system, 0), Param32(system, 1), Param32(system, 2),
|
||||
Param32(system, 3), ¶m_1)
|
||||
.raw;
|
||||
system.CurrentArmInterface().SetReg(1, param_1);
|
||||
FuncReturn(system, retval);
|
||||
}
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
@@ -133,15 +133,16 @@ void Thread::CancelWait() {
|
||||
ResumeFromWait();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets a thread context, making it ready to be scheduled and run by the CPU
|
||||
* @param context Thread context to reset
|
||||
* @param stack_top Address of the top of the stack
|
||||
* @param entry_point Address of entry point for execution
|
||||
* @param arg User argument for thread
|
||||
*/
|
||||
static void ResetThreadContext(Core::ARM_Interface::ThreadContext& context, VAddr stack_top,
|
||||
VAddr entry_point, u64 arg) {
|
||||
static void ResetThreadContext32(Core::ARM_Interface::ThreadContext32& context, u32 stack_top,
|
||||
u32 entry_point, u32 arg) {
|
||||
context = {};
|
||||
context.cpu_registers[0] = arg;
|
||||
context.cpu_registers[15] = entry_point;
|
||||
context.cpu_registers[13] = stack_top;
|
||||
}
|
||||
|
||||
static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context, VAddr stack_top,
|
||||
VAddr entry_point, u64 arg) {
|
||||
context = {};
|
||||
context.cpu_registers[0] = arg;
|
||||
context.pc = entry_point;
|
||||
@@ -198,9 +199,9 @@ ResultVal<std::shared_ptr<Thread>> Thread::Create(KernelCore& kernel, std::strin
|
||||
|
||||
thread->owner_process->RegisterThread(thread.get());
|
||||
|
||||
// TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used
|
||||
// to initialize the context
|
||||
ResetThreadContext(thread->context, stack_top, entry_point, arg);
|
||||
ResetThreadContext32(thread->context_32, static_cast<u32>(stack_top),
|
||||
static_cast<u32>(entry_point), static_cast<u32>(arg));
|
||||
ResetThreadContext64(thread->context_64, stack_top, entry_point, arg);
|
||||
|
||||
return MakeResult<std::shared_ptr<Thread>>(std::move(thread));
|
||||
}
|
||||
@@ -213,11 +214,13 @@ void Thread::SetPriority(u32 priority) {
|
||||
}
|
||||
|
||||
void Thread::SetWaitSynchronizationResult(ResultCode result) {
|
||||
context.cpu_registers[0] = result.raw;
|
||||
context_32.cpu_registers[0] = result.raw;
|
||||
context_64.cpu_registers[0] = result.raw;
|
||||
}
|
||||
|
||||
void Thread::SetWaitSynchronizationOutput(s32 output) {
|
||||
context.cpu_registers[1] = output;
|
||||
context_32.cpu_registers[1] = output;
|
||||
context_64.cpu_registers[1] = output;
|
||||
}
|
||||
|
||||
s32 Thread::GetSynchronizationObjectIndex(std::shared_ptr<SynchronizationObject> object) const {
|
||||
|
||||
@@ -102,7 +102,8 @@ public:
|
||||
|
||||
using MutexWaitingThreads = std::vector<std::shared_ptr<Thread>>;
|
||||
|
||||
using ThreadContext = Core::ARM_Interface::ThreadContext;
|
||||
using ThreadContext32 = Core::ARM_Interface::ThreadContext32;
|
||||
using ThreadContext64 = Core::ARM_Interface::ThreadContext64;
|
||||
|
||||
using ThreadSynchronizationObjects = std::vector<std::shared_ptr<SynchronizationObject>>;
|
||||
|
||||
@@ -273,12 +274,20 @@ public:
|
||||
return status == ThreadStatus::WaitSynch;
|
||||
}
|
||||
|
||||
ThreadContext& GetContext() {
|
||||
return context;
|
||||
ThreadContext32& GetContext32() {
|
||||
return context_32;
|
||||
}
|
||||
|
||||
const ThreadContext& GetContext() const {
|
||||
return context;
|
||||
const ThreadContext32& GetContext32() const {
|
||||
return context_32;
|
||||
}
|
||||
|
||||
ThreadContext64& GetContext64() {
|
||||
return context_64;
|
||||
}
|
||||
|
||||
const ThreadContext64& GetContext64() const {
|
||||
return context_64;
|
||||
}
|
||||
|
||||
ThreadStatus GetStatus() const {
|
||||
@@ -466,7 +475,8 @@ private:
|
||||
void AdjustSchedulingOnPriority(u32 old_priority);
|
||||
void AdjustSchedulingOnAffinity(u64 old_affinity_mask, s32 old_core);
|
||||
|
||||
Core::ARM_Interface::ThreadContext context{};
|
||||
ThreadContext32 context_32{};
|
||||
ThreadContext64 context_64{};
|
||||
|
||||
u64 thread_id = 0;
|
||||
|
||||
|
||||
@@ -52,6 +52,11 @@ enum class LaunchParameterKind : u32 {
|
||||
AccountPreselectedUser = 2,
|
||||
};
|
||||
|
||||
enum class VrMode : u8 {
|
||||
Disabled = 0,
|
||||
Enabled = 1,
|
||||
};
|
||||
|
||||
constexpr u32 LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC = 0xC79497CA;
|
||||
|
||||
struct LaunchParameterAccountPreselectedUser {
|
||||
@@ -605,11 +610,11 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system,
|
||||
{30, nullptr, "GetHomeButtonReaderLockAccessor"},
|
||||
{31, nullptr, "GetReaderLockAccessorEx"},
|
||||
{40, nullptr, "GetCradleFwVersion"},
|
||||
{50, nullptr, "IsVrModeEnabled"},
|
||||
{51, nullptr, "SetVrModeEnabled"},
|
||||
{50, &ICommonStateGetter::IsVrModeEnabled, "IsVrModeEnabled"},
|
||||
{51, &ICommonStateGetter::SetVrModeEnabled, "SetVrModeEnabled"},
|
||||
{52, &ICommonStateGetter::SetLcdBacklighOffEnabled, "SetLcdBacklighOffEnabled"},
|
||||
{53, nullptr, "BeginVrModeEx"},
|
||||
{54, nullptr, "EndVrModeEx"},
|
||||
{54, &ICommonStateGetter::EndVrModeEx, "EndVrModeEx"},
|
||||
{55, nullptr, "IsInControllerFirmwareUpdateSection"},
|
||||
{60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"},
|
||||
{61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"},
|
||||
@@ -672,6 +677,30 @@ void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) {
|
||||
rb.Push(static_cast<u8>(FocusState::InFocus));
|
||||
}
|
||||
|
||||
void ICommonStateGetter::IsVrModeEnabled(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushEnum(VrMode::Disabled);
|
||||
}
|
||||
|
||||
void ICommonStateGetter::SetVrModeEnabled(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto is_vr_mode_enabled = rp.Pop<bool>();
|
||||
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called. is_vr_mode_enabled={}", is_vr_mode_enabled);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
if (!is_vr_mode_enabled) {
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
} else {
|
||||
// TODO: Find better error code for this
|
||||
UNIMPLEMENTED_MSG("is_vr_mode_enabled={}", is_vr_mode_enabled);
|
||||
rb.Push(RESULT_UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
void ICommonStateGetter::SetLcdBacklighOffEnabled(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto is_lcd_backlight_off_enabled = rp.Pop<bool>();
|
||||
@@ -683,6 +712,13 @@ void ICommonStateGetter::SetLcdBacklighOffEnabled(Kernel::HLERequestContext& ctx
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void ICommonStateGetter::EndVrModeEx(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
|
||||
|
||||
@@ -182,7 +182,10 @@ private:
|
||||
void GetOperationMode(Kernel::HLERequestContext& ctx);
|
||||
void GetPerformanceMode(Kernel::HLERequestContext& ctx);
|
||||
void GetBootMode(Kernel::HLERequestContext& ctx);
|
||||
void IsVrModeEnabled(Kernel::HLERequestContext& ctx);
|
||||
void SetVrModeEnabled(Kernel::HLERequestContext& ctx);
|
||||
void SetLcdBacklighOffEnabled(Kernel::HLERequestContext& ctx);
|
||||
void EndVrModeEx(Kernel::HLERequestContext& ctx);
|
||||
void GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx);
|
||||
void SetCpuBoostMode(Kernel::HLERequestContext& ctx);
|
||||
|
||||
|
||||
@@ -254,6 +254,12 @@ void WebBrowser::Execute() {
|
||||
|
||||
if (status != RESULT_SUCCESS) {
|
||||
complete = true;
|
||||
|
||||
// This is a workaround in order not to softlock yuzu when an error happens during the
|
||||
// webapplet init. In order to avoid an svcBreak, the status is set to RESULT_SUCCESS
|
||||
Finalize();
|
||||
status = RESULT_SUCCESS;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,168 +2,24 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "core/hle/service/caps/caps.h"
|
||||
#include "core/hle/service/caps/caps_a.h"
|
||||
#include "core/hle/service/caps/caps_c.h"
|
||||
#include "core/hle/service/caps/caps_sc.h"
|
||||
#include "core/hle/service/caps/caps_ss.h"
|
||||
#include "core/hle/service/caps/caps_su.h"
|
||||
#include "core/hle/service/caps/caps_u.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
|
||||
namespace Service::Capture {
|
||||
|
||||
class CAPS_A final : public ServiceFramework<CAPS_A> {
|
||||
public:
|
||||
explicit CAPS_A() : ServiceFramework{"caps:a"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetAlbumFileCount"},
|
||||
{1, nullptr, "GetAlbumFileList"},
|
||||
{2, nullptr, "LoadAlbumFile"},
|
||||
{3, nullptr, "DeleteAlbumFile"},
|
||||
{4, nullptr, "StorageCopyAlbumFile"},
|
||||
{5, nullptr, "IsAlbumMounted"},
|
||||
{6, nullptr, "GetAlbumUsage"},
|
||||
{7, nullptr, "GetAlbumFileSize"},
|
||||
{8, nullptr, "LoadAlbumFileThumbnail"},
|
||||
{9, nullptr, "LoadAlbumScreenShotImage"},
|
||||
{10, nullptr, "LoadAlbumScreenShotThumbnailImage"},
|
||||
{11, nullptr, "GetAlbumEntryFromApplicationAlbumEntry"},
|
||||
{12, nullptr, "Unknown12"},
|
||||
{13, nullptr, "Unknown13"},
|
||||
{14, nullptr, "Unknown14"},
|
||||
{15, nullptr, "Unknown15"},
|
||||
{16, nullptr, "Unknown16"},
|
||||
{17, nullptr, "Unknown17"},
|
||||
{18, nullptr, "Unknown18"},
|
||||
{202, nullptr, "SaveEditedScreenShot"},
|
||||
{301, nullptr, "GetLastThumbnail"},
|
||||
{401, nullptr, "GetAutoSavingStorage"},
|
||||
{501, nullptr, "GetRequiredStorageSpaceSizeToCopyAll"},
|
||||
{1001, nullptr, "Unknown1001"},
|
||||
{1002, nullptr, "Unknown1002"},
|
||||
{1003, nullptr, "Unknown1003"},
|
||||
{8001, nullptr, "ForceAlbumUnmounted"},
|
||||
{8002, nullptr, "ResetAlbumMountStatus"},
|
||||
{8011, nullptr, "RefreshAlbumCache"},
|
||||
{8012, nullptr, "GetAlbumCache"},
|
||||
{8013, nullptr, "Unknown8013"},
|
||||
{8021, nullptr, "GetAlbumEntryFromApplicationAlbumEntryAruid"},
|
||||
{10011, nullptr, "SetInternalErrorConversionEnabled"},
|
||||
{50000, nullptr, "Unknown50000"},
|
||||
{60002, nullptr, "Unknown60002"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class CAPS_C final : public ServiceFramework<CAPS_C> {
|
||||
public:
|
||||
explicit CAPS_C() : ServiceFramework{"caps:c"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{33, nullptr, "Unknown33"},
|
||||
{2001, nullptr, "Unknown2001"},
|
||||
{2002, nullptr, "Unknown2002"},
|
||||
{2011, nullptr, "Unknown2011"},
|
||||
{2012, nullptr, "Unknown2012"},
|
||||
{2013, nullptr, "Unknown2013"},
|
||||
{2014, nullptr, "Unknown2014"},
|
||||
{2101, nullptr, "Unknown2101"},
|
||||
{2102, nullptr, "Unknown2102"},
|
||||
{2201, nullptr, "Unknown2201"},
|
||||
{2301, nullptr, "Unknown2301"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class CAPS_SC final : public ServiceFramework<CAPS_SC> {
|
||||
public:
|
||||
explicit CAPS_SC() : ServiceFramework{"caps:sc"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{1, nullptr, "Unknown1"},
|
||||
{2, nullptr, "Unknown2"},
|
||||
{1001, nullptr, "Unknown3"},
|
||||
{1002, nullptr, "Unknown4"},
|
||||
{1003, nullptr, "Unknown5"},
|
||||
{1011, nullptr, "Unknown6"},
|
||||
{1012, nullptr, "Unknown7"},
|
||||
{1201, nullptr, "Unknown8"},
|
||||
{1202, nullptr, "Unknown9"},
|
||||
{1203, nullptr, "Unknown10"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class CAPS_SS final : public ServiceFramework<CAPS_SS> {
|
||||
public:
|
||||
explicit CAPS_SS() : ServiceFramework{"caps:ss"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{201, nullptr, "Unknown1"},
|
||||
{202, nullptr, "Unknown2"},
|
||||
{203, nullptr, "Unknown3"},
|
||||
{204, nullptr, "Unknown4"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class CAPS_SU final : public ServiceFramework<CAPS_SU> {
|
||||
public:
|
||||
explicit CAPS_SU() : ServiceFramework{"caps:su"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{201, nullptr, "SaveScreenShot"},
|
||||
{203, nullptr, "SaveScreenShotEx0"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class CAPS_U final : public ServiceFramework<CAPS_U> {
|
||||
public:
|
||||
explicit CAPS_U() : ServiceFramework{"caps:u"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{32, nullptr, "SetShimLibraryVersion"},
|
||||
{102, nullptr, "GetAlbumFileListByAruid"},
|
||||
{103, nullptr, "DeleteAlbumFileByAruid"},
|
||||
{104, nullptr, "GetAlbumFileSizeByAruid"},
|
||||
{105, nullptr, "DeleteAlbumFileByAruidForDebug"},
|
||||
{110, nullptr, "LoadAlbumScreenShotImageByAruid"},
|
||||
{120, nullptr, "LoadAlbumScreenShotThumbnailImageByAruid"},
|
||||
{130, nullptr, "PrecheckToCreateContentsByAruid"},
|
||||
{140, nullptr, "GetAlbumFileList1AafeAruidDeprecated"},
|
||||
{141, nullptr, "GetAlbumFileList2AafeUidAruidDeprecated"},
|
||||
{142, nullptr, "GetAlbumFileList3AaeAruid"},
|
||||
{143, nullptr, "GetAlbumFileList4AaeUidAruid"},
|
||||
{60002, nullptr, "OpenAccessorSessionForApplication"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& sm) {
|
||||
std::make_shared<CAPS_A>()->InstallAsService(sm);
|
||||
std::make_shared<CAPS_C>()->InstallAsService(sm);
|
||||
std::make_shared<CAPS_U>()->InstallAsService(sm);
|
||||
std::make_shared<CAPS_SC>()->InstallAsService(sm);
|
||||
std::make_shared<CAPS_SS>()->InstallAsService(sm);
|
||||
std::make_shared<CAPS_SU>()->InstallAsService(sm);
|
||||
std::make_shared<CAPS_U>()->InstallAsService(sm);
|
||||
}
|
||||
|
||||
} // namespace Service::Capture
|
||||
|
||||
@@ -4,12 +4,83 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::SM {
|
||||
class ServiceManager;
|
||||
}
|
||||
|
||||
namespace Service::Capture {
|
||||
|
||||
enum AlbumImageOrientation {
|
||||
Orientation0 = 0,
|
||||
Orientation1 = 1,
|
||||
Orientation2 = 2,
|
||||
Orientation3 = 3,
|
||||
};
|
||||
|
||||
enum AlbumReportOption {
|
||||
Disable = 0,
|
||||
Enable = 1,
|
||||
};
|
||||
|
||||
enum ContentType : u8 {
|
||||
Screenshot = 0,
|
||||
Movie = 1,
|
||||
ExtraMovie = 3,
|
||||
};
|
||||
|
||||
enum AlbumStorage : u8 {
|
||||
NAND = 0,
|
||||
SD = 1,
|
||||
};
|
||||
|
||||
struct AlbumFileDateTime {
|
||||
u16 year;
|
||||
u8 month;
|
||||
u8 day;
|
||||
u8 hour;
|
||||
u8 minute;
|
||||
u8 second;
|
||||
u8 uid;
|
||||
};
|
||||
|
||||
struct AlbumEntry {
|
||||
u64 size;
|
||||
u64 application_id;
|
||||
AlbumFileDateTime datetime;
|
||||
AlbumStorage storage;
|
||||
ContentType content;
|
||||
u8 padding[6];
|
||||
};
|
||||
|
||||
struct AlbumFileEntry {
|
||||
u64 size;
|
||||
u64 hash;
|
||||
AlbumFileDateTime datetime;
|
||||
AlbumStorage storage;
|
||||
ContentType content;
|
||||
u8 padding[5];
|
||||
u8 unknown;
|
||||
};
|
||||
|
||||
struct ApplicationAlbumEntry {
|
||||
u64 size;
|
||||
u64 hash;
|
||||
AlbumFileDateTime datetime;
|
||||
AlbumStorage storage;
|
||||
ContentType content;
|
||||
u8 padding[5];
|
||||
u8 unknown;
|
||||
};
|
||||
|
||||
struct ApplicationAlbumFileEntry {
|
||||
ApplicationAlbumEntry entry;
|
||||
AlbumFileDateTime datetime;
|
||||
u64 unknown;
|
||||
};
|
||||
|
||||
/// Registers all Capture services with the specified service manager.
|
||||
void InstallInterfaces(SM::ServiceManager& sm);
|
||||
|
||||
} // namespace Service::Capture
|
||||
|
||||
78
src/core/hle/service/caps/caps_a.cpp
Normal file
78
src/core/hle/service/caps/caps_a.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
// Copyright 2020 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/service/caps/caps_a.h"
|
||||
|
||||
namespace Service::Capture {
|
||||
|
||||
class IAlbumAccessorSession final : public ServiceFramework<IAlbumAccessorSession> {
|
||||
public:
|
||||
explicit IAlbumAccessorSession() : ServiceFramework{"IAlbumAccessorSession"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{2001, nullptr, "OpenAlbumMovieReadStream"},
|
||||
{2002, nullptr, "CloseAlbumMovieReadStream"},
|
||||
{2003, nullptr, "GetAlbumMovieReadStreamMovieDataSize"},
|
||||
{2004, nullptr, "ReadMovieDataFromAlbumMovieReadStream"},
|
||||
{2005, nullptr, "GetAlbumMovieReadStreamBrokenReason"},
|
||||
{2006, nullptr, "GetAlbumMovieReadStreamImageDataSize"},
|
||||
{2007, nullptr, "ReadImageDataFromAlbumMovieReadStream"},
|
||||
{2008, nullptr, "ReadFileAttributeFromAlbumMovieReadStream"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
CAPS_A::CAPS_A() : ServiceFramework("caps:a") {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetAlbumFileCount"},
|
||||
{1, nullptr, "GetAlbumFileList"},
|
||||
{2, nullptr, "LoadAlbumFile"},
|
||||
{3, nullptr, "DeleteAlbumFile"},
|
||||
{4, nullptr, "StorageCopyAlbumFile"},
|
||||
{5, nullptr, "IsAlbumMounted"},
|
||||
{6, nullptr, "GetAlbumUsage"},
|
||||
{7, nullptr, "GetAlbumFileSize"},
|
||||
{8, nullptr, "LoadAlbumFileThumbnail"},
|
||||
{9, nullptr, "LoadAlbumScreenShotImage"},
|
||||
{10, nullptr, "LoadAlbumScreenShotThumbnailImage"},
|
||||
{11, nullptr, "GetAlbumEntryFromApplicationAlbumEntry"},
|
||||
{12, nullptr, "LoadAlbumScreenShotImageEx"},
|
||||
{13, nullptr, "LoadAlbumScreenShotThumbnailImageEx"},
|
||||
{14, nullptr, "LoadAlbumScreenShotImageEx0"},
|
||||
{15, nullptr, "GetAlbumUsage3"},
|
||||
{16, nullptr, "GetAlbumMountResult"},
|
||||
{17, nullptr, "GetAlbumUsage16"},
|
||||
{18, nullptr, "Unknown18"},
|
||||
{100, nullptr, "GetAlbumFileCountEx0"},
|
||||
{101, nullptr, "GetAlbumFileListEx0"},
|
||||
{202, nullptr, "SaveEditedScreenShot"},
|
||||
{301, nullptr, "GetLastThumbnail"},
|
||||
{302, nullptr, "GetLastOverlayMovieThumbnail"},
|
||||
{401, nullptr, "GetAutoSavingStorage"},
|
||||
{501, nullptr, "GetRequiredStorageSpaceSizeToCopyAll"},
|
||||
{1001, nullptr, "LoadAlbumScreenShotThumbnailImageEx0"},
|
||||
{1002, nullptr, "LoadAlbumScreenShotImageEx1"},
|
||||
{1003, nullptr, "LoadAlbumScreenShotThumbnailImageEx1"},
|
||||
{8001, nullptr, "ForceAlbumUnmounted"},
|
||||
{8002, nullptr, "ResetAlbumMountStatus"},
|
||||
{8011, nullptr, "RefreshAlbumCache"},
|
||||
{8012, nullptr, "GetAlbumCache"},
|
||||
{8013, nullptr, "GetAlbumCacheEx"},
|
||||
{8021, nullptr, "GetAlbumEntryFromApplicationAlbumEntryAruid"},
|
||||
{10011, nullptr, "SetInternalErrorConversionEnabled"},
|
||||
{50000, nullptr, "LoadMakerNoteInfoForDebug"},
|
||||
{60002, nullptr, "OpenAccessorSession"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
CAPS_A::~CAPS_A() = default;
|
||||
|
||||
} // namespace Service::Capture
|
||||
21
src/core/hle/service/caps/caps_a.h
Normal file
21
src/core/hle/service/caps/caps_a.h
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright 2020 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 Kernel {
|
||||
class HLERequestContext;
|
||||
}
|
||||
|
||||
namespace Service::Capture {
|
||||
|
||||
class CAPS_A final : public ServiceFramework<CAPS_A> {
|
||||
public:
|
||||
explicit CAPS_A();
|
||||
~CAPS_A() override;
|
||||
};
|
||||
|
||||
} // namespace Service::Capture
|
||||
75
src/core/hle/service/caps/caps_c.cpp
Normal file
75
src/core/hle/service/caps/caps_c.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
// Copyright 2020 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/service/caps/caps_c.h"
|
||||
|
||||
namespace Service::Capture {
|
||||
|
||||
class IAlbumControlSession final : public ServiceFramework<IAlbumControlSession> {
|
||||
public:
|
||||
explicit IAlbumControlSession() : ServiceFramework{"IAlbumControlSession"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{2001, nullptr, "OpenAlbumMovieReadStream"},
|
||||
{2002, nullptr, "CloseAlbumMovieReadStream"},
|
||||
{2003, nullptr, "GetAlbumMovieReadStreamMovieDataSize"},
|
||||
{2004, nullptr, "ReadMovieDataFromAlbumMovieReadStream"},
|
||||
{2005, nullptr, "GetAlbumMovieReadStreamBrokenReason"},
|
||||
{2006, nullptr, "GetAlbumMovieReadStreamImageDataSize"},
|
||||
{2007, nullptr, "ReadImageDataFromAlbumMovieReadStream"},
|
||||
{2008, nullptr, "ReadFileAttributeFromAlbumMovieReadStream"},
|
||||
{2401, nullptr, "OpenAlbumMovieWriteStream"},
|
||||
{2402, nullptr, "FinishAlbumMovieWriteStream"},
|
||||
{2403, nullptr, "CommitAlbumMovieWriteStream"},
|
||||
{2404, nullptr, "DiscardAlbumMovieWriteStream"},
|
||||
{2405, nullptr, "DiscardAlbumMovieWriteStreamNoDelete"},
|
||||
{2406, nullptr, "CommitAlbumMovieWriteStreamEx"},
|
||||
{2411, nullptr, "StartAlbumMovieWriteStreamDataSection"},
|
||||
{2412, nullptr, "EndAlbumMovieWriteStreamDataSection"},
|
||||
{2413, nullptr, "StartAlbumMovieWriteStreamMetaSection"},
|
||||
{2414, nullptr, "EndAlbumMovieWriteStreamMetaSection"},
|
||||
{2421, nullptr, "ReadDataFromAlbumMovieWriteStream"},
|
||||
{2422, nullptr, "WriteDataToAlbumMovieWriteStream"},
|
||||
{2424, nullptr, "WriteMetaToAlbumMovieWriteStream"},
|
||||
{2431, nullptr, "GetAlbumMovieWriteStreamBrokenReason"},
|
||||
{2433, nullptr, "GetAlbumMovieWriteStreamDataSize"},
|
||||
{2434, nullptr, "SetAlbumMovieWriteStreamDataSize"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
CAPS_C::CAPS_C() : ServiceFramework("caps:c") {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{1, nullptr, "CaptureRawImage"},
|
||||
{2, nullptr, "CaptureRawImageWithTimeout"},
|
||||
{33, nullptr, "Unknown33"},
|
||||
{1001, nullptr, "RequestTakingScreenShot"},
|
||||
{1002, nullptr, "RequestTakingScreenShotWithTimeout"},
|
||||
{1011, nullptr, "NotifyTakingScreenShotRefused"},
|
||||
{2001, nullptr, "NotifyAlbumStorageIsAvailable"},
|
||||
{2002, nullptr, "NotifyAlbumStorageIsUnavailable"},
|
||||
{2011, nullptr, "RegisterAppletResourceUserId"},
|
||||
{2012, nullptr, "UnregisterAppletResourceUserId"},
|
||||
{2013, nullptr, "GetApplicationIdFromAruid"},
|
||||
{2014, nullptr, "CheckApplicationIdRegistered"},
|
||||
{2101, nullptr, "GenerateCurrentAlbumFileId"},
|
||||
{2102, nullptr, "GenerateApplicationAlbumEntry"},
|
||||
{2201, nullptr, "SaveAlbumScreenShotFile"},
|
||||
{2202, nullptr, "SaveAlbumScreenShotFileEx"},
|
||||
{2301, nullptr, "SetOverlayScreenShotThumbnailData"},
|
||||
{2302, nullptr, "SetOverlayMovieThumbnailData"},
|
||||
{60001, nullptr, "OpenControlSession"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
CAPS_C::~CAPS_C() = default;
|
||||
|
||||
} // namespace Service::Capture
|
||||
21
src/core/hle/service/caps/caps_c.h
Normal file
21
src/core/hle/service/caps/caps_c.h
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright 2020 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 Kernel {
|
||||
class HLERequestContext;
|
||||
}
|
||||
|
||||
namespace Service::Capture {
|
||||
|
||||
class CAPS_C final : public ServiceFramework<CAPS_C> {
|
||||
public:
|
||||
explicit CAPS_C();
|
||||
~CAPS_C() override;
|
||||
};
|
||||
|
||||
} // namespace Service::Capture
|
||||
40
src/core/hle/service/caps/caps_sc.cpp
Normal file
40
src/core/hle/service/caps/caps_sc.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
// Copyright 2020 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/service/caps/caps_sc.h"
|
||||
|
||||
namespace Service::Capture {
|
||||
|
||||
CAPS_SC::CAPS_SC() : ServiceFramework("caps:sc") {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{1, nullptr, "CaptureRawImage"},
|
||||
{2, nullptr, "CaptureRawImageWithTimeout"},
|
||||
{3, nullptr, "AttachSharedBuffer"},
|
||||
{5, nullptr, "CaptureRawImageToAttachedSharedBuffer"},
|
||||
{210, nullptr, "Unknown210"},
|
||||
{1001, nullptr, "RequestTakingScreenShot"},
|
||||
{1002, nullptr, "RequestTakingScreenShotWithTimeout"},
|
||||
{1003, nullptr, "RequestTakingScreenShotEx"},
|
||||
{1004, nullptr, "RequestTakingScreenShotEx1"},
|
||||
{1009, nullptr, "CancelTakingScreenShot"},
|
||||
{1010, nullptr, "SetTakingScreenShotCancelState"},
|
||||
{1011, nullptr, "NotifyTakingScreenShotRefused"},
|
||||
{1012, nullptr, "NotifyTakingScreenShotFailed"},
|
||||
{1101, nullptr, "SetupOverlayMovieThumbnail"},
|
||||
{1106, nullptr, "Unknown1106"},
|
||||
{1107, nullptr, "Unknown1107"},
|
||||
{1201, nullptr, "OpenRawScreenShotReadStream"},
|
||||
{1202, nullptr, "CloseRawScreenShotReadStream"},
|
||||
{1203, nullptr, "ReadRawScreenShotReadStream"},
|
||||
{1204, nullptr, "Unknown1204"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
CAPS_SC::~CAPS_SC() = default;
|
||||
|
||||
} // namespace Service::Capture
|
||||
21
src/core/hle/service/caps/caps_sc.h
Normal file
21
src/core/hle/service/caps/caps_sc.h
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright 2020 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 Kernel {
|
||||
class HLERequestContext;
|
||||
}
|
||||
|
||||
namespace Service::Capture {
|
||||
|
||||
class CAPS_SC final : public ServiceFramework<CAPS_SC> {
|
||||
public:
|
||||
explicit CAPS_SC();
|
||||
~CAPS_SC() override;
|
||||
};
|
||||
|
||||
} // namespace Service::Capture
|
||||
26
src/core/hle/service/caps/caps_ss.cpp
Normal file
26
src/core/hle/service/caps/caps_ss.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright 2020 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/service/caps/caps_ss.h"
|
||||
|
||||
namespace Service::Capture {
|
||||
|
||||
CAPS_SS::CAPS_SS() : ServiceFramework("caps:ss") {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{201, nullptr, "SaveScreenShot"},
|
||||
{202, nullptr, "SaveEditedScreenShot"},
|
||||
{203, nullptr, "SaveScreenShotEx0"},
|
||||
{204, nullptr, "SaveEditedScreenShotEx0"},
|
||||
{206, nullptr, "Unknown206"},
|
||||
{208, nullptr, "SaveScreenShotOfMovieEx1"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
CAPS_SS::~CAPS_SS() = default;
|
||||
|
||||
} // namespace Service::Capture
|
||||
21
src/core/hle/service/caps/caps_ss.h
Normal file
21
src/core/hle/service/caps/caps_ss.h
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright 2020 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 Kernel {
|
||||
class HLERequestContext;
|
||||
}
|
||||
|
||||
namespace Service::Capture {
|
||||
|
||||
class CAPS_SS final : public ServiceFramework<CAPS_SS> {
|
||||
public:
|
||||
explicit CAPS_SS();
|
||||
~CAPS_SS() override;
|
||||
};
|
||||
|
||||
} // namespace Service::Capture
|
||||
22
src/core/hle/service/caps/caps_su.cpp
Normal file
22
src/core/hle/service/caps/caps_su.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2020 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/service/caps/caps_su.h"
|
||||
|
||||
namespace Service::Capture {
|
||||
|
||||
CAPS_SU::CAPS_SU() : ServiceFramework("caps:su") {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{201, nullptr, "SaveScreenShot"},
|
||||
{203, nullptr, "SaveScreenShotEx0"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
CAPS_SU::~CAPS_SU() = default;
|
||||
|
||||
} // namespace Service::Capture
|
||||
21
src/core/hle/service/caps/caps_su.h
Normal file
21
src/core/hle/service/caps/caps_su.h
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright 2020 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 Kernel {
|
||||
class HLERequestContext;
|
||||
}
|
||||
|
||||
namespace Service::Capture {
|
||||
|
||||
class CAPS_SU final : public ServiceFramework<CAPS_SU> {
|
||||
public:
|
||||
explicit CAPS_SU();
|
||||
~CAPS_SU() override;
|
||||
};
|
||||
|
||||
} // namespace Service::Capture
|
||||
76
src/core/hle/service/caps/caps_u.cpp
Normal file
76
src/core/hle/service/caps/caps_u.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
// Copyright 2020 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/caps/caps.h"
|
||||
#include "core/hle/service/caps/caps_u.h"
|
||||
|
||||
namespace Service::Capture {
|
||||
|
||||
class IAlbumAccessorApplicationSession final
|
||||
: public ServiceFramework<IAlbumAccessorApplicationSession> {
|
||||
public:
|
||||
explicit IAlbumAccessorApplicationSession()
|
||||
: ServiceFramework{"IAlbumAccessorApplicationSession"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{2001, nullptr, "OpenAlbumMovieReadStream"},
|
||||
{2002, nullptr, "CloseAlbumMovieReadStream"},
|
||||
{2003, nullptr, "GetAlbumMovieReadStreamMovieDataSize"},
|
||||
{2004, nullptr, "ReadMovieDataFromAlbumMovieReadStream"},
|
||||
{2005, nullptr, "GetAlbumMovieReadStreamBrokenReason"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
CAPS_U::CAPS_U() : ServiceFramework("caps:u") {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{31, nullptr, "GetShimLibraryVersion"},
|
||||
{32, nullptr, "SetShimLibraryVersion"},
|
||||
{102, &CAPS_U::GetAlbumContentsFileListForApplication, "GetAlbumContentsFileListForApplication"},
|
||||
{103, nullptr, "DeleteAlbumContentsFileForApplication"},
|
||||
{104, nullptr, "GetAlbumContentsFileSizeForApplication"},
|
||||
{105, nullptr, "DeleteAlbumFileByAruidForDebug"},
|
||||
{110, nullptr, "LoadAlbumContentsFileScreenShotImageForApplication"},
|
||||
{120, nullptr, "LoadAlbumContentsFileThumbnailImageForApplication"},
|
||||
{130, nullptr, "PrecheckToCreateContentsForApplication"},
|
||||
{140, nullptr, "GetAlbumFileList1AafeAruidDeprecated"},
|
||||
{141, nullptr, "GetAlbumFileList2AafeUidAruidDeprecated"},
|
||||
{142, nullptr, "GetAlbumFileList3AaeAruid"},
|
||||
{143, nullptr, "GetAlbumFileList4AaeUidAruid"},
|
||||
{60002, nullptr, "OpenAccessorSessionForApplication"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
CAPS_U::~CAPS_U() = default;
|
||||
|
||||
void CAPS_U::GetAlbumContentsFileListForApplication(Kernel::HLERequestContext& ctx) {
|
||||
// Takes a type-0x6 output buffer containing an array of ApplicationAlbumFileEntry, a PID, an
|
||||
// u8 ContentType, two s64s, and an u64 AppletResourceUserId. Returns an output u64 for total
|
||||
// output entries (which is copied to a s32 by official SW).
|
||||
IPC::RequestParser rp{ctx};
|
||||
[[maybe_unused]] const auto application_album_file_entries = rp.PopRaw<std::array<u8, 0x30>>();
|
||||
const auto pid = rp.Pop<s32>();
|
||||
const auto content_type = rp.PopRaw<ContentType>();
|
||||
[[maybe_unused]] const auto start_datetime = rp.PopRaw<AlbumFileDateTime>();
|
||||
[[maybe_unused]] const auto end_datetime = rp.PopRaw<AlbumFileDateTime>();
|
||||
const auto applet_resource_user_id = rp.Pop<u64>();
|
||||
LOG_WARNING(Service_Capture,
|
||||
"(STUBBED) called. pid={}, content_type={}, applet_resource_user_id={}", pid,
|
||||
content_type, applet_resource_user_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<s32>(0);
|
||||
}
|
||||
|
||||
} // namespace Service::Capture
|
||||
24
src/core/hle/service/caps/caps_u.h
Normal file
24
src/core/hle/service/caps/caps_u.h
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright 2020 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 Kernel {
|
||||
class HLERequestContext;
|
||||
}
|
||||
|
||||
namespace Service::Capture {
|
||||
|
||||
class CAPS_U final : public ServiceFramework<CAPS_U> {
|
||||
public:
|
||||
explicit CAPS_U();
|
||||
~CAPS_U() override;
|
||||
|
||||
private:
|
||||
void GetAlbumContentsFileListForApplication(Kernel::HLERequestContext& ctx);
|
||||
};
|
||||
|
||||
} // namespace Service::Capture
|
||||
@@ -235,7 +235,7 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) {
|
||||
{303, nullptr, "ActivateSevenSixAxisSensor"},
|
||||
{304, nullptr, "StartSevenSixAxisSensor"},
|
||||
{305, nullptr, "StopSevenSixAxisSensor"},
|
||||
{306, nullptr, "InitializeSevenSixAxisSensor"},
|
||||
{306, &Hid::InitializeSevenSixAxisSensor, "InitializeSevenSixAxisSensor"},
|
||||
{307, nullptr, "FinalizeSevenSixAxisSensor"},
|
||||
{308, nullptr, "SetSevenSixAxisSensorFusionStrength"},
|
||||
{309, nullptr, "GetSevenSixAxisSensorFusionStrength"},
|
||||
@@ -853,6 +853,13 @@ void Hid::SetPalmaBoostMode(Kernel::HLERequestContext& ctx) {
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void Hid::InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_HID, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
class HidDbg final : public ServiceFramework<HidDbg> {
|
||||
public:
|
||||
explicit HidDbg() : ServiceFramework{"hid:dbg"} {
|
||||
|
||||
@@ -128,6 +128,7 @@ private:
|
||||
void StopSixAxisSensor(Kernel::HLERequestContext& ctx);
|
||||
void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx);
|
||||
void SetPalmaBoostMode(Kernel::HLERequestContext& ctx);
|
||||
void InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx);
|
||||
|
||||
std::shared_ptr<IAppletResource> applet_resource;
|
||||
Core::System& system;
|
||||
|
||||
@@ -191,8 +191,6 @@ void NVFlinger::Compose() {
|
||||
// Search for a queued buffer and acquire it
|
||||
auto buffer = buffer_queue.AcquireBuffer();
|
||||
|
||||
MicroProfileFlip();
|
||||
|
||||
if (!buffer) {
|
||||
continue;
|
||||
}
|
||||
@@ -206,6 +204,8 @@ void NVFlinger::Compose() {
|
||||
gpu.WaitFence(fence.id, fence.value);
|
||||
}
|
||||
|
||||
MicroProfileFlip();
|
||||
|
||||
// Now send the buffer to the GPU for drawing.
|
||||
// TODO(Subv): Support more than just disp0. The display device selection is probably based
|
||||
// on which display we're drawing (Default, Internal, External, etc)
|
||||
|
||||
@@ -111,6 +111,14 @@ void SET::GetLanguageCode(Kernel::HLERequestContext& ctx) {
|
||||
rb.PushEnum(available_language_codes[Settings::values.language_index]);
|
||||
}
|
||||
|
||||
void SET::GetRegionCode(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_SET, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push(Settings::values.region_index);
|
||||
}
|
||||
|
||||
SET::SET() : ServiceFramework("set") {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
@@ -118,7 +126,7 @@ SET::SET() : ServiceFramework("set") {
|
||||
{1, &SET::GetAvailableLanguageCodes, "GetAvailableLanguageCodes"},
|
||||
{2, &SET::MakeLanguageCode, "MakeLanguageCode"},
|
||||
{3, &SET::GetAvailableLanguageCodeCount, "GetAvailableLanguageCodeCount"},
|
||||
{4, nullptr, "GetRegionCode"},
|
||||
{4, &SET::GetRegionCode, "GetRegionCode"},
|
||||
{5, &SET::GetAvailableLanguageCodes2, "GetAvailableLanguageCodes2"},
|
||||
{6, &SET::GetAvailableLanguageCodeCount2, "GetAvailableLanguageCodeCount2"},
|
||||
{7, nullptr, "GetKeyCodeMap"},
|
||||
|
||||
@@ -43,6 +43,7 @@ private:
|
||||
void GetAvailableLanguageCodeCount(Kernel::HLERequestContext& ctx);
|
||||
void GetAvailableLanguageCodeCount2(Kernel::HLERequestContext& ctx);
|
||||
void GetQuestFlag(Kernel::HLERequestContext& ctx);
|
||||
void GetRegionCode(Kernel::HLERequestContext& ctx);
|
||||
};
|
||||
|
||||
} // namespace Service::Set
|
||||
|
||||
@@ -44,7 +44,7 @@ void Controller::QueryPointerBufferSize(Kernel::HLERequestContext& ctx) {
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u16>(0x500);
|
||||
rb.Push<u16>(0x1000);
|
||||
}
|
||||
|
||||
Controller::Controller() : ServiceFramework("IpcController") {
|
||||
|
||||
@@ -30,7 +30,7 @@ Time::Time(std::shared_ptr<Module> module, Core::System& system, const char* nam
|
||||
{400, &Time::GetClockSnapshot, "GetClockSnapshot"},
|
||||
{401, &Time::GetClockSnapshotFromSystemClockContext, "GetClockSnapshotFromSystemClockContext"},
|
||||
{500, nullptr, "CalculateStandardUserSystemClockDifferenceByUser"},
|
||||
{501, nullptr, "CalculateSpanBetween"},
|
||||
{501, &Time::CalculateSpanBetween, "CalculateSpanBetween"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -308,6 +308,35 @@ void Module::Interface::GetClockSnapshotFromSystemClockContext(Kernel::HLEReques
|
||||
ctx.WriteBuffer(&clock_snapshot, sizeof(Clock::ClockSnapshot));
|
||||
}
|
||||
|
||||
void Module::Interface::CalculateSpanBetween(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto snapshot_a = rp.PopRaw<Clock::ClockSnapshot>();
|
||||
const auto snapshot_b = rp.PopRaw<Clock::ClockSnapshot>();
|
||||
|
||||
Clock::TimeSpanType time_span_type{};
|
||||
s64 span{};
|
||||
if (const ResultCode result{snapshot_a.steady_clock_time_point.GetSpanBetween(
|
||||
snapshot_b.steady_clock_time_point, span)};
|
||||
result != RESULT_SUCCESS) {
|
||||
if (snapshot_a.network_time && snapshot_b.network_time) {
|
||||
time_span_type =
|
||||
Clock::TimeSpanType::FromSeconds(snapshot_b.network_time - snapshot_a.network_time);
|
||||
} else {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ERROR_TIME_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
time_span_type = Clock::TimeSpanType::FromSeconds(span);
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, (sizeof(s64) / 4) + 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushRaw(time_span_type.nanoseconds);
|
||||
}
|
||||
|
||||
void Module::Interface::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called");
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
|
||||
@@ -32,6 +32,7 @@ public:
|
||||
void CalculateMonotonicSystemClockBaseTimePoint(Kernel::HLERequestContext& ctx);
|
||||
void GetClockSnapshot(Kernel::HLERequestContext& ctx);
|
||||
void GetClockSnapshotFromSystemClockContext(Kernel::HLERequestContext& ctx);
|
||||
void CalculateSpanBetween(Kernel::HLERequestContext& ctx);
|
||||
void GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx);
|
||||
|
||||
private:
|
||||
|
||||
@@ -53,7 +53,7 @@ static std::vector<std::string> BuildLocationNameCache(Core::System& system) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<char> raw_data(binary_list->GetSize());
|
||||
std::vector<char> raw_data(binary_list->GetSize() + 1);
|
||||
binary_list->ReadBytes<char>(raw_data.data(), binary_list->GetSize());
|
||||
|
||||
std::stringstream data_stream{raw_data.data()};
|
||||
|
||||
@@ -129,12 +129,6 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
|
||||
}
|
||||
metadata.Print();
|
||||
|
||||
const FileSys::ProgramAddressSpaceType arch_bits{metadata.GetAddressSpaceType()};
|
||||
if (arch_bits == FileSys::ProgramAddressSpaceType::Is32Bit ||
|
||||
arch_bits == FileSys::ProgramAddressSpaceType::Is32BitNoMap) {
|
||||
return {ResultStatus::Error32BitISA, {}};
|
||||
}
|
||||
|
||||
if (process.LoadFromMetadata(metadata).IsError()) {
|
||||
return {ResultStatus::ErrorUnableToParseKernelMetadata, {}};
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ json GetProcessorStateDataAuto(Core::System& system) {
|
||||
const auto& vm_manager{process->VMManager()};
|
||||
auto& arm{system.CurrentArmInterface()};
|
||||
|
||||
Core::ARM_Interface::ThreadContext context{};
|
||||
Core::ARM_Interface::ThreadContext64 context{};
|
||||
arm.SaveContext(context);
|
||||
|
||||
return GetProcessorStateData(process->Is64BitProcess() ? "AArch64" : "AArch32",
|
||||
|
||||
@@ -86,6 +86,7 @@ void LogSettings() {
|
||||
LogSetting("System_RngSeed", Settings::values.rng_seed.value_or(0));
|
||||
LogSetting("System_CurrentUser", Settings::values.current_user);
|
||||
LogSetting("System_LanguageIndex", Settings::values.language_index);
|
||||
LogSetting("System_RegionIndex", Settings::values.region_index);
|
||||
LogSetting("Core_UseMultiCore", Settings::values.use_multi_core);
|
||||
LogSetting("Renderer_UseResolutionFactor", Settings::values.resolution_factor);
|
||||
LogSetting("Renderer_UseFrameLimit", Settings::values.use_frame_limit);
|
||||
|
||||
@@ -387,6 +387,8 @@ struct Values {
|
||||
|
||||
s32 current_user;
|
||||
s32 language_index;
|
||||
s32 region_index;
|
||||
s32 sound_index;
|
||||
|
||||
// Controls
|
||||
std::array<PlayerInput, 10> players;
|
||||
@@ -430,6 +432,7 @@ struct Values {
|
||||
|
||||
float resolution_factor;
|
||||
int aspect_ratio;
|
||||
int max_anisotropy;
|
||||
bool use_frame_limit;
|
||||
u16 frame_limit;
|
||||
bool use_disk_shader_cache;
|
||||
|
||||
@@ -32,8 +32,16 @@ public:
|
||||
SocketCallback callback)
|
||||
: callback(std::move(callback)), timer(io_service),
|
||||
socket(io_service, udp::endpoint(udp::v4(), 0)), client_id(client_id),
|
||||
pad_index(pad_index),
|
||||
send_endpoint(udp::endpoint(boost::asio::ip::make_address_v4(host), port)) {}
|
||||
pad_index(pad_index) {
|
||||
boost::system::error_code ec{};
|
||||
auto ipv4 = boost::asio::ip::make_address_v4(host, ec);
|
||||
if (ec.value() != boost::system::errc::success) {
|
||||
LOG_ERROR(Input, "Invalid IPv4 address \"{}\" provided to socket", host);
|
||||
ipv4 = boost::asio::ip::address_v4{};
|
||||
}
|
||||
|
||||
send_endpoint = {udp::endpoint(ipv4, port)};
|
||||
}
|
||||
|
||||
void Stop() {
|
||||
io_service.stop();
|
||||
@@ -85,17 +93,18 @@ private:
|
||||
}
|
||||
|
||||
void HandleSend(const boost::system::error_code& error) {
|
||||
boost::system::error_code _ignored{};
|
||||
// Send a request for getting port info for the pad
|
||||
Request::PortInfo port_info{1, {pad_index, 0, 0, 0}};
|
||||
const auto port_message = Request::Create(port_info, client_id);
|
||||
std::memcpy(&send_buffer1, &port_message, PORT_INFO_SIZE);
|
||||
socket.send_to(boost::asio::buffer(send_buffer1), send_endpoint);
|
||||
socket.send_to(boost::asio::buffer(send_buffer1), send_endpoint, {}, _ignored);
|
||||
|
||||
// Send a request for getting pad data for the pad
|
||||
Request::PadData pad_data{Request::PadData::Flags::Id, pad_index, EMPTY_MAC_ADDRESS};
|
||||
const auto pad_message = Request::Create(pad_data, client_id);
|
||||
std::memcpy(send_buffer2.data(), &pad_message, PAD_DATA_SIZE);
|
||||
socket.send_to(boost::asio::buffer(send_buffer2), send_endpoint);
|
||||
socket.send_to(boost::asio::buffer(send_buffer2), send_endpoint, {}, _ignored);
|
||||
StartSend(timer.expiry());
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ namespace Response {
|
||||
*/
|
||||
std::optional<Type> Validate(u8* data, std::size_t size) {
|
||||
if (size < sizeof(Header)) {
|
||||
LOG_DEBUG(Input, "Invalid UDP packet received");
|
||||
return std::nullopt;
|
||||
}
|
||||
Header header{};
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <tuple>
|
||||
|
||||
#include "common/param_package.h"
|
||||
@@ -44,7 +45,7 @@ public:
|
||||
std::unique_ptr<Input::TouchDevice> Create(const Common::ParamPackage& params) override {
|
||||
{
|
||||
std::lock_guard guard(status->update_mutex);
|
||||
status->touch_calibration.emplace();
|
||||
status->touch_calibration = DeviceStatus::CalibrationData{};
|
||||
// These default values work well for DS4 but probably not other touch inputs
|
||||
status->touch_calibration->min_x = params.Get("min_x", 100);
|
||||
status->touch_calibration->min_y = params.Get("min_y", 50);
|
||||
|
||||
@@ -65,8 +65,6 @@ add_library(video_core STATIC
|
||||
renderer_opengl/gl_shader_decompiler.h
|
||||
renderer_opengl/gl_shader_disk_cache.cpp
|
||||
renderer_opengl/gl_shader_disk_cache.h
|
||||
renderer_opengl/gl_shader_gen.cpp
|
||||
renderer_opengl/gl_shader_gen.h
|
||||
renderer_opengl/gl_shader_manager.cpp
|
||||
renderer_opengl/gl_shader_manager.h
|
||||
renderer_opengl/gl_shader_util.cpp
|
||||
@@ -118,8 +116,6 @@ add_library(video_core STATIC
|
||||
shader/ast.h
|
||||
shader/compiler_settings.cpp
|
||||
shader/compiler_settings.h
|
||||
shader/const_buffer_locker.cpp
|
||||
shader/const_buffer_locker.h
|
||||
shader/control_flow.cpp
|
||||
shader/control_flow.h
|
||||
shader/decode.cpp
|
||||
@@ -128,9 +124,13 @@ add_library(video_core STATIC
|
||||
shader/node_helper.cpp
|
||||
shader/node_helper.h
|
||||
shader/node.h
|
||||
shader/registry.cpp
|
||||
shader/registry.h
|
||||
shader/shader_ir.cpp
|
||||
shader/shader_ir.h
|
||||
shader/track.cpp
|
||||
shader/transform_feedback.cpp
|
||||
shader/transform_feedback.h
|
||||
surface.cpp
|
||||
surface.h
|
||||
texture_cache/format_lookup_table.cpp
|
||||
@@ -210,6 +210,8 @@ if (ENABLE_VULKAN)
|
||||
renderer_vulkan/vk_texture_cache.h
|
||||
renderer_vulkan/vk_update_descriptor.cpp
|
||||
renderer_vulkan/vk_update_descriptor.h
|
||||
renderer_vulkan/wrapper.cpp
|
||||
renderer_vulkan/wrapper.h
|
||||
)
|
||||
|
||||
target_include_directories(video_core PRIVATE sirit ../../externals/Vulkan-Headers/include)
|
||||
|
||||
@@ -15,14 +15,6 @@ namespace VideoCommon::Dirty {
|
||||
|
||||
using Tegra::Engines::Maxwell3D;
|
||||
|
||||
void SetupCommonOnWriteStores(Tegra::Engines::Maxwell3D::DirtyState::Flags& store) {
|
||||
store[RenderTargets] = true;
|
||||
store[ZetaBuffer] = true;
|
||||
for (std::size_t i = 0; i < Maxwell3D::Regs::NumRenderTargets; ++i) {
|
||||
store[ColorBuffer0 + i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SetupDirtyRenderTargets(Tegra::Engines::Maxwell3D::DirtyState::Tables& tables) {
|
||||
static constexpr std::size_t num_per_rt = NUM(rt[0]);
|
||||
static constexpr std::size_t begin = OFF(rt);
|
||||
|
||||
@@ -44,8 +44,6 @@ void FillBlock(Tegra::Engines::Maxwell3D::DirtyState::Tables& tables, std::size_
|
||||
FillBlock(tables[1], begin, num, index_b);
|
||||
}
|
||||
|
||||
void SetupCommonOnWriteStores(Tegra::Engines::Maxwell3D::DirtyState::Flags& store);
|
||||
|
||||
void SetupDirtyRenderTargets(Tegra::Engines::Maxwell3D::DirtyState::Tables& tables);
|
||||
|
||||
} // namespace VideoCommon::Dirty
|
||||
|
||||
@@ -16,11 +16,16 @@ namespace Tegra::Engines {
|
||||
|
||||
struct SamplerDescriptor {
|
||||
union {
|
||||
BitField<0, 20, Tegra::Shader::TextureType> texture_type;
|
||||
BitField<20, 1, u32> is_array;
|
||||
BitField<21, 1, u32> is_buffer;
|
||||
BitField<22, 1, u32> is_shadow;
|
||||
u32 raw{};
|
||||
u32 raw = 0;
|
||||
BitField<0, 2, Tegra::Shader::TextureType> texture_type;
|
||||
BitField<2, 3, Tegra::Texture::ComponentType> r_type;
|
||||
BitField<5, 1, u32> is_array;
|
||||
BitField<6, 1, u32> is_buffer;
|
||||
BitField<7, 1, u32> is_shadow;
|
||||
BitField<8, 3, Tegra::Texture::ComponentType> g_type;
|
||||
BitField<11, 3, Tegra::Texture::ComponentType> b_type;
|
||||
BitField<14, 3, Tegra::Texture::ComponentType> a_type;
|
||||
BitField<17, 7, Tegra::Texture::TextureFormat> format;
|
||||
};
|
||||
|
||||
bool operator==(const SamplerDescriptor& rhs) const noexcept {
|
||||
@@ -31,68 +36,50 @@ struct SamplerDescriptor {
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
static SamplerDescriptor FromTicTexture(Tegra::Texture::TextureType tic_texture_type) {
|
||||
static SamplerDescriptor FromTIC(const Tegra::Texture::TICEntry& tic) {
|
||||
using Tegra::Shader::TextureType;
|
||||
SamplerDescriptor result;
|
||||
switch (tic_texture_type) {
|
||||
|
||||
result.format.Assign(tic.format.Value());
|
||||
result.r_type.Assign(tic.r_type.Value());
|
||||
result.g_type.Assign(tic.g_type.Value());
|
||||
result.b_type.Assign(tic.b_type.Value());
|
||||
result.a_type.Assign(tic.a_type.Value());
|
||||
|
||||
switch (tic.texture_type.Value()) {
|
||||
case Tegra::Texture::TextureType::Texture1D:
|
||||
result.texture_type.Assign(Tegra::Shader::TextureType::Texture1D);
|
||||
result.is_array.Assign(0);
|
||||
result.is_buffer.Assign(0);
|
||||
result.is_shadow.Assign(0);
|
||||
result.texture_type.Assign(TextureType::Texture1D);
|
||||
return result;
|
||||
case Tegra::Texture::TextureType::Texture2D:
|
||||
result.texture_type.Assign(Tegra::Shader::TextureType::Texture2D);
|
||||
result.is_array.Assign(0);
|
||||
result.is_buffer.Assign(0);
|
||||
result.is_shadow.Assign(0);
|
||||
result.texture_type.Assign(TextureType::Texture2D);
|
||||
return result;
|
||||
case Tegra::Texture::TextureType::Texture3D:
|
||||
result.texture_type.Assign(Tegra::Shader::TextureType::Texture3D);
|
||||
result.is_array.Assign(0);
|
||||
result.is_buffer.Assign(0);
|
||||
result.is_shadow.Assign(0);
|
||||
result.texture_type.Assign(TextureType::Texture3D);
|
||||
return result;
|
||||
case Tegra::Texture::TextureType::TextureCubemap:
|
||||
result.texture_type.Assign(Tegra::Shader::TextureType::TextureCube);
|
||||
result.is_array.Assign(0);
|
||||
result.is_buffer.Assign(0);
|
||||
result.is_shadow.Assign(0);
|
||||
result.texture_type.Assign(TextureType::TextureCube);
|
||||
return result;
|
||||
case Tegra::Texture::TextureType::Texture1DArray:
|
||||
result.texture_type.Assign(Tegra::Shader::TextureType::Texture1D);
|
||||
result.texture_type.Assign(TextureType::Texture1D);
|
||||
result.is_array.Assign(1);
|
||||
result.is_buffer.Assign(0);
|
||||
result.is_shadow.Assign(0);
|
||||
return result;
|
||||
case Tegra::Texture::TextureType::Texture2DArray:
|
||||
result.texture_type.Assign(Tegra::Shader::TextureType::Texture2D);
|
||||
result.texture_type.Assign(TextureType::Texture2D);
|
||||
result.is_array.Assign(1);
|
||||
result.is_buffer.Assign(0);
|
||||
result.is_shadow.Assign(0);
|
||||
return result;
|
||||
case Tegra::Texture::TextureType::Texture1DBuffer:
|
||||
result.texture_type.Assign(Tegra::Shader::TextureType::Texture1D);
|
||||
result.is_array.Assign(0);
|
||||
result.texture_type.Assign(TextureType::Texture1D);
|
||||
result.is_buffer.Assign(1);
|
||||
result.is_shadow.Assign(0);
|
||||
return result;
|
||||
case Tegra::Texture::TextureType::Texture2DNoMipmap:
|
||||
result.texture_type.Assign(Tegra::Shader::TextureType::Texture2D);
|
||||
result.is_array.Assign(0);
|
||||
result.is_buffer.Assign(0);
|
||||
result.is_shadow.Assign(0);
|
||||
result.texture_type.Assign(TextureType::Texture2D);
|
||||
return result;
|
||||
case Tegra::Texture::TextureType::TextureCubeArray:
|
||||
result.texture_type.Assign(Tegra::Shader::TextureType::TextureCube);
|
||||
result.texture_type.Assign(TextureType::TextureCube);
|
||||
result.is_array.Assign(1);
|
||||
result.is_buffer.Assign(0);
|
||||
result.is_shadow.Assign(0);
|
||||
return result;
|
||||
default:
|
||||
result.texture_type.Assign(Tegra::Shader::TextureType::Texture2D);
|
||||
result.is_array.Assign(0);
|
||||
result.is_buffer.Assign(0);
|
||||
result.is_shadow.Assign(0);
|
||||
result.texture_type.Assign(TextureType::Texture2D);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ SamplerDescriptor KeplerCompute::AccessBindlessSampler(ShaderType stage, u64 con
|
||||
|
||||
const Texture::TextureHandle tex_handle{memory_manager.Read<u32>(tex_info_address)};
|
||||
const Texture::FullTextureInfo tex_info = GetTextureInfo(tex_handle);
|
||||
SamplerDescriptor result = SamplerDescriptor::FromTicTexture(tex_info.tic.texture_type.Value());
|
||||
SamplerDescriptor result = SamplerDescriptor::FromTIC(tex_info.tic);
|
||||
result.is_shadow.Assign(tex_info.tsc.depth_compare_enabled.Value());
|
||||
return result;
|
||||
}
|
||||
@@ -119,14 +119,6 @@ Texture::TICEntry KeplerCompute::GetTICEntry(u32 tic_index) const {
|
||||
Texture::TICEntry tic_entry;
|
||||
memory_manager.ReadBlockUnsafe(tic_address_gpu, &tic_entry, sizeof(Texture::TICEntry));
|
||||
|
||||
const auto r_type{tic_entry.r_type.Value()};
|
||||
const auto g_type{tic_entry.g_type.Value()};
|
||||
const auto b_type{tic_entry.b_type.Value()};
|
||||
const auto a_type{tic_entry.a_type.Value()};
|
||||
|
||||
// TODO(Subv): Different data types for separate components are not supported
|
||||
DEBUG_ASSERT(r_type == g_type && r_type == b_type && r_type == a_type);
|
||||
|
||||
return tic_entry;
|
||||
}
|
||||
|
||||
|
||||
@@ -98,6 +98,8 @@ void Maxwell3D::InitializeRegisterDefaults() {
|
||||
regs.framebuffer_srgb = 1;
|
||||
regs.front_face = Maxwell3D::Regs::FrontFace::ClockWise;
|
||||
|
||||
shadow_state = regs;
|
||||
|
||||
mme_inline[MAXWELL3D_REG_INDEX(draw.vertex_end_gl)] = true;
|
||||
mme_inline[MAXWELL3D_REG_INDEX(draw.vertex_begin_gl)] = true;
|
||||
mme_inline[MAXWELL3D_REG_INDEX(vertex_buffer.count)] = true;
|
||||
@@ -160,8 +162,17 @@ void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) {
|
||||
ASSERT_MSG(method < Regs::NUM_REGS,
|
||||
"Invalid Maxwell3D register, increase the size of the Regs structure");
|
||||
|
||||
if (regs.reg_array[method] != method_call.argument) {
|
||||
regs.reg_array[method] = method_call.argument;
|
||||
u32 arg = method_call.argument;
|
||||
// Keep track of the register value in shadow_state when requested.
|
||||
if (shadow_state.shadow_ram_control == Regs::ShadowRamControl::Track ||
|
||||
shadow_state.shadow_ram_control == Regs::ShadowRamControl::TrackWithFilter) {
|
||||
shadow_state.reg_array[method] = arg;
|
||||
} else if (shadow_state.shadow_ram_control == Regs::ShadowRamControl::Replay) {
|
||||
arg = shadow_state.reg_array[method];
|
||||
}
|
||||
|
||||
if (regs.reg_array[method] != arg) {
|
||||
regs.reg_array[method] = arg;
|
||||
|
||||
for (const auto& table : dirty.tables) {
|
||||
dirty.flags[table[method]] = true;
|
||||
@@ -169,12 +180,16 @@ void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) {
|
||||
}
|
||||
|
||||
switch (method) {
|
||||
case MAXWELL3D_REG_INDEX(shadow_ram_control): {
|
||||
shadow_state.shadow_ram_control = static_cast<Regs::ShadowRamControl>(method_call.argument);
|
||||
break;
|
||||
}
|
||||
case MAXWELL3D_REG_INDEX(macros.data): {
|
||||
ProcessMacroUpload(method_call.argument);
|
||||
ProcessMacroUpload(arg);
|
||||
break;
|
||||
}
|
||||
case MAXWELL3D_REG_INDEX(macros.bind): {
|
||||
ProcessMacroBind(method_call.argument);
|
||||
ProcessMacroBind(arg);
|
||||
break;
|
||||
}
|
||||
case MAXWELL3D_REG_INDEX(firmware[4]): {
|
||||
@@ -250,7 +265,7 @@ void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) {
|
||||
}
|
||||
case MAXWELL3D_REG_INDEX(data_upload): {
|
||||
const bool is_last_call = method_call.IsLastCall();
|
||||
upload_state.ProcessData(method_call.argument, is_last_call);
|
||||
upload_state.ProcessData(arg, is_last_call);
|
||||
if (is_last_call) {
|
||||
OnMemoryWrite();
|
||||
}
|
||||
@@ -638,7 +653,7 @@ SamplerDescriptor Maxwell3D::AccessBindlessSampler(ShaderType stage, u64 const_b
|
||||
|
||||
const Texture::TextureHandle tex_handle{memory_manager.Read<u32>(tex_info_address)};
|
||||
const Texture::FullTextureInfo tex_info = GetTextureInfo(tex_handle);
|
||||
SamplerDescriptor result = SamplerDescriptor::FromTicTexture(tex_info.tic.texture_type.Value());
|
||||
SamplerDescriptor result = SamplerDescriptor::FromTIC(tex_info.tic);
|
||||
result.is_shadow.Assign(tex_info.tsc.depth_compare_enabled.Value());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@ public:
|
||||
static constexpr std::size_t NumVaryings = 31;
|
||||
static constexpr std::size_t NumImages = 8; // TODO(Rodrigo): Investigate this number
|
||||
static constexpr std::size_t NumClipDistances = 8;
|
||||
static constexpr std::size_t NumTransformFeedbackBuffers = 4;
|
||||
static constexpr std::size_t MaxShaderProgram = 6;
|
||||
static constexpr std::size_t MaxShaderStage = 5;
|
||||
// Maximum number of const buffers per shader stage.
|
||||
@@ -524,6 +525,23 @@ public:
|
||||
FractionalEven = 2,
|
||||
};
|
||||
|
||||
enum class PolygonMode : u32 {
|
||||
Point = 0x1b00,
|
||||
Line = 0x1b01,
|
||||
Fill = 0x1b02,
|
||||
};
|
||||
|
||||
enum class ShadowRamControl : u32 {
|
||||
// write value to shadow ram
|
||||
Track = 0,
|
||||
// write value to shadow ram ( with validation ??? )
|
||||
TrackWithFilter = 1,
|
||||
// only write to real hw register
|
||||
Passthrough = 2,
|
||||
// write value from shadow ram to real hw register
|
||||
Replay = 3,
|
||||
};
|
||||
|
||||
struct RenderTargetConfig {
|
||||
u32 address_high;
|
||||
u32 address_low;
|
||||
@@ -621,6 +639,29 @@ public:
|
||||
float depth_range_far;
|
||||
};
|
||||
|
||||
struct TransformFeedbackBinding {
|
||||
u32 buffer_enable;
|
||||
u32 address_high;
|
||||
u32 address_low;
|
||||
s32 buffer_size;
|
||||
s32 buffer_offset;
|
||||
INSERT_UNION_PADDING_WORDS(3);
|
||||
|
||||
GPUVAddr Address() const {
|
||||
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
|
||||
address_low);
|
||||
}
|
||||
};
|
||||
static_assert(sizeof(TransformFeedbackBinding) == 32);
|
||||
|
||||
struct TransformFeedbackLayout {
|
||||
u32 stream;
|
||||
u32 varying_count;
|
||||
u32 stride;
|
||||
INSERT_UNION_PADDING_WORDS(1);
|
||||
};
|
||||
static_assert(sizeof(TransformFeedbackLayout) == 16);
|
||||
|
||||
bool IsShaderConfigEnabled(std::size_t index) const {
|
||||
// The VertexB is always enabled.
|
||||
if (index == static_cast<std::size_t>(Regs::ShaderProgram::VertexB)) {
|
||||
@@ -629,6 +670,10 @@ public:
|
||||
return shader_config[index].enable != 0;
|
||||
}
|
||||
|
||||
bool IsShaderConfigEnabled(Regs::ShaderProgram type) const {
|
||||
return IsShaderConfigEnabled(static_cast<std::size_t>(type));
|
||||
}
|
||||
|
||||
union {
|
||||
struct {
|
||||
INSERT_UNION_PADDING_WORDS(0x45);
|
||||
@@ -640,7 +685,9 @@ public:
|
||||
u32 bind;
|
||||
} macros;
|
||||
|
||||
INSERT_UNION_PADDING_WORDS(0x17);
|
||||
ShadowRamControl shadow_ram_control;
|
||||
|
||||
INSERT_UNION_PADDING_WORDS(0x16);
|
||||
|
||||
Upload::Registers upload;
|
||||
struct {
|
||||
@@ -677,7 +724,13 @@ public:
|
||||
|
||||
u32 rasterize_enable;
|
||||
|
||||
INSERT_UNION_PADDING_WORDS(0xF1);
|
||||
std::array<TransformFeedbackBinding, NumTransformFeedbackBuffers> tfb_bindings;
|
||||
|
||||
INSERT_UNION_PADDING_WORDS(0xC0);
|
||||
|
||||
std::array<TransformFeedbackLayout, NumTransformFeedbackBuffers> tfb_layouts;
|
||||
|
||||
INSERT_UNION_PADDING_WORDS(0x1);
|
||||
|
||||
u32 tfb_enabled;
|
||||
|
||||
@@ -705,7 +758,12 @@ public:
|
||||
|
||||
s32 clear_stencil;
|
||||
|
||||
INSERT_UNION_PADDING_WORDS(0x7);
|
||||
INSERT_UNION_PADDING_WORDS(0x2);
|
||||
|
||||
PolygonMode polygon_mode_front;
|
||||
PolygonMode polygon_mode_back;
|
||||
|
||||
INSERT_UNION_PADDING_WORDS(0x3);
|
||||
|
||||
u32 polygon_offset_point_enable;
|
||||
u32 polygon_offset_line_enable;
|
||||
@@ -764,7 +822,11 @@ public:
|
||||
BitField<12, 4, u32> viewport;
|
||||
} clear_flags;
|
||||
|
||||
INSERT_UNION_PADDING_WORDS(0x19);
|
||||
INSERT_UNION_PADDING_WORDS(0x10);
|
||||
|
||||
u32 fill_rectangle;
|
||||
|
||||
INSERT_UNION_PADDING_WORDS(0x8);
|
||||
|
||||
std::array<VertexAttribute, NumVertexAttributes> vertex_attrib_format;
|
||||
|
||||
@@ -1187,7 +1249,11 @@ public:
|
||||
|
||||
u32 tex_cb_index;
|
||||
|
||||
INSERT_UNION_PADDING_WORDS(0x395);
|
||||
INSERT_UNION_PADDING_WORDS(0x7D);
|
||||
|
||||
std::array<std::array<u8, 128>, NumTransformFeedbackBuffers> tfb_varying_locs;
|
||||
|
||||
INSERT_UNION_PADDING_WORDS(0x298);
|
||||
|
||||
struct {
|
||||
/// Compressed address of a buffer that holds information about bound SSBOs.
|
||||
@@ -1210,7 +1276,12 @@ public:
|
||||
};
|
||||
std::array<u32, NUM_REGS> reg_array;
|
||||
};
|
||||
} regs{};
|
||||
};
|
||||
|
||||
Regs regs{};
|
||||
|
||||
/// Store temporary hw register values, used by some calls to restore state after a operation
|
||||
Regs shadow_state;
|
||||
|
||||
static_assert(sizeof(Regs) == Regs::NUM_REGS * sizeof(u32), "Maxwell3D Regs has wrong size");
|
||||
static_assert(std::is_trivially_copyable_v<Regs>, "Maxwell3D Regs must be trivially copyable");
|
||||
@@ -1405,6 +1476,7 @@ private:
|
||||
"Field " #field_name " has invalid position")
|
||||
|
||||
ASSERT_REG_POSITION(macros, 0x45);
|
||||
ASSERT_REG_POSITION(shadow_ram_control, 0x49);
|
||||
ASSERT_REG_POSITION(upload, 0x60);
|
||||
ASSERT_REG_POSITION(exec_upload, 0x6C);
|
||||
ASSERT_REG_POSITION(data_upload, 0x6D);
|
||||
@@ -1413,6 +1485,8 @@ ASSERT_REG_POSITION(tess_mode, 0xC8);
|
||||
ASSERT_REG_POSITION(tess_level_outer, 0xC9);
|
||||
ASSERT_REG_POSITION(tess_level_inner, 0xCD);
|
||||
ASSERT_REG_POSITION(rasterize_enable, 0xDF);
|
||||
ASSERT_REG_POSITION(tfb_bindings, 0xE0);
|
||||
ASSERT_REG_POSITION(tfb_layouts, 0x1C0);
|
||||
ASSERT_REG_POSITION(tfb_enabled, 0x1D1);
|
||||
ASSERT_REG_POSITION(rt, 0x200);
|
||||
ASSERT_REG_POSITION(viewport_transform, 0x280);
|
||||
@@ -1422,6 +1496,8 @@ ASSERT_REG_POSITION(depth_mode, 0x35F);
|
||||
ASSERT_REG_POSITION(clear_color[0], 0x360);
|
||||
ASSERT_REG_POSITION(clear_depth, 0x364);
|
||||
ASSERT_REG_POSITION(clear_stencil, 0x368);
|
||||
ASSERT_REG_POSITION(polygon_mode_front, 0x36B);
|
||||
ASSERT_REG_POSITION(polygon_mode_back, 0x36C);
|
||||
ASSERT_REG_POSITION(polygon_offset_point_enable, 0x370);
|
||||
ASSERT_REG_POSITION(polygon_offset_line_enable, 0x371);
|
||||
ASSERT_REG_POSITION(polygon_offset_fill_enable, 0x372);
|
||||
@@ -1435,6 +1511,7 @@ ASSERT_REG_POSITION(rt_separate_frag_data, 0x3EB);
|
||||
ASSERT_REG_POSITION(depth_bounds, 0x3E7);
|
||||
ASSERT_REG_POSITION(zeta, 0x3F8);
|
||||
ASSERT_REG_POSITION(clear_flags, 0x43E);
|
||||
ASSERT_REG_POSITION(fill_rectangle, 0x44F);
|
||||
ASSERT_REG_POSITION(vertex_attrib_format, 0x458);
|
||||
ASSERT_REG_POSITION(rt_control, 0x487);
|
||||
ASSERT_REG_POSITION(zeta_width, 0x48a);
|
||||
@@ -1508,6 +1585,7 @@ ASSERT_REG_POSITION(firmware, 0x8C0);
|
||||
ASSERT_REG_POSITION(const_buffer, 0x8E0);
|
||||
ASSERT_REG_POSITION(cb_bind[0], 0x904);
|
||||
ASSERT_REG_POSITION(tex_cb_index, 0x982);
|
||||
ASSERT_REG_POSITION(tfb_varying_locs, 0xA00);
|
||||
ASSERT_REG_POSITION(ssbo_info, 0xD18);
|
||||
ASSERT_REG_POSITION(tex_info_buffers.address[0], 0xD2A);
|
||||
ASSERT_REG_POSITION(tex_info_buffers.size[0], 0xD2F);
|
||||
|
||||
@@ -82,6 +82,10 @@ union Attribute {
|
||||
Position = 7,
|
||||
Attribute_0 = 8,
|
||||
Attribute_31 = 39,
|
||||
FrontColor = 40,
|
||||
FrontSecondaryColor = 41,
|
||||
BackColor = 42,
|
||||
BackSecondaryColor = 43,
|
||||
ClipDistances0123 = 44,
|
||||
ClipDistances4567 = 45,
|
||||
PointCoord = 46,
|
||||
@@ -89,6 +93,8 @@ union Attribute {
|
||||
// shader, and a tuple of (TessCoord.x, TessCoord.y, TessCoord.z, ~) when inside a Tess Eval
|
||||
// shader.
|
||||
TessCoordInstanceIDVertexID = 47,
|
||||
TexCoord_0 = 48,
|
||||
TexCoord_7 = 55,
|
||||
// This attribute contains a tuple of (Unk, Unk, Unk, gl_FrontFacing) when inside a fragment
|
||||
// shader. It is unknown what the other values contain.
|
||||
FrontFacing = 63,
|
||||
@@ -225,18 +231,6 @@ enum class AtomicOp : u64 {
|
||||
Or = 6,
|
||||
Xor = 7,
|
||||
Exch = 8,
|
||||
};
|
||||
|
||||
enum class GlobalAtomicOp : u64 {
|
||||
Add = 0,
|
||||
Min = 1,
|
||||
Max = 2,
|
||||
Inc = 3,
|
||||
Dec = 4,
|
||||
And = 5,
|
||||
Or = 6,
|
||||
Xor = 7,
|
||||
Exch = 8,
|
||||
SafeAdd = 10,
|
||||
};
|
||||
|
||||
@@ -911,14 +905,9 @@ union Instruction {
|
||||
} fadd32i;
|
||||
|
||||
union {
|
||||
BitField<20, 8, u64> shift_position;
|
||||
BitField<28, 8, u64> shift_length;
|
||||
BitField<48, 1, u64> negate_b;
|
||||
BitField<49, 1, u64> negate_a;
|
||||
|
||||
u64 GetLeftShiftValue() const {
|
||||
return 32 - (shift_position + shift_length);
|
||||
}
|
||||
BitField<40, 1, u64> brev;
|
||||
BitField<47, 1, u64> rd_cc;
|
||||
BitField<48, 1, u64> is_signed;
|
||||
} bfe;
|
||||
|
||||
union {
|
||||
@@ -1000,7 +989,7 @@ union Instruction {
|
||||
} stg;
|
||||
|
||||
union {
|
||||
BitField<52, 4, GlobalAtomicOp> operation;
|
||||
BitField<52, 4, AtomicOp> operation;
|
||||
BitField<49, 3, GlobalAtomicType> type;
|
||||
BitField<28, 20, s64> offset;
|
||||
} atom;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/core_timing_util.h"
|
||||
#include "core/frontend/emu_window.h"
|
||||
#include "core/memory.h"
|
||||
#include "video_core/engines/fermi_2d.h"
|
||||
#include "video_core/engines/kepler_compute.h"
|
||||
@@ -16,14 +17,15 @@
|
||||
#include "video_core/gpu.h"
|
||||
#include "video_core/memory_manager.h"
|
||||
#include "video_core/renderer_base.h"
|
||||
#include "video_core/video_core.h"
|
||||
|
||||
namespace Tegra {
|
||||
|
||||
MICROPROFILE_DEFINE(GPU_wait, "GPU", "Wait for the GPU", MP_RGB(128, 128, 192));
|
||||
|
||||
GPU::GPU(Core::System& system, VideoCore::RendererBase& renderer, bool is_async)
|
||||
: system{system}, renderer{renderer}, is_async{is_async} {
|
||||
auto& rasterizer{renderer.Rasterizer()};
|
||||
GPU::GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_, bool is_async)
|
||||
: system{system}, renderer{std::move(renderer_)}, is_async{is_async} {
|
||||
auto& rasterizer{renderer->Rasterizer()};
|
||||
memory_manager = std::make_unique<Tegra::MemoryManager>(system, rasterizer);
|
||||
dma_pusher = std::make_unique<Tegra::DmaPusher>(*this);
|
||||
maxwell_3d = std::make_unique<Engines::Maxwell3D>(system, rasterizer, *memory_manager);
|
||||
@@ -137,7 +139,7 @@ u64 GPU::GetTicks() const {
|
||||
}
|
||||
|
||||
void GPU::FlushCommands() {
|
||||
renderer.Rasterizer().FlushCommands();
|
||||
renderer->Rasterizer().FlushCommands();
|
||||
}
|
||||
|
||||
// Note that, traditionally, methods are treated as 4-byte addressable locations, and hence
|
||||
|
||||
@@ -25,8 +25,11 @@ inline u8* FromCacheAddr(CacheAddr cache_addr) {
|
||||
}
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
namespace Frontend {
|
||||
class EmuWindow;
|
||||
}
|
||||
class System;
|
||||
} // namespace Core
|
||||
|
||||
namespace VideoCore {
|
||||
class RendererBase;
|
||||
@@ -39,6 +42,7 @@ enum class RenderTargetFormat : u32 {
|
||||
RGBA32_FLOAT = 0xC0,
|
||||
RGBA32_UINT = 0xC2,
|
||||
RGBA16_UNORM = 0xC6,
|
||||
RGBA16_SNORM = 0xC7,
|
||||
RGBA16_UINT = 0xC9,
|
||||
RGBA16_FLOAT = 0xCA,
|
||||
RG32_FLOAT = 0xCB,
|
||||
@@ -128,7 +132,8 @@ class MemoryManager;
|
||||
|
||||
class GPU {
|
||||
public:
|
||||
explicit GPU(Core::System& system, VideoCore::RendererBase& renderer, bool is_async);
|
||||
explicit GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
|
||||
bool is_async);
|
||||
|
||||
virtual ~GPU();
|
||||
|
||||
@@ -173,6 +178,14 @@ public:
|
||||
/// Returns a reference to the GPU DMA pusher.
|
||||
Tegra::DmaPusher& DmaPusher();
|
||||
|
||||
VideoCore::RendererBase& Renderer() {
|
||||
return *renderer;
|
||||
}
|
||||
|
||||
const VideoCore::RendererBase& Renderer() const {
|
||||
return *renderer;
|
||||
}
|
||||
|
||||
// Waits for the GPU to finish working
|
||||
virtual void WaitIdle() const = 0;
|
||||
|
||||
@@ -286,7 +299,7 @@ private:
|
||||
protected:
|
||||
std::unique_ptr<Tegra::DmaPusher> dma_pusher;
|
||||
Core::System& system;
|
||||
VideoCore::RendererBase& renderer;
|
||||
std::unique_ptr<VideoCore::RendererBase> renderer;
|
||||
|
||||
private:
|
||||
std::unique_ptr<Tegra::MemoryManager> memory_manager;
|
||||
|
||||
@@ -10,13 +10,16 @@
|
||||
|
||||
namespace VideoCommon {
|
||||
|
||||
GPUAsynch::GPUAsynch(Core::System& system, VideoCore::RendererBase& renderer)
|
||||
: GPU(system, renderer, true), gpu_thread{system} {}
|
||||
GPUAsynch::GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext>&& context)
|
||||
: GPU(system, std::move(renderer_), true), gpu_thread{system}, gpu_context(std::move(context)),
|
||||
cpu_context(renderer->GetRenderWindow().CreateSharedContext()) {}
|
||||
|
||||
GPUAsynch::~GPUAsynch() = default;
|
||||
|
||||
void GPUAsynch::Start() {
|
||||
gpu_thread.StartThread(renderer, *dma_pusher);
|
||||
cpu_context->MakeCurrent();
|
||||
gpu_thread.StartThread(*renderer, *gpu_context, *dma_pusher);
|
||||
}
|
||||
|
||||
void GPUAsynch::PushGPUEntries(Tegra::CommandList&& entries) {
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
#include "video_core/gpu.h"
|
||||
#include "video_core/gpu_thread.h"
|
||||
|
||||
namespace Core::Frontend {
|
||||
class GraphicsContext;
|
||||
}
|
||||
|
||||
namespace VideoCore {
|
||||
class RendererBase;
|
||||
} // namespace VideoCore
|
||||
@@ -16,7 +20,8 @@ namespace VideoCommon {
|
||||
/// Implementation of GPU interface that runs the GPU asynchronously
|
||||
class GPUAsynch final : public Tegra::GPU {
|
||||
public:
|
||||
explicit GPUAsynch(Core::System& system, VideoCore::RendererBase& renderer);
|
||||
explicit GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext>&& context);
|
||||
~GPUAsynch() override;
|
||||
|
||||
void Start() override;
|
||||
@@ -32,6 +37,8 @@ protected:
|
||||
|
||||
private:
|
||||
GPUThread::ThreadManager gpu_thread;
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context;
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> gpu_context;
|
||||
};
|
||||
|
||||
} // namespace VideoCommon
|
||||
|
||||
@@ -7,12 +7,15 @@
|
||||
|
||||
namespace VideoCommon {
|
||||
|
||||
GPUSynch::GPUSynch(Core::System& system, VideoCore::RendererBase& renderer)
|
||||
: GPU(system, renderer, false) {}
|
||||
GPUSynch::GPUSynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext>&& context)
|
||||
: GPU(system, std::move(renderer), false), context{std::move(context)} {}
|
||||
|
||||
GPUSynch::~GPUSynch() = default;
|
||||
|
||||
void GPUSynch::Start() {}
|
||||
void GPUSynch::Start() {
|
||||
context->MakeCurrent();
|
||||
}
|
||||
|
||||
void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) {
|
||||
dma_pusher->Push(std::move(entries));
|
||||
@@ -20,19 +23,19 @@ void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) {
|
||||
}
|
||||
|
||||
void GPUSynch::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
|
||||
renderer.SwapBuffers(framebuffer);
|
||||
renderer->SwapBuffers(framebuffer);
|
||||
}
|
||||
|
||||
void GPUSynch::FlushRegion(CacheAddr addr, u64 size) {
|
||||
renderer.Rasterizer().FlushRegion(addr, size);
|
||||
renderer->Rasterizer().FlushRegion(addr, size);
|
||||
}
|
||||
|
||||
void GPUSynch::InvalidateRegion(CacheAddr addr, u64 size) {
|
||||
renderer.Rasterizer().InvalidateRegion(addr, size);
|
||||
renderer->Rasterizer().InvalidateRegion(addr, size);
|
||||
}
|
||||
|
||||
void GPUSynch::FlushAndInvalidateRegion(CacheAddr addr, u64 size) {
|
||||
renderer.Rasterizer().FlushAndInvalidateRegion(addr, size);
|
||||
renderer->Rasterizer().FlushAndInvalidateRegion(addr, size);
|
||||
}
|
||||
|
||||
} // namespace VideoCommon
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
|
||||
#include "video_core/gpu.h"
|
||||
|
||||
namespace Core::Frontend {
|
||||
class GraphicsContext;
|
||||
}
|
||||
|
||||
namespace VideoCore {
|
||||
class RendererBase;
|
||||
} // namespace VideoCore
|
||||
@@ -15,7 +19,8 @@ namespace VideoCommon {
|
||||
/// Implementation of GPU interface that runs the GPU synchronously
|
||||
class GPUSynch final : public Tegra::GPU {
|
||||
public:
|
||||
explicit GPUSynch(Core::System& system, VideoCore::RendererBase& renderer);
|
||||
explicit GPUSynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext>&& context);
|
||||
~GPUSynch() override;
|
||||
|
||||
void Start() override;
|
||||
@@ -29,6 +34,9 @@ public:
|
||||
protected:
|
||||
void TriggerCpuInterrupt([[maybe_unused]] u32 syncpoint_id,
|
||||
[[maybe_unused]] u32 value) const override {}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context;
|
||||
};
|
||||
|
||||
} // namespace VideoCommon
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/microprofile.h"
|
||||
#include "core/core.h"
|
||||
#include "core/frontend/scope_acquire_context.h"
|
||||
#include "core/frontend/emu_window.h"
|
||||
#include "video_core/dma_pusher.h"
|
||||
#include "video_core/gpu.h"
|
||||
#include "video_core/gpu_thread.h"
|
||||
@@ -14,8 +14,8 @@
|
||||
namespace VideoCommon::GPUThread {
|
||||
|
||||
/// Runs the GPU thread
|
||||
static void RunThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_pusher,
|
||||
SynchState& state) {
|
||||
static void RunThread(VideoCore::RendererBase& renderer, Core::Frontend::GraphicsContext& context,
|
||||
Tegra::DmaPusher& dma_pusher, SynchState& state) {
|
||||
MicroProfileOnThreadCreate("GpuThread");
|
||||
|
||||
// Wait for first GPU command before acquiring the window context
|
||||
@@ -27,7 +27,7 @@ static void RunThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_p
|
||||
return;
|
||||
}
|
||||
|
||||
Core::Frontend::ScopeAcquireContext acquire_context{renderer.GetRenderWindow()};
|
||||
auto current_context = context.Acquire();
|
||||
|
||||
CommandDataContainer next;
|
||||
while (state.is_running) {
|
||||
@@ -62,8 +62,11 @@ ThreadManager::~ThreadManager() {
|
||||
thread.join();
|
||||
}
|
||||
|
||||
void ThreadManager::StartThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_pusher) {
|
||||
thread = std::thread{RunThread, std::ref(renderer), std::ref(dma_pusher), std::ref(state)};
|
||||
void ThreadManager::StartThread(VideoCore::RendererBase& renderer,
|
||||
Core::Frontend::GraphicsContext& context,
|
||||
Tegra::DmaPusher& dma_pusher) {
|
||||
thread = std::thread{RunThread, std::ref(renderer), std::ref(context), std::ref(dma_pusher),
|
||||
std::ref(state)};
|
||||
}
|
||||
|
||||
void ThreadManager::SubmitList(Tegra::CommandList&& entries) {
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include <optional>
|
||||
#include <thread>
|
||||
#include <variant>
|
||||
|
||||
#include "common/threadsafe_queue.h"
|
||||
#include "video_core/gpu.h"
|
||||
|
||||
@@ -20,6 +19,9 @@ class DmaPusher;
|
||||
} // namespace Tegra
|
||||
|
||||
namespace Core {
|
||||
namespace Frontend {
|
||||
class GraphicsContext;
|
||||
}
|
||||
class System;
|
||||
} // namespace Core
|
||||
|
||||
@@ -99,7 +101,8 @@ public:
|
||||
~ThreadManager();
|
||||
|
||||
/// Creates and starts the GPU thread.
|
||||
void StartThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_pusher);
|
||||
void StartThread(VideoCore::RendererBase& renderer, Core::Frontend::GraphicsContext& context,
|
||||
Tegra::DmaPusher& dma_pusher);
|
||||
|
||||
/// Push GPU command entries to be processed
|
||||
void SubmitList(Tegra::CommandList&& entries);
|
||||
|
||||
@@ -4,13 +4,15 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/guest_driver.h"
|
||||
|
||||
namespace VideoCore {
|
||||
|
||||
void GuestDriverProfile::DeduceTextureHandlerSize(std::vector<u32>&& bound_offsets) {
|
||||
if (texture_handler_size_deduced) {
|
||||
void GuestDriverProfile::DeduceTextureHandlerSize(std::vector<u32> bound_offsets) {
|
||||
if (texture_handler_size) {
|
||||
return;
|
||||
}
|
||||
const std::size_t size = bound_offsets.size();
|
||||
@@ -29,7 +31,6 @@ void GuestDriverProfile::DeduceTextureHandlerSize(std::vector<u32>&& bound_offse
|
||||
if (min_val > 2) {
|
||||
return;
|
||||
}
|
||||
texture_handler_size_deduced = true;
|
||||
texture_handler_size = min_texture_handler_size * min_val;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_types.h"
|
||||
@@ -17,25 +18,29 @@ namespace VideoCore {
|
||||
*/
|
||||
class GuestDriverProfile {
|
||||
public:
|
||||
void DeduceTextureHandlerSize(std::vector<u32>&& bound_offsets);
|
||||
explicit GuestDriverProfile() = default;
|
||||
explicit GuestDriverProfile(std::optional<u32> texture_handler_size)
|
||||
: texture_handler_size{texture_handler_size} {}
|
||||
|
||||
void DeduceTextureHandlerSize(std::vector<u32> bound_offsets);
|
||||
|
||||
u32 GetTextureHandlerSize() const {
|
||||
return texture_handler_size;
|
||||
return texture_handler_size.value_or(default_texture_handler_size);
|
||||
}
|
||||
|
||||
bool TextureHandlerSizeKnown() const {
|
||||
return texture_handler_size_deduced;
|
||||
bool IsTextureHandlerSizeKnown() const {
|
||||
return texture_handler_size.has_value();
|
||||
}
|
||||
|
||||
private:
|
||||
// Minimum size of texture handler any driver can use.
|
||||
static constexpr u32 min_texture_handler_size = 4;
|
||||
// This goes with Vulkan and OpenGL standards but Nvidia GPUs can easily
|
||||
// use 4 bytes instead. Thus, certain drivers may squish the size.
|
||||
|
||||
// This goes with Vulkan and OpenGL standards but Nvidia GPUs can easily use 4 bytes instead.
|
||||
// Thus, certain drivers may squish the size.
|
||||
static constexpr u32 default_texture_handler_size = 8;
|
||||
|
||||
u32 texture_handler_size = default_texture_handler_size;
|
||||
bool texture_handler_size_deduced = false;
|
||||
std::optional<u32> texture_handler_size = default_texture_handler_size;
|
||||
};
|
||||
|
||||
} // namespace VideoCore
|
||||
|
||||
@@ -174,7 +174,7 @@ private:
|
||||
/// End of address space, based on address space in bits.
|
||||
static constexpr GPUVAddr address_space_end{1ULL << address_space_width};
|
||||
|
||||
Common::PageTable page_table{page_bits};
|
||||
Common::BackingPageTable page_table{page_bits};
|
||||
VMAMap vma_map;
|
||||
VideoCore::RasterizerInterface& rasterizer;
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ static constexpr ConversionArray morton_to_linear_fns = {
|
||||
MortonCopy<true, PixelFormat::R8UI>,
|
||||
MortonCopy<true, PixelFormat::RGBA16F>,
|
||||
MortonCopy<true, PixelFormat::RGBA16U>,
|
||||
MortonCopy<true, PixelFormat::RGBA16S>,
|
||||
MortonCopy<true, PixelFormat::RGBA16UI>,
|
||||
MortonCopy<true, PixelFormat::R11FG11FB10F>,
|
||||
MortonCopy<true, PixelFormat::RGBA32UI>,
|
||||
@@ -131,6 +132,7 @@ static constexpr ConversionArray linear_to_morton_fns = {
|
||||
MortonCopy<false, PixelFormat::R8U>,
|
||||
MortonCopy<false, PixelFormat::R8UI>,
|
||||
MortonCopy<false, PixelFormat::RGBA16F>,
|
||||
MortonCopy<false, PixelFormat::RGBA16S>,
|
||||
MortonCopy<false, PixelFormat::RGBA16U>,
|
||||
MortonCopy<false, PixelFormat::RGBA16UI>,
|
||||
MortonCopy<false, PixelFormat::R11FG11FB10F>,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user