Compare commits
71 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
85ed42a1d2 | ||
|
|
1e4935c3a0 | ||
|
|
d3fd0351a7 | ||
|
|
3c1cb3b11e | ||
|
|
657bd113e3 | ||
|
|
52cb5dcf0f | ||
|
|
5c42cadbc9 | ||
|
|
f445464baf | ||
|
|
ee8123bf13 | ||
|
|
0686183c3e | ||
|
|
af787744ab | ||
|
|
704824d50a | ||
|
|
184324c2f0 | ||
|
|
abc5b3347d | ||
|
|
a6ea6febc9 | ||
|
|
e0106a7d68 | ||
|
|
daf2504d31 | ||
|
|
f747a7e35d | ||
|
|
4f574201ea | ||
|
|
340771ccd7 | ||
|
|
5d4ad999cf | ||
|
|
ea0bc8c002 | ||
|
|
933c9ee853 | ||
|
|
8f2c4191ab | ||
|
|
4cc1e180ec | ||
|
|
0162f8b3a7 | ||
|
|
16139ed53b | ||
|
|
b5eb3905cd | ||
|
|
4cf2185e81 | ||
|
|
07c2d057bd | ||
|
|
9539a1eadd | ||
|
|
77daef44b0 | ||
|
|
c73410bf2c | ||
|
|
8e8e906432 | ||
|
|
316c994f55 | ||
|
|
23e85b6b9f | ||
|
|
1cbf7ac6ea | ||
|
|
0f830d08f1 | ||
|
|
d092ea0870 | ||
|
|
b70f757913 | ||
|
|
54af9c206a | ||
|
|
a61124a9e7 | ||
|
|
44646e2ea0 | ||
|
|
b8459d2778 | ||
|
|
9d2cacdc9e | ||
|
|
63c605c04a | ||
|
|
76f191ce36 | ||
|
|
2f029577c7 | ||
|
|
bc5b65a1b0 | ||
|
|
69c45ce71c | ||
|
|
6b3e54621f | ||
|
|
ccc42702b5 | ||
|
|
7d124ec82b | ||
|
|
1d755abce4 | ||
|
|
1ff3bea6c7 | ||
|
|
2ff86f5765 | ||
|
|
92304181d5 | ||
|
|
8b83adfed6 | ||
|
|
47ac369180 | ||
|
|
c2b4ff5d48 | ||
|
|
59cb258409 | ||
|
|
22fd3f0026 | ||
|
|
33e2033af5 | ||
|
|
2a1daf8f83 | ||
|
|
a27c0099ed | ||
|
|
3a19c1098d | ||
|
|
bcc184acfa | ||
|
|
89db8c2171 | ||
|
|
c4322ce87e | ||
|
|
81aa02424b | ||
|
|
db48ebb9c9 |
2
externals/dynarmic
vendored
2
externals/dynarmic
vendored
Submodule externals/dynarmic updated: fc6b73bd85...98e2380129
@@ -826,7 +826,7 @@ std::string_view GetPathWithoutTop(std::string_view path) {
|
||||
}
|
||||
|
||||
while (path[0] == '\\' || path[0] == '/') {
|
||||
path.remove_suffix(1);
|
||||
path.remove_prefix(1);
|
||||
if (path.empty()) {
|
||||
return path;
|
||||
}
|
||||
@@ -870,6 +870,15 @@ std::string_view RemoveTrailingSlash(std::string_view path) {
|
||||
return path;
|
||||
}
|
||||
|
||||
std::string SanitizePath(std::string_view path_) {
|
||||
std::string path(path_);
|
||||
std::replace(path.begin(), path.end(), '\\', '/');
|
||||
path.erase(std::unique(path.begin(), path.end(),
|
||||
[](char c1, char c2) { return c1 == '/' && c2 == '/'; }),
|
||||
path.end());
|
||||
return std::string(RemoveTrailingSlash(path));
|
||||
}
|
||||
|
||||
IOFile::IOFile() {}
|
||||
|
||||
IOFile::IOFile(const std::string& filename, const char openmode[], int flags) {
|
||||
|
||||
@@ -178,6 +178,9 @@ std::vector<T> SliceVector(const std::vector<T>& vector, size_t first, size_t la
|
||||
return std::vector<T>(vector.begin() + first, vector.begin() + first + last);
|
||||
}
|
||||
|
||||
// Removes trailing slash, makes all '\\' into '/', and removes duplicate '/'.
|
||||
std::string SanitizePath(std::string_view path);
|
||||
|
||||
// simple wrapper for cstdlib file functions to
|
||||
// hopefully will make error checking easier
|
||||
// and make forgetting an fclose() harder
|
||||
|
||||
@@ -10,6 +10,8 @@ add_library(core STATIC
|
||||
core_cpu.h
|
||||
core_timing.cpp
|
||||
core_timing.h
|
||||
core_timing_util.cpp
|
||||
core_timing_util.h
|
||||
file_sys/content_archive.cpp
|
||||
file_sys/content_archive.h
|
||||
file_sys/control_metadata.cpp
|
||||
@@ -114,26 +116,26 @@ add_library(core STATIC
|
||||
hle/service/apm/apm.h
|
||||
hle/service/apm/interface.cpp
|
||||
hle/service/apm/interface.h
|
||||
hle/service/audio/audio.cpp
|
||||
hle/service/audio/audio.h
|
||||
hle/service/audio/audin_u.cpp
|
||||
hle/service/audio/audin_u.h
|
||||
hle/service/audio/audio.cpp
|
||||
hle/service/audio/audio.h
|
||||
hle/service/audio/audout_u.cpp
|
||||
hle/service/audio/audout_u.h
|
||||
hle/service/audio/audrec_u.cpp
|
||||
hle/service/audio/audrec_u.h
|
||||
hle/service/audio/audren_u.cpp
|
||||
hle/service/audio/audren_u.h
|
||||
hle/service/audio/audren_u.cpp
|
||||
hle/service/audio/audren_u.h
|
||||
hle/service/audio/audren_u.h
|
||||
hle/service/audio/codecctl.cpp
|
||||
hle/service/audio/codecctl.h
|
||||
hle/service/audio/hwopus.cpp
|
||||
hle/service/audio/hwopus.h
|
||||
hle/service/bcat/module.cpp
|
||||
hle/service/bcat/module.h
|
||||
hle/service/bcat/bcat.cpp
|
||||
hle/service/bcat/bcat.h
|
||||
hle/service/bcat/module.cpp
|
||||
hle/service/bcat/module.h
|
||||
hle/service/fatal/fatal.cpp
|
||||
hle/service/fatal/fatal.h
|
||||
hle/service/fatal/fatal_p.cpp
|
||||
@@ -146,28 +148,20 @@ add_library(core STATIC
|
||||
hle/service/filesystem/fsp_srv.h
|
||||
hle/service/friend/friend.cpp
|
||||
hle/service/friend/friend.h
|
||||
hle/service/friend/friend_a.cpp
|
||||
hle/service/friend/friend_a.h
|
||||
hle/service/friend/friend_u.cpp
|
||||
hle/service/friend/friend_u.h
|
||||
hle/service/friend/interface.cpp
|
||||
hle/service/friend/interface.h
|
||||
hle/service/hid/hid.cpp
|
||||
hle/service/hid/hid.h
|
||||
hle/service/lm/lm.cpp
|
||||
hle/service/lm/lm.h
|
||||
hle/service/mm/mm_u.cpp
|
||||
hle/service/mm/mm_u.h
|
||||
hle/service/nifm/nifm.cpp
|
||||
hle/service/nifm/nifm.h
|
||||
hle/service/nifm/nifm_a.cpp
|
||||
hle/service/nifm/nifm_a.h
|
||||
hle/service/nifm/nifm_s.cpp
|
||||
hle/service/nifm/nifm_s.h
|
||||
hle/service/nifm/nifm_u.cpp
|
||||
hle/service/nifm/nifm_u.h
|
||||
hle/service/nfp/nfp.cpp
|
||||
hle/service/nfp/nfp.h
|
||||
hle/service/nfp/nfp_user.cpp
|
||||
hle/service/nfp/nfp_user.h
|
||||
hle/service/nifm/nifm.cpp
|
||||
hle/service/nifm/nifm.h
|
||||
hle/service/ns/ns.cpp
|
||||
hle/service/ns/ns.h
|
||||
hle/service/ns/pl_u.cpp
|
||||
@@ -235,12 +229,10 @@ add_library(core STATIC
|
||||
hle/service/spl/spl.h
|
||||
hle/service/ssl/ssl.cpp
|
||||
hle/service/ssl/ssl.h
|
||||
hle/service/time/interface.cpp
|
||||
hle/service/time/interface.h
|
||||
hle/service/time/time.cpp
|
||||
hle/service/time/time.h
|
||||
hle/service/time/time_s.cpp
|
||||
hle/service/time/time_s.h
|
||||
hle/service/time/time_u.cpp
|
||||
hle/service/time/time_u.h
|
||||
hle/service/vi/vi.cpp
|
||||
hle/service/vi/vi.h
|
||||
hle/service/vi/vi_m.cpp
|
||||
|
||||
@@ -102,8 +102,8 @@ public:
|
||||
u64 tpidr_el0 = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit() {
|
||||
const auto page_table = Core::CurrentProcess()->vm_manager.page_table.pointers.data();
|
||||
std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit() const {
|
||||
auto** const page_table = Core::CurrentProcess()->vm_manager.page_table.pointers.data();
|
||||
|
||||
Dynarmic::A64::UserConfig config;
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
void PageTableChanged() override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<Dynarmic::A64::Jit> MakeJit();
|
||||
std::unique_ptr<Dynarmic::A64::Jit> MakeJit() const;
|
||||
|
||||
friend class ARM_Dynarmic_Callbacks;
|
||||
std::unique_ptr<ARM_Dynarmic_Callbacks> cb;
|
||||
|
||||
@@ -5,17 +5,15 @@
|
||||
#include "core/core_timing.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cinttypes>
|
||||
#include <limits>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/thread.h"
|
||||
#include "common/threadsafe_queue.h"
|
||||
#include "core/core_timing_util.h"
|
||||
|
||||
namespace CoreTiming {
|
||||
|
||||
@@ -59,7 +57,6 @@ static u64 event_fifo_id;
|
||||
static Common::MPSCQueue<Event, false> ts_queue;
|
||||
|
||||
constexpr int MAX_SLICE_LENGTH = 20000;
|
||||
constexpr u64 MAX_VALUE_TO_MULTIPLY = std::numeric_limits<s64>::max() / BASE_CLOCK_RATE;
|
||||
|
||||
static s64 idled_cycles;
|
||||
|
||||
@@ -72,54 +69,6 @@ static EventType* ev_lost = nullptr;
|
||||
|
||||
static void EmptyTimedCallback(u64 userdata, s64 cyclesLate) {}
|
||||
|
||||
s64 usToCycles(s64 us) {
|
||||
if (us / 1000000 > MAX_VALUE_TO_MULTIPLY) {
|
||||
LOG_ERROR(Core_Timing, "Integer overflow, use max value");
|
||||
return std::numeric_limits<s64>::max();
|
||||
}
|
||||
if (us > MAX_VALUE_TO_MULTIPLY) {
|
||||
LOG_DEBUG(Core_Timing, "Time very big, do rounding");
|
||||
return BASE_CLOCK_RATE * (us / 1000000);
|
||||
}
|
||||
return (BASE_CLOCK_RATE * us) / 1000000;
|
||||
}
|
||||
|
||||
s64 usToCycles(u64 us) {
|
||||
if (us / 1000000 > MAX_VALUE_TO_MULTIPLY) {
|
||||
LOG_ERROR(Core_Timing, "Integer overflow, use max value");
|
||||
return std::numeric_limits<s64>::max();
|
||||
}
|
||||
if (us > MAX_VALUE_TO_MULTIPLY) {
|
||||
LOG_DEBUG(Core_Timing, "Time very big, do rounding");
|
||||
return BASE_CLOCK_RATE * static_cast<s64>(us / 1000000);
|
||||
}
|
||||
return (BASE_CLOCK_RATE * static_cast<s64>(us)) / 1000000;
|
||||
}
|
||||
|
||||
s64 nsToCycles(s64 ns) {
|
||||
if (ns / 1000000000 > MAX_VALUE_TO_MULTIPLY) {
|
||||
LOG_ERROR(Core_Timing, "Integer overflow, use max value");
|
||||
return std::numeric_limits<s64>::max();
|
||||
}
|
||||
if (ns > MAX_VALUE_TO_MULTIPLY) {
|
||||
LOG_DEBUG(Core_Timing, "Time very big, do rounding");
|
||||
return BASE_CLOCK_RATE * (ns / 1000000000);
|
||||
}
|
||||
return (BASE_CLOCK_RATE * ns) / 1000000000;
|
||||
}
|
||||
|
||||
s64 nsToCycles(u64 ns) {
|
||||
if (ns / 1000000000 > MAX_VALUE_TO_MULTIPLY) {
|
||||
LOG_ERROR(Core_Timing, "Integer overflow, use max value");
|
||||
return std::numeric_limits<s64>::max();
|
||||
}
|
||||
if (ns > MAX_VALUE_TO_MULTIPLY) {
|
||||
LOG_DEBUG(Core_Timing, "Time very big, do rounding");
|
||||
return BASE_CLOCK_RATE * (static_cast<s64>(ns) / 1000000000);
|
||||
}
|
||||
return (BASE_CLOCK_RATE * static_cast<s64>(ns)) / 1000000000;
|
||||
}
|
||||
|
||||
EventType* RegisterEvent(const std::string& name, TimedCallback callback) {
|
||||
// check for existing type with same name.
|
||||
// we want event type names to remain unique so that we can use them for serialization.
|
||||
|
||||
@@ -23,59 +23,6 @@
|
||||
|
||||
namespace CoreTiming {
|
||||
|
||||
// The below clock rate is based on Switch's clockspeed being widely known as 1.020GHz
|
||||
// The exact value used is of course unverified.
|
||||
constexpr u64 BASE_CLOCK_RATE = 1019215872; // Switch clock speed is 1020MHz un/docked
|
||||
|
||||
inline s64 msToCycles(int ms) {
|
||||
// since ms is int there is no way to overflow
|
||||
return BASE_CLOCK_RATE * static_cast<s64>(ms) / 1000;
|
||||
}
|
||||
|
||||
inline s64 msToCycles(float ms) {
|
||||
return static_cast<s64>(BASE_CLOCK_RATE * (0.001f) * ms);
|
||||
}
|
||||
|
||||
inline s64 msToCycles(double ms) {
|
||||
return static_cast<s64>(BASE_CLOCK_RATE * (0.001) * ms);
|
||||
}
|
||||
|
||||
inline s64 usToCycles(float us) {
|
||||
return static_cast<s64>(BASE_CLOCK_RATE * (0.000001f) * us);
|
||||
}
|
||||
|
||||
inline s64 usToCycles(int us) {
|
||||
return (BASE_CLOCK_RATE * static_cast<s64>(us) / 1000000);
|
||||
}
|
||||
|
||||
s64 usToCycles(s64 us);
|
||||
|
||||
s64 usToCycles(u64 us);
|
||||
|
||||
inline s64 nsToCycles(float ns) {
|
||||
return static_cast<s64>(BASE_CLOCK_RATE * (0.000000001f) * ns);
|
||||
}
|
||||
|
||||
inline s64 nsToCycles(int ns) {
|
||||
return BASE_CLOCK_RATE * static_cast<s64>(ns) / 1000000000;
|
||||
}
|
||||
|
||||
s64 nsToCycles(s64 ns);
|
||||
|
||||
s64 nsToCycles(u64 ns);
|
||||
|
||||
inline u64 cyclesToNs(s64 cycles) {
|
||||
return cycles * 1000000000 / BASE_CLOCK_RATE;
|
||||
}
|
||||
|
||||
inline s64 cyclesToUs(s64 cycles) {
|
||||
return cycles * 1000000 / BASE_CLOCK_RATE;
|
||||
}
|
||||
|
||||
inline u64 cyclesToMs(s64 cycles) {
|
||||
return cycles * 1000 / BASE_CLOCK_RATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* CoreTiming begins at the boundary of timing slice -1. An initial call to Advance() is
|
||||
* required to end slice -1 and start slice 0 before the first cycle of code is executed.
|
||||
|
||||
63
src/core/core_timing_util.cpp
Normal file
63
src/core/core_timing_util.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
// Copyright 2008 Dolphin Emulator Project / 2017 Citra Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/core_timing_util.h"
|
||||
|
||||
#include <cinttypes>
|
||||
#include <limits>
|
||||
#include "common/logging/log.h"
|
||||
|
||||
namespace CoreTiming {
|
||||
|
||||
constexpr u64 MAX_VALUE_TO_MULTIPLY = std::numeric_limits<s64>::max() / BASE_CLOCK_RATE;
|
||||
|
||||
s64 usToCycles(s64 us) {
|
||||
if (us / 1000000 > MAX_VALUE_TO_MULTIPLY) {
|
||||
LOG_ERROR(Core_Timing, "Integer overflow, use max value");
|
||||
return std::numeric_limits<s64>::max();
|
||||
}
|
||||
if (us > MAX_VALUE_TO_MULTIPLY) {
|
||||
LOG_DEBUG(Core_Timing, "Time very big, do rounding");
|
||||
return BASE_CLOCK_RATE * (us / 1000000);
|
||||
}
|
||||
return (BASE_CLOCK_RATE * us) / 1000000;
|
||||
}
|
||||
|
||||
s64 usToCycles(u64 us) {
|
||||
if (us / 1000000 > MAX_VALUE_TO_MULTIPLY) {
|
||||
LOG_ERROR(Core_Timing, "Integer overflow, use max value");
|
||||
return std::numeric_limits<s64>::max();
|
||||
}
|
||||
if (us > MAX_VALUE_TO_MULTIPLY) {
|
||||
LOG_DEBUG(Core_Timing, "Time very big, do rounding");
|
||||
return BASE_CLOCK_RATE * static_cast<s64>(us / 1000000);
|
||||
}
|
||||
return (BASE_CLOCK_RATE * static_cast<s64>(us)) / 1000000;
|
||||
}
|
||||
|
||||
s64 nsToCycles(s64 ns) {
|
||||
if (ns / 1000000000 > MAX_VALUE_TO_MULTIPLY) {
|
||||
LOG_ERROR(Core_Timing, "Integer overflow, use max value");
|
||||
return std::numeric_limits<s64>::max();
|
||||
}
|
||||
if (ns > MAX_VALUE_TO_MULTIPLY) {
|
||||
LOG_DEBUG(Core_Timing, "Time very big, do rounding");
|
||||
return BASE_CLOCK_RATE * (ns / 1000000000);
|
||||
}
|
||||
return (BASE_CLOCK_RATE * ns) / 1000000000;
|
||||
}
|
||||
|
||||
s64 nsToCycles(u64 ns) {
|
||||
if (ns / 1000000000 > MAX_VALUE_TO_MULTIPLY) {
|
||||
LOG_ERROR(Core_Timing, "Integer overflow, use max value");
|
||||
return std::numeric_limits<s64>::max();
|
||||
}
|
||||
if (ns > MAX_VALUE_TO_MULTIPLY) {
|
||||
LOG_DEBUG(Core_Timing, "Time very big, do rounding");
|
||||
return BASE_CLOCK_RATE * (static_cast<s64>(ns) / 1000000000);
|
||||
}
|
||||
return (BASE_CLOCK_RATE * static_cast<s64>(ns)) / 1000000000;
|
||||
}
|
||||
|
||||
} // namespace CoreTiming
|
||||
64
src/core/core_timing_util.h
Normal file
64
src/core/core_timing_util.h
Normal file
@@ -0,0 +1,64 @@
|
||||
// Copyright 2008 Dolphin Emulator Project / 2017 Citra Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace CoreTiming {
|
||||
|
||||
// The below clock rate is based on Switch's clockspeed being widely known as 1.020GHz
|
||||
// The exact value used is of course unverified.
|
||||
constexpr u64 BASE_CLOCK_RATE = 1019215872; // Switch clock speed is 1020MHz un/docked
|
||||
|
||||
inline s64 msToCycles(int ms) {
|
||||
// since ms is int there is no way to overflow
|
||||
return BASE_CLOCK_RATE * static_cast<s64>(ms) / 1000;
|
||||
}
|
||||
|
||||
inline s64 msToCycles(float ms) {
|
||||
return static_cast<s64>(BASE_CLOCK_RATE * (0.001f) * ms);
|
||||
}
|
||||
|
||||
inline s64 msToCycles(double ms) {
|
||||
return static_cast<s64>(BASE_CLOCK_RATE * (0.001) * ms);
|
||||
}
|
||||
|
||||
inline s64 usToCycles(float us) {
|
||||
return static_cast<s64>(BASE_CLOCK_RATE * (0.000001f) * us);
|
||||
}
|
||||
|
||||
inline s64 usToCycles(int us) {
|
||||
return (BASE_CLOCK_RATE * static_cast<s64>(us) / 1000000);
|
||||
}
|
||||
|
||||
s64 usToCycles(s64 us);
|
||||
|
||||
s64 usToCycles(u64 us);
|
||||
|
||||
inline s64 nsToCycles(float ns) {
|
||||
return static_cast<s64>(BASE_CLOCK_RATE * (0.000000001f) * ns);
|
||||
}
|
||||
|
||||
inline s64 nsToCycles(int ns) {
|
||||
return BASE_CLOCK_RATE * static_cast<s64>(ns) / 1000000000;
|
||||
}
|
||||
|
||||
s64 nsToCycles(s64 ns);
|
||||
|
||||
s64 nsToCycles(u64 ns);
|
||||
|
||||
inline u64 cyclesToNs(s64 cycles) {
|
||||
return cycles * 1000000000 / BASE_CLOCK_RATE;
|
||||
}
|
||||
|
||||
inline s64 cyclesToUs(s64 cycles) {
|
||||
return cycles * 1000000 / BASE_CLOCK_RATE;
|
||||
}
|
||||
|
||||
inline u64 cyclesToMs(s64 cycles) {
|
||||
return cycles * 1000 / BASE_CLOCK_RATE;
|
||||
}
|
||||
|
||||
} // namespace CoreTiming
|
||||
@@ -11,7 +11,13 @@ namespace FileSys {
|
||||
enum class Mode : u32 {
|
||||
Read = 1,
|
||||
Write = 2,
|
||||
ReadWrite = 3,
|
||||
Append = 4,
|
||||
WriteAppend = 6,
|
||||
};
|
||||
|
||||
inline u32 operator&(Mode lhs, Mode rhs) {
|
||||
return static_cast<u32>(lhs) & static_cast<u32>(rhs);
|
||||
}
|
||||
|
||||
} // namespace FileSys
|
||||
|
||||
@@ -65,8 +65,8 @@ PartitionFilesystem::PartitionFilesystem(std::shared_ptr<VfsFile> file) {
|
||||
std::string name(
|
||||
reinterpret_cast<const char*>(&file_data[strtab_offset + entry.strtab_offset]));
|
||||
|
||||
pfs_files.emplace_back(
|
||||
std::make_shared<OffsetVfsFile>(file, entry.size, content_offset + entry.offset, name));
|
||||
pfs_files.emplace_back(std::make_shared<OffsetVfsFile>(
|
||||
file, entry.size, content_offset + entry.offset, std::move(name)));
|
||||
}
|
||||
|
||||
status = Loader::ResultStatus::Success;
|
||||
@@ -109,7 +109,7 @@ bool PartitionFilesystem::ReplaceFileWithSubdirectory(VirtualFile file, VirtualD
|
||||
return false;
|
||||
|
||||
const std::ptrdiff_t offset = std::distance(pfs_files.begin(), iter);
|
||||
pfs_files[offset] = pfs_files.back();
|
||||
pfs_files[offset] = std::move(pfs_files.back());
|
||||
pfs_files.pop_back();
|
||||
|
||||
pfs_dirs.emplace_back(std::move(dir));
|
||||
|
||||
@@ -13,24 +13,31 @@
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
static std::string PermissionsToCharArray(Mode perms) {
|
||||
std::string out;
|
||||
switch (perms) {
|
||||
case Mode::Read:
|
||||
out += "r";
|
||||
break;
|
||||
case Mode::Write:
|
||||
out += "r+";
|
||||
break;
|
||||
case Mode::Append:
|
||||
out += "a";
|
||||
break;
|
||||
static std::string ModeFlagsToString(Mode mode) {
|
||||
std::string mode_str;
|
||||
|
||||
// Calculate the correct open mode for the file.
|
||||
if (mode & Mode::Read && mode & Mode::Write) {
|
||||
if (mode & Mode::Append)
|
||||
mode_str = "a+";
|
||||
else
|
||||
mode_str = "r+";
|
||||
} else {
|
||||
if (mode & Mode::Read)
|
||||
mode_str = "r";
|
||||
else if (mode & Mode::Append)
|
||||
mode_str = "a";
|
||||
else if (mode & Mode::Write)
|
||||
mode_str = "w";
|
||||
}
|
||||
return out + "b";
|
||||
|
||||
mode_str += "b";
|
||||
|
||||
return mode_str;
|
||||
}
|
||||
|
||||
RealVfsFile::RealVfsFile(const std::string& path_, Mode perms_)
|
||||
: backing(path_, PermissionsToCharArray(perms_).c_str()), path(path_),
|
||||
: backing(path_, ModeFlagsToString(perms_).c_str()), path(path_),
|
||||
parent_path(FileUtil::GetParentPath(path_)),
|
||||
path_components(FileUtil::SplitPathComponents(path_)),
|
||||
parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)),
|
||||
@@ -53,11 +60,11 @@ std::shared_ptr<VfsDirectory> RealVfsFile::GetContainingDirectory() const {
|
||||
}
|
||||
|
||||
bool RealVfsFile::IsWritable() const {
|
||||
return perms == Mode::Append || perms == Mode::Write;
|
||||
return (perms & Mode::WriteAppend) != 0;
|
||||
}
|
||||
|
||||
bool RealVfsFile::IsReadable() const {
|
||||
return perms == Mode::Read || perms == Mode::Write;
|
||||
return (perms & Mode::ReadWrite) != 0;
|
||||
}
|
||||
|
||||
size_t RealVfsFile::Read(u8* data, size_t length, size_t offset) const {
|
||||
@@ -79,7 +86,7 @@ bool RealVfsFile::Rename(std::string_view name) {
|
||||
path = (parent_path + DIR_SEP).append(name);
|
||||
path_components = parent_components;
|
||||
path_components.push_back(std::move(name_str));
|
||||
backing = FileUtil::IOFile(path, PermissionsToCharArray(perms).c_str());
|
||||
backing = FileUtil::IOFile(path, ModeFlagsToString(perms).c_str());
|
||||
|
||||
return out;
|
||||
}
|
||||
@@ -93,7 +100,7 @@ RealVfsDirectory::RealVfsDirectory(const std::string& path_, Mode perms_)
|
||||
path_components(FileUtil::SplitPathComponents(path)),
|
||||
parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)),
|
||||
perms(perms_) {
|
||||
if (!FileUtil::Exists(path) && (perms == Mode::Write || perms == Mode::Append))
|
||||
if (!FileUtil::Exists(path) && perms & Mode::WriteAppend)
|
||||
FileUtil::CreateDir(path);
|
||||
|
||||
if (perms == Mode::Append)
|
||||
@@ -120,11 +127,11 @@ std::vector<std::shared_ptr<VfsDirectory>> RealVfsDirectory::GetSubdirectories()
|
||||
}
|
||||
|
||||
bool RealVfsDirectory::IsWritable() const {
|
||||
return perms == Mode::Write || perms == Mode::Append;
|
||||
return (perms & Mode::WriteAppend) != 0;
|
||||
}
|
||||
|
||||
bool RealVfsDirectory::IsReadable() const {
|
||||
return perms == Mode::Read || perms == Mode::Write;
|
||||
return (perms & Mode::ReadWrite) != 0;
|
||||
}
|
||||
|
||||
std::string RealVfsDirectory::GetName() const {
|
||||
|
||||
@@ -25,9 +25,9 @@ protected:
|
||||
ptrdiff_t index = 0;
|
||||
|
||||
public:
|
||||
RequestHelperBase(u32* command_buffer) : cmdbuf(command_buffer) {}
|
||||
explicit RequestHelperBase(u32* command_buffer) : cmdbuf(command_buffer) {}
|
||||
|
||||
RequestHelperBase(Kernel::HLERequestContext& context)
|
||||
explicit RequestHelperBase(Kernel::HLERequestContext& context)
|
||||
: context(&context), cmdbuf(context.CommandBuffer()) {}
|
||||
|
||||
void Skip(unsigned size_in_words, bool set_to_null) {
|
||||
@@ -56,13 +56,6 @@ public:
|
||||
|
||||
class ResponseBuilder : public RequestHelperBase {
|
||||
public:
|
||||
ResponseBuilder(u32* command_buffer) : RequestHelperBase(command_buffer) {}
|
||||
|
||||
u32 normal_params_size{};
|
||||
u32 num_handles_to_copy{};
|
||||
u32 num_objects_to_move{}; ///< Domain objects or move handles, context dependent
|
||||
std::ptrdiff_t datapayload_index{};
|
||||
|
||||
/// Flags used for customizing the behavior of ResponseBuilder
|
||||
enum class Flags : u32 {
|
||||
None = 0,
|
||||
@@ -71,9 +64,11 @@ public:
|
||||
AlwaysMoveHandles = 1,
|
||||
};
|
||||
|
||||
ResponseBuilder(Kernel::HLERequestContext& context, u32 normal_params_size,
|
||||
u32 num_handles_to_copy = 0, u32 num_objects_to_move = 0,
|
||||
Flags flags = Flags::None)
|
||||
explicit ResponseBuilder(u32* command_buffer) : RequestHelperBase(command_buffer) {}
|
||||
|
||||
explicit ResponseBuilder(Kernel::HLERequestContext& context, u32 normal_params_size,
|
||||
u32 num_handles_to_copy = 0, u32 num_objects_to_move = 0,
|
||||
Flags flags = Flags::None)
|
||||
|
||||
: RequestHelperBase(context), normal_params_size(normal_params_size),
|
||||
num_handles_to_copy(num_handles_to_copy), num_objects_to_move(num_objects_to_move) {
|
||||
@@ -206,6 +201,12 @@ public:
|
||||
|
||||
template <typename... O>
|
||||
void PushCopyObjects(Kernel::SharedPtr<O>... pointers);
|
||||
|
||||
private:
|
||||
u32 normal_params_size{};
|
||||
u32 num_handles_to_copy{};
|
||||
u32 num_objects_to_move{}; ///< Domain objects or move handles, context dependent
|
||||
std::ptrdiff_t datapayload_index{};
|
||||
};
|
||||
|
||||
/// Push ///
|
||||
@@ -273,9 +274,9 @@ inline void ResponseBuilder::PushMoveObjects(Kernel::SharedPtr<O>... pointers) {
|
||||
|
||||
class RequestParser : public RequestHelperBase {
|
||||
public:
|
||||
RequestParser(u32* command_buffer) : RequestHelperBase(command_buffer) {}
|
||||
explicit RequestParser(u32* command_buffer) : RequestHelperBase(command_buffer) {}
|
||||
|
||||
RequestParser(Kernel::HLERequestContext& context) : RequestHelperBase(context) {
|
||||
explicit RequestParser(Kernel::HLERequestContext& context) : RequestHelperBase(context) {
|
||||
ASSERT_MSG(context.GetDataPayloadOffset(), "context is incomplete");
|
||||
Skip(context.GetDataPayloadOffset(), false);
|
||||
// Skip the u64 command id, it's already stored in the context
|
||||
@@ -285,8 +286,9 @@ public:
|
||||
|
||||
ResponseBuilder MakeBuilder(u32 normal_params_size, u32 num_handles_to_copy,
|
||||
u32 num_handles_to_move,
|
||||
ResponseBuilder::Flags flags = ResponseBuilder::Flags::None) {
|
||||
return {*context, normal_params_size, num_handles_to_copy, num_handles_to_move, flags};
|
||||
ResponseBuilder::Flags flags = ResponseBuilder::Flags::None) const {
|
||||
return ResponseBuilder{*context, normal_params_size, num_handles_to_copy,
|
||||
num_handles_to_move, flags};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -298,6 +300,14 @@ public:
|
||||
template <typename First, typename... Other>
|
||||
void Pop(First& first_value, Other&... other_values);
|
||||
|
||||
template <typename T>
|
||||
T PopEnum() {
|
||||
static_assert(std::is_enum_v<T>, "T must be an enum type within a PopEnum call.");
|
||||
static_assert(!std::is_convertible_v<T, int>,
|
||||
"enum type in PopEnum must be a strongly typed enum.");
|
||||
return static_cast<T>(Pop<std::underlying_type_t<T>>());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads the next normal parameters as a struct, by copying it
|
||||
* @note: The output class must be correctly packed/padded to fit hardware layout.
|
||||
|
||||
@@ -91,7 +91,7 @@ protected:
|
||||
*/
|
||||
class HLERequestContext {
|
||||
public:
|
||||
HLERequestContext(SharedPtr<Kernel::ServerSession> session);
|
||||
explicit HLERequestContext(SharedPtr<ServerSession> session);
|
||||
~HLERequestContext();
|
||||
|
||||
/// Returns a pointer to the IPC command buffer for this request.
|
||||
|
||||
@@ -40,7 +40,9 @@ static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) {
|
||||
}
|
||||
|
||||
static ResultCode SetMemoryAttribute(VAddr addr, u64 size, u32 state0, u32 state1) {
|
||||
LOG_WARNING(Kernel_SVC, "(STUBBED) called, addr=0x{:X}", addr);
|
||||
LOG_WARNING(Kernel_SVC,
|
||||
"(STUBBED) called, addr=0x{:X}, size=0x{:X}, state0=0x{:X}, state1=0x{:X}", addr,
|
||||
size, state0, state1);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -165,11 +167,14 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64
|
||||
using ObjectPtr = SharedPtr<WaitObject>;
|
||||
std::vector<ObjectPtr> objects(handle_count);
|
||||
|
||||
for (int i = 0; i < handle_count; ++i) {
|
||||
Handle handle = Memory::Read32(handles_address + i * sizeof(Handle));
|
||||
auto object = g_handle_table.Get<WaitObject>(handle);
|
||||
if (object == nullptr)
|
||||
for (u64 i = 0; i < handle_count; ++i) {
|
||||
const Handle handle = Memory::Read32(handles_address + i * sizeof(Handle));
|
||||
const auto object = g_handle_table.Get<WaitObject>(handle);
|
||||
|
||||
if (object == nullptr) {
|
||||
return ERR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
objects[i] = object;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "core/arm/arm_interface.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/core_timing_util.h"
|
||||
#include "core/hle/kernel/errors.h"
|
||||
#include "core/hle/kernel/handle_table.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/core_timing_util.h"
|
||||
#include "core/hle/kernel/handle_table.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/thread.h"
|
||||
|
||||
@@ -35,7 +35,7 @@ static constexpr u128 DEFAULT_USER_ID{1ull, 0ull};
|
||||
|
||||
class IProfile final : public ServiceFramework<IProfile> {
|
||||
public:
|
||||
IProfile(u128 user_id) : ServiceFramework("IProfile"), user_id(user_id) {
|
||||
explicit IProfile(u128 user_id) : ServiceFramework("IProfile"), user_id(user_id) {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "Get"},
|
||||
{1, &IProfile::GetBase, "GetBase"},
|
||||
|
||||
@@ -19,7 +19,4 @@ private:
|
||||
std::shared_ptr<Module> apm;
|
||||
};
|
||||
|
||||
/// Registers all AM services with the specified service manager.
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager);
|
||||
|
||||
} // namespace Service::APM
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <vector>
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/core_timing_util.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/event.h"
|
||||
#include "core/hle/kernel/hle_ipc.h"
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "common/alignment.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/core_timing_util.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/event.h"
|
||||
#include "core/hle/kernel/hle_ipc.h"
|
||||
|
||||
@@ -24,7 +24,8 @@ namespace Service::FileSystem {
|
||||
constexpr u64 EMULATED_SD_REPORTED_SIZE = 32000000000;
|
||||
|
||||
static FileSys::VirtualDir GetDirectoryRelativeWrapped(FileSys::VirtualDir base,
|
||||
std::string_view dir_name) {
|
||||
std::string_view dir_name_) {
|
||||
std::string dir_name(FileUtil::SanitizePath(dir_name_));
|
||||
if (dir_name.empty() || dir_name == "." || dir_name == "/" || dir_name == "\\")
|
||||
return base;
|
||||
|
||||
@@ -38,7 +39,8 @@ std::string VfsDirectoryServiceWrapper::GetName() const {
|
||||
return backing->GetName();
|
||||
}
|
||||
|
||||
ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path, u64 size) const {
|
||||
ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64 size) const {
|
||||
std::string path(FileUtil::SanitizePath(path_));
|
||||
auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path));
|
||||
auto file = dir->CreateFile(FileUtil::GetFilename(path));
|
||||
if (file == nullptr) {
|
||||
@@ -52,7 +54,8 @@ ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path, u64 s
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path) const {
|
||||
ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path_) const {
|
||||
std::string path(FileUtil::SanitizePath(path_));
|
||||
auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path));
|
||||
if (path == "/" || path == "\\") {
|
||||
// TODO(DarkLordZach): Why do games call this and what should it do? Works as is but...
|
||||
@@ -60,14 +63,15 @@ ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path) const
|
||||
}
|
||||
if (dir->GetFile(FileUtil::GetFilename(path)) == nullptr)
|
||||
return FileSys::ERROR_PATH_NOT_FOUND;
|
||||
if (!backing->DeleteFile(FileUtil::GetFilename(path))) {
|
||||
if (!dir->DeleteFile(FileUtil::GetFilename(path))) {
|
||||
// TODO(DarkLordZach): Find a better error code for this
|
||||
return ResultCode(-1);
|
||||
}
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path) const {
|
||||
ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path_) const {
|
||||
std::string path(FileUtil::SanitizePath(path_));
|
||||
auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path));
|
||||
if (dir == nullptr && FileUtil::GetFilename(FileUtil::GetParentPath(path)).empty())
|
||||
dir = backing;
|
||||
@@ -79,7 +83,8 @@ ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path)
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
ResultCode VfsDirectoryServiceWrapper::DeleteDirectory(const std::string& path) const {
|
||||
ResultCode VfsDirectoryServiceWrapper::DeleteDirectory(const std::string& path_) const {
|
||||
std::string path(FileUtil::SanitizePath(path_));
|
||||
auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path));
|
||||
if (!dir->DeleteSubdirectory(FileUtil::GetFilename(path))) {
|
||||
// TODO(DarkLordZach): Find a better error code for this
|
||||
@@ -88,7 +93,8 @@ ResultCode VfsDirectoryServiceWrapper::DeleteDirectory(const std::string& path)
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
ResultCode VfsDirectoryServiceWrapper::DeleteDirectoryRecursively(const std::string& path) const {
|
||||
ResultCode VfsDirectoryServiceWrapper::DeleteDirectoryRecursively(const std::string& path_) const {
|
||||
std::string path(FileUtil::SanitizePath(path_));
|
||||
auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path));
|
||||
if (!dir->DeleteSubdirectoryRecursive(FileUtil::GetFilename(path))) {
|
||||
// TODO(DarkLordZach): Find a better error code for this
|
||||
@@ -97,8 +103,10 @@ ResultCode VfsDirectoryServiceWrapper::DeleteDirectoryRecursively(const std::str
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
ResultCode VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path,
|
||||
const std::string& dest_path) const {
|
||||
ResultCode VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path_,
|
||||
const std::string& dest_path_) const {
|
||||
std::string src_path(FileUtil::SanitizePath(src_path_));
|
||||
std::string dest_path(FileUtil::SanitizePath(dest_path_));
|
||||
auto src = backing->GetFileRelative(src_path);
|
||||
if (FileUtil::GetParentPath(src_path) == FileUtil::GetParentPath(dest_path)) {
|
||||
// Use more-optimized vfs implementation rename.
|
||||
@@ -130,8 +138,10 @@ ResultCode VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path,
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
ResultCode VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path,
|
||||
const std::string& dest_path) const {
|
||||
ResultCode VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path_,
|
||||
const std::string& dest_path_) const {
|
||||
std::string src_path(FileUtil::SanitizePath(src_path_));
|
||||
std::string dest_path(FileUtil::SanitizePath(dest_path_));
|
||||
auto src = GetDirectoryRelativeWrapped(backing, src_path);
|
||||
if (FileUtil::GetParentPath(src_path) == FileUtil::GetParentPath(dest_path)) {
|
||||
// Use more-optimized vfs implementation rename.
|
||||
@@ -154,8 +164,9 @@ ResultCode VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_pa
|
||||
return ResultCode(-1);
|
||||
}
|
||||
|
||||
ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std::string& path,
|
||||
ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std::string& path_,
|
||||
FileSys::Mode mode) const {
|
||||
std::string path(FileUtil::SanitizePath(path_));
|
||||
auto npath = path;
|
||||
while (npath.size() > 0 && (npath[0] == '/' || npath[0] == '\\'))
|
||||
npath = npath.substr(1);
|
||||
@@ -171,7 +182,8 @@ ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std::
|
||||
return MakeResult<FileSys::VirtualFile>(file);
|
||||
}
|
||||
|
||||
ResultVal<FileSys::VirtualDir> VfsDirectoryServiceWrapper::OpenDirectory(const std::string& path) {
|
||||
ResultVal<FileSys::VirtualDir> VfsDirectoryServiceWrapper::OpenDirectory(const std::string& path_) {
|
||||
std::string path(FileUtil::SanitizePath(path_));
|
||||
auto dir = GetDirectoryRelativeWrapped(backing, path);
|
||||
if (dir == nullptr) {
|
||||
// TODO(DarkLordZach): Find a better error code for this
|
||||
@@ -188,7 +200,8 @@ u64 VfsDirectoryServiceWrapper::GetFreeSpaceSize() const {
|
||||
}
|
||||
|
||||
ResultVal<FileSys::EntryType> VfsDirectoryServiceWrapper::GetEntryType(
|
||||
const std::string& path) const {
|
||||
const std::string& path_) const {
|
||||
std::string path(FileUtil::SanitizePath(path_));
|
||||
auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path));
|
||||
if (dir == nullptr)
|
||||
return FileSys::ERROR_PATH_NOT_FOUND;
|
||||
@@ -272,9 +285,9 @@ void RegisterFileSystems() {
|
||||
sdmc_factory = nullptr;
|
||||
|
||||
auto nand_directory = std::make_shared<FileSys::RealVfsDirectory>(
|
||||
FileUtil::GetUserPath(FileUtil::UserPath::NANDDir), FileSys::Mode::Write);
|
||||
FileUtil::GetUserPath(FileUtil::UserPath::NANDDir), FileSys::Mode::ReadWrite);
|
||||
auto sd_directory = std::make_shared<FileSys::RealVfsDirectory>(
|
||||
FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir), FileSys::Mode::Write);
|
||||
FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir), FileSys::Mode::ReadWrite);
|
||||
|
||||
auto savedata = std::make_unique<FileSys::SaveDataFactory>(std::move(nand_directory));
|
||||
save_data_factory = std::move(savedata);
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/service/friend/friend.h"
|
||||
#include "core/hle/service/friend/friend_a.h"
|
||||
#include "core/hle/service/friend/friend_u.h"
|
||||
#include "core/hle/service/friend/interface.h"
|
||||
|
||||
namespace Service::Friend {
|
||||
|
||||
@@ -21,8 +20,11 @@ Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager) {
|
||||
auto module = std::make_shared<Module>();
|
||||
std::make_shared<Friend_A>(module)->InstallAsService(service_manager);
|
||||
std::make_shared<Friend_U>(module)->InstallAsService(service_manager);
|
||||
std::make_shared<Friend>(module, "friend:a")->InstallAsService(service_manager);
|
||||
std::make_shared<Friend>(module, "friend:m")->InstallAsService(service_manager);
|
||||
std::make_shared<Friend>(module, "friend:s")->InstallAsService(service_manager);
|
||||
std::make_shared<Friend>(module, "friend:u")->InstallAsService(service_manager);
|
||||
std::make_shared<Friend>(module, "friend:v")->InstallAsService(service_manager);
|
||||
}
|
||||
|
||||
} // namespace Service::Friend
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/service/friend/friend_u.h"
|
||||
|
||||
namespace Service::Friend {
|
||||
|
||||
Friend_U::Friend_U(std::shared_ptr<Module> module)
|
||||
: Module::Interface(std::move(module), "friend:u") {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &Friend_U::CreateFriendService, "CreateFriendService"},
|
||||
{1, nullptr, "CreateNotificationService"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
} // namespace Service::Friend
|
||||
@@ -1,16 +0,0 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/friend/friend.h"
|
||||
|
||||
namespace Service::Friend {
|
||||
|
||||
class Friend_U final : public Module::Interface {
|
||||
public:
|
||||
explicit Friend_U(std::shared_ptr<Module> module);
|
||||
};
|
||||
|
||||
} // namespace Service::Friend
|
||||
@@ -2,15 +2,16 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/service/friend/friend_a.h"
|
||||
#include "core/hle/service/friend/interface.h"
|
||||
|
||||
namespace Service::Friend {
|
||||
|
||||
Friend_A::Friend_A(std::shared_ptr<Module> module)
|
||||
: Module::Interface(std::move(module), "friend:a") {
|
||||
Friend::Friend(std::shared_ptr<Module> module, const char* name)
|
||||
: Interface(std::move(module), name) {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &Friend_A::CreateFriendService, "CreateFriendService"},
|
||||
{0, &Friend::CreateFriendService, "CreateFriendService"},
|
||||
{1, nullptr, "CreateNotificationService"},
|
||||
{2, nullptr, "CreateDaemonSuspendSessionService"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
@@ -8,9 +8,9 @@
|
||||
|
||||
namespace Service::Friend {
|
||||
|
||||
class Friend_A final : public Module::Interface {
|
||||
class Friend final : public Module::Interface {
|
||||
public:
|
||||
explicit Friend_A(std::shared_ptr<Module> module);
|
||||
explicit Friend(std::shared_ptr<Module> module, const char* name);
|
||||
};
|
||||
|
||||
} // namespace Service::Friend
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <atomic>
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/core_timing_util.h"
|
||||
#include "core/frontend/emu_window.h"
|
||||
#include "core/frontend/input.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
|
||||
@@ -5,9 +5,7 @@
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/event.h"
|
||||
#include "core/hle/service/nifm/nifm.h"
|
||||
#include "core/hle/service/nifm/nifm_a.h"
|
||||
#include "core/hle/service/nifm/nifm_s.h"
|
||||
#include "core/hle/service/nifm/nifm_u.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::NIFM {
|
||||
|
||||
@@ -210,28 +208,35 @@ IGeneralService::IGeneralService() : ServiceFramework("IGeneralService") {
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
void Module::Interface::CreateGeneralServiceOld(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<IGeneralService>();
|
||||
LOG_DEBUG(Service_NIFM, "called");
|
||||
}
|
||||
class NetworkInterface final : public ServiceFramework<NetworkInterface> {
|
||||
public:
|
||||
explicit NetworkInterface(const char* name) : ServiceFramework{name} {
|
||||
static const FunctionInfo functions[] = {
|
||||
{4, &NetworkInterface::CreateGeneralServiceOld, "CreateGeneralServiceOld"},
|
||||
{5, &NetworkInterface::CreateGeneralService, "CreateGeneralService"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
void Module::Interface::CreateGeneralService(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<IGeneralService>();
|
||||
LOG_DEBUG(Service_NIFM, "called");
|
||||
}
|
||||
void CreateGeneralServiceOld(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<IGeneralService>();
|
||||
LOG_DEBUG(Service_NIFM, "called");
|
||||
}
|
||||
|
||||
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
|
||||
: ServiceFramework(name), module(std::move(module)) {}
|
||||
void CreateGeneralService(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<IGeneralService>();
|
||||
LOG_DEBUG(Service_NIFM, "called");
|
||||
}
|
||||
};
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager) {
|
||||
auto module = std::make_shared<Module>();
|
||||
std::make_shared<NIFM_A>(module)->InstallAsService(service_manager);
|
||||
std::make_shared<NIFM_S>(module)->InstallAsService(service_manager);
|
||||
std::make_shared<NIFM_U>(module)->InstallAsService(service_manager);
|
||||
std::make_shared<NetworkInterface>("nifm:a")->InstallAsService(service_manager);
|
||||
std::make_shared<NetworkInterface>("nifm:s")->InstallAsService(service_manager);
|
||||
std::make_shared<NetworkInterface>("nifm:u")->InstallAsService(service_manager);
|
||||
}
|
||||
|
||||
} // namespace Service::NIFM
|
||||
|
||||
@@ -4,24 +4,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
namespace Service::SM {
|
||||
class ServiceManager;
|
||||
}
|
||||
|
||||
namespace Service::NIFM {
|
||||
|
||||
class Module final {
|
||||
public:
|
||||
class Interface : public ServiceFramework<Interface> {
|
||||
public:
|
||||
explicit Interface(std::shared_ptr<Module> module, const char* name);
|
||||
|
||||
void CreateGeneralServiceOld(Kernel::HLERequestContext& ctx);
|
||||
void CreateGeneralService(Kernel::HLERequestContext& ctx);
|
||||
|
||||
protected:
|
||||
std::shared_ptr<Module> module;
|
||||
};
|
||||
};
|
||||
|
||||
/// Registers all NIFM services with the specified service manager.
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager);
|
||||
|
||||
} // namespace Service::NIFM
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/service/nifm/nifm_a.h"
|
||||
|
||||
namespace Service::NIFM {
|
||||
|
||||
NIFM_A::NIFM_A(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "nifm:a") {
|
||||
static const FunctionInfo functions[] = {
|
||||
{4, &NIFM_A::CreateGeneralServiceOld, "CreateGeneralServiceOld"},
|
||||
{5, &NIFM_A::CreateGeneralService, "CreateGeneralService"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
} // namespace Service::NIFM
|
||||
@@ -1,16 +0,0 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/nifm/nifm.h"
|
||||
|
||||
namespace Service::NIFM {
|
||||
|
||||
class NIFM_A final : public Module::Interface {
|
||||
public:
|
||||
explicit NIFM_A(std::shared_ptr<Module> module);
|
||||
};
|
||||
|
||||
} // namespace Service::NIFM
|
||||
@@ -1,17 +0,0 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/service/nifm/nifm_s.h"
|
||||
|
||||
namespace Service::NIFM {
|
||||
|
||||
NIFM_S::NIFM_S(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "nifm:s") {
|
||||
static const FunctionInfo functions[] = {
|
||||
{4, &NIFM_S::CreateGeneralServiceOld, "CreateGeneralServiceOld"},
|
||||
{5, &NIFM_S::CreateGeneralService, "CreateGeneralService"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
} // namespace Service::NIFM
|
||||
@@ -1,16 +0,0 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/nifm/nifm.h"
|
||||
|
||||
namespace Service::NIFM {
|
||||
|
||||
class NIFM_S final : public Module::Interface {
|
||||
public:
|
||||
explicit NIFM_S(std::shared_ptr<Module> module);
|
||||
};
|
||||
|
||||
} // namespace Service::NIFM
|
||||
@@ -1,17 +0,0 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/service/nifm/nifm_u.h"
|
||||
|
||||
namespace Service::NIFM {
|
||||
|
||||
NIFM_U::NIFM_U(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "nifm:u") {
|
||||
static const FunctionInfo functions[] = {
|
||||
{4, &NIFM_U::CreateGeneralServiceOld, "CreateGeneralServiceOld"},
|
||||
{5, &NIFM_U::CreateGeneralService, "CreateGeneralService"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
} // namespace Service::NIFM
|
||||
@@ -1,16 +0,0 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/nifm/nifm.h"
|
||||
|
||||
namespace Service::NIFM {
|
||||
|
||||
class NIFM_U final : public Module::Interface {
|
||||
public:
|
||||
explicit NIFM_U(std::shared_ptr<Module> module);
|
||||
};
|
||||
|
||||
} // namespace Service::NIFM
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "common/scope_exit.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/core_timing_util.h"
|
||||
#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
|
||||
#include "core/hle/service/nvdrv/nvdrv.h"
|
||||
#include "core/hle/service/nvflinger/buffer_queue.h"
|
||||
|
||||
@@ -146,7 +146,7 @@ protected:
|
||||
* @param max_sessions Maximum number of sessions that can be
|
||||
* connected to this service at the same time.
|
||||
*/
|
||||
ServiceFramework(const char* service_name, u32 max_sessions = DefaultMaxSessions)
|
||||
explicit ServiceFramework(const char* service_name, u32 max_sessions = DefaultMaxSessions)
|
||||
: ServiceFrameworkBase(service_name, max_sessions, Invoker) {}
|
||||
|
||||
/// Registers handlers in the service.
|
||||
|
||||
@@ -10,13 +10,22 @@
|
||||
namespace Service::Set {
|
||||
|
||||
void SET_SYS::GetColorSetId(Kernel::HLERequestContext& ctx) {
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u32>(0);
|
||||
rb.PushEnum(color_set);
|
||||
|
||||
LOG_WARNING(Service_SET, "(STUBBED) called");
|
||||
LOG_DEBUG(Service_SET, "called");
|
||||
}
|
||||
|
||||
void SET_SYS::SetColorSetId(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
color_set = rp.PopEnum<ColorSet>();
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_DEBUG(Service_SET, "called");
|
||||
}
|
||||
|
||||
SET_SYS::SET_SYS() : ServiceFramework("set:sys") {
|
||||
@@ -44,7 +53,7 @@ SET_SYS::SET_SYS() : ServiceFramework("set:sys") {
|
||||
{21, nullptr, "GetEulaVersions"},
|
||||
{22, nullptr, "SetEulaVersions"},
|
||||
{23, &SET_SYS::GetColorSetId, "GetColorSetId"},
|
||||
{24, nullptr, "SetColorSetId"},
|
||||
{24, &SET_SYS::SetColorSetId, "SetColorSetId"},
|
||||
{25, nullptr, "GetConsoleInformationUploadFlag"},
|
||||
{26, nullptr, "SetConsoleInformationUploadFlag"},
|
||||
{27, nullptr, "GetAutomaticApplicationDownloadFlag"},
|
||||
@@ -172,4 +181,6 @@ SET_SYS::SET_SYS() : ServiceFramework("set:sys") {
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
SET_SYS::~SET_SYS() = default;
|
||||
|
||||
} // namespace Service::Set
|
||||
|
||||
@@ -11,10 +11,19 @@ namespace Service::Set {
|
||||
class SET_SYS final : public ServiceFramework<SET_SYS> {
|
||||
public:
|
||||
explicit SET_SYS();
|
||||
~SET_SYS() = default;
|
||||
~SET_SYS() override;
|
||||
|
||||
private:
|
||||
/// Indicates the current theme set by the system settings
|
||||
enum class ColorSet : u32 {
|
||||
BasicWhite = 0,
|
||||
BasicBlack = 1,
|
||||
};
|
||||
|
||||
void GetColorSetId(Kernel::HLERequestContext& ctx);
|
||||
void SetColorSetId(Kernel::HLERequestContext& ctx);
|
||||
|
||||
ColorSet color_set = ColorSet::BasicWhite;
|
||||
};
|
||||
|
||||
} // namespace Service::Set
|
||||
|
||||
@@ -2,17 +2,18 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/service/time/time_s.h"
|
||||
#include "core/hle/service/time/interface.h"
|
||||
|
||||
namespace Service::Time {
|
||||
|
||||
TIME_S::TIME_S(std::shared_ptr<Module> time) : Module::Interface(std::move(time), "time:s") {
|
||||
Time::Time(std::shared_ptr<Module> time, const char* name)
|
||||
: Module::Interface(std::move(time), name) {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &TIME_S::GetStandardUserSystemClock, "GetStandardUserSystemClock"},
|
||||
{1, &TIME_S::GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"},
|
||||
{2, &TIME_S::GetStandardSteadyClock, "GetStandardSteadyClock"},
|
||||
{3, &TIME_S::GetTimeZoneService, "GetTimeZoneService"},
|
||||
{4, &TIME_S::GetStandardLocalSystemClock, "GetStandardLocalSystemClock"},
|
||||
{0, &Time::GetStandardUserSystemClock, "GetStandardUserSystemClock"},
|
||||
{1, &Time::GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"},
|
||||
{2, &Time::GetStandardSteadyClock, "GetStandardSteadyClock"},
|
||||
{3, &Time::GetTimeZoneService, "GetTimeZoneService"},
|
||||
{4, &Time::GetStandardLocalSystemClock, "GetStandardLocalSystemClock"},
|
||||
{5, nullptr, "GetEphemeralNetworkSystemClock"},
|
||||
{50, nullptr, "SetStandardSteadyClockInternalOffset"},
|
||||
{100, nullptr, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||
@@ -8,9 +8,9 @@
|
||||
|
||||
namespace Service::Time {
|
||||
|
||||
class TIME_S final : public Module::Interface {
|
||||
class Time final : public Module::Interface {
|
||||
public:
|
||||
explicit TIME_S(std::shared_ptr<Module> time);
|
||||
explicit Time(std::shared_ptr<Module> time, const char* name);
|
||||
};
|
||||
|
||||
} // namespace Service::Time
|
||||
@@ -6,12 +6,12 @@
|
||||
#include <ctime>
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/core_timing_util.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/client_port.h"
|
||||
#include "core/hle/kernel/client_session.h"
|
||||
#include "core/hle/service/time/interface.h"
|
||||
#include "core/hle/service/time/time.h"
|
||||
#include "core/hle/service/time/time_s.h"
|
||||
#include "core/hle/service/time/time_u.h"
|
||||
|
||||
namespace Service::Time {
|
||||
|
||||
@@ -212,8 +212,9 @@ Module::Interface::Interface(std::shared_ptr<Module> time, const char* name)
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager) {
|
||||
auto time = std::make_shared<Module>();
|
||||
std::make_shared<TIME_S>(time)->InstallAsService(service_manager);
|
||||
std::make_shared<TIME_U>(time)->InstallAsService(service_manager);
|
||||
std::make_shared<Time>(time, "time:a")->InstallAsService(service_manager);
|
||||
std::make_shared<Time>(time, "time:s")->InstallAsService(service_manager);
|
||||
std::make_shared<Time>(time, "time:u")->InstallAsService(service_manager);
|
||||
}
|
||||
|
||||
} // namespace Service::Time
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/service/time/time_u.h"
|
||||
|
||||
namespace Service::Time {
|
||||
|
||||
TIME_U::TIME_U(std::shared_ptr<Module> time) : Module::Interface(std::move(time), "time:u") {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &TIME_U::GetStandardUserSystemClock, "GetStandardUserSystemClock"},
|
||||
{1, &TIME_U::GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"},
|
||||
{2, &TIME_U::GetStandardSteadyClock, "GetStandardSteadyClock"},
|
||||
{3, &TIME_U::GetTimeZoneService, "GetTimeZoneService"},
|
||||
{4, &TIME_U::GetStandardLocalSystemClock, "GetStandardLocalSystemClock"},
|
||||
{5, nullptr, "GetEphemeralNetworkSystemClock"},
|
||||
{50, nullptr, "SetStandardSteadyClockInternalOffset"},
|
||||
{100, nullptr, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{101, nullptr, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{102, nullptr, "GetStandardUserSystemClockInitialYear"},
|
||||
{200, nullptr, "IsStandardNetworkSystemClockAccuracySufficient"},
|
||||
{300, nullptr, "CalculateMonotonicSystemClockBaseTimePoint"},
|
||||
{400, nullptr, "GetClockSnapshot"},
|
||||
{401, nullptr, "GetClockSnapshotFromSystemClockContext"},
|
||||
{500, nullptr, "CalculateStandardUserSystemClockDifferenceByUser"},
|
||||
{501, nullptr, "CalculateSpanBetween"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
} // namespace Service::Time
|
||||
@@ -1,16 +0,0 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/time/time.h"
|
||||
|
||||
namespace Service::Time {
|
||||
|
||||
class TIME_U final : public Module::Interface {
|
||||
public:
|
||||
explicit TIME_U(std::shared_ptr<Module> time);
|
||||
};
|
||||
|
||||
} // namespace Service::Time
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/file_util.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/string_util.h"
|
||||
#include "core/file_sys/content_archive.h"
|
||||
#include "core/gdbstub/gdbstub.h"
|
||||
#include "core/hle/kernel/process.h"
|
||||
@@ -18,34 +17,6 @@
|
||||
|
||||
namespace Loader {
|
||||
|
||||
static std::string FindRomFS(const std::string& directory) {
|
||||
std::string filepath_romfs;
|
||||
const auto callback = [&filepath_romfs](u64*, const std::string& directory,
|
||||
const std::string& virtual_name) -> bool {
|
||||
const std::string physical_name = directory + virtual_name;
|
||||
if (FileUtil::IsDirectory(physical_name)) {
|
||||
// Skip directories
|
||||
return true;
|
||||
}
|
||||
|
||||
// Verify extension
|
||||
const std::string extension = physical_name.substr(physical_name.find_last_of(".") + 1);
|
||||
if (Common::ToLower(extension) != "romfs") {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Found it - we are done
|
||||
filepath_romfs = std::move(physical_name);
|
||||
return false;
|
||||
};
|
||||
|
||||
// Search the specified directory recursively, looking for the first .romfs file, which will
|
||||
// be used for the RomFS
|
||||
FileUtil::ForeachDirectoryEntry(nullptr, directory, callback);
|
||||
|
||||
return filepath_romfs;
|
||||
}
|
||||
|
||||
AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file)
|
||||
: AppLoader(std::move(file)) {}
|
||||
|
||||
|
||||
@@ -190,7 +190,7 @@ private:
|
||||
u32 entryPoint;
|
||||
|
||||
public:
|
||||
ElfReader(void* ptr);
|
||||
explicit ElfReader(void* ptr);
|
||||
|
||||
u32 Read32(int off) const {
|
||||
return base32[off >> 2];
|
||||
|
||||
@@ -79,7 +79,7 @@ enum class ResultStatus {
|
||||
/// Interface for loading an application
|
||||
class AppLoader : NonCopyable {
|
||||
public:
|
||||
AppLoader(FileSys::VirtualFile file) : file(std::move(file)) {}
|
||||
explicit AppLoader(FileSys::VirtualFile file) : file(std::move(file)) {}
|
||||
virtual ~AppLoader() {}
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
* Recorder constructor
|
||||
* @param initial_state Initial recorder state
|
||||
*/
|
||||
Recorder(const InitialState& initial_state);
|
||||
explicit Recorder(const InitialState& initial_state);
|
||||
|
||||
/// Finish recording of this Citrace and save it using the given filename.
|
||||
void Finish(const std::string& filename);
|
||||
|
||||
@@ -75,14 +75,6 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
|
||||
ProcessMacroUpload(value);
|
||||
break;
|
||||
}
|
||||
case MAXWELL3D_REG_INDEX(code_address.code_address_high):
|
||||
case MAXWELL3D_REG_INDEX(code_address.code_address_low): {
|
||||
// Note: For some reason games (like Puyo Puyo Tetris) seem to write 0 to the CODE_ADDRESS
|
||||
// register, we do not currently know if that's intended or a bug, so we assert it lest
|
||||
// stuff breaks in other places (like the shader address calculation).
|
||||
ASSERT_MSG(regs.code_address.CodeAddress() == 0, "Unexpected CODE_ADDRESS register value.");
|
||||
break;
|
||||
}
|
||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[0]):
|
||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[1]):
|
||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[2]):
|
||||
|
||||
@@ -35,9 +35,11 @@ u32 RenderTargetBytesPerPixel(RenderTargetFormat format) {
|
||||
case RenderTargetFormat::RGBA32_FLOAT:
|
||||
return 16;
|
||||
case RenderTargetFormat::RGBA16_FLOAT:
|
||||
case RenderTargetFormat::RG32_FLOAT:
|
||||
return 8;
|
||||
case RenderTargetFormat::RGBA8_UNORM:
|
||||
case RenderTargetFormat::RGB10_A2_UNORM:
|
||||
case RenderTargetFormat::BGRA8_UNORM:
|
||||
return 4;
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Unimplemented render target format {}", static_cast<u32>(format));
|
||||
|
||||
@@ -18,10 +18,13 @@ enum class RenderTargetFormat : u32 {
|
||||
RGBA32_FLOAT = 0xC0,
|
||||
RGBA32_UINT = 0xC2,
|
||||
RGBA16_FLOAT = 0xCA,
|
||||
RG32_FLOAT = 0xCB,
|
||||
BGRA8_UNORM = 0xCF,
|
||||
RGB10_A2_UNORM = 0xD1,
|
||||
RGBA8_UNORM = 0xD5,
|
||||
RGBA8_SRGB = 0xD6,
|
||||
R11G11B10_FLOAT = 0xE0,
|
||||
R8_UNORM = 0xF3,
|
||||
};
|
||||
|
||||
enum class DepthFormat : u32 {
|
||||
@@ -31,6 +34,7 @@ enum class DepthFormat : u32 {
|
||||
Z24_X8_UNORM = 0x15,
|
||||
Z24_S8_UNORM = 0x16,
|
||||
Z24_C8_UNORM = 0x18,
|
||||
Z32_S8_X24_FLOAT = 0x19,
|
||||
};
|
||||
|
||||
/// Returns the number of bytes per pixel of each rendertarget format.
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <glad/glad.h>
|
||||
@@ -37,11 +38,6 @@ MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(100, 100, 255));
|
||||
MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Mgmt", MP_RGB(100, 255, 100));
|
||||
|
||||
RasterizerOpenGL::RasterizerOpenGL() {
|
||||
has_ARB_buffer_storage = false;
|
||||
has_ARB_direct_state_access = false;
|
||||
has_ARB_separate_shader_objects = false;
|
||||
has_ARB_vertex_attrib_binding = false;
|
||||
|
||||
// Create sampler objects
|
||||
for (size_t i = 0; i < texture_samplers.size(); ++i) {
|
||||
texture_samplers[i].Create();
|
||||
@@ -59,7 +55,8 @@ RasterizerOpenGL::RasterizerOpenGL() {
|
||||
GLint ext_num;
|
||||
glGetIntegerv(GL_NUM_EXTENSIONS, &ext_num);
|
||||
for (GLint i = 0; i < ext_num; i++) {
|
||||
std::string extension{reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, i))};
|
||||
const std::string_view extension{
|
||||
reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, i))};
|
||||
|
||||
if (extension == "GL_ARB_buffer_storage") {
|
||||
has_ARB_buffer_storage = true;
|
||||
@@ -110,8 +107,6 @@ RasterizerOpenGL::RasterizerOpenGL() {
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, index, buffer.handle);
|
||||
}
|
||||
|
||||
accelerate_draw = AccelDraw::Disabled;
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
LOG_CRITICAL(Render_OpenGL, "Sync fixed function OpenGL state here!");
|
||||
@@ -601,7 +596,6 @@ void RasterizerOpenGL::SamplerInfo::Create() {
|
||||
sampler.Create();
|
||||
mag_filter = min_filter = Tegra::Texture::TextureFilter::Linear;
|
||||
wrap_u = wrap_v = Tegra::Texture::WrapMode::Wrap;
|
||||
border_color_r = border_color_g = border_color_b = border_color_a = 0;
|
||||
|
||||
// default is GL_LINEAR_MIPMAP_LINEAR
|
||||
glSamplerParameteri(sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
@@ -630,8 +624,12 @@ void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntr
|
||||
}
|
||||
|
||||
if (wrap_u == Tegra::Texture::WrapMode::Border || wrap_v == Tegra::Texture::WrapMode::Border) {
|
||||
// TODO(Subv): Implement border color
|
||||
ASSERT(false);
|
||||
const GLvec4 new_border_color = {{config.border_color_r, config.border_color_g,
|
||||
config.border_color_b, config.border_color_a}};
|
||||
if (border_color != new_border_color) {
|
||||
border_color = new_border_color;
|
||||
glSamplerParameterfv(s, GL_TEXTURE_BORDER_COLOR, border_color.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -691,10 +689,12 @@ u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, GLuint progr
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
|
||||
// Now configure the bindpoint of the buffer inside the shader
|
||||
std::string buffer_name = used_buffer.GetName();
|
||||
GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, buffer_name.c_str());
|
||||
if (index != -1)
|
||||
const std::string buffer_name = used_buffer.GetName();
|
||||
const GLuint index =
|
||||
glGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, buffer_name.c_str());
|
||||
if (index != GL_INVALID_INDEX) {
|
||||
glUniformBlockBinding(program, index, buffer_draw_state.bindpoint);
|
||||
}
|
||||
}
|
||||
|
||||
state.Apply();
|
||||
|
||||
@@ -77,10 +77,7 @@ private:
|
||||
Tegra::Texture::TextureFilter min_filter;
|
||||
Tegra::Texture::WrapMode wrap_u;
|
||||
Tegra::Texture::WrapMode wrap_v;
|
||||
u32 border_color_r;
|
||||
u32 border_color_g;
|
||||
u32 border_color_b;
|
||||
u32 border_color_a;
|
||||
GLvec4 border_color;
|
||||
};
|
||||
|
||||
/// Configures the color and depth framebuffer states and returns the dirty <Color, Depth>
|
||||
@@ -138,10 +135,10 @@ private:
|
||||
/// Syncs the blend state to match the guest state
|
||||
void SyncBlendState();
|
||||
|
||||
bool has_ARB_buffer_storage;
|
||||
bool has_ARB_direct_state_access;
|
||||
bool has_ARB_separate_shader_objects;
|
||||
bool has_ARB_vertex_attrib_binding;
|
||||
bool has_ARB_buffer_storage = false;
|
||||
bool has_ARB_direct_state_access = false;
|
||||
bool has_ARB_separate_shader_objects = false;
|
||||
bool has_ARB_vertex_attrib_binding = false;
|
||||
|
||||
OpenGLState state;
|
||||
|
||||
@@ -170,5 +167,5 @@ private:
|
||||
void SetupShaders(u8* buffer_ptr, GLintptr buffer_offset);
|
||||
|
||||
enum class AccelDraw { Disabled, Arrays, Indexed };
|
||||
AccelDraw accelerate_draw;
|
||||
AccelDraw accelerate_draw = AccelDraw::Disabled;
|
||||
};
|
||||
|
||||
@@ -38,7 +38,8 @@ struct FormatTuple {
|
||||
params.addr = config.tic.Address();
|
||||
params.is_tiled = config.tic.IsTiled();
|
||||
params.block_height = params.is_tiled ? config.tic.BlockHeight() : 0,
|
||||
params.pixel_format = PixelFormatFromTextureFormat(config.tic.format);
|
||||
params.pixel_format =
|
||||
PixelFormatFromTextureFormat(config.tic.format, config.tic.r_type.Value());
|
||||
params.component_type = ComponentTypeFromTexture(config.tic.r_type.Value());
|
||||
params.type = GetFormatType(params.pixel_format);
|
||||
params.width = Common::AlignUp(config.tic.Width(), GetCompressionFactor(params.pixel_format));
|
||||
@@ -106,6 +107,12 @@ static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_form
|
||||
true}, // BC7U
|
||||
{GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_4X4
|
||||
{GL_RG8, GL_RG, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // G8R8
|
||||
{GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // BGRA8
|
||||
{GL_RGBA32F, GL_RGBA, GL_FLOAT, ComponentType::Float, false}, // RGBA32F
|
||||
{GL_RG32F, GL_RG, GL_FLOAT, ComponentType::Float, false}, // RG32F
|
||||
{GL_R32F, GL_RED, GL_FLOAT, ComponentType::Float, false}, // R32F
|
||||
{GL_R16F, GL_RED, GL_HALF_FLOAT, ComponentType::Float, false}, // R16F
|
||||
{GL_R16, GL_RED, GL_UNSIGNED_SHORT, ComponentType::UNorm, false}, // R16UNORM
|
||||
|
||||
// DepthStencil formats
|
||||
{GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, ComponentType::UNorm,
|
||||
@@ -115,6 +122,8 @@ static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_form
|
||||
{GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, ComponentType::Float, false}, // Z32F
|
||||
{GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, ComponentType::UNorm,
|
||||
false}, // Z16
|
||||
{GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
|
||||
ComponentType::Float, false}, // Z32FS8
|
||||
}};
|
||||
|
||||
static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) {
|
||||
@@ -197,9 +206,12 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr),
|
||||
MortonCopy<true, PixelFormat::DXT1>, MortonCopy<true, PixelFormat::DXT23>,
|
||||
MortonCopy<true, PixelFormat::DXT45>, MortonCopy<true, PixelFormat::DXN1>,
|
||||
MortonCopy<true, PixelFormat::BC7U>, MortonCopy<true, PixelFormat::ASTC_2D_4X4>,
|
||||
MortonCopy<true, PixelFormat::G8R8>, MortonCopy<true, PixelFormat::Z24S8>,
|
||||
MortonCopy<true, PixelFormat::G8R8>, MortonCopy<true, PixelFormat::BGRA8>,
|
||||
MortonCopy<true, PixelFormat::RGBA32F>, MortonCopy<true, PixelFormat::RG32F>,
|
||||
MortonCopy<true, PixelFormat::R32F>, MortonCopy<true, PixelFormat::R16F>,
|
||||
MortonCopy<true, PixelFormat::R16UNORM>, MortonCopy<true, PixelFormat::Z24S8>,
|
||||
MortonCopy<true, PixelFormat::S8Z24>, MortonCopy<true, PixelFormat::Z32F>,
|
||||
MortonCopy<true, PixelFormat::Z16>,
|
||||
MortonCopy<true, PixelFormat::Z16>, MortonCopy<true, PixelFormat::Z32FS8>,
|
||||
};
|
||||
|
||||
static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr),
|
||||
@@ -213,7 +225,7 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr),
|
||||
MortonCopy<false, PixelFormat::RGBA16F>,
|
||||
MortonCopy<false, PixelFormat::R11FG11FB10F>,
|
||||
MortonCopy<false, PixelFormat::RGBA32UI>,
|
||||
// TODO(Subv): Swizzling the DXT1/DXT23/DXT45/DXN1/BC7U formats is not yet supported
|
||||
// TODO(Subv): Swizzling DXT1/DXT23/DXT45/DXN1/BC7U/ASTC_2D_4X4 formats is not supported
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
@@ -221,10 +233,17 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr),
|
||||
nullptr,
|
||||
nullptr,
|
||||
MortonCopy<false, PixelFormat::G8R8>,
|
||||
MortonCopy<false, PixelFormat::BGRA8>,
|
||||
MortonCopy<false, PixelFormat::RGBA32F>,
|
||||
MortonCopy<false, PixelFormat::RG32F>,
|
||||
MortonCopy<false, PixelFormat::R32F>,
|
||||
MortonCopy<false, PixelFormat::R16F>,
|
||||
MortonCopy<false, PixelFormat::R16UNORM>,
|
||||
MortonCopy<false, PixelFormat::Z24S8>,
|
||||
MortonCopy<false, PixelFormat::S8Z24>,
|
||||
MortonCopy<false, PixelFormat::Z32F>,
|
||||
MortonCopy<false, PixelFormat::Z16>,
|
||||
MortonCopy<false, PixelFormat::Z32FS8>,
|
||||
};
|
||||
|
||||
// Allocate an uninitialized texture of appropriate size and format for the surface
|
||||
|
||||
@@ -37,14 +37,21 @@ struct SurfaceParams {
|
||||
BC7U = 12,
|
||||
ASTC_2D_4X4 = 13,
|
||||
G8R8 = 14,
|
||||
BGRA8 = 15,
|
||||
RGBA32F = 16,
|
||||
RG32F = 17,
|
||||
R32F = 18,
|
||||
R16F = 19,
|
||||
R16UNORM = 20,
|
||||
|
||||
MaxColorFormat,
|
||||
|
||||
// DepthStencil formats
|
||||
Z24S8 = 15,
|
||||
S8Z24 = 16,
|
||||
Z32F = 17,
|
||||
Z16 = 18,
|
||||
Z24S8 = 21,
|
||||
S8Z24 = 22,
|
||||
Z32F = 23,
|
||||
Z16 = 24,
|
||||
Z32FS8 = 25,
|
||||
|
||||
MaxDepthStencilFormat,
|
||||
|
||||
@@ -97,10 +104,17 @@ struct SurfaceParams {
|
||||
4, // BC7U
|
||||
4, // ASTC_2D_4X4
|
||||
1, // G8R8
|
||||
1, // BGRA8
|
||||
1, // RGBA32F
|
||||
1, // RG32F
|
||||
1, // R32F
|
||||
1, // R16F
|
||||
1, // R16UNORM
|
||||
1, // Z24S8
|
||||
1, // S8Z24
|
||||
1, // Z32F
|
||||
1, // Z16
|
||||
1, // Z32FS8
|
||||
}};
|
||||
|
||||
ASSERT(static_cast<size_t>(format) < compression_factor_table.size());
|
||||
@@ -127,10 +141,17 @@ struct SurfaceParams {
|
||||
128, // BC7U
|
||||
32, // ASTC_2D_4X4
|
||||
16, // G8R8
|
||||
32, // BGRA8
|
||||
128, // RGBA32F
|
||||
64, // RG32F
|
||||
32, // R32F
|
||||
16, // R16F
|
||||
16, // R16UNORM
|
||||
32, // Z24S8
|
||||
32, // S8Z24
|
||||
32, // Z32F
|
||||
16, // Z16
|
||||
64, // Z32FS8
|
||||
}};
|
||||
|
||||
ASSERT(static_cast<size_t>(format) < bpp_table.size());
|
||||
@@ -151,6 +172,8 @@ struct SurfaceParams {
|
||||
return PixelFormat::Z32F;
|
||||
case Tegra::DepthFormat::Z16_UNORM:
|
||||
return PixelFormat::Z16;
|
||||
case Tegra::DepthFormat::Z32_S8_X24_FLOAT:
|
||||
return PixelFormat::Z32FS8;
|
||||
default:
|
||||
LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
|
||||
UNREACHABLE();
|
||||
@@ -162,21 +185,30 @@ struct SurfaceParams {
|
||||
case Tegra::RenderTargetFormat::RGBA8_UNORM:
|
||||
case Tegra::RenderTargetFormat::RGBA8_SRGB:
|
||||
return PixelFormat::ABGR8;
|
||||
case Tegra::RenderTargetFormat::BGRA8_UNORM:
|
||||
return PixelFormat::BGRA8;
|
||||
case Tegra::RenderTargetFormat::RGB10_A2_UNORM:
|
||||
return PixelFormat::A2B10G10R10;
|
||||
case Tegra::RenderTargetFormat::RGBA16_FLOAT:
|
||||
return PixelFormat::RGBA16F;
|
||||
case Tegra::RenderTargetFormat::RGBA32_FLOAT:
|
||||
return PixelFormat::RGBA32F;
|
||||
case Tegra::RenderTargetFormat::RG32_FLOAT:
|
||||
return PixelFormat::RG32F;
|
||||
case Tegra::RenderTargetFormat::R11G11B10_FLOAT:
|
||||
return PixelFormat::R11FG11FB10F;
|
||||
case Tegra::RenderTargetFormat::RGBA32_UINT:
|
||||
return PixelFormat::RGBA32UI;
|
||||
case Tegra::RenderTargetFormat::R8_UNORM:
|
||||
return PixelFormat::R8;
|
||||
default:
|
||||
LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
static PixelFormat PixelFormatFromTextureFormat(Tegra::Texture::TextureFormat format) {
|
||||
static PixelFormat PixelFormatFromTextureFormat(Tegra::Texture::TextureFormat format,
|
||||
Tegra::Texture::ComponentType component_type) {
|
||||
// TODO(Subv): Properly implement this
|
||||
switch (format) {
|
||||
case Tegra::Texture::TextureFormat::A8R8G8B8:
|
||||
@@ -196,7 +228,33 @@ struct SurfaceParams {
|
||||
case Tegra::Texture::TextureFormat::BF10GF11RF11:
|
||||
return PixelFormat::R11FG11FB10F;
|
||||
case Tegra::Texture::TextureFormat::R32_G32_B32_A32:
|
||||
return PixelFormat::RGBA32UI;
|
||||
switch (component_type) {
|
||||
case Tegra::Texture::ComponentType::FLOAT:
|
||||
return PixelFormat::RGBA32F;
|
||||
case Tegra::Texture::ComponentType::UINT:
|
||||
return PixelFormat::RGBA32UI;
|
||||
}
|
||||
LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}",
|
||||
static_cast<u32>(component_type));
|
||||
UNREACHABLE();
|
||||
case Tegra::Texture::TextureFormat::R32_G32:
|
||||
return PixelFormat::RG32F;
|
||||
case Tegra::Texture::TextureFormat::R16:
|
||||
switch (component_type) {
|
||||
case Tegra::Texture::ComponentType::FLOAT:
|
||||
return PixelFormat::R16F;
|
||||
case Tegra::Texture::ComponentType::UNORM:
|
||||
return PixelFormat::R16UNORM;
|
||||
}
|
||||
LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}",
|
||||
static_cast<u32>(component_type));
|
||||
UNREACHABLE();
|
||||
case Tegra::Texture::TextureFormat::R32:
|
||||
return PixelFormat::R32F;
|
||||
case Tegra::Texture::TextureFormat::ZF32:
|
||||
return PixelFormat::Z32F;
|
||||
case Tegra::Texture::TextureFormat::Z24S8:
|
||||
return PixelFormat::Z24S8;
|
||||
case Tegra::Texture::TextureFormat::DXT1:
|
||||
return PixelFormat::DXT1;
|
||||
case Tegra::Texture::TextureFormat::DXT23:
|
||||
@@ -210,7 +268,8 @@ struct SurfaceParams {
|
||||
case Tegra::Texture::TextureFormat::ASTC_2D_4X4:
|
||||
return PixelFormat::ASTC_2D_4X4;
|
||||
default:
|
||||
LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
|
||||
LOG_CRITICAL(HW_GPU, "Unimplemented format={}, component_type={}",
|
||||
static_cast<u32>(format), static_cast<u32>(component_type));
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
@@ -248,7 +307,25 @@ struct SurfaceParams {
|
||||
return Tegra::Texture::TextureFormat::BC7U;
|
||||
case PixelFormat::ASTC_2D_4X4:
|
||||
return Tegra::Texture::TextureFormat::ASTC_2D_4X4;
|
||||
case PixelFormat::BGRA8:
|
||||
// TODO(bunnei): This is fine for unswizzling (since we just need the right component
|
||||
// sizes), but could be a bug if we used this function in different ways.
|
||||
return Tegra::Texture::TextureFormat::A8R8G8B8;
|
||||
case PixelFormat::RGBA32F:
|
||||
return Tegra::Texture::TextureFormat::R32_G32_B32_A32;
|
||||
case PixelFormat::RG32F:
|
||||
return Tegra::Texture::TextureFormat::R32_G32;
|
||||
case PixelFormat::R32F:
|
||||
return Tegra::Texture::TextureFormat::R32;
|
||||
case PixelFormat::R16F:
|
||||
case PixelFormat::R16UNORM:
|
||||
return Tegra::Texture::TextureFormat::R16;
|
||||
case PixelFormat::Z32F:
|
||||
return Tegra::Texture::TextureFormat::ZF32;
|
||||
case PixelFormat::Z24S8:
|
||||
return Tegra::Texture::TextureFormat::Z24S8;
|
||||
default:
|
||||
LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
@@ -263,7 +340,10 @@ struct SurfaceParams {
|
||||
return Tegra::DepthFormat::Z32_FLOAT;
|
||||
case PixelFormat::Z16:
|
||||
return Tegra::DepthFormat::Z16_UNORM;
|
||||
case PixelFormat::Z32FS8:
|
||||
return Tegra::DepthFormat::Z32_S8_X24_FLOAT;
|
||||
default:
|
||||
LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
@@ -273,6 +353,8 @@ struct SurfaceParams {
|
||||
switch (type) {
|
||||
case Tegra::Texture::ComponentType::UNORM:
|
||||
return ComponentType::UNorm;
|
||||
case Tegra::Texture::ComponentType::FLOAT:
|
||||
return ComponentType::Float;
|
||||
default:
|
||||
LOG_CRITICAL(HW_GPU, "Unimplemented component type={}", static_cast<u32>(type));
|
||||
UNREACHABLE();
|
||||
@@ -284,10 +366,14 @@ struct SurfaceParams {
|
||||
switch (format) {
|
||||
case Tegra::RenderTargetFormat::RGBA8_UNORM:
|
||||
case Tegra::RenderTargetFormat::RGBA8_SRGB:
|
||||
case Tegra::RenderTargetFormat::BGRA8_UNORM:
|
||||
case Tegra::RenderTargetFormat::RGB10_A2_UNORM:
|
||||
case Tegra::RenderTargetFormat::R8_UNORM:
|
||||
return ComponentType::UNorm;
|
||||
case Tegra::RenderTargetFormat::RGBA16_FLOAT:
|
||||
case Tegra::RenderTargetFormat::R11G11B10_FLOAT:
|
||||
case Tegra::RenderTargetFormat::RGBA32_FLOAT:
|
||||
case Tegra::RenderTargetFormat::RG32_FLOAT:
|
||||
return ComponentType::Float;
|
||||
case Tegra::RenderTargetFormat::RGBA32_UINT:
|
||||
return ComponentType::UInt;
|
||||
@@ -314,6 +400,7 @@ struct SurfaceParams {
|
||||
case Tegra::DepthFormat::Z24_S8_UNORM:
|
||||
return ComponentType::UNorm;
|
||||
case Tegra::DepthFormat::Z32_FLOAT:
|
||||
case Tegra::DepthFormat::Z32_S8_X24_FLOAT:
|
||||
return ComponentType::Float;
|
||||
default:
|
||||
LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
|
||||
|
||||
@@ -488,6 +488,12 @@ private:
|
||||
*/
|
||||
void SetRegister(const Register& reg, u64 elem, const std::string& value,
|
||||
u64 dest_num_components, u64 value_num_components, u64 dest_elem) {
|
||||
if (reg == Register::ZeroIndex) {
|
||||
LOG_CRITICAL(HW_GPU, "Cannot set Register::ZeroIndex");
|
||||
UNREACHABLE();
|
||||
return;
|
||||
}
|
||||
|
||||
std::string dest = GetRegister(reg, static_cast<u32>(dest_elem));
|
||||
if (dest_num_components > 1) {
|
||||
dest += GetSwizzle(elem);
|
||||
@@ -750,8 +756,8 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
std::string WriteTexsInstruction(const Instruction& instr, const std::string& coord,
|
||||
const std::string& texture) {
|
||||
void WriteTexsInstruction(const Instruction& instr, const std::string& coord,
|
||||
const std::string& texture) {
|
||||
// Add an extra scope and declare the texture coords inside to prevent
|
||||
// overwriting them in case they are used as outputs of the texs instruction.
|
||||
shader.AddLine('{');
|
||||
@@ -804,7 +810,8 @@ private:
|
||||
return offset + 1;
|
||||
}
|
||||
|
||||
shader.AddLine("// " + std::to_string(offset) + ": " + opcode->GetName());
|
||||
shader.AddLine("// " + std::to_string(offset) + ": " + opcode->GetName() + " (" +
|
||||
std::to_string(instr.value) + ')');
|
||||
|
||||
using Tegra::Shader::Pred;
|
||||
ASSERT_MSG(instr.pred.full_pred != Pred::NeverExecute,
|
||||
|
||||
@@ -56,6 +56,9 @@ inline GLenum VertexType(Maxwell::VertexAttribute attrib) {
|
||||
return {};
|
||||
}
|
||||
|
||||
case Maxwell::VertexAttribute::Type::UnsignedInt:
|
||||
return GL_UNSIGNED_INT;
|
||||
|
||||
case Maxwell::VertexAttribute::Type::Float:
|
||||
return GL_FLOAT;
|
||||
}
|
||||
@@ -112,6 +115,8 @@ inline GLenum WrapMode(Tegra::Texture::WrapMode wrap_mode) {
|
||||
return GL_MIRRORED_REPEAT;
|
||||
case Tegra::Texture::WrapMode::ClampToEdge:
|
||||
return GL_CLAMP_TO_EDGE;
|
||||
case Tegra::Texture::WrapMode::Border:
|
||||
return GL_CLAMP_TO_BORDER;
|
||||
case Tegra::Texture::WrapMode::ClampOGL:
|
||||
// TODO(Subv): GL_CLAMP was removed as of OpenGL 3.1, to implement GL_CLAMP, we can use
|
||||
// GL_CLAMP_TO_BORDER to get the border color of the texture, and then sample the edge to
|
||||
|
||||
@@ -61,10 +61,12 @@ u32 BytesPerPixel(TextureFormat format) {
|
||||
case TextureFormat::A8R8G8B8:
|
||||
case TextureFormat::A2B10G10R10:
|
||||
case TextureFormat::BF10GF11RF11:
|
||||
case TextureFormat::R32:
|
||||
return 4;
|
||||
case TextureFormat::A1B5G5R5:
|
||||
case TextureFormat::B5G6R5:
|
||||
case TextureFormat::G8R8:
|
||||
case TextureFormat::R16:
|
||||
return 2;
|
||||
case TextureFormat::R8:
|
||||
return 1;
|
||||
@@ -72,6 +74,8 @@ u32 BytesPerPixel(TextureFormat format) {
|
||||
return 8;
|
||||
case TextureFormat::R32_G32_B32_A32:
|
||||
return 16;
|
||||
case TextureFormat::R32_G32:
|
||||
return 8;
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Format not implemented");
|
||||
break;
|
||||
@@ -86,6 +90,8 @@ static u32 DepthBytesPerPixel(DepthFormat format) {
|
||||
case DepthFormat::Z24_S8_UNORM:
|
||||
case DepthFormat::Z32_FLOAT:
|
||||
return 4;
|
||||
case DepthFormat::Z32_S8_X24_FLOAT:
|
||||
return 8;
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Format not implemented");
|
||||
break;
|
||||
@@ -118,6 +124,9 @@ std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width,
|
||||
case TextureFormat::G8R8:
|
||||
case TextureFormat::R16_G16_B16_A16:
|
||||
case TextureFormat::R32_G32_B32_A32:
|
||||
case TextureFormat::R32_G32:
|
||||
case TextureFormat::R32:
|
||||
case TextureFormat::R16:
|
||||
case TextureFormat::BF10GF11RF11:
|
||||
case TextureFormat::ASTC_2D_4X4:
|
||||
CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data,
|
||||
@@ -143,6 +152,7 @@ std::vector<u8> UnswizzleDepthTexture(VAddr address, DepthFormat format, u32 wid
|
||||
case DepthFormat::S8_Z24_UNORM:
|
||||
case DepthFormat::Z24_S8_UNORM:
|
||||
case DepthFormat::Z32_FLOAT:
|
||||
case DepthFormat::Z32_S8_X24_FLOAT:
|
||||
CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data,
|
||||
unswizzled_data.data(), true, block_height);
|
||||
break;
|
||||
@@ -174,6 +184,9 @@ std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat
|
||||
case TextureFormat::G8R8:
|
||||
case TextureFormat::BF10GF11RF11:
|
||||
case TextureFormat::R32_G32_B32_A32:
|
||||
case TextureFormat::R32_G32:
|
||||
case TextureFormat::R32:
|
||||
case TextureFormat::R16:
|
||||
// TODO(Subv): For the time being just forward the same data without any decoding.
|
||||
rgba_data = texture_data;
|
||||
break;
|
||||
|
||||
@@ -242,10 +242,10 @@ struct TSCEntry {
|
||||
BitField<6, 2, TextureMipmapFilter> mip_filter;
|
||||
};
|
||||
INSERT_PADDING_BYTES(8);
|
||||
u32 border_color_r;
|
||||
u32 border_color_g;
|
||||
u32 border_color_b;
|
||||
u32 border_color_a;
|
||||
float border_color_r;
|
||||
float border_color_g;
|
||||
float border_color_b;
|
||||
float border_color_a;
|
||||
};
|
||||
static_assert(sizeof(TSCEntry) == 0x20, "TSCEntry has wrong size");
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "yuzu/debugger/wait_tree.h"
|
||||
#include "yuzu/util/util.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/kernel/event.h"
|
||||
#include "core/hle/kernel/handle_table.h"
|
||||
@@ -169,6 +170,8 @@ QString WaitTreeWaitObject::GetResetTypeQString(Kernel::ResetType reset_type) {
|
||||
case Kernel::ResetType::Pulse:
|
||||
return tr("pulse");
|
||||
}
|
||||
UNREACHABLE();
|
||||
return {};
|
||||
}
|
||||
|
||||
WaitTreeObjectList::WaitTreeObjectList(
|
||||
|
||||
Reference in New Issue
Block a user