Update the code of APT service(part2)

This commit is contained in:
JamePeng 2016-08-17 22:29:15 +08:00
parent 04a2cb01cf
commit 5cfd37225a
6 changed files with 884 additions and 121 deletions

View File

@ -17,6 +17,7 @@
/// Detailed description of the error. This listing is likely incomplete.
enum class ErrorDescription : u32 {
Success = 0,
InvalidMemoryPermissions = 2,
WrongPermission = 46,
OS_InvalidBufferDescriptor = 48,
WrongAddress = 53,

View File

@ -7,6 +7,7 @@
#include "common/logging/log.h"
#include "core/hle/applets/applet.h"
#include "core/hle/config_mem.h"
#include "core/hle/service/service.h"
#include "core/hle/service/apt/apt.h"
#include "core/hle/service/apt/apt_a.h"
@ -14,6 +15,7 @@
#include "core/hle/service/apt/apt_u.h"
#include "core/hle/service/apt/bcfnt/bcfnt.h"
#include "core/hle/service/fs/archive.h"
#include "core/hle/service/gsp_gpu.h"
#include "core/hle/service/ptm/ptm.h"
#include "core/hle/kernel/event.h"
@ -21,6 +23,9 @@
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/shared_memory.h"
#include "core/hw/gpu.h"
#include "core/settings.h"
namespace Service {
namespace APT {
@ -33,6 +38,13 @@ static Kernel::SharedPtr<Kernel::Event> notification_event; ///< APT notificatio
static Kernel::SharedPtr<Kernel::Event> parameter_event; ///< APT parameter event
static u32 cpu_percent; ///< CPU time available to the running application
static u32 homemenu_input_buffer;
static bool is_capture_buffer_info_set = false;
static bool is_homemenu_input_buffer_set = false;
static AppletPreparationState applet_preparation_state = AppletPreparationState::NoPreparation;
static CaptureBufferInfo capture_buffer_info;
static WirelessRebootInfo wireless_reboot_info;
// APT::CheckNew3DSApp will check this unknown_ns_state_field to determine processing mode
static u8 unknown_ns_state_field;
@ -41,6 +53,46 @@ static ScreencapPostPermission screen_capture_post_permission;
/// Parameter data to be returned in the next call to Glance/ReceiveParameter
static MessageParameter next_parameter;
static std::array<MessageParameter, 0x4> MessageParameters;
/**
* GetMessageParametersIndex(sub_10F564)
* Index 0 :
* 0x300 : Application
* Index 1 :
* 0x11X : System Applet
* Index 2 :
* 0x10X : Home Menu
* Index 3 :
* 0x2XX : Library Applet
* 0x4XX : Library Applet
*/
static u32 GetMessageParametersIndex(const u32& app_id) {
u32 result = 0;
if (!(app_id & 0xFF)) {
return 0xFFFFFFFF;
} else {
if (app_id == 0x101 || app_id == 0x103) {
if (app_id & 0x100) {
return 0x2;
}
return 0xFFFFFFFF;
}
if ((app_id & 0x300) != app_id) {
if ((app_id & 0x110) != app_id) {
if ((app_id & 0x100) != app_id) {
if ((app_id & 0x200) != app_id && (app_id & 0x400) != app_id) {
return 0xFFFFFFFF;
}
return 3;
}
return 2;
}
return 1;
}
return 0;
}
}
void SendParameter(const MessageParameter& parameter) {
next_parameter = parameter;
@ -48,6 +100,16 @@ void SendParameter(const MessageParameter& parameter) {
parameter_event->Signal();
}
void SendParameter(const u32& dst_app_id, const MessageParameter& parameter) {
u32 index = GetMessageParametersIndex(dst_app_id);
if(index != 0xFFFFFFFF){
memcpy(&MessageParameters[index], &parameter, sizeof(MessageParameter));
}
// Signal the event to let the application know that a new parameter is ready to be read
parameter_event->Signal();
}
void Initialize(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 app_id = cmd_buff[1];
@ -100,11 +162,213 @@ void GetSharedFont(Service::Interface* self) {
cmd_buff[4] = Kernel::g_handle_table.Create(shared_font_mem).MoveFrom();
}
void GetWirelessRebootInfo(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 buffer_size = cmd_buff[1];
VAddr buffer_addr = cmd_buff[0x41];
if (buffer_size > sizeof(WirelessRebootInfo)) {
buffer_size = sizeof(WirelessRebootInfo);
}
memcpy(&wireless_reboot_info, Memory::GetPointer(buffer_addr), sizeof(buffer_size));
cmd_buff[0] = IPC::MakeHeader(0x45, 0x1, 0x2);
cmd_buff[1] = RESULT_SUCCESS.raw;
cmd_buff[2] = (buffer_size << 14) | 2;
cmd_buff[3] = buffer_size;
LOG_WARNING(Service_APT, "(STUBBED) called");
}
void PrepareToLeaveResidentApplet(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 caller_exiting = cmd_buff[1] & 0xFF;
cmd_buff[1] = RESULT_SUCCESS.raw;
LOG_WARNING(Service_APT, "(STUBBED) caller_exiting=0x%08X", caller_exiting);
}
void LeaveResidentApplet(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 parameters_size = cmd_buff[1];
u32 parameter_handle = cmd_buff[3];
u32 parameters_addr = cmd_buff[5];
cmd_buff[1] = RESULT_SUCCESS.raw;
LOG_WARNING(Service_APT, "(STUBBED) parameter_size=0x%08X, parameter_handle=0x%08X, parameter_addr=0x%08X",
parameters_size, parameter_handle, parameters_addr);
}
void PreloadResidentApplet(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 app_id = cmd_buff[1];
cmd_buff[1] = RESULT_SUCCESS.raw;
LOG_WARNING(Service_APT, "(STUBBED) app_id=0x%08X", app_id);
}
void PrepareToStartResidentApplet(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 app_id = cmd_buff[1];
cmd_buff[1] = RESULT_SUCCESS.raw;
LOG_WARNING(Service_APT, "(STUBBED) app_id=0x%08X", app_id);
}
void StartResidentApplet(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 parameters_size = cmd_buff[1];
u32 parameter_handle = cmd_buff[3];
u32 parameters_addr = cmd_buff[5];
cmd_buff[1] = RESULT_SUCCESS.raw;
LOG_WARNING(Service_APT, "(STUBBED) parameter_size=0x%08X, parameter_handle=0x%08X, parameter_addr=0x%08X",
parameters_size, parameter_handle, parameters_addr);
}
void CancelLibraryApplet(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 application_exiting = cmd_buff[1] & 0xf;
cmd_buff[0] = IPC::MakeHeader(0x3B, 0x1, 0);
cmd_buff[1] = RESULT_SUCCESS.raw;
LOG_WARNING(Service_APT, "(STUBBED) application_exiting=%u", application_exiting);
}
void ReplySleepQuery(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 app_id = cmd_buff[1];
QueryReply query_reply = static_cast<QueryReply>(cmd_buff[2] & 0xFF);
cmd_buff[1] = RESULT_SUCCESS.raw;
if (query_reply == QueryReply::Reject) {
LOG_ERROR(Service_APT, "(STUBBED) app_id=0x%08X, query_reply=REJECT", app_id);
} else {
LOG_WARNING(Service_APT, "(STUBBED) app_id=0x%08X, query_reply=%u", app_id, query_reply);
}
}
void ReplySleepNotificationComplete(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 app_id = cmd_buff[1];
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
LOG_WARNING(Service_APT, "(STUBBED) app_id=0x%08X", app_id);
}
static void InitCaptureBufferInfo() {
u32 thread_id = 0;
u32 top_screen_color_per_pixel;
u32 bottom_screen_color_per_pixel;
GSP_GPU::FrameBufferUpdate* top_screen = GSP_GPU::GetFrameBufferInfo(thread_id, 0);
GSP_GPU::FrameBufferUpdate* bottom_screen = GSP_GPU::GetFrameBufferInfo(thread_id, 1);
// not 3D
capture_buffer_info.is_3d = 0;
// main screen config
capture_buffer_info.top_screen_left_offset = top_screen->framebuffer_info[top_screen->index].address_left;
capture_buffer_info.top_screen_right_offset = top_screen->framebuffer_info[top_screen->index].address_right;
capture_buffer_info.top_screen_format = top_screen->framebuffer_info[top_screen->index].format & 0x7;
// sub screen config
capture_buffer_info.bottom_screen_left_offset = bottom_screen->framebuffer_info[bottom_screen->index].address_left;
capture_buffer_info.bottom_screen_right_offset = bottom_screen->framebuffer_info[bottom_screen->index].address_right;
capture_buffer_info.bottom_screen_format = bottom_screen->framebuffer_info[bottom_screen->index].format & 0x7;
top_screen_color_per_pixel = GPU::Regs::BytesPerPixel(static_cast<GPU::Regs::PixelFormat>(capture_buffer_info.top_screen_format));
bottom_screen_color_per_pixel = GPU::Regs::BytesPerPixel(static_cast<GPU::Regs::PixelFormat>(capture_buffer_info.bottom_screen_format));
capture_buffer_info.size = 240 * (top_screen_color_per_pixel * 400 + bottom_screen_color_per_pixel * 320);
is_capture_buffer_info_set = true;
}
ResultCode SendCaptureBufferInfo(u32& buffer_addr, u32& buffer_size) {
if (buffer_addr) {
if (buffer_size > sizeof(CaptureBufferInfo)) {
buffer_size = sizeof(CaptureBufferInfo);
}
is_capture_buffer_info_set = true;
} else {
buffer_size = 0;
}
memcpy(&capture_buffer_info, Memory::GetPointer(buffer_addr), buffer_size);
return RESULT_SUCCESS;
}
void SendCaptureBufferInfo(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 buffer_size = cmd_buff[1];
u32 buffer_transition = cmd_buff[2];
u32 buffer_addr = cmd_buff[3];
if ((buffer_transition & 0x3C0F) != 0x2) {
cmd_buff[0] = IPC::MakeHeader(0, 0x1, 0);
cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS,
ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; //0xD9001830
return;
}
cmd_buff[0] = IPC::MakeHeader(0x40, 0x1, 0); //0x00400040
cmd_buff[1] = SendCaptureBufferInfo(buffer_addr, buffer_size).raw;
LOG_WARNING(Service_APT, "buffer_addr=0x%08X, buffer_size=0x%08X", buffer_addr, buffer_size);
}
ResultCode ReceiveCaptureBufferInfo(u32& buffer_addr, u32 buffer_size) {
if (buffer_addr) {
if (buffer_size > sizeof(CaptureBufferInfo)) {
buffer_size = sizeof(CaptureBufferInfo);
}
} else {
buffer_size = 0;
}
if (is_capture_buffer_info_set) {
memcpy(Memory::GetPointer(buffer_addr), &capture_buffer_info, buffer_size);
} else {
InitCaptureBufferInfo();
memcpy(Memory::GetPointer(buffer_addr), &capture_buffer_info, buffer_size);
}
return RESULT_SUCCESS;
}
void ReceiveCaptureBufferInfo(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 buffer_size = cmd_buff[1];
VAddr buffer_addr = cmd_buff[0x41];
if (buffer_size > 0x1000) {
buffer_size = 0x1000;
}
cmd_buff[0] = IPC::MakeHeader(0x41, 0x2, 0x2); //0x00410082
cmd_buff[1] = ReceiveCaptureBufferInfo(buffer_addr, buffer_size).raw;
cmd_buff[2] = buffer_size;
cmd_buff[3] = (buffer_size << 14) | 2;
LOG_WARNING(Service_APT, "buffer_size=0x%08X", buffer_size);
}
void GetCaptureInfo(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 buffer_size = cmd_buff[1];
VAddr buffer_addr = cmd_buff[0x41];
if (buffer_size > 0x1000) {
buffer_size = 0x1000;
}
cmd_buff[0] = IPC::MakeHeader(0x4A, 0x1, 0x2);
cmd_buff[1] = ReceiveCaptureBufferInfo(buffer_addr, buffer_size).raw;
cmd_buff[2] = (buffer_size << 14) | 2;
LOG_WARNING(Service_APT, "buffer_size=0x%08X", buffer_size);
}
void NotifyToWait(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 app_id = cmd_buff[1];
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
LOG_WARNING(Service_APT, "(STUBBED) app_id=%u", app_id);
LOG_WARNING(Service_APT, "(STUBBED) app_id=0x%08X", app_id);
}
void GetLockHandle(Service::Interface* self) {
@ -127,6 +391,7 @@ void GetLockHandle(Service::Interface* self) {
void Enable(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 attributes = cmd_buff[1];
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
parameter_event->Signal(); // Let the application know that it has been started
LOG_WARNING(Service_APT, "(STUBBED) called attributes=0x%08X", attributes);
@ -134,14 +399,22 @@ void Enable(Service::Interface* self) {
void GetAppletManInfo(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 unk = cmd_buff[1];
AppletPos applet_pos = static_cast<AppletPos>(cmd_buff[1]);
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
cmd_buff[2] = 0;
cmd_buff[2] = static_cast<u32>(applet_pos);
cmd_buff[3] = 0;
cmd_buff[4] = static_cast<u32>(AppletId::HomeMenu); // Home menu AppID
cmd_buff[5] = static_cast<u32>(AppletId::Application); // TODO(purpasmart96): Do this correctly
LOG_WARNING(Service_APT, "(STUBBED) called applet_pos=0x%08X", applet_pos);
}
LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk);
void CountRegisteredApplet(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
cmd_buff[2] = HLE::Applets::GetRegisteredAppletCount();
LOG_WARNING(Service_APT, "registered_applet_count=0x%08X", cmd_buff[2]);
}
void IsRegistered(Service::Interface* self) {
@ -164,6 +437,7 @@ void IsRegistered(Service::Interface* self) {
void InquireNotification(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 app_id = cmd_buff[1];
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
cmd_buff[2] = static_cast<u32>(SignalType::None); // Signal type
LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X", app_id);
@ -207,7 +481,7 @@ void ReceiveParameter(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 app_id = cmd_buff[1];
u32 buffer_size = cmd_buff[2];
VAddr buffer = cmd_buff[0x104 >> 2];
VAddr buffer = cmd_buff[0x41];
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
cmd_buff[2] = next_parameter.sender_id;
@ -229,7 +503,7 @@ void GlanceParameter(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 app_id = cmd_buff[1];
u32 buffer_size = cmd_buff[2];
VAddr buffer = cmd_buff[0x104 >> 2];
VAddr buffer = cmd_buff[0x41];
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
cmd_buff[2] = next_parameter.sender_id;
@ -249,16 +523,32 @@ void GlanceParameter(Service::Interface* self) {
void CancelParameter(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 flag1 = cmd_buff[1];
u32 unk = cmd_buff[2];
u32 flag2 = cmd_buff[3];
u32 app_id = cmd_buff[4];
u32 check_sender = cmd_buff[1] & 0xFF;
u32 sender_id = cmd_buff[2];
u32 check_receiver = cmd_buff[3] & 0xFF;
u32 receiver_id = cmd_buff[4];
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
cmd_buff[2] = 1; // Set to Success
LOG_WARNING(Service_APT, "(STUBBED) called flag1=0x%08X, unk=0x%08X, flag2=0x%08X, app_id=0x%08X",
flag1, unk, flag2, app_id);
LOG_WARNING(Service_APT, "(STUBBED) check_sender=0x%08X, sender_id=0x%08X, check_receiver=0x%08X, receiver_id=0x%08X",
check_sender, sender_id, check_receiver, receiver_id);
}
void GetPreparationState(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
cmd_buff[2] = static_cast<u32>(applet_preparation_state);
LOG_WARNING(Service_APT, "(STUBBED) called");
}
void SetPreparationState(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
applet_preparation_state = static_cast<AppletPreparationState>(cmd_buff[1]);
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
LOG_WARNING(Service_APT, "(STUBBED) applet_preparation_state=0x%08X", applet_preparation_state);
}
void PrepareToStartApplication(Service::Interface* self) {
@ -281,36 +571,119 @@ void PrepareToStartApplication(Service::Interface* self) {
void StartApplication(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 buffer1_size = cmd_buff[1];
u32 buffer2_size = cmd_buff[2];
u32 flag = cmd_buff[3];
u32 size1 = cmd_buff[4];
u32 buffer1_ptr = cmd_buff[5];
u32 size2 = cmd_buff[6];
u32 buffer2_ptr = cmd_buff[7];
u32 parameter_size = cmd_buff[1];
u32 hmac_size = cmd_buff[2];
u32 is_paused = cmd_buff[3] & 0xFF;
u32 parameter_transition = cmd_buff[4];
u32 parameter_buffer = cmd_buff[5];
u32 hmac_transtion = cmd_buff[6];
u32 hmac_buffer = cmd_buff[7];
if ((parameter_transition & 0x3C0F) != 2 || (hmac_transtion & 0x3C0F) != 0x802) {
cmd_buff[0] = IPC::MakeHeader(0, 0x1, 0); // 0x40
cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS,
ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; //0xD9001830
return;
}
cmd_buff[0] = IPC::MakeHeader(0x1B, 0x1, 0);
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
LOG_WARNING(Service_APT, "(STUBBED) parameter_size=0x%08X, hmac_size=0x%08X, is_paused=0x%08X, parameter_buffer=0x%08X, hmac_buffer=0x%08X",
parameter_size, hmac_size, is_paused, parameter_buffer, hmac_buffer);
}
LOG_WARNING(Service_APT, "(STUBBED) called buffer1_size=0x%08X, buffer2_size=0x%08X, flag=0x%08X,"
"size1=0x%08X, buffer1_ptr=0x%08X, size2=0x%08X, buffer2_ptr=0x%08X",
buffer1_size, buffer2_size, flag, size1, buffer1_ptr, size2, buffer2_ptr);
ResultCode AppletUtility(u32& utility_id, u32& input_buffer, u32& input_size, u32& output_buffer,u32& output_size, bool applet_result) {
u32 sender_id = 0;
u32 transition = 0;
bool shell_open = true;
switch (static_cast<UtilityID>(utility_id)) {
case UtilityID::ClearPowerButtonState: // not useful
case UtilityID::ClearExclusiveControl:
break;
case UtilityID::SleepIfShellClosed:
shell_open = PTM::GetShellState();
if (!shell_open) {
LOG_WARNING(Service_APT, "(STUBBED) SleepIfShellClosed, The 3DS system should sleep now.");
}
else {
LOG_WARNING(Service_APT, "(STUBBED) SleepIfShellClosed shell_open=%u", shell_open);
}
break;
case UtilityID::LockTransition:
transition = Memory::Read32(input_buffer);
LOG_WARNING(Service_APT, "(STUBBED) LockTransition, transition=0x%08X", transition);
break;
case UtilityID::TryLockTransition:
applet_result = false;
if (output_buffer) {
if (output_size != 0) {
transition = Memory::Read32(input_buffer);
Memory::Write32(output_buffer, 0);
applet_result = true;
LOG_WARNING(Service_APT, "(STUBBED) TryLockTransition, transition=0x%08X", transition);
}
}
LOG_ERROR(Service_APT, "(STUBBED) Utility TryLockTransition Operation Failed");
break;
case UtilityID::UnlockTransition:
transition = Memory::Read32(input_buffer);
LOG_WARNING(Service_APT, "(STUBBED) UnlockTransition, transition=0x%08X", transition);
break;
case UtilityID::StartExitTask: // not useful
break;
case UtilityID::SetInitialSenderId:
sender_id = Memory::Read32(input_buffer);
LOG_WARNING(Service_APT, "(STUBBED) SetInitialSenderId, sender_id=0x%08X", sender_id);
break;
case UtilityID::SetPowerButtonClick: // not useful
break;
case UtilityID::SetHomeMenuBuffer:
// This input_buffer content(may be a src_appid or a dst_appid)
// will be used by homemenu operation(like APT::LeaveHomeMenu) which try to do SendParameter()
is_homemenu_input_buffer_set = true;
homemenu_input_buffer = Memory::Read32(input_buffer);
LOG_WARNING(Service_APT, "(STUBBED) SetLeaveHomeMenuBuffer, input_buffer=0x%08X", input_buffer);
break;
default:
LOG_ERROR(Service_APT, "(STUBBED) unknown utility_id=0x%08X", utility_id);
UNIMPLEMENTED();
}
return RESULT_SUCCESS;
}
void AppletUtility(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
// These are from 3dbrew - I'm not really sure what they're used for.
u32 command = cmd_buff[1];
u32 buffer1_size = cmd_buff[2];
u32 buffer2_size = cmd_buff[3];
u32 buffer1_addr = cmd_buff[5];
u32 buffer2_addr = cmd_buff[65];
u32 utility_id = cmd_buff[1];
u32 input_size = cmd_buff[2];
u32 output_size = (cmd_buff[3] > 0x1000) ? 0x1000 : cmd_buff[3];
u32 input_traslation = cmd_buff[4];
u32 input_buffer = cmd_buff[5];
u32 output_traslation = cmd_buff[0x40];
u32 output_buffer = cmd_buff[0x41];
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
bool applet_result = false; // Only use for utility_id = 6 (bool TryLockTransition)
LOG_WARNING(Service_APT, "(STUBBED) called command=0x%08X, buffer1_size=0x%08X, buffer2_size=0x%08X, "
"buffer1_addr=0x%08X, buffer2_addr=0x%08X", command, buffer1_size, buffer2_size,
buffer1_addr, buffer2_addr);
if (input_size > 0x1000) {
cmd_buff[0] = IPC::MakeHeader(0, 0x1, 0); // 0x40
cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS,
ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw;;// 0xD9001830
return;
}
cmd_buff[0] = IPC::MakeHeader(0x4B, 0x2, 0x2);// 0x004B0082
cmd_buff[1] = AppletUtility(utility_id, input_buffer, input_size, output_buffer, output_size, applet_result).raw;
cmd_buff[2] = static_cast<u32>(applet_result);
}
void SetAppCpuTimeLimit(Service::Interface* self) {
@ -410,6 +783,45 @@ void GetScreenCapPostPermission(Service::Interface* self) {
LOG_WARNING(Service_APT, "(STUBBED) screen_capture_post_permission=%u", screen_capture_post_permission);
}
void PrepareToCloseApplication(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 cancel_preload = cmd_buff[1] & 0xFF;
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
LOG_WARNING(Service_APT, "(STUBBED) cancel_preload=%u", cancel_preload);
}
void CloseApplication(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 parameter_size = cmd_buff[1];
u32 handle_parameter = cmd_buff[3];
u32 parameter_buffer = cmd_buff[5];
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
LOG_WARNING(Service_APT, "(STUBBED) parameter_size=0x%08X, handle_parameter=0x%08X, parameter_buffer=0x%08X",
parameter_size, handle_parameter, parameter_buffer);
}
void LeaveHomeMenu(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 parameter_size = cmd_buff[1];
u32 handle_parameter = cmd_buff[3];
u32 parameter_buffer_transition = cmd_buff[4];
u32 parameter_buffer = cmd_buff[5];
if (cmd_buff[2] != 0 || (parameter_buffer_transition & 0x3C0F) != 2) {
cmd_buff[0] = IPC::MakeHeader(0, 0x1, 0);// 0x40
cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS,
ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; //0xD9001830
return;
}
cmd_buff[0] = IPC::MakeHeader(0x2E, 0x1, 0); //0x2E0040
cmd_buff[1] = RESULT_SUCCESS.raw;
LOG_WARNING(Service_APT, "(STUBBED) parameter_size=0x%08X, handle_parameter=0x%08X, parameter_buffer=0x%08X",
parameter_size, handle_parameter, parameter_buffer);
}
void GetAppletInfo(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
auto app_id = static_cast<AppletId>(cmd_buff[1]);
@ -431,18 +843,20 @@ void GetAppletInfo(Service::Interface* self) {
void GetStartupArgument(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 parameter_size = cmd_buff[1];
u32 parameter_buffer = cmd_buff[0x41];
StartupArgumentType startup_argument_type = static_cast<StartupArgumentType>(cmd_buff[2]);
if (parameter_size >= 0x300) {
LOG_ERROR(Service_APT, "Parameter size is outside the valid range (capped to 0x300): parameter_size=0x%08x", parameter_size);
return;
if (parameter_size > 0x1000) {
parameter_size = 0x1000;
}
LOG_WARNING(Service_APT,"(stubbed) called startup_argument_type=%u , parameter_size=0x%08x , parameter_value=0x%08x",
startup_argument_type, parameter_size, Memory::Read32(cmd_buff[41]));
LOG_WARNING(Service_APT,"(STUBBED) called startup_argument_type=%u , parameter_size=0x%08x , parameter_buffer=0x%08x",
startup_argument_type, parameter_size, parameter_buffer);
cmd_buff[1] = RESULT_SUCCESS.raw;
cmd_buff[2] = (parameter_size > 0) ? 1 : 0;
cmd_buff[3] = (parameter_size << 14) | 2;
}
void CheckNew3DSApp(Service::Interface* self) {
@ -468,6 +882,31 @@ void CheckNew3DS(Service::Interface* self) {
LOG_WARNING(Service_APT, "(STUBBED) called");
}
void IsStandardMemoryLayout(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
const bool is_new_3ds = Settings::values.is_new_3ds;
u32 is_standard_memory_layout = 0;
using ConfigMem::config_mem;
if (is_new_3ds) {
if (config_mem.app_mem_type != 7) { // 7 for 178MB mode.
is_standard_memory_layout = 1;
}
} else {
if (config_mem.app_mem_type == 0) { // 0 for 64MB mode
is_standard_memory_layout = 1;
}
}
cmd_buff[0] = IPC::MakeHeader(0x104, 0x2, 0);
cmd_buff[1] = RESULT_SUCCESS.raw;
cmd_buff[2] = is_standard_memory_layout;
LOG_WARNING(Service_APT, "(STUBBED) is_standard_memory_layout=%u", is_standard_memory_layout);
}
void Init() {
AddService(new APT_A_Interface);
AddService(new APT_S_Interface);
@ -501,7 +940,7 @@ void Init() {
lock = Kernel::Mutex::Create(false, "APT_U:Lock");
cpu_percent = 0;
unknown_ns_state_field = 0;
homemenu_input_buffer = 0;
screen_capture_post_permission = ScreencapPostPermission::CleanThePermission; // TODO(JamePeng): verify the initial value
// TODO(bunnei): Check if these are created in Initialize or on APT process startup.
@ -513,6 +952,8 @@ void Init() {
}
void Shutdown() {
is_capture_buffer_info_set = false;
is_homemenu_input_buffer_set = false;
shared_font_mem = nullptr;
shared_font_relocated = false;
lock = nullptr;

View File

@ -4,6 +4,8 @@
#pragma once
#include <array>
#include "common/common_types.h"
#include "common/swap.h"
@ -44,6 +46,13 @@ struct CaptureBufferInfo {
};
static_assert(sizeof(CaptureBufferInfo) == 0x20, "CaptureBufferInfo struct has incorrect size");
struct WirelessRebootInfo {
std::array<u8, 6> mac_address{};
std::array<u8, 9> wireless_reboot_passphrase{};
INSERT_PADDING_BYTES(1);
};
static_assert(sizeof(WirelessRebootInfo) == 0x10, "WirelessRebootInfo struct has incorrect size");
/// Signals used by APT functions
enum class SignalType : u32 {
None = 0x0,
@ -70,12 +79,12 @@ enum class AppletId : u32 {
AmiiboSettings = 0x119,
SoftwareKeyboard1 = 0x201,
Ed1 = 0x202,
PnoteApp = 0x204,
SnoteApp = 0x205,
PnoteApp1 = 0x204,
SnoteApp1 = 0x205,
Error = 0x206,
Mint = 0x207,
Extrapad = 0x208,
Memolib = 0x209,
Mint1 = 0x207,
Extrapad1 = 0x208,
Memolib1 = 0x209,
Application = 0x300,
AnyLibraryApplet = 0x400,
SoftwareKeyboard2 = 0x401,
@ -88,6 +97,15 @@ enum class AppletId : u32 {
Memolib2 = 0x409,
};
enum class AppletPos {
None = -1,
App = 0,
AppLib = 1,
Sys = 2,
SysLib = 3,
Resident = 4
};
enum class StartupArgumentType : u32 {
OtherApp = 0,
Restart = 1,
@ -101,6 +119,49 @@ enum class ScreencapPostPermission : u32 {
DisableScreenshotPostingToMiiverse = 3
};
enum class QueryReply : u32 {
Reject = 0,
Accept = 1,
Later = 2
};
enum class AppletPreparationState : u32 {
NoPreparation = 0,
PreparedToLaunchApp = 1,
PreparedToCloseApp = 2,
PreparedToForceToCloseApp = 3,
PreparedToPreloadApplib = 4,
PreparedToLaunchApplib = 5,
PreparedToCloseApplib = 6,
PreparedToLaunchSys = 7,
PreparedToCloseSys = 8,
PreparedToPreloadSyslib = 9,
PreparedToLaunchSyslib = 10,
PreparedToCloseSyslib = 11,
PreparedToLaunchResident = 12,
PreparedToLeaveResident = 13,
PreparedToDoHomemenu = 14,
PreparedToLeaveHomemenu = 15,
PreparedToStartResident = 16,
PreparedToDoAppJump = 17,
PreparedToForceToCloseSys = 18,
PreparedToLaunchOtherSys = 19,
PreparedToJumpToApp = 20,
};
enum class UtilityID : u32 {
ClearPowerButtonState = 0,
ClearExclusiveControl = 3,
SleepIfShellClosed = 4,
LockTransition = 5,
TryLockTransition = 6,
UnlockTransition = 7,
StartExitTask = 10,
SetInitialSenderId = 11,
SetPowerButtonClick = 12,
SetHomeMenuBuffer = 17
};
/// Send a parameter to the currently-running application, which will read it via ReceiveParameter
void SendParameter(const MessageParameter& parameter);
@ -123,6 +184,149 @@ void Initialize(Service::Interface* self);
*/
void GetSharedFont(Service::Interface* self);
/**
* APT::GetWirelessRebootInfo service function
* Inputs:
* 1 : buffer_size
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
* Note:
* Same as NSS:SetWirelessRebootInfo except this loads the data instead.
* The state flag set by NSS:SetWirelessRebootInfo must have bit0 set,
* Otherwise the output buffer is just cleared without copying any data.
* This is used by DLP-child titles.
*/
void GetWirelessRebootInfo(Service::Interface* self);
/**
* APT::PrepareToLeaveResidentApplet service function
* Inputs:
* 1 : u8, Caller Exiting (0 = not exiting, 1 = exiting)
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void PrepareToLeaveResidentApplet(Service::Interface* self);
/**
* APT::LeaveResidentApplet service function
* Inputs:
* 1 : Parameters Size
* 2 : 0x0
* 3 : Handle Parameter
* 5 : void*, Parameters
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void LeaveResidentApplet(Service::Interface* self);
/**
* APT::PreloadResidentApplet service function
* Inputs:
* 1 : AppID
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void PreloadResidentApplet(Service::Interface* self);
/**
* APT::PrepareToStartResidentApplet service function
* Inputs:
* 1 : AppID
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void PrepareToStartResidentApplet(Service::Interface* self);
/**
* APT::StartResidentApplet service function
* Inputs:
* 1 : Parameters Size
* 2 : 0x0
* 3 : Handle Parameter
* 5 : void*, Parameters
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void StartResidentApplet(Service::Interface* self);
/**
* APT::CancelLibraryApplet service function
* Inputs:
* 0 : Header code [0x003B0040]
* 1 : u8, Application Exiting (0 = not exiting, 1 = exiting)
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void CancelLibraryApplet(Service::Interface* self);
/**
* APT::ReplySleepQuery service function
* Inputs:
* 1 : AppID
* 2: QueryReply
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
* Note: If the specific unimplemented function or applet was called by application,
* It would return a value QueryReply::Reject to cmd_buff[2]
* For example, "Could not create applet XXXX" will cause the command QueryReply::Reject to this function
*/
void ReplySleepQuery(Service::Interface* self);
/**
* APT::ReplySleepNotificationComplete service function
* Inputs:
* 1 : AppId
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void ReplySleepNotificationComplete(Service::Interface* self);
/**
* APT::SendCaptureBufferInfo service function
* Inputs:
* 1 : Size
* 2 : (Size << 14) | 2
* 3: void* CaptureBufferInfo
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
* Note:
* The input size is clamped to 0x20-bytes by NS.
* The input buffer with the clamped size is then copied to a NS state buffer.
* The size field for this state buffer is also set to this clamped size.
*/
void SendCaptureBufferInfo(Service::Interface* self);
/**
* APT::ReceiveCaptureBufferInfo service function
* Inputs:
* 1 : Size
* 0x40 : (Size << 14) | 2
* 0x41 : void*, CaptureBufferInfo
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
* 2 : Actual Size
* Note:
* This command loads the data set by APT:SendCaptureBufferInfo.
* The input size is clamped to 0x20-bytes by NS, then this size is clamped to the size for the NS state buffer.
* The NS state buffer data is copied to the output buffer, (when the clamped size is not zero) then the size field for the state buffer is set 0.
*/
void ReceiveCaptureBufferInfo(Service::Interface* self);
/**
* APT::GetCaptureInfo service function
* Inputs:
* 1 : Size
* 0x40 : (Size << 14) | 2
* 0x41 : void*, CaptureBufferInfo
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
* Notes:
* This command loads the data set by APT:SendCaptureBufferInfo, this command is similar to APT:ReceiveCaptureBufferInfo.
* The input size is clamped to 0x20-bytes by NS.
* The NS state buffer data is then copied to the output buffer.
*/
void GetCaptureInfo(Service::Interface* self);
/**
* APT::NotifyToWait service function
* Inputs:
@ -157,11 +361,11 @@ void Enable(Service::Interface* self);
/**
* APT::GetAppletManInfo service function.
* Inputs:
* 1 : Unknown
* 1 : AppletPos
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
* 2 : Unknown u32 value
* 3 : Unknown u8 value
* 2 : AppletPos
* 3 : Requested AppId
* 4 : Home Menu AppId
* 5 : AppID of currently active app
*/
@ -182,19 +386,37 @@ void GetAppletManInfo(Service::Interface* self);
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,
* while displaying the "Nintendo 3DS" loading screen.
* APT::CountRegisteredApplet service function.
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
* 2 : Registered Applet Count
*/
void CountRegisteredApplet(Service::Interface* self);
/**
* APT::IsRegistered service function
* Inputs:
* 1 : AppID
* Outputs:
* 0 : Return header
* 1 : Result of function, 0 on success, otherwise error code
* 2 : Output, 0 = not registered, 1 = registered.
* Note:
* 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,
* while displaying the "Nintendo 3DS" loading screen.
*/
void IsRegistered(Service::Interface* self);
/**
* APT::InquireNotification service function.
* Inputs:
* 1 : AppId
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
* 2 : Notification
*/
void InquireNotification(Service::Interface* self);
/**
@ -215,11 +437,7 @@ void InquireNotification(Service::Interface* self);
void SendParameter(Service::Interface* self);
/**
* APT::ReceiveParameter service function. This returns the current parameter data from NS state,
* from the source process which set the parameters. Once finished, NS will clear a flag in the NS
* state so that this command will return an error if this command is used again if parameters were
* not set again. This is called when the second Initialize event is triggered. It returns a signal
* type indicating why it was triggered.
* APT::ReceiveParameter service function
* Inputs:
* 1 : AppID
* 2 : Parameter buffer size, max size is 0x1000
@ -232,90 +450,123 @@ void SendParameter(Service::Interface* self);
* 6 : Handle from the source process which set the parameters, likely used for shared memory
* 7 : Size
* 8 : Output parameter buffer ptr
* Note:
* This returns the current parameter data from NS state,
* from the source process which set the parameters. Once finished, NS will clear a flag in the NS
* state so that this command will return an error if this command is used again if parameters were
* not set again. This is called when the second Initialize event is triggered. It returns a signal
* type indicating why it was triggered.
*/
void ReceiveParameter(Service::Interface* self);
/**
* APT::GlanceParameter service function. This is exactly the same as APT_U::ReceiveParameter
* (except for the word value prior to the output handle), except this will not clear the flag
* (except when responseword[3]==8 || responseword[3]==9) in NS state.
* APT::GlanceParameter service function
* Inputs:
* 1 : AppID
* 2 : Parameter buffer size, max size is 0x1000
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
* 2 : Unknown, for now assume AppID of the process which sent these parameters
* 3 : Unknown, for now assume Signal type
* 2 : Sender AppID, for now assume AppID of the process which sent these parameters
* 3 : Command, for now assume Signal type
* 4 : Actual parameter buffer size, this is <= to the the input size
* 5 : Value
* 6 : Handle from the source process which set the parameters, likely used for shared memory
* 7 : Size
* 8 : Output parameter buffer ptr
* Note:
* This is exactly the same as APT_U::ReceiveParameter
* (except for the word value prior to the output handle), except this will not clear the flag
* (except when responseword[3]==8 || responseword[3]==9) in NS state.
*/
void GlanceParameter(Service::Interface* self);
/**
* APT::CancelParameter service function. When the parameter data is available, and when the above
* specified fields match the ones in NS state(for the ones where the checks are enabled), this
* clears the flag which indicates that parameter data is available
* (same flag cleared by APT:ReceiveParameter).
* APT::CancelParameter service function.
* Inputs:
* 1 : Flag, when non-zero NS will compare the word after this one with a field in the NS state.
* 2 : Unknown, this is the same as the first unknown field returned by APT:ReceiveParameter.
* 3 : Flag, when non-zero NS will compare the word after this one with a field in the NS state.
* 4 : AppID
* 1 : u8, Check Sender (0 = don't check, 1 = check)
* 2 : Sender AppID
* 3 : u8, Check Receiver (0 = don't check, 1 = check)
* 4 : Receiver AppID
* Outputs:
* 0 : Return header
* 1 : Result of function, 0 on success, otherwise error code
* 2 : Status flag, 0 = failure due to no parameter data being available, or the above enabled
* fields don't match the fields in NS state. 1 = success.
* Note:
* When the parameter data is available, and when the above specified fields match the ones in NS state(for the ones where the checks are enabled),
* This clears the flag which indicates that parameter data is available(same flag cleared by APT:ReceiveParameter).
*/
void CancelParameter(Service::Interface* self);
/**
* APT::PrepareToStartApplication service function. When the input title-info programID is zero,
* APT::GetPreparationState service function
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
* 2: AppletPreparationState
*/
void GetPreparationState(Service::Interface* self);
/**
* APT::SetPreparationState service function
* Inputs:
* 1 : AppletPreparationState
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void SetPreparationState(Service::Interface* self);
/**
* APT::PrepareToStartApplication service function
* Inputs:
* 1-4 : ProgramInfo
* 5 : Flags (usually zero, when zero, NS writes a title-info struct with Program ID = ~0
* and MediaType = NAND to the FIRM parameters structure)
* Outputs:
* 0 : Return header
* 1 : Result of function, 0 on success, otherwise error code
* Note:
* When the input title-info programID is zero,
* NS will load the actual program ID via AMNet:GetTitleIDList. After doing some checks with the
* programID, NS will then set a NS state flag to value 1, then set the programID for AppID
* 0x300(application) to the input program ID(or the one from GetTitleIDList). A media-type field
* in the NS state is also set to the input media-type value
* (other state fields are set at this point as well). With 8.0.0-18, NS will set an u8 NS state
* field to value 1 when input flags bit8 is set
* Inputs:
* 1-4 : 0x10-byte title-info struct
* 4 : Flags
* Outputs:
* 0 : Return header
* 1 : Result of function, 0 on success, otherwise error code
*/
void PrepareToStartApplication(Service::Interface* self);
/**
* APT::StartApplication service function. Buf0 is copied to NS FIRMparams+0x0, then Buf1 is copied
* to the NS FIRMparams+0x480. Then the application is launched.
* APT::StartApplication service function.
* Inputs:
* 1 : Buffer 0 size, max size is 0x300
* 2 : Buffer 1 size, max size is 0x20 (this can be zero)
* 3 : u8 flag
* 4 : (Size0<<14) | 2
* 5 : Buffer 0 pointer
* 6 : (Size1<<14) | 0x802
* 7 : Buffer 1 pointer
* 1 : Parameter Size (capped to 0x300)
* 2 : HMAC Size (capped to 0x20)
* 3 : u8 Paused (0 = not paused, 1 = paused)
* 4 : (Parameter Size << 14) | 2
* 5 : void*, Parameter
* 6 : (HMAC Size << 14) | 0x802
* 7 : void*, HMAC
* Outputs:
* 0 : Return Header
* 1 : Result of function, 0 on success, otherwise error code
*/
* Note:
* The parameter buffer is copied to NS FIRMparams+0x0, then the HMAC buffer is copied to NS FIRMparams+0x480.
* Then the application is launched.
*/
void StartApplication(Service::Interface* self);
/**
* APT::AppletUtility service function
* Inputs:
* 1 : Unknown, but clearly used for something
* 2 : Buffer 1 size (purpose is unknown)
* 3 : Buffer 2 size (purpose is unknown)
* 5 : Buffer 1 address (purpose is unknown)
* 65 : Buffer 2 address (purpose is unknown)
* 1 : UtilityID
* 2 : Input Size
* 3 : Output Size
* 4 : (Input Size << 14) | 0x402
* 5 : void*, Input
* 0x41 : void*, Output
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
* 2 : Applet Result
* Note:
* This function may affect specific srv:Notifications operation by using Utility
*/
void AppletUtility(Service::Interface* self);
@ -378,14 +629,50 @@ void PreloadLibraryApplet(Service::Interface* self);
*/
void StartLibraryApplet(Service::Interface* self);
/**
* APT::PrepareToCloseApplication service function
* Inputs:
* 1 : u8, Cancel Preload (0 = don't cancel, 1 = cancel)
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void PrepareToCloseApplication(Service::Interface* self);
/**
* APT::CloseApplication service function
* Inputs:
* 1 : Parameters Size
* 2 : 0x0
* 3 : Handle Parameter
* 4 : (Parameters Size << 14) | 2
* 5 : void*, Parameters
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void CloseApplication(Service::Interface* self);
/**
* APT::LeaveHomeMenu service function
* Inputs:
* 0 : Header code [0x002E0044]
* 1 : Parameters Size
* 2 : 0x0
* 3 : Handle Parameter
* 4 : (Parameters Size << 14) | 2
* 5 : void*, Parameters
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void LeaveHomeMenu(Service::Interface* self);
/**
* APT::GetStartupArgument service function
* Inputs:
* 1 : Parameter Size (capped to 0x300)
* 2 : StartupArgumentType
* Outputs:
* 0 : Return header
* 1 : u8, Exists (0 = does not exist, 1 = exists)
* 1 : Result of function, 0 on success, otherwise error code
* 2 : u8, Exists (0 = does not exist, 1 = exists)
*/
void GetStartupArgument(Service::Interface* self);
@ -432,6 +719,17 @@ void CheckNew3DSApp(Service::Interface* self);
*/
void CheckNew3DS(Service::Interface* self);
/**
* APT::IsStandardMemoryLayout service function
* Inputs:
* 0 : Header code [0x01040000]
* Outputs:
* 0 : Header code
* 1 : Result code
* 2 : u8, Standard Memory Layout (0 = non-standard, 1 = standard)
*/
void IsStandardMemoryLayout(Service::Interface* self);
/// Initialize the APT service
void Init();

View File

@ -15,20 +15,37 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00040040, nullptr, "Finalize?"},
{0x00050040, GetAppletManInfo, "GetAppletManInfo"},
{0x00060040, GetAppletInfo, "GetAppletInfo"},
{0x00080000, CountRegisteredApplet, "CountRegisteredApplet"},
{0x00090040, IsRegistered, "IsRegistered"},
{0x000B0040, InquireNotification, "InquireNotification"},
{0x000C0104, SendParameter, "SendParameter"},
{0x000D0080, ReceiveParameter, "ReceiveParameter"},
{0x000E0080, GlanceParameter, "GlanceParameter"},
{0x000F0100, CancelParameter, "CancelParameter"},
{0x00130000, GetPreparationState, "GetPreparationState"},
{0x00140040, SetPreparationState, "SetPreparationState"},
{0x00150140, PrepareToStartApplication, "PrepareToStartApplication"},
{0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"},
{0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"},
{0x001B00C4, StartApplication, "StartApplication"},
{0x001E0084, StartLibraryApplet, "StartLibraryApplet"},
{0x003B0040, nullptr, "CancelLibraryApplet?"},
{0x003E0080, nullptr, "ReplySleepQuery"},
{0x00220040, PrepareToCloseApplication, "PrepareToCloseApplication"},
{0x00270044, CloseApplication, "CloseApplication"},
{0x002E0044, LeaveHomeMenu, "LeaveHomeMenu"},
{0x002F0040, PrepareToLeaveResidentApplet, "PrepareToLeaveResidentApplet"},
{0x00300044, LeaveResidentApplet, "LeaveResidentApplet"},
{0x00380040, PreloadResidentApplet, "PreloadResidentApplet"},
{0x00390040, PrepareToStartResidentApplet, "PrepareToStartResidentApplet"},
{0x003A0044, StartResidentApplet, "StartResidentApplet"},
{0x003B0040, CancelLibraryApplet, "CancelLibraryApplet?"},
{0x003E0080, ReplySleepQuery, "ReplySleepQuery"},
{0x003F0040, ReplySleepNotificationComplete,"ReplySleepNotificationComplete"},
{0x00400042, SendCaptureBufferInfo, "SendCaptureBufferInfo"},
{0x00410040, ReceiveCaptureBufferInfo, "ReceiveCaptureBufferInfo"},
{0x00430040, NotifyToWait, "NotifyToWait?"},
{0x00440000, GetSharedFont, "GetSharedFont?"},
{0x00450040, GetWirelessRebootInfo, "GetWirelessRebootInfo"},
{0x004A0040, GetCaptureInfo, "GetCaptureInfo"},
{0x004B00C2, AppletUtility, "AppletUtility?"},
{0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"},
{0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"},
@ -36,7 +53,9 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"},
{0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"},
{0x01010000, CheckNew3DSApp, "CheckNew3DSApp"},
{0x01020000, CheckNew3DS, "CheckNew3DS"}
{0x01020000, CheckNew3DS, "CheckNew3DS"},
{0x01040000, IsStandardMemoryLayout, "IsStandardMemoryLayout" },
{0x01050100, nullptr, "IsTitleAllowed" }
};
APT_A_Interface::APT_A_Interface() {

View File

@ -16,7 +16,7 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00050040, GetAppletManInfo, "GetAppletManInfo"},
{0x00060040, GetAppletInfo, "GetAppletInfo"},
{0x00070000, nullptr, "GetLastSignaledAppletId"},
{0x00080000, nullptr, "CountRegisteredApplet"},
{0x00080000, CountRegisteredApplet, "CountRegisteredApplet"},
{0x00090040, IsRegistered, "IsRegistered"},
{0x000A0040, nullptr, "GetAttribute"},
{0x000B0040, InquireNotification, "InquireNotification"},
@ -27,36 +27,36 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x001000C2, nullptr, "DebugFunc"},
{0x001100C0, nullptr, "MapProgramIdForDebug"},
{0x00120040, nullptr, "SetHomeMenuAppletIdForDebug"},
{0x00130000, nullptr, "GetPreparationState"},
{0x00140040, nullptr, "SetPreparationState"},
{0x00130000, GetPreparationState, "GetPreparationState"},
{0x00140040, SetPreparationState, "SetPreparationState"},
{0x00150140, PrepareToStartApplication, "PrepareToStartApplication"},
{0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"},
{0x00170040, nullptr, "FinishPreloadingLibraryApplet"},
{0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"},
{0x00190040, nullptr, "PrepareToStartSystemApplet"},
{0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"},
{0x001B00C4, nullptr, "StartApplication"},
{0x001B00C4, StartApplication, "StartApplication"},
{0x001C0000, nullptr, "WakeupApplication"},
{0x001D0000, nullptr, "CancelApplication"},
{0x001E0084, StartLibraryApplet, "StartLibraryApplet"},
{0x001F0084, nullptr, "StartSystemApplet"},
{0x00200044, nullptr, "StartNewestHomeMenu"},
{0x00210000, nullptr, "OrderToCloseApplication"},
{0x00220040, nullptr, "PrepareToCloseApplication"},
{0x00220040, PrepareToCloseApplication, "PrepareToCloseApplication"},
{0x00230040, nullptr, "PrepareToJumpToApplication"},
{0x00240044, nullptr, "JumpToApplication"},
{0x002500C0, nullptr, "PrepareToCloseLibraryApplet"},
{0x00260000, nullptr, "PrepareToCloseSystemApplet"},
{0x00270044, nullptr, "CloseApplication"},
{0x00270044, CloseApplication, "CloseApplication"},
{0x00280044, nullptr, "CloseLibraryApplet"},
{0x00290044, nullptr, "CloseSystemApplet"},
{0x002A0000, nullptr, "OrderToCloseSystemApplet"},
{0x002B0000, nullptr, "PrepareToJumpToHomeMenu"},
{0x002C0044, nullptr, "JumpToHomeMenu"},
{0x002D0000, nullptr, "PrepareToLeaveHomeMenu"},
{0x002E0044, nullptr, "LeaveHomeMenu"},
{0x002F0040, nullptr, "PrepareToLeaveResidentApplet"},
{0x00300044, nullptr, "LeaveResidentApplet"},
{0x002E0044, LeaveHomeMenu, "LeaveHomeMenu"},
{0x002F0040, PrepareToLeaveResidentApplet, "PrepareToLeaveResidentApplet"},
{0x00300044, LeaveResidentApplet, "LeaveResidentApplet"},
{0x00310100, nullptr, "PrepareToDoApplicationJump"},
{0x00320084, nullptr, "DoApplicationJump"},
{0x00330000, nullptr, "GetProgramIdOnApplicationJump"},
@ -64,25 +64,25 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00350080, nullptr, "ReceiveDeliverArg"},
{0x00360040, nullptr, "LoadSysMenuArg"},
{0x00370042, nullptr, "StoreSysMenuArg"},
{0x00380040, nullptr, "PreloadResidentApplet"},
{0x00390040, nullptr, "PrepareToStartResidentApplet"},
{0x003A0044, nullptr, "StartResidentApplet"},
{0x003B0040, nullptr, "CancelLibraryApplet"},
{0x00380040, PreloadResidentApplet, "PreloadResidentApplet"},
{0x00390040, PrepareToStartResidentApplet, "PrepareToStartResidentApplet"},
{0x003A0044, StartResidentApplet, "StartResidentApplet"},
{0x003B0040, CancelLibraryApplet, "CancelLibraryApplet"},
{0x003C0042, nullptr, "SendDspSleep"},
{0x003D0042, nullptr, "SendDspWakeUp"},
{0x003E0080, nullptr, "ReplySleepQuery"},
{0x003F0040, nullptr, "ReplySleepNotificationComplete"},
{0x00400042, nullptr, "SendCaptureBufferInfo"},
{0x00410040, nullptr, "ReceiveCaptureBufferInfo"},
{0x003E0080, ReplySleepQuery, "ReplySleepQuery"},
{0x003F0040, ReplySleepNotificationComplete, "ReplySleepNotificationComplete"},
{0x00400042, SendCaptureBufferInfo, "SendCaptureBufferInfo"},
{0x00410040, ReceiveCaptureBufferInfo, "ReceiveCaptureBufferInfo"},
{0x00420080, nullptr, "SleepSystem"},
{0x00430040, NotifyToWait, "NotifyToWait"},
{0x00440000, GetSharedFont, "GetSharedFont"},
{0x00450040, nullptr, "GetWirelessRebootInfo"},
{0x00450040, GetWirelessRebootInfo, "GetWirelessRebootInfo"},
{0x00460104, nullptr, "Wrap"},
{0x00470104, nullptr, "Unwrap"},
{0x00480100, nullptr, "GetProgramInfo"},
{0x00490180, nullptr, "Reboot"},
{0x004A0040, nullptr, "GetCaptureInfo"},
{0x004A0040, GetCaptureInfo, "GetCaptureInfo"},
{0x004B00C2, AppletUtility, "AppletUtility"},
{0x004C0000, nullptr, "SetFatalErrDispMode"},
{0x004D0080, nullptr, "GetAppletProgramInfo"},
@ -96,7 +96,9 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"},
{0x00580002, nullptr, "GetProgramID"},
{0x01010000, CheckNew3DSApp, "CheckNew3DSApp"},
{0x01020000, CheckNew3DS, "CheckNew3DS"}
{0x01020000, CheckNew3DS, "CheckNew3DS"},
{0x01040000, IsStandardMemoryLayout, "IsStandardMemoryLayout"},
{0x01050100, nullptr, "IsTitleAllowed"}
};
APT_U_Interface::APT_U_Interface() {

View File

@ -611,6 +611,7 @@ static void TriggerCmdReqQueue(Service::Interface* self) {
* Inputs:
* 0: Header 0x00180000
* Outputs:
* 0: Header Code[0x00180240]
* 1: Result code
* 2: Left framebuffer virtual address for the main screen
* 3: Right framebuffer virtual address for the main screen
@ -633,18 +634,19 @@ static void ImportDisplayCaptureInfo(Service::Interface* self) {
FrameBufferUpdate* top_screen = GetFrameBufferInfo(thread_id, 0);
FrameBufferUpdate* bottom_screen = GetFrameBufferInfo(thread_id, 1);
cmd_buff[0] = IPC::MakeHeader(0x18, 0x9, 0);
cmd_buff[1] = RESULT_SUCCESS.raw;
//Top Screen
cmd_buff[2] = top_screen->framebuffer_info[top_screen->index].address_left;
cmd_buff[3] = top_screen->framebuffer_info[top_screen->index].address_right;
cmd_buff[4] = top_screen->framebuffer_info[top_screen->index].format;
cmd_buff[5] = top_screen->framebuffer_info[top_screen->index].stride;
//Bottom Screen
cmd_buff[6] = bottom_screen->framebuffer_info[bottom_screen->index].address_left;
cmd_buff[7] = bottom_screen->framebuffer_info[bottom_screen->index].address_right;
cmd_buff[8] = bottom_screen->framebuffer_info[bottom_screen->index].format;
cmd_buff[9] = bottom_screen->framebuffer_info[bottom_screen->index].stride;
cmd_buff[1] = RESULT_SUCCESS.raw;
LOG_WARNING(Service_GSP, "called");
}