summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/citra/citra.cpp14
-rw-r--r--src/citra/emu_window/emu_window_sdl2.cpp4
-rw-r--r--src/citra_qt/debugger/graphics_vertex_shader.cpp16
-rw-r--r--src/citra_qt/main.cpp7
-rw-r--r--src/citra_qt/main.h2
-rw-r--r--src/common/CMakeLists.txt1
-rw-r--r--src/common/alignment.h22
-rw-r--r--src/common/common_funcs.h10
-rw-r--r--src/common/common_types.h6
-rw-r--r--src/common/logging/backend.cpp1
-rw-r--r--src/common/logging/log.h1
-rw-r--r--src/common/vector_math.h5
-rw-r--r--src/common/x64/emitter.h113
-rw-r--r--src/core/CMakeLists.txt8
-rw-r--r--src/core/hle/applets/applet.cpp6
-rw-r--r--src/core/hle/applets/mii_selector.cpp75
-rw-r--r--src/core/hle/applets/mii_selector.h37
-rw-r--r--src/core/hle/function_wrappers.h1
-rw-r--r--src/core/hle/kernel/event.cpp2
-rw-r--r--src/core/hle/kernel/event.h8
-rw-r--r--src/core/hle/kernel/timer.cpp2
-rw-r--r--src/core/hle/kernel/timer.h2
-rw-r--r--src/core/hle/service/apt/apt.cpp23
-rw-r--r--src/core/hle/service/apt/apt.h17
-rw-r--r--src/core/hle/service/apt/apt_u.cpp2
-rw-r--r--src/core/hle/service/cam/cam.cpp8
-rw-r--r--src/core/hle/service/dsp_dsp.cpp2
-rw-r--r--src/core/hle/service/fs/fs_user.cpp26
-rw-r--r--src/core/hle/service/gsp_gpu.cpp10
-rw-r--r--src/core/hle/service/gsp_lcd.cpp1
-rw-r--r--src/core/hle/service/hid/hid.cpp12
-rw-r--r--src/core/hle/service/http_c.cpp2
-rw-r--r--src/core/hle/service/ir/ir.cpp4
-rw-r--r--src/core/hle/service/ndm/ndm.cpp47
-rw-r--r--src/core/hle/service/ndm/ndm.h52
-rw-r--r--src/core/hle/service/ndm/ndm_u.cpp (renamed from src/core/hle/service/ndm_u.cpp)23
-rw-r--r--src/core/hle/service/ndm/ndm_u.h (renamed from src/core/hle/service/ndm_u.h)15
-rw-r--r--src/core/hle/service/nwm_uds.cpp2
-rw-r--r--src/core/hle/service/service.cpp5
-rw-r--r--src/core/hle/service/soc_u.cpp4
-rw-r--r--src/core/hle/service/srv.cpp2
-rw-r--r--src/core/hle/service/ssl_c.cpp10
-rw-r--r--src/core/hle/service/y2r_u.cpp4
-rw-r--r--src/core/hle/svc.cpp4
-rw-r--r--src/core/hle/svc.h16
-rw-r--r--src/core/hw/gpu.cpp10
-rw-r--r--src/core/hw/gpu.h8
-rw-r--r--src/core/hw/lcd.h8
-rw-r--r--src/core/system.cpp2
-rw-r--r--src/video_core/command_processor.cpp35
-rw-r--r--src/video_core/debug_utils/debug_utils.cpp26
-rw-r--r--src/video_core/pica.h12
-rw-r--r--src/video_core/renderer_base.h18
-rw-r--r--src/video_core/shader/shader.cpp16
-rw-r--r--src/video_core/shader/shader.h8
-rw-r--r--src/video_core/shader/shader_interpreter.cpp9
-rw-r--r--src/video_core/shader/shader_jit_x64.cpp68
-rw-r--r--src/video_core/shader/shader_jit_x64.h5
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);
/**