Compare commits

..

1 Commits

Author SHA1 Message Date
Marshall Mohror afa334a319 Remove C++ standard flag 2020-02-27 16:48:12 +01:00
297 changed files with 8817 additions and 15009 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ parameters:
version: ''
steps:
- script: mkdir build && cd build && cmake -G "Visual Studio 16 2019" -A x64 --config Release -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_BUNDLED_UNICORN=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DUSE_DISCORD_PRESENCE=ON -DDISPLAY_VERSION=${{ parameters['version'] }} .. && cd ..
- script: mkdir build && cd build && cmake -G "Visual Studio 15 2017 Win64" --config Release -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_BUNDLED_UNICORN=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DUSE_DISCORD_PRESENCE=ON -DDISPLAY_VERSION=${{ parameters['version'] }} .. && cd ..
displayName: 'Configure CMake'
- task: MSBuild@1
displayName: 'Build'
+1 -1
View File
@@ -45,7 +45,7 @@ stages:
- job: build
displayName: 'msvc'
pool:
vmImage: windows-2019
vmImage: vs2017-win2016
steps:
- template: ./templates/sync-source.yml
parameters:
+1 -1
View File
@@ -22,7 +22,7 @@ stages:
- job: build
displayName: 'windows-msvc'
pool:
vmImage: windows-2019
vmImage: vs2017-win2016
steps:
- template: ./templates/sync-source.yml
parameters:
+4 -8
View File
@@ -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}plugins/platforms/)
set(STYLES ${DLL_DEST}plugins/styles/)
set(IMAGEFORMATS ${DLL_DEST}plugins/imageformats/)
set(PLATFORMS ${DLL_DEST}platforms/)
set(STYLES ${DLL_DEST}styles/)
set(IMAGEFORMATS ${DLL_DEST}imageformats/)
windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST}
icudt*.dll
icuin*.dll
@@ -42,15 +42,11 @@ 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)
+4 -4
View File
@@ -57,6 +57,8 @@ 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"
@@ -89,6 +91,8 @@ 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"
@@ -97,13 +101,9 @@ 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)
+2 -3
View File
@@ -1,8 +1,7 @@
yuzu emulator
=============
[![Travis CI Build Status](https://travis-ci.com/yuzu-emu/yuzu.svg?branch=master)](https://travis-ci.com/yuzu-emu/yuzu)
[![Travis CI Build Status](https://travis-ci.org/yuzu-emu/yuzu.svg?branch=master)](https://travis-ci.org/yuzu-emu/yuzu)
[![Azure Mainline CI Build Status](https://dev.azure.com/yuzu-emu/yuzu/_apis/build/status/yuzu%20mainline?branchName=master)](https://dev.azure.com/yuzu-emu/yuzu/)
[![Discord](https://img.shields.io/discord/398318088170242053?color=%237289DA&label=yuzu&logo=discord&logoColor=white)](https://discord.gg/XQV6dn9)
yuzu is an experimental open-source emulator for the Nintendo Switch from the creators of [Citra](https://citra-emu.org/).
@@ -22,7 +21,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](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.
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.
### Building
+4 -2
View File
@@ -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 | 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/checked.png | Free for non-commercial use
qt_themes/default/icons/16x16/failed.png | Free for non-commercial use
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,6 +11,8 @@ 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
Binary file not shown.

Before

Width:  |  Height:  |  Size: 657 B

After

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 524 B

After

Width:  |  Height:  |  Size: 428 B

+3 -4
View File
@@ -243,7 +243,6 @@ 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__))
@@ -828,7 +827,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((uint64_t)t == nBegin);
MP_ASSERT(t == nBegin);
MP_ASSERT(nTimerIndex == (nToken&0x3fff));
return Entry;
@@ -1556,10 +1555,10 @@ void MicroProfileFlip()
pFramePut->nFrameStartCpu = MP_TICK();
pFramePut->nFrameStartGpu = (uint32_t)MicroProfileGpuInsertTimeStamp();
if(pFrameNext->nFrameStartGpu != -1)
if(pFrameNext->nFrameStartGpu != (uint64_t)-1)
pFrameNext->nFrameStartGpu = MicroProfileGpuGetTimeStamp((uint32_t)pFrameNext->nFrameStartGpu);
if(pFrameCurrent->nFrameStartGpu == -1)
if(pFrameCurrent->nFrameStartGpu == (uint64_t)-1)
pFrameCurrent->nFrameStartGpu = pFrameNext->nFrameStartGpu + 1;
uint64_t nFrameStartCpu = pFrameCurrent->nFrameStartCpu;
+2 -2
View File
@@ -343,8 +343,8 @@ The icons used in this project have the following licenses:
Icon Name | License | Origin/Author
--- | --- | ---
checked.png | CC BY-ND 3.0 | https://icons8.com
failed.png | CC BY-ND 3.0 | https://icons8.com
checked.png | Free for non-commercial use
failed.png | Free for non-commercial use
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
-1
View File
@@ -38,7 +38,6 @@ if (MSVC)
/Zo
/permissive-
/EHsc
/std:c++latest
/volatile:iso
/Zc:externConstexpr
/Zc:inline
+22 -32
View File
@@ -8,14 +8,13 @@
#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,
@@ -57,7 +56,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,
@@ -99,7 +98,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,
@@ -147,10 +146,10 @@ std::vector<s16> Interpolate(InterpolationState& state, std::vector<s16> input,
if (ratio <= 0) {
LOG_CRITICAL(Audio, "Nonsensical interpolation ratio {}", ratio);
return input;
ratio = 1.0;
}
const s32 step{static_cast<s32>(ratio * 0x8000)};
const int step = static_cast<int>(ratio * 0x8000);
const std::array<s16, 512>& lut = [step] {
if (step > 0xaaaa) {
return curve_lut0;
@@ -161,37 +160,28 @@ std::vector<s16> Interpolate(InterpolationState& state, std::vector<s16> input,
return curve_lut2;
}();
const std::size_t num_frames{input.size() / 2};
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;
std::vector<s16> output;
output.reserve(static_cast<std::size_t>(input.size() / ratio + InterpolationState::taps));
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];
for (std::size_t frame{}; frame < num_frames; ++frame) {
const std::size_t lut_index{(state.fraction >> 8) * 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];
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];
const int new_offset = state.fraction + step;
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};
in_offset += new_offset >> 15;
state.fraction = new_offset & 0x7fff;
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;
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));
}
return output;
+1 -6
View File
@@ -6,17 +6,12 @@
#include <array>
#include <vector>
#include "common/common_types.h"
namespace AudioCore {
struct InterpolationState {
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{};
int fraction = 0;
};
/// Interpolates input signal to produce output signal.
+1 -1
View File
@@ -189,7 +189,7 @@ struct UpdateDataHeader {
UpdateDataHeader() {}
explicit UpdateDataHeader(const AudioRendererParameter& config) {
revision = Common::MakeMagic('R', 'E', 'V', '8'); // 9.2.0 Revision
revision = Common::MakeMagic('R', 'E', 'V', '4'); // 5.1.0 Revision
behavior_size = 0xb0;
memory_pools_size = (config.effect_count + (config.voice_count * 4)) * 0x10;
voices_size = config.voice_count * 0x10;
+3 -17
View File
@@ -8,7 +8,6 @@
#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"
@@ -66,25 +65,12 @@ 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) {
// 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));
for (std::size_t ch = 0; ch < num_channels; ch++) {
buf.push_back(samples[i + ch]);
}
}
queue.Push(buf);
return;
+4 -6
View File
@@ -38,6 +38,8 @@ 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"
@@ -70,6 +72,8 @@ 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"
@@ -78,13 +82,9 @@ 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"
@@ -106,8 +106,6 @@ add_library(common STATIC
common_funcs.h
common_paths.h
common_types.h
dynamic_library.cpp
dynamic_library.h
file_util.cpp
file_util.h
hash.h
-106
View File
@@ -1,106 +0,0 @@
// Copyright 2019 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <cstring>
#include <string>
#include <utility>
#include <fmt/format.h>
#include "common/dynamic_library.h"
#ifdef _WIN32
#include <windows.h>
#else
#include <dlfcn.h>
#endif
namespace Common {
DynamicLibrary::DynamicLibrary() = default;
DynamicLibrary::DynamicLibrary(const char* filename) {
Open(filename);
}
DynamicLibrary::DynamicLibrary(DynamicLibrary&& rhs) noexcept
: handle{std::exchange(rhs.handle, nullptr)} {}
DynamicLibrary& DynamicLibrary::operator=(DynamicLibrary&& rhs) noexcept {
Close();
handle = std::exchange(rhs.handle, nullptr);
return *this;
}
DynamicLibrary::~DynamicLibrary() {
Close();
}
std::string DynamicLibrary::GetUnprefixedFilename(const char* filename) {
#if defined(_WIN32)
return std::string(filename) + ".dll";
#elif defined(__APPLE__)
return std::string(filename) + ".dylib";
#else
return std::string(filename) + ".so";
#endif
}
std::string DynamicLibrary::GetVersionedFilename(const char* libname, int major, int minor) {
#if defined(_WIN32)
if (major >= 0 && minor >= 0)
return fmt::format("{}-{}-{}.dll", libname, major, minor);
else if (major >= 0)
return fmt::format("{}-{}.dll", libname, major);
else
return fmt::format("{}.dll", libname);
#elif defined(__APPLE__)
const char* prefix = std::strncmp(libname, "lib", 3) ? "lib" : "";
if (major >= 0 && minor >= 0)
return fmt::format("{}{}.{}.{}.dylib", prefix, libname, major, minor);
else if (major >= 0)
return fmt::format("{}{}.{}.dylib", prefix, libname, major);
else
return fmt::format("{}{}.dylib", prefix, libname);
#else
const char* prefix = std::strncmp(libname, "lib", 3) ? "lib" : "";
if (major >= 0 && minor >= 0)
return fmt::format("{}{}.so.{}.{}", prefix, libname, major, minor);
else if (major >= 0)
return fmt::format("{}{}.so.{}", prefix, libname, major);
else
return fmt::format("{}{}.so", prefix, libname);
#endif
}
bool DynamicLibrary::Open(const char* filename) {
#ifdef _WIN32
handle = reinterpret_cast<void*>(LoadLibraryA(filename));
#else
handle = dlopen(filename, RTLD_NOW);
#endif
return handle != nullptr;
}
void DynamicLibrary::Close() {
if (!IsOpen())
return;
#ifdef _WIN32
FreeLibrary(reinterpret_cast<HMODULE>(handle));
#else
dlclose(handle);
#endif
handle = nullptr;
}
void* DynamicLibrary::GetSymbolAddress(const char* name) const {
#ifdef _WIN32
return reinterpret_cast<void*>(GetProcAddress(reinterpret_cast<HMODULE>(handle), name));
#else
return reinterpret_cast<void*>(dlsym(handle, name));
#endif
}
} // namespace Common
-75
View File
@@ -1,75 +0,0 @@
// Copyright 2019 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <string>
namespace Common {
/**
* Provides a platform-independent interface for loading a dynamic library and retrieving symbols.
* The interface maintains an internal reference count to allow one handle to be shared between
* multiple users.
*/
class DynamicLibrary final {
public:
/// Default constructor, does not load a library.
explicit DynamicLibrary();
/// Automatically loads the specified library. Call IsOpen() to check validity before use.
explicit DynamicLibrary(const char* filename);
/// Moves the library.
DynamicLibrary(DynamicLibrary&&) noexcept;
DynamicLibrary& operator=(DynamicLibrary&&) noexcept;
/// Delete copies, we can't copy a dynamic library.
DynamicLibrary(const DynamicLibrary&) = delete;
DynamicLibrary& operator=(const DynamicLibrary&) = delete;
/// Closes the library.
~DynamicLibrary();
/// Returns the specified library name with the platform-specific suffix added.
static std::string GetUnprefixedFilename(const char* filename);
/// Returns the specified library name in platform-specific format.
/// Major/minor versions will not be included if set to -1.
/// If libname already contains the "lib" prefix, it will not be added again.
/// Windows: LIBNAME-MAJOR-MINOR.dll
/// Linux: libLIBNAME.so.MAJOR.MINOR
/// Mac: libLIBNAME.MAJOR.MINOR.dylib
static std::string GetVersionedFilename(const char* libname, int major = -1, int minor = -1);
/// Returns true if a module is loaded, otherwise false.
bool IsOpen() const {
return handle != nullptr;
}
/// Loads (or replaces) the handle with the specified library file name.
/// Returns true if the library was loaded and can be used.
bool Open(const char* filename);
/// Unloads the library, any function pointers from this library are no longer valid.
void Close();
/// Returns the address of the specified symbol (function or variable) as an untyped pointer.
/// If the specified symbol does not exist in this library, nullptr is returned.
void* GetSymbolAddress(const char* name) const;
/// Obtains the address of the specified symbol, automatically casting to the correct type.
/// Returns true if the symbol was found and assigned, otherwise false.
template <typename T>
bool GetSymbol(const char* name, T* ptr) const {
*ptr = reinterpret_cast<T>(GetSymbolAddress(name));
return *ptr != nullptr;
}
private:
/// Platform-dependent data type representing a dynamic library handle.
void* handle = nullptr;
};
} // namespace Common
+9 -13
View File
@@ -3,7 +3,6 @@
// Refer to the license.txt file included.
#include <array>
#include <limits>
#include <memory>
#include <sstream>
#include <unordered_map>
@@ -531,11 +530,11 @@ void CopyDir(const std::string& source_path, const std::string& dest_path) {
std::optional<std::string> GetCurrentDir() {
// Get the current working directory (getcwd uses malloc)
#ifdef _WIN32
wchar_t* dir = _wgetcwd(nullptr, 0);
if (!dir) {
wchar_t* dir;
if (!(dir = _wgetcwd(nullptr, 0))) {
#else
char* dir = getcwd(nullptr, 0);
if (!dir) {
char* dir;
if (!(dir = getcwd(nullptr, 0))) {
#endif
LOG_ERROR(Common_Filesystem, "GetCurrentDirectory failed: {}", GetLastErrorMsg());
return {};
@@ -919,22 +918,19 @@ void IOFile::Swap(IOFile& other) noexcept {
bool IOFile::Open(const std::string& filename, const char openmode[], int flags) {
Close();
bool m_good;
#ifdef _WIN32
if (flags != 0) {
m_file = _wfsopen(Common::UTF8ToUTF16W(filename).c_str(),
Common::UTF8ToUTF16W(openmode).c_str(), flags);
m_good = m_file != nullptr;
} else {
m_good = _wfopen_s(&m_file, Common::UTF8ToUTF16W(filename).c_str(),
Common::UTF8ToUTF16W(openmode).c_str()) == 0;
_wfopen_s(&m_file, Common::UTF8ToUTF16W(filename).c_str(),
Common::UTF8ToUTF16W(openmode).c_str());
}
#else
m_file = std::fopen(filename.c_str(), openmode);
m_good = m_file != nullptr;
m_file = fopen(filename.c_str(), openmode);
#endif
return m_good;
return IsOpen();
}
bool IOFile::Close() {
@@ -960,7 +956,7 @@ u64 IOFile::Tell() const {
if (IsOpen())
return ftello(m_file);
return std::numeric_limits<u64>::max();
return -1;
}
bool IOFile::Flush() {
+2 -14
View File
@@ -24,29 +24,17 @@ struct Rectangle {
: left(left), top(top), right(right), bottom(bottom) {}
T GetWidth() const {
if constexpr (std::is_floating_point_v<T>) {
return std::abs(right - left);
} else {
return std::abs(static_cast<std::make_signed_t<T>>(right - left));
}
return std::abs(static_cast<std::make_signed_t<T>>(right - left));
}
T GetHeight() const {
if constexpr (std::is_floating_point_v<T>) {
return std::abs(bottom - top);
} else {
return std::abs(static_cast<std::make_signed_t<T>>(bottom - top));
}
return std::abs(static_cast<std::make_signed_t<T>>(bottom - top));
}
Rectangle<T> TranslateX(const T x) const {
return Rectangle{left + x, top, right + x, bottom};
}
Rectangle<T> TranslateY(const T y) const {
return Rectangle{left, top + y, right, bottom + y};
}
Rectangle<T> Scale(const float s) const {
return Rectangle{left, top, static_cast<T>(left + GetWidth() * s),
static_cast<T>(top + GetHeight() * s)};
+1 -11
View File
@@ -16,6 +16,7 @@ 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
@@ -24,17 +25,6 @@ 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();
}
+2 -13
View File
@@ -76,20 +76,9 @@ 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
+6 -3
View File
@@ -28,8 +28,11 @@ namespace Common {
#ifdef _MSC_VER
// Sets the debugger-visible name of the current thread.
// Uses trick documented in:
// https://docs.microsoft.com/en-us/visualstudio/debugger/how-to-set-a-thread-name-in-native-code
// Uses undocumented (actually, it is now documented) trick.
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/vxtsksettingthreadname.asp
// This is implemented much nicer in upcoming msvc++, see:
// http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.100).aspx
void SetCurrentThreadName(const char* name) {
static const DWORD MS_VC_EXCEPTION = 0x406D1388;
@@ -44,7 +47,7 @@ void SetCurrentThreadName(const char* name) {
info.dwType = 0x1000;
info.szName = name;
info.dwThreadID = std::numeric_limits<DWORD>::max();
info.dwThreadID = -1; // dwThreadID;
info.dwFlags = 0;
__try {
+4 -18
View File
@@ -131,6 +131,8 @@ add_library(core STATIC
frontend/framebuffer_layout.cpp
frontend/framebuffer_layout.h
frontend/input.h
frontend/scope_acquire_window_context.cpp
frontend/scope_acquire_window_context.h
gdbstub/gdbstub.cpp
gdbstub/gdbstub.h
hardware_interrupt_manager.cpp
@@ -285,18 +287,6 @@ 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
@@ -605,12 +595,8 @@ endif()
if (ARCHITECTURE_x86_64)
target_sources(core PRIVATE
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
arm/dynarmic/arm_dynarmic.cpp
arm/dynarmic/arm_dynarmic.h
)
target_link_libraries(core PRIVATE dynarmic)
endif()
+13 -19
View File
@@ -25,20 +25,7 @@ public:
explicit ARM_Interface(System& system_) : system{system_} {}
virtual ~ARM_Interface() = default;
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 {
struct ThreadContext {
std::array<u64, 31> cpu_registers;
u64 sp;
u64 pc;
@@ -51,7 +38,7 @@ public:
};
// Internally within the kernel, it expects the AArch64 version of the
// thread context to be 800 bytes in size.
static_assert(sizeof(ThreadContext64) == 0x320);
static_assert(sizeof(ThreadContext) == 0x320);
/// Runs the CPU until an event happens
virtual void Run() = 0;
@@ -143,10 +130,17 @@ public:
*/
virtual void SetTPIDR_EL0(u64 value) = 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;
/**
* 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;
/// Clears the exclusive monitor's state.
virtual void ClearExclusiveState() = 0;
@@ -8,7 +8,7 @@
#include <dynarmic/A64/config.h>
#include "common/logging/log.h"
#include "common/microprofile.h"
#include "core/arm/dynarmic/arm_dynarmic_64.h"
#include "core/arm/dynarmic/arm_dynarmic.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 DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
class ARM_Dynarmic_Callbacks : public Dynarmic::A64::UserCallbacks {
public:
explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent) : parent(parent) {}
explicit ARM_Dynarmic_Callbacks(ARM_Dynarmic& 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::ThreadContext64 ctx;
ARM_Interface::ThreadContext 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->GetContext64());
parent.SaveContext(thread->GetContext());
GDBStub::Break();
GDBStub::SendTrap(thread, 5);
return;
@@ -126,14 +126,14 @@ public:
return Timing::CpuCyclesToClockCycles(parent.system.CoreTiming().GetTicks());
}
ARM_Dynarmic_64& parent;
ARM_Dynarmic& parent;
std::size_t num_interpreted_instructions = 0;
u64 tpidrro_el0 = 0;
u64 tpidr_el0 = 0;
};
std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable& page_table,
std::size_t address_space_bits) const {
std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit(Common::PageTable& page_table,
std::size_t address_space_bits) const {
Dynarmic::A64::UserConfig config;
// Callbacks
@@ -159,79 +159,79 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable&
// Unpredictable instructions
config.define_unpredictable_behaviour = true;
return std::make_shared<Dynarmic::A64::Jit>(config);
return std::make_unique<Dynarmic::A64::Jit>(config);
}
MICROPROFILE_DEFINE(ARM_Jit_Dynarmic_64, "ARM JIT", "Dynarmic", MP_RGB(255, 64, 64));
MICROPROFILE_DEFINE(ARM_Jit_Dynarmic, "ARM JIT", "Dynarmic", MP_RGB(255, 64, 64));
void ARM_Dynarmic_64::Run() {
MICROPROFILE_SCOPE(ARM_Jit_Dynarmic_64);
void ARM_Dynarmic::Run() {
MICROPROFILE_SCOPE(ARM_Jit_Dynarmic);
jit->Run();
}
void ARM_Dynarmic_64::Step() {
void ARM_Dynarmic::Step() {
cb->InterpreterFallback(jit->GetPC(), 1);
}
ARM_Dynarmic_64::ARM_Dynarmic_64(System& system, ExclusiveMonitor& exclusive_monitor,
std::size_t core_index)
ARM_Dynarmic::ARM_Dynarmic(System& system, ExclusiveMonitor& exclusive_monitor,
std::size_t core_index)
: ARM_Interface{system},
cb(std::make_unique<DynarmicCallbacks64>(*this)), inner_unicorn{system},
cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), inner_unicorn{system},
core_index{core_index}, exclusive_monitor{
dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {}
ARM_Dynarmic_64::~ARM_Dynarmic_64() = default;
ARM_Dynarmic::~ARM_Dynarmic() = default;
void ARM_Dynarmic_64::SetPC(u64 pc) {
void ARM_Dynarmic::SetPC(u64 pc) {
jit->SetPC(pc);
}
u64 ARM_Dynarmic_64::GetPC() const {
u64 ARM_Dynarmic::GetPC() const {
return jit->GetPC();
}
u64 ARM_Dynarmic_64::GetReg(int index) const {
u64 ARM_Dynarmic::GetReg(int index) const {
return jit->GetRegister(index);
}
void ARM_Dynarmic_64::SetReg(int index, u64 value) {
void ARM_Dynarmic::SetReg(int index, u64 value) {
jit->SetRegister(index, value);
}
u128 ARM_Dynarmic_64::GetVectorReg(int index) const {
u128 ARM_Dynarmic::GetVectorReg(int index) const {
return jit->GetVector(index);
}
void ARM_Dynarmic_64::SetVectorReg(int index, u128 value) {
void ARM_Dynarmic::SetVectorReg(int index, u128 value) {
jit->SetVector(index, value);
}
u32 ARM_Dynarmic_64::GetPSTATE() const {
u32 ARM_Dynarmic::GetPSTATE() const {
return jit->GetPstate();
}
void ARM_Dynarmic_64::SetPSTATE(u32 pstate) {
void ARM_Dynarmic::SetPSTATE(u32 pstate) {
jit->SetPstate(pstate);
}
u64 ARM_Dynarmic_64::GetTlsAddress() const {
u64 ARM_Dynarmic::GetTlsAddress() const {
return cb->tpidrro_el0;
}
void ARM_Dynarmic_64::SetTlsAddress(VAddr address) {
void ARM_Dynarmic::SetTlsAddress(VAddr address) {
cb->tpidrro_el0 = address;
}
u64 ARM_Dynarmic_64::GetTPIDR_EL0() const {
u64 ARM_Dynarmic::GetTPIDR_EL0() const {
return cb->tpidr_el0;
}
void ARM_Dynarmic_64::SetTPIDR_EL0(u64 value) {
void ARM_Dynarmic::SetTPIDR_EL0(u64 value) {
cb->tpidr_el0 = value;
}
void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) {
void ARM_Dynarmic::SaveContext(ThreadContext& ctx) {
ctx.cpu_registers = jit->GetRegisters();
ctx.sp = jit->GetSP();
ctx.pc = jit->GetPC();
@@ -242,7 +242,7 @@ void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) {
ctx.tpidr = cb->tpidr_el0;
}
void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) {
void ARM_Dynarmic::LoadContext(const ThreadContext& ctx) {
jit->SetRegisters(ctx.cpu_registers);
jit->SetSP(ctx.sp);
jit->SetPC(ctx.pc);
@@ -253,32 +253,25 @@ void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) {
SetTPIDR_EL0(ctx.tpidr);
}
void ARM_Dynarmic_64::PrepareReschedule() {
void ARM_Dynarmic::PrepareReschedule() {
jit->HaltExecution();
}
void ARM_Dynarmic_64::ClearInstructionCache() {
void ARM_Dynarmic::ClearInstructionCache() {
jit->ClearCache();
}
void ARM_Dynarmic_64::ClearExclusiveState() {
void ARM_Dynarmic::ClearExclusiveState() {
jit->ClearExclusiveState();
}
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;
}
void ARM_Dynarmic::PageTableChanged(Common::PageTable& page_table,
std::size_t new_address_space_size_in_bits) {
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,12 +5,9 @@
#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"
@@ -21,14 +18,14 @@ class Memory;
namespace Core {
class DynarmicCallbacks64;
class ARM_Dynarmic_Callbacks;
class DynarmicExclusiveMonitor;
class System;
class ARM_Dynarmic_64 final : public ARM_Interface {
class ARM_Dynarmic final : public ARM_Interface {
public:
ARM_Dynarmic_64(System& system, ExclusiveMonitor& exclusive_monitor, std::size_t core_index);
~ARM_Dynarmic_64() override;
ARM_Dynarmic(System& system, ExclusiveMonitor& exclusive_monitor, std::size_t core_index);
~ARM_Dynarmic() override;
void SetPC(u64 pc) override;
u64 GetPC() const override;
@@ -45,10 +42,8 @@ public:
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 SaveContext(ThreadContext& ctx) override;
void LoadContext(const ThreadContext& ctx) override;
void PrepareReschedule() override;
void ClearExclusiveState() override;
@@ -58,17 +53,12 @@ public:
std::size_t new_address_space_size_in_bits) override;
private:
std::shared_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable& page_table,
std::unique_ptr<Dynarmic::A64::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::A64::Jit>, Common::PairHash>;
friend class DynarmicCallbacks64;
std::unique_ptr<DynarmicCallbacks64> cb;
JitCacheType jit_cache;
std::shared_ptr<Dynarmic::A64::Jit> jit;
friend class ARM_Dynarmic_Callbacks;
std::unique_ptr<ARM_Dynarmic_Callbacks> cb;
std::unique_ptr<Dynarmic::A64::Jit> jit;
ARM_Unicorn inner_unicorn;
std::size_t core_index;
@@ -77,7 +67,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;
@@ -90,7 +80,7 @@ public:
bool ExclusiveWrite128(std::size_t core_index, VAddr vaddr, u128 value) override;
private:
friend class ARM_Dynarmic_64;
friend class ARM_Dynarmic;
Dynarmic::A64::ExclusiveMonitor monitor;
Memory::Memory& memory;
};
-208
View File
@@ -1,208 +0,0 @@
// 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
View File
@@ -1,77 +0,0 @@
// 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
@@ -1,80 +0,0 @@
// 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
View File
@@ -1,152 +0,0 @@
// 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{};
};
+1 -1
View File
@@ -3,7 +3,7 @@
// Refer to the license.txt file included.
#ifdef ARCHITECTURE_x86_64
#include "core/arm/dynarmic/arm_dynarmic_64.h"
#include "core/arm/dynarmic/arm_dynarmic.h"
#endif
#include "core/arm/exclusive_monitor.h"
#include "core/memory.h"
+4 -4
View File
@@ -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::ThreadContext64 ctx{};
ARM_Interface::ThreadContext 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->GetContext64());
SaveContext(thread->GetContext());
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(ThreadContext64& ctx) {
void ARM_Unicorn::SaveContext(ThreadContext& ctx) {
int uregs[32];
void* tregs[32];
@@ -215,7 +215,7 @@ void ARM_Unicorn::SaveContext(ThreadContext64& ctx) {
CHECKED(uc_reg_read_batch(uc, uregs, tregs, 32));
}
void ARM_Unicorn::LoadContext(const ThreadContext64& ctx) {
void ARM_Unicorn::LoadContext(const ThreadContext& ctx) {
int uregs[32];
void* tregs[32];
+2 -5
View File
@@ -30,6 +30,8 @@ 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);
@@ -39,11 +41,6 @@ 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);
+13 -7
View File
@@ -165,14 +165,14 @@ struct System::Impl {
service_manager = std::make_shared<Service::SM::ServiceManager>();
Service::Init(service_manager, system);
GDBStub::DeferStart();
GDBStub::Init();
interrupt_manager = std::make_unique<Core::Hardware::InterruptManager>(system);
gpu_core = VideoCore::CreateGPU(emu_window, system);
if (!gpu_core) {
renderer = VideoCore::CreateRenderer(emu_window, system);
if (!renderer->Init()) {
return ResultStatus::ErrorVideoCore;
}
gpu_core->Renderer().Rasterizer().SetupDirtyFlags();
interrupt_manager = std::make_unique<Core::Hardware::InterruptManager>(system);
gpu_core = VideoCore::CreateGPU(system);
is_powered_on = true;
exit_lock = false;
@@ -212,6 +212,10 @@ 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();
@@ -269,6 +273,7 @@ struct System::Impl {
}
// Shutdown emulation session
renderer.reset();
GDBStub::Shutdown();
Service::Shutdown();
service_manager.reset();
@@ -344,6 +349,7 @@ 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;
@@ -526,11 +532,11 @@ const Core::Hardware::InterruptManager& System::InterruptManager() const {
}
VideoCore::RendererBase& System::Renderer() {
return impl->gpu_core->Renderer();
return *impl->renderer;
}
const VideoCore::RendererBase& System::Renderer() const {
return impl->gpu_core->Renderer();
return *impl->renderer;
}
Kernel::KernelCore& System::Kernel() {
+3
View File
@@ -6,6 +6,9 @@
#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"
+1 -2
View File
@@ -5,7 +5,6 @@
#include <memory>
#include "common/common_types.h"
#include "common/string_util.h"
#include "common/swap.h"
#include "core/file_sys/fsmitm_romfsbuild.h"
#include "core/file_sys/romfs.h"
@@ -127,7 +126,7 @@ VirtualDir ExtractRomFS(VirtualFile file, RomFSExtractionType type) {
return out->GetSubdirectories().front();
while (out->GetSubdirectories().size() == 1 && out->GetFiles().empty()) {
if (Common::ToLower(out->GetSubdirectories().front()->GetName()) == "data" &&
if (out->GetSubdirectories().front()->GetName() == "data" &&
type == RomFSExtractionType::Truncated)
break;
out = out->GetSubdirectories().front();
+23 -63
View File
@@ -12,49 +12,23 @@
namespace Core::Frontend {
/// Information for the Graphics Backends signifying what type of screen pointer is in
/// WindowInformation
enum class WindowSystemType {
Headless,
Windows,
X11,
Wayland,
};
/**
* Represents a drawing context that supports graphics operations.
* 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
*/
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() {}
virtual void MakeCurrent() = 0;
/// Releases (dunno if this is the "right" word) the context from the caller thread
virtual void DoneCurrent() {}
virtual void DoneCurrent() = 0;
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};
}
/// Swap buffers to display the next frame
virtual void SwapBuffers() = 0;
};
/**
@@ -75,7 +49,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 {
class EmuWindow : public GraphicsContext {
public:
/// Data structure to store emuwindow configuration
struct WindowConfig {
@@ -85,34 +59,29 @@ public:
std::pair<unsigned, unsigned> min_client_area_size;
};
/// Data describing host window system information
struct WindowSystemInfo {
// Window system type. Determines which GL context or Vulkan WSI is used.
WindowSystemType type = WindowSystemType::Headless;
// Connection to a display server. This is used on X11 and Wayland platforms.
void* display_connection = nullptr;
// Render surface. This is a pointer to the native window handle, which depends
// on the platform. e.g. HWND for Windows, Window for X11. If the surface is
// set to nullptr, the video backend will run in headless mode.
void* render_surface = nullptr;
// Scale of the render surface. For hidpi systems, this will be >1.
float render_surface_scale = 1.0f;
};
/// Polls window events
virtual void PollEvents() = 0;
/**
* Returns a GraphicsContext that the frontend provides to be used for rendering.
* 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
*/
virtual std::unique_ptr<GraphicsContext> CreateSharedContext() const = 0;
virtual std::unique_ptr<GraphicsContext> CreateSharedContext() const {
return nullptr;
}
/// Returns if window is shown (not minimized)
virtual bool IsShown() const = 0;
/// Retrieves Vulkan specific handlers from the window
virtual void RetrieveVulkanHandlers(void* get_instance_proc_addr, void* instance,
void* surface) const = 0;
/**
* Signal that a touch pressed event has occurred (e.g. mouse click pressed)
* @param framebuffer_x Framebuffer x-coordinate that was pressed
@@ -149,13 +118,6 @@ public:
config = val;
}
/**
* Returns system information about the drawing area.
*/
const WindowSystemInfo& GetWindowInfo() const {
return window_info;
}
/**
* Gets the framebuffer layout (width, height, and screen regions)
* @note This method is thread-safe
@@ -171,7 +133,7 @@ public:
void UpdateCurrentFramebufferLayout(unsigned width, unsigned height);
protected:
explicit EmuWindow();
EmuWindow();
virtual ~EmuWindow();
/**
@@ -208,8 +170,6 @@ protected:
client_area_height = size.second;
}
WindowSystemInfo window_info;
private:
/**
* Handler called when the minimal client area was requested to be changed via SetConfig.
+2 -2
View File
@@ -48,8 +48,8 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale) {
u32 width, height;
if (Settings::values.use_docked_mode) {
width = ScreenDocked::Width * res_scale;
height = ScreenDocked::Height * res_scale;
width = ScreenDocked::WidthDocked * res_scale;
height = ScreenDocked::HeightDocked * res_scale;
} else {
width = ScreenUndocked::Width * res_scale;
height = ScreenUndocked::Height * res_scale;
+8 -9
View File
@@ -8,15 +8,15 @@
namespace Layout {
namespace ScreenUndocked {
constexpr u32 Width = 1280;
constexpr u32 Height = 720;
} // namespace ScreenUndocked
enum ScreenUndocked : u32 {
Width = 1280,
Height = 720,
};
namespace ScreenDocked {
constexpr u32 Width = 1920;
constexpr u32 Height = 1080;
} // namespace ScreenDocked
enum ScreenDocked : u32 {
WidthDocked = 1920,
HeightDocked = 1080,
};
enum class AspectRatio {
Default,
@@ -29,7 +29,6 @@ enum class AspectRatio {
struct FramebufferLayout {
u32 width{ScreenUndocked::Width};
u32 height{ScreenUndocked::Height};
bool is_srgb{};
Common::Rectangle<u32> screen;
@@ -0,0 +1,18 @@
// 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_window_context.h"
namespace Core::Frontend {
ScopeAcquireWindowContext::ScopeAcquireWindowContext(Core::Frontend::EmuWindow& emu_window_)
: emu_window{emu_window_} {
emu_window.MakeCurrent();
}
ScopeAcquireWindowContext::~ScopeAcquireWindowContext() {
emu_window.DoneCurrent();
}
} // namespace Core::Frontend
@@ -0,0 +1,23 @@
// 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 EmuWindow;
/// Helper class to acquire/release window context within a given scope
class ScopeAcquireWindowContext : NonCopyable {
public:
explicit ScopeAcquireWindowContext(Core::Frontend::EmuWindow& window);
~ScopeAcquireWindowContext();
private:
Core::Frontend::EmuWindow& emu_window;
};
} // namespace Core::Frontend
+7 -16
View File
@@ -141,7 +141,6 @@ constexpr char target_xml[] =
)";
int gdbserver_socket = -1;
bool defer_start = false;
u8 command_buffer[GDB_BUFFER_SIZE];
u32 command_length;
@@ -218,7 +217,7 @@ static u64 RegRead(std::size_t id, Kernel::Thread* thread = nullptr) {
return 0;
}
const auto& thread_context = thread->GetContext64();
const auto& thread_context = thread->GetContext();
if (id < SP_REGISTER) {
return thread_context.cpu_registers[id];
@@ -240,7 +239,7 @@ static void RegWrite(std::size_t id, u64 val, Kernel::Thread* thread = nullptr)
return;
}
auto& thread_context = thread->GetContext64();
auto& thread_context = thread->GetContext();
if (id < SP_REGISTER) {
thread_context.cpu_registers[id] = val;
@@ -260,7 +259,7 @@ static u128 FpuRead(std::size_t id, Kernel::Thread* thread = nullptr) {
return u128{0};
}
auto& thread_context = thread->GetContext64();
auto& thread_context = thread->GetContext();
if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {
return thread_context.vector_registers[id - UC_ARM64_REG_Q0];
@@ -276,7 +275,7 @@ static void FpuWrite(std::size_t id, u128 val, Kernel::Thread* thread = nullptr)
return;
}
auto& thread_context = thread->GetContext64();
auto& thread_context = thread->GetContext();
if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {
thread_context.vector_registers[id - UC_ARM64_REG_Q0] = val;
@@ -917,7 +916,7 @@ static void WriteRegister() {
// Update ARM context, skipping scheduler - no running threads at this point
Core::System::GetInstance()
.ArmInterface(current_core)
.LoadContext(current_thread->GetContext64());
.LoadContext(current_thread->GetContext());
SendReply("OK");
}
@@ -948,7 +947,7 @@ static void WriteRegisters() {
// Update ARM context, skipping scheduler - no running threads at this point
Core::System::GetInstance()
.ArmInterface(current_core)
.LoadContext(current_thread->GetContext64());
.LoadContext(current_thread->GetContext());
SendReply("OK");
}
@@ -1020,7 +1019,7 @@ static void Step() {
// Update ARM context, skipping scheduler - no running threads at this point
Core::System::GetInstance()
.ArmInterface(current_core)
.LoadContext(current_thread->GetContext64());
.LoadContext(current_thread->GetContext());
}
step_loop = true;
halt_loop = true;
@@ -1167,9 +1166,6 @@ static void RemoveBreakpoint() {
void HandlePacket() {
if (!IsConnected()) {
if (defer_start) {
ToggleServer(true);
}
return;
}
@@ -1260,10 +1256,6 @@ 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.
@@ -1349,7 +1341,6 @@ void Shutdown() {
if (!server_enabled) {
return;
}
defer_start = false;
LOG_INFO(Debug_GDBStub, "Stopping GDB ...");
if (gdbserver_socket != -1) {
-7
View File
@@ -43,13 +43,6 @@ 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();
-4
View File
@@ -186,10 +186,6 @@ struct KernelCore::Impl {
return;
}
for (auto& core : cores) {
core.SetIs64Bit(process->Is64BitProcess());
}
system.Memory().SetCurrentPageTable(*process);
}
+3 -16
View File
@@ -5,8 +5,7 @@
#include "common/logging/log.h"
#include "core/arm/arm_interface.h"
#ifdef ARCHITECTURE_x86_64
#include "core/arm/dynarmic/arm_dynarmic_32.h"
#include "core/arm/dynarmic/arm_dynarmic_64.h"
#include "core/arm/dynarmic/arm_dynarmic.h"
#endif
#include "core/arm/exclusive_monitor.h"
#include "core/arm/unicorn/arm_unicorn.h"
@@ -21,17 +20,13 @@ PhysicalCore::PhysicalCore(Core::System& system, std::size_t id,
Core::ExclusiveMonitor& exclusive_monitor)
: core_index{id} {
#ifdef ARCHITECTURE_x86_64
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);
arm_interface = std::make_unique<Core::ARM_Dynarmic>(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, core_index);
scheduler = std::make_unique<Kernel::Scheduler>(system, *arm_interface, core_index);
}
PhysicalCore::~PhysicalCore() = default;
@@ -53,12 +48,4 @@ 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
+1 -5
View File
@@ -68,14 +68,10 @@ public:
return *scheduler;
}
void SetIs64Bit(bool is_64_bit);
private:
std::size_t core_index;
std::unique_ptr<Core::ARM_Interface> arm_interface_32;
std::unique_ptr<Core::ARM_Interface> arm_interface_64;
std::unique_ptr<Core::ARM_Interface> arm_interface;
std::unique_ptr<Kernel::Scheduler> scheduler;
Core::ARM_Interface* arm_interface{};
};
} // namespace Kernel
+1 -2
View File
@@ -42,8 +42,7 @@ 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->GetContext32().cpu_registers[1] = thread_handle;
thread->GetContext64().cpu_registers[1] = thread_handle;
thread->GetContext().cpu_registers[1] = thread_handle;
// Threads by default are dormant, wake up the main thread so it runs when the scheduler fires
thread->ResumeFromWait();
+9 -12
View File
@@ -383,8 +383,8 @@ void GlobalScheduler::Unlock() {
// TODO(Blinkhawk): Setup the interrupts and change context on current core.
}
Scheduler::Scheduler(Core::System& system, std::size_t core_id)
: system{system}, core_id{core_id} {}
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() = default;
@@ -422,10 +422,9 @@ void Scheduler::UnloadThread() {
// Save context for previous thread
if (previous_thread) {
system.ArmInterface(core_id).SaveContext(previous_thread->GetContext32());
system.ArmInterface(core_id).SaveContext(previous_thread->GetContext64());
cpu_core.SaveContext(previous_thread->GetContext());
// Save the TPIDR_EL0 system register in case it was modified.
previous_thread->SetTPIDR_EL0(system.ArmInterface(core_id).GetTPIDR_EL0());
previous_thread->SetTPIDR_EL0(cpu_core.GetTPIDR_EL0());
if (previous_thread->GetStatus() == ThreadStatus::Running) {
// This is only the case when a reschedule is triggered without the current thread
@@ -452,10 +451,9 @@ void Scheduler::SwitchContext() {
// Save context for previous thread
if (previous_thread) {
system.ArmInterface(core_id).SaveContext(previous_thread->GetContext32());
system.ArmInterface(core_id).SaveContext(previous_thread->GetContext64());
cpu_core.SaveContext(previous_thread->GetContext());
// Save the TPIDR_EL0 system register in case it was modified.
previous_thread->SetTPIDR_EL0(system.ArmInterface(core_id).GetTPIDR_EL0());
previous_thread->SetTPIDR_EL0(cpu_core.GetTPIDR_EL0());
if (previous_thread->GetStatus() == ThreadStatus::Running) {
// This is only the case when a reschedule is triggered without the current thread
@@ -483,10 +481,9 @@ void Scheduler::SwitchContext() {
system.Kernel().MakeCurrentProcess(thread_owner_process);
}
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());
cpu_core.LoadContext(new_thread->GetContext());
cpu_core.SetTlsAddress(new_thread->GetTLSAddress());
cpu_core.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
+2 -1
View File
@@ -181,7 +181,7 @@ private:
class Scheduler final {
public:
explicit Scheduler(Core::System& system, std::size_t core_id);
explicit Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, std::size_t core_id);
~Scheduler();
/// Returns whether there are any threads that are ready to run.
@@ -235,6 +235,7 @@ 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;
+65 -264
View File
@@ -187,13 +187,6 @@ 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);
@@ -378,12 +371,6 @@ 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();
@@ -403,10 +390,6 @@ 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);
@@ -422,17 +405,6 @@ 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);
@@ -507,12 +479,6 @@ 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);
@@ -951,18 +917,6 @@ 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);
@@ -1104,7 +1058,7 @@ static ResultCode GetThreadContext(Core::System& system, VAddr thread_context, H
return ERR_BUSY;
}
Core::ARM_Interface::ThreadContext64 ctx = thread->GetContext64();
Core::ARM_Interface::ThreadContext ctx = thread->GetContext();
// Mask away mode bits, interrupt bits, IL bit, and other reserved bits.
ctx.pstate &= 0xFF0FFE20;
@@ -1134,10 +1088,6 @@ 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");
@@ -1309,11 +1259,6 @@ 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,
@@ -1730,10 +1675,6 @@ 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) {
@@ -1819,10 +1760,6 @@ 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);
@@ -2380,196 +2317,69 @@ struct FunctionDef {
};
} // namespace
static const FunctionDef SVC_Table_32[] = {
static const FunctionDef SVC_Table[] = {
{0x00, nullptr, "Unknown"},
{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"},
{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"},
{0x20, nullptr, "SendSyncRequestLight"},
{0x21, SvcWrap64<SendSyncRequest>, "SendSyncRequest"},
{0x21, SvcWrap<SendSyncRequest>, "SendSyncRequest"},
{0x22, nullptr, "SendSyncRequestWithUserBuffer"},
{0x23, nullptr, "SendAsyncRequestWithUserBuffer"},
{0x24, SvcWrap64<GetProcessId>, "GetProcessId"},
{0x25, SvcWrap64<GetThreadId>, "GetThreadId"},
{0x26, SvcWrap64<Break>, "Break"},
{0x27, SvcWrap64<OutputDebugString>, "OutputDebugString"},
{0x24, SvcWrap<GetProcessId>, "GetProcessId"},
{0x25, SvcWrap<GetThreadId>, "GetThreadId"},
{0x26, SvcWrap<Break>, "Break"},
{0x27, SvcWrap<OutputDebugString>, "OutputDebugString"},
{0x28, nullptr, "ReturnFromException"},
{0x29, SvcWrap64<GetInfo>, "GetInfo"},
{0x29, SvcWrap<GetInfo>, "GetInfo"},
{0x2A, nullptr, "FlushEntireDataCache"},
{0x2B, nullptr, "FlushDataCache"},
{0x2C, SvcWrap64<MapPhysicalMemory>, "MapPhysicalMemory"},
{0x2D, SvcWrap64<UnmapPhysicalMemory>, "UnmapPhysicalMemory"},
{0x2C, SvcWrap<MapPhysicalMemory>, "MapPhysicalMemory"},
{0x2D, SvcWrap<UnmapPhysicalMemory>, "UnmapPhysicalMemory"},
{0x2E, nullptr, "GetFutureThreadInfo"},
{0x2F, nullptr, "GetLastThreadInfo"},
{0x30, SvcWrap64<GetResourceLimitLimitValue>, "GetResourceLimitLimitValue"},
{0x31, SvcWrap64<GetResourceLimitCurrentValue>, "GetResourceLimitCurrentValue"},
{0x32, SvcWrap64<SetThreadActivity>, "SetThreadActivity"},
{0x33, SvcWrap64<GetThreadContext>, "GetThreadContext"},
{0x34, SvcWrap64<WaitForAddress>, "WaitForAddress"},
{0x35, SvcWrap64<SignalToAddress>, "SignalToAddress"},
{0x30, SvcWrap<GetResourceLimitLimitValue>, "GetResourceLimitLimitValue"},
{0x31, SvcWrap<GetResourceLimitCurrentValue>, "GetResourceLimitCurrentValue"},
{0x32, SvcWrap<SetThreadActivity>, "SetThreadActivity"},
{0x33, SvcWrap<GetThreadContext>, "GetThreadContext"},
{0x34, SvcWrap<WaitForAddress>, "WaitForAddress"},
{0x35, SvcWrap<SignalToAddress>, "SignalToAddress"},
{0x36, nullptr, "SynchronizePreemptionState"},
{0x37, nullptr, "Unknown"},
{0x38, nullptr, "Unknown"},
{0x39, nullptr, "Unknown"},
{0x3A, nullptr, "Unknown"},
{0x3B, nullptr, "Unknown"},
{0x3C, SvcWrap64<KernelDebug>, "KernelDebug"},
{0x3D, SvcWrap64<ChangeKernelTraceState>, "ChangeKernelTraceState"},
{0x3C, SvcWrap<KernelDebug>, "KernelDebug"},
{0x3D, SvcWrap<ChangeKernelTraceState>, "ChangeKernelTraceState"},
{0x3E, nullptr, "Unknown"},
{0x3F, nullptr, "Unknown"},
{0x40, nullptr, "CreateSession"},
@@ -2577,7 +2387,7 @@ static const FunctionDef SVC_Table_64[] = {
{0x42, nullptr, "ReplyAndReceiveLight"},
{0x43, nullptr, "ReplyAndReceive"},
{0x44, nullptr, "ReplyAndReceiveWithUserBuffer"},
{0x45, SvcWrap64<CreateEvent>, "CreateEvent"},
{0x45, SvcWrap<CreateEvent>, "CreateEvent"},
{0x46, nullptr, "Unknown"},
{0x47, nullptr, "Unknown"},
{0x48, nullptr, "MapPhysicalMemoryUnsafe"},
@@ -2588,9 +2398,9 @@ static const FunctionDef SVC_Table_64[] = {
{0x4D, nullptr, "SleepSystem"},
{0x4E, nullptr, "ReadWriteRegister"},
{0x4F, nullptr, "SetProcessActivity"},
{0x50, SvcWrap64<CreateSharedMemory>, "CreateSharedMemory"},
{0x51, SvcWrap64<MapTransferMemory>, "MapTransferMemory"},
{0x52, SvcWrap64<UnmapTransferMemory>, "UnmapTransferMemory"},
{0x50, SvcWrap<CreateSharedMemory>, "CreateSharedMemory"},
{0x51, SvcWrap<MapTransferMemory>, "MapTransferMemory"},
{0x52, SvcWrap<UnmapTransferMemory>, "UnmapTransferMemory"},
{0x53, nullptr, "CreateInterruptEvent"},
{0x54, nullptr, "QueryPhysicalAddress"},
{0x55, nullptr, "QueryIoMapping"},
@@ -2609,8 +2419,8 @@ static const FunctionDef SVC_Table_64[] = {
{0x62, nullptr, "TerminateDebugProcess"},
{0x63, nullptr, "GetDebugEvent"},
{0x64, nullptr, "ContinueDebugEvent"},
{0x65, SvcWrap64<GetProcessList>, "GetProcessList"},
{0x66, SvcWrap64<GetThreadList>, "GetThreadList"},
{0x65, SvcWrap<GetProcessList>, "GetProcessList"},
{0x66, SvcWrap<GetThreadList>, "GetThreadList"},
{0x67, nullptr, "GetDebugThreadContext"},
{0x68, nullptr, "SetDebugThreadContext"},
{0x69, nullptr, "QueryDebugProcessMemory"},
@@ -2626,32 +2436,24 @@ static const FunctionDef SVC_Table_64[] = {
{0x73, nullptr, "SetProcessMemoryPermission"},
{0x74, nullptr, "MapProcessMemory"},
{0x75, nullptr, "UnmapProcessMemory"},
{0x76, SvcWrap64<QueryProcessMemory>, "QueryProcessMemory"},
{0x77, SvcWrap64<MapProcessCodeMemory>, "MapProcessCodeMemory"},
{0x78, SvcWrap64<UnmapProcessCodeMemory>, "UnmapProcessCodeMemory"},
{0x76, SvcWrap<QueryProcessMemory>, "QueryProcessMemory"},
{0x77, SvcWrap<MapProcessCodeMemory>, "MapProcessCodeMemory"},
{0x78, SvcWrap<UnmapProcessCodeMemory>, "UnmapProcessCodeMemory"},
{0x79, nullptr, "CreateProcess"},
{0x7A, nullptr, "StartProcess"},
{0x7B, nullptr, "TerminateProcess"},
{0x7C, SvcWrap64<GetProcessInfo>, "GetProcessInfo"},
{0x7D, SvcWrap64<CreateResourceLimit>, "CreateResourceLimit"},
{0x7E, SvcWrap64<SetResourceLimitLimitValue>, "SetResourceLimitLimitValue"},
{0x7C, SvcWrap<GetProcessInfo>, "GetProcessInfo"},
{0x7D, SvcWrap<CreateResourceLimit>, "CreateResourceLimit"},
{0x7E, SvcWrap<SetResourceLimitLimitValue>, "SetResourceLimitLimitValue"},
{0x7F, nullptr, "CallSecureMonitor"},
};
static const FunctionDef* GetSVCInfo32(u32 func_num) {
if (func_num >= std::size(SVC_Table_32)) {
static const FunctionDef* GetSVCInfo(u32 func_num) {
if (func_num >= std::size(SVC_Table)) {
LOG_ERROR(Kernel_SVC, "Unknown svc=0x{:02X}", func_num);
return nullptr;
}
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];
return &SVC_Table[func_num];
}
MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70));
@@ -2662,8 +2464,7 @@ 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 = system.CurrentProcess()->Is64BitProcess() ? GetSVCInfo64(immediate)
: GetSVCInfo32(immediate);
const FunctionDef* info = GetSVCInfo(immediate);
if (info) {
if (info->func) {
info->func(system);
+42 -116
View File
@@ -15,10 +15,6 @@ 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
@@ -28,44 +24,40 @@ 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 SvcWrap64(Core::System& system) {
void SvcWrap(Core::System& system) {
FuncReturn(system, func(system, Param(system, 0)).raw);
}
template <ResultCode func(Core::System&, u64, u64)>
void SvcWrap64(Core::System& system) {
void SvcWrap(Core::System& system) {
FuncReturn(system, func(system, Param(system, 0), Param(system, 1)).raw);
}
template <ResultCode func(Core::System&, u32)>
void SvcWrap64(Core::System& system) {
void SvcWrap(Core::System& system) {
FuncReturn(system, func(system, static_cast<u32>(Param(system, 0))).raw);
}
template <ResultCode func(Core::System&, u32, u32)>
void SvcWrap64(Core::System& system) {
void SvcWrap(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 SvcWrap64(Core::System& system) {
void SvcWrap(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 SvcWrap64(Core::System& system) {
void SvcWrap(Core::System& system) {
u32 param = 0;
const u32 retval = func(system, &param).raw;
system.CurrentArmInterface().SetReg(1, param);
@@ -73,7 +65,7 @@ void SvcWrap64(Core::System& system) {
}
template <ResultCode func(Core::System&, u32*, u32)>
void SvcWrap64(Core::System& system) {
void SvcWrap(Core::System& system) {
u32 param_1 = 0;
const u32 retval = func(system, &param_1, static_cast<u32>(Param(system, 1))).raw;
system.CurrentArmInterface().SetReg(1, param_1);
@@ -81,7 +73,7 @@ void SvcWrap64(Core::System& system) {
}
template <ResultCode func(Core::System&, u32*, u32*)>
void SvcWrap64(Core::System& system) {
void SvcWrap(Core::System& system) {
u32 param_1 = 0;
u32 param_2 = 0;
const u32 retval = func(system, &param_1, &param_2).raw;
@@ -94,7 +86,7 @@ void SvcWrap64(Core::System& system) {
}
template <ResultCode func(Core::System&, u32*, u64)>
void SvcWrap64(Core::System& system) {
void SvcWrap(Core::System& system) {
u32 param_1 = 0;
const u32 retval = func(system, &param_1, Param(system, 1)).raw;
system.CurrentArmInterface().SetReg(1, param_1);
@@ -102,7 +94,7 @@ void SvcWrap64(Core::System& system) {
}
template <ResultCode func(Core::System&, u32*, u64, u32)>
void SvcWrap64(Core::System& system) {
void SvcWrap(Core::System& system) {
u32 param_1 = 0;
const u32 retval =
func(system, &param_1, Param(system, 1), static_cast<u32>(Param(system, 2))).raw;
@@ -112,7 +104,7 @@ void SvcWrap64(Core::System& system) {
}
template <ResultCode func(Core::System&, u64*, u32)>
void SvcWrap64(Core::System& system) {
void SvcWrap(Core::System& system) {
u64 param_1 = 0;
const u32 retval = func(system, &param_1, static_cast<u32>(Param(system, 1))).raw;
@@ -121,12 +113,12 @@ void SvcWrap64(Core::System& system) {
}
template <ResultCode func(Core::System&, u64, u32)>
void SvcWrap64(Core::System& system) {
void SvcWrap(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 SvcWrap64(Core::System& system) {
void SvcWrap(Core::System& system) {
u64 param_1 = 0;
const u32 retval = func(system, &param_1, Param(system, 1)).raw;
@@ -135,7 +127,7 @@ void SvcWrap64(Core::System& system) {
}
template <ResultCode func(Core::System&, u64*, u32, u32)>
void SvcWrap64(Core::System& system) {
void SvcWrap(Core::System& system) {
u64 param_1 = 0;
const u32 retval = func(system, &param_1, static_cast<u32>(Param(system, 1)),
static_cast<u32>(Param(system, 2)))
@@ -146,19 +138,19 @@ void SvcWrap64(Core::System& system) {
}
template <ResultCode func(Core::System&, u32, u64)>
void SvcWrap64(Core::System& system) {
void SvcWrap(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 SvcWrap64(Core::System& system) {
void SvcWrap(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 SvcWrap64(Core::System& system) {
void SvcWrap(Core::System& system) {
u32 param_1 = 0;
u64 param_2 = 0;
const ResultCode retval = func(system, static_cast<u32>(Param(system, 2)), &param_1, &param_2);
@@ -169,54 +161,54 @@ void SvcWrap64(Core::System& system) {
}
template <ResultCode func(Core::System&, u64, u64, u32, u32)>
void SvcWrap64(Core::System& system) {
void SvcWrap(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 SvcWrap64(Core::System& system) {
void SvcWrap(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 SvcWrap64(Core::System& system) {
void SvcWrap(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 SvcWrap64(Core::System& system) {
void SvcWrap(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 SvcWrap64(Core::System& system) {
void SvcWrap(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 SvcWrap64(Core::System& system) {
void SvcWrap(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 SvcWrap64(Core::System& system) {
void SvcWrap(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 SvcWrap64(Core::System& system) {
void SvcWrap(Core::System& system) {
u32 param_1 = 0;
const u32 retval = func(system, &param_1, Param(system, 1), static_cast<u32>(Param(system, 2)),
static_cast<s64>(Param(system, 3)))
@@ -227,14 +219,14 @@ void SvcWrap64(Core::System& system) {
}
template <ResultCode func(Core::System&, u64, u64, u32, s64)>
void SvcWrap64(Core::System& system) {
void SvcWrap(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 SvcWrap64(Core::System& system) {
void SvcWrap(Core::System& system) {
u64 param_1 = 0;
const u32 retval =
func(system, &param_1, Param(system, 1), Param(system, 2), Param(system, 3)).raw;
@@ -244,7 +236,7 @@ void SvcWrap64(Core::System& system) {
}
template <ResultCode func(Core::System&, u32*, u64, u64, u64, u32, s32)>
void SvcWrap64(Core::System& system) {
void SvcWrap(Core::System& system) {
u32 param_1 = 0;
const u32 retval = func(system, &param_1, Param(system, 1), Param(system, 2), Param(system, 3),
static_cast<u32>(Param(system, 4)), static_cast<s32>(Param(system, 5)))
@@ -255,7 +247,7 @@ void SvcWrap64(Core::System& system) {
}
template <ResultCode func(Core::System&, u32*, u64, u64, u32)>
void SvcWrap64(Core::System& system) {
void SvcWrap(Core::System& system) {
u32 param_1 = 0;
const u32 retval = func(system, &param_1, Param(system, 1), Param(system, 2),
static_cast<u32>(Param(system, 3)))
@@ -266,7 +258,7 @@ void SvcWrap64(Core::System& system) {
}
template <ResultCode func(Core::System&, Handle*, u64, u32, u32)>
void SvcWrap64(Core::System& system) {
void SvcWrap(Core::System& system) {
u32 param_1 = 0;
const u32 retval = func(system, &param_1, Param(system, 1), static_cast<u32>(Param(system, 2)),
static_cast<u32>(Param(system, 3)))
@@ -277,14 +269,14 @@ void SvcWrap64(Core::System& system) {
}
template <ResultCode func(Core::System&, u64, u32, s32, s64)>
void SvcWrap64(Core::System& system) {
void SvcWrap(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 SvcWrap64(Core::System& system) {
void SvcWrap(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);
@@ -294,7 +286,7 @@ void SvcWrap64(Core::System& system) {
// Function wrappers that return type u32
template <u32 func(Core::System&)>
void SvcWrap64(Core::System& system) {
void SvcWrap(Core::System& system) {
FuncReturn(system, func(system));
}
@@ -302,7 +294,7 @@ void SvcWrap64(Core::System& system) {
// Function wrappers that return type u64
template <u64 func(Core::System&)>
void SvcWrap64(Core::System& system) {
void SvcWrap(Core::System& system) {
FuncReturn(system, func(system));
}
@@ -310,110 +302,44 @@ void SvcWrap64(Core::System& system) {
/// Function wrappers that return type void
template <void func(Core::System&)>
void SvcWrap64(Core::System& system) {
void SvcWrap(Core::System& system) {
func(system);
}
template <void func(Core::System&, u32)>
void SvcWrap64(Core::System& system) {
void SvcWrap(Core::System& system) {
func(system, static_cast<u32>(Param(system, 0)));
}
template <void func(Core::System&, u32, u64, u64, u64)>
void SvcWrap64(Core::System& system) {
void SvcWrap(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 SvcWrap64(Core::System& system) {
void SvcWrap(Core::System& system) {
func(system, static_cast<s64>(Param(system, 0)));
}
template <void func(Core::System&, u64, s32)>
void SvcWrap64(Core::System& system) {
void SvcWrap(Core::System& system) {
func(system, Param(system, 0), static_cast<s32>(Param(system, 1)));
}
template <void func(Core::System&, u64, u64)>
void SvcWrap64(Core::System& system) {
void SvcWrap(Core::System& system) {
func(system, Param(system, 0), Param(system, 1));
}
template <void func(Core::System&, u64, u64, u64)>
void SvcWrap64(Core::System& system) {
void SvcWrap(Core::System& system) {
func(system, Param(system, 0), Param(system, 1), Param(system, 2));
}
template <void func(Core::System&, u32, u64, u64)>
void SvcWrap64(Core::System& system) {
void SvcWrap(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, &param_1, &param_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, &param_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, &param_1, &param_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), &param_1)
.raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
} // namespace Kernel
+14 -17
View File
@@ -133,16 +133,15 @@ void Thread::CancelWait() {
ResumeFromWait();
}
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) {
/**
* 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) {
context = {};
context.cpu_registers[0] = arg;
context.pc = entry_point;
@@ -199,9 +198,9 @@ ResultVal<std::shared_ptr<Thread>> Thread::Create(KernelCore& kernel, std::strin
thread->owner_process->RegisterThread(thread.get());
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);
// 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);
return MakeResult<std::shared_ptr<Thread>>(std::move(thread));
}
@@ -214,13 +213,11 @@ void Thread::SetPriority(u32 priority) {
}
void Thread::SetWaitSynchronizationResult(ResultCode result) {
context_32.cpu_registers[0] = result.raw;
context_64.cpu_registers[0] = result.raw;
context.cpu_registers[0] = result.raw;
}
void Thread::SetWaitSynchronizationOutput(s32 output) {
context_32.cpu_registers[1] = output;
context_64.cpu_registers[1] = output;
context.cpu_registers[1] = output;
}
s32 Thread::GetSynchronizationObjectIndex(std::shared_ptr<SynchronizationObject> object) const {
+6 -16
View File
@@ -102,8 +102,7 @@ public:
using MutexWaitingThreads = std::vector<std::shared_ptr<Thread>>;
using ThreadContext32 = Core::ARM_Interface::ThreadContext32;
using ThreadContext64 = Core::ARM_Interface::ThreadContext64;
using ThreadContext = Core::ARM_Interface::ThreadContext;
using ThreadSynchronizationObjects = std::vector<std::shared_ptr<SynchronizationObject>>;
@@ -274,20 +273,12 @@ public:
return status == ThreadStatus::WaitSynch;
}
ThreadContext32& GetContext32() {
return context_32;
ThreadContext& GetContext() {
return context;
}
const ThreadContext32& GetContext32() const {
return context_32;
}
ThreadContext64& GetContext64() {
return context_64;
}
const ThreadContext64& GetContext64() const {
return context_64;
const ThreadContext& GetContext() const {
return context;
}
ThreadStatus GetStatus() const {
@@ -475,8 +466,7 @@ private:
void AdjustSchedulingOnPriority(u32 old_priority);
void AdjustSchedulingOnAffinity(u64 old_affinity_mask, s32 old_core);
ThreadContext32 context_32{};
ThreadContext64 context_64{};
Core::ARM_Interface::ThreadContext context{};
u64 thread_id = 0;
+5 -52
View File
@@ -52,11 +52,6 @@ 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 {
@@ -610,11 +605,11 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system,
{30, nullptr, "GetHomeButtonReaderLockAccessor"},
{31, nullptr, "GetReaderLockAccessorEx"},
{40, nullptr, "GetCradleFwVersion"},
{50, &ICommonStateGetter::IsVrModeEnabled, "IsVrModeEnabled"},
{51, &ICommonStateGetter::SetVrModeEnabled, "SetVrModeEnabled"},
{52, &ICommonStateGetter::SetLcdBacklighOffEnabled, "SetLcdBacklighOffEnabled"},
{50, nullptr, "IsVrModeEnabled"},
{51, nullptr, "SetVrModeEnabled"},
{52, nullptr, "SwitchLcdBacklight"},
{53, nullptr, "BeginVrModeEx"},
{54, &ICommonStateGetter::EndVrModeEx, "EndVrModeEx"},
{54, nullptr, "EndVrModeEx"},
{55, nullptr, "IsInControllerFirmwareUpdateSection"},
{60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"},
{61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"},
@@ -641,6 +636,7 @@ void ICommonStateGetter::GetBootMode(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u8>(static_cast<u8>(Service::PM::SystemBootMode::Normal)); // Normal boot mode
}
@@ -664,7 +660,6 @@ void ICommonStateGetter::ReceiveMessage(Kernel::HLERequestContext& ctx) {
rb.PushEnum<AppletMessageQueue::AppletMessage>(message);
return;
}
rb.Push(RESULT_SUCCESS);
rb.PushEnum<AppletMessageQueue::AppletMessage>(message);
}
@@ -677,48 +672,6 @@ 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>();
LOG_WARNING(Service_AM, "(STUBBED) called. is_lcd_backlight_off_enabled={}",
is_lcd_backlight_off_enabled);
IPC::ResponseBuilder rb{ctx, 2};
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");
-4
View File
@@ -182,10 +182,6 @@ 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,12 +254,6 @@ 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;
}
+151 -7
View File
@@ -2,24 +2,168 @@
// 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
-71
View File
@@ -4,83 +4,12 @@
#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
View File
@@ -1,78 +0,0 @@
// 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
View File
@@ -1,21 +0,0 @@
// 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
View File
@@ -1,75 +0,0 @@
// 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
View File
@@ -1,21 +0,0 @@
// 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
View File
@@ -1,40 +0,0 @@
// 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
View File
@@ -1,21 +0,0 @@
// 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
View File
@@ -1,26 +0,0 @@
// 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
View File
@@ -1,21 +0,0 @@
// 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
View File
@@ -1,22 +0,0 @@
// 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
View File
@@ -1,21 +0,0 @@
// 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
View File
@@ -1,76 +0,0 @@
// 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
View File
@@ -1,24 +0,0 @@
// 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
+1 -8
View File
@@ -235,7 +235,7 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) {
{303, nullptr, "ActivateSevenSixAxisSensor"},
{304, nullptr, "StartSevenSixAxisSensor"},
{305, nullptr, "StopSevenSixAxisSensor"},
{306, &Hid::InitializeSevenSixAxisSensor, "InitializeSevenSixAxisSensor"},
{306, nullptr, "InitializeSevenSixAxisSensor"},
{307, nullptr, "FinalizeSevenSixAxisSensor"},
{308, nullptr, "SetSevenSixAxisSensorFusionStrength"},
{309, nullptr, "GetSevenSixAxisSensorFusionStrength"},
@@ -853,13 +853,6 @@ 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"} {
-1
View File
@@ -128,7 +128,6 @@ 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;
+5 -15
View File
@@ -342,27 +342,17 @@ public:
return;
}
// Mark text and read-only region as ModuleCode
ASSERT(vm_manager
.MirrorMemory(*map_address, nro_address, header.text_size + header.ro_size,
Kernel::MemoryState::ModuleCode)
.IsSuccess());
// Mark read/write region as ModuleCodeData, which is necessary if this region is used for
// TransferMemory (e.g. Final Fantasy VIII Remastered does this)
ASSERT(vm_manager
.MirrorMemory(*map_address + header.rw_offset, nro_address + header.rw_offset,
header.rw_size, Kernel::MemoryState::ModuleCodeData)
.IsSuccess());
// Revoke permissions from the old memory region
ASSERT(
vm_manager
.MirrorMemory(*map_address, nro_address, nro_size, Kernel::MemoryState::ModuleCode)
.IsSuccess());
ASSERT(vm_manager.ReprotectRange(nro_address, nro_size, Kernel::VMAPermission::None)
.IsSuccess());
if (bss_size > 0) {
// Mark BSS region as ModuleCodeData, which is necessary if this region is used for
// TransferMemory (e.g. Final Fantasy VIII Remastered does this)
ASSERT(vm_manager
.MirrorMemory(*map_address + nro_size, bss_address, bss_size,
Kernel::MemoryState::ModuleCodeData)
Kernel::MemoryState::ModuleCode)
.IsSuccess());
ASSERT(vm_manager.ReprotectRange(bss_address, bss_size, Kernel::VMAPermission::None)
.IsSuccess());
@@ -28,7 +28,6 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer)
buffer.slot = slot;
buffer.igbp_buffer = igbp_buffer;
buffer.status = Buffer::Status::Free;
free_buffers.push_back(slot);
queue.emplace_back(buffer);
buffer_wait_event.writable->Signal();
@@ -36,37 +35,16 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer)
std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::DequeueBuffer(u32 width,
u32 height) {
if (free_buffers.empty()) {
return {};
}
auto f_itr = free_buffers.begin();
auto itr = queue.end();
while (f_itr != free_buffers.end()) {
auto slot = *f_itr;
itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) {
// Only consider free buffers. Buffers become free once again after they've been
// Acquired and Released by the compositor, see the NVFlinger::Compose method.
if (buffer.status != Buffer::Status::Free) {
return false;
}
if (buffer.slot != slot) {
return false;
}
// Make sure that the parameters match.
return buffer.igbp_buffer.width == width && buffer.igbp_buffer.height == height;
});
if (itr != queue.end()) {
free_buffers.erase(f_itr);
break;
auto itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) {
// Only consider free buffers. Buffers become free once again after they've been Acquired
// and Released by the compositor, see the NVFlinger::Compose method.
if (buffer.status != Buffer::Status::Free) {
return false;
}
++f_itr;
}
// Make sure that the parameters match.
return buffer.igbp_buffer.width == width && buffer.igbp_buffer.height == height;
});
if (itr == queue.end()) {
return {};
@@ -121,18 +99,10 @@ void BufferQueue::ReleaseBuffer(u32 slot) {
ASSERT(itr != queue.end());
ASSERT(itr->status == Buffer::Status::Acquired);
itr->status = Buffer::Status::Free;
free_buffers.push_back(slot);
buffer_wait_event.writable->Signal();
}
void BufferQueue::Disconnect() {
queue.clear();
queue_sequence.clear();
id = 1;
layer_id = 1;
}
u32 BufferQueue::Query(QueryType type) {
LOG_WARNING(Service, "(STUBBED) called type={}", static_cast<u32>(type));
@@ -87,7 +87,6 @@ public:
Service::Nvidia::MultiFence& multi_fence);
std::optional<std::reference_wrapper<const Buffer>> AcquireBuffer();
void ReleaseBuffer(u32 slot);
void Disconnect();
u32 Query(QueryType type);
u32 GetId() const {
@@ -102,7 +101,6 @@ private:
u32 id;
u64 layer_id;
std::list<u32> free_buffers;
std::vector<Buffer> queue;
std::list<u32> queue_sequence;
Kernel::EventPair buffer_wait_event;
+2 -2
View File
@@ -191,6 +191,8 @@ void NVFlinger::Compose() {
// Search for a queued buffer and acquire it
auto buffer = buffer_queue.AcquireBuffer();
MicroProfileFlip();
if (!buffer) {
continue;
}
@@ -204,8 +206,6 @@ 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)
+1 -9
View File
@@ -111,14 +111,6 @@ 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[] = {
@@ -126,7 +118,7 @@ SET::SET() : ServiceFramework("set") {
{1, &SET::GetAvailableLanguageCodes, "GetAvailableLanguageCodes"},
{2, &SET::MakeLanguageCode, "MakeLanguageCode"},
{3, &SET::GetAvailableLanguageCodeCount, "GetAvailableLanguageCodeCount"},
{4, &SET::GetRegionCode, "GetRegionCode"},
{4, nullptr, "GetRegionCode"},
{5, &SET::GetAvailableLanguageCodes2, "GetAvailableLanguageCodes2"},
{6, &SET::GetAvailableLanguageCodeCount2, "GetAvailableLanguageCodeCount2"},
{7, nullptr, "GetKeyCodeMap"},
-1
View File
@@ -43,7 +43,6 @@ private:
void GetAvailableLanguageCodeCount(Kernel::HLERequestContext& ctx);
void GetAvailableLanguageCodeCount2(Kernel::HLERequestContext& ctx);
void GetQuestFlag(Kernel::HLERequestContext& ctx);
void GetRegionCode(Kernel::HLERequestContext& ctx);
};
} // namespace Service::Set
+1 -1
View File
@@ -44,7 +44,7 @@ void Controller::QueryPointerBufferSize(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u16>(0x1000);
rb.Push<u16>(0x500);
}
Controller::Controller() : ServiceFramework("IpcController") {
+1 -1
View File
@@ -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, &Time::CalculateSpanBetween, "CalculateSpanBetween"},
{501, nullptr, "CalculateSpanBetween"},
};
// clang-format on
-29
View File
@@ -308,35 +308,6 @@ 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};
-1
View File
@@ -32,7 +32,6 @@ 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() + 1);
std::vector<char> raw_data(binary_list->GetSize());
binary_list->ReadBytes<char>(raw_data.data(), binary_list->GetSize());
std::stringstream data_stream{raw_data.data()};
+10 -36
View File
@@ -513,8 +513,7 @@ private:
auto& buffer_queue = nv_flinger->FindBufferQueue(id);
switch (transaction) {
case TransactionId::Connect: {
if (transaction == TransactionId::Connect) {
IGBPConnectRequestParcel request{ctx.ReadBuffer()};
IGBPConnectResponseParcel response{
static_cast<u32>(static_cast<u32>(DisplayResolution::UndockedWidth) *
@@ -522,18 +521,14 @@ private:
static_cast<u32>(static_cast<u32>(DisplayResolution::UndockedHeight) *
Settings::values.resolution_factor)};
ctx.WriteBuffer(response.Serialize());
break;
}
case TransactionId::SetPreallocatedBuffer: {
} else if (transaction == TransactionId::SetPreallocatedBuffer) {
IGBPSetPreallocatedBufferRequestParcel request{ctx.ReadBuffer()};
buffer_queue.SetPreallocatedBuffer(request.data.slot, request.buffer);
IGBPSetPreallocatedBufferResponseParcel response{};
ctx.WriteBuffer(response.Serialize());
break;
}
case TransactionId::DequeueBuffer: {
} else if (transaction == TransactionId::DequeueBuffer) {
IGBPDequeueBufferRequestParcel request{ctx.ReadBuffer()};
const u32 width{request.data.width};
const u32 height{request.data.height};
@@ -561,18 +556,14 @@ private:
},
buffer_queue.GetWritableBufferWaitEvent());
}
break;
}
case TransactionId::RequestBuffer: {
} else if (transaction == TransactionId::RequestBuffer) {
IGBPRequestBufferRequestParcel request{ctx.ReadBuffer()};
auto& buffer = buffer_queue.RequestBuffer(request.slot);
IGBPRequestBufferResponseParcel response{buffer};
ctx.WriteBuffer(response.Serialize());
break;
}
case TransactionId::QueueBuffer: {
} else if (transaction == TransactionId::QueueBuffer) {
IGBPQueueBufferRequestParcel request{ctx.ReadBuffer()};
buffer_queue.QueueBuffer(request.data.slot, request.data.transform,
@@ -581,9 +572,7 @@ private:
IGBPQueueBufferResponseParcel response{1280, 720};
ctx.WriteBuffer(response.Serialize());
break;
}
case TransactionId::Query: {
} else if (transaction == TransactionId::Query) {
IGBPQueryRequestParcel request{ctx.ReadBuffer()};
const u32 value =
@@ -591,30 +580,15 @@ private:
IGBPQueryResponseParcel response{value};
ctx.WriteBuffer(response.Serialize());
break;
}
case TransactionId::CancelBuffer: {
} else if (transaction == TransactionId::CancelBuffer) {
LOG_CRITICAL(Service_VI, "(STUBBED) called, transaction=CancelBuffer");
break;
}
case TransactionId::Disconnect: {
LOG_WARNING(Service_VI, "(STUBBED) called, transaction=Disconnect");
const auto buffer = ctx.ReadBuffer();
buffer_queue.Disconnect();
IGBPEmptyResponseParcel response{};
ctx.WriteBuffer(response.Serialize());
break;
}
case TransactionId::DetachBuffer: {
} else if (transaction == TransactionId::Disconnect ||
transaction == TransactionId::DetachBuffer) {
const auto buffer = ctx.ReadBuffer();
IGBPEmptyResponseParcel response{};
ctx.WriteBuffer(response.Serialize());
break;
}
default:
} else {
ASSERT_MSG(false, "Unimplemented");
}
@@ -129,6 +129,12 @@ 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, {}};
}
+6 -121
View File
@@ -242,52 +242,7 @@ struct Memory::Impl {
}
case Common::PageType::RasterizerCachedMemory: {
const u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
system.GPU().FlushRegion(current_vaddr, copy_amount);
std::memcpy(dest_buffer, host_ptr, copy_amount);
break;
}
default:
UNREACHABLE();
}
page_index++;
page_offset = 0;
dest_buffer = static_cast<u8*>(dest_buffer) + copy_amount;
remaining_size -= copy_amount;
}
}
void ReadBlockUnsafe(const Kernel::Process& process, const VAddr src_addr, void* dest_buffer,
const std::size_t size) {
const auto& page_table = process.VMManager().page_table;
std::size_t remaining_size = size;
std::size_t page_index = src_addr >> PAGE_BITS;
std::size_t page_offset = src_addr & PAGE_MASK;
while (remaining_size > 0) {
const std::size_t copy_amount =
std::min(static_cast<std::size_t>(PAGE_SIZE) - page_offset, remaining_size);
const auto current_vaddr = static_cast<VAddr>((page_index << PAGE_BITS) + page_offset);
switch (page_table.attributes[page_index]) {
case Common::PageType::Unmapped: {
LOG_ERROR(HW_Memory,
"Unmapped ReadBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
current_vaddr, src_addr, size);
std::memset(dest_buffer, 0, copy_amount);
break;
}
case Common::PageType::Memory: {
DEBUG_ASSERT(page_table.pointers[page_index]);
const u8* const src_ptr =
page_table.pointers[page_index] + page_offset + (page_index << PAGE_BITS);
std::memcpy(dest_buffer, src_ptr, copy_amount);
break;
}
case Common::PageType::RasterizerCachedMemory: {
const u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
system.GPU().FlushRegion(ToCacheAddr(host_ptr), copy_amount);
std::memcpy(dest_buffer, host_ptr, copy_amount);
break;
}
@@ -306,10 +261,6 @@ struct Memory::Impl {
ReadBlock(*system.CurrentProcess(), src_addr, dest_buffer, size);
}
void ReadBlockUnsafe(const VAddr src_addr, void* dest_buffer, const std::size_t size) {
ReadBlockUnsafe(*system.CurrentProcess(), src_addr, dest_buffer, size);
}
void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const void* src_buffer,
const std::size_t size) {
const auto& page_table = process.VMManager().page_table;
@@ -339,50 +290,7 @@ struct Memory::Impl {
}
case Common::PageType::RasterizerCachedMemory: {
u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
system.GPU().InvalidateRegion(current_vaddr, copy_amount);
std::memcpy(host_ptr, src_buffer, copy_amount);
break;
}
default:
UNREACHABLE();
}
page_index++;
page_offset = 0;
src_buffer = static_cast<const u8*>(src_buffer) + copy_amount;
remaining_size -= copy_amount;
}
}
void WriteBlockUnsafe(const Kernel::Process& process, const VAddr dest_addr,
const void* src_buffer, const std::size_t size) {
const auto& page_table = process.VMManager().page_table;
std::size_t remaining_size = size;
std::size_t page_index = dest_addr >> PAGE_BITS;
std::size_t page_offset = dest_addr & PAGE_MASK;
while (remaining_size > 0) {
const std::size_t copy_amount =
std::min(static_cast<std::size_t>(PAGE_SIZE) - page_offset, remaining_size);
const auto current_vaddr = static_cast<VAddr>((page_index << PAGE_BITS) + page_offset);
switch (page_table.attributes[page_index]) {
case Common::PageType::Unmapped: {
LOG_ERROR(HW_Memory,
"Unmapped WriteBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
current_vaddr, dest_addr, size);
break;
}
case Common::PageType::Memory: {
DEBUG_ASSERT(page_table.pointers[page_index]);
u8* const dest_ptr =
page_table.pointers[page_index] + page_offset + (page_index << PAGE_BITS);
std::memcpy(dest_ptr, src_buffer, copy_amount);
break;
}
case Common::PageType::RasterizerCachedMemory: {
u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
system.GPU().InvalidateRegion(ToCacheAddr(host_ptr), copy_amount);
std::memcpy(host_ptr, src_buffer, copy_amount);
break;
}
@@ -401,10 +309,6 @@ struct Memory::Impl {
WriteBlock(*system.CurrentProcess(), dest_addr, src_buffer, size);
}
void WriteBlockUnsafe(const VAddr dest_addr, const void* src_buffer, const std::size_t size) {
WriteBlockUnsafe(*system.CurrentProcess(), dest_addr, src_buffer, size);
}
void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std::size_t size) {
const auto& page_table = process.VMManager().page_table;
std::size_t remaining_size = size;
@@ -433,7 +337,7 @@ struct Memory::Impl {
}
case Common::PageType::RasterizerCachedMemory: {
u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
system.GPU().InvalidateRegion(current_vaddr, copy_amount);
system.GPU().InvalidateRegion(ToCacheAddr(host_ptr), copy_amount);
std::memset(host_ptr, 0, copy_amount);
break;
}
@@ -480,7 +384,7 @@ struct Memory::Impl {
}
case Common::PageType::RasterizerCachedMemory: {
const u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
system.GPU().FlushRegion(current_vaddr, copy_amount);
system.GPU().FlushRegion(ToCacheAddr(host_ptr), copy_amount);
WriteBlock(process, dest_addr, host_ptr, copy_amount);
break;
}
@@ -641,7 +545,7 @@ struct Memory::Impl {
break;
case Common::PageType::RasterizerCachedMemory: {
const u8* const host_ptr = GetPointerFromVMA(vaddr);
system.GPU().FlushRegion(vaddr, sizeof(T));
system.GPU().FlushRegion(ToCacheAddr(host_ptr), sizeof(T));
T value;
std::memcpy(&value, host_ptr, sizeof(T));
return value;
@@ -683,7 +587,7 @@ struct Memory::Impl {
break;
case Common::PageType::RasterizerCachedMemory: {
u8* const host_ptr{GetPointerFromVMA(vaddr)};
system.GPU().InvalidateRegion(vaddr, sizeof(T));
system.GPU().InvalidateRegion(ToCacheAddr(host_ptr), sizeof(T));
std::memcpy(host_ptr, &data, sizeof(T));
break;
}
@@ -792,15 +696,6 @@ void Memory::ReadBlock(const VAddr src_addr, void* dest_buffer, const std::size_
impl->ReadBlock(src_addr, dest_buffer, size);
}
void Memory::ReadBlockUnsafe(const Kernel::Process& process, const VAddr src_addr,
void* dest_buffer, const std::size_t size) {
impl->ReadBlockUnsafe(process, src_addr, dest_buffer, size);
}
void Memory::ReadBlockUnsafe(const VAddr src_addr, void* dest_buffer, const std::size_t size) {
impl->ReadBlockUnsafe(src_addr, dest_buffer, size);
}
void Memory::WriteBlock(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer,
std::size_t size) {
impl->WriteBlock(process, dest_addr, src_buffer, size);
@@ -810,16 +705,6 @@ void Memory::WriteBlock(const VAddr dest_addr, const void* src_buffer, const std
impl->WriteBlock(dest_addr, src_buffer, size);
}
void Memory::WriteBlockUnsafe(const Kernel::Process& process, VAddr dest_addr,
const void* src_buffer, std::size_t size) {
impl->WriteBlockUnsafe(process, dest_addr, src_buffer, size);
}
void Memory::WriteBlockUnsafe(const VAddr dest_addr, const void* src_buffer,
const std::size_t size) {
impl->WriteBlockUnsafe(dest_addr, src_buffer, size);
}
void Memory::ZeroBlock(const Kernel::Process& process, VAddr dest_addr, std::size_t size) {
impl->ZeroBlock(process, dest_addr, size);
}
-78
View File
@@ -294,27 +294,6 @@ public:
void ReadBlock(const Kernel::Process& process, VAddr src_addr, void* dest_buffer,
std::size_t size);
/**
* Reads a contiguous block of bytes from a specified process' address space.
* This unsafe version does not trigger GPU flushing.
*
* @param process The process to read the data from.
* @param src_addr The virtual address to begin reading from.
* @param dest_buffer The buffer to place the read bytes into.
* @param size The amount of data to read, in bytes.
*
* @note If a size of 0 is specified, then this function reads nothing and
* no attempts to access memory are made at all.
*
* @pre dest_buffer must be at least size bytes in length, otherwise a
* buffer overrun will occur.
*
* @post The range [dest_buffer, size) contains the read bytes from the
* process' address space.
*/
void ReadBlockUnsafe(const Kernel::Process& process, VAddr src_addr, void* dest_buffer,
std::size_t size);
/**
* Reads a contiguous block of bytes from the current process' address space.
*
@@ -333,25 +312,6 @@ public:
*/
void ReadBlock(VAddr src_addr, void* dest_buffer, std::size_t size);
/**
* Reads a contiguous block of bytes from the current process' address space.
* This unsafe version does not trigger GPU flushing.
*
* @param src_addr The virtual address to begin reading from.
* @param dest_buffer The buffer to place the read bytes into.
* @param size The amount of data to read, in bytes.
*
* @note If a size of 0 is specified, then this function reads nothing and
* no attempts to access memory are made at all.
*
* @pre dest_buffer must be at least size bytes in length, otherwise a
* buffer overrun will occur.
*
* @post The range [dest_buffer, size) contains the read bytes from the
* current process' address space.
*/
void ReadBlockUnsafe(VAddr src_addr, void* dest_buffer, std::size_t size);
/**
* Writes a range of bytes into a given process' address space at the specified
* virtual address.
@@ -375,26 +335,6 @@ public:
void WriteBlock(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer,
std::size_t size);
/**
* Writes a range of bytes into a given process' address space at the specified
* virtual address.
* This unsafe version does not invalidate GPU Memory.
*
* @param process The process to write data into the address space of.
* @param dest_addr The destination virtual address to begin writing the data at.
* @param src_buffer The data to write into the process' address space.
* @param size The size of the data to write, in bytes.
*
* @post The address range [dest_addr, size) in the process' address space
* contains the data that was within src_buffer.
*
* @post If an attempt is made to write into an unmapped region of memory, the writes
* will be ignored and an error will be logged.
*
*/
void WriteBlockUnsafe(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer,
std::size_t size);
/**
* Writes a range of bytes into the current process' address space at the specified
* virtual address.
@@ -416,24 +356,6 @@ public:
*/
void WriteBlock(VAddr dest_addr, const void* src_buffer, std::size_t size);
/**
* Writes a range of bytes into the current process' address space at the specified
* virtual address.
* This unsafe version does not invalidate GPU Memory.
*
* @param dest_addr The destination virtual address to begin writing the data at.
* @param src_buffer The data to write into the current process' address space.
* @param size The size of the data to write, in bytes.
*
* @post The address range [dest_addr, size) in the current process' address space
* contains the data that was within src_buffer.
*
* @post If an attempt is made to write into an unmapped region of memory, the writes
* will be ignored and an error will be logged.
*
*/
void WriteBlockUnsafe(VAddr dest_addr, const void* src_buffer, std::size_t size);
/**
* Fills the specified address range within a process' address space with zeroes.
*
+1 -1
View File
@@ -111,7 +111,7 @@ json GetProcessorStateDataAuto(Core::System& system) {
const auto& vm_manager{process->VMManager()};
auto& arm{system.CurrentArmInterface()};
Core::ARM_Interface::ThreadContext64 context{};
Core::ARM_Interface::ThreadContext context{};
arm.SaveContext(context);
return GetProcessorStateData(process->Is64BitProcess() ? "AArch64" : "AArch32",
-2
View File
@@ -86,7 +86,6 @@ 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);
@@ -95,7 +94,6 @@ void LogSettings() {
LogSetting("Renderer_UseAccurateGpuEmulation", Settings::values.use_accurate_gpu_emulation);
LogSetting("Renderer_UseAsynchronousGpuEmulation",
Settings::values.use_asynchronous_gpu_emulation);
LogSetting("Renderer_UseVsync", Settings::values.use_vsync);
LogSetting("Audio_OutputEngine", Settings::values.sink_id);
LogSetting("Audio_EnableAudioStretching", Settings::values.enable_audio_stretching);
LogSetting("Audio_OutputDevice", Settings::values.audio_device_id);
-4
View File
@@ -387,8 +387,6 @@ struct Values {
s32 current_user;
s32 language_index;
s32 region_index;
s32 sound_index;
// Controls
std::array<PlayerInput, 10> players;
@@ -432,13 +430,11 @@ struct Values {
float resolution_factor;
int aspect_ratio;
int max_anisotropy;
bool use_frame_limit;
u16 frame_limit;
bool use_disk_shader_cache;
bool use_accurate_gpu_emulation;
bool use_asynchronous_gpu_emulation;
bool use_vsync;
bool force_30fps_mode;
float bg_red;
-1
View File
@@ -188,7 +188,6 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) {
Settings::values.use_accurate_gpu_emulation);
AddField(field_type, "Renderer_UseAsynchronousGpuEmulation",
Settings::values.use_asynchronous_gpu_emulation);
AddField(field_type, "Renderer_UseVsync", Settings::values.use_vsync);
AddField(field_type, "System_UseDockedMode", Settings::values.use_docked_mode);
}
+4 -13
View File
@@ -32,16 +32,8 @@ 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) {
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)};
}
pad_index(pad_index),
send_endpoint(udp::endpoint(boost::asio::ip::make_address_v4(host), port)) {}
void Stop() {
io_service.stop();
@@ -93,18 +85,17 @@ 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, {}, _ignored);
socket.send_to(boost::asio::buffer(send_buffer1), send_endpoint);
// 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, {}, _ignored);
socket.send_to(boost::asio::buffer(send_buffer2), send_endpoint);
StartSend(timer.expiry());
}
+1
View File
@@ -31,6 +31,7 @@ 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{};
+1 -2
View File
@@ -3,7 +3,6 @@
// Refer to the license.txt file included.
#include <mutex>
#include <optional>
#include <tuple>
#include "common/param_package.h"
@@ -45,7 +44,7 @@ public:
std::unique_ptr<Input::TouchDevice> Create(const Common::ParamPackage& params) override {
{
std::lock_guard guard(status->update_mutex);
status->touch_calibration = DeviceStatus::CalibrationData{};
status->touch_calibration.emplace();
// 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);
+10 -29
View File
@@ -2,8 +2,6 @@ add_library(video_core STATIC
buffer_cache/buffer_block.h
buffer_cache/buffer_cache.h
buffer_cache/map_interval.h
dirty_flags.cpp
dirty_flags.h
dma_pusher.cpp
dma_pusher.h
engines/const_buffer_engine_interface.h
@@ -65,12 +63,14 @@ 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
renderer_opengl/gl_shader_util.h
renderer_opengl/gl_state_tracker.cpp
renderer_opengl/gl_state_tracker.h
renderer_opengl/gl_state.cpp
renderer_opengl/gl_state.h
renderer_opengl/gl_stream_buffer.cpp
renderer_opengl/gl_stream_buffer.h
renderer_opengl/gl_texture_cache.cpp
@@ -116,6 +116,8 @@ 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
@@ -124,13 +126,9 @@ 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
@@ -148,7 +146,6 @@ add_library(video_core STATIC
textures/convert.h
textures/decoders.cpp
textures/decoders.h
textures/texture.cpp
textures/texture.h
video_core.cpp
video_core.h
@@ -156,12 +153,11 @@ add_library(video_core STATIC
if (ENABLE_VULKAN)
target_sources(video_core PRIVATE
renderer_vulkan/declarations.h
renderer_vulkan/fixed_pipeline_state.cpp
renderer_vulkan/fixed_pipeline_state.h
renderer_vulkan/maxwell_to_vk.cpp
renderer_vulkan/maxwell_to_vk.h
renderer_vulkan/nsight_aftermath_tracker.cpp
renderer_vulkan/nsight_aftermath_tracker.h
renderer_vulkan/renderer_vulkan.h
renderer_vulkan/renderer_vulkan.cpp
renderer_vulkan/vk_blit_screen.cpp
@@ -202,8 +198,6 @@ if (ENABLE_VULKAN)
renderer_vulkan/vk_shader_util.h
renderer_vulkan/vk_staging_buffer_pool.cpp
renderer_vulkan/vk_staging_buffer_pool.h
renderer_vulkan/vk_state_tracker.cpp
renderer_vulkan/vk_state_tracker.h
renderer_vulkan/vk_stream_buffer.cpp
renderer_vulkan/vk_stream_buffer.h
renderer_vulkan/vk_swapchain.cpp
@@ -212,33 +206,20 @@ 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)
target_compile_definitions(video_core PRIVATE HAS_VULKAN)
endif()
create_target_directory_groups(video_core)
target_link_libraries(video_core PUBLIC common core)
target_link_libraries(video_core PRIVATE glad)
if (ENABLE_VULKAN)
target_include_directories(video_core PRIVATE sirit ../../externals/Vulkan-Headers/include)
target_compile_definitions(video_core PRIVATE HAS_VULKAN)
target_link_libraries(video_core PRIVATE sirit)
endif()
if (ENABLE_NSIGHT_AFTERMATH)
if (NOT DEFINED ENV{NSIGHT_AFTERMATH_SDK})
message(ERROR "Environment variable NSIGHT_AFTERMATH_SDK has to be provided")
endif()
if (NOT WIN32)
message(ERROR "Nsight Aftermath doesn't support non-Windows platforms")
endif()
target_compile_definitions(video_core PRIVATE HAS_NSIGHT_AFTERMATH)
target_include_directories(video_core PRIVATE "$ENV{NSIGHT_AFTERMATH_SDK}/include")
endif()
if (MSVC)
target_compile_options(video_core PRIVATE /we4267)
else()
+25 -17
View File
@@ -15,29 +15,37 @@ namespace VideoCommon {
class BufferBlock {
public:
bool Overlaps(const VAddr start, const VAddr end) const {
return (cpu_addr < end) && (cpu_addr_end > start);
bool Overlaps(const CacheAddr start, const CacheAddr end) const {
return (cache_addr < end) && (cache_addr_end > start);
}
bool IsInside(const VAddr other_start, const VAddr other_end) const {
return cpu_addr <= other_start && other_end <= cpu_addr_end;
bool IsInside(const CacheAddr other_start, const CacheAddr other_end) const {
return cache_addr <= other_start && other_end <= cache_addr_end;
}
std::size_t GetOffset(const VAddr in_addr) {
return static_cast<std::size_t>(in_addr - cpu_addr);
u8* GetWritableHostPtr() const {
return FromCacheAddr(cache_addr);
}
VAddr GetCpuAddr() const {
return cpu_addr;
u8* GetWritableHostPtr(std::size_t offset) const {
return FromCacheAddr(cache_addr + offset);
}
VAddr GetCpuAddrEnd() const {
return cpu_addr_end;
std::size_t GetOffset(const CacheAddr in_addr) {
return static_cast<std::size_t>(in_addr - cache_addr);
}
void SetCpuAddr(const VAddr new_addr) {
cpu_addr = new_addr;
cpu_addr_end = new_addr + size;
CacheAddr GetCacheAddr() const {
return cache_addr;
}
CacheAddr GetCacheAddrEnd() const {
return cache_addr_end;
}
void SetCacheAddr(const CacheAddr new_addr) {
cache_addr = new_addr;
cache_addr_end = new_addr + size;
}
std::size_t GetSize() const {
@@ -53,14 +61,14 @@ public:
}
protected:
explicit BufferBlock(VAddr cpu_addr, const std::size_t size) : size{size} {
SetCpuAddr(cpu_addr);
explicit BufferBlock(CacheAddr cache_addr, const std::size_t size) : size{size} {
SetCacheAddr(cache_addr);
}
~BufferBlock() = default;
private:
VAddr cpu_addr{};
VAddr cpu_addr_end{};
CacheAddr cache_addr{};
CacheAddr cache_addr_end{};
std::size_t size{};
u64 epoch{};
};
+59 -86
View File
@@ -19,7 +19,6 @@
#include "common/alignment.h"
#include "common/common_types.h"
#include "core/core.h"
#include "core/memory.h"
#include "video_core/buffer_cache/buffer_block.h"
#include "video_core/buffer_cache/map_interval.h"
#include "video_core/memory_manager.h"
@@ -38,45 +37,28 @@ public:
bool is_written = false, bool use_fast_cbuf = false) {
std::lock_guard lock{mutex};
const std::optional<VAddr> cpu_addr_opt =
system.GPU().MemoryManager().GpuToCpuAddress(gpu_addr);
if (!cpu_addr_opt) {
auto& memory_manager = system.GPU().MemoryManager();
const auto host_ptr = memory_manager.GetPointer(gpu_addr);
if (!host_ptr) {
return {GetEmptyBuffer(size), 0};
}
VAddr cpu_addr = *cpu_addr_opt;
const auto cache_addr = ToCacheAddr(host_ptr);
// Cache management is a big overhead, so only cache entries with a given size.
// TODO: Figure out which size is the best for given games.
constexpr std::size_t max_stream_size = 0x800;
if (use_fast_cbuf || size < max_stream_size) {
if (!is_written && !IsRegionWritten(cpu_addr, cpu_addr + size - 1)) {
auto& memory_manager = system.GPU().MemoryManager();
if (!is_written && !IsRegionWritten(cache_addr, cache_addr + size - 1)) {
if (use_fast_cbuf) {
if (memory_manager.IsGranularRange(gpu_addr, size)) {
const auto host_ptr = memory_manager.GetPointer(gpu_addr);
return ConstBufferUpload(host_ptr, size);
} else {
staging_buffer.resize(size);
memory_manager.ReadBlockUnsafe(gpu_addr, staging_buffer.data(), size);
return ConstBufferUpload(staging_buffer.data(), size);
}
return ConstBufferUpload(host_ptr, size);
} else {
if (memory_manager.IsGranularRange(gpu_addr, size)) {
const auto host_ptr = memory_manager.GetPointer(gpu_addr);
return StreamBufferUpload(host_ptr, size, alignment);
} else {
staging_buffer.resize(size);
memory_manager.ReadBlockUnsafe(gpu_addr, staging_buffer.data(), size);
return StreamBufferUpload(staging_buffer.data(), size, alignment);
}
return StreamBufferUpload(host_ptr, size, alignment);
}
}
}
auto block = GetBlock(cpu_addr, size);
auto map = MapAddress(block, gpu_addr, cpu_addr, size);
auto block = GetBlock(cache_addr, size);
auto map = MapAddress(block, gpu_addr, cache_addr, size);
if (is_written) {
map->MarkAsModified(true, GetModifiedTicks());
if (!map->IsWritten()) {
@@ -89,7 +71,7 @@ public:
}
}
const u64 offset = static_cast<u64>(block->GetOffset(cpu_addr));
const u64 offset = static_cast<u64>(block->GetOffset(cache_addr));
return {ToHandle(block), offset};
}
@@ -130,7 +112,7 @@ public:
}
/// Write any cached resources overlapping the specified region back to memory
void FlushRegion(VAddr addr, std::size_t size) {
void FlushRegion(CacheAddr addr, std::size_t size) {
std::lock_guard lock{mutex};
std::vector<MapInterval> objects = GetMapsInRange(addr, size);
@@ -145,7 +127,7 @@ public:
}
/// Mark the specified region as being invalidated
void InvalidateRegion(VAddr addr, u64 size) {
void InvalidateRegion(CacheAddr addr, u64 size) {
std::lock_guard lock{mutex};
std::vector<MapInterval> objects = GetMapsInRange(addr, size);
@@ -170,7 +152,7 @@ protected:
virtual void WriteBarrier() = 0;
virtual TBuffer CreateBlock(VAddr cpu_addr, std::size_t size) = 0;
virtual TBuffer CreateBlock(CacheAddr cache_addr, std::size_t size) = 0;
virtual void UploadBlockData(const TBuffer& buffer, std::size_t offset, std::size_t size,
const u8* data) = 0;
@@ -187,17 +169,20 @@ protected:
/// Register an object into the cache
void Register(const MapInterval& new_map, bool inherit_written = false) {
const VAddr cpu_addr = new_map->GetStart();
if (!cpu_addr) {
const CacheAddr cache_ptr = new_map->GetStart();
const std::optional<VAddr> cpu_addr =
system.GPU().MemoryManager().GpuToCpuAddress(new_map->GetGpuAddress());
if (!cache_ptr || !cpu_addr) {
LOG_CRITICAL(HW_GPU, "Failed to register buffer with unmapped gpu_address 0x{:016x}",
new_map->GetGpuAddress());
return;
}
const std::size_t size = new_map->GetEnd() - new_map->GetStart();
new_map->SetCpuAddress(*cpu_addr);
new_map->MarkAsRegistered(true);
const IntervalType interval{new_map->GetStart(), new_map->GetEnd()};
mapped_addresses.insert({interval, new_map});
rasterizer.UpdatePagesCachedCount(cpu_addr, size, 1);
rasterizer.UpdatePagesCachedCount(*cpu_addr, size, 1);
if (inherit_written) {
MarkRegionAsWritten(new_map->GetStart(), new_map->GetEnd() - 1);
new_map->MarkAsWritten(true);
@@ -207,7 +192,7 @@ protected:
/// Unregisters an object from the cache
void Unregister(MapInterval& map) {
const std::size_t size = map->GetEnd() - map->GetStart();
rasterizer.UpdatePagesCachedCount(map->GetStart(), size, -1);
rasterizer.UpdatePagesCachedCount(map->GetCpuAddress(), size, -1);
map->MarkAsRegistered(false);
if (map->IsWritten()) {
UnmarkRegionAsWritten(map->GetStart(), map->GetEnd() - 1);
@@ -217,39 +202,32 @@ protected:
}
private:
MapInterval CreateMap(const VAddr start, const VAddr end, const GPUVAddr gpu_addr) {
MapInterval CreateMap(const CacheAddr start, const CacheAddr end, const GPUVAddr gpu_addr) {
return std::make_shared<MapIntervalBase>(start, end, gpu_addr);
}
MapInterval MapAddress(const TBuffer& block, const GPUVAddr gpu_addr, const VAddr cpu_addr,
const std::size_t size) {
MapInterval MapAddress(const TBuffer& block, const GPUVAddr gpu_addr,
const CacheAddr cache_addr, const std::size_t size) {
std::vector<MapInterval> overlaps = GetMapsInRange(cpu_addr, size);
std::vector<MapInterval> overlaps = GetMapsInRange(cache_addr, size);
if (overlaps.empty()) {
auto& memory_manager = system.GPU().MemoryManager();
const VAddr cpu_addr_end = cpu_addr + size;
MapInterval new_map = CreateMap(cpu_addr, cpu_addr_end, gpu_addr);
if (memory_manager.IsGranularRange(gpu_addr, size)) {
u8* host_ptr = memory_manager.GetPointer(gpu_addr);
UploadBlockData(block, block->GetOffset(cpu_addr), size, host_ptr);
} else {
staging_buffer.resize(size);
memory_manager.ReadBlockUnsafe(gpu_addr, staging_buffer.data(), size);
UploadBlockData(block, block->GetOffset(cpu_addr), size, staging_buffer.data());
}
const CacheAddr cache_addr_end = cache_addr + size;
MapInterval new_map = CreateMap(cache_addr, cache_addr_end, gpu_addr);
u8* host_ptr = FromCacheAddr(cache_addr);
UploadBlockData(block, block->GetOffset(cache_addr), size, host_ptr);
Register(new_map);
return new_map;
}
const VAddr cpu_addr_end = cpu_addr + size;
const CacheAddr cache_addr_end = cache_addr + size;
if (overlaps.size() == 1) {
MapInterval& current_map = overlaps[0];
if (current_map->IsInside(cpu_addr, cpu_addr_end)) {
if (current_map->IsInside(cache_addr, cache_addr_end)) {
return current_map;
}
}
VAddr new_start = cpu_addr;
VAddr new_end = cpu_addr_end;
CacheAddr new_start = cache_addr;
CacheAddr new_end = cache_addr_end;
bool write_inheritance = false;
bool modified_inheritance = false;
// Calculate new buffer parameters
@@ -259,7 +237,7 @@ private:
write_inheritance |= overlap->IsWritten();
modified_inheritance |= overlap->IsModified();
}
GPUVAddr new_gpu_addr = gpu_addr + new_start - cpu_addr;
GPUVAddr new_gpu_addr = gpu_addr + new_start - cache_addr;
for (auto& overlap : overlaps) {
Unregister(overlap);
}
@@ -272,7 +250,7 @@ private:
return new_map;
}
void UpdateBlock(const TBuffer& block, VAddr start, VAddr end,
void UpdateBlock(const TBuffer& block, CacheAddr start, CacheAddr end,
std::vector<MapInterval>& overlaps) {
const IntervalType base_interval{start, end};
IntervalSet interval_set{};
@@ -284,15 +262,13 @@ private:
for (auto& interval : interval_set) {
std::size_t size = interval.upper() - interval.lower();
if (size > 0) {
staging_buffer.resize(size);
system.Memory().ReadBlockUnsafe(interval.lower(), staging_buffer.data(), size);
UploadBlockData(block, block->GetOffset(interval.lower()), size,
staging_buffer.data());
u8* host_ptr = FromCacheAddr(interval.lower());
UploadBlockData(block, block->GetOffset(interval.lower()), size, host_ptr);
}
}
}
std::vector<MapInterval> GetMapsInRange(VAddr addr, std::size_t size) {
std::vector<MapInterval> GetMapsInRange(CacheAddr addr, std::size_t size) {
if (size == 0) {
return {};
}
@@ -314,9 +290,8 @@ private:
void FlushMap(MapInterval map) {
std::size_t size = map->GetEnd() - map->GetStart();
TBuffer block = blocks[map->GetStart() >> block_page_bits];
staging_buffer.resize(size);
DownloadBlockData(block, block->GetOffset(map->GetStart()), size, staging_buffer.data());
system.Memory().WriteBlockUnsafe(map->GetStart(), staging_buffer.data(), size);
u8* host_ptr = FromCacheAddr(map->GetStart());
DownloadBlockData(block, block->GetOffset(map->GetStart()), size, host_ptr);
map->MarkAsModified(false, 0);
}
@@ -341,14 +316,14 @@ private:
TBuffer EnlargeBlock(TBuffer buffer) {
const std::size_t old_size = buffer->GetSize();
const std::size_t new_size = old_size + block_page_size;
const VAddr cpu_addr = buffer->GetCpuAddr();
TBuffer new_buffer = CreateBlock(cpu_addr, new_size);
const CacheAddr cache_addr = buffer->GetCacheAddr();
TBuffer new_buffer = CreateBlock(cache_addr, new_size);
CopyBlock(buffer, new_buffer, 0, 0, old_size);
buffer->SetEpoch(epoch);
pending_destruction.push_back(buffer);
const VAddr cpu_addr_end = cpu_addr + new_size - 1;
u64 page_start = cpu_addr >> block_page_bits;
const u64 page_end = cpu_addr_end >> block_page_bits;
const CacheAddr cache_addr_end = cache_addr + new_size - 1;
u64 page_start = cache_addr >> block_page_bits;
const u64 page_end = cache_addr_end >> block_page_bits;
while (page_start <= page_end) {
blocks[page_start] = new_buffer;
++page_start;
@@ -359,9 +334,9 @@ private:
TBuffer MergeBlocks(TBuffer first, TBuffer second) {
const std::size_t size_1 = first->GetSize();
const std::size_t size_2 = second->GetSize();
const VAddr first_addr = first->GetCpuAddr();
const VAddr second_addr = second->GetCpuAddr();
const VAddr new_addr = std::min(first_addr, second_addr);
const CacheAddr first_addr = first->GetCacheAddr();
const CacheAddr second_addr = second->GetCacheAddr();
const CacheAddr new_addr = std::min(first_addr, second_addr);
const std::size_t new_size = size_1 + size_2;
TBuffer new_buffer = CreateBlock(new_addr, new_size);
CopyBlock(first, new_buffer, 0, new_buffer->GetOffset(first_addr), size_1);
@@ -370,9 +345,9 @@ private:
second->SetEpoch(epoch);
pending_destruction.push_back(first);
pending_destruction.push_back(second);
const VAddr cpu_addr_end = new_addr + new_size - 1;
const CacheAddr cache_addr_end = new_addr + new_size - 1;
u64 page_start = new_addr >> block_page_bits;
const u64 page_end = cpu_addr_end >> block_page_bits;
const u64 page_end = cache_addr_end >> block_page_bits;
while (page_start <= page_end) {
blocks[page_start] = new_buffer;
++page_start;
@@ -380,18 +355,18 @@ private:
return new_buffer;
}
TBuffer GetBlock(const VAddr cpu_addr, const std::size_t size) {
TBuffer GetBlock(const CacheAddr cache_addr, const std::size_t size) {
TBuffer found{};
const VAddr cpu_addr_end = cpu_addr + size - 1;
u64 page_start = cpu_addr >> block_page_bits;
const u64 page_end = cpu_addr_end >> block_page_bits;
const CacheAddr cache_addr_end = cache_addr + size - 1;
u64 page_start = cache_addr >> block_page_bits;
const u64 page_end = cache_addr_end >> block_page_bits;
while (page_start <= page_end) {
auto it = blocks.find(page_start);
if (it == blocks.end()) {
if (found) {
found = EnlargeBlock(found);
} else {
const VAddr start_addr = (page_start << block_page_bits);
const CacheAddr start_addr = (page_start << block_page_bits);
found = CreateBlock(start_addr, block_page_size);
blocks[page_start] = found;
}
@@ -411,7 +386,7 @@ private:
return found;
}
void MarkRegionAsWritten(const VAddr start, const VAddr end) {
void MarkRegionAsWritten(const CacheAddr start, const CacheAddr end) {
u64 page_start = start >> write_page_bit;
const u64 page_end = end >> write_page_bit;
while (page_start <= page_end) {
@@ -425,7 +400,7 @@ private:
}
}
void UnmarkRegionAsWritten(const VAddr start, const VAddr end) {
void UnmarkRegionAsWritten(const CacheAddr start, const CacheAddr end) {
u64 page_start = start >> write_page_bit;
const u64 page_end = end >> write_page_bit;
while (page_start <= page_end) {
@@ -441,7 +416,7 @@ private:
}
}
bool IsRegionWritten(const VAddr start, const VAddr end) const {
bool IsRegionWritten(const CacheAddr start, const CacheAddr end) const {
u64 page_start = start >> write_page_bit;
const u64 page_end = end >> write_page_bit;
while (page_start <= page_end) {
@@ -465,8 +440,8 @@ private:
u64 buffer_offset = 0;
u64 buffer_offset_base = 0;
using IntervalSet = boost::icl::interval_set<VAddr>;
using IntervalCache = boost::icl::interval_map<VAddr, MapInterval>;
using IntervalSet = boost::icl::interval_set<CacheAddr>;
using IntervalCache = boost::icl::interval_map<CacheAddr, MapInterval>;
using IntervalType = typename IntervalCache::interval_type;
IntervalCache mapped_addresses;
@@ -481,8 +456,6 @@ private:
u64 epoch = 0;
u64 modified_ticks = 0;
std::vector<u8> staging_buffer;
std::recursive_mutex mutex;
};

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