summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/audio_core/sdl2_sink.cpp4
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.cpp5
-rw-r--r--src/core/hle/applets/erreula.cpp6
-rw-r--r--src/core/hle/applets/mii_selector.cpp6
-rw-r--r--src/core/hle/applets/swkbd.cpp6
-rw-r--r--src/core/hle/kernel/event.cpp5
-rw-r--r--src/core/hle/kernel/timer.cpp5
-rw-r--r--src/core/hle/service/apt/apt.cpp11
-rw-r--r--src/core/hle/service/apt/apt.h34
-rw-r--r--src/core/hle/service/apt/apt_a.cpp2
-rw-r--r--src/core/hle/service/apt/apt_u.cpp2
-rw-r--r--src/core/hle/service/cfg/cfg.cpp10
-rw-r--r--src/core/hle/service/err_f.cpp316
-rw-r--r--src/core/memory.cpp14
-rw-r--r--src/core/memory.h9
-rw-r--r--src/video_core/command_processor.cpp24
-rw-r--r--src/video_core/pica.h2
17 files changed, 300 insertions, 161 deletions
diff --git a/src/audio_core/sdl2_sink.cpp b/src/audio_core/sdl2_sink.cpp
index 75cc0d6dd..4b66cd826 100644
--- a/src/audio_core/sdl2_sink.cpp
+++ b/src/audio_core/sdl2_sink.cpp
@@ -25,7 +25,7 @@ struct SDL2Sink::Impl {
25 25
26SDL2Sink::SDL2Sink() : impl(std::make_unique<Impl>()) { 26SDL2Sink::SDL2Sink() : impl(std::make_unique<Impl>()) {
27 if (SDL_Init(SDL_INIT_AUDIO) < 0) { 27 if (SDL_Init(SDL_INIT_AUDIO) < 0) {
28 LOG_CRITICAL(Audio_Sink, "SDL_Init(SDL_INIT_AUDIO) failed"); 28 LOG_CRITICAL(Audio_Sink, "SDL_Init(SDL_INIT_AUDIO) failed with: %s", SDL_GetError());
29 impl->audio_device_id = 0; 29 impl->audio_device_id = 0;
30 return; 30 return;
31 } 31 }
@@ -45,7 +45,7 @@ SDL2Sink::SDL2Sink() : impl(std::make_unique<Impl>()) {
45 impl->audio_device_id = 45 impl->audio_device_id =
46 SDL_OpenAudioDevice(nullptr, false, &desired_audiospec, &obtained_audiospec, 0); 46 SDL_OpenAudioDevice(nullptr, false, &desired_audiospec, &obtained_audiospec, 0);
47 if (impl->audio_device_id <= 0) { 47 if (impl->audio_device_id <= 0) {
48 LOG_CRITICAL(Audio_Sink, "SDL_OpenAudioDevice failed"); 48 LOG_CRITICAL(Audio_Sink, "SDL_OpenAudioDevice failed with: %s", SDL_GetError());
49 return; 49 return;
50 } 50 }
51 51
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp
index b4444c869..ca8a94ee9 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic.cpp
@@ -52,6 +52,7 @@ static Dynarmic::UserCallbacks GetUserCallbacks(ARMul_State* interpeter_state) {
52 user_callbacks.MemoryWrite16 = &Memory::Write16; 52 user_callbacks.MemoryWrite16 = &Memory::Write16;
53 user_callbacks.MemoryWrite32 = &Memory::Write32; 53 user_callbacks.MemoryWrite32 = &Memory::Write32;
54 user_callbacks.MemoryWrite64 = &Memory::Write64; 54 user_callbacks.MemoryWrite64 = &Memory::Write64;
55 user_callbacks.page_table = Memory::GetCurrentPageTablePointers();
55 return user_callbacks; 56 return user_callbacks;
56} 57}
57 58
@@ -130,9 +131,9 @@ MICROPROFILE_DEFINE(ARM_Jit, "ARM JIT", "ARM JIT", MP_RGB(255, 64, 64));
130void ARM_Dynarmic::ExecuteInstructions(int num_instructions) { 131void ARM_Dynarmic::ExecuteInstructions(int num_instructions) {
131 MICROPROFILE_SCOPE(ARM_Jit); 132 MICROPROFILE_SCOPE(ARM_Jit);
132 133
133 jit->Run(static_cast<unsigned>(num_instructions)); 134 unsigned ticks_executed = jit->Run(static_cast<unsigned>(num_instructions));
134 135
135 AddTicks(num_instructions); 136 AddTicks(ticks_executed);
136} 137}
137 138
138void ARM_Dynarmic::SaveContext(Core::ThreadContext& ctx) { 139void ARM_Dynarmic::SaveContext(Core::ThreadContext& ctx) {
diff --git a/src/core/hle/applets/erreula.cpp b/src/core/hle/applets/erreula.cpp
index 14964427b..e1379ac4d 100644
--- a/src/core/hle/applets/erreula.cpp
+++ b/src/core/hle/applets/erreula.cpp
@@ -10,7 +10,7 @@ namespace HLE {
10namespace Applets { 10namespace Applets {
11 11
12ResultCode ErrEula::ReceiveParameter(const Service::APT::MessageParameter& parameter) { 12ResultCode ErrEula::ReceiveParameter(const Service::APT::MessageParameter& parameter) {
13 if (parameter.signal != static_cast<u32>(Service::APT::SignalType::LibAppJustStarted)) { 13 if (parameter.signal != static_cast<u32>(Service::APT::SignalType::Request)) {
14 LOG_ERROR(Service_APT, "unsupported signal %u", parameter.signal); 14 LOG_ERROR(Service_APT, "unsupported signal %u", parameter.signal);
15 UNIMPLEMENTED(); 15 UNIMPLEMENTED();
16 // TODO(Subv): Find the right error code 16 // TODO(Subv): Find the right error code
@@ -36,7 +36,7 @@ ResultCode ErrEula::ReceiveParameter(const Service::APT::MessageParameter& param
36 36
37 // Send the response message with the newly created SharedMemory 37 // Send the response message with the newly created SharedMemory
38 Service::APT::MessageParameter result; 38 Service::APT::MessageParameter result;
39 result.signal = static_cast<u32>(Service::APT::SignalType::LibAppFinished); 39 result.signal = static_cast<u32>(Service::APT::SignalType::Response);
40 result.buffer.clear(); 40 result.buffer.clear();
41 result.destination_id = static_cast<u32>(Service::APT::AppletId::Application); 41 result.destination_id = static_cast<u32>(Service::APT::AppletId::Application);
42 result.sender_id = static_cast<u32>(id); 42 result.sender_id = static_cast<u32>(id);
@@ -57,7 +57,7 @@ ResultCode ErrEula::StartImpl(const Service::APT::AppletStartupParameter& parame
57 Service::APT::MessageParameter message; 57 Service::APT::MessageParameter message;
58 message.buffer.resize(parameter.buffer.size()); 58 message.buffer.resize(parameter.buffer.size());
59 std::fill(message.buffer.begin(), message.buffer.end(), 0); 59 std::fill(message.buffer.begin(), message.buffer.end(), 0);
60 message.signal = static_cast<u32>(Service::APT::SignalType::LibAppClosed); 60 message.signal = static_cast<u32>(Service::APT::SignalType::WakeupByExit);
61 message.destination_id = static_cast<u32>(Service::APT::AppletId::Application); 61 message.destination_id = static_cast<u32>(Service::APT::AppletId::Application);
62 message.sender_id = static_cast<u32>(id); 62 message.sender_id = static_cast<u32>(id);
63 Service::APT::SendParameter(message); 63 Service::APT::SendParameter(message);
diff --git a/src/core/hle/applets/mii_selector.cpp b/src/core/hle/applets/mii_selector.cpp
index 53a8683a4..3455b9201 100644
--- a/src/core/hle/applets/mii_selector.cpp
+++ b/src/core/hle/applets/mii_selector.cpp
@@ -19,7 +19,7 @@ namespace HLE {
19namespace Applets { 19namespace Applets {
20 20
21ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& parameter) { 21ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& parameter) {
22 if (parameter.signal != static_cast<u32>(Service::APT::SignalType::LibAppJustStarted)) { 22 if (parameter.signal != static_cast<u32>(Service::APT::SignalType::Request)) {
23 LOG_ERROR(Service_APT, "unsupported signal %u", parameter.signal); 23 LOG_ERROR(Service_APT, "unsupported signal %u", parameter.signal);
24 UNIMPLEMENTED(); 24 UNIMPLEMENTED();
25 // TODO(Subv): Find the right error code 25 // TODO(Subv): Find the right error code
@@ -44,7 +44,7 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p
44 44
45 // Send the response message with the newly created SharedMemory 45 // Send the response message with the newly created SharedMemory
46 Service::APT::MessageParameter result; 46 Service::APT::MessageParameter result;
47 result.signal = static_cast<u32>(Service::APT::SignalType::LibAppFinished); 47 result.signal = static_cast<u32>(Service::APT::SignalType::Response);
48 result.buffer.clear(); 48 result.buffer.clear();
49 result.destination_id = static_cast<u32>(Service::APT::AppletId::Application); 49 result.destination_id = static_cast<u32>(Service::APT::AppletId::Application);
50 result.sender_id = static_cast<u32>(id); 50 result.sender_id = static_cast<u32>(id);
@@ -73,7 +73,7 @@ ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& pa
73 Service::APT::MessageParameter message; 73 Service::APT::MessageParameter message;
74 message.buffer.resize(sizeof(MiiResult)); 74 message.buffer.resize(sizeof(MiiResult));
75 std::memcpy(message.buffer.data(), &result, message.buffer.size()); 75 std::memcpy(message.buffer.data(), &result, message.buffer.size());
76 message.signal = static_cast<u32>(Service::APT::SignalType::LibAppClosed); 76 message.signal = static_cast<u32>(Service::APT::SignalType::WakeupByExit);
77 message.destination_id = static_cast<u32>(Service::APT::AppletId::Application); 77 message.destination_id = static_cast<u32>(Service::APT::AppletId::Application);
78 message.sender_id = static_cast<u32>(id); 78 message.sender_id = static_cast<u32>(id);
79 Service::APT::SendParameter(message); 79 Service::APT::SendParameter(message);
diff --git a/src/core/hle/applets/swkbd.cpp b/src/core/hle/applets/swkbd.cpp
index 06ddf538b..1e21337f5 100644
--- a/src/core/hle/applets/swkbd.cpp
+++ b/src/core/hle/applets/swkbd.cpp
@@ -22,7 +22,7 @@ namespace HLE {
22namespace Applets { 22namespace Applets {
23 23
24ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter const& parameter) { 24ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter const& parameter) {
25 if (parameter.signal != static_cast<u32>(Service::APT::SignalType::LibAppJustStarted)) { 25 if (parameter.signal != static_cast<u32>(Service::APT::SignalType::Request)) {
26 LOG_ERROR(Service_APT, "unsupported signal %u", parameter.signal); 26 LOG_ERROR(Service_APT, "unsupported signal %u", parameter.signal);
27 UNIMPLEMENTED(); 27 UNIMPLEMENTED();
28 // TODO(Subv): Find the right error code 28 // TODO(Subv): Find the right error code
@@ -47,7 +47,7 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con
47 47
48 // Send the response message with the newly created SharedMemory 48 // Send the response message with the newly created SharedMemory
49 Service::APT::MessageParameter result; 49 Service::APT::MessageParameter result;
50 result.signal = static_cast<u32>(Service::APT::SignalType::LibAppFinished); 50 result.signal = static_cast<u32>(Service::APT::SignalType::Response);
51 result.buffer.clear(); 51 result.buffer.clear();
52 result.destination_id = static_cast<u32>(Service::APT::AppletId::Application); 52 result.destination_id = static_cast<u32>(Service::APT::AppletId::Application);
53 result.sender_id = static_cast<u32>(id); 53 result.sender_id = static_cast<u32>(id);
@@ -108,7 +108,7 @@ void SoftwareKeyboard::Finalize() {
108 Service::APT::MessageParameter message; 108 Service::APT::MessageParameter message;
109 message.buffer.resize(sizeof(SoftwareKeyboardConfig)); 109 message.buffer.resize(sizeof(SoftwareKeyboardConfig));
110 std::memcpy(message.buffer.data(), &config, message.buffer.size()); 110 std::memcpy(message.buffer.data(), &config, message.buffer.size());
111 message.signal = static_cast<u32>(Service::APT::SignalType::LibAppClosed); 111 message.signal = static_cast<u32>(Service::APT::SignalType::WakeupByExit);
112 message.destination_id = static_cast<u32>(Service::APT::AppletId::Application); 112 message.destination_id = static_cast<u32>(Service::APT::AppletId::Application);
113 message.sender_id = static_cast<u32>(id); 113 message.sender_id = static_cast<u32>(id);
114 Service::APT::SendParameter(message); 114 Service::APT::SendParameter(message);
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp
index 1489c7002..3e116e3df 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -22,6 +22,11 @@ SharedPtr<Event> Event::Create(ResetType reset_type, std::string name) {
22 evt->reset_type = reset_type; 22 evt->reset_type = reset_type;
23 evt->name = std::move(name); 23 evt->name = std::move(name);
24 24
25 if (reset_type == ResetType::Pulse) {
26 LOG_ERROR(Kernel, "Unimplemented event reset type Pulse");
27 UNIMPLEMENTED();
28 }
29
25 return evt; 30 return evt;
26} 31}
27 32
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp
index a9f98223c..eac181f4e 100644
--- a/src/core/hle/kernel/timer.cpp
+++ b/src/core/hle/kernel/timer.cpp
@@ -31,6 +31,11 @@ SharedPtr<Timer> Timer::Create(ResetType reset_type, std::string name) {
31 timer->interval_delay = 0; 31 timer->interval_delay = 0;
32 timer->callback_handle = timer_callback_handle_table.Create(timer).MoveFrom(); 32 timer->callback_handle = timer_callback_handle_table.Create(timer).MoveFrom();
33 33
34 if (reset_type == ResetType::Pulse) {
35 LOG_ERROR(Kernel, "Unimplemented timer reset type Pulse");
36 UNIMPLEMENTED();
37 }
38
34 return timer; 39 return timer;
35} 40}
36 41
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp
index c4bd65986..31e5e07b2 100644
--- a/src/core/hle/service/apt/apt.cpp
+++ b/src/core/hle/service/apt/apt.cpp
@@ -396,6 +396,15 @@ void StartLibraryApplet(Service::Interface* self) {
396 cmd_buff[1] = applet->Start(parameter).raw; 396 cmd_buff[1] = applet->Start(parameter).raw;
397} 397}
398 398
399void CancelLibraryApplet(Service::Interface* self) {
400 u32* cmd_buff = Kernel::GetCommandBuffer();
401 u32 exiting = cmd_buff[1] & 0xFF;
402
403 cmd_buff[1] = 1; // TODO: Find the return code meaning
404
405 LOG_WARNING(Service_APT, "(STUBBED) called exiting=%u", exiting);
406}
407
399void SetScreenCapPostPermission(Service::Interface* self) { 408void SetScreenCapPostPermission(Service::Interface* self) {
400 u32* cmd_buff = Kernel::GetCommandBuffer(); 409 u32* cmd_buff = Kernel::GetCommandBuffer();
401 410
@@ -523,7 +532,7 @@ void Init() {
523 notification_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "APT_U:Notification"); 532 notification_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "APT_U:Notification");
524 parameter_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "APT_U:Start"); 533 parameter_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "APT_U:Start");
525 534
526 next_parameter.signal = static_cast<u32>(SignalType::AppJustStarted); 535 next_parameter.signal = static_cast<u32>(SignalType::Wakeup);
527 next_parameter.destination_id = 0x300; 536 next_parameter.destination_id = 0x300;
528} 537}
529 538
diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h
index a118cda1f..44dbd8757 100644
--- a/src/core/hle/service/apt/apt.h
+++ b/src/core/hle/service/apt/apt.h
@@ -46,12 +46,23 @@ static_assert(sizeof(CaptureBufferInfo) == 0x20, "CaptureBufferInfo struct has i
46/// Signals used by APT functions 46/// Signals used by APT functions
47enum class SignalType : u32 { 47enum class SignalType : u32 {
48 None = 0x0, 48 None = 0x0,
49 AppJustStarted = 0x1, 49 Wakeup = 0x1,
50 LibAppJustStarted = 0x2, 50 Request = 0x2,
51 LibAppFinished = 0x3, 51 Response = 0x3,
52 LibAppClosed = 0xA, 52 Exit = 0x4,
53 ReturningToApp = 0xB, 53 Message = 0x5,
54 ExitingApp = 0xC, 54 HomeButtonSingle = 0x6,
55 HomeButtonDouble = 0x7,
56 DspSleep = 0x8,
57 DspWakeup = 0x9,
58 WakeupByExit = 0xA,
59 WakeupByPause = 0xB,
60 WakeupByCancel = 0xC,
61 WakeupByCancelAll = 0xD,
62 WakeupByPowerButtonClick = 0xE,
63 WakeupToJumpHome = 0xF,
64 RequestForSysApplet = 0x10,
65 WakeupToLaunchApplication = 0x11,
55}; 66};
56 67
57/// App Id's used by APT functions 68/// App Id's used by APT functions
@@ -381,6 +392,17 @@ void PreloadLibraryApplet(Service::Interface* self);
381void StartLibraryApplet(Service::Interface* self); 392void StartLibraryApplet(Service::Interface* self);
382 393
383/** 394/**
395 * APT::CancelLibraryApplet service function
396 * Inputs:
397 * 0 : Command header [0x003B0040]
398 * 1 : u8, Application exiting (0 = not exiting, 1 = exiting)
399 * Outputs:
400 * 0 : Header code
401 * 1 : Result code
402 */
403void CancelLibraryApplet(Service::Interface* self);
404
405/**
384 * APT::GetStartupArgument service function 406 * APT::GetStartupArgument service function
385 * Inputs: 407 * Inputs:
386 * 1 : Parameter Size (capped to 0x300) 408 * 1 : Parameter Size (capped to 0x300)
diff --git a/src/core/hle/service/apt/apt_a.cpp b/src/core/hle/service/apt/apt_a.cpp
index f27ad91b7..a7a0c8a41 100644
--- a/src/core/hle/service/apt/apt_a.cpp
+++ b/src/core/hle/service/apt/apt_a.cpp
@@ -25,7 +25,7 @@ const Interface::FunctionInfo FunctionTable[] = {
25 {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, 25 {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"},
26 {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, 26 {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"},
27 {0x001E0084, StartLibraryApplet, "StartLibraryApplet"}, 27 {0x001E0084, StartLibraryApplet, "StartLibraryApplet"},
28 {0x003B0040, nullptr, "CancelLibraryApplet?"}, 28 {0x003B0040, CancelLibraryApplet, "CancelLibraryApplet"},
29 {0x003E0080, nullptr, "ReplySleepQuery"}, 29 {0x003E0080, nullptr, "ReplySleepQuery"},
30 {0x00430040, NotifyToWait, "NotifyToWait?"}, 30 {0x00430040, NotifyToWait, "NotifyToWait?"},
31 {0x00440000, GetSharedFont, "GetSharedFont?"}, 31 {0x00440000, GetSharedFont, "GetSharedFont?"},
diff --git a/src/core/hle/service/apt/apt_u.cpp b/src/core/hle/service/apt/apt_u.cpp
index d6ad42e21..a731c39f6 100644
--- a/src/core/hle/service/apt/apt_u.cpp
+++ b/src/core/hle/service/apt/apt_u.cpp
@@ -67,7 +67,7 @@ const Interface::FunctionInfo FunctionTable[] = {
67 {0x00380040, nullptr, "PreloadResidentApplet"}, 67 {0x00380040, nullptr, "PreloadResidentApplet"},
68 {0x00390040, nullptr, "PrepareToStartResidentApplet"}, 68 {0x00390040, nullptr, "PrepareToStartResidentApplet"},
69 {0x003A0044, nullptr, "StartResidentApplet"}, 69 {0x003A0044, nullptr, "StartResidentApplet"},
70 {0x003B0040, nullptr, "CancelLibraryApplet"}, 70 {0x003B0040, CancelLibraryApplet, "CancelLibraryApplet"},
71 {0x003C0042, nullptr, "SendDspSleep"}, 71 {0x003C0042, nullptr, "SendDspSleep"},
72 {0x003D0042, nullptr, "SendDspWakeUp"}, 72 {0x003D0042, nullptr, "SendDspWakeUp"},
73 {0x003E0080, nullptr, "ReplySleepQuery"}, 73 {0x003E0080, nullptr, "ReplySleepQuery"},
diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp
index 24eee6903..d3d0f3b55 100644
--- a/src/core/hle/service/cfg/cfg.cpp
+++ b/src/core/hle/service/cfg/cfg.cpp
@@ -45,7 +45,8 @@ static_assert(sizeof(SaveFileConfig) == 0x455C,
45enum ConfigBlockID { 45enum ConfigBlockID {
46 StereoCameraSettingsBlockID = 0x00050005, 46 StereoCameraSettingsBlockID = 0x00050005,
47 SoundOutputModeBlockID = 0x00070001, 47 SoundOutputModeBlockID = 0x00070001,
48 ConsoleUniqueIDBlockID = 0x00090001, 48 ConsoleUniqueID1BlockID = 0x00090000,
49 ConsoleUniqueID2BlockID = 0x00090001,
49 UsernameBlockID = 0x000A0000, 50 UsernameBlockID = 0x000A0000,
50 BirthdayBlockID = 0x000A0001, 51 BirthdayBlockID = 0x000A0001,
51 LanguageBlockID = 0x000A0002, 52 LanguageBlockID = 0x000A0002,
@@ -409,7 +410,12 @@ ResultCode FormatConfig() {
409 if (!res.IsSuccess()) 410 if (!res.IsSuccess())
410 return res; 411 return res;
411 412
412 res = CreateConfigInfoBlk(ConsoleUniqueIDBlockID, sizeof(CONSOLE_UNIQUE_ID), 0xE, 413 res = CreateConfigInfoBlk(ConsoleUniqueID1BlockID, sizeof(CONSOLE_UNIQUE_ID), 0xE,
414 &CONSOLE_UNIQUE_ID);
415 if (!res.IsSuccess())
416 return res;
417
418 res = CreateConfigInfoBlk(ConsoleUniqueID2BlockID, sizeof(CONSOLE_UNIQUE_ID), 0xE,
413 &CONSOLE_UNIQUE_ID); 419 &CONSOLE_UNIQUE_ID);
414 if (!res.IsSuccess()) 420 if (!res.IsSuccess())
415 return res; 421 return res;
diff --git a/src/core/hle/service/err_f.cpp b/src/core/hle/service/err_f.cpp
index 3ca4f98de..9905757c7 100644
--- a/src/core/hle/service/err_f.cpp
+++ b/src/core/hle/service/err_f.cpp
@@ -2,9 +2,15 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <array>
6#include <chrono>
7#include <iomanip>
8#include <sstream>
9
5#include "common/bit_field.h" 10#include "common/bit_field.h"
6#include "common/common_types.h" 11#include "common/common_types.h"
7#include "common/logging/log.h" 12#include "common/logging/log.h"
13#include "core/hle/result.h"
8#include "core/hle/service/err_f.h" 14#include "core/hle/service/err_f.h"
9 15
10//////////////////////////////////////////////////////////////////////////////////////////////////// 16////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -12,12 +18,45 @@
12 18
13namespace ERR_F { 19namespace ERR_F {
14 20
15enum { 21enum class FatalErrType : u32 {
16 ErrSpecifier0 = 0, 22 Generic = 0,
17 ErrSpecifier1 = 1, 23 Corrupted = 1,
18 ErrSpecifier3 = 3, 24 CardRemoved = 2,
19 ErrSpecifier4 = 4, 25 Exception = 3,
26 ResultFailure = 4,
27 Logged = 5,
28};
29
30enum class ExceptionType : u32 {
31 PrefetchAbort = 0,
32 DataAbort = 1,
33 Undefined = 2,
34 VectorFP = 3,
35};
36
37struct ExceptionInfo {
38 u8 exception_type;
39 INSERT_PADDING_BYTES(3);
40 u32 sr;
41 u32 ar;
42 u32 fpexc;
43 u32 fpinst;
44 u32 fpinst2;
45};
46static_assert(sizeof(ExceptionInfo) == 0x18, "ExceptionInfo struct has incorrect size");
47
48struct ExceptionContext final {
49 std::array<u32, 16> arm_regs;
50 u32 cpsr;
20}; 51};
52static_assert(sizeof(ExceptionContext) == 0x44, "ExceptionContext struct has incorrect size");
53
54struct ExceptionData {
55 ExceptionInfo exception_info;
56 ExceptionContext exception_context;
57 INSERT_PADDING_WORDS(1);
58};
59static_assert(sizeof(ExceptionData) == 0x60, "ExceptionData struct has incorrect size");
21 60
22// This is used instead of ResultCode from result.h 61// This is used instead of ResultCode from result.h
23// because we can't have non-trivial data members in unions. 62// because we can't have non-trivial data members in unions.
@@ -30,150 +69,191 @@ union RSL {
30 BitField<27, 5, u32> level; 69 BitField<27, 5, u32> level;
31}; 70};
32 71
33union ErrInfo { 72struct ErrInfo {
34 u8 specifier; 73 struct ErrInfoCommon {
35 74 u8 specifier; // 0x0
36 struct { 75 u8 rev_high; // 0x1
37 u8 specifier; // 0x0 76 u16 rev_low; // 0x2
38 u8 rev_high; // 0x1 77 RSL result_code; // 0x4
39 u16 rev_low; // 0x2 78 u32 pc_address; // 0x8
40 RSL result_code; // 0x4 79 u32 pid; // 0xC
41 u32 address; // 0x8 80 u32 title_id_low; // 0x10
42 INSERT_PADDING_BYTES(4); // 0xC 81 u32 title_id_high; // 0x14
43 u32 pid_low; // 0x10 82 u32 app_title_id_low; // 0x18
44 u32 pid_high; // 0x14 83 u32 app_title_id_high; // 0x1C
45 u32 aid_low; // 0x18 84 } errinfo_common;
46 u32 aid_high; // 0x1C 85 static_assert(sizeof(ErrInfoCommon) == 0x20, "ErrInfoCommon struct has incorrect size");
47 } errtype1; 86
48 87 union {
49 struct { 88 struct {
50 u8 specifier; // 0x0 89 char data[0x60]; // 0x20
51 u8 rev_high; // 0x1 90 } generic;
52 u16 rev_low; // 0x2 91
53 INSERT_PADDING_BYTES(0xC); // 0x4 92 struct {
54 u32 pid_low; // 0x10 93 ExceptionData exception_data; // 0x20
55 u32 pid_high; // 0x14 94 } exception;
56 u32 aid_low; // 0x18 95
57 u32 aid_high; // 0x1C 96 struct {
58 u8 error_type; // 0x20 97 char message[0x60]; // 0x20
59 INSERT_PADDING_BYTES(3); // 0x21 98 } result_failure;
60 u32 fault_status_reg; // 0x24 99 };
61 u32 fault_addr; // 0x28
62 u32 fpexc; // 0x2C
63 u32 finst; // 0x30
64 u32 finst2; // 0x34
65 INSERT_PADDING_BYTES(0x34); // 0x38
66 u32 sp; // 0x6C
67 u32 pc; // 0x70
68 u32 lr; // 0x74
69 u32 cpsr; // 0x78
70 } errtype3;
71
72 struct {
73 u8 specifier; // 0x0
74 u8 rev_high; // 0x1
75 u16 rev_low; // 0x2
76 RSL result_code; // 0x4
77 INSERT_PADDING_BYTES(8); // 0x8
78 u32 pid_low; // 0x10
79 u32 pid_high; // 0x14
80 u32 aid_low; // 0x18
81 u32 aid_high; // 0x1C
82 char debug_string1[0x2E]; // 0x20
83 char debug_string2[0x2E]; // 0x4E
84 } errtype4;
85}; 100};
86 101
87enum { PrefetchAbort = 0, DataAbort = 1, UndefInstr = 2, VectorFP = 3 }; 102static std::string GetErrType(u8 type_code) {
103 switch (static_cast<FatalErrType>(type_code)) {
104 case FatalErrType::Generic:
105 return "Generic";
106 case FatalErrType::Corrupted:
107 return "Corrupted";
108 case FatalErrType::CardRemoved:
109 return "CardRemoved";
110 case FatalErrType::Exception:
111 return "Exception";
112 case FatalErrType::ResultFailure:
113 return "ResultFailure";
114 case FatalErrType::Logged:
115 return "Logged";
116 default:
117 return "Unknown Error Type";
118 }
119}
88 120
89static std::string GetErrInfo3Type(u8 type_code) { 121static std::string GetExceptionType(u8 type_code) {
90 switch (type_code) { 122 switch (static_cast<ExceptionType>(type_code)) {
91 case PrefetchAbort: 123 case ExceptionType::PrefetchAbort:
92 return "Prefetch Abort"; 124 return "Prefetch Abort";
93 case DataAbort: 125 case ExceptionType::DataAbort:
94 return "Data Abort"; 126 return "Data Abort";
95 case UndefInstr: 127 case ExceptionType::Undefined:
96 return "Undefined Instruction"; 128 return "Undefined Exception";
97 case VectorFP: 129 case ExceptionType::VectorFP:
98 return "Vector Floating Point"; 130 return "Vector Floating Point Exception";
99 default: 131 default:
100 return "unknown"; 132 return "Unknown Exception Type";
101 } 133 }
102} 134}
103 135
136static std::string GetCurrentSystemTime() {
137 auto now = std::chrono::system_clock::now();
138 auto time = std::chrono::system_clock::to_time_t(now);
139
140 std::stringstream time_stream;
141 time_stream << std::put_time(std::localtime(&time), "%Y/%m/%d %H:%M:%S");
142 return time_stream.str();
143}
144
145static void LogGenericInfo(const ErrInfo::ErrInfoCommon& errinfo_common) {
146 LOG_CRITICAL(Service_ERR, "PID: 0x%08X", errinfo_common.pid);
147 LOG_CRITICAL(Service_ERR, "REV: 0x%08X_0x%08X", errinfo_common.rev_high,
148 errinfo_common.rev_low);
149 LOG_CRITICAL(Service_ERR, "TID: 0x%08X_0x%08X", errinfo_common.title_id_high,
150 errinfo_common.title_id_low);
151 LOG_CRITICAL(Service_ERR, "AID: 0x%08X_0x%08X", errinfo_common.app_title_id_high,
152 errinfo_common.app_title_id_low);
153 LOG_CRITICAL(Service_ERR, "ADR: 0x%08X", errinfo_common.pc_address);
154
155 LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errinfo_common.result_code.raw);
156 LOG_CRITICAL(Service_ERR, " Level: %u", errinfo_common.result_code.level.Value());
157 LOG_CRITICAL(Service_ERR, " Summary: %u", errinfo_common.result_code.summary.Value());
158 LOG_CRITICAL(Service_ERR, " Module: %u", errinfo_common.result_code.module.Value());
159 LOG_CRITICAL(Service_ERR, " Desc: %u", errinfo_common.result_code.description.Value());
160}
161
162/* ThrowFatalError function
163 * Inputs:
164 * 0 : Header code [0x00010800]
165 * 1-32 : FatalErrInfo
166 * Outputs:
167 * 0 : Header code
168 * 1 : Result code
169 */
104static void ThrowFatalError(Service::Interface* self) { 170static void ThrowFatalError(Service::Interface* self) {
105 u32* cmd_buff = Kernel::GetCommandBuffer(); 171 u32* cmd_buff = Kernel::GetCommandBuffer();
106 172
107 LOG_CRITICAL(Service_ERR, "Fatal error!"); 173 LOG_CRITICAL(Service_ERR, "Fatal error");
108 const ErrInfo* errinfo = reinterpret_cast<ErrInfo*>(&cmd_buff[1]); 174 const ErrInfo* errinfo = reinterpret_cast<ErrInfo*>(&cmd_buff[1]);
175 LOG_CRITICAL(Service_ERR, "Fatal error type: %s",
176 GetErrType(errinfo->errinfo_common.specifier).c_str());
109 177
110 switch (errinfo->specifier) { 178 // Generic Info
111 case ErrSpecifier0: 179 LogGenericInfo(errinfo->errinfo_common);
112 case ErrSpecifier1: { 180
113 const auto& errtype = errinfo->errtype1; 181 switch (static_cast<FatalErrType>(errinfo->errinfo_common.specifier)) {
114 LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high); 182 case FatalErrType::Generic:
115 LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16)); 183 case FatalErrType::Corrupted:
116 LOG_CRITICAL(Service_ERR, "AID: 0x%08X_0x%08X", errtype.aid_low, errtype.aid_high); 184 case FatalErrType::CardRemoved:
117 LOG_CRITICAL(Service_ERR, "ADR: 0x%08X", errtype.address); 185 case FatalErrType::Logged: {
118 186 LOG_CRITICAL(Service_ERR, "Datetime: %s", GetCurrentSystemTime().c_str());
119 LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw);
120 LOG_CRITICAL(Service_ERR, " Level: %u", errtype.result_code.level.Value());
121 LOG_CRITICAL(Service_ERR, " Summary: %u", errtype.result_code.summary.Value());
122 LOG_CRITICAL(Service_ERR, " Module: %u", errtype.result_code.module.Value());
123 LOG_CRITICAL(Service_ERR, " Desc: %u", errtype.result_code.description.Value());
124 break; 187 break;
125 } 188 }
189 case FatalErrType::Exception: {
190 const auto& errtype = errinfo->exception;
191
192 // Register Info
193 LOG_CRITICAL(Service_ERR, "ARM Registers:");
194 for (u32 index = 0; index < errtype.exception_data.exception_context.arm_regs.size();
195 ++index) {
196 if (index < 13) {
197 LOG_DEBUG(Service_ERR, "r%u=0x%08X", index,
198 errtype.exception_data.exception_context.arm_regs.at(index));
199 } else if (index == 13) {
200 LOG_CRITICAL(Service_ERR, "SP=0x%08X",
201 errtype.exception_data.exception_context.arm_regs.at(index));
202 } else if (index == 14) {
203 LOG_CRITICAL(Service_ERR, "LR=0x%08X",
204 errtype.exception_data.exception_context.arm_regs.at(index));
205 } else if (index == 15) {
206 LOG_CRITICAL(Service_ERR, "PC=0x%08X",
207 errtype.exception_data.exception_context.arm_regs.at(index));
208 }
209 }
210 LOG_CRITICAL(Service_ERR, "CPSR=0x%08X", errtype.exception_data.exception_context.cpsr);
126 211
127 case ErrSpecifier3: { 212 // Exception Info
128 const auto& errtype = errinfo->errtype3; 213 LOG_CRITICAL(
129 LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high); 214 Service_ERR, "EXCEPTION TYPE: %s",
130 LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16)); 215 GetExceptionType(errtype.exception_data.exception_info.exception_type).c_str());
131 LOG_CRITICAL(Service_ERR, "AID: 0x%08X_0x%08X", errtype.aid_low, errtype.aid_high); 216 switch (static_cast<ExceptionType>(errtype.exception_data.exception_info.exception_type)) {
132 LOG_CRITICAL(Service_ERR, "TYPE: %s", GetErrInfo3Type(errtype.error_type).c_str()); 217 case ExceptionType::PrefetchAbort:
133 218 LOG_CRITICAL(Service_ERR, "IFSR: 0x%08X", errtype.exception_data.exception_info.sr);
134 LOG_CRITICAL(Service_ERR, "PC: 0x%08X", errtype.pc); 219 LOG_CRITICAL(Service_ERR, "r15: 0x%08X", errtype.exception_data.exception_info.ar);
135 LOG_CRITICAL(Service_ERR, "LR: 0x%08X", errtype.lr); 220 case ExceptionType::DataAbort:
136 LOG_CRITICAL(Service_ERR, "SP: 0x%08X", errtype.sp); 221 LOG_CRITICAL(Service_ERR, "DFSR: 0x%08X", errtype.exception_data.exception_info.sr);
137 LOG_CRITICAL(Service_ERR, "CPSR: 0x%08X", errtype.cpsr); 222 LOG_CRITICAL(Service_ERR, "DFAR: 0x%08X", errtype.exception_data.exception_info.ar);
138
139 switch (errtype.error_type) {
140 case PrefetchAbort:
141 case DataAbort:
142 LOG_CRITICAL(Service_ERR, "Fault Address: 0x%08X", errtype.fault_addr);
143 LOG_CRITICAL(Service_ERR, "Fault Status Register: 0x%08X", errtype.fault_status_reg);
144 break; 223 break;
145 case VectorFP: 224 case ExceptionType::VectorFP:
146 LOG_CRITICAL(Service_ERR, "FPEXC: 0x%08X", errtype.fpexc); 225 LOG_CRITICAL(Service_ERR, "FPEXC: 0x%08X",
147 LOG_CRITICAL(Service_ERR, "FINST: 0x%08X", errtype.finst); 226 errtype.exception_data.exception_info.fpinst);
148 LOG_CRITICAL(Service_ERR, "FINST2: 0x%08X", errtype.finst2); 227 LOG_CRITICAL(Service_ERR, "FINST: 0x%08X",
228 errtype.exception_data.exception_info.fpinst);
229 LOG_CRITICAL(Service_ERR, "FINST2: 0x%08X",
230 errtype.exception_data.exception_info.fpinst2);
149 break; 231 break;
150 } 232 }
233 LOG_CRITICAL(Service_ERR, "Datetime: %s", GetCurrentSystemTime().c_str());
151 break; 234 break;
152 } 235 }
153 236
154 case ErrSpecifier4: { 237 case FatalErrType::ResultFailure: {
155 const auto& errtype = errinfo->errtype4; 238 const auto& errtype = errinfo->result_failure;
156 LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high);
157 LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16));
158 LOG_CRITICAL(Service_ERR, "AID: 0x%08X_0x%08X", errtype.aid_low, errtype.aid_high);
159 239
160 LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw); 240 // Failure Message
161 LOG_CRITICAL(Service_ERR, " Level: %u", errtype.result_code.level.Value()); 241 LOG_CRITICAL(Service_ERR, "Failure Message: %s", errtype.message);
162 LOG_CRITICAL(Service_ERR, " Summary: %u", errtype.result_code.summary.Value()); 242 LOG_CRITICAL(Service_ERR, "Datetime: %s", GetCurrentSystemTime().c_str());
163 LOG_CRITICAL(Service_ERR, " Module: %u", errtype.result_code.module.Value());
164 LOG_CRITICAL(Service_ERR, " Desc: %u", errtype.result_code.description.Value());
165
166 LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string1);
167 LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string2);
168 break; 243 break;
169 } 244 }
170 }
171 245
172 cmd_buff[1] = 0; // No error 246 } // switch FatalErrType
247
248 cmd_buff[0] = IPC::MakeHeader(0x1, 1, 0);
249 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
173} 250}
174 251
175const Interface::FunctionInfo FunctionTable[] = { 252const Interface::FunctionInfo FunctionTable[] = {
253 // clang-format off
176 {0x00010800, ThrowFatalError, "ThrowFatalError"}, 254 {0x00010800, ThrowFatalError, "ThrowFatalError"},
255 {0x00020042, nullptr, "SetUserString"},
256 // clang-format on
177}; 257};
178 258
179//////////////////////////////////////////////////////////////////////////////////////////////////// 259////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 64c388374..65e4bba85 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -45,13 +45,11 @@ struct SpecialRegion {
45 * requires an indexed fetch and a check for NULL. 45 * requires an indexed fetch and a check for NULL.
46 */ 46 */
47struct PageTable { 47struct PageTable {
48 static const size_t NUM_ENTRIES = 1 << (32 - PAGE_BITS);
49
50 /** 48 /**
51 * Array of memory pointers backing each page. An entry can only be non-null if the 49 * Array of memory pointers backing each page. An entry can only be non-null if the
52 * corresponding entry in the `attributes` array is of type `Memory`. 50 * corresponding entry in the `attributes` array is of type `Memory`.
53 */ 51 */
54 std::array<u8*, NUM_ENTRIES> pointers; 52 std::array<u8*, PAGE_TABLE_NUM_ENTRIES> pointers;
55 53
56 /** 54 /**
57 * Contains MMIO handlers that back memory regions whose entries in the `attribute` array is of 55 * Contains MMIO handlers that back memory regions whose entries in the `attribute` array is of
@@ -63,13 +61,13 @@ struct PageTable {
63 * Array of fine grained page attributes. If it is set to any value other than `Memory`, then 61 * Array of fine grained page attributes. If it is set to any value other than `Memory`, then
64 * the corresponding entry in `pointers` MUST be set to null. 62 * the corresponding entry in `pointers` MUST be set to null.
65 */ 63 */
66 std::array<PageType, NUM_ENTRIES> attributes; 64 std::array<PageType, PAGE_TABLE_NUM_ENTRIES> attributes;
67 65
68 /** 66 /**
69 * Indicates the number of externally cached resources touching a page that should be 67 * Indicates the number of externally cached resources touching a page that should be
70 * flushed before the memory is accessed 68 * flushed before the memory is accessed
71 */ 69 */
72 std::array<u8, NUM_ENTRIES> cached_res_count; 70 std::array<u8, PAGE_TABLE_NUM_ENTRIES> cached_res_count;
73}; 71};
74 72
75/// Singular page table used for the singleton process 73/// Singular page table used for the singleton process
@@ -77,6 +75,10 @@ static PageTable main_page_table;
77/// Currently active page table 75/// Currently active page table
78static PageTable* current_page_table = &main_page_table; 76static PageTable* current_page_table = &main_page_table;
79 77
78std::array<u8*, PAGE_TABLE_NUM_ENTRIES>* GetCurrentPageTablePointers() {
79 return &current_page_table->pointers;
80}
81
80static void MapPages(u32 base, u32 size, u8* memory, PageType type) { 82static void MapPages(u32 base, u32 size, u8* memory, PageType type) {
81 LOG_DEBUG(HW_Memory, "Mapping %p onto %08X-%08X", memory, base * PAGE_SIZE, 83 LOG_DEBUG(HW_Memory, "Mapping %p onto %08X-%08X", memory, base * PAGE_SIZE,
82 (base + size) * PAGE_SIZE); 84 (base + size) * PAGE_SIZE);
@@ -84,7 +86,7 @@ static void MapPages(u32 base, u32 size, u8* memory, PageType type) {
84 u32 end = base + size; 86 u32 end = base + size;
85 87
86 while (base != end) { 88 while (base != end) {
87 ASSERT_MSG(base < PageTable::NUM_ENTRIES, "out of range mapping at %08X", base); 89 ASSERT_MSG(base < PAGE_TABLE_NUM_ENTRIES, "out of range mapping at %08X", base);
88 90
89 // Since pages are unmapped on shutdown after video core is shutdown, the renderer may be 91 // Since pages are unmapped on shutdown after video core is shutdown, the renderer may be
90 // null here 92 // null here
diff --git a/src/core/memory.h b/src/core/memory.h
index 8fd3080ff..903b58a22 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
7#include <cstddef> 8#include <cstddef>
8#include <string> 9#include <string>
9#include "common/common_types.h" 10#include "common/common_types.h"
@@ -17,6 +18,7 @@ namespace Memory {
17const u32 PAGE_SIZE = 0x1000; 18const u32 PAGE_SIZE = 0x1000;
18const u32 PAGE_MASK = PAGE_SIZE - 1; 19const u32 PAGE_MASK = PAGE_SIZE - 1;
19const int PAGE_BITS = 12; 20const int PAGE_BITS = 12;
21const size_t PAGE_TABLE_NUM_ENTRIES = 1 << (32 - PAGE_BITS);
20 22
21/// Physical memory regions as seen from the ARM11 23/// Physical memory regions as seen from the ARM11
22enum : PAddr { 24enum : PAddr {
@@ -166,4 +168,11 @@ void RasterizerFlushRegion(PAddr start, u32 size);
166 * Flushes and invalidates any externally cached rasterizer resources touching the given region. 168 * Flushes and invalidates any externally cached rasterizer resources touching the given region.
167 */ 169 */
168void RasterizerFlushAndInvalidateRegion(PAddr start, u32 size); 170void RasterizerFlushAndInvalidateRegion(PAddr start, u32 size);
171
172/**
173 * Dynarmic has an optimization to memory accesses when the pointer to the page exists that
174 * can be used by setting up the current page table as a callback. This function is used to
175 * retrieve the current page table for that purpose.
176 */
177std::array<u8*, PAGE_TABLE_NUM_ENTRIES>* GetCurrentPageTablePointers();
169} 178}
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp
index fda91e29c..b7c32035e 100644
--- a/src/video_core/command_processor.cpp
+++ b/src/video_core/command_processor.cpp
@@ -215,18 +215,17 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
215 215
216 PrimitiveAssembler<Shader::OutputVertex>& primitive_assembler = g_state.primitive_assembler; 216 PrimitiveAssembler<Shader::OutputVertex>& primitive_assembler = g_state.primitive_assembler;
217 217
218 if (g_debug_context) { 218 if (g_debug_context && g_debug_context->recorder) {
219 for (int i = 0; i < 3; ++i) { 219 for (int i = 0; i < 3; ++i) {
220 const auto texture = regs.GetTextures()[i]; 220 const auto texture = regs.GetTextures()[i];
221 if (!texture.enabled) 221 if (!texture.enabled)
222 continue; 222 continue;
223 223
224 u8* texture_data = Memory::GetPhysicalPointer(texture.config.GetPhysicalAddress()); 224 u8* texture_data = Memory::GetPhysicalPointer(texture.config.GetPhysicalAddress());
225 if (g_debug_context && Pica::g_debug_context->recorder) 225 g_debug_context->recorder->MemoryAccessed(
226 g_debug_context->recorder->MemoryAccessed( 226 texture_data, Pica::Regs::NibblesPerPixel(texture.format) *
227 texture_data, Pica::Regs::NibblesPerPixel(texture.format) * 227 texture.config.width / 2 * texture.config.height,
228 texture.config.width / 2 * texture.config.height, 228 texture.config.GetPhysicalAddress());
229 texture.config.GetPhysicalAddress());
230 } 229 }
231 } 230 }
232 231
@@ -236,7 +235,8 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
236 // The size has been tuned for optimal balance between hit-rate and the cost of lookup 235 // The size has been tuned for optimal balance between hit-rate and the cost of lookup
237 const size_t VERTEX_CACHE_SIZE = 32; 236 const size_t VERTEX_CACHE_SIZE = 32;
238 std::array<u16, VERTEX_CACHE_SIZE> vertex_cache_ids; 237 std::array<u16, VERTEX_CACHE_SIZE> vertex_cache_ids;
239 std::array<Shader::OutputRegisters, VERTEX_CACHE_SIZE> vertex_cache; 238 std::array<Shader::OutputVertex, VERTEX_CACHE_SIZE> vertex_cache;
239 Shader::OutputVertex output_vertex;
240 240
241 unsigned int vertex_cache_pos = 0; 241 unsigned int vertex_cache_pos = 0;
242 vertex_cache_ids.fill(-1); 242 vertex_cache_ids.fill(-1);
@@ -266,7 +266,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
266 266
267 for (unsigned int i = 0; i < VERTEX_CACHE_SIZE; ++i) { 267 for (unsigned int i = 0; i < VERTEX_CACHE_SIZE; ++i) {
268 if (vertex == vertex_cache_ids[i]) { 268 if (vertex == vertex_cache_ids[i]) {
269 output_registers = vertex_cache[i]; 269 output_vertex = vertex_cache[i];
270 vertex_cache_hit = true; 270 vertex_cache_hit = true;
271 break; 271 break;
272 } 272 }
@@ -285,16 +285,16 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
285 g_state.vs.Run(shader_unit, input, loader.GetNumTotalAttributes()); 285 g_state.vs.Run(shader_unit, input, loader.GetNumTotalAttributes());
286 output_registers = shader_unit.output_registers; 286 output_registers = shader_unit.output_registers;
287 287
288 // Retrieve vertex from register data
289 output_vertex = output_registers.ToVertex(regs.vs);
290
288 if (is_indexed) { 291 if (is_indexed) {
289 vertex_cache[vertex_cache_pos] = output_registers; 292 vertex_cache[vertex_cache_pos] = output_vertex;
290 vertex_cache_ids[vertex_cache_pos] = vertex; 293 vertex_cache_ids[vertex_cache_pos] = vertex;
291 vertex_cache_pos = (vertex_cache_pos + 1) % VERTEX_CACHE_SIZE; 294 vertex_cache_pos = (vertex_cache_pos + 1) % VERTEX_CACHE_SIZE;
292 } 295 }
293 } 296 }
294 297
295 // Retrieve vertex from register data
296 Shader::OutputVertex output_vertex = output_registers.ToVertex(regs.vs);
297
298 // Send to renderer 298 // Send to renderer
299 using Pica::Shader::OutputVertex; 299 using Pica::Shader::OutputVertex;
300 auto AddTriangle = [](const OutputVertex& v0, const OutputVertex& v1, 300 auto AddTriangle = [](const OutputVertex& v0, const OutputVertex& v1,
diff --git a/src/video_core/pica.h b/src/video_core/pica.h
index b2db609ec..99bd59a69 100644
--- a/src/video_core/pica.h
+++ b/src/video_core/pica.h
@@ -40,7 +40,7 @@ namespace Pica {
40// field offset. Otherwise, the compiler will fail to compile this code. 40// field offset. Otherwise, the compiler will fail to compile this code.
41#define PICA_REG_INDEX_WORKAROUND(field_name, backup_workaround_index) \ 41#define PICA_REG_INDEX_WORKAROUND(field_name, backup_workaround_index) \
42 ((typename std::enable_if<backup_workaround_index == PICA_REG_INDEX(field_name), \ 42 ((typename std::enable_if<backup_workaround_index == PICA_REG_INDEX(field_name), \
43 size_t>::type)PICA_REG_INDEX(field_name)) 43 size_t>::type) PICA_REG_INDEX(field_name))
44#endif // _MSC_VER 44#endif // _MSC_VER
45 45
46struct Regs { 46struct Regs {