diff options
| author | 2014-11-26 15:00:51 -0500 | |
|---|---|---|
| committer | 2014-12-12 22:06:10 -0500 | |
| commit | 6fe61d3debff9da8df7c2422edf426045b87d23b (patch) | |
| tree | 0fe2c4c4d989874bc7a49cd832bee85d36b86480 | |
| parent | Common: Add "sysdata" to GetUserPath and cleanup. (diff) | |
| download | yuzu-6fe61d3debff9da8df7c2422edf426045b87d23b.tar.gz yuzu-6fe61d3debff9da8df7c2422edf426045b87d23b.tar.xz yuzu-6fe61d3debff9da8df7c2422edf426045b87d23b.zip | |
APT_U: Added GetSharedFont service function.
| -rw-r--r-- | src/common/common_paths.h | 3 | ||||
| -rw-r--r-- | src/core/hle/service/apt_u.cpp | 134 |
2 files changed, 103 insertions, 34 deletions
diff --git a/src/common/common_paths.h b/src/common/common_paths.h index 95479a529..42e1a29c1 100644 --- a/src/common/common_paths.h +++ b/src/common/common_paths.h | |||
| @@ -58,6 +58,9 @@ | |||
| 58 | #define DEBUGGER_CONFIG "debugger.ini" | 58 | #define DEBUGGER_CONFIG "debugger.ini" |
| 59 | #define LOGGER_CONFIG "logger.ini" | 59 | #define LOGGER_CONFIG "logger.ini" |
| 60 | 60 | ||
| 61 | // Sys files | ||
| 62 | #define SHARED_FONT "shared_font.bin" | ||
| 63 | |||
| 61 | // Files in the directory returned by GetUserPath(D_LOGS_IDX) | 64 | // Files in the directory returned by GetUserPath(D_LOGS_IDX) |
| 62 | #define MAIN_LOG "emu.log" | 65 | #define MAIN_LOG "emu.log" |
| 63 | 66 | ||
diff --git a/src/core/hle/service/apt_u.cpp b/src/core/hle/service/apt_u.cpp index 4bb05ce40..181763724 100644 --- a/src/core/hle/service/apt_u.cpp +++ b/src/core/hle/service/apt_u.cpp | |||
| @@ -4,10 +4,12 @@ | |||
| 4 | 4 | ||
| 5 | 5 | ||
| 6 | #include "common/common.h" | 6 | #include "common/common.h" |
| 7 | #include "common/file_util.h" | ||
| 7 | 8 | ||
| 8 | #include "core/hle/hle.h" | 9 | #include "core/hle/hle.h" |
| 9 | #include "core/hle/kernel/event.h" | 10 | #include "core/hle/kernel/event.h" |
| 10 | #include "core/hle/kernel/mutex.h" | 11 | #include "core/hle/kernel/mutex.h" |
| 12 | #include "core/hle/kernel/shared_memory.h" | ||
| 11 | #include "apt_u.h" | 13 | #include "apt_u.h" |
| 12 | 14 | ||
| 13 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 15 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -15,7 +17,19 @@ | |||
| 15 | 17 | ||
| 16 | namespace APT_U { | 18 | namespace APT_U { |
| 17 | 19 | ||
| 20 | // Address used for shared font (as observed on HW) | ||
| 21 | // TODO(bunnei): This is the hard-coded address where we currently dump the shared font from via | ||
| 22 | // https://github.com/citra-emu/3dsutils. This is technically a hack, and will not work at any | ||
| 23 | // address other than 0x18000000 due to internal pointers in the shared font dump that would need to | ||
| 24 | // be relocated. This might be fixed by dumping the shared font @ address 0x00000000 and then | ||
| 25 | // correctly mapping it in Citra, however we still do not understand how the mapping is determined. | ||
| 26 | static const VAddr SHARED_FONT_VADDR = 0x18000000; | ||
| 27 | |||
| 28 | // Handle to shared memory region designated to for shared system font | ||
| 29 | static Handle shared_font_mem = 0; | ||
| 30 | |||
| 18 | static Handle lock_handle = 0; | 31 | static Handle lock_handle = 0; |
| 32 | static std::vector<u8> shared_font; | ||
| 19 | 33 | ||
| 20 | /// Signals used by APT functions | 34 | /// Signals used by APT functions |
| 21 | enum class SignalType : u32 { | 35 | enum class SignalType : u32 { |
| @@ -84,18 +98,18 @@ void InquireNotification(Service::Interface* self) { | |||
| 84 | * state so that this command will return an error if this command is used again if parameters were | 98 | * state so that this command will return an error if this command is used again if parameters were |
| 85 | * not set again. This is called when the second Initialize event is triggered. It returns a signal | 99 | * not set again. This is called when the second Initialize event is triggered. It returns a signal |
| 86 | * type indicating why it was triggered. | 100 | * type indicating why it was triggered. |
| 87 | * Inputs: | 101 | * Inputs: |
| 88 | * 1 : AppID | 102 | * 1 : AppID |
| 89 | * 2 : Parameter buffer size, max size is 0x1000 | 103 | * 2 : Parameter buffer size, max size is 0x1000 |
| 90 | * Outputs: | 104 | * Outputs: |
| 91 | * 1 : Result of function, 0 on success, otherwise error code | 105 | * 1 : Result of function, 0 on success, otherwise error code |
| 92 | * 2 : Unknown, for now assume AppID of the process which sent these parameters | 106 | * 2 : Unknown, for now assume AppID of the process which sent these parameters |
| 93 | * 3 : Unknown, for now assume Signal type | 107 | * 3 : Unknown, for now assume Signal type |
| 94 | * 4 : Actual parameter buffer size, this is <= to the the input size | 108 | * 4 : Actual parameter buffer size, this is <= to the the input size |
| 95 | * 5 : Value | 109 | * 5 : Value |
| 96 | * 6 : Handle from the source process which set the parameters, likely used for shared memory | 110 | * 6 : Handle from the source process which set the parameters, likely used for shared memory |
| 97 | * 7 : Size | 111 | * 7 : Size |
| 98 | * 8 : Output parameter buffer ptr | 112 | * 8 : Output parameter buffer ptr |
| 99 | */ | 113 | */ |
| 100 | void ReceiveParameter(Service::Interface* self) { | 114 | void ReceiveParameter(Service::Interface* self) { |
| 101 | u32* cmd_buff = Service::GetCommandBuffer(); | 115 | u32* cmd_buff = Service::GetCommandBuffer(); |
| @@ -115,18 +129,18 @@ void ReceiveParameter(Service::Interface* self) { | |||
| 115 | * APT_U::GlanceParameter service function. This is exactly the same as APT_U::ReceiveParameter | 129 | * APT_U::GlanceParameter service function. This is exactly the same as APT_U::ReceiveParameter |
| 116 | * (except for the word value prior to the output handle), except this will not clear the flag | 130 | * (except for the word value prior to the output handle), except this will not clear the flag |
| 117 | * (except when responseword[3]==8 || responseword[3]==9) in NS state. | 131 | * (except when responseword[3]==8 || responseword[3]==9) in NS state. |
| 118 | * Inputs: | 132 | * Inputs: |
| 119 | * 1 : AppID | 133 | * 1 : AppID |
| 120 | * 2 : Parameter buffer size, max size is 0x1000 | 134 | * 2 : Parameter buffer size, max size is 0x1000 |
| 121 | * Outputs: | 135 | * Outputs: |
| 122 | * 1 : Result of function, 0 on success, otherwise error code | 136 | * 1 : Result of function, 0 on success, otherwise error code |
| 123 | * 2 : Unknown, for now assume AppID of the process which sent these parameters | 137 | * 2 : Unknown, for now assume AppID of the process which sent these parameters |
| 124 | * 3 : Unknown, for now assume Signal type | 138 | * 3 : Unknown, for now assume Signal type |
| 125 | * 4 : Actual parameter buffer size, this is <= to the the input size | 139 | * 4 : Actual parameter buffer size, this is <= to the the input size |
| 126 | * 5 : Value | 140 | * 5 : Value |
| 127 | * 6 : Handle from the source process which set the parameters, likely used for shared memory | 141 | * 6 : Handle from the source process which set the parameters, likely used for shared memory |
| 128 | * 7 : Size | 142 | * 7 : Size |
| 129 | * 8 : Output parameter buffer ptr | 143 | * 8 : Output parameter buffer ptr |
| 130 | */ | 144 | */ |
| 131 | void GlanceParameter(Service::Interface* self) { | 145 | void GlanceParameter(Service::Interface* self) { |
| 132 | u32* cmd_buff = Service::GetCommandBuffer(); | 146 | u32* cmd_buff = Service::GetCommandBuffer(); |
| @@ -146,14 +160,14 @@ void GlanceParameter(Service::Interface* self) { | |||
| 146 | 160 | ||
| 147 | /** | 161 | /** |
| 148 | * APT_U::AppletUtility service function | 162 | * APT_U::AppletUtility service function |
| 149 | * Inputs: | 163 | * Inputs: |
| 150 | * 1 : Unknown, but clearly used for something | 164 | * 1 : Unknown, but clearly used for something |
| 151 | * 2 : Buffer 1 size (purpose is unknown) | 165 | * 2 : Buffer 1 size (purpose is unknown) |
| 152 | * 3 : Buffer 2 size (purpose is unknown) | 166 | * 3 : Buffer 2 size (purpose is unknown) |
| 153 | * 5 : Buffer 1 address (purpose is unknown) | 167 | * 5 : Buffer 1 address (purpose is unknown) |
| 154 | * 65 : Buffer 2 address (purpose is unknown) | 168 | * 65 : Buffer 2 address (purpose is unknown) |
| 155 | * Outputs: | 169 | * Outputs: |
| 156 | * 1 : Result of function, 0 on success, otherwise error code | 170 | * 1 : Result of function, 0 on success, otherwise error code |
| 157 | */ | 171 | */ |
| 158 | void AppletUtility(Service::Interface* self) { | 172 | void AppletUtility(Service::Interface* self) { |
| 159 | u32* cmd_buff = Service::GetCommandBuffer(); | 173 | u32* cmd_buff = Service::GetCommandBuffer(); |
| @@ -172,6 +186,34 @@ void AppletUtility(Service::Interface* self) { | |||
| 172 | buffer1_addr, buffer2_addr); | 186 | buffer1_addr, buffer2_addr); |
| 173 | } | 187 | } |
| 174 | 188 | ||
| 189 | /** | ||
| 190 | * APT_U::GetSharedFont service function | ||
| 191 | * Outputs: | ||
| 192 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 193 | * 2 : Virtual address of where shared font will be loaded in memory | ||
| 194 | * 4 : Handle to shared font memory | ||
| 195 | */ | ||
| 196 | void GetSharedFont(Service::Interface* self) { | ||
| 197 | DEBUG_LOG(KERNEL, "called"); | ||
| 198 | |||
| 199 | u32* cmd_buff = Service::GetCommandBuffer(); | ||
| 200 | |||
| 201 | if (!shared_font.empty()) { | ||
| 202 | // TODO(bunnei): This function shouldn't copy the shared font every time it's called. | ||
| 203 | // Instead, it should probably map the shared font as RO memory. We don't currently have | ||
| 204 | // an easy way to do this, but the copy should be sufficient for now. | ||
| 205 | memcpy(Memory::GetPointer(SHARED_FONT_VADDR), shared_font.data(), shared_font.size()); | ||
| 206 | |||
| 207 | cmd_buff[0] = 0x00440082; | ||
| 208 | cmd_buff[1] = 0; // No error | ||
| 209 | cmd_buff[2] = SHARED_FONT_VADDR; | ||
| 210 | cmd_buff[4] = shared_font_mem; | ||
| 211 | } else { | ||
| 212 | cmd_buff[1] = -1; // Generic error (not really possible to verify this on hardware) | ||
| 213 | ERROR_LOG(KERNEL, "called, but %s has not been loaded!", SHARED_FONT); | ||
| 214 | } | ||
| 215 | } | ||
| 216 | |||
| 175 | const Interface::FunctionInfo FunctionTable[] = { | 217 | const Interface::FunctionInfo FunctionTable[] = { |
| 176 | {0x00010040, GetLockHandle, "GetLockHandle"}, | 218 | {0x00010040, GetLockHandle, "GetLockHandle"}, |
| 177 | {0x00020080, Initialize, "Initialize"}, | 219 | {0x00020080, Initialize, "Initialize"}, |
| @@ -240,7 +282,7 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 240 | {0x00410040, nullptr, "ReceiveCaptureBufferInfo"}, | 282 | {0x00410040, nullptr, "ReceiveCaptureBufferInfo"}, |
| 241 | {0x00420080, nullptr, "SleepSystem"}, | 283 | {0x00420080, nullptr, "SleepSystem"}, |
| 242 | {0x00430040, nullptr, "NotifyToWait"}, | 284 | {0x00430040, nullptr, "NotifyToWait"}, |
| 243 | {0x00440000, nullptr, "GetSharedFont"}, | 285 | {0x00440000, GetSharedFont, "GetSharedFont"}, |
| 244 | {0x00450040, nullptr, "GetWirelessRebootInfo"}, | 286 | {0x00450040, nullptr, "GetWirelessRebootInfo"}, |
| 245 | {0x00460104, nullptr, "Wrap"}, | 287 | {0x00460104, nullptr, "Wrap"}, |
| 246 | {0x00470104, nullptr, "Unwrap"}, | 288 | {0x00470104, nullptr, "Unwrap"}, |
| @@ -259,9 +301,33 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 259 | // Interface class | 301 | // Interface class |
| 260 | 302 | ||
| 261 | Interface::Interface() { | 303 | Interface::Interface() { |
| 262 | Register(FunctionTable, ARRAY_SIZE(FunctionTable)); | 304 | // Load the shared system font (if available). |
| 305 | // The expected format is a decrypted, uncompressed BCFNT file with the 0x80 byte header | ||
| 306 | // generated by the APT:U service. The best way to get is by dumping it from RAM. We've provided | ||
| 307 | // a homebrew app to do this: https://github.com/citra-emu/3dsutils. Put the resulting file | ||
| 308 | // "shared_font.bin" in the Citra "sysdata" directory. | ||
| 309 | |||
| 310 | shared_font.clear(); | ||
| 311 | std::string filepath = FileUtil::GetUserPath(D_SYSDATA_IDX) + SHARED_FONT; | ||
| 312 | |||
| 313 | FileUtil::CreateFullPath(filepath); // Create path if not already created | ||
| 314 | FileUtil::IOFile file(filepath, "rb"); | ||
| 315 | |||
| 316 | if (file.IsOpen()) { | ||
| 317 | // Read shared font data | ||
| 318 | shared_font.resize(file.GetSize()); | ||
| 319 | file.ReadBytes(shared_font.data(), file.GetSize()); | ||
| 320 | |||
| 321 | // Create shared font memory object | ||
| 322 | shared_font_mem = Kernel::CreateSharedMemory("APT_U:shared_font_mem"); | ||
| 323 | } else { | ||
| 324 | WARN_LOG(KERNEL, "Unable to load shared font: %s", filepath.c_str()); | ||
| 325 | shared_font_mem = 0; | ||
| 326 | } | ||
| 263 | 327 | ||
| 264 | lock_handle = 0; | 328 | lock_handle = 0; |
| 329 | |||
| 330 | Register(FunctionTable, ARRAY_SIZE(FunctionTable)); | ||
| 265 | } | 331 | } |
| 266 | 332 | ||
| 267 | Interface::~Interface() { | 333 | Interface::~Interface() { |