Compare commits
101 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f9d8f20d7e | ||
|
|
f6e5fb17d7 | ||
|
|
fd53a7b0a1 | ||
|
|
d2e361533c | ||
|
|
afa72e1725 | ||
|
|
86c41aabd7 | ||
|
|
a7c8064927 | ||
|
|
ade5096f84 | ||
|
|
e1d66ea794 | ||
|
|
f1c519f2cb | ||
|
|
2a742229ee | ||
|
|
ab756fd068 | ||
|
|
abb4894188 | ||
|
|
906d785c73 | ||
|
|
0191a1e526 | ||
|
|
2128ab2d21 | ||
|
|
833ebbb626 | ||
|
|
d2749ef0ed | ||
|
|
50dadc33e3 | ||
|
|
04d144aa40 | ||
|
|
ea8dd8b650 | ||
|
|
c2c543e8f7 | ||
|
|
dc4e5f9159 | ||
|
|
e247bd577c | ||
|
|
f49248437e | ||
|
|
1121622dc1 | ||
|
|
7550c2c866 | ||
|
|
82cb5f030d | ||
|
|
ec2b7cdb1d | ||
|
|
f1fbb476df | ||
|
|
8440b814bc | ||
|
|
41d7b020a8 | ||
|
|
e4191b624c | ||
|
|
40eb243f86 | ||
|
|
e013fdc2b2 | ||
|
|
5a27f4e4cc | ||
|
|
18c2c96927 | ||
|
|
b28af1f6c9 | ||
|
|
f85cff0f48 | ||
|
|
0cd843151f | ||
|
|
6f05a57712 | ||
|
|
9d2a1c6f12 | ||
|
|
7a2acc86e6 | ||
|
|
f916611e32 | ||
|
|
8781beaf0d | ||
|
|
57cd80c410 | ||
|
|
31642ae2ee | ||
|
|
3f5dfc4d96 | ||
|
|
165e7645e1 | ||
|
|
1958d07d7d | ||
|
|
8ac52c6b56 | ||
|
|
0e05f98be2 | ||
|
|
3fb124961e | ||
|
|
91d86df920 | ||
|
|
6f4d3d8163 | ||
|
|
8650be1020 | ||
|
|
7458e71f24 | ||
|
|
821f2c03cb | ||
|
|
b0adb9a3d9 | ||
|
|
851089b482 | ||
|
|
4672a01cbf | ||
|
|
d245610939 | ||
|
|
19b5ae5a25 | ||
|
|
c88382517c | ||
|
|
f9951352f6 | ||
|
|
a2cd07d094 | ||
|
|
85ed42a1d2 | ||
|
|
c664f8a257 | ||
|
|
2474340684 | ||
|
|
4175712976 | ||
|
|
1e4935c3a0 | ||
|
|
d3fd0351a7 | ||
|
|
3c1cb3b11e | ||
|
|
657bd113e3 | ||
|
|
52cb5dcf0f | ||
|
|
5c42cadbc9 | ||
|
|
f445464baf | ||
|
|
c5b838aeef | ||
|
|
ee8123bf13 | ||
|
|
0686183c3e | ||
|
|
af787744ab | ||
|
|
704824d50a | ||
|
|
184324c2f0 | ||
|
|
abc5b3347d | ||
|
|
a6ea6febc9 | ||
|
|
e0106a7d68 | ||
|
|
f747a7e35d | ||
|
|
4f574201ea | ||
|
|
8f2c4191ab | ||
|
|
0162f8b3a7 | ||
|
|
16139ed53b | ||
|
|
b5eb3905cd | ||
|
|
bf608f125e | ||
|
|
d71e19fd75 | ||
|
|
8e8e906432 | ||
|
|
a61124a9e7 | ||
|
|
44646e2ea0 | ||
|
|
b8459d2778 | ||
|
|
9d2cacdc9e | ||
|
|
63c605c04a | ||
|
|
76f191ce36 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -11,7 +11,7 @@ src/common/scm_rev.cpp
|
||||
.idea/
|
||||
.vs/
|
||||
.vscode/
|
||||
CMakeLists.txt.user
|
||||
CMakeLists.txt.user*
|
||||
|
||||
# *nix related
|
||||
# Common convention for backup or temporary files
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -22,3 +22,6 @@
|
||||
[submodule "unicorn"]
|
||||
path = externals/unicorn
|
||||
url = https://github.com/yuzu-emu/unicorn
|
||||
[submodule "opus"]
|
||||
path = externals/opus
|
||||
url = https://github.com/ogniK5377/opus.git
|
||||
|
||||
4
externals/CMakeLists.txt
vendored
4
externals/CMakeLists.txt
vendored
@@ -50,3 +50,7 @@ if (ARCHITECTURE_x86_64)
|
||||
target_include_directories(xbyak INTERFACE ./xbyak/xbyak)
|
||||
target_compile_definitions(xbyak INTERFACE XBYAK_NO_OP_NAMES)
|
||||
endif()
|
||||
|
||||
# Opus
|
||||
add_subdirectory(opus)
|
||||
target_include_directories(opus INTERFACE ./opus/include)
|
||||
|
||||
2
externals/dynarmic
vendored
2
externals/dynarmic
vendored
Submodule externals/dynarmic updated: fc6b73bd85...98e2380129
1
externals/opus
vendored
Submodule
1
externals/opus
vendored
Submodule
Submodule externals/opus added at b2871922a1
@@ -3,6 +3,7 @@ include_directories(.)
|
||||
|
||||
add_subdirectory(common)
|
||||
add_subdirectory(core)
|
||||
add_subdirectory(audio_core)
|
||||
add_subdirectory(video_core)
|
||||
add_subdirectory(input_common)
|
||||
add_subdirectory(tests)
|
||||
|
||||
11
src/audio_core/CMakeLists.txt
Normal file
11
src/audio_core/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
add_library(audio_core STATIC
|
||||
audio_out.cpp
|
||||
audio_out.h
|
||||
buffer.h
|
||||
stream.cpp
|
||||
stream.h
|
||||
)
|
||||
|
||||
create_target_directory_groups(audio_core)
|
||||
|
||||
target_link_libraries(audio_core PUBLIC common core)
|
||||
50
src/audio_core/audio_out.cpp
Normal file
50
src/audio_core/audio_out.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
// Copyright 2018 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "audio_core/audio_out.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
|
||||
namespace AudioCore {
|
||||
|
||||
/// Returns the stream format from the specified number of channels
|
||||
static Stream::Format ChannelsToStreamFormat(int num_channels) {
|
||||
switch (num_channels) {
|
||||
case 1:
|
||||
return Stream::Format::Mono16;
|
||||
case 2:
|
||||
return Stream::Format::Stereo16;
|
||||
case 6:
|
||||
return Stream::Format::Multi51Channel16;
|
||||
}
|
||||
|
||||
LOG_CRITICAL(Audio, "Unimplemented num_channels={}", num_channels);
|
||||
UNREACHABLE();
|
||||
return {};
|
||||
}
|
||||
|
||||
StreamPtr AudioOut::OpenStream(int sample_rate, int num_channels,
|
||||
Stream::ReleaseCallback&& release_callback) {
|
||||
streams.push_back(std::make_shared<Stream>(sample_rate, ChannelsToStreamFormat(num_channels),
|
||||
std::move(release_callback)));
|
||||
return streams.back();
|
||||
}
|
||||
|
||||
std::vector<u64> AudioOut::GetTagsAndReleaseBuffers(StreamPtr stream, size_t max_count) {
|
||||
return stream->GetTagsAndReleaseBuffers(max_count);
|
||||
}
|
||||
|
||||
void AudioOut::StartStream(StreamPtr stream) {
|
||||
stream->Play();
|
||||
}
|
||||
|
||||
void AudioOut::StopStream(StreamPtr stream) {
|
||||
stream->Stop();
|
||||
}
|
||||
|
||||
bool AudioOut::QueueBuffer(StreamPtr stream, Buffer::Tag tag, std::vector<u8>&& data) {
|
||||
return stream->QueueBuffer(std::make_shared<Buffer>(tag, std::move(data)));
|
||||
}
|
||||
|
||||
} // namespace AudioCore
|
||||
44
src/audio_core/audio_out.h
Normal file
44
src/audio_core/audio_out.h
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright 2018 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "audio_core/buffer.h"
|
||||
#include "audio_core/stream.h"
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace AudioCore {
|
||||
|
||||
using StreamPtr = std::shared_ptr<Stream>;
|
||||
|
||||
/**
|
||||
* Represents an audio playback interface, used to open and play audio streams
|
||||
*/
|
||||
class AudioOut {
|
||||
public:
|
||||
/// Opens a new audio stream
|
||||
StreamPtr OpenStream(int sample_rate, int num_channels,
|
||||
Stream::ReleaseCallback&& release_callback);
|
||||
|
||||
/// Returns a vector of recently released buffers specified by tag for the specified stream
|
||||
std::vector<u64> GetTagsAndReleaseBuffers(StreamPtr stream, size_t max_count);
|
||||
|
||||
/// Starts an audio stream for playback
|
||||
void StartStream(StreamPtr stream);
|
||||
|
||||
/// Stops an audio stream that is currently playing
|
||||
void StopStream(StreamPtr stream);
|
||||
|
||||
/// Queues a buffer into the specified audio stream, returns true on success
|
||||
bool QueueBuffer(StreamPtr stream, Buffer::Tag tag, std::vector<u8>&& data);
|
||||
|
||||
private:
|
||||
/// Active audio streams on the interface
|
||||
std::vector<StreamPtr> streams;
|
||||
};
|
||||
|
||||
} // namespace AudioCore
|
||||
37
src/audio_core/buffer.h
Normal file
37
src/audio_core/buffer.h
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright 2018 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace AudioCore {
|
||||
|
||||
/**
|
||||
* Represents a buffer of audio samples to be played in an audio stream
|
||||
*/
|
||||
class Buffer {
|
||||
public:
|
||||
using Tag = u64;
|
||||
|
||||
Buffer(Tag tag, std::vector<u8>&& data) : tag{tag}, data{std::move(data)} {}
|
||||
|
||||
/// Returns the raw audio data for the buffer
|
||||
const std::vector<u8>& GetData() const {
|
||||
return data;
|
||||
}
|
||||
|
||||
/// Returns the buffer tag, this is provided by the game to the audout service
|
||||
Tag GetTag() const {
|
||||
return tag;
|
||||
}
|
||||
|
||||
private:
|
||||
Tag tag;
|
||||
std::vector<u8> data;
|
||||
};
|
||||
|
||||
} // namespace AudioCore
|
||||
103
src/audio_core/stream.cpp
Normal file
103
src/audio_core/stream.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
// Copyright 2018 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/core_timing_util.h"
|
||||
|
||||
#include "audio_core/stream.h"
|
||||
|
||||
namespace AudioCore {
|
||||
|
||||
constexpr size_t MaxAudioBufferCount{32};
|
||||
|
||||
/// Returns the sample size for the specified audio stream format
|
||||
static size_t SampleSizeFromFormat(Stream::Format format) {
|
||||
switch (format) {
|
||||
case Stream::Format::Mono16:
|
||||
return 2;
|
||||
case Stream::Format::Stereo16:
|
||||
return 4;
|
||||
case Stream::Format::Multi51Channel16:
|
||||
return 12;
|
||||
};
|
||||
|
||||
LOG_CRITICAL(Audio, "Unimplemented format={}", static_cast<u32>(format));
|
||||
UNREACHABLE();
|
||||
return {};
|
||||
}
|
||||
|
||||
Stream::Stream(int sample_rate, Format format, ReleaseCallback&& release_callback)
|
||||
: sample_rate{sample_rate}, format{format}, release_callback{std::move(release_callback)} {
|
||||
release_event = CoreTiming::RegisterEvent(
|
||||
"Stream::Release", [this](u64 userdata, int cycles_late) { ReleaseActiveBuffer(); });
|
||||
}
|
||||
|
||||
void Stream::Play() {
|
||||
state = State::Playing;
|
||||
PlayNextBuffer();
|
||||
}
|
||||
|
||||
void Stream::Stop() {
|
||||
ASSERT_MSG(false, "Unimplemented");
|
||||
}
|
||||
|
||||
s64 Stream::GetBufferReleaseCycles(const Buffer& buffer) const {
|
||||
const size_t num_samples{buffer.GetData().size() / SampleSizeFromFormat(format)};
|
||||
return CoreTiming::usToCycles((static_cast<u64>(num_samples) * 1000000) / sample_rate);
|
||||
}
|
||||
|
||||
void Stream::PlayNextBuffer() {
|
||||
if (!IsPlaying()) {
|
||||
// Ensure we are in playing state before playing the next buffer
|
||||
return;
|
||||
}
|
||||
|
||||
if (active_buffer) {
|
||||
// Do not queue a new buffer if we are already playing a buffer
|
||||
return;
|
||||
}
|
||||
|
||||
if (queued_buffers.empty()) {
|
||||
// No queued buffers - we are effectively paused
|
||||
return;
|
||||
}
|
||||
|
||||
active_buffer = queued_buffers.front();
|
||||
queued_buffers.pop();
|
||||
|
||||
CoreTiming::ScheduleEventThreadsafe(GetBufferReleaseCycles(*active_buffer), release_event, {});
|
||||
}
|
||||
|
||||
void Stream::ReleaseActiveBuffer() {
|
||||
released_buffers.push(std::move(active_buffer));
|
||||
release_callback();
|
||||
PlayNextBuffer();
|
||||
}
|
||||
|
||||
bool Stream::QueueBuffer(BufferPtr&& buffer) {
|
||||
if (queued_buffers.size() < MaxAudioBufferCount) {
|
||||
queued_buffers.push(std::move(buffer));
|
||||
PlayNextBuffer();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Stream::ContainsBuffer(Buffer::Tag tag) const {
|
||||
ASSERT_MSG(false, "Unimplemented");
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<Buffer::Tag> Stream::GetTagsAndReleaseBuffers(size_t max_count) {
|
||||
std::vector<Buffer::Tag> tags;
|
||||
for (size_t count = 0; count < max_count && !released_buffers.empty(); ++count) {
|
||||
tags.push_back(released_buffers.front()->GetTag());
|
||||
released_buffers.pop();
|
||||
}
|
||||
return tags;
|
||||
}
|
||||
|
||||
} // namespace AudioCore
|
||||
89
src/audio_core/stream.h
Normal file
89
src/audio_core/stream.h
Normal file
@@ -0,0 +1,89 @@
|
||||
// Copyright 2018 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
|
||||
#include "audio_core/buffer.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "core/core_timing.h"
|
||||
|
||||
namespace AudioCore {
|
||||
|
||||
using BufferPtr = std::shared_ptr<Buffer>;
|
||||
|
||||
/**
|
||||
* Represents an audio stream, which is a sequence of queued buffers, to be outputed by AudioOut
|
||||
*/
|
||||
class Stream {
|
||||
public:
|
||||
/// Audio format of the stream
|
||||
enum class Format {
|
||||
Mono16,
|
||||
Stereo16,
|
||||
Multi51Channel16,
|
||||
};
|
||||
|
||||
/// Callback function type, used to change guest state on a buffer being released
|
||||
using ReleaseCallback = std::function<void()>;
|
||||
|
||||
Stream(int sample_rate, Format format, ReleaseCallback&& release_callback);
|
||||
|
||||
/// Plays the audio stream
|
||||
void Play();
|
||||
|
||||
/// Stops the audio stream
|
||||
void Stop();
|
||||
|
||||
/// Queues a buffer into the audio stream, returns true on success
|
||||
bool QueueBuffer(BufferPtr&& buffer);
|
||||
|
||||
/// Returns true if the audio stream contains a buffer with the specified tag
|
||||
bool ContainsBuffer(Buffer::Tag tag) const;
|
||||
|
||||
/// Returns a vector of recently released buffers specified by tag
|
||||
std::vector<Buffer::Tag> GetTagsAndReleaseBuffers(size_t max_count);
|
||||
|
||||
/// Returns true if the stream is currently playing
|
||||
bool IsPlaying() const {
|
||||
return state == State::Playing;
|
||||
}
|
||||
|
||||
/// Returns the number of queued buffers
|
||||
size_t GetQueueSize() const {
|
||||
return queued_buffers.size();
|
||||
}
|
||||
|
||||
private:
|
||||
/// Current state of the stream
|
||||
enum class State {
|
||||
Stopped,
|
||||
Playing,
|
||||
};
|
||||
|
||||
/// Plays the next queued buffer in the audio stream, starting playback if necessary
|
||||
void PlayNextBuffer();
|
||||
|
||||
/// Releases the actively playing buffer, signalling that it has been completed
|
||||
void ReleaseActiveBuffer();
|
||||
|
||||
/// Gets the number of core cycles when the specified buffer will be released
|
||||
s64 GetBufferReleaseCycles(const Buffer& buffer) const;
|
||||
|
||||
int sample_rate; ///< Sample rate of the stream
|
||||
Format format; ///< Format of the stream
|
||||
ReleaseCallback release_callback; ///< Buffer release callback for the stream
|
||||
State state{State::Stopped}; ///< Playback state of the stream
|
||||
CoreTiming::EventType* release_event{}; ///< Core timing release event for the stream
|
||||
BufferPtr active_buffer; ///< Actively playing buffer in the stream
|
||||
std::queue<BufferPtr> queued_buffers; ///< Buffers queued to be played in the stream
|
||||
std::queue<BufferPtr> released_buffers; ///< Buffers recently released from the stream
|
||||
};
|
||||
|
||||
} // namespace AudioCore
|
||||
@@ -173,8 +173,11 @@ void FileBackend::Write(const Entry& entry) {
|
||||
SUB(Service, Friend) \
|
||||
SUB(Service, FS) \
|
||||
SUB(Service, HID) \
|
||||
SUB(Service, LBL) \
|
||||
SUB(Service, LDN) \
|
||||
SUB(Service, LM) \
|
||||
SUB(Service, MM) \
|
||||
SUB(Service, NFC) \
|
||||
SUB(Service, NFP) \
|
||||
SUB(Service, NIFM) \
|
||||
SUB(Service, NS) \
|
||||
|
||||
@@ -60,8 +60,11 @@ enum class Class : ClassType {
|
||||
Service_Friend, ///< The friend service
|
||||
Service_FS, ///< The FS (Filesystem) service
|
||||
Service_HID, ///< The HID (Human interface device) service
|
||||
Service_LBL, ///< The LBL (LCD backlight) service
|
||||
Service_LDN, ///< The LDN (Local domain network) service
|
||||
Service_LM, ///< The LM (Logger) service
|
||||
Service_MM, ///< The MM (Multimedia) service
|
||||
Service_NFC, ///< The NFC (Near-field communication) service
|
||||
Service_NFP, ///< The NFP service
|
||||
Service_NIFM, ///< The NIFM (Network interface) service
|
||||
Service_NS, ///< The NS services
|
||||
|
||||
@@ -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
|
||||
@@ -21,6 +23,8 @@ add_library(core STATIC
|
||||
file_sys/partition_filesystem.h
|
||||
file_sys/program_metadata.cpp
|
||||
file_sys/program_metadata.h
|
||||
file_sys/romfs.cpp
|
||||
file_sys/romfs.h
|
||||
file_sys/romfs_factory.cpp
|
||||
file_sys/romfs_factory.h
|
||||
file_sys/savedata_factory.cpp
|
||||
@@ -33,6 +37,8 @@ add_library(core STATIC
|
||||
file_sys/vfs_offset.h
|
||||
file_sys/vfs_real.cpp
|
||||
file_sys/vfs_real.h
|
||||
file_sys/vfs_vector.cpp
|
||||
file_sys/vfs_vector.h
|
||||
frontend/emu_window.cpp
|
||||
frontend/emu_window.h
|
||||
frontend/framebuffer_layout.cpp
|
||||
@@ -114,26 +120,34 @@ 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/btdrv/btdrv.cpp
|
||||
hle/service/btdrv/btdrv.h
|
||||
hle/service/erpt/erpt.cpp
|
||||
hle/service/erpt/erpt.h
|
||||
hle/service/es/es.cpp
|
||||
hle/service/es/es.h
|
||||
hle/service/eupld/eupld.cpp
|
||||
hle/service/eupld/eupld.h
|
||||
hle/service/fatal/fatal.cpp
|
||||
hle/service/fatal/fatal.h
|
||||
hle/service/fatal/fatal_p.cpp
|
||||
@@ -148,24 +162,34 @@ add_library(core STATIC
|
||||
hle/service/friend/friend.h
|
||||
hle/service/friend/interface.cpp
|
||||
hle/service/friend/interface.h
|
||||
hle/service/grc/grc.cpp
|
||||
hle/service/grc/grc.h
|
||||
hle/service/hid/hid.cpp
|
||||
hle/service/hid/hid.h
|
||||
hle/service/hid/irs.cpp
|
||||
hle/service/hid/irs.h
|
||||
hle/service/hid/xcd.cpp
|
||||
hle/service/hid/xcd.h
|
||||
hle/service/lbl/lbl.cpp
|
||||
hle/service/lbl/lbl.h
|
||||
hle/service/ldn/ldn.cpp
|
||||
hle/service/ldn/ldn.h
|
||||
hle/service/ldr/ldr.cpp
|
||||
hle/service/ldr/ldr.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/nfc/nfc.cpp
|
||||
hle/service/nfc/nfc.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/nim/nim.cpp
|
||||
hle/service/nim/nim.h
|
||||
hle/service/ns/ns.cpp
|
||||
hle/service/ns/ns.h
|
||||
hle/service/ns/pl_u.cpp
|
||||
@@ -199,6 +223,8 @@ add_library(core STATIC
|
||||
hle/service/pctl/module.h
|
||||
hle/service/pctl/pctl.cpp
|
||||
hle/service/pctl/pctl.h
|
||||
hle/service/pm/pm.cpp
|
||||
hle/service/pm/pm.h
|
||||
hle/service/prepo/prepo.cpp
|
||||
hle/service/prepo/prepo.h
|
||||
hle/service/service.cpp
|
||||
@@ -219,6 +245,8 @@ add_library(core STATIC
|
||||
hle/service/sm/sm.h
|
||||
hle/service/sockets/bsd.cpp
|
||||
hle/service/sockets/bsd.h
|
||||
hle/service/sockets/ethc.cpp
|
||||
hle/service/sockets/ethc.h
|
||||
hle/service/sockets/nsd.cpp
|
||||
hle/service/sockets/nsd.h
|
||||
hle/service/sockets/sfdnsres.cpp
|
||||
@@ -233,12 +261,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
|
||||
@@ -283,8 +309,8 @@ add_library(core STATIC
|
||||
|
||||
create_target_directory_groups(core)
|
||||
|
||||
target_link_libraries(core PUBLIC common PRIVATE video_core)
|
||||
target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt lz4_static unicorn)
|
||||
target_link_libraries(core PUBLIC common PRIVATE audio_core video_core)
|
||||
target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt lz4_static opus unicorn)
|
||||
|
||||
if (ARCHITECTURE_x86_64)
|
||||
target_sources(core PRIVATE
|
||||
|
||||
@@ -177,6 +177,7 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
|
||||
}
|
||||
|
||||
gpu_core = std::make_unique<Tegra::GPU>();
|
||||
audio_core = std::make_unique<AudioCore::AudioOut>();
|
||||
telemetry_session = std::make_unique<Core::TelemetrySession>();
|
||||
service_manager = std::make_shared<Service::SM::ServiceManager>();
|
||||
|
||||
@@ -228,6 +229,7 @@ void System::Shutdown() {
|
||||
service_manager.reset();
|
||||
telemetry_session.reset();
|
||||
gpu_core.reset();
|
||||
audio_core.reset();
|
||||
|
||||
// Close all CPU/threading state
|
||||
cpu_barrier->NotifyEnd();
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include "audio_core/audio_out.h"
|
||||
#include "common/common_types.h"
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/core_cpu.h"
|
||||
@@ -131,6 +132,11 @@ public:
|
||||
return *gpu_core;
|
||||
}
|
||||
|
||||
/// Gets the AudioCore interface
|
||||
AudioCore::AudioOut& AudioCore() {
|
||||
return *audio_core;
|
||||
}
|
||||
|
||||
/// Gets the scheduler for the CPU core that is currently running
|
||||
Kernel::Scheduler& CurrentScheduler() {
|
||||
return *CurrentCpuCore().Scheduler();
|
||||
@@ -195,6 +201,7 @@ private:
|
||||
/// AppLoader used to load the current executing application
|
||||
std::unique_ptr<Loader::AppLoader> app_loader;
|
||||
std::unique_ptr<Tegra::GPU> gpu_core;
|
||||
std::unique_ptr<AudioCore::AudioOut> audio_core;
|
||||
std::shared_ptr<Tegra::DebugContext> debug_context;
|
||||
Kernel::SharedPtr<Kernel::Process> current_process;
|
||||
std::shared_ptr<ExclusiveMonitor> cpu_exclusive_monitor;
|
||||
|
||||
@@ -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
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "core/file_sys/content_archive.h"
|
||||
#include "core/file_sys/vfs_offset.h"
|
||||
#include "core/loader/loader.h"
|
||||
#include "romfs.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
@@ -46,21 +47,9 @@ struct PFS0Superblock {
|
||||
};
|
||||
static_assert(sizeof(PFS0Superblock) == 0x200, "PFS0Superblock has incorrect size.");
|
||||
|
||||
struct IVFCLevel {
|
||||
u64_le offset;
|
||||
u64_le size;
|
||||
u32_le block_size;
|
||||
u32_le reserved;
|
||||
};
|
||||
static_assert(sizeof(IVFCLevel) == 0x18, "IVFCLevel has incorrect size.");
|
||||
|
||||
struct RomFSSuperblock {
|
||||
NCASectionHeaderBlock header_block;
|
||||
u32_le magic;
|
||||
u32_le magic_number;
|
||||
INSERT_PADDING_BYTES(8);
|
||||
std::array<IVFCLevel, 6> levels;
|
||||
INSERT_PADDING_BYTES(64);
|
||||
IVFCHeader ivfc;
|
||||
};
|
||||
static_assert(sizeof(RomFSSuperblock) == 0xE8, "RomFSSuperblock has incorrect size.");
|
||||
|
||||
@@ -92,8 +81,8 @@ NCA::NCA(VirtualFile file_) : file(std::move(file_)) {
|
||||
|
||||
const size_t romfs_offset =
|
||||
header.section_tables[i].media_offset * MEDIA_OFFSET_MULTIPLIER +
|
||||
sb.levels[IVFC_MAX_LEVEL - 1].offset;
|
||||
const size_t romfs_size = sb.levels[IVFC_MAX_LEVEL - 1].size;
|
||||
sb.ivfc.levels[IVFC_MAX_LEVEL - 1].offset;
|
||||
const size_t romfs_size = sb.ivfc.levels[IVFC_MAX_LEVEL - 1].size;
|
||||
files.emplace_back(std::make_shared<OffsetVfsFile>(file, romfs_size, romfs_offset));
|
||||
romfs = files.back();
|
||||
} else if (block.filesystem_type == NCASectionFilesystemType::PFS0) {
|
||||
|
||||
124
src/core/file_sys/romfs.cpp
Normal file
124
src/core/file_sys/romfs.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "common/swap.h"
|
||||
#include "core/file_sys/romfs.h"
|
||||
#include "core/file_sys/vfs.h"
|
||||
#include "core/file_sys/vfs_offset.h"
|
||||
#include "core/file_sys/vfs_vector.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
constexpr u32 ROMFS_ENTRY_EMPTY = 0xFFFFFFFF;
|
||||
|
||||
struct TableLocation {
|
||||
u64_le offset;
|
||||
u64_le size;
|
||||
};
|
||||
static_assert(sizeof(TableLocation) == 0x10, "TableLocation has incorrect size.");
|
||||
|
||||
struct RomFSHeader {
|
||||
u64_le header_size;
|
||||
TableLocation directory_hash;
|
||||
TableLocation directory_meta;
|
||||
TableLocation file_hash;
|
||||
TableLocation file_meta;
|
||||
u64_le data_offset;
|
||||
};
|
||||
static_assert(sizeof(RomFSHeader) == 0x50, "RomFSHeader has incorrect size.");
|
||||
|
||||
struct DirectoryEntry {
|
||||
u32_le sibling;
|
||||
u32_le child_dir;
|
||||
u32_le child_file;
|
||||
u32_le hash;
|
||||
u32_le name_length;
|
||||
};
|
||||
static_assert(sizeof(DirectoryEntry) == 0x14, "DirectoryEntry has incorrect size.");
|
||||
|
||||
struct FileEntry {
|
||||
u32_le parent;
|
||||
u32_le sibling;
|
||||
u64_le offset;
|
||||
u64_le size;
|
||||
u32_le hash;
|
||||
u32_le name_length;
|
||||
};
|
||||
static_assert(sizeof(FileEntry) == 0x20, "FileEntry has incorrect size.");
|
||||
|
||||
template <typename Entry>
|
||||
static std::pair<Entry, std::string> GetEntry(const VirtualFile& file, size_t offset) {
|
||||
Entry entry{};
|
||||
if (file->ReadObject(&entry, offset) != sizeof(Entry))
|
||||
return {};
|
||||
std::string string(entry.name_length, '\0');
|
||||
if (file->ReadArray(&string[0], string.size(), offset + sizeof(Entry)) != string.size())
|
||||
return {};
|
||||
return {entry, string};
|
||||
}
|
||||
|
||||
void ProcessFile(VirtualFile file, size_t file_offset, size_t data_offset, u32 this_file_offset,
|
||||
std::shared_ptr<VectorVfsDirectory> parent) {
|
||||
while (true) {
|
||||
auto entry = GetEntry<FileEntry>(file, file_offset + this_file_offset);
|
||||
|
||||
parent->AddFile(std::make_shared<OffsetVfsFile>(
|
||||
file, entry.first.size, entry.first.offset + data_offset, entry.second, parent));
|
||||
|
||||
if (entry.first.sibling == ROMFS_ENTRY_EMPTY)
|
||||
break;
|
||||
|
||||
this_file_offset = entry.first.sibling;
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessDirectory(VirtualFile file, size_t dir_offset, size_t file_offset, size_t data_offset,
|
||||
u32 this_dir_offset, std::shared_ptr<VectorVfsDirectory> parent) {
|
||||
while (true) {
|
||||
auto entry = GetEntry<DirectoryEntry>(file, dir_offset + this_dir_offset);
|
||||
auto current = std::make_shared<VectorVfsDirectory>(
|
||||
std::vector<VirtualFile>{}, std::vector<VirtualDir>{}, parent, entry.second);
|
||||
|
||||
if (entry.first.child_file != ROMFS_ENTRY_EMPTY) {
|
||||
ProcessFile(file, file_offset, data_offset, entry.first.child_file, current);
|
||||
}
|
||||
|
||||
if (entry.first.child_dir != ROMFS_ENTRY_EMPTY) {
|
||||
ProcessDirectory(file, dir_offset, file_offset, data_offset, entry.first.child_dir,
|
||||
current);
|
||||
}
|
||||
|
||||
parent->AddDirectory(current);
|
||||
if (entry.first.sibling == ROMFS_ENTRY_EMPTY)
|
||||
break;
|
||||
this_dir_offset = entry.first.sibling;
|
||||
}
|
||||
}
|
||||
|
||||
VirtualDir ExtractRomFS(VirtualFile file) {
|
||||
RomFSHeader header{};
|
||||
if (file->ReadObject(&header) != sizeof(RomFSHeader))
|
||||
return nullptr;
|
||||
|
||||
if (header.header_size != sizeof(RomFSHeader))
|
||||
return nullptr;
|
||||
|
||||
const u64 file_offset = header.file_meta.offset;
|
||||
const u64 dir_offset = header.directory_meta.offset + 4;
|
||||
|
||||
const auto root =
|
||||
std::make_shared<VectorVfsDirectory>(std::vector<VirtualFile>{}, std::vector<VirtualDir>{},
|
||||
file->GetContainingDirectory(), file->GetName());
|
||||
|
||||
ProcessDirectory(file, dir_offset, file_offset, header.data_offset, 0, root);
|
||||
|
||||
VirtualDir out = std::move(root);
|
||||
|
||||
while (out->GetSubdirectory("") != nullptr)
|
||||
out = out->GetSubdirectory("");
|
||||
|
||||
return out;
|
||||
}
|
||||
} // namespace FileSys
|
||||
35
src/core/file_sys/romfs.h
Normal file
35
src/core/file_sys/romfs.h
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/swap.h"
|
||||
#include "core/file_sys/vfs.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
struct IVFCLevel {
|
||||
u64_le offset;
|
||||
u64_le size;
|
||||
u32_le block_size;
|
||||
u32_le reserved;
|
||||
};
|
||||
static_assert(sizeof(IVFCLevel) == 0x18, "IVFCLevel has incorrect size.");
|
||||
|
||||
struct IVFCHeader {
|
||||
u32_le magic;
|
||||
u32_le magic_number;
|
||||
INSERT_PADDING_BYTES(8);
|
||||
std::array<IVFCLevel, 6> levels;
|
||||
INSERT_PADDING_BYTES(64);
|
||||
};
|
||||
static_assert(sizeof(IVFCHeader) == 0xE0, "IVFCHeader has incorrect size.");
|
||||
|
||||
// Converts a RomFS binary blob to VFS Filesystem
|
||||
// Returns nullptr on failure
|
||||
VirtualDir ExtractRomFS(VirtualFile file);
|
||||
|
||||
} // namespace FileSys
|
||||
@@ -46,6 +46,13 @@ size_t VfsFile::WriteBytes(const std::vector<u8>& data, size_t offset) {
|
||||
return Write(data.data(), data.size(), offset);
|
||||
}
|
||||
|
||||
std::string VfsFile::GetFullPath() const {
|
||||
if (GetContainingDirectory() == nullptr)
|
||||
return "/" + GetName();
|
||||
|
||||
return GetContainingDirectory()->GetFullPath() + "/" + GetName();
|
||||
}
|
||||
|
||||
std::shared_ptr<VfsFile> VfsDirectory::GetFileRelative(std::string_view path) const {
|
||||
auto vec = FileUtil::SplitPathComponents(path);
|
||||
vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }),
|
||||
@@ -243,6 +250,13 @@ bool VfsDirectory::Copy(std::string_view src, std::string_view dest) {
|
||||
return f2->WriteBytes(f1->ReadAllBytes()) == f1->GetSize();
|
||||
}
|
||||
|
||||
std::string VfsDirectory::GetFullPath() const {
|
||||
if (IsRoot())
|
||||
return GetName();
|
||||
|
||||
return GetParentDirectory()->GetFullPath() + "/" + GetName();
|
||||
}
|
||||
|
||||
bool ReadOnlyVfsDirectory::IsWritable() const {
|
||||
return false;
|
||||
}
|
||||
@@ -270,4 +284,13 @@ bool ReadOnlyVfsDirectory::DeleteFile(std::string_view name) {
|
||||
bool ReadOnlyVfsDirectory::Rename(std::string_view name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VfsRawCopy(VirtualFile src, VirtualFile dest) {
|
||||
if (src == nullptr || dest == nullptr)
|
||||
return false;
|
||||
if (!dest->Resize(src->GetSize()))
|
||||
return false;
|
||||
std::vector<u8> data = src->ReadAllBytes();
|
||||
return dest->WriteBytes(data, 0) == data.size();
|
||||
}
|
||||
} // namespace FileSys
|
||||
|
||||
@@ -113,6 +113,9 @@ struct VfsFile : NonCopyable {
|
||||
|
||||
// Renames the file to name. Returns whether or not the operation was successsful.
|
||||
virtual bool Rename(std::string_view name) = 0;
|
||||
|
||||
// Returns the full path of this file as a string, recursively
|
||||
virtual std::string GetFullPath() const;
|
||||
};
|
||||
|
||||
// A class representing a directory in an abstract filesystem.
|
||||
@@ -213,6 +216,17 @@ struct VfsDirectory : NonCopyable {
|
||||
return ReplaceFileWithSubdirectory(file_p, std::make_shared<Directory>(file_p));
|
||||
}
|
||||
|
||||
bool InterpretAsDirectory(const std::function<VirtualDir(VirtualFile)>& function,
|
||||
const std::string& file) {
|
||||
auto file_p = GetFile(file);
|
||||
if (file_p == nullptr)
|
||||
return false;
|
||||
return ReplaceFileWithSubdirectory(file_p, function(file_p));
|
||||
}
|
||||
|
||||
// Returns the full path of this directory as a string, recursively
|
||||
virtual std::string GetFullPath() const;
|
||||
|
||||
protected:
|
||||
// Backend for InterpretAsDirectory.
|
||||
// Removes all references to file and adds a reference to dir in the directory's implementation.
|
||||
@@ -230,4 +244,10 @@ struct ReadOnlyVfsDirectory : public VfsDirectory {
|
||||
bool DeleteFile(std::string_view name) override;
|
||||
bool Rename(std::string_view name) override;
|
||||
};
|
||||
|
||||
// A method that copies the raw data between two different implementations of VirtualFile. If you
|
||||
// are using the same implementation, it is probably better to use the Copy method in the parent
|
||||
// directory of src/dest.
|
||||
bool VfsRawCopy(VirtualFile src, VirtualFile dest);
|
||||
|
||||
} // namespace FileSys
|
||||
|
||||
@@ -10,8 +10,9 @@
|
||||
namespace FileSys {
|
||||
|
||||
OffsetVfsFile::OffsetVfsFile(std::shared_ptr<VfsFile> file_, size_t size_, size_t offset_,
|
||||
std::string name_)
|
||||
: file(std::move(file_)), offset(offset_), size(size_), name(std::move(name_)) {}
|
||||
std::string name_, VirtualDir parent_)
|
||||
: file(file_), offset(offset_), size(size_), name(std::move(name_)),
|
||||
parent(parent_ == nullptr ? file->GetContainingDirectory() : std::move(parent_)) {}
|
||||
|
||||
std::string OffsetVfsFile::GetName() const {
|
||||
return name.empty() ? file->GetName() : name;
|
||||
@@ -35,7 +36,7 @@ bool OffsetVfsFile::Resize(size_t new_size) {
|
||||
}
|
||||
|
||||
std::shared_ptr<VfsDirectory> OffsetVfsFile::GetContainingDirectory() const {
|
||||
return file->GetContainingDirectory();
|
||||
return parent;
|
||||
}
|
||||
|
||||
bool OffsetVfsFile::IsWritable() const {
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace FileSys {
|
||||
// the size of this wrapper.
|
||||
struct OffsetVfsFile : public VfsFile {
|
||||
OffsetVfsFile(std::shared_ptr<VfsFile> file, size_t size, size_t offset = 0,
|
||||
std::string new_name = "");
|
||||
std::string new_name = "", VirtualDir new_parent = nullptr);
|
||||
|
||||
std::string GetName() const override;
|
||||
size_t GetSize() const override;
|
||||
@@ -44,6 +44,7 @@ private:
|
||||
size_t offset;
|
||||
size_t size;
|
||||
std::string name;
|
||||
VirtualDir parent;
|
||||
};
|
||||
|
||||
} // namespace FileSys
|
||||
|
||||
@@ -195,6 +195,12 @@ bool RealVfsDirectory::Rename(std::string_view name) {
|
||||
return FileUtil::Rename(path, new_name);
|
||||
}
|
||||
|
||||
std::string RealVfsDirectory::GetFullPath() const {
|
||||
auto out = path;
|
||||
std::replace(out.begin(), out.end(), '\\', '/');
|
||||
return out;
|
||||
}
|
||||
|
||||
bool RealVfsDirectory::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
|
||||
const auto iter = std::find(files.begin(), files.end(), file);
|
||||
if (iter == files.end())
|
||||
|
||||
@@ -41,7 +41,7 @@ private:
|
||||
|
||||
// An implementation of VfsDirectory that represents a directory on the user's computer.
|
||||
struct RealVfsDirectory : public VfsDirectory {
|
||||
RealVfsDirectory(const std::string& path, Mode perms);
|
||||
RealVfsDirectory(const std::string& path, Mode perms = Mode::Read);
|
||||
|
||||
std::vector<std::shared_ptr<VfsFile>> GetFiles() const override;
|
||||
std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const override;
|
||||
@@ -54,6 +54,7 @@ struct RealVfsDirectory : public VfsDirectory {
|
||||
bool DeleteSubdirectory(std::string_view name) override;
|
||||
bool DeleteFile(std::string_view name) override;
|
||||
bool Rename(std::string_view name) override;
|
||||
std::string GetFullPath() const override;
|
||||
|
||||
protected:
|
||||
bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
|
||||
|
||||
83
src/core/file_sys/vfs_vector.cpp
Normal file
83
src/core/file_sys/vfs_vector.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include "core/file_sys/vfs_vector.h"
|
||||
|
||||
namespace FileSys {
|
||||
VectorVfsDirectory::VectorVfsDirectory(std::vector<VirtualFile> files_,
|
||||
std::vector<VirtualDir> dirs_, VirtualDir parent_,
|
||||
std::string name_)
|
||||
: files(std::move(files_)), dirs(std::move(dirs_)), parent(std::move(parent_)),
|
||||
name(std::move(name_)) {}
|
||||
|
||||
std::vector<std::shared_ptr<VfsFile>> VectorVfsDirectory::GetFiles() const {
|
||||
return files;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<VfsDirectory>> VectorVfsDirectory::GetSubdirectories() const {
|
||||
return dirs;
|
||||
}
|
||||
|
||||
bool VectorVfsDirectory::IsWritable() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VectorVfsDirectory::IsReadable() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string VectorVfsDirectory::GetName() const {
|
||||
return name;
|
||||
}
|
||||
std::shared_ptr<VfsDirectory> VectorVfsDirectory::GetParentDirectory() const {
|
||||
return parent;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static bool FindAndRemoveVectorElement(std::vector<T>& vec, std::string_view name) {
|
||||
auto iter = std::find_if(vec.begin(), vec.end(), [name](T e) { return e->GetName() == name; });
|
||||
if (iter == vec.end())
|
||||
return false;
|
||||
auto old_size = vec.size();
|
||||
vec.erase(iter);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VectorVfsDirectory::DeleteSubdirectory(std::string_view name) {
|
||||
return FindAndRemoveVectorElement(dirs, name);
|
||||
}
|
||||
|
||||
bool VectorVfsDirectory::DeleteFile(std::string_view name) {
|
||||
return FindAndRemoveVectorElement(files, name);
|
||||
}
|
||||
|
||||
bool VectorVfsDirectory::Rename(std::string_view name_) {
|
||||
name = name_;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<VfsDirectory> VectorVfsDirectory::CreateSubdirectory(std::string_view name) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<VfsFile> VectorVfsDirectory::CreateFile(std::string_view name) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void VectorVfsDirectory::AddFile(VirtualFile file) {
|
||||
files.push_back(std::move(file));
|
||||
}
|
||||
|
||||
void VectorVfsDirectory::AddDirectory(VirtualDir dir) {
|
||||
dirs.push_back(std::move(dir));
|
||||
}
|
||||
|
||||
bool VectorVfsDirectory::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
|
||||
if (!DeleteFile(file->GetName()))
|
||||
return false;
|
||||
dirs.emplace_back(dir);
|
||||
return true;
|
||||
}
|
||||
} // namespace FileSys
|
||||
44
src/core/file_sys/vfs_vector.h
Normal file
44
src/core/file_sys/vfs_vector.h
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/file_sys/vfs.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
// An implementation of VfsDirectory that maintains two vectors for subdirectories and files.
|
||||
// Vector data is supplied upon construction.
|
||||
struct VectorVfsDirectory : public VfsDirectory {
|
||||
explicit VectorVfsDirectory(std::vector<VirtualFile> files = {},
|
||||
std::vector<VirtualDir> dirs = {}, VirtualDir parent = nullptr,
|
||||
std::string name = "");
|
||||
|
||||
std::vector<std::shared_ptr<VfsFile>> GetFiles() const override;
|
||||
std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const override;
|
||||
bool IsWritable() const override;
|
||||
bool IsReadable() const override;
|
||||
std::string GetName() const override;
|
||||
std::shared_ptr<VfsDirectory> GetParentDirectory() const override;
|
||||
bool DeleteSubdirectory(std::string_view name) override;
|
||||
bool DeleteFile(std::string_view name) override;
|
||||
bool Rename(std::string_view name) override;
|
||||
std::shared_ptr<VfsDirectory> CreateSubdirectory(std::string_view name) override;
|
||||
std::shared_ptr<VfsFile> CreateFile(std::string_view name) override;
|
||||
|
||||
virtual void AddFile(VirtualFile file);
|
||||
virtual void AddDirectory(VirtualDir dir);
|
||||
|
||||
protected:
|
||||
bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
|
||||
|
||||
private:
|
||||
std::vector<VirtualFile> files;
|
||||
std::vector<VirtualDir> dirs;
|
||||
|
||||
VirtualDir parent;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
} // namespace FileSys
|
||||
@@ -300,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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -32,13 +32,17 @@ public:
|
||||
return HANDLE_TYPE;
|
||||
}
|
||||
|
||||
ResetType reset_type; ///< The ResetType of this timer
|
||||
ResetType GetResetType() const {
|
||||
return reset_type;
|
||||
}
|
||||
|
||||
bool signaled; ///< Whether the timer has been signaled or not
|
||||
std::string name; ///< Name of timer (optional)
|
||||
u64 GetInitialDelay() const {
|
||||
return initial_delay;
|
||||
}
|
||||
|
||||
u64 initial_delay; ///< The delay until the timer fires for the first time
|
||||
u64 interval_delay; ///< The delay until the timer fires after the first time
|
||||
u64 GetIntervalDelay() const {
|
||||
return interval_delay;
|
||||
}
|
||||
|
||||
bool ShouldWait(Thread* thread) const override;
|
||||
void Acquire(Thread* thread) override;
|
||||
@@ -67,6 +71,14 @@ private:
|
||||
Timer();
|
||||
~Timer() override;
|
||||
|
||||
ResetType reset_type; ///< The ResetType of this timer
|
||||
|
||||
u64 initial_delay; ///< The delay until the timer fires for the first time
|
||||
u64 interval_delay; ///< The delay until the timer fires after the first time
|
||||
|
||||
bool signaled; ///< Whether the timer has been signaled or not
|
||||
std::string name; ///< Name of timer (optional)
|
||||
|
||||
/// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
|
||||
Handle callback_handle;
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/event.h"
|
||||
#include "core/hle/kernel/hle_ipc.h"
|
||||
@@ -13,17 +13,22 @@
|
||||
|
||||
namespace Service::Audio {
|
||||
|
||||
/// Switch sample rate frequency
|
||||
constexpr u32 sample_rate{48000};
|
||||
/// TODO(st4rk): dynamic number of channels, as I think Switch has support
|
||||
/// to more audio channels (probably when Docked I guess)
|
||||
constexpr u32 audio_channels{2};
|
||||
/// TODO(st4rk): find a proper value for the audio_ticks
|
||||
constexpr u64 audio_ticks{static_cast<u64>(CoreTiming::BASE_CLOCK_RATE / 500)};
|
||||
namespace ErrCodes {
|
||||
enum {
|
||||
ErrorUnknown = 2,
|
||||
BufferCountExceeded = 8,
|
||||
};
|
||||
}
|
||||
|
||||
constexpr std::array<char, 10> DefaultDevice{{"DeviceOut"}};
|
||||
constexpr int DefaultSampleRate{48000};
|
||||
|
||||
class IAudioOut final : public ServiceFramework<IAudioOut> {
|
||||
public:
|
||||
IAudioOut() : ServiceFramework("IAudioOut"), audio_out_state(AudioState::Stopped) {
|
||||
IAudioOut(AudoutParams audio_params)
|
||||
: ServiceFramework("IAudioOut"), audio_params(audio_params),
|
||||
audio_core(Core::System::GetInstance().AudioCore()) {
|
||||
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &IAudioOut::GetAudioOutState, "GetAudioOutState"},
|
||||
{1, &IAudioOut::StartAudioOut, "StartAudioOut"},
|
||||
@@ -31,66 +36,65 @@ public:
|
||||
{3, &IAudioOut::AppendAudioOutBufferImpl, "AppendAudioOutBuffer"},
|
||||
{4, &IAudioOut::RegisterBufferEvent, "RegisterBufferEvent"},
|
||||
{5, &IAudioOut::GetReleasedAudioOutBufferImpl, "GetReleasedAudioOutBuffer"},
|
||||
{6, nullptr, "ContainsAudioOutBuffer"},
|
||||
{6, &IAudioOut::ContainsAudioOutBuffer, "ContainsAudioOutBuffer"},
|
||||
{7, &IAudioOut::AppendAudioOutBufferImpl, "AppendAudioOutBufferAuto"},
|
||||
{8, &IAudioOut::GetReleasedAudioOutBufferImpl, "GetReleasedAudioOutBufferAuto"},
|
||||
{9, nullptr, "GetAudioOutBufferCount"},
|
||||
{9, &IAudioOut::GetAudioOutBufferCount, "GetAudioOutBufferCount"},
|
||||
{10, nullptr, "GetAudioOutPlayedSampleCount"},
|
||||
{11, nullptr, "FlushAudioOutBuffers"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
|
||||
// This is the event handle used to check if the audio buffer was released
|
||||
buffer_event =
|
||||
Kernel::Event::Create(Kernel::ResetType::OneShot, "IAudioOutBufferReleasedEvent");
|
||||
buffer_event = Kernel::Event::Create(Kernel::ResetType::Sticky, "IAudioOutBufferReleased");
|
||||
|
||||
// Register event callback to update the Audio Buffer
|
||||
audio_event = CoreTiming::RegisterEvent(
|
||||
"IAudioOut::UpdateAudioBuffersCallback", [this](u64 userdata, int cycles_late) {
|
||||
UpdateAudioBuffersCallback();
|
||||
CoreTiming::ScheduleEvent(audio_ticks - cycles_late, audio_event);
|
||||
});
|
||||
|
||||
// Start the audio event
|
||||
CoreTiming::ScheduleEvent(audio_ticks, audio_event);
|
||||
}
|
||||
|
||||
~IAudioOut() {
|
||||
CoreTiming::UnscheduleEvent(audio_event, 0);
|
||||
stream = audio_core.OpenStream(audio_params.sample_rate, audio_params.channel_count,
|
||||
[=]() { buffer_event->Signal(); });
|
||||
}
|
||||
|
||||
private:
|
||||
struct AudioBuffer {
|
||||
u64_le next;
|
||||
u64_le buffer;
|
||||
u64_le buffer_capacity;
|
||||
u64_le buffer_size;
|
||||
u64_le offset;
|
||||
};
|
||||
static_assert(sizeof(AudioBuffer) == 0x28, "AudioBuffer is an invalid size");
|
||||
|
||||
void GetAudioOutState(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Audio, "called");
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push(static_cast<u32>(audio_out_state));
|
||||
rb.Push(static_cast<u32>(stream->IsPlaying() ? AudioState::Started : AudioState::Stopped));
|
||||
}
|
||||
|
||||
void StartAudioOut(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_Audio, "(STUBBED) called");
|
||||
LOG_DEBUG(Service_Audio, "called");
|
||||
|
||||
// Start audio
|
||||
audio_out_state = AudioState::Started;
|
||||
if (stream->IsPlaying()) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultCode(ErrorModule::Audio, ErrCodes::ErrorUnknown));
|
||||
return;
|
||||
}
|
||||
|
||||
audio_core.StartStream(stream);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void StopAudioOut(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_Audio, "(STUBBED) called");
|
||||
LOG_DEBUG(Service_Audio, "called");
|
||||
|
||||
// Stop audio
|
||||
audio_out_state = AudioState::Stopped;
|
||||
|
||||
queue_keys.clear();
|
||||
audio_core.StopStream(stream);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void RegisterBufferEvent(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_Audio, "(STUBBED) called");
|
||||
LOG_DEBUG(Service_Audio, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
@@ -98,101 +102,107 @@ private:
|
||||
}
|
||||
|
||||
void AppendAudioOutBufferImpl(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_Audio, "(STUBBED) called");
|
||||
LOG_DEBUG(Service_Audio, "(STUBBED) called {}", ctx.Description());
|
||||
IPC::RequestParser rp{ctx};
|
||||
|
||||
const u64 key{rp.Pop<u64>()};
|
||||
queue_keys.insert(queue_keys.begin(), key);
|
||||
const auto& input_buffer{ctx.ReadBuffer()};
|
||||
ASSERT_MSG(input_buffer.size() == sizeof(AudioBuffer),
|
||||
"AudioBuffer input is an invalid size!");
|
||||
AudioBuffer audio_buffer{};
|
||||
std::memcpy(&audio_buffer, input_buffer.data(), sizeof(AudioBuffer));
|
||||
const u64 tag{rp.Pop<u64>()};
|
||||
|
||||
std::vector<u8> data(audio_buffer.buffer_size);
|
||||
Memory::ReadBlock(audio_buffer.buffer, data.data(), data.size());
|
||||
|
||||
if (!audio_core.QueueBuffer(stream, tag, std::move(data))) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultCode(ErrorModule::Audio, ErrCodes::BufferCountExceeded));
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void GetReleasedAudioOutBufferImpl(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_Audio, "(STUBBED) called");
|
||||
LOG_DEBUG(Service_Audio, "called {}", ctx.Description());
|
||||
IPC::RequestParser rp{ctx};
|
||||
const u64 max_count{ctx.GetWriteBufferSize() / sizeof(u64)};
|
||||
const auto released_buffers{audio_core.GetTagsAndReleaseBuffers(stream, max_count)};
|
||||
|
||||
// TODO(st4rk): This is how libtransistor currently implements the
|
||||
// GetReleasedAudioOutBuffer, it should return the key (a VAddr) to the app and this address
|
||||
// is used to know which buffer should be filled with data and send again to the service
|
||||
// through AppendAudioOutBuffer. Check if this is the proper way to do it.
|
||||
u64 key{0};
|
||||
|
||||
if (queue_keys.size()) {
|
||||
key = queue_keys.back();
|
||||
queue_keys.pop_back();
|
||||
}
|
||||
|
||||
ctx.WriteBuffer(&key, sizeof(u64));
|
||||
std::vector<u64> tags{released_buffers};
|
||||
tags.resize(max_count);
|
||||
ctx.WriteBuffer(tags);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
// TODO(st4rk): This might be the total of released buffers, needs to be verified on
|
||||
// hardware
|
||||
rb.Push<u32>(static_cast<u32>(queue_keys.size()));
|
||||
rb.Push<u32>(static_cast<u32>(released_buffers.size()));
|
||||
}
|
||||
|
||||
void UpdateAudioBuffersCallback() {
|
||||
if (audio_out_state != AudioState::Started) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (queue_keys.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
buffer_event->Signal();
|
||||
void ContainsAudioOutBuffer(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Audio, "called");
|
||||
IPC::RequestParser rp{ctx};
|
||||
const u64 tag{rp.Pop<u64>()};
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push(stream->ContainsBuffer(tag));
|
||||
}
|
||||
|
||||
enum class AudioState : u32 {
|
||||
Started,
|
||||
Stopped,
|
||||
};
|
||||
void GetAudioOutBufferCount(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Audio, "called");
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push(static_cast<u32>(stream->GetQueueSize()));
|
||||
}
|
||||
|
||||
/// This is used to trigger the audio event callback that is going to read the samples from the
|
||||
/// audio_buffer list and enqueue the samples using the sink (audio_core).
|
||||
CoreTiming::EventType* audio_event;
|
||||
AudioCore::AudioOut& audio_core;
|
||||
AudioCore::StreamPtr stream;
|
||||
|
||||
AudoutParams audio_params{};
|
||||
|
||||
/// This is the evend handle used to check if the audio buffer was released
|
||||
Kernel::SharedPtr<Kernel::Event> buffer_event;
|
||||
|
||||
/// (st4rk): This is just a temporary workaround for the future implementation. Libtransistor
|
||||
/// uses the key as an address in the App, so we need to return when the
|
||||
/// GetReleasedAudioOutBuffer_1 is called, otherwise we'll run in problems, because
|
||||
/// libtransistor uses the key returned as an pointer.
|
||||
std::vector<u64> queue_keys;
|
||||
|
||||
AudioState audio_out_state;
|
||||
};
|
||||
|
||||
void AudOutU::ListAudioOutsImpl(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_Audio, "(STUBBED) called");
|
||||
LOG_DEBUG(Service_Audio, "called");
|
||||
IPC::RequestParser rp{ctx};
|
||||
|
||||
constexpr std::array<char, 15> audio_interface{{"AudioInterface"}};
|
||||
ctx.WriteBuffer(audio_interface);
|
||||
ctx.WriteBuffer(DefaultDevice);
|
||||
|
||||
IPC::ResponseBuilder rb = rp.MakeBuilder(3, 0, 0);
|
||||
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
// TODO(st4rk): We're currently returning only one audio interface (stringlist size). However,
|
||||
// it's highly possible to have more than one interface (despite that libtransistor requires
|
||||
// only one).
|
||||
rb.Push<u32>(1);
|
||||
rb.Push<u32>(1); // Amount of audio devices
|
||||
}
|
||||
|
||||
void AudOutU::OpenAudioOutImpl(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_Audio, "(STUBBED) called");
|
||||
LOG_DEBUG(Service_Audio, "called");
|
||||
|
||||
if (!audio_out_interface) {
|
||||
audio_out_interface = std::make_shared<IAudioOut>();
|
||||
ctx.WriteBuffer(DefaultDevice);
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto params{rp.PopRaw<AudoutParams>()};
|
||||
if (params.channel_count <= 2) {
|
||||
// Mono does not exist for audout
|
||||
params.channel_count = 2;
|
||||
} else {
|
||||
params.channel_count = 6;
|
||||
}
|
||||
if (!params.sample_rate) {
|
||||
params.sample_rate = DefaultSampleRate;
|
||||
}
|
||||
|
||||
// TODO(bunnei): Support more than one IAudioOut interface. When we add this, ListAudioOutsImpl
|
||||
// will likely need to be updated as well.
|
||||
ASSERT_MSG(!audio_out_interface, "Unimplemented");
|
||||
audio_out_interface = std::make_shared<IAudioOut>(std::move(params));
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 6, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u32>(sample_rate);
|
||||
rb.Push<u32>(audio_channels);
|
||||
rb.Push<u32>(DefaultSampleRate);
|
||||
rb.Push<u32>(params.channel_count);
|
||||
rb.Push<u32>(static_cast<u32>(PcmFormat::Int16));
|
||||
rb.Push<u32>(0); // This field is unknown
|
||||
rb.Push<u32>(static_cast<u32>(AudioState::Stopped));
|
||||
rb.PushIpcInterface<Audio::IAudioOut>(audio_out_interface);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,18 @@ class HLERequestContext;
|
||||
|
||||
namespace Service::Audio {
|
||||
|
||||
struct AudoutParams {
|
||||
s32_le sample_rate;
|
||||
u16_le channel_count;
|
||||
INSERT_PADDING_BYTES(2);
|
||||
};
|
||||
static_assert(sizeof(AudoutParams) == 0x8, "AudoutParams is an invalid size");
|
||||
|
||||
enum class AudioState : u32 {
|
||||
Started,
|
||||
Stopped,
|
||||
};
|
||||
|
||||
class IAudioOut;
|
||||
|
||||
class AudOutU final : public ServiceFramework<AudOutU> {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cstring>
|
||||
#include <opus.h>
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/hle_ipc.h"
|
||||
@@ -9,19 +11,142 @@
|
||||
|
||||
namespace Service::Audio {
|
||||
|
||||
struct OpusDeleter {
|
||||
void operator()(void* ptr) const {
|
||||
operator delete(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> {
|
||||
public:
|
||||
IHardwareOpusDecoderManager(std::unique_ptr<OpusDecoder, OpusDeleter> decoder, u32 sample_rate,
|
||||
u32 channel_count)
|
||||
: ServiceFramework("IHardwareOpusDecoderManager"), decoder(std::move(decoder)),
|
||||
sample_rate(sample_rate), channel_count(channel_count) {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleaved"},
|
||||
{1, nullptr, "SetContext"},
|
||||
{2, nullptr, "DecodeInterleavedForMultiStream"},
|
||||
{3, nullptr, "SetContextForMultiStream"},
|
||||
{4, nullptr, "Unknown4"},
|
||||
{5, nullptr, "Unknown5"},
|
||||
{6, nullptr, "Unknown6"},
|
||||
{7, nullptr, "Unknown7"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
private:
|
||||
void DecodeInterleaved(Kernel::HLERequestContext& ctx) {
|
||||
u32 consumed = 0;
|
||||
u32 sample_count = 0;
|
||||
std::vector<opus_int16> samples(ctx.GetWriteBufferSize() / sizeof(opus_int16));
|
||||
if (!Decoder_DecodeInterleaved(consumed, sample_count, ctx.ReadBuffer(), samples)) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
// TODO(ogniK): Use correct error code
|
||||
rb.Push(ResultCode(-1));
|
||||
return;
|
||||
}
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u32>(consumed);
|
||||
rb.Push<u32>(sample_count);
|
||||
ctx.WriteBuffer(samples.data(), samples.size() * sizeof(s16));
|
||||
}
|
||||
|
||||
bool Decoder_DecodeInterleaved(u32& consumed, u32& sample_count, const std::vector<u8>& input,
|
||||
std::vector<opus_int16>& output) {
|
||||
size_t raw_output_sz = output.size() * sizeof(opus_int16);
|
||||
if (sizeof(OpusHeader) > input.size())
|
||||
return false;
|
||||
OpusHeader hdr{};
|
||||
std::memcpy(&hdr, input.data(), sizeof(OpusHeader));
|
||||
if (sizeof(OpusHeader) + static_cast<u32>(hdr.sz) > input.size()) {
|
||||
return false;
|
||||
}
|
||||
auto frame = input.data() + sizeof(OpusHeader);
|
||||
auto decoded_sample_count = opus_packet_get_nb_samples(
|
||||
frame, static_cast<opus_int32>(input.size() - sizeof(OpusHeader)),
|
||||
static_cast<opus_int32>(sample_rate));
|
||||
if (decoded_sample_count * channel_count * sizeof(u16) > raw_output_sz)
|
||||
return false;
|
||||
auto out_sample_count =
|
||||
opus_decode(decoder.get(), frame, hdr.sz, output.data(),
|
||||
(static_cast<int>(raw_output_sz / sizeof(s16) / channel_count)), 0);
|
||||
if (out_sample_count < 0)
|
||||
return false;
|
||||
sample_count = out_sample_count;
|
||||
consumed = static_cast<u32>(sizeof(OpusHeader) + hdr.sz);
|
||||
return true;
|
||||
}
|
||||
|
||||
struct OpusHeader {
|
||||
u32_be sz; // Needs to be BE for some odd reason
|
||||
INSERT_PADDING_WORDS(1);
|
||||
};
|
||||
static_assert(sizeof(OpusHeader) == 0x8, "OpusHeader is an invalid size");
|
||||
|
||||
std::unique_ptr<OpusDecoder, OpusDeleter> decoder;
|
||||
u32 sample_rate;
|
||||
u32 channel_count;
|
||||
};
|
||||
|
||||
static size_t WorkerBufferSize(u32 channel_count) {
|
||||
ASSERT_MSG(channel_count == 1 || channel_count == 2, "Invalid channel count");
|
||||
return opus_decoder_get_size(static_cast<int>(channel_count));
|
||||
}
|
||||
|
||||
void HwOpus::GetWorkBufferSize(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_Audio, "(STUBBED) called");
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto sample_rate = rp.Pop<u32>();
|
||||
auto channel_count = rp.Pop<u32>();
|
||||
ASSERT_MSG(sample_rate == 48000 || sample_rate == 24000 || sample_rate == 16000 ||
|
||||
sample_rate == 12000 || sample_rate == 8000,
|
||||
"Invalid sample rate");
|
||||
ASSERT_MSG(channel_count == 1 || channel_count == 2, "Invalid channel count");
|
||||
u32 worker_buffer_sz = static_cast<u32>(WorkerBufferSize(channel_count));
|
||||
LOG_DEBUG(Audio, "called worker_buffer_sz={}", worker_buffer_sz);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u32>(0x4000);
|
||||
rb.Push<u32>(worker_buffer_sz);
|
||||
}
|
||||
|
||||
void HwOpus::OpenOpusDecoder(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto sample_rate = rp.Pop<u32>();
|
||||
auto channel_count = rp.Pop<u32>();
|
||||
auto buffer_sz = rp.Pop<u32>();
|
||||
LOG_DEBUG(Audio, "called sample_rate={}, channel_count={}, buffer_size={}", sample_rate,
|
||||
channel_count, buffer_sz);
|
||||
ASSERT_MSG(sample_rate == 48000 || sample_rate == 24000 || sample_rate == 16000 ||
|
||||
sample_rate == 12000 || sample_rate == 8000,
|
||||
"Invalid sample rate");
|
||||
ASSERT_MSG(channel_count == 1 || channel_count == 2, "Invalid channel count");
|
||||
|
||||
size_t worker_sz = WorkerBufferSize(channel_count);
|
||||
ASSERT_MSG(buffer_sz < worker_sz, "Worker buffer too large");
|
||||
std::unique_ptr<OpusDecoder, OpusDeleter> decoder{
|
||||
static_cast<OpusDecoder*>(operator new(worker_sz))};
|
||||
if (opus_decoder_init(decoder.get(), sample_rate, channel_count)) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
// TODO(ogniK): Use correct error code
|
||||
rb.Push(ResultCode(-1));
|
||||
return;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<IHardwareOpusDecoderManager>(std::move(decoder), sample_rate,
|
||||
channel_count);
|
||||
}
|
||||
|
||||
HwOpus::HwOpus() : ServiceFramework("hwopus") {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "Initialize"},
|
||||
{0, &HwOpus::OpenOpusDecoder, "OpenOpusDecoder"},
|
||||
{1, &HwOpus::GetWorkBufferSize, "GetWorkBufferSize"},
|
||||
{2, nullptr, "InitializeMultiStream"},
|
||||
{3, nullptr, "GetWorkBufferSizeMultiStream"},
|
||||
{2, nullptr, "OpenOpusDecoderForMultiStream"},
|
||||
{3, nullptr, "GetWorkBufferSizeForMultiStream"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ public:
|
||||
~HwOpus() = default;
|
||||
|
||||
private:
|
||||
void OpenOpusDecoder(Kernel::HLERequestContext& ctx);
|
||||
void GetWorkBufferSize(Kernel::HLERequestContext& ctx);
|
||||
};
|
||||
|
||||
|
||||
72
src/core/hle/service/btdrv/btdrv.cpp
Normal file
72
src/core/hle/service/btdrv/btdrv.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/service/btdrv/btdrv.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
|
||||
namespace Service::BtDrv {
|
||||
|
||||
class BtDrv final : public ServiceFramework<BtDrv> {
|
||||
public:
|
||||
explicit BtDrv() : ServiceFramework{"btdrv"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "Unknown"},
|
||||
{1, nullptr, "Init"},
|
||||
{2, nullptr, "Enable"},
|
||||
{3, nullptr, "Disable"},
|
||||
{4, nullptr, "CleanupAndShutdown"},
|
||||
{5, nullptr, "GetAdapterProperties"},
|
||||
{6, nullptr, "GetAdapterProperty"},
|
||||
{7, nullptr, "SetAdapterProperty"},
|
||||
{8, nullptr, "StartDiscovery"},
|
||||
{9, nullptr, "CancelDiscovery"},
|
||||
{10, nullptr, "CreateBond"},
|
||||
{11, nullptr, "RemoveBond"},
|
||||
{12, nullptr, "CancelBond"},
|
||||
{13, nullptr, "PinReply"},
|
||||
{14, nullptr, "SspReply"},
|
||||
{15, nullptr, "Unknown2"},
|
||||
{16, nullptr, "InitInterfaces"},
|
||||
{17, nullptr, "HidHostInterface_Connect"},
|
||||
{18, nullptr, "HidHostInterface_Disconnect"},
|
||||
{19, nullptr, "HidHostInterface_SendData"},
|
||||
{20, nullptr, "HidHostInterface_SendData2"},
|
||||
{21, nullptr, "HidHostInterface_SetReport"},
|
||||
{22, nullptr, "HidHostInterface_GetReport"},
|
||||
{23, nullptr, "HidHostInterface_WakeController"},
|
||||
{24, nullptr, "HidHostInterface_AddPairedDevice"},
|
||||
{25, nullptr, "HidHostInterface_GetPairedDevice"},
|
||||
{26, nullptr, "HidHostInterface_CleanupAndShutdown"},
|
||||
{27, nullptr, "Unknown3"},
|
||||
{28, nullptr, "ExtInterface_SetTSI"},
|
||||
{29, nullptr, "ExtInterface_SetBurstMode"},
|
||||
{30, nullptr, "ExtInterface_SetZeroRetran"},
|
||||
{31, nullptr, "ExtInterface_SetMcMode"},
|
||||
{32, nullptr, "ExtInterface_StartLlrMode"},
|
||||
{33, nullptr, "ExtInterface_ExitLlrMode"},
|
||||
{34, nullptr, "ExtInterface_SetRadio"},
|
||||
{35, nullptr, "ExtInterface_SetVisibility"},
|
||||
{36, nullptr, "Unknown4"},
|
||||
{37, nullptr, "Unknown5"},
|
||||
{38, nullptr, "HidHostInterface_GetLatestPlr"},
|
||||
{39, nullptr, "ExtInterface_GetPendingConnections"},
|
||||
{40, nullptr, "HidHostInterface_GetChannelMap"},
|
||||
{41, nullptr, "SetIsBluetoothBoostEnabled"},
|
||||
{42, nullptr, "GetIsBluetoothBoostEnabled"},
|
||||
{43, nullptr, "SetIsBluetoothAfhEnabled"},
|
||||
{44, nullptr, "GetIsBluetoothAfhEnabled"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& sm) {
|
||||
std::make_shared<BtDrv>()->InstallAsService(sm);
|
||||
}
|
||||
|
||||
} // namespace Service::BtDrv
|
||||
16
src/core/hle/service/btdrv/btdrv.h
Normal file
16
src/core/hle/service/btdrv/btdrv.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Service::SM {
|
||||
class ServiceManager;
|
||||
}
|
||||
|
||||
namespace Service::BtDrv {
|
||||
|
||||
/// Registers all BtDrv services with the specified service manager.
|
||||
void InstallInterfaces(SM::ServiceManager& sm);
|
||||
|
||||
} // namespace Service::BtDrv
|
||||
51
src/core/hle/service/erpt/erpt.cpp
Normal file
51
src/core/hle/service/erpt/erpt.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "core/hle/service/erpt/erpt.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
|
||||
namespace Service::ERPT {
|
||||
|
||||
class ErrorReportContext final : public ServiceFramework<ErrorReportContext> {
|
||||
public:
|
||||
explicit ErrorReportContext() : ServiceFramework{"erpt:c"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "SubmitContext"},
|
||||
{1, nullptr, "CreateReport"},
|
||||
{2, nullptr, "Unknown1"},
|
||||
{3, nullptr, "Unknown2"},
|
||||
{4, nullptr, "Unknown3"},
|
||||
{5, nullptr, "Unknown4"},
|
||||
{6, nullptr, "Unknown5"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class ErrorReportSession final : public ServiceFramework<ErrorReportSession> {
|
||||
public:
|
||||
explicit ErrorReportSession() : ServiceFramework{"erpt:r"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "OpenReport"},
|
||||
{1, nullptr, "OpenManager"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& sm) {
|
||||
std::make_shared<ErrorReportContext>()->InstallAsService(sm);
|
||||
std::make_shared<ErrorReportSession>()->InstallAsService(sm);
|
||||
}
|
||||
|
||||
} // namespace Service::ERPT
|
||||
16
src/core/hle/service/erpt/erpt.h
Normal file
16
src/core/hle/service/erpt/erpt.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Service::SM {
|
||||
class ServiceManager;
|
||||
}
|
||||
|
||||
namespace Service::ERPT {
|
||||
|
||||
/// Registers all ERPT services with the specified service manager.
|
||||
void InstallInterfaces(SM::ServiceManager& sm);
|
||||
|
||||
} // namespace Service::ERPT
|
||||
57
src/core/hle/service/es/es.cpp
Normal file
57
src/core/hle/service/es/es.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::ES {
|
||||
|
||||
class ETicket final : public ServiceFramework<ETicket> {
|
||||
public:
|
||||
explicit ETicket() : ServiceFramework{"es"} {
|
||||
static const FunctionInfo functions[] = {
|
||||
{1, nullptr, "ImportTicket"},
|
||||
{2, nullptr, "ImportTicketCertificateSet"},
|
||||
{3, nullptr, "DeleteTicket"},
|
||||
{4, nullptr, "DeletePersonalizedTicket"},
|
||||
{5, nullptr, "DeleteAllCommonTicket"},
|
||||
{6, nullptr, "DeleteAllPersonalizedTicket"},
|
||||
{7, nullptr, "DeleteAllPersonalizedTicketEx"},
|
||||
{8, nullptr, "GetTitleKey"},
|
||||
{9, nullptr, "CountCommonTicket"},
|
||||
{10, nullptr, "CountPersonalizedTicket"},
|
||||
{11, nullptr, "ListCommonTicket"},
|
||||
{12, nullptr, "ListPersonalizedTicket"},
|
||||
{13, nullptr, "ListMissingPersonalizedTicket"},
|
||||
{14, nullptr, "GetCommonTicketSize"},
|
||||
{15, nullptr, "GetPersonalizedTicketSize"},
|
||||
{16, nullptr, "GetCommonTicketData"},
|
||||
{17, nullptr, "GetPersonalizedTicketData"},
|
||||
{18, nullptr, "OwnTicket"},
|
||||
{19, nullptr, "GetTicketInfo"},
|
||||
{20, nullptr, "ListLightTicketInfo"},
|
||||
{21, nullptr, "SignData"},
|
||||
{22, nullptr, "GetCommonTicketAndCertificateSize"},
|
||||
{23, nullptr, "GetCommonTicketAndCertificateData"},
|
||||
{24, nullptr, "ImportPrepurchaseRecord"},
|
||||
{25, nullptr, "DeletePrepurchaseRecord"},
|
||||
{26, nullptr, "DeleteAllPrepurchaseRecord"},
|
||||
{27, nullptr, "CountPrepurchaseRecord"},
|
||||
{28, nullptr, "ListPrepurchaseRecord"},
|
||||
{29, nullptr, "ListPrepurchaseRecordInfo"},
|
||||
{30, nullptr, "Unknown1"},
|
||||
{31, nullptr, "Unknown2"},
|
||||
{32, nullptr, "Unknown3"},
|
||||
{33, nullptr, "Unknown4"},
|
||||
{34, nullptr, "Unknown5"},
|
||||
{35, nullptr, "Unknown6"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager) {
|
||||
std::make_shared<ETicket>()->InstallAsService(service_manager);
|
||||
}
|
||||
|
||||
} // namespace Service::ES
|
||||
16
src/core/hle/service/es/es.h
Normal file
16
src/core/hle/service/es/es.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Service::SM {
|
||||
class ServiceManager;
|
||||
}
|
||||
|
||||
namespace Service::ES {
|
||||
|
||||
/// Registers all ES services with the specified service manager.
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager);
|
||||
|
||||
} // namespace Service::ES
|
||||
52
src/core/hle/service/eupld/eupld.cpp
Normal file
52
src/core/hle/service/eupld/eupld.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "core/hle/service/eupld/eupld.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
|
||||
namespace Service::EUPLD {
|
||||
|
||||
class ErrorUploadContext final : public ServiceFramework<ErrorUploadContext> {
|
||||
public:
|
||||
explicit ErrorUploadContext() : ServiceFramework{"eupld:c"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "SetUrl"},
|
||||
{1, nullptr, "ImportCrt"},
|
||||
{2, nullptr, "ImportPki"},
|
||||
{3, nullptr, "SetAutoUpload"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class ErrorUploadRequest final : public ServiceFramework<ErrorUploadRequest> {
|
||||
public:
|
||||
explicit ErrorUploadRequest() : ServiceFramework{"eupld:r"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "Initialize"},
|
||||
{1, nullptr, "UploadAll"},
|
||||
{2, nullptr, "UploadSelected"},
|
||||
{3, nullptr, "GetUploadStatus"},
|
||||
{4, nullptr, "CancelUpload"},
|
||||
{5, nullptr, "GetResult"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& sm) {
|
||||
std::make_shared<ErrorUploadContext>()->InstallAsService(sm);
|
||||
std::make_shared<ErrorUploadRequest>()->InstallAsService(sm);
|
||||
}
|
||||
|
||||
} // namespace Service::EUPLD
|
||||
16
src/core/hle/service/eupld/eupld.h
Normal file
16
src/core/hle/service/eupld/eupld.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Service::SM {
|
||||
class ServiceManager;
|
||||
}
|
||||
|
||||
namespace Service::EUPLD {
|
||||
|
||||
/// Registers all EUPLD services with the specified service manager.
|
||||
void InstallInterfaces(SM::ServiceManager& sm);
|
||||
|
||||
} // namespace Service::EUPLD
|
||||
31
src/core/hle/service/grc/grc.cpp
Normal file
31
src/core/hle/service/grc/grc.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "core/hle/service/grc/grc.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
|
||||
namespace Service::GRC {
|
||||
|
||||
class GRC final : public ServiceFramework<GRC> {
|
||||
public:
|
||||
explicit GRC() : ServiceFramework{"grc:c"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{1, nullptr, "OpenContinuousRecorder"},
|
||||
{2, nullptr, "OpenGameMovieTrimmer"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& sm) {
|
||||
std::make_shared<GRC>()->InstallAsService(sm);
|
||||
}
|
||||
|
||||
} // namespace Service::GRC
|
||||
15
src/core/hle/service/grc/grc.h
Normal file
15
src/core/hle/service/grc/grc.h
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Service::SM {
|
||||
class ServiceManager;
|
||||
}
|
||||
|
||||
namespace Service::GRC {
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& sm);
|
||||
|
||||
} // namespace Service::GRC
|
||||
@@ -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"
|
||||
@@ -13,6 +14,8 @@
|
||||
#include "core/hle/kernel/event.h"
|
||||
#include "core/hle/kernel/shared_memory.h"
|
||||
#include "core/hle/service/hid/hid.h"
|
||||
#include "core/hle/service/hid/irs.h"
|
||||
#include "core/hle/service/hid/xcd.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::HID {
|
||||
@@ -554,10 +557,233 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
class HidDbg final : public ServiceFramework<HidDbg> {
|
||||
public:
|
||||
explicit HidDbg() : ServiceFramework{"hid:dbg"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "DeactivateDebugPad"},
|
||||
{1, nullptr, "SetDebugPadAutoPilotState"},
|
||||
{2, nullptr, "UnsetDebugPadAutoPilotState"},
|
||||
{10, nullptr, "DeactivateTouchScreen"},
|
||||
{11, nullptr, "SetTouchScreenAutoPilotState"},
|
||||
{12, nullptr, "UnsetTouchScreenAutoPilotState"},
|
||||
{20, nullptr, "DeactivateMouse"},
|
||||
{21, nullptr, "SetMouseAutoPilotState"},
|
||||
{22, nullptr, "UnsetMouseAutoPilotState"},
|
||||
{30, nullptr, "DeactivateKeyboard"},
|
||||
{31, nullptr, "SetKeyboardAutoPilotState"},
|
||||
{32, nullptr, "UnsetKeyboardAutoPilotState"},
|
||||
{50, nullptr, "DeactivateXpad"},
|
||||
{51, nullptr, "SetXpadAutoPilotState"},
|
||||
{52, nullptr, "UnsetXpadAutoPilotState"},
|
||||
{60, nullptr, "DeactivateJoyXpad"},
|
||||
{91, nullptr, "DeactivateGesture"},
|
||||
{110, nullptr, "DeactivateHomeButton"},
|
||||
{111, nullptr, "SetHomeButtonAutoPilotState"},
|
||||
{112, nullptr, "UnsetHomeButtonAutoPilotState"},
|
||||
{120, nullptr, "DeactivateSleepButton"},
|
||||
{121, nullptr, "SetSleepButtonAutoPilotState"},
|
||||
{122, nullptr, "UnsetSleepButtonAutoPilotState"},
|
||||
{123, nullptr, "DeactivateInputDetector"},
|
||||
{130, nullptr, "DeactivateCaptureButton"},
|
||||
{131, nullptr, "SetCaptureButtonAutoPilotState"},
|
||||
{132, nullptr, "UnsetCaptureButtonAutoPilotState"},
|
||||
{133, nullptr, "SetShiftAccelerometerCalibrationValue"},
|
||||
{134, nullptr, "GetShiftAccelerometerCalibrationValue"},
|
||||
{135, nullptr, "SetShiftGyroscopeCalibrationValue"},
|
||||
{136, nullptr, "GetShiftGyroscopeCalibrationValue"},
|
||||
{140, nullptr, "DeactivateConsoleSixAxisSensor"},
|
||||
{141, nullptr, "GetConsoleSixAxisSensorSamplingFrequency"},
|
||||
{142, nullptr, "DeactivateSevenSixAxisSensor"},
|
||||
{201, nullptr, "ActivateFirmwareUpdate"},
|
||||
{202, nullptr, "DeactivateFirmwareUpdate"},
|
||||
{203, nullptr, "StartFirmwareUpdate"},
|
||||
{204, nullptr, "GetFirmwareUpdateStage"},
|
||||
{205, nullptr, "GetFirmwareVersion"},
|
||||
{206, nullptr, "GetDestinationFirmwareVersion"},
|
||||
{207, nullptr, "DiscardFirmwareInfoCacheForRevert"},
|
||||
{208, nullptr, "StartFirmwareUpdateForRevert"},
|
||||
{209, nullptr, "GetAvailableFirmwareVersionForRevert"},
|
||||
{210, nullptr, "IsFirmwareUpdatingDevice"},
|
||||
{221, nullptr, "UpdateControllerColor"},
|
||||
{222, nullptr, "ConnectUsbPadsAsync"},
|
||||
{223, nullptr, "DisconnectUsbPadsAsync"},
|
||||
{224, nullptr, "UpdateDesignInfo"},
|
||||
{225, nullptr, "GetUniquePadDriverState"},
|
||||
{226, nullptr, "GetSixAxisSensorDriverStates"},
|
||||
{301, nullptr, "GetAbstractedPadHandles"},
|
||||
{302, nullptr, "GetAbstractedPadState"},
|
||||
{303, nullptr, "GetAbstractedPadsState"},
|
||||
{321, nullptr, "SetAutoPilotVirtualPadState"},
|
||||
{322, nullptr, "UnsetAutoPilotVirtualPadState"},
|
||||
{323, nullptr, "UnsetAllAutoPilotVirtualPadState"},
|
||||
{350, nullptr, "AddRegisteredDevice"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class HidSys final : public ServiceFramework<HidSys> {
|
||||
public:
|
||||
explicit HidSys() : ServiceFramework{"hid:sys"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{31, nullptr, "SendKeyboardLockKeyEvent"},
|
||||
{101, nullptr, "AcquireHomeButtonEventHandle"},
|
||||
{111, nullptr, "ActivateHomeButton"},
|
||||
{121, nullptr, "AcquireSleepButtonEventHandle"},
|
||||
{131, nullptr, "ActivateSleepButton"},
|
||||
{141, nullptr, "AcquireCaptureButtonEventHandle"},
|
||||
{151, nullptr, "ActivateCaptureButton"},
|
||||
{210, nullptr, "AcquireNfcDeviceUpdateEventHandle"},
|
||||
{211, nullptr, "GetNpadsWithNfc"},
|
||||
{212, nullptr, "AcquireNfcActivateEventHandle"},
|
||||
{213, nullptr, "ActivateNfc"},
|
||||
{214, nullptr, "GetXcdHandleForNpadWithNfc"},
|
||||
{215, nullptr, "IsNfcActivated"},
|
||||
{230, nullptr, "AcquireIrSensorEventHandle"},
|
||||
{231, nullptr, "ActivateIrSensor"},
|
||||
{301, nullptr, "ActivateNpadSystem"},
|
||||
{303, nullptr, "ApplyNpadSystemCommonPolicy"},
|
||||
{304, nullptr, "EnableAssigningSingleOnSlSrPress"},
|
||||
{305, nullptr, "DisableAssigningSingleOnSlSrPress"},
|
||||
{306, nullptr, "GetLastActiveNpad"},
|
||||
{307, nullptr, "GetNpadSystemExtStyle"},
|
||||
{308, nullptr, "ApplyNpadSystemCommonPolicyFull"},
|
||||
{309, nullptr, "GetNpadFullKeyGripColor"},
|
||||
{311, nullptr, "SetNpadPlayerLedBlinkingDevice"},
|
||||
{321, nullptr, "GetUniquePadsFromNpad"},
|
||||
{322, nullptr, "GetIrSensorState"},
|
||||
{323, nullptr, "GetXcdHandleForNpadWithIrSensor"},
|
||||
{500, nullptr, "SetAppletResourceUserId"},
|
||||
{501, nullptr, "RegisterAppletResourceUserId"},
|
||||
{502, nullptr, "UnregisterAppletResourceUserId"},
|
||||
{503, nullptr, "EnableAppletToGetInput"},
|
||||
{504, nullptr, "SetAruidValidForVibration"},
|
||||
{505, nullptr, "EnableAppletToGetSixAxisSensor"},
|
||||
{510, nullptr, "SetVibrationMasterVolume"},
|
||||
{511, nullptr, "GetVibrationMasterVolume"},
|
||||
{512, nullptr, "BeginPermitVibrationSession"},
|
||||
{513, nullptr, "EndPermitVibrationSession"},
|
||||
{520, nullptr, "EnableHandheldHids"},
|
||||
{521, nullptr, "DisableHandheldHids"},
|
||||
{540, nullptr, "AcquirePlayReportControllerUsageUpdateEvent"},
|
||||
{541, nullptr, "GetPlayReportControllerUsages"},
|
||||
{542, nullptr, "AcquirePlayReportRegisteredDeviceUpdateEvent"},
|
||||
{543, nullptr, "GetRegisteredDevicesOld"},
|
||||
{544, nullptr, "AcquireConnectionTriggerTimeoutEvent"},
|
||||
{545, nullptr, "SendConnectionTrigger"},
|
||||
{546, nullptr, "AcquireDeviceRegisteredEventForControllerSupport"},
|
||||
{547, nullptr, "GetAllowedBluetoothLinksCount"},
|
||||
{548, nullptr, "GetRegisteredDevices"},
|
||||
{700, nullptr, "ActivateUniquePad"},
|
||||
{702, nullptr, "AcquireUniquePadConnectionEventHandle"},
|
||||
{703, nullptr, "GetUniquePadIds"},
|
||||
{751, nullptr, "AcquireJoyDetachOnBluetoothOffEventHandle"},
|
||||
{800, nullptr, "ListSixAxisSensorHandles"},
|
||||
{801, nullptr, "IsSixAxisSensorUserCalibrationSupported"},
|
||||
{802, nullptr, "ResetSixAxisSensorCalibrationValues"},
|
||||
{803, nullptr, "StartSixAxisSensorUserCalibration"},
|
||||
{804, nullptr, "CancelSixAxisSensorUserCalibration"},
|
||||
{805, nullptr, "GetUniquePadBluetoothAddress"},
|
||||
{806, nullptr, "DisconnectUniquePad"},
|
||||
{807, nullptr, "GetUniquePadType"},
|
||||
{808, nullptr, "GetUniquePadInterface"},
|
||||
{809, nullptr, "GetUniquePadSerialNumber"},
|
||||
{810, nullptr, "GetUniquePadControllerNumber"},
|
||||
{811, nullptr, "GetSixAxisSensorUserCalibrationStage"},
|
||||
{821, nullptr, "StartAnalogStickManualCalibration"},
|
||||
{822, nullptr, "RetryCurrentAnalogStickManualCalibrationStage"},
|
||||
{823, nullptr, "CancelAnalogStickManualCalibration"},
|
||||
{824, nullptr, "ResetAnalogStickManualCalibration"},
|
||||
{825, nullptr, "GetAnalogStickState"},
|
||||
{826, nullptr, "GetAnalogStickManualCalibrationStage"},
|
||||
{827, nullptr, "IsAnalogStickButtonPressed"},
|
||||
{828, nullptr, "IsAnalogStickInReleasePosition"},
|
||||
{829, nullptr, "IsAnalogStickInCircumference"},
|
||||
{850, nullptr, "IsUsbFullKeyControllerEnabled"},
|
||||
{851, nullptr, "EnableUsbFullKeyController"},
|
||||
{852, nullptr, "IsUsbConnected"},
|
||||
{900, nullptr, "ActivateInputDetector"},
|
||||
{901, nullptr, "NotifyInputDetector"},
|
||||
{1000, nullptr, "InitializeFirmwareUpdate"},
|
||||
{1001, nullptr, "GetFirmwareVersion"},
|
||||
{1002, nullptr, "GetAvailableFirmwareVersion"},
|
||||
{1003, nullptr, "IsFirmwareUpdateAvailable"},
|
||||
{1004, nullptr, "CheckFirmwareUpdateRequired"},
|
||||
{1005, nullptr, "StartFirmwareUpdate"},
|
||||
{1006, nullptr, "AbortFirmwareUpdate"},
|
||||
{1007, nullptr, "GetFirmwareUpdateState"},
|
||||
{1008, nullptr, "ActivateAudioControl"},
|
||||
{1009, nullptr, "AcquireAudioControlEventHandle"},
|
||||
{1010, nullptr, "GetAudioControlStates"},
|
||||
{1011, nullptr, "DeactivateAudioControl"},
|
||||
{1050, nullptr, "IsSixAxisSensorAccurateUserCalibrationSupported"},
|
||||
{1051, nullptr, "StartSixAxisSensorAccurateUserCalibration"},
|
||||
{1052, nullptr, "CancelSixAxisSensorAccurateUserCalibration"},
|
||||
{1053, nullptr, "GetSixAxisSensorAccurateUserCalibrationState"},
|
||||
{1100, nullptr, "GetHidbusSystemServiceObject"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class HidTmp final : public ServiceFramework<HidTmp> {
|
||||
public:
|
||||
explicit HidTmp() : ServiceFramework{"hid:tmp"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetConsoleSixAxisSensorCalibrationValues"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class HidBus final : public ServiceFramework<HidBus> {
|
||||
public:
|
||||
explicit HidBus() : ServiceFramework{"hidbus"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{1, nullptr, "GetBusHandle"},
|
||||
{2, nullptr, "IsExternalDeviceConnected"},
|
||||
{3, nullptr, "Initialize"},
|
||||
{4, nullptr, "Finalize"},
|
||||
{5, nullptr, "EnableExternalDevice"},
|
||||
{6, nullptr, "GetExternalDeviceId"},
|
||||
{7, nullptr, "SendCommandAsync"},
|
||||
{8, nullptr, "GetSendCommandAsynceResult"},
|
||||
{9, nullptr, "SetEventForSendCommandAsycResult"},
|
||||
{10, nullptr, "GetSharedMemoryHandle"},
|
||||
{11, nullptr, "EnableJoyPollingReceiveMode"},
|
||||
{12, nullptr, "DisableJoyPollingReceiveMode"},
|
||||
{13, nullptr, "GetPollingData"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
void ReloadInputDevices() {}
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager) {
|
||||
std::make_shared<Hid>()->InstallAsService(service_manager);
|
||||
std::make_shared<HidBus>()->InstallAsService(service_manager);
|
||||
std::make_shared<HidDbg>()->InstallAsService(service_manager);
|
||||
std::make_shared<HidSys>()->InstallAsService(service_manager);
|
||||
std::make_shared<HidTmp>()->InstallAsService(service_manager);
|
||||
|
||||
std::make_shared<IRS>()->InstallAsService(service_manager);
|
||||
std::make_shared<IRS_SYS>()->InstallAsService(service_manager);
|
||||
|
||||
std::make_shared<XCD_SYS>()->InstallAsService(service_manager);
|
||||
}
|
||||
|
||||
} // namespace Service::HID
|
||||
|
||||
49
src/core/hle/service/hid/irs.cpp
Normal file
49
src/core/hle/service/hid/irs.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/service/hid/irs.h"
|
||||
|
||||
namespace Service::HID {
|
||||
|
||||
IRS::IRS() : ServiceFramework{"irs"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{302, nullptr, "ActivateIrsensor"},
|
||||
{303, nullptr, "DeactivateIrsensor"},
|
||||
{304, nullptr, "GetIrsensorSharedMemoryHandle"},
|
||||
{305, nullptr, "StopImageProcessor"},
|
||||
{306, nullptr, "RunMomentProcessor"},
|
||||
{307, nullptr, "RunClusteringProcessor"},
|
||||
{308, nullptr, "RunImageTransferProcessor"},
|
||||
{309, nullptr, "GetImageTransferProcessorState"},
|
||||
{310, nullptr, "RunTeraPluginProcessor"},
|
||||
{311, nullptr, "GetNpadIrCameraHandle"},
|
||||
{312, nullptr, "RunPointingProcessor"},
|
||||
{313, nullptr, "SuspendImageProcessor"},
|
||||
{314, nullptr, "CheckFirmwareVersion"},
|
||||
{315, nullptr, "SetFunctionLevel"},
|
||||
{316, nullptr, "RunImageTransferExProcessor"},
|
||||
{317, nullptr, "RunIrLedProcessor"},
|
||||
{318, nullptr, "StopImageProcessorAsync"},
|
||||
{319, nullptr, "ActivateIrsensorWithFunctionLevel"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IRS_SYS::IRS_SYS() : ServiceFramework{"irs:sys"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{500, nullptr, "SetAppletResourceUserId"},
|
||||
{501, nullptr, "RegisterAppletResourceUserId"},
|
||||
{502, nullptr, "UnregisterAppletResourceUserId"},
|
||||
{503, nullptr, "EnableAppletToGetInput"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
} // namespace Service::HID
|
||||
21
src/core/hle/service/hid/irs.h
Normal file
21
src/core/hle/service/hid/irs.h
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::HID {
|
||||
|
||||
class IRS final : public ServiceFramework<IRS> {
|
||||
public:
|
||||
explicit IRS();
|
||||
};
|
||||
|
||||
class IRS_SYS final : public ServiceFramework<IRS_SYS> {
|
||||
public:
|
||||
explicit IRS_SYS();
|
||||
};
|
||||
|
||||
} // namespace Service::HID
|
||||
37
src/core/hle/service/hid/xcd.cpp
Normal file
37
src/core/hle/service/hid/xcd.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/service/hid/xcd.h"
|
||||
|
||||
namespace Service::HID {
|
||||
|
||||
XCD_SYS::XCD_SYS() : ServiceFramework{"xcd:sys"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetDataFormat"},
|
||||
{1, nullptr, "SetDataFormat"},
|
||||
{2, nullptr, "GetMcuState"},
|
||||
{3, nullptr, "SetMcuState"},
|
||||
{4, nullptr, "GetMcuVersionForNfc"},
|
||||
{5, nullptr, "CheckNfcDevicePower"},
|
||||
{10, nullptr, "SetNfcEvent"},
|
||||
{11, nullptr, "GetNfcInfo"},
|
||||
{12, nullptr, "StartNfcDiscovery"},
|
||||
{13, nullptr, "StopNfcDiscovery"},
|
||||
{14, nullptr, "StartNtagRead"},
|
||||
{15, nullptr, "StartNtagWrite"},
|
||||
{16, nullptr, "SendNfcRawData"},
|
||||
{17, nullptr, "RegisterMifareKey"},
|
||||
{18, nullptr, "ClearMifareKey"},
|
||||
{19, nullptr, "StartMifareRead"},
|
||||
{20, nullptr, "StartMifareWrite"},
|
||||
{101, nullptr, "GetAwakeTriggerReasonForLeftRail"},
|
||||
{102, nullptr, "GetAwakeTriggerReasonForRightRail"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
} // namespace Service::HID
|
||||
16
src/core/hle/service/hid/xcd.h
Normal file
16
src/core/hle/service/hid/xcd.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::HID {
|
||||
|
||||
class XCD_SYS final : public ServiceFramework<XCD_SYS> {
|
||||
public:
|
||||
explicit XCD_SYS();
|
||||
};
|
||||
|
||||
} // namespace Service::HID
|
||||
90
src/core/hle/service/lbl/lbl.cpp
Normal file
90
src/core/hle/service/lbl/lbl.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/hle_ipc.h"
|
||||
#include "core/hle/service/lbl/lbl.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
|
||||
namespace Service::LBL {
|
||||
|
||||
class LBL final : public ServiceFramework<LBL> {
|
||||
public:
|
||||
explicit LBL() : ServiceFramework{"lbl"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "Unknown1"},
|
||||
{1, nullptr, "Unknown2"},
|
||||
{2, nullptr, "Unknown3"},
|
||||
{3, nullptr, "Unknown4"},
|
||||
{4, nullptr, "Unknown5"},
|
||||
{5, nullptr, "Unknown6"},
|
||||
{6, nullptr, "TurnOffBacklight"},
|
||||
{7, nullptr, "TurnOnBacklight"},
|
||||
{8, nullptr, "GetBacklightStatus"},
|
||||
{9, nullptr, "Unknown7"},
|
||||
{10, nullptr, "Unknown8"},
|
||||
{11, nullptr, "Unknown9"},
|
||||
{12, nullptr, "Unknown10"},
|
||||
{13, nullptr, "Unknown11"},
|
||||
{14, nullptr, "Unknown12"},
|
||||
{15, nullptr, "Unknown13"},
|
||||
{16, nullptr, "ReadRawLightSensor"},
|
||||
{17, nullptr, "Unknown14"},
|
||||
{18, nullptr, "Unknown15"},
|
||||
{19, nullptr, "Unknown16"},
|
||||
{20, nullptr, "Unknown17"},
|
||||
{21, nullptr, "Unknown18"},
|
||||
{22, nullptr, "Unknown19"},
|
||||
{23, nullptr, "Unknown20"},
|
||||
{24, nullptr, "Unknown21"},
|
||||
{25, nullptr, "Unknown22"},
|
||||
{26, &LBL::EnableVrMode, "EnableVrMode"},
|
||||
{27, &LBL::DisableVrMode, "DisableVrMode"},
|
||||
{28, &LBL::GetVrMode, "GetVrMode"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
private:
|
||||
void EnableVrMode(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
vr_mode_enabled = true;
|
||||
|
||||
LOG_DEBUG(Service_LBL, "called");
|
||||
}
|
||||
|
||||
void DisableVrMode(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
vr_mode_enabled = false;
|
||||
|
||||
LOG_DEBUG(Service_LBL, "called");
|
||||
}
|
||||
|
||||
void GetVrMode(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push(vr_mode_enabled);
|
||||
|
||||
LOG_DEBUG(Service_LBL, "called");
|
||||
}
|
||||
|
||||
bool vr_mode_enabled = false;
|
||||
};
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& sm) {
|
||||
std::make_shared<LBL>()->InstallAsService(sm);
|
||||
}
|
||||
|
||||
} // namespace Service::LBL
|
||||
15
src/core/hle/service/lbl/lbl.h
Normal file
15
src/core/hle/service/lbl/lbl.h
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Service::SM {
|
||||
class ServiceManager;
|
||||
}
|
||||
|
||||
namespace Service::LBL {
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& sm);
|
||||
|
||||
} // namespace Service::LBL
|
||||
142
src/core/hle/service/ldn/ldn.cpp
Normal file
142
src/core/hle/service/ldn/ldn.cpp
Normal file
@@ -0,0 +1,142 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/ldn/ldn.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
|
||||
namespace Service::LDN {
|
||||
|
||||
class IMonitorService final : public ServiceFramework<IMonitorService> {
|
||||
public:
|
||||
explicit IMonitorService() : ServiceFramework{"IMonitorService"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetStateForMonitor"},
|
||||
{1, nullptr, "GetNetworkInfoForMonitor"},
|
||||
{2, nullptr, "GetIpv4AddressForMonitor"},
|
||||
{3, nullptr, "GetDisconnectReasonForMonitor"},
|
||||
{4, nullptr, "GetSecurityParameterForMonitor"},
|
||||
{5, nullptr, "GetNetworkConfigForMonitor"},
|
||||
{100, nullptr, "InitializeMonitor"},
|
||||
{101, nullptr, "FinalizeMonitor"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class LDNM final : public ServiceFramework<LDNM> {
|
||||
public:
|
||||
explicit LDNM() : ServiceFramework{"ldn:m"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &LDNM::CreateMonitorService, "CreateMonitorService"}
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
void CreateMonitorService(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<IMonitorService>();
|
||||
|
||||
LOG_DEBUG(Service_LDN, "called");
|
||||
}
|
||||
};
|
||||
|
||||
class ILocalCommunicationService final : public ServiceFramework<ILocalCommunicationService> {
|
||||
public:
|
||||
explicit ILocalCommunicationService(const char* name) : ServiceFramework{name} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetState"},
|
||||
{1, nullptr, "GetNetworkInfo"},
|
||||
{2, nullptr, "GetIpv4Address"},
|
||||
{3, nullptr, "GetDisconnectReason"},
|
||||
{4, nullptr, "GetSecurityParameter"},
|
||||
{5, nullptr, "GetNetworkConfig"},
|
||||
{100, nullptr, "AttachStateChangeEvent"},
|
||||
{101, nullptr, "GetNetworkInfoLatestUpdate"},
|
||||
{102, nullptr, "Scan"},
|
||||
{103, nullptr, "ScanPrivate"},
|
||||
{200, nullptr, "OpenAccessPoint"},
|
||||
{201, nullptr, "CloseAccessPoint"},
|
||||
{202, nullptr, "CreateNetwork"},
|
||||
{203, nullptr, "CreateNetworkPrivate"},
|
||||
{204, nullptr, "DestroyNetwork"},
|
||||
{205, nullptr, "Reject"},
|
||||
{206, nullptr, "SetAdvertiseData"},
|
||||
{207, nullptr, "SetStationAcceptPolicy"},
|
||||
{208, nullptr, "AddAcceptFilterEntry"},
|
||||
{209, nullptr, "ClearAcceptFilter"},
|
||||
{300, nullptr, "OpenStation"},
|
||||
{301, nullptr, "CloseStation"},
|
||||
{302, nullptr, "Connect"},
|
||||
{303, nullptr, "ConnectPrivate"},
|
||||
{304, nullptr, "Disconnect"},
|
||||
{400, nullptr, "InitializeSystem"},
|
||||
{401, nullptr, "FinalizeSystem"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class LDNS final : public ServiceFramework<LDNS> {
|
||||
public:
|
||||
explicit LDNS() : ServiceFramework{"ldn:s"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &LDNS::CreateSystemLocalCommunicationService, "CreateSystemLocalCommunicationService"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
void CreateSystemLocalCommunicationService(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<ILocalCommunicationService>("ISystemLocalCommunicationService");
|
||||
|
||||
LOG_DEBUG(Service_LDN, "called");
|
||||
}
|
||||
};
|
||||
|
||||
class LDNU final : public ServiceFramework<LDNU> {
|
||||
public:
|
||||
explicit LDNU() : ServiceFramework{"ldn:u"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &LDNU::CreateUserLocalCommunicationService, "CreateUserLocalCommunicationService"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
void CreateUserLocalCommunicationService(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<ILocalCommunicationService>("IUserLocalCommunicationService");
|
||||
|
||||
LOG_DEBUG(Service_LDN, "called");
|
||||
}
|
||||
};
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& sm) {
|
||||
std::make_shared<LDNM>()->InstallAsService(sm);
|
||||
std::make_shared<LDNS>()->InstallAsService(sm);
|
||||
std::make_shared<LDNU>()->InstallAsService(sm);
|
||||
}
|
||||
|
||||
} // namespace Service::LDN
|
||||
16
src/core/hle/service/ldn/ldn.h
Normal file
16
src/core/hle/service/ldn/ldn.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Service::SM {
|
||||
class ServiceManager;
|
||||
}
|
||||
|
||||
namespace Service::LDN {
|
||||
|
||||
/// Registers all LDN services with the specified service manager.
|
||||
void InstallInterfaces(SM::ServiceManager& sm);
|
||||
|
||||
} // namespace Service::LDN
|
||||
81
src/core/hle/service/ldr/ldr.cpp
Normal file
81
src/core/hle/service/ldr/ldr.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "core/hle/service/ldr/ldr.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::LDR {
|
||||
|
||||
class DebugMonitor final : public ServiceFramework<DebugMonitor> {
|
||||
public:
|
||||
explicit DebugMonitor() : ServiceFramework{"ldr:dmnt"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "AddProcessToDebugLaunchQueue"},
|
||||
{1, nullptr, "ClearDebugLaunchQueue"},
|
||||
{2, nullptr, "GetNsoInfos"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class ProcessManager final : public ServiceFramework<ProcessManager> {
|
||||
public:
|
||||
explicit ProcessManager() : ServiceFramework{"ldr:pm"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "CreateProcess"},
|
||||
{1, nullptr, "GetProgramInfo"},
|
||||
{2, nullptr, "RegisterTitle"},
|
||||
{3, nullptr, "UnregisterTitle"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class Shell final : public ServiceFramework<Shell> {
|
||||
public:
|
||||
explicit Shell() : ServiceFramework{"ldr:shel"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "AddProcessToLaunchQueue"},
|
||||
{1, nullptr, "ClearLaunchQueue"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class RelocatableObject final : public ServiceFramework<RelocatableObject> {
|
||||
public:
|
||||
explicit RelocatableObject() : ServiceFramework{"ldr:ro"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "LoadNro"},
|
||||
{1, nullptr, "UnloadNro"},
|
||||
{2, nullptr, "LoadNrr"},
|
||||
{3, nullptr, "UnloadNrr"},
|
||||
{4, nullptr, "Initialize"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& sm) {
|
||||
std::make_shared<DebugMonitor>()->InstallAsService(sm);
|
||||
std::make_shared<ProcessManager>()->InstallAsService(sm);
|
||||
std::make_shared<Shell>()->InstallAsService(sm);
|
||||
std::make_shared<RelocatableObject>()->InstallAsService(sm);
|
||||
}
|
||||
|
||||
} // namespace Service::LDR
|
||||
16
src/core/hle/service/ldr/ldr.h
Normal file
16
src/core/hle/service/ldr/ldr.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Service::SM {
|
||||
class ServiceManager;
|
||||
}
|
||||
|
||||
namespace Service::LDR {
|
||||
|
||||
/// Registers all LDR services with the specified service manager.
|
||||
void InstallInterfaces(SM::ServiceManager& sm);
|
||||
|
||||
} // namespace Service::LDR
|
||||
@@ -4,10 +4,12 @@
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/client_session.h"
|
||||
#include "core/hle/service/lm/lm.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
namespace Service::LM {
|
||||
|
||||
@@ -15,13 +17,12 @@ class Logger final : public ServiceFramework<Logger> {
|
||||
public:
|
||||
Logger() : ServiceFramework("Logger") {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0x00000000, &Logger::Log, "Log"},
|
||||
{0x00000000, &Logger::Initialize, "Initialize"},
|
||||
{0x00000001, nullptr, "SetDestination"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
~Logger() = default;
|
||||
|
||||
private:
|
||||
struct MessageHeader {
|
||||
enum Flags : u32_le {
|
||||
@@ -66,13 +67,13 @@ private:
|
||||
};
|
||||
|
||||
/**
|
||||
* LM::Log service function
|
||||
* ILogger::Initialize service function
|
||||
* Inputs:
|
||||
* 0: 0x00000000
|
||||
* Outputs:
|
||||
* 0: ResultCode
|
||||
*/
|
||||
void Log(Kernel::HLERequestContext& ctx) {
|
||||
void Initialize(Kernel::HLERequestContext& ctx) {
|
||||
// This function only succeeds - Get that out of the way
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
@@ -162,30 +163,33 @@ private:
|
||||
std::ostringstream log_stream;
|
||||
};
|
||||
|
||||
class LM final : public ServiceFramework<LM> {
|
||||
public:
|
||||
explicit LM() : ServiceFramework{"lm"} {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0x00000000, &LM::OpenLogger, "OpenLogger"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
/**
|
||||
* LM::OpenLogger service function
|
||||
* Inputs:
|
||||
* 0: 0x00000000
|
||||
* Outputs:
|
||||
* 0: ResultCode
|
||||
*/
|
||||
void OpenLogger(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<Logger>();
|
||||
|
||||
LOG_DEBUG(Service_LM, "called");
|
||||
}
|
||||
};
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager) {
|
||||
std::make_shared<LM>()->InstallAsService(service_manager);
|
||||
}
|
||||
|
||||
/**
|
||||
* LM::Initialize service function
|
||||
* Inputs:
|
||||
* 0: 0x00000000
|
||||
* Outputs:
|
||||
* 0: ResultCode
|
||||
*/
|
||||
void LM::Initialize(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<Logger>();
|
||||
|
||||
LOG_DEBUG(Service_LM, "called");
|
||||
}
|
||||
|
||||
LM::LM() : ServiceFramework("lm") {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0x00000000, &LM::Initialize, "Initialize"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
} // namespace Service::LM
|
||||
|
||||
@@ -4,21 +4,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/service/service.h"
|
||||
namespace Service::SM {
|
||||
class ServiceManager;
|
||||
}
|
||||
|
||||
namespace Service::LM {
|
||||
|
||||
class LM final : public ServiceFramework<LM> {
|
||||
public:
|
||||
LM();
|
||||
~LM() = default;
|
||||
|
||||
private:
|
||||
void Initialize(Kernel::HLERequestContext& ctx);
|
||||
};
|
||||
|
||||
/// Registers all LM services with the specified service manager.
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager);
|
||||
|
||||
|
||||
222
src/core/hle/service/nfc/nfc.cpp
Normal file
222
src/core/hle/service/nfc/nfc.cpp
Normal file
@@ -0,0 +1,222 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/hle_ipc.h"
|
||||
#include "core/hle/service/nfc/nfc.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
|
||||
namespace Service::NFC {
|
||||
|
||||
class IAm final : public ServiceFramework<IAm> {
|
||||
public:
|
||||
explicit IAm() : ServiceFramework{"IAm"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "Initialize"},
|
||||
{1, nullptr, "Finalize"},
|
||||
{2, nullptr, "NotifyForegroundApplet"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class NFC_AM final : public ServiceFramework<NFC_AM> {
|
||||
public:
|
||||
explicit NFC_AM() : ServiceFramework{"nfc:am"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &NFC_AM::CreateAmInterface, "CreateAmInterface"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
private:
|
||||
void CreateAmInterface(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<IAm>();
|
||||
|
||||
LOG_DEBUG(Service_NFC, "called");
|
||||
}
|
||||
};
|
||||
|
||||
class MFIUser final : public ServiceFramework<MFIUser> {
|
||||
public:
|
||||
explicit MFIUser() : ServiceFramework{"IUser"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "Initialize"},
|
||||
{1, nullptr, "Finalize"},
|
||||
{2, nullptr, "ListDevices"},
|
||||
{3, nullptr, "StartDetection"},
|
||||
{4, nullptr, "StopDetection"},
|
||||
{5, nullptr, "Read"},
|
||||
{6, nullptr, "Write"},
|
||||
{7, nullptr, "GetTagInfo"},
|
||||
{8, nullptr, "GetActivateEventHandle"},
|
||||
{9, nullptr, "GetDeactivateEventHandle"},
|
||||
{10, nullptr, "GetState"},
|
||||
{11, nullptr, "GetDeviceState"},
|
||||
{12, nullptr, "GetNpadId"},
|
||||
{13, nullptr, "GetAvailabilityChangeEventHandle"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class NFC_MF_U final : public ServiceFramework<NFC_MF_U> {
|
||||
public:
|
||||
explicit NFC_MF_U() : ServiceFramework{"nfc:mf:u"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &NFC_MF_U::CreateUserInterface, "CreateUserInterface"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
private:
|
||||
void CreateUserInterface(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<MFIUser>();
|
||||
|
||||
LOG_DEBUG(Service_NFC, "called");
|
||||
}
|
||||
};
|
||||
|
||||
class IUser final : public ServiceFramework<IUser> {
|
||||
public:
|
||||
explicit IUser() : ServiceFramework{"IUser"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "Initialize"},
|
||||
{1, nullptr, "Finalize"},
|
||||
{2, nullptr, "GetState"},
|
||||
{3, nullptr, "IsNfcEnabled"},
|
||||
{400, nullptr, "Initialize"},
|
||||
{401, nullptr, "Finalize"},
|
||||
{402, nullptr, "GetState"},
|
||||
{403, nullptr, "IsNfcEnabled"},
|
||||
{404, nullptr, "ListDevices"},
|
||||
{405, nullptr, "GetDeviceState"},
|
||||
{406, nullptr, "GetNpadId"},
|
||||
{407, nullptr, "AttachAvailabilityChangeEvent"},
|
||||
{408, nullptr, "StartDetection"},
|
||||
{409, nullptr, "StopDetection"},
|
||||
{410, nullptr, "GetTagInfo"},
|
||||
{411, nullptr, "AttachActivateEvent"},
|
||||
{412, nullptr, "AttachDeactivateEvent"},
|
||||
{1000, nullptr, "ReadMifare"},
|
||||
{1001, nullptr, "WriteMifare"},
|
||||
{1300, nullptr, "SendCommandByPassThrough"},
|
||||
{1301, nullptr, "KeepPassThroughSession"},
|
||||
{1302, nullptr, "ReleasePassThroughSession"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class NFC_U final : public ServiceFramework<NFC_U> {
|
||||
public:
|
||||
explicit NFC_U() : ServiceFramework{"nfc:u"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &NFC_U::CreateUserInterface, "CreateUserInterface"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
private:
|
||||
void CreateUserInterface(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<IUser>();
|
||||
|
||||
LOG_DEBUG(Service_NFC, "called");
|
||||
}
|
||||
};
|
||||
|
||||
class ISystem final : public ServiceFramework<ISystem> {
|
||||
public:
|
||||
explicit ISystem() : ServiceFramework{"ISystem"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "Initialize"},
|
||||
{1, nullptr, "Finalize"},
|
||||
{2, nullptr, "GetState"},
|
||||
{3, nullptr, "IsNfcEnabled"},
|
||||
{100, nullptr, "SetNfcEnabled"},
|
||||
{400, nullptr, "InitializeSystem"},
|
||||
{401, nullptr, "FinalizeSystem"},
|
||||
{402, nullptr, "GetState"},
|
||||
{403, nullptr, "IsNfcEnabled"},
|
||||
{404, nullptr, "ListDevices"},
|
||||
{405, nullptr, "GetDeviceState"},
|
||||
{406, nullptr, "GetNpadId"},
|
||||
{407, nullptr, "AttachAvailabilityChangeEvent"},
|
||||
{408, nullptr, "StartDetection"},
|
||||
{409, nullptr, "StopDetection"},
|
||||
{410, nullptr, "GetTagInfo"},
|
||||
{411, nullptr, "AttachActivateEvent"},
|
||||
{412, nullptr, "AttachDeactivateEvent"},
|
||||
{500, nullptr, "SetNfcEnabled"},
|
||||
{1000, nullptr, "ReadMifare"},
|
||||
{1001, nullptr, "WriteMifare"},
|
||||
{1300, nullptr, "SendCommandByPassThrough"},
|
||||
{1301, nullptr, "KeepPassThroughSession"},
|
||||
{1302, nullptr, "ReleasePassThroughSession"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class NFC_SYS final : public ServiceFramework<NFC_SYS> {
|
||||
public:
|
||||
explicit NFC_SYS() : ServiceFramework{"nfc:sys"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &NFC_SYS::CreateSystemInterface, "CreateSystemInterface"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
private:
|
||||
void CreateSystemInterface(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<ISystem>();
|
||||
|
||||
LOG_DEBUG(Service_NFC, "called");
|
||||
}
|
||||
};
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& sm) {
|
||||
std::make_shared<NFC_AM>()->InstallAsService(sm);
|
||||
std::make_shared<NFC_MF_U>()->InstallAsService(sm);
|
||||
std::make_shared<NFC_U>()->InstallAsService(sm);
|
||||
std::make_shared<NFC_SYS>()->InstallAsService(sm);
|
||||
}
|
||||
|
||||
} // namespace Service::NFC
|
||||
15
src/core/hle/service/nfc/nfc.h
Normal file
15
src/core/hle/service/nfc/nfc.h
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Service::SM {
|
||||
class ServiceManager;
|
||||
}
|
||||
|
||||
namespace Service::NFC {
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& sm);
|
||||
|
||||
} // namespace Service::NFC
|
||||
@@ -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
|
||||
124
src/core/hle/service/nim/nim.cpp
Normal file
124
src/core/hle/service/nim/nim.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/service/nim/nim.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
|
||||
namespace Service::NIM {
|
||||
|
||||
class NIM final : public ServiceFramework<NIM> {
|
||||
public:
|
||||
explicit NIM() : ServiceFramework{"nim"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "CreateSystemUpdateTask"},
|
||||
{1, nullptr, "DestroySystemUpdateTask"},
|
||||
{2, nullptr, "ListSystemUpdateTask"},
|
||||
{3, nullptr, "RequestSystemUpdateTaskRun"},
|
||||
{4, nullptr, "GetSystemUpdateTaskInfo"},
|
||||
{5, nullptr, "CommitSystemUpdateTask"},
|
||||
{6, nullptr, "CreateNetworkInstallTask"},
|
||||
{7, nullptr, "DestroyNetworkInstallTask"},
|
||||
{8, nullptr, "ListNetworkInstallTask"},
|
||||
{9, nullptr, "RequestNetworkInstallTaskRun"},
|
||||
{10, nullptr, "GetNetworkInstallTaskInfo"},
|
||||
{11, nullptr, "CommitNetworkInstallTask"},
|
||||
{12, nullptr, "RequestLatestSystemUpdateMeta"},
|
||||
{14, nullptr, "ListApplicationNetworkInstallTask"},
|
||||
{15, nullptr, "ListNetworkInstallTaskContentMeta"},
|
||||
{16, nullptr, "RequestLatestVersion"},
|
||||
{17, nullptr, "SetNetworkInstallTaskAttribute"},
|
||||
{18, nullptr, "AddNetworkInstallTaskContentMeta"},
|
||||
{19, nullptr, "GetDownloadedSystemDataPath"},
|
||||
{20, nullptr, "CalculateNetworkInstallTaskRequiredSize"},
|
||||
{21, nullptr, "IsExFatDriverIncluded"},
|
||||
{22, nullptr, "GetBackgroundDownloadStressTaskInfo"},
|
||||
{23, nullptr, "RequestDeviceAuthenticationToken"},
|
||||
{24, nullptr, "RequestGameCardRegistrationStatus"},
|
||||
{25, nullptr, "RequestRegisterGameCard"},
|
||||
{26, nullptr, "RequestRegisterNotificationToken"},
|
||||
{27, nullptr, "RequestDownloadTaskList"},
|
||||
{28, nullptr, "RequestApplicationControl"},
|
||||
{29, nullptr, "RequestLatestApplicationControl"},
|
||||
{30, nullptr, "RequestVersionList"},
|
||||
{31, nullptr, "CreateApplyDeltaTask"},
|
||||
{32, nullptr, "DestroyApplyDeltaTask"},
|
||||
{33, nullptr, "ListApplicationApplyDeltaTask"},
|
||||
{34, nullptr, "RequestApplyDeltaTaskRun"},
|
||||
{35, nullptr, "GetApplyDeltaTaskInfo"},
|
||||
{36, nullptr, "ListApplyDeltaTask"},
|
||||
{37, nullptr, "CommitApplyDeltaTask"},
|
||||
{38, nullptr, "CalculateApplyDeltaTaskRequiredSize"},
|
||||
{39, nullptr, "PrepareShutdown"},
|
||||
{40, nullptr, "ListApplyDeltaTask"},
|
||||
{41, nullptr, "ClearNotEnoughSpaceStateOfApplyDeltaTask"},
|
||||
{42, nullptr, "Unknown1"},
|
||||
{43, nullptr, "Unknown2"},
|
||||
{44, nullptr, "Unknown3"},
|
||||
{45, nullptr, "Unknown4"},
|
||||
{46, nullptr, "Unknown5"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class NIM_SHP final : public ServiceFramework<NIM_SHP> {
|
||||
public:
|
||||
explicit NIM_SHP() : ServiceFramework{"nim:shp"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "RequestDeviceAuthenticationToken"},
|
||||
{1, nullptr, "RequestCachedDeviceAuthenticationToken"},
|
||||
{100, nullptr, "RequestRegisterDeviceAccount"},
|
||||
{101, nullptr, "RequestUnregisterDeviceAccount"},
|
||||
{102, nullptr, "RequestDeviceAccountStatus"},
|
||||
{103, nullptr, "GetDeviceAccountInfo"},
|
||||
{104, nullptr, "RequestDeviceRegistrationInfo"},
|
||||
{105, nullptr, "RequestTransferDeviceAccount"},
|
||||
{106, nullptr, "RequestSyncRegistration"},
|
||||
{107, nullptr, "IsOwnDeviceId"},
|
||||
{200, nullptr, "RequestRegisterNotificationToken"},
|
||||
{300, nullptr, "RequestUnlinkDevice"},
|
||||
{301, nullptr, "RequestUnlinkDeviceIntegrated"},
|
||||
{302, nullptr, "RequestLinkDevice"},
|
||||
{303, nullptr, "HasDeviceLink"},
|
||||
{304, nullptr, "RequestUnlinkDeviceAll"},
|
||||
{305, nullptr, "RequestCreateVirtualAccount"},
|
||||
{306, nullptr, "RequestDeviceLinkStatus"},
|
||||
{400, nullptr, "GetAccountByVirtualAccount"},
|
||||
{500, nullptr, "RequestSyncTicket"},
|
||||
{501, nullptr, "RequestDownloadTicket"},
|
||||
{502, nullptr, "RequestDownloadTicketForPrepurchasedContents"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class NTC final : public ServiceFramework<NTC> {
|
||||
public:
|
||||
explicit NTC() : ServiceFramework{"ntc"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "OpenEnsureNetworkClockAvailabilityService"},
|
||||
{100, nullptr, "SuspendAutonomicTimeCorrection"},
|
||||
{101, nullptr, "ResumeAutonomicTimeCorrection"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& sm) {
|
||||
std::make_shared<NIM>()->InstallAsService(sm);
|
||||
std::make_shared<NIM_SHP>()->InstallAsService(sm);
|
||||
std::make_shared<NTC>()->InstallAsService(sm);
|
||||
}
|
||||
|
||||
} // namespace Service::NIM
|
||||
15
src/core/hle/service/nim/nim.h
Normal file
15
src/core/hle/service/nim/nim.h
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Service::SM {
|
||||
class ServiceManager;
|
||||
}
|
||||
|
||||
namespace Service::NIM {
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& sm);
|
||||
|
||||
} // namespace Service::NIM
|
||||
@@ -2,6 +2,8 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/service/nvdrv/devices/nvdevice.h"
|
||||
#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
|
||||
@@ -40,14 +42,14 @@ Module::Module() {
|
||||
devices["/dev/nvhost-nvdec"] = std::make_shared<Devices::nvhost_nvdec>();
|
||||
}
|
||||
|
||||
u32 Module::Open(std::string device_name) {
|
||||
u32 Module::Open(const std::string& device_name) {
|
||||
ASSERT_MSG(devices.find(device_name) != devices.end(), "Trying to open unknown device {}",
|
||||
device_name);
|
||||
|
||||
auto device = devices[device_name];
|
||||
u32 fd = next_fd++;
|
||||
const u32 fd = next_fd++;
|
||||
|
||||
open_files[fd] = device;
|
||||
open_files[fd] = std::move(device);
|
||||
|
||||
return fd;
|
||||
}
|
||||
@@ -56,7 +58,7 @@ u32 Module::Ioctl(u32 fd, u32_le command, const std::vector<u8>& input, std::vec
|
||||
auto itr = open_files.find(fd);
|
||||
ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device");
|
||||
|
||||
auto device = itr->second;
|
||||
auto& device = itr->second;
|
||||
return device->ioctl({command}, input, output);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ public:
|
||||
}
|
||||
|
||||
/// Opens a device node and returns a file descriptor to it.
|
||||
u32 Open(std::string device_name);
|
||||
u32 Open(const std::string& device_name);
|
||||
/// Sends an ioctl command to the specified file descriptor.
|
||||
u32 Ioctl(u32 fd, u32 command, const std::vector<u8>& input, std::vector<u8>& output);
|
||||
/// Closes a device file descriptor and returns operation success.
|
||||
|
||||
@@ -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"
|
||||
|
||||
70
src/core/hle/service/pm/pm.cpp
Normal file
70
src/core/hle/service/pm/pm.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::PM {
|
||||
|
||||
class BootMode final : public ServiceFramework<BootMode> {
|
||||
public:
|
||||
explicit BootMode() : ServiceFramework{"pm:bm"} {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetBootMode"},
|
||||
{1, nullptr, "SetMaintenanceBoot"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class DebugMonitor final : public ServiceFramework<DebugMonitor> {
|
||||
public:
|
||||
explicit DebugMonitor() : ServiceFramework{"pm:dmnt"} {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "IsDebugMode"},
|
||||
{1, nullptr, "GetDebugProcesses"},
|
||||
{2, nullptr, "StartDebugProcess"},
|
||||
{3, nullptr, "GetTitlePid"},
|
||||
{4, nullptr, "EnableDebugForTitleId"},
|
||||
{5, nullptr, "GetApplicationPid"},
|
||||
{6, nullptr, "EnableDebugForApplication"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class Info final : public ServiceFramework<Info> {
|
||||
public:
|
||||
explicit Info() : ServiceFramework{"pm:info"} {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetTitleId"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class Shell final : public ServiceFramework<Shell> {
|
||||
public:
|
||||
explicit Shell() : ServiceFramework{"pm:shell"} {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "LaunchProcess"},
|
||||
{1, nullptr, "TerminateProcessByPid"},
|
||||
{2, nullptr, "TerminateProcessByTitleId"},
|
||||
{3, nullptr, "GetProcessEventWaiter"},
|
||||
{4, nullptr, "GetProcessEventType"},
|
||||
{5, nullptr, "NotifyBootFinished"},
|
||||
{6, nullptr, "GetApplicationPid"},
|
||||
{7, nullptr, "BoostSystemMemoryResourceLimit"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& sm) {
|
||||
std::make_shared<BootMode>()->InstallAsService(sm);
|
||||
std::make_shared<DebugMonitor>()->InstallAsService(sm);
|
||||
std::make_shared<Info>()->InstallAsService(sm);
|
||||
std::make_shared<Shell>()->InstallAsService(sm);
|
||||
}
|
||||
|
||||
} // namespace Service::PM
|
||||
16
src/core/hle/service/pm/pm.h
Normal file
16
src/core/hle/service/pm/pm.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Service::SM {
|
||||
class ServiceManager;
|
||||
}
|
||||
|
||||
namespace Service::PM {
|
||||
|
||||
/// Registers all PM services with the specified service manager.
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager);
|
||||
|
||||
} // namespace Service::PM
|
||||
@@ -21,17 +21,28 @@
|
||||
#include "core/hle/service/apm/apm.h"
|
||||
#include "core/hle/service/audio/audio.h"
|
||||
#include "core/hle/service/bcat/bcat.h"
|
||||
#include "core/hle/service/btdrv/btdrv.h"
|
||||
#include "core/hle/service/erpt/erpt.h"
|
||||
#include "core/hle/service/es/es.h"
|
||||
#include "core/hle/service/eupld/eupld.h"
|
||||
#include "core/hle/service/fatal/fatal.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "core/hle/service/friend/friend.h"
|
||||
#include "core/hle/service/grc/grc.h"
|
||||
#include "core/hle/service/hid/hid.h"
|
||||
#include "core/hle/service/lbl/lbl.h"
|
||||
#include "core/hle/service/ldn/ldn.h"
|
||||
#include "core/hle/service/ldr/ldr.h"
|
||||
#include "core/hle/service/lm/lm.h"
|
||||
#include "core/hle/service/mm/mm_u.h"
|
||||
#include "core/hle/service/nfc/nfc.h"
|
||||
#include "core/hle/service/nfp/nfp.h"
|
||||
#include "core/hle/service/nifm/nifm.h"
|
||||
#include "core/hle/service/nim/nim.h"
|
||||
#include "core/hle/service/ns/ns.h"
|
||||
#include "core/hle/service/nvdrv/nvdrv.h"
|
||||
#include "core/hle/service/pctl/pctl.h"
|
||||
#include "core/hle/service/pm/pm.h"
|
||||
#include "core/hle/service/prepo/prepo.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/set/settings.h"
|
||||
@@ -185,20 +196,31 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm) {
|
||||
AM::InstallInterfaces(*sm, nv_flinger);
|
||||
AOC::InstallInterfaces(*sm);
|
||||
APM::InstallInterfaces(*sm);
|
||||
BCAT::InstallInterfaces(*sm);
|
||||
Audio::InstallInterfaces(*sm);
|
||||
BCAT::InstallInterfaces(*sm);
|
||||
BtDrv::InstallInterfaces(*sm);
|
||||
ERPT::InstallInterfaces(*sm);
|
||||
ES::InstallInterfaces(*sm);
|
||||
EUPLD::InstallInterfaces(*sm);
|
||||
Fatal::InstallInterfaces(*sm);
|
||||
FileSystem::InstallInterfaces(*sm);
|
||||
Friend::InstallInterfaces(*sm);
|
||||
GRC::InstallInterfaces(*sm);
|
||||
HID::InstallInterfaces(*sm);
|
||||
LBL::InstallInterfaces(*sm);
|
||||
LDN::InstallInterfaces(*sm);
|
||||
LDR::InstallInterfaces(*sm);
|
||||
LM::InstallInterfaces(*sm);
|
||||
MM::InstallInterfaces(*sm);
|
||||
NFC::InstallInterfaces(*sm);
|
||||
NFP::InstallInterfaces(*sm);
|
||||
NIFM::InstallInterfaces(*sm);
|
||||
NIM::InstallInterfaces(*sm);
|
||||
NS::InstallInterfaces(*sm);
|
||||
Nvidia::InstallInterfaces(*sm);
|
||||
PCTL::InstallInterfaces(*sm);
|
||||
PlayReport::InstallInterfaces(*sm);
|
||||
PM::InstallInterfaces(*sm);
|
||||
Sockets::InstallInterfaces(*sm);
|
||||
SPL::InstallInterfaces(*sm);
|
||||
SSL::InstallInterfaces(*sm);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -109,4 +109,26 @@ BSD::BSD(const char* name) : ServiceFramework(name) {
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
BSDCFG::BSDCFG() : ServiceFramework{"bsdcfg"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "SetIfUp"},
|
||||
{1, nullptr, "SetIfUpWithEvent"},
|
||||
{2, nullptr, "CancelIf"},
|
||||
{3, nullptr, "SetIfDown"},
|
||||
{4, nullptr, "GetIfState"},
|
||||
{5, nullptr, "DhcpRenew"},
|
||||
{6, nullptr, "AddStaticArpEntry"},
|
||||
{7, nullptr, "RemoveArpEntry"},
|
||||
{8, nullptr, "LookupArpEntry"},
|
||||
{9, nullptr, "LookupArpEntry2"},
|
||||
{10, nullptr, "ClearArpEntries"},
|
||||
{11, nullptr, "ClearArpEntries2"},
|
||||
{12, nullptr, "PrintArpEntries"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
} // namespace Service::Sockets
|
||||
|
||||
@@ -26,4 +26,9 @@ private:
|
||||
u32 next_fd = 1;
|
||||
};
|
||||
|
||||
class BSDCFG final : public ServiceFramework<BSDCFG> {
|
||||
public:
|
||||
explicit BSDCFG();
|
||||
};
|
||||
|
||||
} // namespace Service::Sockets
|
||||
|
||||
38
src/core/hle/service/sockets/ethc.cpp
Normal file
38
src/core/hle/service/sockets/ethc.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/service/sockets/ethc.h"
|
||||
|
||||
namespace Service::Sockets {
|
||||
|
||||
ETHC_C::ETHC_C() : ServiceFramework{"ethc:c"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "Initialize"},
|
||||
{1, nullptr, "Cancel"},
|
||||
{2, nullptr, "GetResult"},
|
||||
{3, nullptr, "GetMediaList"},
|
||||
{4, nullptr, "SetMediaType"},
|
||||
{5, nullptr, "GetMediaType"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
ETHC_I::ETHC_I() : ServiceFramework{"ethc:i"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetReadableHandle"},
|
||||
{1, nullptr, "Cancel"},
|
||||
{2, nullptr, "GetResult"},
|
||||
{3, nullptr, "GetInterfaceList"},
|
||||
{4, nullptr, "GetInterfaceCount"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
} // namespace Service::Sockets
|
||||
21
src/core/hle/service/sockets/ethc.h
Normal file
21
src/core/hle/service/sockets/ethc.h
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::Sockets {
|
||||
|
||||
class ETHC_C final : public ServiceFramework<ETHC_C> {
|
||||
public:
|
||||
explicit ETHC_C();
|
||||
};
|
||||
|
||||
class ETHC_I final : public ServiceFramework<ETHC_I> {
|
||||
public:
|
||||
explicit ETHC_I();
|
||||
};
|
||||
|
||||
} // namespace Service::Sockets
|
||||
@@ -3,6 +3,7 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/service/sockets/bsd.h"
|
||||
#include "core/hle/service/sockets/ethc.h"
|
||||
#include "core/hle/service/sockets/nsd.h"
|
||||
#include "core/hle/service/sockets/sfdnsres.h"
|
||||
#include "core/hle/service/sockets/sockets.h"
|
||||
@@ -12,8 +13,14 @@ namespace Service::Sockets {
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager) {
|
||||
std::make_shared<BSD>("bsd:s")->InstallAsService(service_manager);
|
||||
std::make_shared<BSD>("bsd:u")->InstallAsService(service_manager);
|
||||
std::make_shared<BSDCFG>()->InstallAsService(service_manager);
|
||||
|
||||
std::make_shared<ETHC_C>()->InstallAsService(service_manager);
|
||||
std::make_shared<ETHC_I>()->InstallAsService(service_manager);
|
||||
|
||||
std::make_shared<NSD>("nsd:a")->InstallAsService(service_manager);
|
||||
std::make_shared<NSD>("nsd:u")->InstallAsService(service_manager);
|
||||
|
||||
std::make_shared<SFDNSRES>()->InstallAsService(service_manager);
|
||||
}
|
||||
|
||||
|
||||
@@ -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_U final : public Module::Interface {
|
||||
class Time final : public Module::Interface {
|
||||
public:
|
||||
explicit TIME_U(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,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_S final : public Module::Interface {
|
||||
public:
|
||||
explicit TIME_S(std::shared_ptr<Module> time);
|
||||
};
|
||||
|
||||
} // 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
|
||||
@@ -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]):
|
||||
|
||||
@@ -23,7 +23,14 @@ enum class RenderTargetFormat : u32 {
|
||||
RGB10_A2_UNORM = 0xD1,
|
||||
RGBA8_UNORM = 0xD5,
|
||||
RGBA8_SRGB = 0xD6,
|
||||
RG16_UNORM = 0xDA,
|
||||
RG16_SNORM = 0xDB,
|
||||
RG16_SINT = 0xDC,
|
||||
RG16_UINT = 0xDD,
|
||||
RG16_FLOAT = 0xDE,
|
||||
R11G11B10_FLOAT = 0xE0,
|
||||
R16_FLOAT = 0xF2,
|
||||
R8_UNORM = 0xF3,
|
||||
};
|
||||
|
||||
enum class DepthFormat : u32 {
|
||||
|
||||
@@ -13,8 +13,10 @@ GPUVAddr MemoryManager::AllocateSpace(u64 size, u64 align) {
|
||||
ASSERT(gpu_addr);
|
||||
|
||||
for (u64 offset = 0; offset < size; offset += PAGE_SIZE) {
|
||||
ASSERT(PageSlot(*gpu_addr + offset) == static_cast<u64>(PageStatus::Unmapped));
|
||||
PageSlot(*gpu_addr + offset) = static_cast<u64>(PageStatus::Allocated);
|
||||
VAddr& slot = PageSlot(*gpu_addr + offset);
|
||||
|
||||
ASSERT(slot == static_cast<u64>(PageStatus::Unmapped));
|
||||
slot = static_cast<u64>(PageStatus::Allocated);
|
||||
}
|
||||
|
||||
return *gpu_addr;
|
||||
@@ -22,8 +24,10 @@ GPUVAddr MemoryManager::AllocateSpace(u64 size, u64 align) {
|
||||
|
||||
GPUVAddr MemoryManager::AllocateSpace(GPUVAddr gpu_addr, u64 size, u64 align) {
|
||||
for (u64 offset = 0; offset < size; offset += PAGE_SIZE) {
|
||||
ASSERT(PageSlot(gpu_addr + offset) == static_cast<u64>(PageStatus::Unmapped));
|
||||
PageSlot(gpu_addr + offset) = static_cast<u64>(PageStatus::Allocated);
|
||||
VAddr& slot = PageSlot(gpu_addr + offset);
|
||||
|
||||
ASSERT(slot == static_cast<u64>(PageStatus::Unmapped));
|
||||
slot = static_cast<u64>(PageStatus::Allocated);
|
||||
}
|
||||
|
||||
return gpu_addr;
|
||||
@@ -34,8 +38,10 @@ GPUVAddr MemoryManager::MapBufferEx(VAddr cpu_addr, u64 size) {
|
||||
ASSERT(gpu_addr);
|
||||
|
||||
for (u64 offset = 0; offset < size; offset += PAGE_SIZE) {
|
||||
ASSERT(PageSlot(*gpu_addr + offset) == static_cast<u64>(PageStatus::Unmapped));
|
||||
PageSlot(*gpu_addr + offset) = cpu_addr + offset;
|
||||
VAddr& slot = PageSlot(*gpu_addr + offset);
|
||||
|
||||
ASSERT(slot == static_cast<u64>(PageStatus::Unmapped));
|
||||
slot = cpu_addr + offset;
|
||||
}
|
||||
|
||||
MappedRegion region{cpu_addr, *gpu_addr, size};
|
||||
@@ -48,8 +54,10 @@ GPUVAddr MemoryManager::MapBufferEx(VAddr cpu_addr, GPUVAddr gpu_addr, u64 size)
|
||||
ASSERT((gpu_addr & PAGE_MASK) == 0);
|
||||
|
||||
for (u64 offset = 0; offset < size; offset += PAGE_SIZE) {
|
||||
ASSERT(PageSlot(gpu_addr + offset) == static_cast<u64>(PageStatus::Allocated));
|
||||
PageSlot(gpu_addr + offset) = cpu_addr + offset;
|
||||
VAddr& slot = PageSlot(gpu_addr + offset);
|
||||
|
||||
ASSERT(slot == static_cast<u64>(PageStatus::Allocated));
|
||||
slot = cpu_addr + offset;
|
||||
}
|
||||
|
||||
MappedRegion region{cpu_addr, gpu_addr, size};
|
||||
@@ -62,9 +70,11 @@ GPUVAddr MemoryManager::UnmapBuffer(GPUVAddr gpu_addr, u64 size) {
|
||||
ASSERT((gpu_addr & PAGE_MASK) == 0);
|
||||
|
||||
for (u64 offset = 0; offset < size; offset += PAGE_SIZE) {
|
||||
ASSERT(PageSlot(gpu_addr + offset) != static_cast<u64>(PageStatus::Allocated) &&
|
||||
PageSlot(gpu_addr + offset) != static_cast<u64>(PageStatus::Unmapped));
|
||||
PageSlot(gpu_addr + offset) = static_cast<u64>(PageStatus::Unmapped);
|
||||
VAddr& slot = PageSlot(gpu_addr + offset);
|
||||
|
||||
ASSERT(slot != static_cast<u64>(PageStatus::Allocated) &&
|
||||
slot != static_cast<u64>(PageStatus::Unmapped));
|
||||
slot = static_cast<u64>(PageStatus::Unmapped);
|
||||
}
|
||||
|
||||
// Delete the region mappings that are contained within the unmapped region
|
||||
@@ -128,9 +138,7 @@ VAddr& MemoryManager::PageSlot(GPUVAddr gpu_addr) {
|
||||
auto& block = page_table[(gpu_addr >> (PAGE_BITS + PAGE_TABLE_BITS)) & PAGE_TABLE_MASK];
|
||||
if (!block) {
|
||||
block = std::make_unique<PageBlock>();
|
||||
for (unsigned index = 0; index < PAGE_BLOCK_SIZE; index++) {
|
||||
(*block)[index] = static_cast<u64>(PageStatus::Unmapped);
|
||||
}
|
||||
block->fill(static_cast<VAddr>(PageStatus::Unmapped));
|
||||
}
|
||||
return (*block)[(gpu_addr >> PAGE_BITS) & PAGE_BLOCK_MASK];
|
||||
}
|
||||
|
||||
@@ -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!");
|
||||
@@ -694,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();
|
||||
|
||||
@@ -135,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;
|
||||
|
||||
@@ -167,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;
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user