diff options
Diffstat (limited to 'src')
58 files changed, 597 insertions, 262 deletions
diff --git a/src/citra/citra.cpp b/src/citra/citra.cpp index 415b98a05..40e40f192 100644 --- a/src/citra/citra.cpp +++ b/src/citra/citra.cpp @@ -19,6 +19,8 @@ #include "common/logging/log.h" #include "common/logging/backend.h" #include "common/logging/filter.h" +#include "common/make_unique.h" +#include "common/scope_exit.h" #include "core/settings.h" #include "core/system.h" @@ -64,6 +66,7 @@ int main(int argc, char **argv) { Log::SetFilter(&log_filter); MicroProfileOnThreadCreate("EmuThread"); + SCOPE_EXIT({ MicroProfileShutdown(); }); if (boot_filename.empty()) { LOG_CRITICAL(Frontend, "Failed to load ROM: No ROM specified"); @@ -76,12 +79,13 @@ int main(int argc, char **argv) { GDBStub::ToggleServer(Settings::values.use_gdbstub); GDBStub::SetServerPort(static_cast<u32>(Settings::values.gdbstub_port)); - EmuWindow_SDL2* emu_window = new EmuWindow_SDL2; + std::unique_ptr<EmuWindow_SDL2> emu_window = Common::make_unique<EmuWindow_SDL2>(); VideoCore::g_hw_renderer_enabled = Settings::values.use_hw_renderer; VideoCore::g_shader_jit_enabled = Settings::values.use_shader_jit; - System::Init(emu_window); + System::Init(emu_window.get()); + SCOPE_EXIT({ System::Shutdown(); }); Loader::ResultStatus load_result = Loader::LoadFile(boot_filename); if (Loader::ResultStatus::Success != load_result) { @@ -93,11 +97,5 @@ int main(int argc, char **argv) { Core::RunLoop(); } - System::Shutdown(); - - delete emu_window; - - MicroProfileShutdown(); - return 0; } diff --git a/src/citra/emu_window/emu_window_sdl2.cpp b/src/citra/emu_window/emu_window_sdl2.cpp index 1fed82e78..924189f4c 100644 --- a/src/citra/emu_window/emu_window_sdl2.cpp +++ b/src/citra/emu_window/emu_window_sdl2.cpp @@ -73,6 +73,10 @@ EmuWindow_SDL2::EmuWindow_SDL2() { SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0); std::string window_title = Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc); render_window = SDL_CreateWindow(window_title.c_str(), diff --git a/src/citra_qt/debugger/graphics_vertex_shader.cpp b/src/citra_qt/debugger/graphics_vertex_shader.cpp index a11c61667..d648d4640 100644 --- a/src/citra_qt/debugger/graphics_vertex_shader.cpp +++ b/src/citra_qt/debugger/graphics_vertex_shader.cpp @@ -179,9 +179,17 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con AlignToColumn(kOutputColumnWidth); print_input(output, src1, swizzle.negate_src1, SelectorToString(swizzle.src1_selector)); AlignToColumn(kInputOperandColumnWidth); - print_input(output, src2, swizzle.negate_src2, SelectorToString(swizzle.src2_selector)); + if (src_is_inverted) { + print_input(output, src2, swizzle.negate_src2, SelectorToString(swizzle.src2_selector)); + } else { + print_input(output, src2, swizzle.negate_src2, SelectorToString(swizzle.src2_selector), true, instr.mad.AddressRegisterName()); + } AlignToColumn(kInputOperandColumnWidth); - print_input(output, src3, swizzle.negate_src3, SelectorToString(swizzle.src3_selector)); + if (src_is_inverted) { + print_input(output, src3, swizzle.negate_src3, SelectorToString(swizzle.src3_selector), true, instr.mad.AddressRegisterName()); + } else { + print_input(output, src3, swizzle.negate_src3, SelectorToString(swizzle.src3_selector)); + } AlignToColumn(kInputOperandColumnWidth); break; } @@ -498,8 +506,8 @@ void GraphicsVertexShaderWidget::Reload(bool replace_vertex_data, void* vertex_d // Reload widget state for (int attr = 0; attr < num_attributes; ++attr) { unsigned source_attr = shader_config.input_register_map.GetRegisterForAttribute(attr); - input_data_mapping[source_attr]->setText(QString("-> v%1").arg(attr)); - input_data_container[source_attr]->setVisible(true); + input_data_mapping[attr]->setText(QString("-> v%1").arg(source_attr)); + input_data_container[attr]->setVisible(true); } // Only show input attributes which are used as input to the shader for (unsigned int attr = num_attributes; attr < 16; ++attr) { diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index 57adbc136..32cceaf7e 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -310,6 +310,7 @@ bool GMainWindow::LoadROM(const std::string& filename) { void GMainWindow::BootGame(const std::string& filename) { LOG_INFO(Frontend, "Citra starting..."); + StoreRecentFile(filename); // Put the filename on top of the list if (!InitializeSystem()) return; @@ -374,11 +375,11 @@ void GMainWindow::ShutdownGame() { emulation_running = false; } -void GMainWindow::StoreRecentFile(const QString& filename) +void GMainWindow::StoreRecentFile(const std::string& filename) { QSettings settings; QStringList recent_files = settings.value("recentFiles").toStringList(); - recent_files.prepend(filename); + recent_files.prepend(QString::fromStdString(filename)); recent_files.removeDuplicates(); while (recent_files.size() > max_recent_files_item) { recent_files.removeLast(); @@ -426,7 +427,6 @@ void GMainWindow::OnMenuLoadFile() { QString filename = QFileDialog::getOpenFileName(this, tr("Load File"), rom_path, tr("3DS executable (*.3ds *.3dsx *.elf *.axf *.cci *.cxi)")); if (!filename.isEmpty()) { settings.setValue("romsPath", QFileInfo(filename).path()); - StoreRecentFile(filename); BootGame(filename.toLocal8Bit().data()); } @@ -462,7 +462,6 @@ void GMainWindow::OnMenuRecentFile() { QFileInfo file_info(filename); if (file_info.exists()) { BootGame(filename.toLocal8Bit().data()); - StoreRecentFile(filename); // Put the filename on top of the list } else { // Display an error message and remove the file from the list. QMessageBox::information(this, tr("File not found"), tr("File \"%1\" not found").arg(filename)); diff --git a/src/citra_qt/main.h b/src/citra_qt/main.h index 945aea0cd..6e4e56689 100644 --- a/src/citra_qt/main.h +++ b/src/citra_qt/main.h @@ -75,7 +75,7 @@ private: * * @param filename the filename to store */ - void StoreRecentFile(const QString& filename); + void StoreRecentFile(const std::string& filename); /** * Updates the recent files menu. diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 959084cdf..1c9be718f 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -22,6 +22,7 @@ set(SRCS ) set(HEADERS + alignment.h assert.h bit_field.h bit_set.h diff --git a/src/common/alignment.h b/src/common/alignment.h new file mode 100644 index 000000000..b77da4a92 --- /dev/null +++ b/src/common/alignment.h @@ -0,0 +1,22 @@ +// This file is under the public domain. + +#pragma once + +#include <cstddef> +#include <type_traits> + +namespace Common { + +template <typename T> +constexpr T AlignUp(T value, size_t size) { + static_assert(std::is_unsigned<T>::value, "T must be an unsigned value."); + return static_cast<T>(value + (size - value % size) % size); +} + +template <typename T> +constexpr T AlignDown(T value, size_t size) { + static_assert(std::is_unsigned<T>::value, "T must be an unsigned value."); + return static_cast<T>(value - value % size); +} + +} // namespace Common diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h index ed20c3629..aa6aff7b9 100644 --- a/src/common/common_funcs.h +++ b/src/common/common_funcs.h @@ -18,19 +18,11 @@ #define INSERT_PADDING_BYTES(num_bytes) u8 CONCAT2(pad, __LINE__)[(num_bytes)] #define INSERT_PADDING_WORDS(num_words) u32 CONCAT2(pad, __LINE__)[(num_words)] +// Inlining #ifdef _WIN32 - // Alignment #define FORCE_INLINE __forceinline - #define MEMORY_ALIGNED16(x) __declspec(align(16)) x - #define MEMORY_ALIGNED32(x) __declspec(align(32)) x - #define MEMORY_ALIGNED64(x) __declspec(align(64)) x - #define MEMORY_ALIGNED128(x) __declspec(align(128)) x #else #define FORCE_INLINE inline __attribute__((always_inline)) - #define MEMORY_ALIGNED16(x) __attribute__((aligned(16))) x - #define MEMORY_ALIGNED32(x) __attribute__((aligned(32))) x - #define MEMORY_ALIGNED64(x) __attribute__((aligned(64))) x - #define MEMORY_ALIGNED128(x) __attribute__((aligned(128))) x #endif #ifndef _MSC_VER diff --git a/src/common/common_types.h b/src/common/common_types.h index fa3e0b8d6..9f51dff18 100644 --- a/src/common/common_types.h +++ b/src/common/common_types.h @@ -53,9 +53,9 @@ typedef u32 PAddr; ///< Represents a pointer in the ARM11 physical address space // An inheritable class to disallow the copy constructor and operator= functions class NonCopyable { protected: - NonCopyable() = default; + constexpr NonCopyable() = default; ~NonCopyable() = default; - NonCopyable(NonCopyable&) = delete; - NonCopyable& operator=(NonCopyable&) = delete; + NonCopyable(const NonCopyable&) = delete; + NonCopyable& operator=(const NonCopyable&) = delete; }; diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 54291429a..4c86151ab 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -42,6 +42,7 @@ namespace Log { SUB(Service, AM) \ SUB(Service, PTM) \ SUB(Service, LDR) \ + SUB(Service, NDM) \ SUB(Service, NIM) \ SUB(Service, NWM) \ SUB(Service, CAM) \ diff --git a/src/common/logging/log.h b/src/common/logging/log.h index 4b01805ae..e4c39c308 100644 --- a/src/common/logging/log.h +++ b/src/common/logging/log.h @@ -57,6 +57,7 @@ enum class Class : ClassType { Service_AM, ///< The AM (Application manager) service Service_PTM, ///< The PTM (Power status & misc.) service Service_LDR, ///< The LDR (3ds dll loader) service + Service_NDM, ///< The NDM (Network daemon manager) service Service_NIM, ///< The NIM (Network interface manager) service Service_NWM, ///< The NWM (Network wlan manager) service Service_CAM, ///< The CAM (Camera) service diff --git a/src/common/vector_math.h b/src/common/vector_math.h index 02688e35e..cfb9481b6 100644 --- a/src/common/vector_math.h +++ b/src/common/vector_math.h @@ -447,7 +447,10 @@ public: void SetZero() { - x=0; y=0; z=0; + x = 0; + y = 0; + z = 0; + w = 0; } // Common alias: RGBA (colors) diff --git a/src/common/x64/emitter.h b/src/common/x64/emitter.h index 2dd0dc94e..7c6548fb5 100644 --- a/src/common/x64/emitter.h +++ b/src/common/x64/emitter.h @@ -157,45 +157,37 @@ class XEmitter; // RIP addressing does not benefit from micro op fusion on Core arch struct OpArg { - OpArg() {} // dummy op arg, used for storage - OpArg(u64 _offset, int _scale, X64Reg rmReg = RAX, X64Reg scaledReg = RAX) + friend class XEmitter; + + constexpr OpArg() = default; // dummy op arg, used for storage + constexpr OpArg(u64 offset_, int scale_, X64Reg rmReg = RAX, X64Reg scaledReg = RAX) + : scale(static_cast<u8>(scale_)) + , offsetOrBaseReg(static_cast<u16>(rmReg)) + , indexReg(static_cast<u16>(scaledReg)) + , offset(offset_) { - operandReg = 0; - scale = (u8)_scale; - offsetOrBaseReg = (u16)rmReg; - indexReg = (u16)scaledReg; - //if scale == 0 never mind offsetting - offset = _offset; } - bool operator==(const OpArg &b) const + + constexpr bool operator==(const OpArg &b) const { - return operandReg == b.operandReg && scale == b.scale && offsetOrBaseReg == b.offsetOrBaseReg && - indexReg == b.indexReg && offset == b.offset; + return operandReg == b.operandReg && + scale == b.scale && + offsetOrBaseReg == b.offsetOrBaseReg && + indexReg == b.indexReg && + offset == b.offset; } + void WriteRex(XEmitter *emit, int opBits, int bits, int customOp = -1) const; void WriteVex(XEmitter* emit, X64Reg regOp1, X64Reg regOp2, int L, int pp, int mmmmm, int W = 0) const; void WriteRest(XEmitter *emit, int extraBytes=0, X64Reg operandReg=INVALID_REG, bool warn_64bit_offset = true) const; - void WriteFloatModRM(XEmitter *emit, FloatOp op); void WriteSingleByteOp(XEmitter *emit, u8 op, X64Reg operandReg, int bits); - // This one is public - must be written to - u64 offset; // use RIP-relative as much as possible - 64-bit immediates are not available. - u16 operandReg; - void WriteNormalOp(XEmitter *emit, bool toRM, NormalOp op, const OpArg &operand, int bits) const; - bool IsImm() const {return scale == SCALE_IMM8 || scale == SCALE_IMM16 || scale == SCALE_IMM32 || scale == SCALE_IMM64;} - bool IsSimpleReg() const {return scale == SCALE_NONE;} - bool IsSimpleReg(X64Reg reg) const - { - if (!IsSimpleReg()) - return false; - return GetSimpleReg() == reg; - } - bool CanDoOpWith(const OpArg &other) const + constexpr bool IsImm() const { return scale == SCALE_IMM8 || scale == SCALE_IMM16 || scale == SCALE_IMM32 || scale == SCALE_IMM64; } + constexpr bool IsSimpleReg() const { return scale == SCALE_NONE; } + constexpr bool IsSimpleReg(X64Reg reg) const { - if (IsSimpleReg()) return true; - if (!IsSimpleReg() && !other.IsSimpleReg() && !other.IsImm()) return false; - return true; + return IsSimpleReg() && GetSimpleReg() == reg; } int GetImmBits() const @@ -220,16 +212,15 @@ struct OpArg } } - X64Reg GetSimpleReg() const + constexpr X64Reg GetSimpleReg() const { - if (scale == SCALE_NONE) - return (X64Reg)offsetOrBaseReg; - else - return INVALID_REG; + return scale == SCALE_NONE + ? static_cast<X64Reg>(offsetOrBaseReg) + : INVALID_REG; } - u32 GetImmValue() const { - return (u32)offset; + constexpr u32 GetImmValue() const { + return static_cast<u32>(offset); } // For loops. @@ -238,56 +229,60 @@ struct OpArg } private: - u8 scale; - u16 offsetOrBaseReg; - u16 indexReg; + u8 scale = 0; + u16 offsetOrBaseReg = 0; + u16 indexReg = 0; + u64 offset = 0; // use RIP-relative as much as possible - 64-bit immediates are not available. + u16 operandReg = 0; }; -inline OpArg M(const void *ptr) {return OpArg((u64)ptr, (int)SCALE_RIP);} template <typename T> -inline OpArg M(const T *ptr) {return OpArg((u64)(const void *)ptr, (int)SCALE_RIP);} -inline OpArg R(X64Reg value) {return OpArg(0, SCALE_NONE, value);} -inline OpArg MatR(X64Reg value) {return OpArg(0, SCALE_ATREG, value);} +inline OpArg M(const T *ptr) { return OpArg(reinterpret_cast<u64>(ptr), static_cast<int>(SCALE_RIP)); } +constexpr OpArg R(X64Reg value) { return OpArg(0, SCALE_NONE, value); } +constexpr OpArg MatR(X64Reg value) { return OpArg(0, SCALE_ATREG, value); } -inline OpArg MDisp(X64Reg value, int offset) +constexpr OpArg MDisp(X64Reg value, int offset) { - return OpArg((u32)offset, SCALE_ATREG, value); + return OpArg(static_cast<u32>(offset), SCALE_ATREG, value); } -inline OpArg MComplex(X64Reg base, X64Reg scaled, int scale, int offset) +constexpr OpArg MComplex(X64Reg base, X64Reg scaled, int scale, int offset) { return OpArg(offset, scale, base, scaled); } -inline OpArg MScaled(X64Reg scaled, int scale, int offset) +constexpr OpArg MScaled(X64Reg scaled, int scale, int offset) { - if (scale == SCALE_1) - return OpArg(offset, SCALE_ATREG, scaled); - else - return OpArg(offset, scale | 0x20, RAX, scaled); + return scale == SCALE_1 + ? OpArg(offset, SCALE_ATREG, scaled) + : OpArg(offset, scale | 0x20, RAX, scaled); } -inline OpArg MRegSum(X64Reg base, X64Reg offset) +constexpr OpArg MRegSum(X64Reg base, X64Reg offset) { return MComplex(base, offset, 1, 0); } -inline OpArg Imm8 (u8 imm) {return OpArg(imm, SCALE_IMM8);} -inline OpArg Imm16(u16 imm) {return OpArg(imm, SCALE_IMM16);} //rarely used -inline OpArg Imm32(u32 imm) {return OpArg(imm, SCALE_IMM32);} -inline OpArg Imm64(u64 imm) {return OpArg(imm, SCALE_IMM64);} -inline OpArg UImmAuto(u32 imm) { +constexpr OpArg Imm8 (u8 imm) { return OpArg(imm, SCALE_IMM8); } +constexpr OpArg Imm16(u16 imm) { return OpArg(imm, SCALE_IMM16); } //rarely used +constexpr OpArg Imm32(u32 imm) { return OpArg(imm, SCALE_IMM32); } +constexpr OpArg Imm64(u64 imm) { return OpArg(imm, SCALE_IMM64); } +constexpr OpArg UImmAuto(u32 imm) { return OpArg(imm, imm >= 128 ? SCALE_IMM32 : SCALE_IMM8); } -inline OpArg SImmAuto(s32 imm) { +constexpr OpArg SImmAuto(s32 imm) { return OpArg(imm, (imm >= 128 || imm < -128) ? SCALE_IMM32 : SCALE_IMM8); } +template <typename T> +OpArg ImmPtr(const T* imm) +{ #ifdef _ARCH_64 -inline OpArg ImmPtr(const void* imm) {return Imm64((u64)imm);} + return Imm64(reinterpret_cast<u64>(imm)); #else -inline OpArg ImmPtr(const void* imm) {return Imm32((u32)imm);} + return Imm32(reinterpret_cast<u32>(imm)); #endif +} inline u32 PtrOffset(const void* ptr, const void* base) { diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index edf5fcc44..3473e2f5b 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -26,6 +26,7 @@ set(SRCS hle/config_mem.cpp hle/hle.cpp hle/applets/applet.cpp + hle/applets/mii_selector.cpp hle/applets/swkbd.cpp hle/kernel/address_arbiter.cpp hle/kernel/event.cpp @@ -86,7 +87,8 @@ set(SRCS hle/service/ir/ir_user.cpp hle/service/ldr_ro.cpp hle/service/mic_u.cpp - hle/service/ndm_u.cpp + hle/service/ndm/ndm.cpp + hle/service/ndm/ndm_u.cpp hle/service/news/news.cpp hle/service/news/news_s.cpp hle/service/news/news_u.cpp @@ -155,6 +157,7 @@ set(HEADERS hle/function_wrappers.h hle/hle.h hle/applets/applet.h + hle/applets/mii_selector.h hle/applets/swkbd.h hle/kernel/address_arbiter.h hle/kernel/event.h @@ -216,7 +219,8 @@ set(HEADERS hle/service/ir/ir_user.h hle/service/ldr_ro.h hle/service/mic_u.h - hle/service/ndm_u.h + hle/service/ndm/ndm.h + hle/service/ndm/ndm_u.h hle/service/news/news.h hle/service/news/news_s.h hle/service/news/news_u.h diff --git a/src/core/hle/applets/applet.cpp b/src/core/hle/applets/applet.cpp index bc2a1829e..90e134437 100644 --- a/src/core/hle/applets/applet.cpp +++ b/src/core/hle/applets/applet.cpp @@ -12,6 +12,7 @@ #include "core/core_timing.h" #include "core/hle/applets/applet.h" +#include "core/hle/applets/mii_selector.h" #include "core/hle/applets/swkbd.h" #include "core/hle/result.h" #include "core/hle/service/apt/apt.h" @@ -47,7 +48,12 @@ ResultCode Applet::Create(Service::APT::AppletId id) { case Service::APT::AppletId::SoftwareKeyboard2: applets[id] = std::make_shared<SoftwareKeyboard>(id); break; + case Service::APT::AppletId::Ed1: + case Service::APT::AppletId::Ed2: + applets[id] = std::make_shared<MiiSelector>(id); + break; default: + LOG_ERROR(Service_APT, "Could not create applet %u", id); // TODO(Subv): Find the right error code return ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, ErrorSummary::NotSupported, ErrorLevel::Permanent); } diff --git a/src/core/hle/applets/mii_selector.cpp b/src/core/hle/applets/mii_selector.cpp new file mode 100644 index 000000000..708d2f630 --- /dev/null +++ b/src/core/hle/applets/mii_selector.cpp @@ -0,0 +1,75 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <cstring> +#include <string> + +#include "common/assert.h" +#include "common/logging/log.h" +#include "common/string_util.h" + +#include "core/hle/applets/mii_selector.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/shared_memory.h" +#include "core/hle/result.h" + +#include "video_core/video_core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace HLE { +namespace Applets { + +MiiSelector::MiiSelector(Service::APT::AppletId id) : Applet(id), started(false) { + // Create the SharedMemory that will hold the framebuffer data + // TODO(Subv): What size should we use here? + using Kernel::MemoryPermission; + framebuffer_memory = Kernel::SharedMemory::Create(0x1000, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, "MiiSelector Memory"); +} + +ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& parameter) { + if (parameter.signal != static_cast<u32>(Service::APT::SignalType::LibAppJustStarted)) { + LOG_ERROR(Service_APT, "unsupported signal %u", parameter.signal); + UNIMPLEMENTED(); + // TODO(Subv): Find the right error code + return ResultCode(-1); + } + + Service::APT::MessageParameter result; + // The buffer passed in parameter contains the data returned by GSPGPU::ImportDisplayCaptureInfo + result.signal = static_cast<u32>(Service::APT::SignalType::LibAppFinished); + result.data = nullptr; + result.buffer_size = 0; + result.destination_id = static_cast<u32>(Service::APT::AppletId::Application); + result.sender_id = static_cast<u32>(id); + result.object = framebuffer_memory; + + Service::APT::SendParameter(result); + return RESULT_SUCCESS; +} + +ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& parameter) { + started = true; + + // TODO(Subv): Set the expected fields in the response buffer before resending it to the application. + // TODO(Subv): Reverse the parameter format for the Mii Selector + + // Let the application know that we're closing + Service::APT::MessageParameter message; + message.buffer_size = parameter.buffer_size; + message.data = parameter.data; + message.signal = static_cast<u32>(Service::APT::SignalType::LibAppClosed); + message.destination_id = static_cast<u32>(Service::APT::AppletId::Application); + message.sender_id = static_cast<u32>(id); + Service::APT::SendParameter(message); + + started = false; + return RESULT_SUCCESS; +} + +void MiiSelector::Update() { +} + +} +} // namespace diff --git a/src/core/hle/applets/mii_selector.h b/src/core/hle/applets/mii_selector.h new file mode 100644 index 000000000..6a3e7c8eb --- /dev/null +++ b/src/core/hle/applets/mii_selector.h @@ -0,0 +1,37 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "common/common_types.h" +#include "common/common_funcs.h" + +#include "core/hle/applets/applet.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/shared_memory.h" +#include "core/hle/result.h" +#include "core/hle/service/apt/apt.h" + +namespace HLE { +namespace Applets { + +class MiiSelector final : public Applet { +public: + MiiSelector(Service::APT::AppletId id); + + ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override; + ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override; + void Update() override; + bool IsRunning() const override { return started; } + + /// TODO(Subv): Find out what this is actually used for. + /// It is believed that the application stores the current screen image here. + Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; + + /// Whether this applet is currently running instead of the host application or not. + bool started; +}; + +} +} // namespace diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index 882a51df1..4d718b681 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h @@ -10,6 +10,7 @@ #include "core/memory.h" #include "core/hle/hle.h" #include "core/hle/result.h" +#include "core/hle/svc.h" namespace HLE { diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 53feebbc0..2b7c6992a 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -35,7 +35,7 @@ void Event::Acquire() { ASSERT_MSG(!ShouldWait(), "object unavailable!"); // Release the event if it's not sticky... - if (reset_type != RESETTYPE_STICKY) + if (reset_type != ResetType::Sticky) signaled = false; } diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index 89d405236..73d0da419 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h @@ -7,10 +7,16 @@ #include "common/common_types.h" #include "core/hle/kernel/kernel.h" -#include "core/hle/svc.h" namespace Kernel { +enum class ResetType { + OneShot, + Sticky, + Pulse, +}; + + class Event final : public WaitObject { public: /** diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp index ce6bbd719..b8daaeede 100644 --- a/src/core/hle/kernel/timer.cpp +++ b/src/core/hle/kernel/timer.cpp @@ -43,7 +43,7 @@ bool Timer::ShouldWait() { void Timer::Acquire() { ASSERT_MSG( !ShouldWait(), "object unavailable!"); - if (reset_type == RESETTYPE_ONESHOT) + if (reset_type == ResetType::OneShot) signaled = false; } diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h index 540e4e187..b1db60e8f 100644 --- a/src/core/hle/kernel/timer.h +++ b/src/core/hle/kernel/timer.h @@ -6,8 +6,8 @@ #include "common/common_types.h" +#include "core/hle/kernel/event.h" #include "core/hle/kernel/kernel.h" -#include "core/hle/svc.h" namespace Kernel { diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index 69255e2ef..a49365287 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -12,6 +12,7 @@ #include "core/hle/service/apt/apt_a.h" #include "core/hle/service/apt/apt_s.h" #include "core/hle/service/apt/apt_u.h" +#include "core/hle/service/fs/archive.h" #include "core/hle/kernel/event.h" #include "core/hle/kernel/mutex.h" @@ -378,6 +379,24 @@ void StartLibraryApplet(Service::Interface* self) { cmd_buff[1] = applet->Start(parameter).raw; } +void GetAppletInfo(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + auto app_id = static_cast<AppletId>(cmd_buff[1]); + + if (auto applet = HLE::Applets::Applet::Get(app_id)) { + // TODO(Subv): Get the title id for the current applet and write it in the response[2-3] + cmd_buff[1] = RESULT_SUCCESS.raw; + cmd_buff[4] = static_cast<u32>(Service::FS::MediaType::NAND); + cmd_buff[5] = 1; // Registered + cmd_buff[6] = 1; // Loaded + cmd_buff[7] = 0; // Applet Attributes + } else { + cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, + ErrorSummary::NotFound, ErrorLevel::Status).raw; + } + LOG_WARNING(Service_APT, "(stubbed) called appid=%u", app_id); +} + void Init() { AddService(new APT_A_Interface); AddService(new APT_S_Interface); @@ -415,8 +434,8 @@ void Init() { cpu_percent = 0; // TODO(bunnei): Check if these are created in Initialize or on APT process startup. - notification_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Notification"); - parameter_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Start"); + notification_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "APT_U:Notification"); + parameter_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "APT_U:Start"); next_parameter.signal = static_cast<u32>(SignalType::AppJustStarted); next_parameter.destination_id = 0x300; diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h index 4a72b6b5c..47a97c1a1 100644 --- a/src/core/hle/service/apt/apt.h +++ b/src/core/hle/service/apt/apt.h @@ -54,7 +54,7 @@ enum class AppletId : u32 { Notifications = 0x116, Miiverse = 0x117, SoftwareKeyboard1 = 0x201, - Ed = 0x202, + Ed1 = 0x202, PnoteApp = 0x204, SnoteApp = 0x205, Error = 0x206, @@ -64,6 +64,7 @@ enum class AppletId : u32 { Application = 0x300, AnyLibraryApplet = 0x400, SoftwareKeyboard2 = 0x401, + Ed2 = 0x402, }; /// Send a parameter to the currently-running application, which will read it via ReceiveParameter @@ -133,6 +134,20 @@ void Enable(Service::Interface* self); void GetAppletManInfo(Service::Interface* self); /** + * APT::GetAppletInfo service function. + * Inputs: + * 1 : AppId + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2-3 : Title ID + * 4 : Media Type + * 5 : Registered + * 6 : Loaded + * 7 : Attributes + */ +void GetAppletInfo(Service::Interface* self); + +/** * APT::IsRegistered service function. This returns whether the specified AppID is registered with NS yet. * An AppID is "registered" once the process associated with the AppID uses APT:Enable. Home Menu uses this * command to determine when the launched process is running and to determine when to stop using GSP etc, diff --git a/src/core/hle/service/apt/apt_u.cpp b/src/core/hle/service/apt/apt_u.cpp index 209a0055b..b13b51549 100644 --- a/src/core/hle/service/apt/apt_u.cpp +++ b/src/core/hle/service/apt/apt_u.cpp @@ -14,7 +14,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00030040, Enable, "Enable"}, {0x00040040, nullptr, "Finalize"}, {0x00050040, GetAppletManInfo, "GetAppletManInfo"}, - {0x00060040, nullptr, "GetAppletInfo"}, + {0x00060040, GetAppletInfo, "GetAppletInfo"}, {0x00070000, nullptr, "GetLastSignaledAppletId"}, {0x00080000, nullptr, "CountRegisteredApplet"}, {0x00090040, IsRegistered, "IsRegistered"}, diff --git a/src/core/hle/service/cam/cam.cpp b/src/core/hle/service/cam/cam.cpp index 4d714037f..9df48a650 100644 --- a/src/core/hle/service/cam/cam.cpp +++ b/src/core/hle/service/cam/cam.cpp @@ -293,10 +293,10 @@ void Init() { AddService(new CAM_S_Interface); AddService(new CAM_U_Interface); - completion_event_cam1 = Kernel::Event::Create(RESETTYPE_ONESHOT, "CAM_U::completion_event_cam1"); - completion_event_cam2 = Kernel::Event::Create(RESETTYPE_ONESHOT, "CAM_U::completion_event_cam2"); - interrupt_error_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "CAM_U::interrupt_error_event"); - vsync_interrupt_error_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "CAM_U::vsync_interrupt_error_event"); + completion_event_cam1 = Kernel::Event::Create(ResetType::OneShot, "CAM_U::completion_event_cam1"); + completion_event_cam2 = Kernel::Event::Create(ResetType::OneShot, "CAM_U::completion_event_cam2"); + interrupt_error_event = Kernel::Event::Create(ResetType::OneShot, "CAM_U::interrupt_error_event"); + vsync_interrupt_error_event = Kernel::Event::Create(ResetType::OneShot, "CAM_U::vsync_interrupt_error_event"); } void Shutdown() { diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp index 3ba24d466..08e437125 100644 --- a/src/core/hle/service/dsp_dsp.cpp +++ b/src/core/hle/service/dsp_dsp.cpp @@ -457,7 +457,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - semaphore_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "DSP_DSP::semaphore_event"); + semaphore_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "DSP_DSP::semaphore_event"); read_pipe_count = 0; Register(FunctionTable); diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index 632620a56..e6c1f3616 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp @@ -707,6 +707,30 @@ static void GetPriority(Service::Interface* self) { LOG_DEBUG(Service_FS, "called priority=0x%X", priority); } +/** + * FS_User::GetArchiveResource service function. + * Inputs: + * 0 : 0x08490040 + * 1 : Media type + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Sector byte-size + * 3 : Cluster byte-size + * 4 : Partition capacity in clusters + * 5 : Available free space in clusters + */ +static void GetArchiveResource(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + LOG_WARNING(Service_FS, "(STUBBED) called Media type=0x%08X", cmd_buff[1]); + + cmd_buff[1] = RESULT_SUCCESS.raw; + cmd_buff[2] = 512; + cmd_buff[3] = 16384; + cmd_buff[4] = 0x80000; // 8GiB capacity + cmd_buff[5] = 0x80000; // 8GiB free +} + const Interface::FunctionInfo FunctionTable[] = { {0x000100C6, nullptr, "Dummy1"}, {0x040100C4, nullptr, "Control"}, @@ -782,7 +806,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x08460102, nullptr, "GetLegacyRomHeader2"}, {0x08470180, nullptr, "FormatCtrCardUserSaveData"}, {0x08480042, nullptr, "GetSdmcCtrRootPath"}, - {0x08490040, nullptr, "GetArchiveResource"}, + {0x08490040, GetArchiveResource, "GetArchiveResource"}, {0x084A0002, nullptr, "ExportIntegrityVerificationSeed"}, {0x084B0002, nullptr, "ImportIntegrityVerificationSeed"}, {0x084C0242, FormatSaveData, "FormatSaveData"}, diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp index 5838b6d71..2ace2cade 100644 --- a/src/core/hle/service/gsp_gpu.cpp +++ b/src/core/hle/service/gsp_gpu.cpp @@ -275,7 +275,7 @@ static void FlushDataCache(Service::Interface* self) { u32 size = cmd_buff[2]; u32 process = cmd_buff[4]; - VideoCore::g_renderer->rasterizer->InvalidateRegion(Memory::VirtualToPhysicalAddress(address), size); + VideoCore::g_renderer->Rasterizer()->InvalidateRegion(Memory::VirtualToPhysicalAddress(address), size); // TODO(purpasmart96): Verify return header on HW @@ -320,7 +320,7 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) { * @todo This probably does not belong in the GSP module, instead move to video_core */ void SignalInterrupt(InterruptId interrupt_id) { - if (0 == g_interrupt_event) { + if (nullptr == g_interrupt_event) { LOG_WARNING(Service_GSP, "cannot synchronize until GSP event has been created!"); return; } @@ -365,7 +365,7 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { // GX request DMA - typically used for copying memory from GSP heap to VRAM case CommandId::REQUEST_DMA: - VideoCore::g_renderer->rasterizer->FlushRegion(Memory::VirtualToPhysicalAddress(command.dma_request.source_address), + VideoCore::g_renderer->Rasterizer()->FlushRegion(Memory::VirtualToPhysicalAddress(command.dma_request.source_address), command.dma_request.size); memcpy(Memory::GetPointer(command.dma_request.dest_address), @@ -373,7 +373,7 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { command.dma_request.size); SignalInterrupt(InterruptId::DMA); - VideoCore::g_renderer->rasterizer->InvalidateRegion(Memory::VirtualToPhysicalAddress(command.dma_request.dest_address), + VideoCore::g_renderer->Rasterizer()->InvalidateRegion(Memory::VirtualToPhysicalAddress(command.dma_request.dest_address), command.dma_request.size); break; @@ -467,7 +467,7 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { if (region.size == 0) break; - VideoCore::g_renderer->rasterizer->InvalidateRegion( + VideoCore::g_renderer->Rasterizer()->InvalidateRegion( Memory::VirtualToPhysicalAddress(region.address), region.size); } break; diff --git a/src/core/hle/service/gsp_lcd.cpp b/src/core/hle/service/gsp_lcd.cpp index 7ad7f081f..c700c21c5 100644 --- a/src/core/hle/service/gsp_lcd.cpp +++ b/src/core/hle/service/gsp_lcd.cpp @@ -14,6 +14,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00100000, nullptr, "PowerOffAllBacklights"}, {0x00110040, nullptr, "PowerOnBacklight"}, {0x00120040, nullptr, "PowerOffBacklight"}, + {0x00130040, nullptr, "SetLedForceOff"} }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 11d7e69a1..cb4fd38e2 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -68,7 +68,7 @@ void Update() { mem->pad.current_state.hex = state.hex; mem->pad.index = next_pad_index; - next_touch_index = (next_touch_index + 1) % mem->pad.entries.size(); + next_pad_index = (next_pad_index + 1) % mem->pad.entries.size(); // Get the previous Pad state u32 last_entry_index = (mem->pad.index - 1) % mem->pad.entries.size(); @@ -201,11 +201,11 @@ void Init() { next_touch_index = 0; // Create event handles - event_pad_or_touch_1 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch1"); - event_pad_or_touch_2 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch2"); - event_accelerometer = Event::Create(RESETTYPE_ONESHOT, "HID:EventAccelerometer"); - event_gyroscope = Event::Create(RESETTYPE_ONESHOT, "HID:EventGyroscope"); - event_debug_pad = Event::Create(RESETTYPE_ONESHOT, "HID:EventDebugPad"); + event_pad_or_touch_1 = Event::Create(ResetType::OneShot, "HID:EventPadOrTouch1"); + event_pad_or_touch_2 = Event::Create(ResetType::OneShot, "HID:EventPadOrTouch2"); + event_accelerometer = Event::Create(ResetType::OneShot, "HID:EventAccelerometer"); + event_gyroscope = Event::Create(ResetType::OneShot, "HID:EventGyroscope"); + event_debug_pad = Event::Create(ResetType::OneShot, "HID:EventDebugPad"); } void Shutdown() { diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp index 79009053e..0855ab227 100644 --- a/src/core/hle/service/http_c.cpp +++ b/src/core/hle/service/http_c.cpp @@ -49,6 +49,8 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00250080, nullptr, "AddDefaultCert"}, {0x00260080, nullptr, "SelectRootCertChain"}, {0x002700C4, nullptr, "SetClientCert"}, + {0x002B0080, nullptr, "SetSSLOpt"}, + {0x002C0080, nullptr, "SetSSLClearOpt"}, {0x002D0000, nullptr, "CreateRootCertChain"}, {0x002E0040, nullptr, "DestroyRootCertChain"}, {0x002F0082, nullptr, "RootCertChainAddCert"}, diff --git a/src/core/hle/service/ir/ir.cpp b/src/core/hle/service/ir/ir.cpp index c2121cb2e..505c441c6 100644 --- a/src/core/hle/service/ir/ir.cpp +++ b/src/core/hle/service/ir/ir.cpp @@ -99,8 +99,8 @@ void Init() { transfer_shared_memory = nullptr; // Create event handle(s) - handle_event = Event::Create(RESETTYPE_ONESHOT, "IR:HandleEvent"); - conn_status_event = Event::Create(RESETTYPE_ONESHOT, "IR:ConnectionStatusEvent"); + handle_event = Event::Create(ResetType::OneShot, "IR:HandleEvent"); + conn_status_event = Event::Create(ResetType::OneShot, "IR:ConnectionStatusEvent"); } void Shutdown() { diff --git a/src/core/hle/service/ndm/ndm.cpp b/src/core/hle/service/ndm/ndm.cpp new file mode 100644 index 000000000..47076a7b8 --- /dev/null +++ b/src/core/hle/service/ndm/ndm.cpp @@ -0,0 +1,47 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/common_types.h" +#include "common/logging/log.h" +#include "core/hle/service/service.h" +#include "core/hle/service/ndm/ndm.h" +#include "core/hle/service/ndm/ndm_u.h" + +namespace Service { +namespace NDM { + +void SuspendDaemons(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + LOG_WARNING(Service_NDM, "(STUBBED) bit_mask=0x%08X ", cmd_buff[1]); + + cmd_buff[1] = RESULT_SUCCESS.raw; // No error +} + +void ResumeDaemons(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + LOG_WARNING(Service_NDM, "(STUBBED) bit_mask=0x%08X ", cmd_buff[1]); + + cmd_buff[1] = RESULT_SUCCESS.raw; // No error +} + +void OverrideDefaultDaemons(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + LOG_WARNING(Service_NDM, "(STUBBED) bit_mask=0x%08X ", cmd_buff[1]); + + cmd_buff[1] = RESULT_SUCCESS.raw; // No error +} + +void Init() { + AddService(new NDM_U_Interface); +} + +void Shutdown() { + +} + +}// namespace NDM +}// namespace Service diff --git a/src/core/hle/service/ndm/ndm.h b/src/core/hle/service/ndm/ndm.h new file mode 100644 index 000000000..734730f8c --- /dev/null +++ b/src/core/hle/service/ndm/ndm.h @@ -0,0 +1,52 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "common/common_types.h" + +namespace Service { + +class Interface; + +namespace NDM { + +/** + * SuspendDaemons + * Inputs: + * 0 : Command header (0x00020082) + * 1 : Daemon bit mask + * Outputs: + * 1 : Result, 0 on success, otherwise error code + */ +void SuspendDaemons(Service::Interface* self); + +/** + * ResumeDaemons + * Inputs: + * 0 : Command header (0x00020082) + * 1 : Daemon bit mask + * Outputs: + * 1 : Result, 0 on success, otherwise error code + */ +void ResumeDaemons(Service::Interface* self); + +/** + * OverrideDefaultDaemons + * Inputs: + * 0 : Command header (0x00020082) + * 1 : Daemon bit mask + * Outputs: + * 1 : Result, 0 on success, otherwise error code + */ +void OverrideDefaultDaemons(Service::Interface* self); + +/// Initialize NDM service +void Init(); + +/// Shutdown NDM service +void Shutdown(); + +}// namespace NDM +}// namespace Service diff --git a/src/core/hle/service/ndm_u.cpp b/src/core/hle/service/ndm/ndm_u.cpp index 8fdf1ef90..bf95cc7aa 100644 --- a/src/core/hle/service/ndm_u.cpp +++ b/src/core/hle/service/ndm/ndm_u.cpp @@ -2,12 +2,11 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include "core/hle/service/ndm_u.h" +#include "core/hle/service/ndm/ndm.h" +#include "core/hle/service/ndm/ndm_u.h" -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Namespace NDM_U - -namespace NDM_U { +namespace Service { +namespace NDM { const Interface::FunctionInfo FunctionTable[] = { {0x00010042, nullptr, "EnterExclusiveState"}, @@ -15,8 +14,8 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00030000, nullptr, "QueryExclusiveMode"}, {0x00040002, nullptr, "LockState"}, {0x00050002, nullptr, "UnlockState"}, - {0x00060040, nullptr, "SuspendDaemons"}, - {0x00070040, nullptr, "ResumeDaemons"}, + {0x00060040, SuspendDaemons, "SuspendDaemons"}, + {0x00070040, ResumeDaemons, "ResumeDaemons"}, {0x00080040, nullptr, "DisableWifiUsage"}, {0x00090000, nullptr, "EnableWifiUsage"}, {0x000A0000, nullptr, "GetCurrentState"}, @@ -29,17 +28,15 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00110000, nullptr, "GetScanInterval"}, {0x00120040, nullptr, "SetRetryInterval"}, {0x00130000, nullptr, "GetRetryInterval"}, - {0x00140040, nullptr, "OverrideDefaultDaemons"}, + {0x00140040, OverrideDefaultDaemons, "OverrideDefaultDaemons"}, {0x00150000, nullptr, "ResetDefaultDaemons"}, {0x00160000, nullptr, "GetDefaultDaemons"}, {0x00170000, nullptr, "ClearHalfAwakeMacFilter"}, }; -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Interface class - -Interface::Interface() { +NDM_U_Interface::NDM_U_Interface() { Register(FunctionTable); } -} // namespace +} // namespace NDM +} // namespace Service diff --git a/src/core/hle/service/ndm_u.h b/src/core/hle/service/ndm/ndm_u.h index 51c4b3902..d567abc84 100644 --- a/src/core/hle/service/ndm_u.h +++ b/src/core/hle/service/ndm/ndm_u.h @@ -6,20 +6,17 @@ #include "core/hle/service/service.h" -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Namespace NDM +namespace Service { +namespace NDM { -// No idea what this is - -namespace NDM_U { - -class Interface : public Service::Interface { +class NDM_U_Interface : public Service::Interface { public: - Interface(); + NDM_U_Interface(); std::string GetPortName() const override { return "ndm:u"; } }; -} // namespace +} // namespace NDM +} // namespace Service diff --git a/src/core/hle/service/nwm_uds.cpp b/src/core/hle/service/nwm_uds.cpp index dc80984b2..ae4640409 100644 --- a/src/core/hle/service/nwm_uds.cpp +++ b/src/core/hle/service/nwm_uds.cpp @@ -138,7 +138,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - handle_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "NWM_UDS::handle_event"); + handle_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "NWM_UDS::handle_event"); Register(FunctionTable); } diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 0de0b13a3..35b648409 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -16,7 +16,6 @@ #include "core/hle/service/http_c.h" #include "core/hle/service/ldr_ro.h" #include "core/hle/service/mic_u.h" -#include "core/hle/service/ndm_u.h" #include "core/hle/service/ns_s.h" #include "core/hle/service/nwm_uds.h" #include "core/hle/service/pm_app.h" @@ -35,6 +34,7 @@ #include "core/hle/service/cfg/cfg.h" #include "core/hle/service/hid/hid.h" #include "core/hle/service/ir/ir.h" +#include "core/hle/service/ndm/ndm.h" #include "core/hle/service/news/news.h" #include "core/hle/service/nim/nim.h" #include "core/hle/service/ptm/ptm.h" @@ -114,6 +114,7 @@ void Init() { Service::HID::Init(); Service::IR::Init(); Service::NEWS::Init(); + Service::NDM::Init(); Service::NIM::Init(); Service::PTM::Init(); @@ -126,7 +127,6 @@ void Init() { AddService(new HTTP_C::Interface); AddService(new LDR_RO::Interface); AddService(new MIC_U::Interface); - AddService(new NDM_U::Interface); AddService(new NS_S::Interface); AddService(new NWM_UDS::Interface); AddService(new PM_APP::Interface); @@ -141,6 +141,7 @@ void Init() { void Shutdown() { Service::PTM::Shutdown(); + Service::NDM::Shutdown(); Service::NIM::Shutdown(); Service::NEWS::Shutdown(); Service::IR::Shutdown(); diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp index e603bf794..b52e52d4a 100644 --- a/src/core/hle/service/soc_u.cpp +++ b/src/core/hle/service/soc_u.cpp @@ -742,7 +742,8 @@ const Interface::FunctionInfo FunctionTable[] = { {0x000C0082, Shutdown, "Shutdown"}, {0x000D0082, nullptr, "GetHostByName"}, {0x000E00C2, nullptr, "GetHostByAddr"}, - {0x000F0106, nullptr, "unknown_resolve_ip"}, + {0x000F0106, nullptr, "GetAddrInfo"}, + {0x00100102, nullptr, "GetNameInfo"}, {0x00110102, nullptr, "GetSockOpt"}, {0x00120104, nullptr, "SetSockOpt"}, {0x001300C2, Fcntl, "Fcntl"}, @@ -759,6 +760,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x001E0040, nullptr, "ICMPClose"}, {0x001F0040, nullptr, "GetResolverInfo"}, {0x00210002, nullptr, "CloseSockets"}, + {0x00230040, nullptr, "AddGlobalSocket"}, }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index 41fc3437b..aae955bf8 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -25,7 +25,7 @@ static void GetProcSemaphore(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); // TODO(bunnei): Change to a semaphore once these have been implemented - event_handle = Kernel::Event::Create(RESETTYPE_ONESHOT, "SRV:Event"); + event_handle = Kernel::Event::Create(Kernel::ResetType::OneShot, "SRV:Event"); event_handle->Clear(); cmd_buff[1] = 0; // No error diff --git a/src/core/hle/service/ssl_c.cpp b/src/core/hle/service/ssl_c.cpp index fc7a4e6d3..14a4e98ec 100644 --- a/src/core/hle/service/ssl_c.cpp +++ b/src/core/hle/service/ssl_c.cpp @@ -66,10 +66,20 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00040040, nullptr, "DestroyRootCertChain"}, {0x00050082, nullptr, "AddTrustedRootCA"}, {0x00060080, nullptr, "RootCertChainAddDefaultCert"}, + {0x00070080, nullptr, "RootCertChainRemoveCert"}, + {0x000E0040, nullptr, "OpenDefaultClientCertContext"}, + {0x000F0040, nullptr, "CloseClientCertContext"}, {0x00110042, GenerateRandomData, "GenerateRandomData"}, + {0x00120042, nullptr, "InitializeConnectionSession"}, + {0x00130040, nullptr, "StartConnection"}, + {0x00140040, nullptr, "StartConnectionGetOut"}, {0x00150082, nullptr, "Read"}, {0x00170082, nullptr, "Write"}, {0x00180080, nullptr, "ContextSetRootCertChain"}, + {0x00190080, nullptr, "ContextSetClientCert"}, + {0x001B0080, nullptr, "ContextClearOpt"}, + {0x001E0040, nullptr, "DestroyContext"}, + {0x001F0082, nullptr, "ContextInitSharedmem"} }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/hle/service/y2r_u.cpp b/src/core/hle/service/y2r_u.cpp index bbead9344..22f373adf 100644 --- a/src/core/hle/service/y2r_u.cpp +++ b/src/core/hle/service/y2r_u.cpp @@ -267,7 +267,7 @@ static void StartConversion(Service::Interface* self) { // dst_image_size would seem to be perfect for this, but it doesn't include the gap :( u32 total_output_size = conversion.input_lines * (conversion.dst.transfer_unit + conversion.dst.gap); - VideoCore::g_renderer->rasterizer->InvalidateRegion( + VideoCore::g_renderer->Rasterizer()->InvalidateRegion( Memory::VirtualToPhysicalAddress(conversion.dst.address), total_output_size); LOG_DEBUG(Service_Y2R, "called"); @@ -424,7 +424,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - completion_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "Y2R:Completed"); + completion_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "Y2R:Completed"); std::memset(&conversion, 0, sizeof(conversion)); Register(FunctionTable); diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 7a39b101d..ae54afb1c 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -661,7 +661,7 @@ static ResultCode QueryMemory(MemoryInfo* memory_info, PageInfo* page_info, u32 static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) { using Kernel::Event; - SharedPtr<Event> evt = Kernel::Event::Create(static_cast<ResetType>(reset_type)); + SharedPtr<Event> evt = Event::Create(static_cast<Kernel::ResetType>(reset_type)); CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt))); LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", @@ -707,7 +707,7 @@ static ResultCode ClearEvent(Handle handle) { static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) { using Kernel::Timer; - SharedPtr<Timer> timer = Timer::Create(static_cast<ResetType>(reset_type)); + SharedPtr<Timer> timer = Timer::Create(static_cast<Kernel::ResetType>(reset_type)); CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer))); LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", diff --git a/src/core/hle/svc.h b/src/core/hle/svc.h index 4b9c71e06..818973eb6 100644 --- a/src/core/hle/svc.h +++ b/src/core/hle/svc.h @@ -20,22 +20,6 @@ struct PageInfo { u32 flags; }; -enum ResetType { - RESETTYPE_ONESHOT, - RESETTYPE_STICKY, - RESETTYPE_PULSE, - RESETTYPE_MAX_BIT = (1u << 31), -}; - -enum ArbitrationType { - ARBITRATIONTYPE_SIGNAL, - ARBITRATIONTYPE_WAIT_IF_LESS_THAN, - ARBITRATIONTYPE_DECREMENT_AND_WAIT_IF_LESS_THAN, - ARBITRATIONTYPE_WAIT_IF_LESS_THAN_WITH_TIMEOUT, - ARBITRATIONTYPE_DECREMENT_AND_WAIT_IF_LESS_THAN_WITH_TIMEOUT, - ARBITRATIONTYPE_MAX_BIT = (1u << 31) -}; - //////////////////////////////////////////////////////////////////////////////////////////////////// // Namespace SVC diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index 5312baa83..7e2f9cdfa 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp @@ -140,7 +140,7 @@ inline void Write(u32 addr, const T data) { GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC1); } - VideoCore::g_renderer->rasterizer->InvalidateRegion(config.GetStartAddress(), config.GetEndAddress() - config.GetStartAddress()); + VideoCore::g_renderer->Rasterizer()->InvalidateRegion(config.GetStartAddress(), config.GetEndAddress() - config.GetStartAddress()); } // Reset "trigger" flag and set the "finish" flag @@ -171,7 +171,7 @@ inline void Write(u32 addr, const T data) { u32 output_gap = config.texture_copy.output_gap * 16; size_t contiguous_input_size = config.texture_copy.size / input_width * (input_width + input_gap); - VideoCore::g_renderer->rasterizer->FlushRegion(config.GetPhysicalInputAddress(), contiguous_input_size); + VideoCore::g_renderer->Rasterizer()->FlushRegion(config.GetPhysicalInputAddress(), contiguous_input_size); u32 remaining_size = config.texture_copy.size; u32 remaining_input = input_width; @@ -204,7 +204,7 @@ inline void Write(u32 addr, const T data) { config.flags); size_t contiguous_output_size = config.texture_copy.size / output_width * (output_width + output_gap); - VideoCore::g_renderer->rasterizer->InvalidateRegion(config.GetPhysicalOutputAddress(), contiguous_output_size); + VideoCore::g_renderer->Rasterizer()->InvalidateRegion(config.GetPhysicalOutputAddress(), contiguous_output_size); GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PPF); break; @@ -231,7 +231,7 @@ inline void Write(u32 addr, const T data) { u32 input_size = config.input_width * config.input_height * GPU::Regs::BytesPerPixel(config.input_format); u32 output_size = output_width * output_height * GPU::Regs::BytesPerPixel(config.output_format); - VideoCore::g_renderer->rasterizer->FlushRegion(config.GetPhysicalInputAddress(), input_size); + VideoCore::g_renderer->Rasterizer()->FlushRegion(config.GetPhysicalInputAddress(), input_size); for (u32 y = 0; y < output_height; ++y) { for (u32 x = 0; x < output_width; ++x) { @@ -338,7 +338,7 @@ inline void Write(u32 addr, const T data) { g_regs.display_transfer_config.trigger = 0; GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PPF); - VideoCore::g_renderer->rasterizer->InvalidateRegion(config.GetPhysicalOutputAddress(), output_size); + VideoCore::g_renderer->Rasterizer()->InvalidateRegion(config.GetPhysicalOutputAddress(), output_size); } break; } diff --git a/src/core/hw/gpu.h b/src/core/hw/gpu.h index 2e3a9f779..a00adbf53 100644 --- a/src/core/hw/gpu.h +++ b/src/core/hw/gpu.h @@ -263,17 +263,17 @@ struct Regs { INSERT_PADDING_WORDS(0x9c3); - static inline size_t NumIds() { + static constexpr size_t NumIds() { return sizeof(Regs) / sizeof(u32); } - u32& operator [] (int index) const { - u32* content = (u32*)this; + const u32& operator [] (int index) const { + const u32* content = reinterpret_cast<const u32*>(this); return content[index]; } u32& operator [] (int index) { - u32* content = (u32*)this; + u32* content = reinterpret_cast<u32*>(this); return content[index]; } diff --git a/src/core/hw/lcd.h b/src/core/hw/lcd.h index bcce6d8cf..3dd877fbf 100644 --- a/src/core/hw/lcd.h +++ b/src/core/hw/lcd.h @@ -38,17 +38,17 @@ struct Regs { u32 backlight_bottom; INSERT_PADDING_WORDS(0x16F); - static inline size_t NumIds() { + static constexpr size_t NumIds() { return sizeof(Regs) / sizeof(u32); } - u32& operator [] (int index) const { - u32* content = (u32*)this; + const u32& operator [] (int index) const { + const u32* content = reinterpret_cast<const u32*>(this); return content[index]; } u32& operator [] (int index) { - u32* content = (u32*)this; + u32* content = reinterpret_cast<u32*>(this); return content[index]; } diff --git a/src/core/system.cpp b/src/core/system.cpp index 1e3b2783c..4a4757af3 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -29,6 +29,8 @@ Result Init(EmuWindow* emu_window) { } AudioCore::Init(); GDBStub::Init(); + + return Result::Success; } void Shutdown() { diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp index 2f92be661..4b59984ad 100644 --- a/src/video_core/command_processor.cpp +++ b/src/video_core/command_processor.cpp @@ -5,6 +5,7 @@ #include <cmath> #include <boost/range/algorithm/fill.hpp> +#include "common/alignment.h" #include "common/microprofile.h" #include "common/profiler.h" @@ -142,7 +143,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { // Send to renderer using Pica::Shader::OutputVertex; auto AddTriangle = [](const OutputVertex& v0, const OutputVertex& v1, const OutputVertex& v2) { - VideoCore::g_renderer->rasterizer->AddTriangle(v0, v1, v2); + VideoCore::g_renderer->Rasterizer()->AddTriangle(v0, v1, v2); }; g_state.immediate.primitive_assembler.SubmitVertex(output, AddTriangle); @@ -155,7 +156,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { case PICA_REG_INDEX(gpu_mode): if (regs.gpu_mode == Regs::GPUMode::Configuring && regs.vs_default_attributes_setup.index == 15) { // Draw immediate mode triangles when GPU Mode is set to GPUMode::Configuring - VideoCore::g_renderer->rasterizer->DrawTriangles(); + VideoCore::g_renderer->Rasterizer()->DrawTriangles(); } break; @@ -199,7 +200,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { for (int loader = 0; loader < 12; ++loader) { const auto& loader_config = attribute_config.attribute_loaders[loader]; - u32 load_address = base_address + loader_config.data_offset; + u32 offset = 0; // TODO: What happens if a loader overwrites a previous one's data? for (unsigned component = 0; component < loader_config.component_count; ++component) { @@ -210,15 +211,18 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { u32 attribute_index = loader_config.GetComponent(component); if (attribute_index < 12) { - vertex_attribute_sources[attribute_index] = load_address; + int element_size = attribute_config.GetElementSizeInBytes(attribute_index); + offset = Common::AlignUp(offset, element_size); + vertex_attribute_sources[attribute_index] = base_address + loader_config.data_offset + offset; vertex_attribute_strides[attribute_index] = static_cast<u32>(loader_config.byte_count); vertex_attribute_formats[attribute_index] = attribute_config.GetFormat(attribute_index); vertex_attribute_elements[attribute_index] = attribute_config.GetNumElements(attribute_index); - vertex_attribute_element_size[attribute_index] = attribute_config.GetElementSizeInBytes(attribute_index); - load_address += attribute_config.GetStride(attribute_index); + vertex_attribute_element_size[attribute_index] = element_size; + offset += attribute_config.GetStride(attribute_index); } else if (attribute_index < 16) { // Attribute ids 12, 13, 14 and 15 signify 4, 8, 12 and 16-byte paddings, respectively - load_address += (attribute_index - 11) * 4; + offset = Common::AlignUp(offset, 4); + offset += (attribute_index - 11) * 4; } else { UNREACHABLE(); // This is truly unreachable due to the number of bits for each component } @@ -230,7 +234,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { const auto& index_info = regs.index_array; const u8* index_address_8 = Memory::GetPhysicalPointer(base_address + index_info.offset); - const u16* index_address_16 = (u16*)index_address_8; + const u16* index_address_16 = reinterpret_cast<const u16*>(index_address_8); bool index_u16 = index_info.format != 0; #if PICA_DUMP_GEOMETRY @@ -341,10 +345,11 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { : (vertex_attribute_formats[i] == Regs::VertexAttributeFormat::SHORT) ? 2 : 1); } - const float srcval = (vertex_attribute_formats[i] == Regs::VertexAttributeFormat::BYTE) ? *(s8*)srcdata : - (vertex_attribute_formats[i] == Regs::VertexAttributeFormat::UBYTE) ? *(u8*)srcdata : - (vertex_attribute_formats[i] == Regs::VertexAttributeFormat::SHORT) ? *(s16*)srcdata : - *(float*)srcdata; + const float srcval = + (vertex_attribute_formats[i] == Regs::VertexAttributeFormat::BYTE) ? *reinterpret_cast<const s8*>(srcdata) : + (vertex_attribute_formats[i] == Regs::VertexAttributeFormat::UBYTE) ? *reinterpret_cast<const u8*>(srcdata) : + (vertex_attribute_formats[i] == Regs::VertexAttributeFormat::SHORT) ? *reinterpret_cast<const s16*>(srcdata) : + *reinterpret_cast<const float*>(srcdata); input.attr[i][comp] = float24::FromFloat32(srcval); LOG_TRACE(HW_GPU, "Loaded component %x of attribute %x for vertex %x (index %x) from 0x%08x + 0x%08x + 0x%04x: %f", @@ -396,7 +401,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { using Pica::Shader::OutputVertex; auto AddTriangle = []( const OutputVertex& v0, const OutputVertex& v1, const OutputVertex& v2) { - VideoCore::g_renderer->rasterizer->AddTriangle(v0, v1, v2); + VideoCore::g_renderer->Rasterizer()->AddTriangle(v0, v1, v2); }; primitive_assembler.SubmitVertex(output, AddTriangle); @@ -407,7 +412,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { range.second, range.first); } - VideoCore::g_renderer->rasterizer->DrawTriangles(); + VideoCore::g_renderer->Rasterizer()->DrawTriangles(); #if PICA_DUMP_GEOMETRY geometry_dumper.Dump(); @@ -542,7 +547,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { break; } - VideoCore::g_renderer->rasterizer->NotifyPicaRegisterChanged(id); + VideoCore::g_renderer->Rasterizer()->NotifyPicaRegisterChanged(id); if (g_debug_context) g_debug_context->OnEvent(DebugContext::Event::PicaCommandProcessed, reinterpret_cast<void*>(&id)); diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp index 6e21caa78..bac6d69c7 100644 --- a/src/video_core/debug_utils/debug_utils.cpp +++ b/src/video_core/debug_utils/debug_utils.cpp @@ -48,7 +48,7 @@ void DebugContext::OnEvent(Event event, void* data) { std::unique_lock<std::mutex> lock(breakpoint_mutex); // Commit the hardware renderer's framebuffer so it will show on debug widgets - VideoCore::g_renderer->rasterizer->FlushFramebuffer(); + VideoCore::g_renderer->Rasterizer()->FlushFramebuffer(); // TODO: Should stop the CPU thread here once we multithread emulation. @@ -117,13 +117,13 @@ void GeometryDumper::Dump() { void DumpShader(const std::string& filename, const Regs::ShaderConfig& config, const Shader::ShaderSetup& setup, const Regs::VSOutputAttributes* output_attributes) { struct StuffToWrite { - u8* pointer; + const u8* pointer; u32 size; }; std::vector<StuffToWrite> writing_queue; u32 write_offset = 0; - auto QueueForWriting = [&writing_queue,&write_offset](u8* pointer, u32 size) { + auto QueueForWriting = [&writing_queue,&write_offset](const u8* pointer, u32 size) { writing_queue.push_back({pointer, size}); u32 old_write_offset = write_offset; write_offset += size; @@ -228,27 +228,27 @@ void DumpShader(const std::string& filename, const Regs::ShaderConfig& config, c DVLPHeader dvlp{ DVLPHeader::MAGIC_WORD }; DVLEHeader dvle{ DVLEHeader::MAGIC_WORD }; - QueueForWriting((u8*)&dvlb, sizeof(dvlb)); - u32 dvlp_offset = QueueForWriting((u8*)&dvlp, sizeof(dvlp)); - dvlb.dvle_offset = QueueForWriting((u8*)&dvle, sizeof(dvle)); + QueueForWriting(reinterpret_cast<const u8*>(&dvlb), sizeof(dvlb)); + u32 dvlp_offset = QueueForWriting(reinterpret_cast<const u8*>(&dvlp), sizeof(dvlp)); + dvlb.dvle_offset = QueueForWriting(reinterpret_cast<const u8*>(&dvle), sizeof(dvle)); // TODO: Reduce the amount of binary code written to relevant portions dvlp.binary_offset = write_offset - dvlp_offset; dvlp.binary_size_words = setup.program_code.size(); - QueueForWriting((u8*)setup.program_code.data(), setup.program_code.size() * sizeof(u32)); + QueueForWriting(reinterpret_cast<const u8*>(setup.program_code.data()), setup.program_code.size() * sizeof(u32)); dvlp.swizzle_info_offset = write_offset - dvlp_offset; dvlp.swizzle_info_num_entries = setup.swizzle_data.size(); u32 dummy = 0; for (unsigned int i = 0; i < setup.swizzle_data.size(); ++i) { - QueueForWriting((u8*)&setup.swizzle_data[i], sizeof(setup.swizzle_data[i])); - QueueForWriting((u8*)&dummy, sizeof(dummy)); + QueueForWriting(reinterpret_cast<const u8*>(&setup.swizzle_data[i]), sizeof(setup.swizzle_data[i])); + QueueForWriting(reinterpret_cast<const u8*>(&dummy), sizeof(dummy)); } dvle.main_offset_words = config.main_offset; dvle.output_register_table_offset = write_offset - dvlb.dvle_offset; dvle.output_register_table_size = static_cast<u32>(output_info_table.size()); - QueueForWriting((u8*)output_info_table.data(), static_cast<u32>(output_info_table.size() * sizeof(OutputRegisterInfo))); + QueueForWriting(reinterpret_cast<const u8*>(output_info_table.data()), static_cast<u32>(output_info_table.size() * sizeof(OutputRegisterInfo))); // TODO: Create a label table for "main" @@ -292,14 +292,14 @@ void DumpShader(const std::string& filename, const Regs::ShaderConfig& config, c dvle.constant_table_offset = write_offset - dvlb.dvle_offset; dvle.constant_table_size = constant_table.size(); for (const auto& constant : constant_table) { - QueueForWriting((uint8_t*)&constant, sizeof(constant)); + QueueForWriting(reinterpret_cast<const u8*>(&constant), sizeof(constant)); } // Write data to file std::ofstream file(filename, std::ios_base::out | std::ios_base::binary); - for (auto& chunk : writing_queue) { - file.write((char*)chunk.pointer, chunk.size); + for (const auto& chunk : writing_queue) { + file.write(reinterpret_cast<const char*>(chunk.pointer), chunk.size); } } diff --git a/src/video_core/pica.h b/src/video_core/pica.h index 2e0c33201..337cff8ce 100644 --- a/src/video_core/pica.h +++ b/src/video_core/pica.h @@ -117,8 +117,8 @@ struct Regs { INSERT_PADDING_WORDS(0x11); union { - BitField< 0, 16, u32> x; - BitField<16, 16, u32> y; + BitField< 0, 10, s32> x; + BitField<16, 10, s32> y; } viewport_corner; INSERT_PADDING_WORDS(0x17); @@ -1221,17 +1221,17 @@ struct Regs { // Used for debugging purposes, so performance is not an issue here static std::string GetCommandName(int index); - static inline size_t NumIds() { + static constexpr size_t NumIds() { return sizeof(Regs) / sizeof(u32); } - u32& operator [] (int index) const { - u32* content = (u32*)this; + const u32& operator [] (int index) const { + const u32* content = reinterpret_cast<const u32*>(this); return content[index]; } u32& operator [] (int index) { - u32* content = (u32*)this; + u32* content = reinterpret_cast<u32*>(this); return content[index]; } diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h index 91a7b7f17..f68091cc8 100644 --- a/src/video_core/renderer_base.h +++ b/src/video_core/renderer_base.h @@ -22,9 +22,6 @@ public: kFramebuffer_Texture }; - RendererBase() : m_current_fps(0), m_current_frame(0) { - } - virtual ~RendererBase() { } @@ -46,21 +43,24 @@ public: // Getter/setter functions: // ------------------------ - f32 GetCurrentframe() const { + f32 GetCurrentFPS() const { return m_current_fps; } - int current_frame() const { + int GetCurrentFrame() const { return m_current_frame; } - void RefreshRasterizerSetting(); + VideoCore::RasterizerInterface* Rasterizer() const { + return rasterizer.get(); + } - std::unique_ptr<VideoCore::RasterizerInterface> rasterizer; + void RefreshRasterizerSetting(); protected: - f32 m_current_fps; ///< Current framerate, should be set by the renderer - int m_current_frame; ///< Current frame, should be set by the renderer + std::unique_ptr<VideoCore::RasterizerInterface> rasterizer; + f32 m_current_fps = 0.0f; ///< Current framerate, should be set by the renderer + int m_current_frame = 0; ///< Current frame, should be set by the renderer private: bool opengl_rasterizer_active = false; diff --git a/src/video_core/shader/shader.cpp b/src/video_core/shader/shader.cpp index 5e8930476..509558fc0 100644 --- a/src/video_core/shader/shader.cpp +++ b/src/video_core/shader/shader.cpp @@ -32,6 +32,12 @@ namespace Shader { static std::unordered_map<u64, CompiledShader*> shader_map; static JitCompiler jit; static CompiledShader* jit_shader; + +static void ClearCache() { + shader_map.clear(); + jit.Clear(); + LOG_INFO(HW_GPU, "Shader JIT cache cleared"); +} #endif // ARCHITECTURE_x86_64 void Setup(UnitState<false>& state) { @@ -45,6 +51,12 @@ void Setup(UnitState<false>& state) { if (iter != shader_map.end()) { jit_shader = iter->second; } else { + // Check if remaining JIT code space is enough for at least one more (massive) shader + if (jit.GetSpaceLeft() < jit_shader_size) { + // If not, clear the cache of all previously compiled shaders + ClearCache(); + } + jit_shader = jit.Compile(); shader_map.emplace(cache_key, jit_shader); } @@ -54,7 +66,7 @@ void Setup(UnitState<false>& state) { void Shutdown() { #ifdef ARCHITECTURE_x86_64 - shader_map.clear(); + ClearCache(); #endif // ARCHITECTURE_x86_64 } @@ -135,7 +147,7 @@ OutputVertex Run(UnitState<false>& state, const InputVertex& input, int num_attr std::fmin(std::fabs(ret.color[i].ToFloat32()), 1.0f)); } - LOG_TRACE(Render_Software, "Output vertex: pos(%.2f, %.2f, %.2f, %.2f), quat(%.2f, %.2f, %.2f, %.2f), " + LOG_TRACE(HW_GPU, "Output vertex: pos(%.2f, %.2f, %.2f, %.2f), quat(%.2f, %.2f, %.2f, %.2f), " "col(%.2f, %.2f, %.2f, %.2f), tc0(%.2f, %.2f), view(%.2f, %.2f, %.2f)", ret.pos.x.ToFloat32(), ret.pos.y.ToFloat32(), ret.pos.z.ToFloat32(), ret.pos.w.ToFloat32(), ret.quat.x.ToFloat32(), ret.quat.y.ToFloat32(), ret.quat.z.ToFloat32(), ret.quat.w.ToFloat32(), diff --git a/src/video_core/shader/shader.h b/src/video_core/shader/shader.h index 1be4e3734..7af8f1fa1 100644 --- a/src/video_core/shader/shader.h +++ b/src/video_core/shader/shader.h @@ -82,7 +82,7 @@ struct ShaderSetup { struct { // The float uniforms are accessed by the shader JIT using SSE instructions, and are // therefore required to be 16-byte aligned. - Math::Vec4<float24> MEMORY_ALIGNED16(f[96]); + alignas(16) Math::Vec4<float24> f[96]; std::array<bool, 16> b; std::array<Math::Vec4<u8>, 4> i; @@ -276,9 +276,9 @@ struct UnitState { struct Registers { // The registers are accessed by the shader JIT using SSE instructions, and are therefore // required to be 16-byte aligned. - Math::Vec4<float24> MEMORY_ALIGNED16(input[16]); - Math::Vec4<float24> MEMORY_ALIGNED16(output[16]); - Math::Vec4<float24> MEMORY_ALIGNED16(temporary[16]); + alignas(16) Math::Vec4<float24> input[16]; + alignas(16) Math::Vec4<float24> output[16]; + alignas(16) Math::Vec4<float24> temporary[16]; } registers; static_assert(std::is_pod<Registers>::value, "Structure is not POD"); diff --git a/src/video_core/shader/shader_interpreter.cpp b/src/video_core/shader/shader_interpreter.cpp index 79fcc56b9..02e1a1cb1 100644 --- a/src/video_core/shader/shader_interpreter.cpp +++ b/src/video_core/shader/shader_interpreter.cpp @@ -409,13 +409,16 @@ void RunInterpreter(UnitState<Debug>& state) { { if ((instr.opcode.Value().EffectiveOpCode() == OpCode::Id::MAD) || (instr.opcode.Value().EffectiveOpCode() == OpCode::Id::MADI)) { - const SwizzlePattern& swizzle = *(SwizzlePattern*)&swizzle_data[instr.mad.operand_desc_id]; + const SwizzlePattern& swizzle = *reinterpret_cast<const SwizzlePattern*>(&swizzle_data[instr.mad.operand_desc_id]); bool is_inverted = (instr.opcode.Value().EffectiveOpCode() == OpCode::Id::MADI); + const int address_offset = (instr.mad.address_register_index == 0) + ? 0 : state.address_registers[instr.mad.address_register_index - 1]; + const float24* src1_ = LookupSourceRegister(instr.mad.GetSrc1(is_inverted)); - const float24* src2_ = LookupSourceRegister(instr.mad.GetSrc2(is_inverted)); - const float24* src3_ = LookupSourceRegister(instr.mad.GetSrc3(is_inverted)); + const float24* src2_ = LookupSourceRegister(instr.mad.GetSrc2(is_inverted) + (!is_inverted * address_offset)); + const float24* src3_ = LookupSourceRegister(instr.mad.GetSrc3(is_inverted) + ( is_inverted * address_offset)); const bool negate_src1 = ((bool)swizzle.negate_src1 != false); const bool negate_src2 = ((bool)swizzle.negate_src2 != false); diff --git a/src/video_core/shader/shader_jit_x64.cpp b/src/video_core/shader/shader_jit_x64.cpp index 5083d7e54..dffe051ef 100644 --- a/src/video_core/shader/shader_jit_x64.cpp +++ b/src/video_core/shader/shader_jit_x64.cpp @@ -160,40 +160,41 @@ void JitCompiler::Compile_SwizzleSrc(Instruction instr, unsigned src_num, Source ASSERT_MSG(src_offset == src_offset_disp, "Source register offset too large for int type"); unsigned operand_desc_id; + + const bool is_inverted = (0 != (instr.opcode.Value().GetInfo().subtype & OpCode::Info::SrcInversed)); + + unsigned address_register_index; + unsigned offset_src; + if (instr.opcode.Value().EffectiveOpCode() == OpCode::Id::MAD || instr.opcode.Value().EffectiveOpCode() == OpCode::Id::MADI) { - // The MAD and MADI instructions do not use the address offset registers, so loading the - // source is a bit simpler here - operand_desc_id = instr.mad.operand_desc_id; - - // Load the source - MOVAPS(dest, MDisp(src_ptr, src_offset_disp)); + offset_src = is_inverted ? 3 : 2; + address_register_index = instr.mad.address_register_index; } else { operand_desc_id = instr.common.operand_desc_id; + offset_src = is_inverted ? 2 : 1; + address_register_index = instr.common.address_register_index; + } - const bool is_inverted = (0 != (instr.opcode.Value().GetInfo().subtype & OpCode::Info::SrcInversed)); - unsigned offset_src = is_inverted ? 2 : 1; - - if (src_num == offset_src && instr.common.address_register_index != 0) { - switch (instr.common.address_register_index) { - case 1: // address offset 1 - MOVAPS(dest, MComplex(src_ptr, ADDROFFS_REG_0, SCALE_1, src_offset_disp)); - break; - case 2: // address offset 2 - MOVAPS(dest, MComplex(src_ptr, ADDROFFS_REG_1, SCALE_1, src_offset_disp)); - break; - case 3: // address offset 3 - MOVAPS(dest, MComplex(src_ptr, LOOPCOUNT_REG, SCALE_1, src_offset_disp)); - break; - default: - UNREACHABLE(); - break; - } - } else { - // Load the source - MOVAPS(dest, MDisp(src_ptr, src_offset_disp)); + if (src_num == offset_src && address_register_index != 0) { + switch (address_register_index) { + case 1: // address offset 1 + MOVAPS(dest, MComplex(src_ptr, ADDROFFS_REG_0, SCALE_1, src_offset_disp)); + break; + case 2: // address offset 2 + MOVAPS(dest, MComplex(src_ptr, ADDROFFS_REG_1, SCALE_1, src_offset_disp)); + break; + case 3: // address offset 3 + MOVAPS(dest, MComplex(src_ptr, LOOPCOUNT_REG, SCALE_1, src_offset_disp)); + break; + default: + UNREACHABLE(); + break; } + } else { + // Load the source + MOVAPS(dest, MDisp(src_ptr, src_offset_disp)); } SwizzlePattern swiz = { g_state.vs.swizzle_data[operand_desc_id] }; @@ -644,7 +645,8 @@ void JitCompiler::Compile_MAD(Instruction instr) { } void JitCompiler::Compile_IF(Instruction instr) { - ASSERT_MSG(instr.flow_control.dest_offset > *offset_ptr, "Backwards if-statements not supported"); + ASSERT_MSG(instr.flow_control.dest_offset > *offset_ptr, "Backwards if-statements (%d -> %d) not supported", + *offset_ptr, instr.flow_control.dest_offset.Value()); // Evaluate the "IF" condition if (instr.opcode.Value() == OpCode::Id::IFU) { @@ -675,7 +677,8 @@ void JitCompiler::Compile_IF(Instruction instr) { } void JitCompiler::Compile_LOOP(Instruction instr) { - ASSERT_MSG(instr.flow_control.dest_offset > *offset_ptr, "Backwards loops not supported"); + ASSERT_MSG(instr.flow_control.dest_offset > *offset_ptr, "Backwards loops (%d -> %d) not supported", + *offset_ptr, instr.flow_control.dest_offset.Value()); ASSERT_MSG(!looping, "Nested loops not supported"); looping = true; @@ -703,7 +706,8 @@ void JitCompiler::Compile_LOOP(Instruction instr) { } void JitCompiler::Compile_JMP(Instruction instr) { - ASSERT_MSG(instr.flow_control.dest_offset > *offset_ptr, "Backwards jumps not supported"); + ASSERT_MSG(instr.flow_control.dest_offset > *offset_ptr, "Backwards jumps (%d -> %d) not supported", + *offset_ptr, instr.flow_control.dest_offset.Value()); if (instr.opcode.Value() == OpCode::Id::JMPC) Compile_EvaluateCondition(instr); @@ -747,7 +751,7 @@ void JitCompiler::Compile_NextInstr(unsigned* offset) { } else { // Unhandled instruction LOG_CRITICAL(HW_GPU, "Unhandled instruction: 0x%02x (0x%08x)", - instr.opcode.Value().EffectiveOpCode(), instr.hex); + instr.opcode.Value().EffectiveOpCode(), instr.hex); } } @@ -786,7 +790,7 @@ CompiledShader* JitCompiler::Compile() { } JitCompiler::JitCompiler() { - AllocCodeSpace(1024 * 1024 * 4); + AllocCodeSpace(jit_cache_size); } void JitCompiler::Clear() { diff --git a/src/video_core/shader/shader_jit_x64.h b/src/video_core/shader/shader_jit_x64.h index 5ad2d9606..5357c964b 100644 --- a/src/video_core/shader/shader_jit_x64.h +++ b/src/video_core/shader/shader_jit_x64.h @@ -19,6 +19,11 @@ namespace Pica { namespace Shader { +/// Memory needed to be available to compile the next shader (otherwise, clear the cache) +constexpr size_t jit_shader_size = 1024 * 512; +/// Memory allocated for the JIT code space cache +constexpr size_t jit_cache_size = 1024 * 1024 * 8; + using CompiledShader = void(void* registers); /** |