From 619e13bcc6eb648de0e9fc1dc593795e025b8fbb Mon Sep 17 00:00:00 2001 From: PabloMK7 Date: Sat, 24 Apr 2021 13:03:03 +0200 Subject: [PATCH] Update to v2.1 --- .gitignore | 3 +- 3ds.ld => 3gx.ld | 24 +- Includes/3ds.h | 35 - Includes/CTRPluginFramework.hpp | 14 - Includes/CTRPluginFramework/Graphics.hpp | 7 - .../CTRPluginFramework/Graphics/Color.hpp | 102 -- Includes/CTRPluginFramework/Graphics/OSD.hpp | 131 -- Includes/CTRPluginFramework/Menu.hpp | 11 - Includes/CTRPluginFramework/Menu/Keyboard.hpp | 258 ---- .../CTRPluginFramework/Menu/MenuEntry.hpp | 150 --- .../Menu/MenuEntryHotkeys.hpp | 133 -- .../CTRPluginFramework/Menu/MenuFolder.hpp | 172 --- .../CTRPluginFramework/Menu/MessageBox.hpp | 45 - .../CTRPluginFramework/Menu/PluginMenu.hpp | 163 --- Includes/CTRPluginFramework/System.hpp | 19 - Includes/CTRPluginFramework/System/Clock.hpp | 22 - .../CTRPluginFramework/System/Controller.hpp | 73 -- .../CTRPluginFramework/System/Directory.hpp | 146 --- Includes/CTRPluginFramework/System/File.hpp | 219 ---- .../CTRPluginFramework/System/FwkSettings.hpp | 82 -- Includes/CTRPluginFramework/System/Hook.hpp | 62 - Includes/CTRPluginFramework/System/Lock.hpp | 29 - Includes/CTRPluginFramework/System/Mutex.hpp | 24 - .../CTRPluginFramework/System/Process.hpp | 284 ----- Includes/CTRPluginFramework/System/Rect.hpp | 147 --- Includes/CTRPluginFramework/System/Sleep.hpp | 12 - Includes/CTRPluginFramework/System/System.hpp | 63 - Includes/CTRPluginFramework/System/Task.hpp | 73 -- Includes/CTRPluginFramework/System/Time.hpp | 118 -- Includes/CTRPluginFramework/System/Touch.hpp | 16 - Includes/CTRPluginFramework/System/Vector.hpp | 127 -- Includes/CTRPluginFramework/Utils.hpp | 9 - .../CTRPluginFramework/Utils/LineReader.hpp | 27 - .../CTRPluginFramework/Utils/LineWriter.hpp | 34 - .../Utils/StringExtensions.hpp | 27 - Includes/CTRPluginFramework/Utils/Utils.hpp | 149 --- Includes/Helpers.hpp | 13 + Includes/Helpers/OSDManager.hpp | 2 +- Includes/csvc.h | 59 +- Includes/ctrulib/allocator/linear.h | 46 - Includes/ctrulib/allocator/mappable.h | 24 - Includes/ctrulib/allocator/newlibHeap.h | 18 - Includes/ctrulib/allocator/vram.h | 46 - Includes/ctrulib/arpa/inet.h | 39 - Includes/ctrulib/env.h | 85 -- Includes/ctrulib/errf.h | 122 -- Includes/ctrulib/font.h | 218 ---- Includes/ctrulib/gfx.h | 176 --- Includes/ctrulib/gpu/enums.h | 464 ------- Includes/ctrulib/gpu/gpu-old.h | 241 ---- Includes/ctrulib/gpu/gpu.h | 115 -- Includes/ctrulib/gpu/gx.h | 138 -- Includes/ctrulib/gpu/registers.h | 773 ------------ Includes/ctrulib/gpu/shaderProgram.h | 142 --- Includes/ctrulib/gpu/shbin.h | 121 -- Includes/ctrulib/ipc.h | 118 -- Includes/ctrulib/netinet/in.h | 45 - Includes/ctrulib/netinet/tcp.h | 9 - Includes/ctrulib/os.h | 190 --- Includes/ctrulib/poll.h | 29 - Includes/ctrulib/result.h | 95 -- Includes/ctrulib/sdmc.h | 34 - Includes/ctrulib/services/ac.h | 24 - Includes/ctrulib/services/am.h | 497 -------- Includes/ctrulib/services/apt.h | 505 -------- Includes/ctrulib/services/cfgu.h | 107 -- Includes/ctrulib/services/csnd.h | 433 ------- Includes/ctrulib/services/fs.h | 1086 ---------------- Includes/ctrulib/services/gspgpu.h | 226 ---- Includes/ctrulib/services/hid.h | 189 --- Includes/ctrulib/services/irrst.h | 62 - Includes/ctrulib/services/soc.h | 149 --- Includes/ctrulib/services/sslc.h | 251 ---- Includes/ctrulib/srv.h | 125 -- Includes/ctrulib/svc.h | 1115 ----------------- Includes/ctrulib/synchronization.h | 171 --- Includes/ctrulib/sys/ioctl.h | 13 - Includes/ctrulib/sys/select.h | 1 - Includes/ctrulib/sys/socket.h | 87 -- Includes/ctrulib/thread.h | 140 --- Includes/ctrulib/util/rbtree.h | 149 --- Includes/ctrulib/util/utf.h | 160 --- Includes/main.hpp | 2 +- Includes/ptm.h | 17 - Includes/types.h | 25 +- Lib/libCTRPluginFramework.a | Bin 1541368 -> 0 bytes Makefile | 47 +- OnionFS.plgInfo | 4 +- OnionFS.sln | 31 - OnionFS.vcxproj | 235 ---- OnionFS.vcxproj.filters | 401 ------ Sources/bootloader.s | 47 - Sources/hooked_func.cpp | 36 + Sources/main.cpp | 1 - Sources/ptm.c | 31 - Sources/rt.c | 3 +- Sources/save.cpp | 1 - 97 files changed, 134 insertions(+), 12609 deletions(-) rename 3ds.ld => 3gx.ld (95%) delete mode 100644 Includes/3ds.h delete mode 100644 Includes/CTRPluginFramework.hpp delete mode 100644 Includes/CTRPluginFramework/Graphics.hpp delete mode 100644 Includes/CTRPluginFramework/Graphics/Color.hpp delete mode 100644 Includes/CTRPluginFramework/Graphics/OSD.hpp delete mode 100644 Includes/CTRPluginFramework/Menu.hpp delete mode 100644 Includes/CTRPluginFramework/Menu/Keyboard.hpp delete mode 100644 Includes/CTRPluginFramework/Menu/MenuEntry.hpp delete mode 100644 Includes/CTRPluginFramework/Menu/MenuEntryHotkeys.hpp delete mode 100644 Includes/CTRPluginFramework/Menu/MenuFolder.hpp delete mode 100644 Includes/CTRPluginFramework/Menu/MessageBox.hpp delete mode 100644 Includes/CTRPluginFramework/Menu/PluginMenu.hpp delete mode 100644 Includes/CTRPluginFramework/System.hpp delete mode 100644 Includes/CTRPluginFramework/System/Clock.hpp delete mode 100644 Includes/CTRPluginFramework/System/Controller.hpp delete mode 100644 Includes/CTRPluginFramework/System/Directory.hpp delete mode 100644 Includes/CTRPluginFramework/System/File.hpp delete mode 100644 Includes/CTRPluginFramework/System/FwkSettings.hpp delete mode 100644 Includes/CTRPluginFramework/System/Hook.hpp delete mode 100644 Includes/CTRPluginFramework/System/Lock.hpp delete mode 100644 Includes/CTRPluginFramework/System/Mutex.hpp delete mode 100644 Includes/CTRPluginFramework/System/Process.hpp delete mode 100644 Includes/CTRPluginFramework/System/Rect.hpp delete mode 100644 Includes/CTRPluginFramework/System/Sleep.hpp delete mode 100644 Includes/CTRPluginFramework/System/System.hpp delete mode 100644 Includes/CTRPluginFramework/System/Task.hpp delete mode 100644 Includes/CTRPluginFramework/System/Time.hpp delete mode 100644 Includes/CTRPluginFramework/System/Touch.hpp delete mode 100644 Includes/CTRPluginFramework/System/Vector.hpp delete mode 100644 Includes/CTRPluginFramework/Utils.hpp delete mode 100644 Includes/CTRPluginFramework/Utils/LineReader.hpp delete mode 100644 Includes/CTRPluginFramework/Utils/LineWriter.hpp delete mode 100644 Includes/CTRPluginFramework/Utils/StringExtensions.hpp delete mode 100644 Includes/CTRPluginFramework/Utils/Utils.hpp create mode 100644 Includes/Helpers.hpp delete mode 100644 Includes/ctrulib/allocator/linear.h delete mode 100644 Includes/ctrulib/allocator/mappable.h delete mode 100644 Includes/ctrulib/allocator/newlibHeap.h delete mode 100644 Includes/ctrulib/allocator/vram.h delete mode 100644 Includes/ctrulib/arpa/inet.h delete mode 100644 Includes/ctrulib/env.h delete mode 100644 Includes/ctrulib/errf.h delete mode 100644 Includes/ctrulib/font.h delete mode 100644 Includes/ctrulib/gfx.h delete mode 100644 Includes/ctrulib/gpu/enums.h delete mode 100644 Includes/ctrulib/gpu/gpu-old.h delete mode 100644 Includes/ctrulib/gpu/gpu.h delete mode 100644 Includes/ctrulib/gpu/gx.h delete mode 100644 Includes/ctrulib/gpu/registers.h delete mode 100644 Includes/ctrulib/gpu/shaderProgram.h delete mode 100644 Includes/ctrulib/gpu/shbin.h delete mode 100644 Includes/ctrulib/ipc.h delete mode 100644 Includes/ctrulib/netinet/in.h delete mode 100644 Includes/ctrulib/netinet/tcp.h delete mode 100644 Includes/ctrulib/os.h delete mode 100644 Includes/ctrulib/poll.h delete mode 100644 Includes/ctrulib/result.h delete mode 100644 Includes/ctrulib/sdmc.h delete mode 100644 Includes/ctrulib/services/ac.h delete mode 100644 Includes/ctrulib/services/am.h delete mode 100644 Includes/ctrulib/services/apt.h delete mode 100644 Includes/ctrulib/services/cfgu.h delete mode 100644 Includes/ctrulib/services/csnd.h delete mode 100644 Includes/ctrulib/services/fs.h delete mode 100644 Includes/ctrulib/services/gspgpu.h delete mode 100644 Includes/ctrulib/services/hid.h delete mode 100644 Includes/ctrulib/services/irrst.h delete mode 100644 Includes/ctrulib/services/soc.h delete mode 100644 Includes/ctrulib/services/sslc.h delete mode 100644 Includes/ctrulib/srv.h delete mode 100644 Includes/ctrulib/svc.h delete mode 100644 Includes/ctrulib/synchronization.h delete mode 100644 Includes/ctrulib/sys/ioctl.h delete mode 100644 Includes/ctrulib/sys/select.h delete mode 100644 Includes/ctrulib/sys/socket.h delete mode 100644 Includes/ctrulib/thread.h delete mode 100644 Includes/ctrulib/util/rbtree.h delete mode 100644 Includes/ctrulib/util/utf.h delete mode 100644 Includes/ptm.h delete mode 100644 Lib/libCTRPluginFramework.a delete mode 100644 OnionFS.sln delete mode 100644 OnionFS.vcxproj delete mode 100644 OnionFS.vcxproj.filters delete mode 100644 Sources/bootloader.s delete mode 100644 Sources/ptm.c diff --git a/.gitignore b/.gitignore index 50f37ea..f9345c0 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ Gitlab/ [Dd]ebug/ .vs *.3gx -*.user \ No newline at end of file +*.user +.vscode/ \ No newline at end of file diff --git a/3ds.ld b/3gx.ld similarity index 95% rename from 3ds.ld rename to 3gx.ld index 55c34a8..9856691 100644 --- a/3ds.ld +++ b/3gx.ld @@ -13,12 +13,14 @@ PHDRS SECTIONS { /* =========== CODE section =========== */ - . = 0x07000100; - __start__ = . ; - .text ALIGN(0x4) : + + PROVIDE(__start__ = 0x07000100); + . = __start__; + + .text ALIGN(4) : { /* .init */ - bootloader.o (.text*) + KEEP( *(.crt0) ) KEEP( *(.init) ) . = ALIGN(4); @@ -48,7 +50,7 @@ SECTIONS *(.gnu.linkonce.r*) SORT(CONSTRUCTORS) . = ALIGN(4); - } + } : rodata .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } : rodata __exidx_start = .; @@ -124,24 +126,26 @@ SECTIONS KEEP (*(.dtors)) } : data - .bss ALIGN(4): - { *(.__bss_start) + __bss_start__ = .; + .bss ALIGN(4) : + { *(.dynbss) *(.bss) *(.bss.*) *(.gnu.linkonce.b*) *(COMMON) . = ALIGN(4); - *(.__bss_end) + /* Reserve space for the TLS segment of the main thread */ __tls_start = .; . += + SIZEOF(.tdata) + SIZEOF(.tbss); __tls_end = .; } : data - + __bss_end__ = .; + __end__ = ABSOLUTE(.) ; - /* ================== + /* ================== ==== Metadata ==== ================== */ diff --git a/Includes/3ds.h b/Includes/3ds.h deleted file mode 100644 index 112bea9..0000000 --- a/Includes/3ds.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef _3DS_H -#define _3DS_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "types.h" - -#include "ctrulib/services/am.h" -#include "ctrulib/services/apt.h" -#include "ctrulib/services/cfgu.h" -#include "ctrulib/services/fs.h" -#include "ctrulib/services/gspgpu.h" -#include "ctrulib/services/hid.h" -#include "ctrulib/services/irrst.h" -#include "ctrulib/services/csnd.h" -#include "ctrulib/util/utf.h" - -#include "ctrulib/env.h" -#include "ctrulib/font.h" -#include "ctrulib/gfx.h" -#include "ctrulib/ipc.h" -#include "ctrulib/os.h" -#include "ctrulib/result.h" -#include "ctrulib/srv.h" -#include "ctrulib/svc.h" -#include "ctrulib/synchronization.h" -#include "ctrulib/thread.h" - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/Includes/CTRPluginFramework.hpp b/Includes/CTRPluginFramework.hpp deleted file mode 100644 index 1032880..0000000 --- a/Includes/CTRPluginFramework.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_HPP -#define CTRPLUGINFRAMEWORK_HPP - -#include "types.h" -#include "3ds.h" - -using CallbackPointer = void (*)(void); - -#include "CTRPluginFramework/Graphics.hpp" -#include "CTRPluginFramework/Menu.hpp" -#include "CTRPluginFramework/System.hpp" -#include "CTRPluginFramework/Utils.hpp" - -#endif \ No newline at end of file diff --git a/Includes/CTRPluginFramework/Graphics.hpp b/Includes/CTRPluginFramework/Graphics.hpp deleted file mode 100644 index 0356714..0000000 --- a/Includes/CTRPluginFramework/Graphics.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_GRAPHICS_HPP -#define CTRPLUGINFRAMEWORK_GRAPHICS_HPP - -#include "CTRPluginFramework/Graphics/Color.hpp" -#include "CTRPluginFramework/Graphics/OSD.hpp" - -#endif \ No newline at end of file diff --git a/Includes/CTRPluginFramework/Graphics/Color.hpp b/Includes/CTRPluginFramework/Graphics/Color.hpp deleted file mode 100644 index 5e1b973..0000000 --- a/Includes/CTRPluginFramework/Graphics/Color.hpp +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_COLOR_HPP -#define CTRPLUGINFRAMEWORK_COLOR_HPP - -#include "types.h" -#include -#include - -namespace CTRPluginFramework -{ - class Color - { - public: - - enum class BlendMode - { - Alpha, - Add, - Sub, - Mul, - None - }; - - Color(void) : r(0), g(0), b(0), a(255) {} - Color(u32 color); - Color(u8 red, u8 green, u8 blue, u8 alpha = 255); - - u32 ToU32(void) const; - Color &Fade(double fading); - Color Blend(const Color &color, BlendMode mode) const; - - bool operator == (const Color &right) const; - bool operator != (const Color &right) const; - bool operator < (const Color &right) const; - bool operator <= (const Color &right) const; - bool operator > (const Color &right) const; - bool operator >= (const Color &right) const; - Color operator + (const Color &right) const; - Color operator - (const Color &right) const; - Color operator * (const Color &right) const; - Color &operator += (const Color &right); - Color &operator -= (const Color &right); - Color &operator *= (const Color &right); - - operator std::string() const - { - char strColor[5] = { 0 }; - - strColor[0] = 0x1B; - strColor[1] = std::max((u8)1, r); - strColor[2] = std::max((u8)1, g); - strColor[3] = std::max((u8)1, b); - - return strColor; - } - - union - { - u32 raw; - struct - { - u8 r; - u8 g; - u8 b; - u8 a; - }; - }; - - // All those colors are from https://www.rapidtables.com/web/color/RGB_Color.html - // Some basic colors constants - static const Color Black; - static const Color White; - static const Color Red; - static const Color Lime; - static const Color Blue; - static const Color Yellow; - static const Color Cyan; - static const Color Magenta; - static const Color Silver; - static const Color Gray; - static const Color Maroon; - static const Color Olive; - static const Color Green; - static const Color Purple; - static const Color Teal; - static const Color Navy; - - static const Color BlackGrey; - static const Color Brown; - static const Color DarkGrey; - static const Color DeepSkyBlue; - static const Color DimGrey; - static const Color DodgerBlue; - static const Color Gainsboro; - static const Color ForestGreen; - static const Color LimeGreen; - static const Color Orange; - static const Color SkyBlue; - static const Color Turquoise; - }; -} - -#endif \ No newline at end of file diff --git a/Includes/CTRPluginFramework/Graphics/OSD.hpp b/Includes/CTRPluginFramework/Graphics/OSD.hpp deleted file mode 100644 index 7ead1c1..0000000 --- a/Includes/CTRPluginFramework/Graphics/OSD.hpp +++ /dev/null @@ -1,131 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_OSD_HPP -#define CTRPLUGINFRAMEWORK_OSD_HPP - -#include "CTRPluginFramework/Graphics/Color.hpp" -#include "ctrulib/services/gspgpu.h" -#include - -namespace CTRPluginFramework -{ - using GSPFormat = GSPGPU_FramebufferFormats; - - class Screen - { - public: - bool IsTop; - bool Is3DEnabled; - u32 LeftFramebuffer; - u32 RightFramebuffer; - u32 Stride; - u32 BytesPerPixel; - GSPFormat Format; - - /** - * \brief Get a pointer to the screen's framebuffer - * \param posX The position on the screen to point to - * \param posY The position on the screen to point to - * \param useRightFb If the function must return a pointer to the right framebuffer - * \return A pointer to the screen's framebuffer at the desired position - */ - u8 * GetFramebuffer(u32 posX, u32 posY, bool useRightFb = false) const; - - /** - * \brief Draw a string using Linux's font - * \param str The string to draw - * \param posX The position on screen to draw the string to - * \param posY The position on screen to draw the string to - * \param foreground The color of the characters - * \param background The color of the background - * \return posY + 10 (line feed) - */ - u32 Draw(const std::string &str, u32 posX, u32 posY, const Color &foreground = Color::White, const Color &background = Color::Black) const; - - /** - * \brief Draw a string using system font (support utf8 strings with special chars & unicode) - * \param str The string to draw - * \param posX The position on screen to draw the string to - * \param posY The position on screen to draw the string to - * \param foreground The color of the characters - * \return posY + 16 (line feed) - */ - u32 DrawSysfont(const std::string &str, u32 posX, u32 posY, const Color &foreground = Color::White) const; - - /** - * \brief Draw a rectangle - * \param posX The position on screen to draw the rectangle - * \param posY The position on screen to draw the rectangle - * \param width The width of the rectangle - * \param height The height of the rectangle - * \param color The color of the rectangle - * \param filled If the rectangle is filled or if the function should only draw the border - */ - void DrawRect(u32 posX, u32 posY, u32 width, u32 height, const Color &color, bool filled = true) const; - /** - * \brief Change the color of a pixel at the desired X, Y position - * \param posX The X position of the pixel to change - * \param posY The Y position of the pixel to change - * \param color The new color of the pixel - */ - void DrawPixel(u32 posX, u32 posY, const Color &color) const; - - /** - * \brief Get the current color of a pixel at X, Y position - * \param posX The X position of the pixel to read - * \param posY The Y position of the pixel to read - * \param pixel The output color of the pixel - * \param fromRightFb If the pixel must be read from the right framebuffer - */ - void ReadPixel(u32 posX, u32 posY, Color &pixel, bool fromRightFb = false) const; - - private: - friend class OSDImpl; - Screen() {}; - }; - - using OSDCallback = bool(*)(const Screen &); - class OSD - { - public: - - /** - * \brief Send a notification on the top screen, a notification duration is 5 seconds\n - * A maximum of 50 notifications can be queued - * \param str Text of the notification - * \param foreground The color of the text (Default: blank) - * \param background The color of the background (Default: black) - * \return 0 if success, -1 if the notification couldn't be added - */ - static int Notify(const std::string &str, const Color &foreground = Color::White, const Color &background = Color::Black); - - /** - * \brief Add a callback to the OSD system which will be called at each game's frame - * \param cb The callback to add - */ - static void Run(OSDCallback cb); - - /** - * \brief Remove a callback from the OSD system - * \param cb The callback to remove - */ - static void Stop(OSDCallback cb); - - /** - * \brief Returns the width in pixels of the specified string - * \param sysfont Which font will be used to compute the width - * \param text - * \return The width in pixels - */ - static float GetTextWidth(bool sysfont, const std::string& text); - - /* Those are to be used only when the process is paused */ - static const Screen& GetTopScreen(void); - static const Screen& GetBottomScreen(void); - static void SwapBuffers(void); - - static void Lock(void); - static bool TryLock(void); //false success, true failure - static void Unlock(void); - }; -} - -#endif diff --git a/Includes/CTRPluginFramework/Menu.hpp b/Includes/CTRPluginFramework/Menu.hpp deleted file mode 100644 index 39bf5e6..0000000 --- a/Includes/CTRPluginFramework/Menu.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_MENU_HPP -#define CTRPLUGINFRAMEWORK_MENU_HPP - -#include "CTRPluginFramework/Menu/Keyboard.hpp" -#include "CTRPluginFramework/Menu/MenuEntry.hpp" -#include "CTRPluginFramework/Menu/MenuEntryHotkeys.hpp" -#include "CTRPluginFramework/Menu/MenuFolder.hpp" -#include "CTRPluginFramework/Menu/PluginMenu.hpp" -#include "CTRPluginFramework/Menu/MessageBox.hpp" - -#endif \ No newline at end of file diff --git a/Includes/CTRPluginFramework/Menu/Keyboard.hpp b/Includes/CTRPluginFramework/Menu/Keyboard.hpp deleted file mode 100644 index e11aea7..0000000 --- a/Includes/CTRPluginFramework/Menu/Keyboard.hpp +++ /dev/null @@ -1,258 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_KEYBOARD_HPP -#define CTRPLUGINFRAMEWORK_KEYBOARD_HPP - -#include "types.h" -#include -#include -#include - -namespace CTRPluginFramework -{ - class InputChangeEvent - { - public: - enum EventType - { - CharacterAdded, - CharacterRemoved, - InputWasCleared - }; - - EventType type{}; ///< Type of the event - u32 codepoint{0}; ///< The codepoint of the character that thrown the event - }; - - class KeyboardImpl; - class Keyboard - { - /** - * \brief The signature of the callback called to check the input - * \param input A void pointer to the input, must be casted to the correct type (as passed to Keyboard::Open) - * \param error A reference to the string that hold the error message. You can edit it according to what you want to display - * \return A boolean \n Return true if the input is valid, false if it's not - */ - using CompareCallback = bool (*)(const void *, std::string&); - - /** - * \brief The signature of the callback called when the input change (user enter / delete a character) - * \param keyboard A reference to the Keyboard object that called the callback - * \event event The event that caused the input to change - */ - using OnInputChangeCallback = void(*)(Keyboard&, InputChangeEvent &event); - public: - - /** - * \brief Keyboard constructor - * \param text The message to display on the top screen if displayed - */ - Keyboard(const std::string &text = ""); - Keyboard(const std::string &text, const std::vector &options); - Keyboard(const std::vector &options); - ~Keyboard(void); - - /** - * \brief Set if the user can abort the keybord by pressing B - * \param canAbort Whether the user can press B to close the keyboard and abort the current operation - */ - void CanAbort(bool canAbort) const; - - /** - * \brief Define if the input must be hexadecimal or not \n - * Have no effect for float, double, string - * \param isHex If the input must be hexadecimal - */ - void IsHexadecimal(bool isHex); - - /** - * \brief Define a maximum input length for qwerty keyboard - * \param maxValue The maximum count of characters that the user can type - */ - void SetMaxLength(u32 maxValue) const; - - /** - * \brief Define a callback to check the input \n - * The callback is called each time the input is changed \n - * See CompareCallback's description for more infos - * \param callback The callback that must be called - */ - void SetCompareCallback(CompareCallback callback) const; - - /** - * \brief Define a callback that will be called when the user change the input \n - * Note that if a CompareCallback is set, CompareCallback is called before OnInputChange \n - * See OnInputChangeCallback's description for more infos - * \param callback - */ - void OnInputChange(OnInputChangeCallback callback) const; - - /** - * \brief Set the error flag and an error message \n - * When the error flag is set, the user can't valid the input - * \param error The error message that must be displayed - */ - void SetError(std::string error) const; - - /** - * \brief Populate a keyboard with the strings contained in an std::vector - * \param input A std::vector that contain a list of strings - */ - void Populate(const std::vector &input); - - /** - * \brief Open a keyboard which is populated with strings - * \return -1 : user abort / not populated \n - * >= 0 : index of the user choice in the vector - */ - int Open(void) const; - - /** - * \brief Open the keyboard and wait for user input - * \param output Where to place the user's input - * \return -1 : user abort / error \n - * 0 : Success - */ - int Open(u8 &output) const; - - /** - * \brief Open the keyboard and wait for user input - * \param output Where to place the user's input - * \param start The keyboard will start with this value as input - * \return -1 : user abort / error \n - * 0 : Success - */ - int Open(u8 &output, u8 start) const; - - /** - * \brief Open the keyboard and wait for user input - * \param output Where to place the user's input - * \return -1 : user abort / error \n - * 0 : Success - */ - int Open(u16 &output) const; - - /** - * \brief Open the keyboard and wait for user input - * \param output Where to place the user's input - * \param start The keyboard will start with this value as input - * \return -1 : user abort / error \n - * 0 : Success - */ - int Open(u16 &output, u16 start) const; - - /** - * \brief Open the keyboard and wait for user input - * \param output Where to place the user's input - * \return -1 : user abort / error \n - * 0 : Success - */ - int Open(u32 &output) const; - - /** - * \brief Open the keyboard and wait for user input - * \param output Where to place the user's input - * \param start The keyboard will start with this value as input - * \return -1 : user abort / error \n - * 0 : Success - */ - int Open(u32 &output, u32 start) const; - - /** - * \brief Open the keyboard and wait for user input - * \param output Where to place the user's input - * \return -1 : user abort / error \n - * 0 : Success - */ - int Open(u64 &output) const; - - /** - * \brief Open the keyboard and wait for user input - * \param output Where to place the user's input - * \param start The keyboard will start with this value as input - * \return -1 : user abort / error \n - * 0 : Success - */ - int Open(u64 &output, u64 start) const; - - /** - * \brief Open the keyboard and wait for user input - * \param output Where to place the user's input - * \return -1 : user abort / error \n - * 0 : Success - */ - int Open(float &output) const; - - /** - * \brief Open the keyboard and wait for user input - * \param output Where to place the user's input - * \param start The keyboard will start with this value as input - * \return -1 : user abort / error \n - * 0 : Success - */ - int Open(float &output, float start) const; - - /** - * \brief Open the keyboard and wait for user input - * \param output Where to place the user's input - * \return -1 : user abort / error \n - * 0 : Success - */ - int Open(double &output) const; - - /** - * \brief Open the keyboard and wait for user input - * \param output Where to place the user's input - * \param start The keyboard will start with this value as input - * \return -1 : user abort / error \n - * 0 : Success - */ - int Open(double &output, double start) const; - - /** - * \brief Open the keyboard and wait for user input - * \param output Where to place the user's input - * \return -1 : user abort / error \n - * 0 : Success - */ - int Open(std::string &output) const; - - /** - * \brief Open the keyboard and wait for user input - * \param output Where to place the user's input - * \param start The keyboard will start with this value as input - * \return -1 : user abort / error \n - * 0 : Success - */ - int Open(std::string &output, const std::string &start) const; - - /** - * \brief Forcefully close the keyboard without any regard to the error flag \n - * (This can only be called from an OnInputChange callback) - */ - void Close(void) const; - - /** - * \brief Get a reference to the Keyboard's input string - * \return A reference to the Keyboard's input string - */ - std::string &GetInput(void) const; - - /** - * \brief Get a reference to the top screen's message string - * \return A reference to the top screen's message string - */ - std::string &GetMessage(void) const; - - /** - * \brief This property define if the top screen must be displayed or not \n - * Note that when disabled, errors messages can't be displayed - */ - bool DisplayTopScreen; - - private: - std::unique_ptr _keyboard; - bool _hexadecimal; - bool _isPopulated; - }; -} - -#endif \ No newline at end of file diff --git a/Includes/CTRPluginFramework/Menu/MenuEntry.hpp b/Includes/CTRPluginFramework/Menu/MenuEntry.hpp deleted file mode 100644 index aa416d0..0000000 --- a/Includes/CTRPluginFramework/Menu/MenuEntry.hpp +++ /dev/null @@ -1,150 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_MENUENTRY_HPP -#define CTRPLUGINFRAMEWORK_MENUENTRY_HPP - -#include "MenuEntryHotkeys.hpp" - -#include -#include - -namespace CTRPluginFramework -{ -#ifndef SEPARATOR_TYPE -#define SEPARATOR_TYPE - enum class Separator - { - None, - Filled, - Stippled - }; -#endif - - class MenuEntryImpl; - class MenuEntry - { - using FuncPointer = void(*)(MenuEntry*); - public: - - explicit MenuEntry(const std::string &name, const std::string ¬e = ""); - MenuEntry(const std::string &name, FuncPointer gameFunc, const std::string ¬e = ""); - MenuEntry(const std::string &name, FuncPointer gameFunc, FuncPointer menuFunc, const std::string ¬e = ""); - MenuEntry(int radioGroup, const std::string &name, FuncPointer gameFunc, const std::string ¬e = ""); - MenuEntry(int radioGroup, const std::string &name, FuncPointer gameFunc, FuncPointer menuFunc, const std::string ¬e = ""); - ~MenuEntry(); - - /** - * \brief Enable the entry (the gamefunction linked to it will be executed) - * \param - */ - void Enable(void) const; - - /** - * \brief Disable the entry - * \param - */ - void Disable(void) const; - - /** - * \brief Hide the entry from the menu. The entry will also be disabled - */ - void Hide(void) const; - - /** - * \brief Unhide an entry previously hidden - */ - void Show(void) const; - /** - * \brief Set the entry as a radio entry and link it to a radio group ID - * \param id The id of the radio group to be linked to - */ - void SetRadio(int id) const; - /** - * \brief Set a value for entry's argument - * \param The value of the argument - */ - void SetArg(void *arg) const; - - /** - * \brief Get the value of this entry's argument - * \return The value of the argument - */ - void *GetArg(void) const; - - /** - * \brief Check if this entry was just activated (first gamefunction execution) - * \return true if the entry was just activated - */ - bool WasJustActivated(void) const; - - /** - * \brief Check if this entry is activated - * \return true if the entry is activated, false otherwise - */ - bool IsActivated(void) const; - - /** - * \brief Check if this entry is visible in the menu - * \return true if the entry is visible, false if the entry is hidden - */ - bool IsVisible(void) const; - - /** - * \brief Set if this entry must display a separator on top of the entry - * \param type Type of separator to display - */ - void UseTopSeparator(Separator type = Separator::Filled) const; - - /** - * \brief Set if this entry must display a separator at the bottom of the entry - * \param type Type of separator to display - */ - void UseBottomSeparator(Separator type = Separator::Filled) const; - - /** - * \brief Set if the entry can be selected in the menu or not.\n - * If the entry is Activated and the state is set to unselectable, the entry will be disabled - * \param canBeSelected - */ - void CanBeSelected(bool canBeSelected) const; - - /** - * \brief Set the gamefunction of this entry - * \param func The new function to be executed on game loop - */ - void SetGameFunc(FuncPointer func) const; - - /** - * \brief Set the menu funuction of this entry - * \param func The new function to be executed on the menu - */ - void SetMenuFunc(FuncPointer func) const; - - /** - * \brief Force the menu to refresh the note - */ - void RefreshNote(void) const; - - /** - * \brief Get the entry's name string - * \return A reference to current name - */ - std::string &Name(void) const; - - /** - * \brief Get the entry's note string - * \return A reference to current note - */ - std::string &Note(void) const; - - /** - * \brief The hotkey manager of this entry. See MenuEntryHotkeys.hpp for more infos - */ - HotkeyManager Hotkeys; - - private: - friend class MenuFolder; - friend class PluginMenu; - std::unique_ptr _item; - }; -} - -#endif diff --git a/Includes/CTRPluginFramework/Menu/MenuEntryHotkeys.hpp b/Includes/CTRPluginFramework/Menu/MenuEntryHotkeys.hpp deleted file mode 100644 index dec46b7..0000000 --- a/Includes/CTRPluginFramework/Menu/MenuEntryHotkeys.hpp +++ /dev/null @@ -1,133 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_MENUENTRYHOTKEYS_HPP -#define CTRPLUGINFRAMEWORK_MENUENTRYHOTKEYS_HPP - -#include "types.h" - -#include -#include - -namespace CTRPluginFramework -{ - class MenuEntry; - class Hotkey - { - public: - - Hotkey(); - - /** - * \brief Create a new Hotkey - * \param keys The default keys of this hotkey - * \param name The name for this hotkey \n - * Appear on the note and on the Hotkey selector when the user want to edit an hotkey - */ - Hotkey(u32 keys, const std::string &name); - ~Hotkey(); - - /** - * \brief Change the keys value of the hotkey - * \param keys the new keys value of the hotkey - */ - void operator=(u32 keys); - - /** - * \brief Change the name of the hotkey - * \param name The new name you want to appear on the note / the HotkeyModifier selector - */ - void operator=(const std::string &name); - - /** - * \brief Check if the keys of this Hotkey are currently down - * \return If the keys are down - */ - bool IsDown(void) const; - - /** - * \brief Display a control for the user to select the keys - */ - void AskForKeys(void); - - /** - * \brief Get the keys value of this Hotkey - * \return the keys value - */ - u32 GetKeys(void); - - /** - * \brief Stringify the Hotkey - * \param withName if the name of the Hotkey must be in the result - * \return return a string of this Hotkey\n - * if withName is false then the output will simply be the Key's value: "A + B" - * if withName is true the output will be: "Hotkey's name : A + B" - */ - std::string ToString(bool withName = false) const; - - private: - friend class HotkeyManager; - friend class PluginMenuImpl; - u32 _keys; - std::string _name; - }; - - class MenuEntry; - class HotkeyManager - { - public: - /** - * \brief A callback type, the args are: - * MenuEntry *: the entry that own the Hotkey - * int : the index in the HotkeyManager of the hotkey that changed - */ - using OnHotkeyChangeClbk = void(*)(MenuEntry*, int); - - HotkeyManager(MenuEntry *owner); - ~HotkeyManager(); - - /** - * \brief Add an hotkey to the manager - * \param hotkey The Hotkey to add - */ - void operator+=(const Hotkey &hotkey); - - /** - * \brief Return a reference to the Hotkey from the manager - * \param index The index of the Hotkey you want from the manager - * \return A reference to the desired Hotkey - */ - Hotkey &operator[](u32 index); - - /** - * \brief Stringify all Hotkeys - * \return a string with all the Hotkey as string - */ - std::string ToString(void); - - /** - * \brief Display a control that allows the user to select which Hotkey he wants to edit - */ - void AskForKeys(void); - - /** - * \brief Add a callback that be called when an Hotkey will change - * \param callback The callback to call - */ - void OnHotkeyChangeCallback(OnHotkeyChangeClbk callback); - - /** - * \brief Get how many Hotkeys the manager currently have - * \return The count of Hotkeys - */ - u32 Count(void); - - private: - friend class PluginMenuHome; - friend class PluginMenuImpl; - - MenuEntry *_owner; - OnHotkeyChangeClbk _callback; - std::vector _hotkeys; - - }; -} - -#endif \ No newline at end of file diff --git a/Includes/CTRPluginFramework/Menu/MenuFolder.hpp b/Includes/CTRPluginFramework/Menu/MenuFolder.hpp deleted file mode 100644 index dcac520..0000000 --- a/Includes/CTRPluginFramework/Menu/MenuFolder.hpp +++ /dev/null @@ -1,172 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_MENUFOLDER_HPP -#define CTRPLUGINFRAMEWORK_MENUFOLDER_HPP - -#include "types.h" -#include -#include - -namespace CTRPluginFramework -{ -#ifndef SEPARATOR_TYPE -#define SEPARATOR_TYPE - enum class Separator - { - None, - Filled, - Stippled - }; -#endif - - enum class ActionType - { - Opening, - Closing - }; - - class MenuFolderImpl; - class MenuFolder - { - - public: - MenuFolder(const std::string &name, const std::string ¬e = ""); - MenuFolder(const std::string &name, const std::vector &entries); - MenuFolder(const std::string &name, const std::string ¬e, const std::vector &entries); - - /** - * \brief Destroy a MenuFolder.\n - * Upon destruction all MenuEntry and MenuFolder objects contained by this folder\n - * will be destroyed too (so all pointers will be invalidated). - */ - ~MenuFolder(); - - /** - * \brief Hide the folder from the menu.\n - * Will disable every MenuEntry objects contained in this folder and subfolders - */ - void Hide(void) const; - - /** - * \brief Display the folder previously hidden in the menu - */ - void Show(void) const; - - /** - * \brief Check if the current folder is visible in the menu - * \return true if the folder is visible, false otherwise - */ - bool IsVisible(void) const; - - /** - * \brief Set if this entry must display a separator on top of the entry - * \param type Type of separator to display - */ - void UseTopSeparator(Separator type = Separator::Filled) const; - - /** - * \brief Set if this entry must display a separator at the bottom of the entry - * \param type Type of separator to display - */ - void UseBottomSeparator(Separator type = Separator::Filled) const; - - /** - * \brief Append a MenuEntry object to this folder - * \param item The entry to append - */ - void Append(MenuEntry *item) const; - - /** - * \brief Append a MenuFolder object to this folder - * \param item The folder to append - */ - void Append(MenuFolder *item) const; - - /** - * \brief Get all entries present in this folder (doesn't contain subfolder's) - * \return A std::vector with pointers to all MenuEntry objects - */ - std::vector GetEntryList(void) const; - - /** - * \brief Get all folders present in this folder (doesn't contain subfolder's) - * \return A std::vector with pointers to all MenuEntry objects - */ - std::vector GetFolderList(void) const; - - /** - * \brief Get a reference of the string that hold the name of this folder - * \return A reference of the std::string - */ - std::string &Name(void) const; - /** - * \brief Get a reference of the string that hold the note of this folder - * \return A reference of the std::string - */ - std::string &Note(void) const; - - /** - * \brief Get the number of items that his folder contains (not counting subfolders's content) - * \return The count of items - */ - u32 ItemsCount(void) const; - - /** - * \brief Remove and destroy all items contained by this folder.\n - * This invalidate all pointers to any contained object. - */ - void Clear(void) const; - - /** - * \brief Remove all objects in the range specified - * \param startIndex The index where the range begin - * \param count The number of elements to remove - * \param destroy If the elements must be destroyed (invalidate pointers and release ressources) - */ - void Remove(u32 startIndex, u32 count, bool destroy) const; - - /** - * \brief Add an entry to this folder - * \param entry The MenuEntry object that must be added - * \return A pointer to this MenuFolder - */ - MenuFolder *operator += (const MenuEntry *entry); - - /** - * \brief Remove an entry from this folder - * \param entry The MenuEntry object that must be removed - * \return A pointer to this MenuFolder - */ - MenuFolder *operator -= (const MenuEntry *entry); - - /** - * \brief Add a (sub)folder to this folder - * \param folder The MenuFolder object that must added - * \return A pointer to this MenuFolder - */ - MenuFolder *operator += (const MenuFolder *folder); - - /** - * \brief Remove a (sub)folder to this folder - * \param folder The MenuFolder object that must be removed - * \return A pointer to this MenuFolder - */ - MenuFolder *operator -= (const MenuFolder *folder); - - /** - * \brief Callback type, receive the object that called the callback \n - * along with the action which triggered the callback - * \return Whether the folder can be opened (on ActionType::Opening only, ignored for ActionType::Closing) - */ - using MenuFolder_OnActionFunc = bool(*)(MenuFolder &, ActionType); - - /** - * \brief This callback is called when the folder is about to be opened or closed - */ - MenuFolder_OnActionFunc OnAction; - - private: - friend class PluginMenu; - std::unique_ptr _item; - }; -} - -#endif diff --git a/Includes/CTRPluginFramework/Menu/MessageBox.hpp b/Includes/CTRPluginFramework/Menu/MessageBox.hpp deleted file mode 100644 index e34b0fa..0000000 --- a/Includes/CTRPluginFramework/Menu/MessageBox.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_MESSAGEBOX_HPP -#define CTRPLUGINFRAMEWORK_MESSAGEBOX_HPP - -#include -#include - -namespace CTRPluginFramework -{ - enum class DialogType - { - DialogOk, - DialogOkCancel, - DialogYesNo - }; - - enum class ClearScreen - { - None = 0, - Top = 1 << 1, - Bottom = 1 << 2, - Both = Top | Bottom - }; - - class MessageBoxImpl; - class MessageBox - { - public: - MessageBox(const std::string &title, const std::string &message, DialogType dialogType = DialogType::DialogOk, ClearScreen clear = ClearScreen::None); - MessageBox(const std::string &message, DialogType dialogType = DialogType::DialogOk, ClearScreen clear = ClearScreen::None); - ~MessageBox(void); - - MessageBox& SetClear(ClearScreen screen); - - // Display the Message Box and wait for the user input - // Return: - // True if user selected Yes / Ok - // False is user selected No / Cancel - bool operator()(void) const; - - private: - std::unique_ptr _messageBox; - }; -} - -#endif diff --git a/Includes/CTRPluginFramework/Menu/PluginMenu.hpp b/Includes/CTRPluginFramework/Menu/PluginMenu.hpp deleted file mode 100644 index 5fe16e5..0000000 --- a/Includes/CTRPluginFramework/Menu/PluginMenu.hpp +++ /dev/null @@ -1,163 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_PLUGINMENU_HPP -#define CTRPLUGINFRAMEWORK_PLUGINMENU_HPP - -#include "CTRPluginFramework/Menu/MenuEntry.hpp" -#include "CTRPluginFramework/Menu/MenuFolder.hpp" -#include "CTRPluginFramework/System/Time.hpp" - -#include -#include -#include - -namespace CTRPluginFramework -{ - class PluginMenuImpl; - class PluginMenu - { - using CallbackPointer = void (*)(void); - using FrameCallback = void (*)(Time); - using DecipherPointer = void(*)(std::string &, void *); - public: - - /* - ** Create a new PluginMenu - ** name = The name of the menu / main folder - ** about = text to display on the bottom screen of Tools section - ******************************/ - explicit PluginMenu(std::string name = "Cheats", std::string about = ""); - - /* - ** Create a new PluginMenu - ** name = The name of the menu / main folder - ** about = pointer to encrypted about's text data - ** func = function to decrypt the about's data - ******************************/ - PluginMenu(std::string name, void *about, DecipherPointer func); - - /** - * \brief Create a new PluginMenu - * \param name The name of the menu / main folder - * \param major The major version number of the plugin version - * \param minor The minor version number of the plugin version - * \param revision The revision version number of the plugin version - * \param about Text to display in Tools About - */ - PluginMenu(std::string name, u32 major, u32 minor, u32 revision, std::string about = ""); - - /* - ** Destructor - ******************************/ - ~PluginMenu(void); - - /* - ** Append a new entry to the menu (root) - ** item = pointer to a MenuEntry object - ******************************/ - void Append(MenuEntry *item) const; - - /* - ** Append a new folder to the menu (root) - ** item = pointer to a MenuFolder object - ******************************/ - void Append(MenuFolder *item) const; - - void operator += (const MenuEntry *entry) const; - void operator += (const MenuFolder *folder) const; - void operator += (CallbackPointer callback) const; - void operator -= (CallbackPointer callback) const; - - /* - ** Add a callback to the menu - ** A callback is a function which is always executed in the menu's main loop - ** callback = function to add as callback - ******************************/ - void Callback(CallbackPointer callback) const; - - /* - ** Run the menu - ** This call is blocking so be sure to do everyting before calling this function - ******************************/ - int Run(void) const; - - /** - * \brief Get all entries present at the root of the menu - * \return A std::vector with pointers to all MenuEntry objects - */ - std::vector GetEntryList(void) const; - - /** - * \brief Get all folders present at the root of the menu - * \return A std::vector with pointers to all MenuFolder objects - */ - std::vector GetFolderList(void) const; - - /** - * \brief Enable / Disable the HexEditor in Tools - * \param isEnabled If HexEditor must be enabled or not - */ - void SetHexEditorState(bool isEnabled) const; - - /** - * \brief Choose to display or not the "plugin ready" message - * \param showMsg If the message must be displayed or not - */ - void ShowWelcomeMessage(bool showMsg) const; - - /** - * \brief Check if the menu is currently open - * \return true if the menu is open, false otherwise - */ - bool IsOpen(void); - - /** - * \brief Check if the menu was opened since last Func execution - * \return true if the menu was opened, false otherwise - */ - bool WasOpened(void); - - /** - * \brief Get a reference to the PluginMenu currently running - * \return A reference to a PluginMenu that is currently running - */ - static PluginMenu *GetRunningInstance(void); - - /** - * \brief If set to true, the plugin's loop will only be executed 1 per top screen's frame - * \param useSync Wheter to wait for the top screen's frame or not - */ - void SynchronizeWithFrame(const bool useSync); - - /** - * \brief If a callback is set, the callback will be called - Must be set before calling Run - * when the menu is opened for the first time - */ - CallbackPointer OnFirstOpening; - - /** - * \brief If a callback is set, the callback will be called - Must be set before calling Run - * when the menu is opened. Ideal to put the code that refresh the UI. ;) - */ - CallbackPointer OnOpening; - - /** - * \brief The callback set will be called at each frame rendered while the menu is open - * Ideal to put some UI effect - * The function will receive the Time elapsed since last frame - * Must be set before calling Run - */ - FrameCallback OnNewFrame; - - - /** - * \brief Returns the reference of the PluginMenu title string - * \return the reference of the PluginMenu title string - */ - std::string & Title(); - - - private: - std::unique_ptr _menu; - }; -} - -#endif diff --git a/Includes/CTRPluginFramework/System.hpp b/Includes/CTRPluginFramework/System.hpp deleted file mode 100644 index 0b76f7e..0000000 --- a/Includes/CTRPluginFramework/System.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_SYSTEM_HPP -#define CTRPLUGINFRAMEWORK_SYSTEM_HPP - -#include "CTRPluginFramework/System/Clock.hpp" -#include "CTRPluginFramework/System/Controller.hpp" -#include "CTRPluginFramework/System/Directory.hpp" -#include "CTRPluginFramework/System/File.hpp" -#include "CTRPluginFramework/System/FwkSettings.hpp" -#include "CTRPluginFramework/System/Hook.hpp" -#include "CTRPluginFramework/System/Lock.hpp" -#include "CTRPluginFramework/System/Mutex.hpp" -#include "CTRPluginFramework/System/Process.hpp" -#include "CTRPluginFramework/System/System.hpp" -#include "CTRPluginFramework/System/Task.hpp" -#include "CTRPluginFramework/System/Time.hpp" -#include "CTRPluginFramework/System/Touch.hpp" -#include "CTRPluginFramework/System/Sleep.hpp" - -#endif diff --git a/Includes/CTRPluginFramework/System/Clock.hpp b/Includes/CTRPluginFramework/System/Clock.hpp deleted file mode 100644 index b594a90..0000000 --- a/Includes/CTRPluginFramework/System/Clock.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef CTRPLUGINFRAMREWORK_CLOCK_HPP -#define CTRPLUGINFRAMREWORK_CLOCK_HPP - -#include "CTRPluginFramework/System/Time.hpp" - -namespace CTRPluginFramework -{ - class Clock - { - public: - Clock(void); - Clock(Time time); - - Time GetElapsedTime(void) const; - bool HasTimePassed(Time time) const; - Time Restart(void); - private: - Time _startTime; - }; -} - -#endif \ No newline at end of file diff --git a/Includes/CTRPluginFramework/System/Controller.hpp b/Includes/CTRPluginFramework/System/Controller.hpp deleted file mode 100644 index 0ad3c2a..0000000 --- a/Includes/CTRPluginFramework/System/Controller.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_CONTROLLER_HPP -#define CTRPLUGINFRAMEWORK_CONTROLLER_HPP - -#include "types.h" - -namespace CTRPluginFramework -{ - enum Key - { - A = 1, - B = 1 << 1, - Select = 1 << 2, - Start = 1 << 3, - DPadRight = 1 << 4, - DPadLeft = 1 << 5, - DPadUp = 1 << 6, - DPadDown = 1 << 7, - R = 1 << 8, - L = 1 << 9, - X = 1 << 10, - Y = 1 << 11, - ZL = 1 << 14, ///< The ZL button (New 3DS only) - ZR = 1 << 15, ///< The ZR button (New 3DS only) - Touchpad = 1 << 20, - CStickRight = 1 << 24, - CStickLeft = 1 << 25, - CStickUp = 1 << 26, - CStickDown = 1 << 27, - CPadRight = 1 << 28, - CPadLeft = 1 << 29, - CPadUp = 1 << 30, - CPadDown = 1 << 31, - Up = DPadUp | CPadUp, - Down = DPadDown | CPadDown, - Left = DPadLeft | CPadLeft, - Right = DPadRight | CPadRight, - CPad = CPadLeft | CPadRight | CPadUp | CPadDown, - CStick = CStickLeft | CStickRight | CStickUp | CStickDown - }; - class Controller - { - public: - - // Return all the keys currently down - static u32 GetKeysDown(void); - // Return all the keys which were released - static u32 GetKeysReleased(void); - // Return if the key is still being pressed - static bool IsKeyDown(Key key); - // Return if the key just got pressed - static bool IsKeyPressed(Key key); - // Return if the key was released - static bool IsKeyReleased(Key key); - - // Return if keyCombo is still being pressed - static bool IsKeysDown(u32 keys); - // Return is the keys combo just got pressed - static bool IsKeysPressed(u32 keys); - // Return is the keys combo just was released - static bool IsKeysReleased(u32 keys); - // Update Controller status - static void Update(void); - - static void InjectTouch(u16 posX, u16 posY); - static void InjectKey(u32 key); - private: - static u32 _keysDown; - static u32 _keysHeld; - static u32 _keysReleased; - }; -} - -#endif \ No newline at end of file diff --git a/Includes/CTRPluginFramework/System/Directory.hpp b/Includes/CTRPluginFramework/System/Directory.hpp deleted file mode 100644 index d6a4865..0000000 --- a/Includes/CTRPluginFramework/System/Directory.hpp +++ /dev/null @@ -1,146 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_DIRECTORY_HPP -#define CTRPLUGINFRAMEWORK_DIRECTORY_HPP - -#include "types.h" -#include "CTRPluginFramework/System/File.hpp" - -#include -#include - -namespace CTRPluginFramework -{ - class File; - class Directory - { - public: - - enum OPResult - { - SUCCESS = 0, ///< Operation succeeded - INVALID_PATH = -1, ///< The path is invalid - NOT_OPEN = -2, ///< The File instance is not opened - INVALID_ARG = -3, ///< One of the args passed to the operation is invalid (nullptr, address unreachable, etc) - UNEXPECTED_ERROR = -4 ///< An error occured - }; - - /** - * \brief Change the working directory - * \param path The new path to set as working directory - * \return An \ref OPResult code - */ - static int ChangeWorkingDirectory(const std::string &path); - - /** - * \brief Create a directory - * \param path Path of the directory to create - * \return Either a value from \ref OPResult or a FS return value - */ - static int Create(const std::string &path); - - /** - * \brief Remove the specified directoy - * \param path The directory to remove - * \return Either a value from \ref OPResult or a FS return value - */ - static int Remove(const std::string &path); - - /** - * \brief Rename the specified directory - * \param oldPath The directory to rename - * \param newPath The new name of the directory - * \return Either a value from \ref OPResult or a FS return value - */ - static int Rename(const std::string &oldPath, const std::string &newPath); - - /** - * \brief Check if the specified directory exists - * \param path The directory to check - * \return - * 1: Exists - * 0: Doesn't exists - */ - static int IsExists(const std::string &path); - - /** - * \brief Open a directory - * \param output Reference to the Directory object - * \param path The directory to open - * \param create If the directory must be created - * \return Either a value from \ref OPResult or a FS return value - */ - static int Open(Directory &output, const std::string &path, bool create = false); - - /** - * \brief Close a Directory - * \return Either a value from \ref OPResult or a FS return value - */ - int Close(void) const; - - /** - * \brief Open a file within the current Directory - * \param output The File object - * \param path The file to open - * \param mode The mode to open the file with - * \return Either a value from \ref OPResult or a FS return value - */ - int OpenFile(File &output, const std::string &path, int mode = File::RW) const; - - /** - * \brief List all the files within the current Directory - * \param files The list of files that will be returned \n - * Beware that the container is not emptied and results files are appended - * \param pattern If specified, only the files that contain the pattern will be returned - * \return The count of files found, OPResult::NOT_OPEN if the Directory is not opened - */ - int ListFiles(std::vector &files, const std::string &pattern = "") const; - - /** - * \brief List all the directories within the current Directory - * \param directories The list of directories that will be returned \n - * Beware that the container is not emptied and results directories are appended - * \param pattern If specified, only the directories that contain the pattern will be returned - * \return The count of directories found, OPResult::NOT_OPEN if the Directory is not opened - */ - int ListDirectories(std::vector &directories, const std::string &pattern = "") const; - - /** - * \brief Get the name of the current Directory - * \return An std::string with the name of the current Directory - */ - std::string GetName(void) const; - - /** - * \brief Get the full path of the current Directory - * \return An std::string with the full path of the current Directory - */ - std::string GetFullName(void) const; - - /** - * \brief Check if the current Directory is open - * \return true if the specified path was successfully opened, false otherwise - */ - bool IsOpen(void) const; - - Directory(void); - Directory(const std::string &path, bool create = false); - ~Directory(); - - private: - - int _List(void) const; - - std::string _path; - Handle _handle; - mutable bool _isOpen; - mutable Mutex _mutex; - struct DirectoryEntry - { - DirectoryEntry(u32 attrib, u8 *name); - u32 attributes; - std::string name; - }; - mutable std::vector _list; - }; -} - -#endif \ No newline at end of file diff --git a/Includes/CTRPluginFramework/System/File.hpp b/Includes/CTRPluginFramework/System/File.hpp deleted file mode 100644 index 6c95298..0000000 --- a/Includes/CTRPluginFramework/System/File.hpp +++ /dev/null @@ -1,219 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_FILE_HPP -#define CTRPLUGINFRAMEWORK_FILE_HPP - -#include "types.h" -#include "CTRPluginFramework/System/Mutex.hpp" - -#include -#include - -namespace CTRPluginFramework -{ - class File - { - public: - - enum SeekPos - { - CUR, - SET, - END - }; - - enum Mode - { - READ = 1, ///< Gives read permission - WRITE = 1 << 1, ///< Gives write permission - CREATE = 1 << 2, ///< The file will be created if it doesn't exist - APPEND = 1 << 3, ///< You'll be unable to overwrite the file, only append data to it - TRUNCATE = 1 << 4, ///< Will clear the file - SYNC = 1 << 5, ///< Will flush and update time on each write - - RW = READ | WRITE, - RWC = READ | WRITE | CREATE - }; - - enum OPResult - { - SUCCESS = 0, ///< Operation succeeded - INVALID_PATH = -1, ///< The path is invalid - NOT_OPEN = -2, ///< The File instance is not opened - INVALID_MODE = -3, ///< The mode passed when opened the file doesn't allow this operation - INVALID_ARG = -4, ///< One of the args passed to the operation is invalid (nullptr, address unreachable, etc) - UNEXPECTED_ERROR = -5 ///< An error occured - }; - - /** - * \brief Create a file - * \param path The path of the file to create - * \return - * Either a value in \ref OPResult or an error code from FS service - */ - static int Create(const std::string &path); - - /** - * \brief Rename the specified file - * \param path Old name - * \param newpath New name - * \return - * Either a value in \ref OPResult or an error code from FS service - */ - static int Rename(const std::string &path, const std::string &newpath); - - /** - * \brief Remove the specified file - * \param path The file to remove - * \return - * Either a value in \ref OPResult or an error code from FS service - */ - static int Remove(const std::string &path); - - - /** - * \brief Determines whether the specified file exists - * \param path The file to check - * \return - * 0: File doesn't exists \n - * 1: File exists \n - * Either a value in \ref OPResult or an error code from FS service - */ - static int Exists(const std::string &path); - - /** - * \brief Open the specified file - * \param output File object - * \param path The file to open - * \param mode The mode that specifies the acces type (See \ref File::Mode) - * \return - * Either a value in \ref OPResult or an error code from FS service - */ - static int Open(File &output, const std::string &path, int mode = READ | WRITE | SYNC); - - /** - * \brief Close the file - * \return - * Either a value in \ref OPResult or an error code from FS service - */ - int Close(void) const; - - /** - * \brief Read file - * \param buffer Where to read the data to, ensure the buffer is large enough - * \param length Size to read in bytes - * \return - * Either a value in \ref OPResult or an error code from FS service - */ - int Read(void *buffer, u32 length) const; - - /** - * \brief Write to file - * \param data Pointer to the data to write to the file - * \param length Length of the data to write in bytes - * \return - * Either a value in \ref OPResult or an error code from FS service - */ - int Write(const void *data, u32 length); - - - /** - * \brief Write a string to file (auto append '\n') - * \param line Text to write - * \return - * Either a value in \ref OPResult or an error code from FS service - */ - int WriteLine(std::string line); - - /** - * \brief Set the position in the file - * \param offset Value to offset from \param origin - * \param origin Position used as reference for \param offset - * \return - * Either a value in \ref OPResult or an error code from FS service - */ - int Seek(s64 offset, SeekPos origin = CUR) const; - - /** - * \brief Get current position in the file - * \return The current position in file from the beginning - */ - u64 Tell(void) const; - - /** - * \brief Set the position to the beginning of the file - */ - void Rewind(void) const; - - /** - * \brief Flushes a file's content - * \return - * Either a value in \ref OPResult or an error code from FS service - */ - int Flush(void) const; - - /** - * \brief Get the size of the file - * \return - * File size if >= 0 \n - * Either a value in \ref OPResult or an error code from FS service otherwise - */ - u64 GetSize(void) const; - - void SetPriority(u32 priority); - - /** - * \brief Write the content of the memory to the file - * \param address Address to start reading the memory from - * \param length Length in bytes to write to the file - * \return - * Either a value in \ref OPResult or an error code from FS service - */ - int Dump(u32 address, u32 length); - - /** - * \brief Write the content of the file (from current position) to memory - * \param address Address to copy the content to - * \param length Length in bytes to copy - * \return - * Either a value in \ref OPResult or an error code from FS service - */ - int Inject(u32 address, u32 length) const; - - /** - * \brief Check if the file is open or not - * \return true if open, false otherwise - */ - bool IsOpen(void) const; - - /** - * \brief Gets the full path of the file - * \return An std::string with the full path of the file - */ - std::string GetFullName(void) const; - - /** - * \brief Get the file name - * \return An std::string with the name of the file - */ - std::string GetName(void) const; - - /** - * \brief Get the extension of the file - * \return An std::string with the extension part of the file - */ - std::string GetExtension(void) const; - - File(void); - File(const std::string &path, u32 mode = READ | WRITE | SYNC); - ~File() { Close(); } - - private: - mutable std::string _path; - mutable Handle _handle; - mutable u64 _offset; - mutable int _mode; - mutable bool _isOpen; - mutable Mutex _mutex; - }; -} - -#endif \ No newline at end of file diff --git a/Includes/CTRPluginFramework/System/FwkSettings.hpp b/Includes/CTRPluginFramework/System/FwkSettings.hpp deleted file mode 100644 index 71bad2b..0000000 --- a/Includes/CTRPluginFramework/System/FwkSettings.hpp +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_SYSTEM_FWKSETTINGS_HPP -#define CTRPLUGINFRAMEWORK_SYSTEM_FWKSETTINGS_HPP - -#include "types.h" -#include "CTRPluginFramework/System/Time.hpp" -#include "CTRPluginFramework/Graphics/Color.hpp" - -namespace CTRPluginFramework -{ - struct PluginHeader - { - u32 magic; - u32 version; - u32 heapVA; - u32 heapSize; - u32 pluginSize; - const char* pluginPathPA; - u32 isDefaultPlugin; - u32 reserved[25]; - u32 config[32]; - }; - - struct FwkSettings - { - // Plugin init options - u32 ThreadPriority; ///< Pri ority for the main thread of the plugin must be within 0x3E - 0x18 | Default: 0x30 - bool AllowActionReplay; ///< Enable the Action Replay's handler, if this is set to off, even if the menu allows to create codes, they won't be executed - bool AllowSearchEngine; ///< If false then the search engine won't be available | Default: true - Time WaitTimeToBoot; ///< Time to wait for the plugin to starts (from when the game will starts) | Default: 5 seconds - - // UI colors - Color MainTextColor; ///< The color of all texts within the plugin | Default: Blank - Color WindowTitleColor; ///< The color of all window's titles | Default: Blank - Color MenuSelectedItemColor; ///< The color of the text for the selected item | Default: Blank - Color MenuUnselectedItemColor; ///< The color of the text for the items not selected | Default: Silver - Color BackgroundMainColor; ///< The color of the background | Default: Black - Color BackgroundSecondaryColor; ///< The color of the background 2 | Default: black/grey (RGB: 15, 15, 15) - Color BackgroundBorderColor; ///< The color of the border around the window | Default: Blank - float CursorFadeValue; ///< The value to be used to draw the cursor (Shade: [-1.0f - 0f], Tint: [0.f - 1.f]) | Default: 0.2f - - // Keyboard colors - struct - { - Color Background; ///< Color of the window's background | Default: Black - Color KeyBackground; ///< Color of the key's background | Default: Black - Color KeyBackgroundPressed; ///< Color of the key's background while pressed | Default: Silver - Color KeyText; ///< Color of the key's text | Default: Blank - Color KeyTextPressed; ///< Color of the key's text while pressed | Default: Blank - Color Cursor; ///< Color of the cursor | Default: Blank - Color Input; ///< Color of the input | Default: Blank - } Keyboard; - - // Custom Keyboard colors - struct - { - Color BackgroundMain; ///< The color of the background | Default: Black - Color BackgroundSecondary; ///< The color of the background 2 | Default: black/grey (RGB: 15, 15, 15) - Color BackgroundBorder; ///< The color of the border around the window | Default: Blank - Color KeyBackground; ///< Color of the background of a key | Default: sort of Grey (51, 51, 51) - Color KeyBackgroundPressed; ///< Color of the background of a key when it's being touched | Default: Gainsboro - Color KeyText; ///< Color of the text of a key | Default: Blank - Color KeyTextPressed; ///< Color of the text of a key when being touched | Default: Black - Color ScrollBarBackground; ///< Color of the scrollbar's background | Default: Silver - Color ScrollBarThumb; ///< Color of the scrollbar's thumb | Default: DimGrey - } CustomKeyboard; - - /** - * \brief Returns a reference to the FwkSettings instance used by the framework - * Allows runtime theme edition - * \return The instance of FwkSettings - */ - static FwkSettings& Get(void); - static PluginHeader *Header; - - /** - * \brief Reset all colors to their default values - */ - static void SetThemeDefault(void); - }; -} - -#endif diff --git a/Includes/CTRPluginFramework/System/Hook.hpp b/Includes/CTRPluginFramework/System/Hook.hpp deleted file mode 100644 index 71f6087..0000000 --- a/Includes/CTRPluginFramework/System/Hook.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_SYSTEM_HOOK_H -#define CTRPLUGINFRAMEWORK_SYSTEM_HOOK_H - -#include "types.h" - -namespace CTRPluginFramework -{ - union HookStatus - { - struct - { - bool isEnabled : 1; ///< Hold the hook's status - bool useLinkRegisterToReturn : 1; ///< Enable the use of bx lr to return from callback. LR will be properly restored after the callback is executed | Default: true - bool ExecuteOverwrittenInstructionBeforeCallback : 1; ///< If the instruction overwriten by the hook (target) must be executed before the callback | Default: true - bool ExecuteOverwrittenInstructionAfterCallback : 1; ///< If the instruction overwritten by the hook (target) must be executed after the callback | Default: false - }; - u32 raw; - }; - - enum class HookResult - { - Success, - InvalidAddress, ///< The target address was not reachable - AddressAlreadyHooked, ///< A hook is already enabled to the same address - TooManyHooks, ///< You attained the maximum of enabled hooks (current limit: 91) - HookParamsError, ///< The parameters of your hook seems off - TargetInstructionCannotBeHandledAutomatically ///< The target's instruction is position dependant (PC) hence using ExecuteOverwrittenInstructionBeforeCallback or ExecuteOverwrittenInstructionAfterCallback is impossible. - }; - - struct Hook - { - HookStatus flags{}; ///< See HookStatus - u32 targetAddress; ///< The address to hook from - u32 returnAddress; ///< The address to return to after callback | Default: targetAddress + 4 - u32 callbackAddress; ///< The address of the callback - u32 overwrittenInstr; - u32 index; - - Hook(); - - /** - * \brief Initialize hook target and callback - * \param targetAddr The address to hook from - * \param callbackAddr The callback to be called by the hook - * \param returnAddr Optional return address. If not passed (0) then the return address is targetAddr + 4 - */ - void Initialize(u32 targetAddr, u32 callbackAddr, u32 returnAddr = 0); - - /** - * \brief Apply the hook - * \return Return the result of the operation (see HookResult for more infos) - */ - HookResult Enable(void); - - /** - * \brief Disable the hook - */ - void Disable(void); - }; -} - -#endif diff --git a/Includes/CTRPluginFramework/System/Lock.hpp b/Includes/CTRPluginFramework/System/Lock.hpp deleted file mode 100644 index 021e052..0000000 --- a/Includes/CTRPluginFramework/System/Lock.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_SYSTEM_LOCK_HPP -#define CTRPLUGINFRAMEWORK_SYSTEM_LOCK_HPP - -#include "ctrulib/synchronization.h" - -namespace CTRPluginFramework -{ - class Mutex; - class Lock - { - public: - explicit Lock(LightLock &llock); - explicit Lock(RecursiveLock &rlock); - explicit Lock(Mutex &mutex); - - ~Lock(void); - - private: - int _type; - union - { - LightLock *_llock; - RecursiveLock *_rlock; - Mutex *_mutex; - }; - }; -} - -#endif diff --git a/Includes/CTRPluginFramework/System/Mutex.hpp b/Includes/CTRPluginFramework/System/Mutex.hpp deleted file mode 100644 index 04732c3..0000000 --- a/Includes/CTRPluginFramework/System/Mutex.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_SYSTEM_MUTEX_HPP -#define CTRPLUGINFRAMEWORK_SYSTEM_MUTEX_HPP - -#include "ctrulib/synchronization.h" - -namespace CTRPluginFramework -{ - class Mutex - { - public: - Mutex(void); - ~Mutex(void); - - void Lock(void); - // Return true on failure - bool TryLock(void); - void Unlock(void); - - private: - RecursiveLock _lock; - }; -} - -#endif diff --git a/Includes/CTRPluginFramework/System/Process.hpp b/Includes/CTRPluginFramework/System/Process.hpp deleted file mode 100644 index aa99509..0000000 --- a/Includes/CTRPluginFramework/System/Process.hpp +++ /dev/null @@ -1,284 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_PROCESS_HPP -#define CTRPLUGINFRAMEWORK_PROCESS_HPP - -#include "ctrulib/svc.h" -#include - -namespace CTRPluginFramework -{ - enum class StringFormat - { - Utf8, - Utf16, - Utf32 - }; - - class Process - { - public: - - /** - * \brief Get current process handle (already open, don't close it) - * \return Return current process handle (already open, don't close it) - */ - static Handle GetHandle(void); - - /** - * \brief Get current process ID - * \return Return current process ID - */ - static u32 GetProcessID(void); - - /** - * \brief Get the title ID of the current process - * \return TitleID of the current process - */ - static u64 GetTitleID(void); - - /** - * \brief Get the title ID of the current process as string - * \param output std::string to append the titleid to \n - * output isn't clear - */ - static void GetTitleID(std::string &output); - - /** - * \brief Get the name of the current process - * \param output string to output the process name - */ - static void GetName(std::string &output); - - /** - * \brief Get the version of the current process - * \return The version of the current processs - */ - static u16 GetVersion(void); - - /** - * \brief Get the total size of the .text section - * \return The total size of the .text section - */ - static u32 GetTextSize(void); - - /** - * \brief Check if the process is currently paused by the framework\n - * (Like when a Keyboard, MessageBox or the menu is open) - * \return true if the process is paused - */ - static bool IsPaused(void); - - /** - * \brief Pause the process at the next frame - */ - static void Pause(void); - - /** - * \brief Resume the process - * \param frames If a number is specified the process will play x frames - * before being paused again - * Please be aware that giving a frame count will not release the process - */ - static void Play(const u32 frames = 0); - - /** - * \brief Safely patch the current process (MemPerm check and Invalidate cache) - * \param addr The address to start the patch - * \param patch The patch values - * \param length The length of the patch values in bytes - * \param original If defined, the original values will be copied to this buffer (size must be enough) - * \return If the patch was successful or not - */ - static bool Patch(u32 addr, void *patch, u32 length, void *original = nullptr); - - /** - * \brief Safely patch the current process (MemPerm check and Invalidate cache) - * \param addr The address to start the patch - * \param patch The patch value - * \param original If defined, the original values will be copied to this buffer (size must be enough) - * \return If the patch was successful or not - */ - static bool Patch(u32 addr, u32 patch, void *original = nullptr); - - - /** - * \brief Protect the memory by settings Read & Write perm - * \param addr Address from start protecting - * \param size Size to protect - * \param perm The permission to apply (RWX by default) - * \return If the protection was successful or not - */ - static bool ProtectMemory(u32 addr, u32 size, int perm = (MEMPERM_READ | MEMPERM_WRITE |MEMPERM_EXECUTE)); - - - /** - * \brief Protect the entire region where addr belongs to - * \param addr An address - * \param perm The permissions that must be applied to the region - * \return If the protection was successful or not - */ - static bool ProtectRegion(u32 addr, int perm = (MEMPERM_READ | MEMPERM_WRITE |MEMPERM_EXECUTE)); - - /** - * \brief Protect all regions within the provided range - * \param startAddress The address from the range starts - * \param endAddress The address from the range ends - * \param perm The permissions that muse be applied to the regions - */ - static void ProtectRegionInRange(u32 startAddress, u32 endAddress, int perm = (MEMPERM_READ | MEMPERM_WRITE |MEMPERM_EXECUTE)); - - /** - * \brief Safely copy the current process memory (MemPerm check) \n Like a memcpy but safe - * \param dst The destination to copy to - * \param src The source to copy from - * \param size The size to copy in bytes - * \return - */ - static bool CopyMemory(void *dst, const void *src, u32 size); - - /** - * \brief Check if the address is available and have the specified permissions \n - * If the address exists but don't have the specified permissions, it tries to change the permissions - * \param address The address to check - * \param perm The permissions that the address must have - * \return If the address is valid and have the specified permissions or not - */ - static bool CheckAddress(u32 address, u32 perm = MEMPERM_READ | MEMPERM_WRITE); - - /** - * \brief Check if the region which the address is from is available and have the specified permissions \n - * If the region exists but don't have the specified permissions, it tries to change the permissions - * \param address The address to check - * \param size A reference to get the region's size - * \param perm The permissions that the region must have - * \return If the region is valid and have the specified permissions or not - */ - static bool CheckRegion(u32 address, u32& size, u32 perm = MEMPERM_READ | MEMPERM_WRITE); - - /** - * \brief Safely write 64 bits - * \param address Address to write to - * \param value The value to write - * \return True if success, false otherwise - */ - static bool Write64(u32 address, u64 value); - - /** - * \brief Safely write 32 bits - * \param address Address to write to - * \param value The value to write - * \return True if success, false otherwise - */ - static bool Write32(u32 address, u32 value); - - /** - * \brief Safely write 16 bits - * \param address Address to write to - * \param value The value to write - * \return True if success, false otherwise - */ - static bool Write16(u32 address, u16 value); - - /** - * \brief Safely write 8 bits - * \param address Address to write to - * \param value The value to write - * \return True if success, false otherwise - */ - static bool Write8(u32 address, u8 value); - - /** - * \brief Safely write a float value - * \param address Address to write to - * \param value The value to write - * \return True if success, false otherwise - */ - static bool WriteFloat(u32 address, float value); - - /** - * \brief Safely write a double value - * \param address Address to write to - * \param value The value to write - * \return True if success, false otherwise - */ - static bool WriteDouble(u32 address, double value); - - /** - * \brief Safely read 64 bits - * \param address The address to read - * \param value The variable to put the value in - * \return True if success, false otherwise - */ - static bool Read64(u32 address, u64 &value); - - /** - * \brief Safely read 32 bits - * \param address The address to read - * \param value The variable to put the value in - * \return True if success, false otherwise - */ - static bool Read32(u32 address, u32 &value); - - /** - * \brief Safely read 16 bits - * \param address The address to read - * \param value The variable to put the value in - * \return True if success, false otherwise - */ - static bool Read16(u32 address, u16 &value); - - /** - * \brief Safely read 8 bits - * \param address The address to read - * \param value The variable to put the value in - * \return True if success, false otherwise - */ - static bool Read8(u32 address, u8 &value); - - /** - * \brief Safely read a float value - * \param address The address to read - * \param value The variable to put the value in - * \return True if success, false otherwise - */ - static bool ReadFloat(u32 address, float &value); - - /** - * \brief Safely read a double value - * \param address The address to read - * \param value The variable to put the value in - * \return True if success, false otherwise - */ - static bool ReadDouble(u32 address, double &value); - - /** - * \brief Read a string from the desired address and convert it to utf8 - * \param address The address to read the string from - * \param output The std::string object with the utf8 string - * \param size The size in bytes to read from the address - * \param format The input format to do the conversion - * \return true if the read is successful, false otherwise - */ - static bool ReadString(u32 address, std::string &output, u32 size, StringFormat format); - - /** - * \brief Write a utf8 string to an address and do the conversion if needed - * \param address The address to write the string to - * \param input The string to write - * \param outFmt The desired output format - * \return true if the write is successful, false otherwise - */ - static bool WriteString(u32 address, const std::string &input, StringFormat outFmt = StringFormat::Utf8); - - /** - * \brief Write a utf8 string to an address and do the conversion if specified - * \param address The address to write the string to - * \param input The string to write - * \param size The number of bytes to write, last is null terminator - * \param outFmt The desired output format - * \return true if the write is successful, false otherwise - */ - static bool WriteString(u32 address, const std::string &input, u32 size, StringFormat outFmt = StringFormat::Utf8); - }; -} - -#endif diff --git a/Includes/CTRPluginFramework/System/Rect.hpp b/Includes/CTRPluginFramework/System/Rect.hpp deleted file mode 100644 index 8a803c6..0000000 --- a/Includes/CTRPluginFramework/System/Rect.hpp +++ /dev/null @@ -1,147 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_RECT_HPP -#define CTRPLUGINFRAMEWORK_RECT_HPP - -#include "CTRPluginFramework/System/Vector.hpp" -#include - -namespace CTRPluginFramework -{ - template - class Rect - { - public: - Rect(); - Rect(const Vector& leftTop, const Vector& size); - Rect(const Vector& leftTop, T width, T height); - Rect(T left, T top, const Vector& size); - Rect(T left, T top, T width, T height); - template - explicit Rect(const Rect& rect); - - bool Contains(T x, T y) const; - bool Contains(const Vector& point) const; - bool Intersects(const Rect& rect) const; - bool Intersects(const Rect& rect, Rect& intersect) const; - - Vector leftTop; - Vector size; - }; - - template - Rect::Rect() : leftTop(0, 0), size(0, 0) - { - - } - - template - Rect::Rect(const Vector& leftTopCorner, const Vector& size) - { - leftTop = leftTopCorner; - this->size = size; - } - - template - Rect::Rect(const Vector& leftTopCorner, T width, T height) - { - leftTop = leftTopCorner; - size.x = width; - size.y = height; - } - - template - Rect::Rect(T left, T top, const Vector& size) - { - leftTop.x = left; - leftTop.y = top; - this->size = size; - } - - template - Rect::Rect(T left, T top, T width, T height) - { - leftTop.x = left; - leftTop.y = top; - size.x = width; - size.y = height; - } - - template - template - Rect::Rect(const Rect& rect) - { - leftTop = reinterpret_cast(rect.leftTop); - size = reinterpret_cast(rect.size); - } - - template - bool Rect::Contains(T x, T y) const - { - T minX = std::min(leftTop.x, leftTop.x + size.x); - T maxX = std::max(leftTop.x, leftTop.x + size.x); - T minY = std::min(leftTop.y, leftTop.y + size.y); - T maxY = std::max(leftTop.y, leftTop.y + size.y); - - return (x >= minX && x < maxX - && y >= minY && y < maxY); - } - - template - bool Rect::Contains(const Vector& point) const - { - return (Contains(point.x, point.y)); - } - - template - bool Rect::Intersects(const Rect& rect) const - { - Rect intersect; - return (Intersects(rect, intersect)); - } - - template - bool Rect::Intersects(const Rect &rect, Rect &intersect) const - { - T thisMinX = std::min(leftTop.x, leftTop.x + size.x); - T thisMaxX = std::max(leftTop.x, leftTop.x + size.x); - T thisMinY = std::min(leftTop.y, leftTop.y + size.y); - T thisMaxY = std::max(leftTop.y, leftTop.y + size.y); - T rectMinX = std::min(rect.leftTop.x, rect.leftTop.x + rect.size.x); - T rectMaxX = std::max(rect.leftTop.x, rect.leftTop.x + rect.size.x); - T rectMinY = std::min(rect.leftTop.y, rect.leftTop.y + rect.size.y); - T rectMaxY = std::max(rect.leftTop.y, rect.leftTop.y + rect.size.y); - - T intersectLeftX = std::max(thisMinX, rectMinX); - T intersectLeftY = std::max(thisMinY, rectMinY); - T intersectRightX = std::min(thisMaxX, rectMaxX); - T intersectRightY = std::min(thisMaxY, rectMaxY); - - if (intersectLeftX < intersectRightX && intersectLeftY < intersectRightY) - { - intersect = Rect(intersectLeftX, intersectLeftY, intersectRightX - intersectLeftX, - intersectRightY - intersectLeftY); - return (true); - } - intersect = Rect(0, 0, 0, 0); - return (false); - } - - template - bool operator ==(Rect &left, Rect &right) - { - return (left.leftTop == right.leftTop - && left.size == right.size); - } - - template - bool operator !=(Rect &left, Rect &right) - { - return (left.leftTop != right.leftTop - && left.size != right.size); - } - - typedef Rect UIntRect; - typedef Rect IntRect; - typedef Rect FloatRect; -} - -#endif \ No newline at end of file diff --git a/Includes/CTRPluginFramework/System/Sleep.hpp b/Includes/CTRPluginFramework/System/Sleep.hpp deleted file mode 100644 index a40baac..0000000 --- a/Includes/CTRPluginFramework/System/Sleep.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_SLEEP_HPP -#define CTRPLUGINFRAMEWORK_SLEEP_HPP - - -namespace CTRPluginFramework -{ - class Time; - - void Sleep(Time sleepTime); -} - -#endif diff --git a/Includes/CTRPluginFramework/System/System.hpp b/Includes/CTRPluginFramework/System/System.hpp deleted file mode 100644 index 7a4cb6d..0000000 --- a/Includes/CTRPluginFramework/System/System.hpp +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_SYSTEM_SYSTEM_HPP -#define CTRPLUGINFRAMEWORK_SYSTEM_SYSTEM_HPP - -#include "types.h" - -namespace CTRPluginFramework -{ - enum class LanguageId - { - Japanese = 0, - English, - French, - German, - Italian, - Spanish, - ChineseSimplified, - Korean, - Dutch, - Portugese, - Russian, - ChineseTraditional - }; - - class System - { - public: - - /** - * \brief Check if the current console is a New3DS - * \return true if the current console is a New3DS,\n false otherwise - */ - static bool IsNew3DS(void); - - /** - * \brief Get the system's language (user defined) - * \return The language of the system - */ - static LanguageId GetSystemLanguage(void); - - /** - * \brief Get if the 3DS is connected to Internet - * \return true if connected \n false if not connected - */ - static bool IsConnectedToInternet(void); - - /** - * \brief Check if the cfw is Luma3DS or not\n - * A version number can be passed and if it's the case the function will return whether the version of the cfw is the same or higher (true) or inferior (false) - * \param major An optional version - * \param minor An optional version - * \param revision An optional version - * \return If the cfw is Luma3DS or not - */ - static bool CfwIsLuma3DS(u8 major = 0, u8 minor = 0, u8 revision = 0); - - /** - * \brief A callback that will be called in std::abort if set - */ - static void (*OnAbort)(void); - }; -} - -#endif diff --git a/Includes/CTRPluginFramework/System/Task.hpp b/Includes/CTRPluginFramework/System/Task.hpp deleted file mode 100644 index 31a66c1..0000000 --- a/Includes/CTRPluginFramework/System/Task.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_SYSTEM_TASK_HPP -#define CTRPLUGINFRAMEWORK_SYSTEM_TASK_HPP - -#include "types.h" -#include "ctrulib/synchronization.h" - -namespace CTRPluginFramework -{ - using TaskFunc = s32 (*)(void *); - - struct TaskContext - { - int refcount{0}; - u32 flags{0}; - s32 affinity{-1}; - s32 result{0}; - void * arg{nullptr}; - TaskFunc func{nullptr}; - LightEvent event{}; - }; - - struct Task - { - enum - { - Idle = 0, - Scheduled = 1, - Processing = 2, - Finished = 4 - }; - - enum - { - AppCore = 1 << 0, - SysCore = 1 << 1, - NewAppCore = 1 << 2, - NewSysCore = 1 << 3, - - AppCores = AppCore | NewAppCore, - SysCores = SysCore | NewSysCore, - AllCores = AppCores | SysCores - }; - - TaskContext *context; - - explicit Task(TaskFunc func, void *arg = nullptr, s32 affinity = -1); - Task(const Task &task); - Task(Task &&task) noexcept; - ~Task(void); - - Task &operator=(const Task &right) = delete; - - /** - * \brief Schedule a Task and starts it - * \return 0 on operation success - */ - int Start(void) const; - - /** - * \brief Wait for the Task to be completed - * \return The result of the Task (returned by TaskFunc) - */ - s32 Wait(void) const; - - /** - * \brief Get the current status of the Task - * \return Task status (see enum) - */ - u32 Status(void) const; - }; -} - -#endif diff --git a/Includes/CTRPluginFramework/System/Time.hpp b/Includes/CTRPluginFramework/System/Time.hpp deleted file mode 100644 index 37f4a91..0000000 --- a/Includes/CTRPluginFramework/System/Time.hpp +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_TIME_HPP -#define CTRPLUGINFRAMEWORK_TIME_HPP - -namespace CTRPluginFramework -{ - class Time - { - public : - - Time(void); - - - float AsSeconds(void) const; - - int AsMilliseconds(void) const; - - s64 AsMicroseconds(void) const; - - - static const Time Zero; ///< Predefined "zero" time value - - private : - - friend Time Seconds(float amount); - friend Time Milliseconds(int amount); - friend Time Microseconds(s64 amount); - - explicit Time(s64 microseconds); - - private : - - - s64 _microseconds; - }; - - - Time Seconds(float amount); - - - Time Milliseconds(int amount); - - - Time Microseconds(s64 amount); - - bool operator ==(Time left, Time right); - - - bool operator !=(Time left, Time right); - - - bool operator <(Time left, Time right); - - - bool operator >(Time left, Time right); - - - bool operator <=(Time left, Time right); - - - bool operator >=(Time left, Time right); - - - Time operator -(Time right); - - - Time operator +(Time left, Time right); - - - Time& operator +=(Time& left, Time right); - - - Time operator -(Time left, Time right); - - - Time& operator -=(Time& left, Time right); - - - Time operator *(Time left, float right); - - - Time operator *(Time left, s64 right); - - - Time operator *(float left, Time right); - - - Time operator *(s64 left, Time right); - - - Time& operator *=(Time& left, float right); - - - Time& operator *=(Time& left, s64 right); - - - Time operator /(Time left, float right); - - - Time operator /(Time left, s64 right); - - - Time& operator /=(Time& left, float right); - - - Time& operator /=(Time& left, s64 right); - - - float operator /(Time left, Time right); - - - Time operator %(Time left, Time right); - - - Time& operator %=(Time& left, Time right); - -} - -#endif diff --git a/Includes/CTRPluginFramework/System/Touch.hpp b/Includes/CTRPluginFramework/System/Touch.hpp deleted file mode 100644 index f38e5a2..0000000 --- a/Includes/CTRPluginFramework/System/Touch.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_TOUCH_HPP -#define CTRPLUGINFRAMEWORK_TOUCH_HPP - -#include "Vector.hpp" - -namespace CTRPluginFramework -{ - class Touch - { - public: - static bool IsDown(void); - static UIntVector GetPosition(void); - }; -} - -#endif \ No newline at end of file diff --git a/Includes/CTRPluginFramework/System/Vector.hpp b/Includes/CTRPluginFramework/System/Vector.hpp deleted file mode 100644 index f99855d..0000000 --- a/Includes/CTRPluginFramework/System/Vector.hpp +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_VECTOR_HPP -#define CTRPLUGINFRAMEWORK_VECTOR_HPP - -#include "types.h" - -namespace CTRPluginFramework -{ - template - class Vector - { - public: - Vector(); - Vector(T x, T y); - template - explicit Vector(const Vector &vector); - - T x; - T y; - }; - - template - Vector::Vector() : x(0), y(0) - { - - } - - template - Vector::Vector(T x, T y) : x(x), y(y) - { - - } - - template - template - Vector::Vector(const Vector &vector) : x(static_cast(vector.x)), y(static_cast(vector.y)) - { - - } - - template - Vector operator - (const Vector &vector) - { - return (Vector(-vector.x, -vector.y)); - } - - template - Vector operator - (const Vector &left, const Vector &right) - { - return (Vector(left.x - right.x, left.y - right.y)); - } - - template - Vector &operator -= (const Vector &left, const Vector &right) - { - left.x -= right.x; - left.y -= right.y; - return (left); - } - - template - Vector operator + (const Vector &left, const Vector &right) - { - return (Vector(left.x + right.x, left.y + right.y)); - } - - template - Vector &operator += (const Vector &left, const Vector &right) - { - left.x += right.x; - left.y += right.y; - return (left); - } - - template - Vector operator * (const Vector &left, T right) - { - return (Vector(left.x * right, left.y * right)); - } - - template - Vector operator * (const T left, const Vector &right) - { - return (Vector(right.x * left, right.y * left)); - } - - template - Vector &operator *= (Vector &left, const T right) - { - left.x *= right; - left.y *= right; - return (left); - } - - template - Vector operator / (const Vector &left, const T right) - { - return (Vector(left.x / right, left.y / right)); - } - - template - Vector &operator /= (Vector &left, const T right) - { - left.x /= right; - left.y /= right; - return (left); - } - - template - bool operator <= (const Vector &left, const Vector &right) - { - return (left.x <= right.x - && left.y <= right.y); - } - - template - bool operator >= (const Vector &left, const Vector &right) - { - return (left.x >= right.x - && left.y >= right.y); - } - - typedef Vector UIntVector; - typedef Vector IntVector; - typedef Vector FloatVector; -} - -#endif \ No newline at end of file diff --git a/Includes/CTRPluginFramework/Utils.hpp b/Includes/CTRPluginFramework/Utils.hpp deleted file mode 100644 index 4b0f0bb..0000000 --- a/Includes/CTRPluginFramework/Utils.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_UTILS_HPP -#define CTRPLUGINFRAMEWORK_UTILS_HPP - -#include "CTRPluginFramework/Utils/LineReader.hpp" -#include "CTRPluginFramework/Utils/LineWriter.hpp" -#include "CTRPluginFramework/Utils/Utils.hpp" -#include "CTRPluginFramework/Utils/StringExtensions.hpp" - -#endif diff --git a/Includes/CTRPluginFramework/Utils/LineReader.hpp b/Includes/CTRPluginFramework/Utils/LineReader.hpp deleted file mode 100644 index b870e12..0000000 --- a/Includes/CTRPluginFramework/Utils/LineReader.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_UTILS_LINEREADER_HPP -#define CTRPLUGINFRAMEWORK_UTILS_LINEREADER_HPP - -#include "types.h" -#include - -namespace CTRPluginFramework -{ - class File; - class LineReader - { - public: - LineReader(File &file); - ~LineReader(void); - - // Return true if a line was read - bool operator()(std::string &line); - - private: - File &_file; - u32 _offsetInBuffer; - u32 _dataInBuffer; - char *_buffer; - }; -} - -#endif \ No newline at end of file diff --git a/Includes/CTRPluginFramework/Utils/LineWriter.hpp b/Includes/CTRPluginFramework/Utils/LineWriter.hpp deleted file mode 100644 index 9e8fbdc..0000000 --- a/Includes/CTRPluginFramework/Utils/LineWriter.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_LINEWRITER_HPP -#define CTRPLUGINFRAMEWORK_LINEWRITER_HPP - -#include "types.h" -#include -#include "CTRPluginFramework/Utils/StringExtensions.hpp" - -namespace CTRPluginFramework -{ - class File; - class LineWriter - { - public: - LineWriter(File &output); - LineWriter(const LineWriter &right) = delete; - LineWriter(LineWriter &&right) = delete; - ~LineWriter(void); - - LineWriter & operator<<(const std::string &input); - LineWriter & operator=(const LineWriter &right) = delete; - LineWriter & operator=(LineWriter &&right) = delete; - - static const std::string &endl(void); - void Flush(void); - void Close(void); - - private: - File &_output; - u32 _offsetInBuffer; - u8 *_buffer; - }; -} - -#endif diff --git a/Includes/CTRPluginFramework/Utils/StringExtensions.hpp b/Includes/CTRPluginFramework/Utils/StringExtensions.hpp deleted file mode 100644 index a3e2ecb..0000000 --- a/Includes/CTRPluginFramework/Utils/StringExtensions.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_UTILS_STRINGEXTENSIONS_HPP -#define CTRPLUGINFRAMEWORK_UTILS_STRINGEXTENSIONS_HPP - -#include "CTRPluginFramework/Graphics/Color.hpp" -#include -#include - -namespace CTRPluginFramework -{ - // Return a string with the charcter that reset the color (0x18) - std::string ResetColor(void); - - std::string operator <<(const std::string &left, const char *right); - std::string operator <<(const std::string &left, const std::string &right); - - template ::value - && !std::is_same::value - >::type* = nullptr> - std::string operator <<(const std::string &left, T right) - { - return (left + std::to_string(right)); - } -} - -#endif diff --git a/Includes/CTRPluginFramework/Utils/Utils.hpp b/Includes/CTRPluginFramework/Utils/Utils.hpp deleted file mode 100644 index 0a94177..0000000 --- a/Includes/CTRPluginFramework/Utils/Utils.hpp +++ /dev/null @@ -1,149 +0,0 @@ -#ifndef CTRPLUGINFRAMEWORK_UTILS_UTILS_HPP -#define CTRPLUGINFRAMEWORK_UTILS_UTILS_HPP - -#include "types.h" - -#include "CTRPluginFramework/System/Process.hpp" - -#include -#include -#include - -namespace CTRPluginFramework -{ - class Color; - class Utils - { - public: - - /** - * \brief Get a string formatted with format specifier from printf - * \param fmt String to be formatted - * \param ... Addtionnal arguments - * \return The formatted std::string - */ - static std::string Format(const char *fmt, ...); - - /** - * \brief Get the hexadecimal representation of a value - * \param value The value to convert - * \return An std::string with the the hexadecimal representation of value - */ - static std::string ToHex(u32 value); - - /** - * \brief Get the string representation of a float value - * \param fpval The value to convert - * \param precision The number of digit after the . - * \return An std::string with the representation of the value\n - * Values between -999999.f && 999999.f will be a fixed representation \n - * while anything lower / higher will be a scientific representation - */ - static std::string ToString(float fpval, int precision = 2); - - /** - * \brief Get a random number - * \return A random number - */ - static u32 Random(void); - - /** - * \brief Get a random number - * \param min Minimu value for the random number - * \param max Maximum value for the random number - * \return A random number between min & max - */ - static u32 Random(u32 min, u32 max); - - /** - * \brief Get the size of an utf8 std::string (max size 0x100) - * \param str The string to count - * \return The count of utf8 chars in the str - */ - static u32 GetSize(const std::string &str); - - - /** - * \brief Open a menu which allow to browse the SD card to select a file - * \param out The absolute path of the selected file - * \param filter If the files must be filtered (can be an extension or a pattern that must be present in the filename) - * \return -1 if the user aborted the operation, 0 on success - */ - static int FilePicker(std::string &out, const std::string &filter = ""); - - /** - * \brief Open a menu which allow to browse the SD card to select a Directory - * \param out The absolute path of the selected directory - * \return -1 if the user aborted the operation, 0 on success - */ - static int DirectoryPicker(std::string &out); - - /** - * \brief Remove the last char of an utf8 string (max size 0x100) - * \param str The string to remove the char from - * \return The codepoint value of the char removed - */ - static u32 RemoveLastChar(std::string &str); - - template - static u32 Search(const u32 start, const u32 size, const std::vector &pattern) - { - if (!start || !size || pattern.empty()) - return (0); - - const u32 patternSize = pattern.size() * sizeof(T); - const u8 *patternc = reinterpret_cast(pattern.data()); - const u8 *startPos = reinterpret_cast(start); - - u32 table[256]; - - for (u32 i = 0; i < 256; i++) - table[i] = patternSize; - - for (u32 i = 0; i < patternSize - 1; i++) - table[patternc[i]] = patternSize - i - 1; - - u32 j = 0; - while (j <= size - patternSize) - { - const u8 c = startPos[j + patternSize - 1]; - if (patternc[patternSize - 1] == c && std::memcmp(patternc, startPos + j, patternSize - 1) == 0) - return (reinterpret_cast(startPos + j)); - j += table[c]; - } - return (0); - } - - template - static u32 Rsearch(const u32 start, const u32 size, const std::vector &pattern) - { - if (!start || !size || pattern.empty()) - return (0); - - const u32 patternSize = pattern.size() * sizeof(T); - const u8 *patternc = reinterpret_cast(pattern.data()); - const u8 *startPos = reinterpret_cast(start); - - u32 table[256]; - - for (u32 i = 0; i < 256; i++) - table[i] = patternSize; - - for (u32 i = 0; i < patternSize - 1; i++) - table[patternc[i]] = patternSize - i - 1; - - u32 j = 0; - u32 last = 0; - while (j <= size - patternSize) - { - const u8 c = startPos[j + patternSize - 1]; - if (patternc[patternSize - 1] == c && std::memcmp(patternc, startPos + j, patternSize - 1) == 0) - last = reinterpret_cast(startPos + j); - j += table[c]; - } - return (last); - } - }; -} - -#endif \ No newline at end of file diff --git a/Includes/Helpers.hpp b/Includes/Helpers.hpp new file mode 100644 index 0000000..4c46fe8 --- /dev/null +++ b/Includes/Helpers.hpp @@ -0,0 +1,13 @@ +#ifndef HELPERS_HPP +#define HELPERS_HPP + +#include "Helpers/AutoRegion.hpp" +#include "Helpers/HoldKey.hpp" +#include "Helpers/KeySequence.hpp" +#include "Helpers/MenuEntryHelpers.hpp" +#include "Helpers/OSDManager.hpp" +#include "Helpers/QuickMenu.hpp" +#include "Helpers/Strings.hpp" +#include "Helpers/Wrappers.hpp" + +#endif diff --git a/Includes/Helpers/OSDManager.hpp b/Includes/Helpers/OSDManager.hpp index ff43e30..964fcfb 100644 --- a/Includes/Helpers/OSDManager.hpp +++ b/Includes/Helpers/OSDManager.hpp @@ -1,7 +1,7 @@ #ifndef OSD_MANAGER_HPP #define OSD_MANAGER_HPP -#include "3DS.h" +#include <3ds.h> #include "CTRPluginFramework.hpp" #include diff --git a/Includes/csvc.h b/Includes/csvc.h index c79f358..1acbdc8 100644 --- a/Includes/csvc.h +++ b/Includes/csvc.h @@ -20,7 +20,7 @@ extern "C" { #endif -#include "types.h" +#include #define PA_RWX(add) (add == 0 ? 0 : (add < 0x30000000 ? (u32)((add) | (1u << 31)) : add)) #define PA_FROM_VA(addr) PA_RWX(svcConvertVAToPA((void *)addr, false)) @@ -78,18 +78,20 @@ void svcInvalidateEntireInstructionCache(void); ///@{ /** * @brief Maps a block of process memory. - * @param process Handle of the process. - * @param destAddress Address of the mapped block in the current process. - * @param srcAddress Address of the mapped block in the source process. - * @param size Size of the block of the memory to map (truncated to a multiple of 0x1000 bytes). + * @param dstProcessHandle Handle of the process to map the memory in (destination) + * @param destAddress Start address of the memory block in the destination process + * @param srcProcessHandle Handle of the process to map the memory from (source) + * @param srcAddress Start address of the memory block in the source process + * @param size Size of the block of the memory to map (truncated to a multiple of 0x1000 bytes) */ -Result svcMapProcessMemoryEx(Handle dstProcessHandle, u32 vaDst, Handle srcProcessHandle, u32 vaSrc, u32 size); +Result svcMapProcessMemoryEx(Handle dstProcessHandle, u32 destAddress, Handle srcProcessHandle, u32 srcAddress, u32 size); /** * @brief Unmaps a block of process memory. - * @param process Handle of the process. - * @param destAddress Address of the block of memory to unmap, in the current (destination) process. + * @param process Handle of the process to unmap the memory from + * @param destAddress Address of the block of memory to unmap * @param size Size of the block of memory to unmap (truncated to a multiple of 0x1000 bytes). + * This function should only be used to unmap memory mapped with svcMapProcessMemoryEx */ Result svcUnmapProcessMemoryEx(Handle process, u32 destAddress, u32 size); @@ -111,6 +113,20 @@ Result svcUnmapProcessMemoryEx(Handle process, u32 destAddress, u32 size); * @sa svcControlMemory */ Result svcControlMemoryEx(u32* addr_out, u32 addr0, u32 addr1, u32 size, MemOp op, MemPerm perm, bool isLoader); + +/** + * @brief Controls memory mapping, this version removes all checks which were being done + * The only operations supported are MEMOP_FREE, MEMOP_ALLOC and MEMOP_ALLOC_LINEAR + * All memory allocated with this svc, must be freed with this svc as well + * @param[out] addr_out The virtual address resulting from the operation. Usually the same as addr0. + * @param addr0 The virtual address to be used for the operation. + * @param size The requested size for @ref MEMOP_ALLOC and @ref MEMOP_ALLOC_LINEAR. + * @param op Operation flags. See @ref MemOp. + * @param perm A combination of @ref MEMPERM_READ and @ref MEMPERM_WRITE + * Value 0 is used when unmapping memory. + * @sa svcControlMemory + */ +Result svcControlMemoryUnsafe(u32 *out, u32 addr0, u32 size, MemOp op, MemPerm perm); ///@} ///@name System @@ -141,23 +157,34 @@ Result svcCopyHandle(Handle *out, Handle outProcess, Handle in, Handle inProcess * @param in The input handle. */ Result svcTranslateHandle(u32 *outKAddr, char *outClassName, Handle in); -///@} /// Operations for svcControlProcess typedef enum ProcessOp { PROCESSOP_GET_ALL_HANDLES, ///< List all handles of the process, varg3 can be either 0 to fetch all handles, or token of the type to fetch - ///< svcControlProcess(handle, PROCESSOP_GET_ALL_HANDLES, (u32)&outBuf, 0) - PROCESSOP_SET_MMU_TO_RWX, ///< Set the whole memory of the process with rwx access + ///< s32 count = svcControlProcess(handle, PROCESSOP_GET_ALL_HANDLES, (u32)&outBuf, 0) + ///< Returns how many handles were found + + PROCESSOP_SET_MMU_TO_RWX, ///< Set the whole memory of the process with rwx access (in the mmu table only) ///< svcControlProcess(handle, PROCESSOP_SET_MMU_TO_RWX, 0, 0) - PROCESSOP_GET_ON_MEMORY_CHANGE_EVENT, - PROCESSOP_GET_ON_EXIT_EVENT, - PROCESSOP_GET_PA_FROM_VA, ///< Get the physical address of the va within the process - ///< svcControlProcess(handle, PROCESSOP_GET_PA_FROM_VA, (u32)&outPa, va) - PROCESSOP_SCHEDULE_THREADS, + + PROCESSOP_GET_ON_MEMORY_CHANGE_EVENT, ///< Get the handle of an event which will be signaled each time the memory layout of this process changes + ///< svcControlProcess(handle, PROCESSOP_GET_ON_MEMORY_CHANGE_EVENT, &eventHandleOut, 0) + + PROCESSOP_SIGNAL_ON_EXIT, ///< Set a flag to be signaled when the process will be exited + ///< svcControlProcess(handle, PROCESSOP_SIGNAL_ON_EXIT, 0, 0) + PROCESSOP_GET_PA_FROM_VA, ///< Get the physical address of the VAddr within the process + ///< svcControlProcess(handle, PROCESSOP_GET_PA_FROM_VA, (u32)&PAOut, VAddr) + + PROCESSOP_SCHEDULE_THREADS, ///< Lock / Unlock the process's threads + ///< svcControlProcess(handle, PROCESSOP_SCHEDULE_THREADS, lock, threadPredicate) + ///< lock: 0 to unlock threads, any other value to lock threads + ///< threadPredicate: can be NULL or a funcptr to a predicate (typedef bool (*ThreadPredicate)(KThread *thread);) + ///< The predicate must return true to operate on the thread } ProcessOp; Result svcControlProcess(Handle process, ProcessOp op, u32 varg2, u32 varg3); +///@} #ifdef __cplusplus } diff --git a/Includes/ctrulib/allocator/linear.h b/Includes/ctrulib/allocator/linear.h deleted file mode 100644 index 1ae5a28..0000000 --- a/Includes/ctrulib/allocator/linear.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @file linear.h - * @brief Linear memory allocator. - */ -#pragma once -#ifdef __cplusplus -extern "C" { -#endif -/** - * @brief Allocates a 0x80-byte aligned buffer. - * @param size Size of the buffer to allocate. - * @return The allocated buffer. - */ -void* linearAlloc(size_t size); - -/** - * @brief Allocates a buffer aligned to the given size. - * @param size Size of the buffer to allocate. - * @param alignment Alignment to use. - * @return The allocated buffer. - */ -void* linearMemAlign(size_t size, size_t alignment); - -/** - * @brief Reallocates a buffer. - * Note: Not implemented yet. - * @param mem Buffer to reallocate. - * @param size Size of the buffer to allocate. - * @return The reallocated buffer. - */ -void* linearRealloc(void* mem, size_t size); - -/** - * @brief Frees a buffer. - * @param mem Buffer to free. - */ -void linearFree(void* mem); - -/** - * @brief Gets the current linear free space. - * @return The current linear free space. - */ -u32 linearSpaceFree(void); -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/Includes/ctrulib/allocator/mappable.h b/Includes/ctrulib/allocator/mappable.h deleted file mode 100644 index 826bc74..0000000 --- a/Includes/ctrulib/allocator/mappable.h +++ /dev/null @@ -1,24 +0,0 @@ -/** - * @file mappable.h - * @brief Mappable memory allocator. - */ -#pragma once - -/** - * @brief Allocates a page-aligned buffer. - * @param size Size of the buffer to allocate. - * @return The allocated buffer. - */ -void* mappableAlloc(size_t size); - -/** - * @brief Frees a buffer. - * @param mem Buffer to free. - */ -void mappableFree(void* mem); - -/** - * @brief Gets the current mappable free space. - * @return The current mappable free space. - */ -u32 mappableSpaceFree(void); diff --git a/Includes/ctrulib/allocator/newlibHeap.h b/Includes/ctrulib/allocator/newlibHeap.h deleted file mode 100644 index b492e49..0000000 --- a/Includes/ctrulib/allocator/newlibHeap.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef NEWLIBHEAP_H -#define NEWLIBHEAP_H -#ifdef __cplusplus -extern "C" { -#endif - -#include "types.h" - -u8 *getHeapStart(void); -u8 *getHeapEnd(void); -u8 *getHeapLimit(void); -int getMemUsed(void); -int getMemFree(void); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/Includes/ctrulib/allocator/vram.h b/Includes/ctrulib/allocator/vram.h deleted file mode 100644 index 5b964c3..0000000 --- a/Includes/ctrulib/allocator/vram.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @file vram.h - * @brief VRAM allocator. - */ -#pragma once -#ifdef __cplusplus -extern "C" { -#endif -/** - * @brief Allocates a 0x80-byte aligned buffer. - * @param size Size of the buffer to allocate. - * @return The allocated buffer. - */ -void* vramAlloc(size_t size); - -/** - * @brief Allocates a buffer aligned to the given size. - * @param size Size of the buffer to allocate. - * @param alignment Alignment to use. - * @return The allocated buffer. - */ -void* vramMemAlign(size_t size, size_t alignment); - -/** - * @brief Reallocates a buffer. - * Note: Not implemented yet. - * @param mem Buffer to reallocate. - * @param size Size of the buffer to allocate. - * @return The reallocated buffer. - */ -void* vramRealloc(void* mem, size_t size); - -/** - * @brief Frees a buffer. - * @param mem Buffer to free. - */ -void vramFree(void* mem); - -/** - * @brief Gets the current VRAM free space. - * @return The current VRAM free space. - */ -u32 vramSpaceFree(void); -#ifdef __cplusplus -} -#endif diff --git a/Includes/ctrulib/arpa/inet.h b/Includes/ctrulib/arpa/inet.h deleted file mode 100644 index 0db5c70..0000000 --- a/Includes/ctrulib/arpa/inet.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include -#include - -static inline uint32_t htonl(uint32_t hostlong) -{ - return __builtin_bswap32(hostlong); -} - -static inline uint16_t htons(uint16_t hostshort) -{ - return __builtin_bswap16(hostshort); -} - -static inline uint32_t ntohl(uint32_t netlong) -{ - return __builtin_bswap32(netlong); -} - -static inline uint16_t ntohs(uint16_t netshort) -{ - return __builtin_bswap16(netshort); -} - -#ifdef __cplusplus -extern "C" { -#endif - - in_addr_t inet_addr(const char *cp); - int inet_aton(const char *cp, struct in_addr *inp); - char* inet_ntoa(struct in_addr in); - - const char *inet_ntop(int af, const void * src, char * dst, socklen_t size); - int inet_pton(int af, const char * src, void * dst); - -#ifdef __cplusplus -} -#endif diff --git a/Includes/ctrulib/env.h b/Includes/ctrulib/env.h deleted file mode 100644 index 56807a7..0000000 --- a/Includes/ctrulib/env.h +++ /dev/null @@ -1,85 +0,0 @@ -/** - * @file env.h - * @brief Homebrew environment information. - */ -#ifndef ENV_H -#define ENV_H -#ifdef __cplusplus -extern "C" { -#endif -#include -#include "../types.h" - -/// System run-flags. -enum { - RUNFLAG_APTWORKAROUND = BIT(0), ///< Use APT workaround. - RUNFLAG_APTREINIT = BIT(1), ///< Reinitialize APT. -}; - -/** - * @brief Gets whether the application was launched from a homebrew environment. - * @return Whether the application was launched from a homebrew environment. - */ -static inline bool envIsHomebrew(void) { - extern void* __service_ptr; - return __service_ptr != NULL; -} - -/** - * @brief Retrieves a handle from the environment handle list. - * @param name Name of the handle. - * @return The retrieved handle. - */ -Handle envGetHandle(const char* name); - -/** - * @brief Gets the environment-recommended app ID to use with APT. - * @return The APT app ID. - */ -static inline u32 envGetAptAppId(void) { - //extern u32 __apt_appid; - //return __apt_appid; - return (0x300); -} - -/** - * @brief Gets the environment-recommended heap size. - * @return The heap size. - */ -static inline u32 envGetHeapSize(void) { - extern u32 __heap_size; - return __heap_size; -} - -/** - * @brief Gets the environment-recommended linear heap size. - * @return The linear heap size. - */ -static inline u32 envGetLinearHeapSize(void) { - extern u32 __linear_heap_size; - return __linear_heap_size; -} - -/** - * @brief Gets the environment argument list. - * @return The argument list. - */ -static inline const char* envGetSystemArgList(void) { - //extern const char* __system_arglist; - //return __system_arglist; - return (NULL); -} - -/** - * @brief Gets the environment run flags. - * @return The run flags. - */ -static inline u32 envGetSystemRunFlags(void) { - //extern u32 __system_runflags; - //return __system_runflags; - return (0); -} -#ifdef __cplusplus -} -#endif -#endif \ No newline at end of file diff --git a/Includes/ctrulib/errf.h b/Includes/ctrulib/errf.h deleted file mode 100644 index 3723716..0000000 --- a/Includes/ctrulib/errf.h +++ /dev/null @@ -1,122 +0,0 @@ -/** - * @file errf.h - * @brief Error Display API - */ - -#pragma once - -#include "types.h" - -/// Types of errors that can be thrown by err:f. -typedef enum { - ERRF_ERRTYPE_GENERIC = 0, ///< For generic errors. Shows miscellaneous info. - ERRF_ERRTYPE_MEM_CORRUPT = 1, ///< Same output as generic, but informs the user that "the System Memory has been damaged". - ERRF_ERRTYPE_CARD_REMOVED = 2, ///< Displays the "The Game Card was removed." message. - ERRF_ERRTYPE_EXCEPTION = 3, ///< For exceptions, or more specifically 'crashes'. union data should be exception_data. - ERRF_ERRTYPE_FAILURE = 4, ///< For general failure. Shows a message. union data should have a string set in failure_mesg - ERRF_ERRTYPE_LOGGED = 5, ///< Outputs logs to NAND in some cases. -} ERRF_ErrType; - -/// Types of 'Exceptions' thrown for ERRF_ERRTYPE_EXCEPTION -typedef enum { - ERRF_EXCEPTION_PREFETCH_ABORT = 0, ///< Prefetch Abort - ERRF_EXCEPTION_DATA_ABORT = 1, ///< Data abort - ERRF_EXCEPTION_UNDEFINED = 2, ///< Undefined instruction - ERRF_EXCEPTION_VFP = 3, ///< VFP (floating point) exception. -} ERRF_ExceptionType; - -typedef struct { - ERRF_ExceptionType type; ///< Type of the exception. One of the ERRF_EXCEPTION_* values. - u8 reserved[3]; - u32 fsr; ///< ifsr (prefetch abort) / dfsr (data abort) - u32 far; ///< pc = ifar (prefetch abort) / dfar (data abort) - u32 fpexc; - u32 fpinst; - u32 fpinst2; -} ERRF_ExceptionInfo; - -typedef struct { - ERRF_ExceptionInfo excep; ///< Exception info struct - CpuRegisters regs; ///< CPU register dump. -} ERRF_ExceptionData; - -typedef struct { - ERRF_ErrType type; ///< Type, one of the ERRF_ERRTYPE_* enum - u8 revHigh; ///< High revison ID - u16 revLow; ///< Low revision ID - u32 resCode; ///< Result code - u32 pcAddr; ///< PC address at exception - u32 procId; ///< Process ID. - u64 titleId; ///< Title ID. - u64 appTitleId; ///< Application Title ID. - union { - ERRF_ExceptionData exception_data; ///< Data for when type is ERRF_ERRTYPE_EXCEPTION - char failure_mesg[0x60]; ///< String for when type is ERRF_ERRTYPE_FAILURE - } data; ///< The different types of data for errors. -} ERRF_FatalErrInfo; - -/// Initializes ERR:f. Unless you plan to call ERRF_Throw yourself, do not use this. -Result errfInit(void); - -/// Exits ERR:f. Unless you plan to call ERRF_Throw yourself, do not use this. -void errfExit(void); - -/** - * @brief Gets the current err:f API session handle. - * @return The current err:f API session handle. - */ -Handle *errfGetSessionHandle(void); - -/** - * @brief Throws a system error and possibly results in ErrDisp triggering. - * @param[in] error Error to throw. - * - * After performing this, the system may panic and need to be rebooted. Extra information will be displayed on the - * top screen with a developer console or the proper patches in a CFW applied. - * - * The error may not be shown and execution aborted until errfExit(void) is called. - * - * You may wish to use ERRF_ThrowResult() or ERRF_ThrowResultWithMessage() instead of - * constructing the ERRF_FatalErrInfo struct yourself. - */ -Result ERRF_Throw(const ERRF_FatalErrInfo* error); - -/** - * @brief Throws a system error with the given Result code. - * @param[in] failure Result code to throw. - * - * This calls ERRF_Throw() with error type ERRF_ERRTYPE_GENERIC and fills in the required data. - * - * This function \em does fill in the address where this function was called from. - * - * See https://3dbrew.org/wiki/ERR:Throw#Generic for expected top screen output - * on development units/patched ErrDisp. - */ -Result ERRF_ThrowResult(Result failure); - -/** - * @brief Throws a system error with the given Result code and message. - * @param[in] failure Result code to throw. - * @param[in] message The message to display. - * - * This calls ERRF_Throw() with error type ERRF_ERRTYPE_FAILURE and fills in the required data. - * - * This function does \em not fill in the address where this function was called from because it - * would not be displayed. - * - * The message is only displayed on development units/patched ErrDisp. - * - * See https://3dbrew.org/wiki/ERR:Throw#Result_Failure for expected top screen output - * on development units/patched ErrDisp. - */ -Result ERRF_ThrowResultWithMessage(Result failure, const char* message); - -/** - * @brief Handles an exception using ErrDisp. - * @param excep Exception information - * @param regs CPU registers - * - * You might want to clear ENVINFO's bit0 to be able to see any debugging information. - * @sa threadOnException - */ -void ERRF_ExceptionHandler(ERRF_ExceptionInfo* excep, CpuRegisters* regs) __attribute__((noreturn)); diff --git a/Includes/ctrulib/font.h b/Includes/ctrulib/font.h deleted file mode 100644 index 9477d0c..0000000 --- a/Includes/ctrulib/font.h +++ /dev/null @@ -1,218 +0,0 @@ -/** - * @file font.h - * @brief Shared font support. - */ -#pragma once -#ifdef __cplusplus -extern "C" { -#endif -#include "../types.h" - -///@name Data types -///@{ - -/// Character width information structure. -typedef struct -{ - s8 left; ///< Horizontal offset to draw the glyph with. - u8 glyphWidth; ///< Width of the glyph. - u8 charWidth; ///< Width of the character, that is, horizontal distance to advance. -} charWidthInfo_s; - -/// Font texture sheet information. -typedef struct -{ - u8 cellWidth; ///< Width of a glyph cell. - u8 cellHeight; ///< Height of a glyph cell. - u8 baselinePos; ///< Vertical position of the baseline. - u8 maxCharWidth; ///< Maximum character width. - - u32 sheetSize; ///< Size in bytes of a texture sheet. - u16 nSheets; ///< Number of texture sheets. - u16 sheetFmt; ///< GPU texture format (GPU_TEXCOLOR). - - u16 nRows; ///< Number of glyphs per row per sheet. - u16 nLines; ///< Number of glyph rows per sheet. - - u16 sheetWidth; ///< Texture sheet width. - u16 sheetHeight; ///< Texture sheet height. - u8* sheetData; ///< Pointer to texture sheet data. -} TGLP_s; - -/// Font character width information block type. -typedef struct tag_CWDH_s CWDH_s; - -/// Font character width information block structure. -struct tag_CWDH_s -{ - u16 startIndex; ///< First Unicode codepoint the block applies to. - u16 endIndex; ///< Last Unicode codepoint the block applies to. - CWDH_s* next; ///< Pointer to the next block. - - charWidthInfo_s widths[0]; ///< Table of character width information structures. -}; - -/// Font character map methods. -enum -{ - CMAP_TYPE_DIRECT = 0, ///< Identity mapping. - CMAP_TYPE_TABLE = 1, ///< Mapping using a table. - CMAP_TYPE_SCAN = 2, ///< Mapping using a list of mapped characters. -}; - -/// Font character map type. -typedef struct tag_CMAP_s CMAP_s; - -/// Font character map structure. -struct tag_CMAP_s -{ - u16 codeBegin; ///< First Unicode codepoint the block applies to. - u16 codeEnd; ///< Last Unicode codepoint the block applies to. - u16 mappingMethod; ///< Mapping method. - u16 reserved; - CMAP_s* next; ///< Pointer to the next map. - - union - { - u16 indexOffset; ///< For CMAP_TYPE_DIRECT: index of the first glyph. - u16 indexTable[0]; ///< For CMAP_TYPE_TABLE: table of glyph indices. - /// For CMAP_TYPE_SCAN: Mapping data. - struct - { - u16 nScanEntries; ///< Number of pairs. - /// Mapping pairs. - struct - { - u16 code; ///< Unicode codepoint. - u16 glyphIndex; ///< Mapped glyph index. - - } scanEntries[0]; - }; - }; -}; - -/// Font information structure. -typedef struct -{ - u32 signature; ///< Signature (FINF). - u32 sectionSize; ///< Section size. - - u8 fontType; ///< Font type - u8 lineFeed; ///< Line feed vertical distance. - u16 alterCharIndex; ///< Glyph index of the replacement character. - charWidthInfo_s defaultWidth; ///< Default character width information. - u8 encoding; ///< Font encoding (?) - - TGLP_s* tglp; ///< Pointer to texture sheet information. - CWDH_s* cwdh; ///< Pointer to the first character width information block. - CMAP_s* cmap; ///< Pointer to the first character map. - - u8 height; ///< Font height. - u8 width; ///< Font width. - u8 ascent; ///< Font ascent. - u8 padding; -} FINF_s; - -/// Font structure. -typedef struct -{ - u32 signature; ///< Signature (CFNU). - u16 endianness; ///< Endianness constant (0xFEFF). - u16 headerSize; ///< Header size. - u32 version; ///< Format version. - u32 fileSize; ///< File size. - u32 nBlocks; ///< Number of blocks. - - FINF_s finf; ///< Font information. -} CFNT_s; - -/// Font glyph position structure. -typedef struct -{ - int sheetIndex; ///< Texture sheet index to use to render the glyph. - float xOffset; ///< Horizontal offset to draw the glyph width. - float xAdvance; ///< Horizontal distance to advance after drawing the glyph. - float width; ///< Glyph width. - /// Texture coordinates to use to render the glyph. - struct - { - float left, top, right, bottom; - } texcoord; - /// Vertex coordinates to use to render the glyph. - struct - { - float left, top, right, bottom; - } vtxcoord; -} fontGlyphPos_s; - -/// Flags for use with fontCalcGlyphPos. -enum -{ - GLYPH_POS_CALC_VTXCOORD = BIT(0), ///< Calculates vertex coordinates in addition to texture coordinates. - GLYPH_POS_AT_BASELINE = BIT(1), ///< Position the glyph at the baseline instead of at the top-left corner. - GLYPH_POS_Y_POINTS_UP = BIT(2), ///< Indicates that the Y axis points up instead of down. -}; - -///@} - -///@name Initialization and basic operations -///@{ - -/// Ensures the shared system font is mapped. -Result fontEnsureMapped(void); - -/// Retrieves the font information structure of the shared system font. -static inline FINF_s* fontGetInfo(void) -{ - extern CFNT_s* g_sharedFont; - return &g_sharedFont->finf; -} - -static inline CFNT_s *fontGetFont(void) -{ - extern CFNT_s* g_sharedFont; - return (g_sharedFont); -} - -/// Retrieves the texture sheet information of the shared system font. -static inline TGLP_s* fontGetGlyphInfo(void) -{ - return fontGetInfo()->tglp; -} - -/** - * @brief Retrieves the pointer to texture data for the specified texture sheet. - * @param sheetIndex Index of the texture sheet. - */ -static inline void* fontGetGlyphSheetTex(int sheetIndex) -{ - TGLP_s* tglp = fontGetGlyphInfo(); - return &tglp->sheetData[sheetIndex*tglp->sheetSize]; -} - -/** - * @brief Retrieves the glyph index of the specified Unicode codepoint. - * @param codePoint Unicode codepoint. - */ -int fontGlyphIndexFromCodePoint(u32 codePoint); - -/** - * @brief Retrieves character width information of the specified glyph. - * @param glyphIndex Index of the glyph. - */ -charWidthInfo_s* fontGetCharWidthInfo(int glyphIndex); - -/** - * @brief Calculates position information for the specified glyph. - * @param out Output structure in which to write the information. - * @param glyphIndex Index of the glyph. - * @param flags Calculation flags (see GLYPH_POS_* flags). - * @param scaleX Scale factor to apply horizontally. - * @param scaleY Scale factor to apply vertically. - */ -void fontCalcGlyphPos(fontGlyphPos_s* out, int glyphIndex, u32 flags, float scaleX, float scaleY); - -///@} -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/Includes/ctrulib/gfx.h b/Includes/ctrulib/gfx.h deleted file mode 100644 index 79d8985..0000000 --- a/Includes/ctrulib/gfx.h +++ /dev/null @@ -1,176 +0,0 @@ -/** - * @file gfx.h - * @brief LCD Screens manipulation - * - * This header provides functions to configure and manipulate the two screens, including double buffering and 3D activation. - * It is mainly an abstraction over the gsp service. - */ -#pragma once -#ifdef __cplusplus -extern "C" { -#endif -#include -#include - -/// Converts red, green, and blue components to packed RGB565. -#define RGB565(r,g,b) (((b)&0x1f)|(((g)&0x3f)<<5)|(((r)&0x1f)<<11)) - -/// Converts packed RGB8 to packed RGB565. -#define RGB8_to_565(r,g,b) (((b)>>3)&0x1f)|((((g)>>2)&0x3f)<<5)|((((r)>>3)&0x1f)<<11) - -/// Available screens. -typedef enum -{ - GFX_TOP = 0, ///< Top screen - GFX_BOTTOM = 1 ///< Bottom screen -}gfxScreen_t; - -/** - * @brief Side of top screen framebuffer. - * - * This is to be used only when the 3D is enabled. - * Use only GFX_LEFT if this concerns the bottom screen or if 3D is disabled. - */ -typedef enum -{ - GFX_LEFT = 0, ///< Left eye framebuffer - GFX_RIGHT = 1,///< Right eye framebuffer -}gfx3dSide_t; - - -///@name System related -///@{ - -/** - * @brief Initializes the LCD framebuffers with default parameters - * - * By default ctrulib will configure the LCD framebuffers with the @ref GSP_BGR8_OES format in linear memory. - * This is the same as calling : @code gfxInit(GSP_BGR8_OES,GSP_BGR8_OES,false); @endcode - * - * @note You should always call @ref gfxExit once done to free the memory and services - */ -void gfxInitDefault(void); - -/** - * @brief Initializes the LCD framebuffers. - * @param topFormat The format of the top screen framebuffers. - * @param bottomFormat The format of the bottom screen framebuffers. - * @param vramBuffers Whether to allocate the framebuffers in VRAM. - * - * This function will allocate the memory for the framebuffers and open a gsp service session. - * It will also bind the newly allocated framebuffers to the LCD screen and setup the VBlank event. - * - * The 3D stereoscopic display is will be disabled. - * - * @note Even if the double buffering is disabled, it will allocate two buffer per screen. - * @note You should always call @ref gfxExit once done to free the memory and services - */ -void gfxInit(GSPGPU_FramebufferFormats topFormat, GSPGPU_FramebufferFormats bottomFormat, bool vrambuffers); - -/** - * @brief Closes the gsp service and frees the framebuffers. - * - * Just call it when you're done. - */ -void gfxExit(void); -///@} - -///@name Control -///@{ -/** - * @brief Enables the 3D stereoscopic effect. - * @param enable Enables the 3D effect if true, disables it if false. - */ -void gfxSet3D(bool enable); - -/** - * @brief Retrieves the status of the 3D stereoscopic effect. - * @return true if 3D enabled, false otherwise. - */ -bool gfxIs3D(void); - -/** - * @brief Changes the color format of a screen - * @param screen The screen of which format should be changed - * @param format One of the gsp pixel formats. - */ -void gfxSetScreenFormat(gfxScreen_t screen, GSPGPU_FramebufferFormats format); - -/** - * @brief Gets a screen pixel format. - * @param screen Screen to get the pixel format of. - * @return the pixel format of the chosen screen set by ctrulib. - */ -GSPGPU_FramebufferFormats gfxGetScreenFormat(gfxScreen_t screen); - -/** - * @brief Sets whether to use ctrulib's double buffering - * @param screen Screen to toggle double buffering for. - * @param doubleBuffering Whether to use double buffering. - * - * ctrulib is by default using a double buffering scheme. - * If you do not want to swap one of the screen framebuffers when @ref gfxSwapBuffers or @ref gfxSwapBuffers is called, - * then you have to disable double buffering. - * - * It is however recommended to call @ref gfxSwapBuffers even if double buffering is disabled - * for both screens if you want to keep the gsp configuration up to date. - */ -void gfxSetDoubleBuffering(gfxScreen_t screen, bool doubleBuffering); - -/** - * @brief Flushes the current framebuffers - * - * Use this if the data within your framebuffers changes a lot and that you want to make sure everything was updated correctly. - * This shouldn't be needed and has a significant overhead. - */ -void gfxFlushBuffers(void); - -/** - * @brief Updates the configuration of the specified screen (swapping the buffers if double-buffering is enabled). - * @param scr Screen to configure. - * @param immediate Whether to apply the updated configuration immediately or let GSPGPU apply it after the next GX transfer completes. - */ -void gfxConfigScreen(gfxScreen_t scr, bool immediate); - -/** - * @brief Swaps the buffers and sets the gsp state - * - * This is to be called to update the gsp state and swap the framebuffers. - * LCD rendering should start as soon as the gsp state is set. - * When using the GPU, call @ref gfxSwapBuffers instead. - */ -void gfxSwapBuffers(void); - -/** - * @brief Swaps the framebuffers - * - * This is the version to be used with the GPU since the GPU will use the gsp shared memory, - * so the gsp state mustn't be set directly by the user. - */ -void gfxSwapBuffersGpu(void); - -///@} - - -///@name Helper -///@{ -/** - * @brief Retrieves a framebuffer information. - * @param screen Screen to retrieve framebuffer information for. - * @param side Side of the screen to retrieve framebuffer information for. - * @param width Pointer that will hold the width of the framebuffer in pixels. - * @param height Pointer that will hold the height of the framebuffer in pixels. - * @return A pointer to the current framebuffer of the choosen screen. - * - * Please remember that the returned pointer will change after each call to gfxSwapBuffers if double buffering is enabled. - */ -u8* gfxGetFramebuffer(gfxScreen_t screen, gfx3dSide_t side, u16* width, u16* height); -///@} - -//global variables -extern u8* gfxTopLeftFramebuffers[2]; -extern u8* gfxTopRightFramebuffers[2]; -extern u8* gfxBottomFramebuffers[2]; -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/Includes/ctrulib/gpu/enums.h b/Includes/ctrulib/gpu/enums.h deleted file mode 100644 index 650c213..0000000 --- a/Includes/ctrulib/gpu/enums.h +++ /dev/null @@ -1,464 +0,0 @@ -/** - * @file enums.h - * @brief GPU enumeration values. - */ -#pragma once -#ifdef __cplusplus -extern "C" { -#endif -/// Creates a texture magnification filter parameter from a @ref GPU_TEXTURE_FILTER_PARAM -#define GPU_TEXTURE_MAG_FILTER(v) (((v)&0x1)<<1) -/// Creates a texture minification filter parameter from a @ref GPU_TEXTURE_FILTER_PARAM -#define GPU_TEXTURE_MIN_FILTER(v) (((v)&0x1)<<2) -/// Creates a texture mipmap filter parameter from a @ref GPU_TEXTURE_FILTER_PARAM -#define GPU_TEXTURE_MIP_FILTER(v) (((v)&0x1)<<24) -/// Creates a texture wrap S parameter from a @ref GPU_TEXTURE_WRAP_PARAM -#define GPU_TEXTURE_WRAP_S(v) (((v)&0x3)<<12) -/// Creates a texture wrap T parameter from a @ref GPU_TEXTURE_WRAP_PARAM -#define GPU_TEXTURE_WRAP_T(v) (((v)&0x3)<<8) -/// Creates a texture mode parameter from a @ref GPU_TEXTURE_MODE_PARAM -#define GPU_TEXTURE_MODE(v) (((v)&0x7)<<28) -/// Texture parameter indicating ETC1 texture. -#define GPU_TEXTURE_ETC1_PARAM BIT(5) -/// Texture parameter indicating shadow texture. -#define GPU_TEXTURE_SHADOW_PARAM BIT(20) - -/// Creates a combiner buffer write configuration. -#define GPU_TEV_BUFFER_WRITE_CONFIG(stage0, stage1, stage2, stage3) ((stage0) | ((stage1) << 1) | ((stage2) << 2) | ((stage3) << 3)) - -/// Texture filters. -typedef enum -{ - GPU_NEAREST = 0x0, ///< Nearest-neighbor interpolation. - GPU_LINEAR = 0x1, ///< Linear interpolation. -} GPU_TEXTURE_FILTER_PARAM; - -/// Texture wrap modes. -typedef enum -{ - GPU_CLAMP_TO_EDGE = 0x0, ///< Clamps to edge. - GPU_CLAMP_TO_BORDER = 0x1, ///< Clamps to border. - GPU_REPEAT = 0x2, ///< Repeats texture. - GPU_MIRRORED_REPEAT = 0x3, ///< Repeats with mirrored texture. -} GPU_TEXTURE_WRAP_PARAM; - -/// Texture modes. -typedef enum -{ - GPU_TEX_2D = 0x0, ///< 2D texture - GPU_TEX_CUBE_MAP = 0x1, ///< Cube map - GPU_TEX_SHADOW_2D = 0x2, ///< 2D Shadow texture - GPU_TEX_PROJECTION = 0x3, ///< Projection texture - GPU_TEX_SHADOW_CUBE = 0x4, ///< Shadow cube map - GPU_TEX_DISABLED = 0x5, ///< Disabled -} GPU_TEXTURE_MODE_PARAM; - -/// Supported texture units. -typedef enum -{ - GPU_TEXUNIT0 = 0x1, ///< Texture unit 0. - GPU_TEXUNIT1 = 0x2, ///< Texture unit 1. - GPU_TEXUNIT2 = 0x4, ///< Texture unit 2. -} GPU_TEXUNIT; - -/// Supported texture formats. -typedef enum -{ - GPU_RGBA8 = 0x0, ///< 8-bit Red + 8-bit Green + 8-bit Blue + 8-bit Alpha - GPU_RGB8 = 0x1, ///< 8-bit Red + 8-bit Green + 8-bit Blue - GPU_RGBA5551 = 0x2, ///< 5-bit Red + 5-bit Green + 5-bit Blue + 1-bit Alpha - GPU_RGB565 = 0x3, ///< 5-bit Red + 6-bit Green + 5-bit Blue - GPU_RGBA4 = 0x4, ///< 4-bit Red + 4-bit Green + 4-bit Blue + 4-bit Alpha - GPU_LA8 = 0x5, ///< 8-bit Luminance + 8-bit Alpha - GPU_HILO8 = 0x6, ///< 8-bit Hi + 8-bit Lo - GPU_L8 = 0x7, ///< 8-bit Luminance - GPU_A8 = 0x8, ///< 8-bit Alpha - GPU_LA4 = 0x9, ///< 4-bit Luminance + 4-bit Alpha - GPU_L4 = 0xA, ///< 4-bit Luminance - GPU_A4 = 0xB, ///< 4-bit Alpha - GPU_ETC1 = 0xC, ///< ETC1 texture compression - GPU_ETC1A4 = 0xD, ///< ETC1 texture compression + 4-bit Alpha -} GPU_TEXCOLOR; - -/// Procedural texture clamp modes. -typedef enum -{ - GPU_PT_CLAMP_TO_ZERO = 0, ///< Clamp to zero. - GPU_PT_CLAMP_TO_EDGE = 1, ///< Clamp to edge. - GPU_PT_REPEAT = 2, ///< Symmetrical repeat. - GPU_PT_MIRRORED_REPEAT = 3, ///< Mirrored repeat. - GPU_PT_PULSE = 4, ///< Pulse. -} GPU_PROCTEX_CLAMP; - -/// Procedural texture mapping functions. -typedef enum -{ - GPU_PT_U = 0, ///< U - GPU_PT_U2 = 1, ///< U2 - GPU_PT_V = 2, ///< V - GPU_PT_V2 = 3, ///< V2 - GPU_PT_ADD = 4, ///< U+V - GPU_PT_ADD2 = 5, ///< U2+V2 - GPU_PT_SQRT2 = 6, ///< sqrt(U2+V2) - GPU_PT_MIN = 7, ///< min - GPU_PT_MAX = 8, ///< max - GPU_PT_RMAX = 9, ///< rmax -} GPU_PROCTEX_MAPFUNC; - -/// Procedural texture shift values. -typedef enum -{ - GPU_PT_NONE = 0, ///< No shift. - GPU_PT_ODD = 1, ///< Odd shift. - GPU_PT_EVEN = 2, ///< Even shift. -} GPU_PROCTEX_SHIFT; - -/// Procedural texture filter values. -typedef enum -{ - GPU_PT_NEAREST = 0, ///< Nearest-neighbor - GPU_PT_LINEAR = 1, ///< Linear interpolation - GPU_PT_NEAREST_MIP_NEAREST = 2, ///< Nearest-neighbor with mipmap using nearest-neighbor - GPU_PT_LINEAR_MIP_NEAREST = 3, ///< Linear interpolation with mipmap using nearest-neighbor - GPU_PT_NEAREST_MIP_LINEAR = 4, ///< Nearest-neighbor with mipmap using linear interpolation - GPU_PT_LINEAR_MIP_LINEAR = 5, ///< Linear interpolation with mipmap using linear interpolation -} GPU_PROCTEX_FILTER; - -/// Procedural texture LUT IDs. -typedef enum -{ - GPU_LUT_NOISE = 0, ///< Noise table - GPU_LUT_RGBMAP = 1, ///< RGB mapping function table - GPU_LUT_ALPHAMAP = 2, ///< Alpha mapping function table - GPU_LUT_COLOR = 3, ///< Color table - GPU_LUT_COLORDIF = 4, ///< Color difference table -} GPU_PROCTEX_LUTID; - -/// Supported color buffer formats. -typedef enum -{ - GPU_RB_RGBA8 = 0, ///< 8-bit Red + 8-bit Green + 8-bit Blue + 8-bit Alpha - GPU_RB_RGB8 = 1, ///< 8-bit Red + 8-bit Green + 8-bit Blue - GPU_RB_RGBA5551 = 2, ///< 5-bit Red + 5-bit Green + 5-bit Blue + 1-bit Alpha - GPU_RB_RGB565 = 3, ///< 5-bit Red + 6-bit Green + 5-bit Blue - GPU_RB_RGBA4 = 4, ///< 4-bit Red + 4-bit Green + 4-bit Blue + 4-bit Alpha -} GPU_COLORBUF; - -/// Supported depth buffer formats. -typedef enum -{ - GPU_RB_DEPTH16 = 0, ///< 16-bit Depth - GPU_RB_DEPTH24 = 2, ///< 24-bit Depth - GPU_RB_DEPTH24_STENCIL8 = 3, ///< 24-bit Depth + 8-bit Stencil -} GPU_DEPTHBUF; - -/// Test functions. -typedef enum -{ - GPU_NEVER = 0, ///< Never pass. - GPU_ALWAYS = 1, ///< Always pass. - GPU_EQUAL = 2, ///< Pass if equal. - GPU_NOTEQUAL = 3, ///< Pass if not equal. - GPU_LESS = 4, ///< Pass if less than. - GPU_LEQUAL = 5, ///< Pass if less than or equal. - GPU_GREATER = 6, ///< Pass if greater than. - GPU_GEQUAL = 7, ///< Pass if greater than or equal. -} GPU_TESTFUNC; - -/// Early depth test functions. -typedef enum -{ - GPU_EARLYDEPTH_GEQUAL = 0, ///< Pass if greater than or equal. - GPU_EARLYDEPTH_GREATER = 1, ///< Pass if greater than. - GPU_EARLYDEPTH_LEQUAL = 2, ///< Pass if less than or equal. - GPU_EARLYDEPTH_LESS = 3, ///< Pass if less than. -} GPU_EARLYDEPTHFUNC; - -/// Scissor test modes. -typedef enum -{ - GPU_SCISSOR_DISABLE = 0, ///< Disable. - GPU_SCISSOR_INVERT = 1, ///< Exclude pixels inside the scissor box. - // 2 is the same as 0 - GPU_SCISSOR_NORMAL = 3, ///< Exclude pixels outside of the scissor box. -} GPU_SCISSORMODE; - -/// Stencil operations. -typedef enum -{ - GPU_STENCIL_KEEP = 0, ///< Keep old value. (old_stencil) - GPU_STENCIL_ZERO = 1, ///< Zero. (0) - GPU_STENCIL_REPLACE = 2, ///< Replace value. (ref) - GPU_STENCIL_INCR = 3, ///< Increment value. (old_stencil + 1 saturated to [0, 255]) - GPU_STENCIL_DECR = 4, ///< Decrement value. (old_stencil - 1 saturated to [0, 255]) - GPU_STENCIL_INVERT = 5, ///< Invert value. (~old_stencil) - GPU_STENCIL_INCR_WRAP = 6, ///< Increment value. (old_stencil + 1) - GPU_STENCIL_DECR_WRAP = 7, ///< Decrement value. (old_stencil - 1) -} GPU_STENCILOP; - -/// Pixel write mask. -typedef enum -{ - GPU_WRITE_RED = 0x01, ///< Write red. - GPU_WRITE_GREEN = 0x02, ///< Write green. - GPU_WRITE_BLUE = 0x04, ///< Write blue. - GPU_WRITE_ALPHA = 0x08, ///< Write alpha. - GPU_WRITE_DEPTH = 0x10, ///< Write depth. - - GPU_WRITE_COLOR = 0x0F, ///< Write all color components. - GPU_WRITE_ALL = 0x1F, ///< Write all components. -} GPU_WRITEMASK; - -/// Blend modes. -typedef enum -{ - GPU_BLEND_ADD = 0, ///< Add colors. - GPU_BLEND_SUBTRACT = 1, ///< Subtract colors. - GPU_BLEND_REVERSE_SUBTRACT = 2, ///< Reverse-subtract colors. - GPU_BLEND_MIN = 3, ///< Use the minimum color. - GPU_BLEND_MAX = 4, ///< Use the maximum color. -} GPU_BLENDEQUATION; - -/// Blend factors. -typedef enum -{ - GPU_ZERO = 0, ///< Zero. - GPU_ONE = 1, ///< One. - GPU_SRC_COLOR = 2, ///< Source color. - GPU_ONE_MINUS_SRC_COLOR = 3, ///< Source color - 1. - GPU_DST_COLOR = 4, ///< Destination color. - GPU_ONE_MINUS_DST_COLOR = 5, ///< Destination color - 1. - GPU_SRC_ALPHA = 6, ///< Source alpha. - GPU_ONE_MINUS_SRC_ALPHA = 7, ///< Source alpha - 1. - GPU_DST_ALPHA = 8, ///< Destination alpha. - GPU_ONE_MINUS_DST_ALPHA = 9, ///< Destination alpha - 1. - GPU_CONSTANT_COLOR = 10, ///< Constant color. - GPU_ONE_MINUS_CONSTANT_COLOR = 11, ///< Constant color - 1. - GPU_CONSTANT_ALPHA = 12, ///< Constant alpha. - GPU_ONE_MINUS_CONSTANT_ALPHA = 13, ///< Constant alpha - 1. - GPU_SRC_ALPHA_SATURATE = 14, ///< Saturated alpha. -} GPU_BLENDFACTOR; - -/// Logical operations. -typedef enum -{ - GPU_LOGICOP_CLEAR = 0, ///< Clear. - GPU_LOGICOP_AND = 1, ///< Bitwise AND. - GPU_LOGICOP_AND_REVERSE = 2, ///< Reverse bitwise AND. - GPU_LOGICOP_COPY = 3, ///< Copy. - GPU_LOGICOP_SET = 4, ///< Set. - GPU_LOGICOP_COPY_INVERTED = 5, ///< Inverted copy. - GPU_LOGICOP_NOOP = 6, ///< No operation. - GPU_LOGICOP_INVERT = 7, ///< Invert. - GPU_LOGICOP_NAND = 8, ///< Bitwise NAND. - GPU_LOGICOP_OR = 9, ///< Bitwise OR. - GPU_LOGICOP_NOR = 10, ///< Bitwise NOR. - GPU_LOGICOP_XOR = 11, ///< Bitwise XOR. - GPU_LOGICOP_EQUIV = 12, ///< Equivalent. - GPU_LOGICOP_AND_INVERTED = 13, ///< Inverted bitwise AND. - GPU_LOGICOP_OR_REVERSE = 14, ///< Reverse bitwise OR. - GPU_LOGICOP_OR_INVERTED = 15, ///< Inverted bitwize OR. -} GPU_LOGICOP; - -/// Fragment operation modes. -typedef enum -{ - GPU_FRAGOPMODE_GL = 0, ///< OpenGL mode. - GPU_FRAGOPMODE_GAS_ACC = 1, ///< Gas mode (?). - GPU_FRAGOPMODE_SHADOW = 3, ///< Shadow mode (?). -} GPU_FRAGOPMODE; - -/// Supported component formats. -typedef enum -{ - GPU_BYTE = 0, ///< 8-bit byte. - GPU_UNSIGNED_BYTE = 1, ///< 8-bit unsigned byte. - GPU_SHORT = 2, ///< 16-bit short. - GPU_FLOAT = 3, ///< 32-bit float. -} GPU_FORMATS; - -/// Cull modes. -typedef enum -{ - GPU_CULL_NONE = 0, ///< Disabled. - GPU_CULL_FRONT_CCW = 1, ///< Front, counter-clockwise. - GPU_CULL_BACK_CCW = 2, ///< Back, counter-clockwise. -} GPU_CULLMODE; - -/// Creates a VBO attribute parameter from its index, size, and format. -#define GPU_ATTRIBFMT(i, n, f) (((((n)-1)<<2)|((f)&3))<<((i)*4)) - -/// Texture combiner sources. -typedef enum -{ - GPU_PRIMARY_COLOR = 0x00, ///< Primary color. - GPU_FRAGMENT_PRIMARY_COLOR = 0x01, ///< Primary fragment color. - GPU_FRAGMENT_SECONDARY_COLOR = 0x02, ///< Secondary fragment color. - GPU_TEXTURE0 = 0x03, ///< Texture unit 0. - GPU_TEXTURE1 = 0x04, ///< Texture unit 1. - GPU_TEXTURE2 = 0x05, ///< Texture unit 2. - GPU_TEXTURE3 = 0x06, ///< Texture unit 3. - GPU_PREVIOUS_BUFFER = 0x0D, ///< Previous buffer. - GPU_CONSTANT = 0x0E, ///< Constant value. - GPU_PREVIOUS = 0x0F, ///< Previous value. -} GPU_TEVSRC; - -/// Texture RGB combiner operands. -typedef enum -{ - GPU_TEVOP_RGB_SRC_COLOR = 0x00, ///< Source color. - GPU_TEVOP_RGB_ONE_MINUS_SRC_COLOR = 0x01, ///< Source color - 1. - GPU_TEVOP_RGB_SRC_ALPHA = 0x02, ///< Source alpha. - GPU_TEVOP_RGB_ONE_MINUS_SRC_ALPHA = 0x03, ///< Source alpha - 1. - GPU_TEVOP_RGB_SRC_R = 0x04, ///< Source red. - GPU_TEVOP_RGB_ONE_MINUS_SRC_R = 0x05, ///< Source red - 1. - GPU_TEVOP_RGB_0x06 = 0x06, ///< Unknown. - GPU_TEVOP_RGB_0x07 = 0x07, ///< Unknown. - GPU_TEVOP_RGB_SRC_G = 0x08, ///< Source green. - GPU_TEVOP_RGB_ONE_MINUS_SRC_G = 0x09, ///< Source green - 1. - GPU_TEVOP_RGB_0x0A = 0x0A, ///< Unknown. - GPU_TEVOP_RGB_0x0B = 0x0B, ///< Unknown. - GPU_TEVOP_RGB_SRC_B = 0x0C, ///< Source blue. - GPU_TEVOP_RGB_ONE_MINUS_SRC_B = 0x0D, ///< Source blue - 1. - GPU_TEVOP_RGB_0x0E = 0x0E, ///< Unknown. - GPU_TEVOP_RGB_0x0F = 0x0F, ///< Unknown. -} GPU_TEVOP_RGB; - -/// Texture Alpha combiner operands. -typedef enum -{ - GPU_TEVOP_A_SRC_ALPHA = 0x00, ///< Source alpha. - GPU_TEVOP_A_ONE_MINUS_SRC_ALPHA = 0x01, ///< Source alpha - 1. - GPU_TEVOP_A_SRC_R = 0x02, ///< Source red. - GPU_TEVOP_A_ONE_MINUS_SRC_R = 0x03, ///< Source red - 1. - GPU_TEVOP_A_SRC_G = 0x04, ///< Source green. - GPU_TEVOP_A_ONE_MINUS_SRC_G = 0x05, ///< Source green - 1. - GPU_TEVOP_A_SRC_B = 0x06, ///< Source blue. - GPU_TEVOP_A_ONE_MINUS_SRC_B = 0x07, ///< Source blue - 1. -} GPU_TEVOP_A; - -/// Texture combiner functions. -typedef enum -{ - GPU_REPLACE = 0x00, ///< Replace. - GPU_MODULATE = 0x01, ///< Modulate. - GPU_ADD = 0x02, ///< Add. - GPU_ADD_SIGNED = 0x03, ///< Signed add. - GPU_INTERPOLATE = 0x04, ///< Interpolate. - GPU_SUBTRACT = 0x05, ///< Subtract. - GPU_DOT3_RGB = 0x06, ///< Dot3. RGB only. - GPU_MULTIPLY_ADD = 0x08, ///< Multiply then add. - GPU_ADD_MULTIPLY = 0x09, ///< Add then multiply. -} GPU_COMBINEFUNC; - -/// Texture scale factors. -typedef enum -{ - GPU_TEVSCALE_1 = 0x0, ///< 1x - GPU_TEVSCALE_2 = 0x1, ///< 2x - GPU_TEVSCALE_4 = 0x2, ///< 4x -} GPU_TEVSCALE; - -/// Creates a texture combiner source parameter from three sources. -#define GPU_TEVSOURCES(a,b,c) (((a))|((b)<<4)|((c)<<8)) -/// Creates a texture combiner operand parameter from three operands. -#define GPU_TEVOPERANDS(a,b,c) (((a))|((b)<<4)|((c)<<8)) - -/// Creates a light environment layer configuration parameter. -#define GPU_LIGHT_ENV_LAYER_CONFIG(n) ((n)+((n)==7)) -/// Light shadow disable bits in GPUREG_LIGHT_CONFIG1. -#define GPU_LC1_SHADOWBIT(n) BIT(n) -/// Light spot disable bits in GPUREG_LIGHT_CONFIG1. -#define GPU_LC1_SPOTBIT(n) BIT((n)+8) -/// LUT disable bits in GPUREG_LIGHT_CONFIG1. -#define GPU_LC1_LUTBIT(n) BIT((n)+16) -/// Light distance attenuation disable bits in GPUREG_LIGHT_CONFIG1. -#define GPU_LC1_ATTNBIT(n) BIT((n)+24) -/// Creates a light permutation parameter. -#define GPU_LIGHTPERM(i,n) ((n) << (i)) -/// Creates a light LUT input parameter. -#define GPU_LIGHTLUTINPUT(i,n) ((n) << ((i)*4)) -/// Creates a light LUT index parameter. -#define GPU_LIGHTLUTIDX(c,i,o) ((o) | ((i) << 8) | ((c) << 11)) -/// Creates a light color parameter from red, green, and blue components. -#define GPU_LIGHTCOLOR(r,g,b) (((b) & 0xFF) | (((g) << 10) & 0xFF) | (((r) << 20) & 0xFF)) - -/// Fresnel options. -typedef enum -{ - GPU_NO_FRESNEL = 0, ///< None. - GPU_PRI_ALPHA_FRESNEL = 1, ///< Primary alpha. - GPU_SEC_ALPHA_FRESNEL = 2, ///< Secondary alpha. - GPU_PRI_SEC_ALPHA_FRESNEL = 3, ///< Primary and secondary alpha. -} GPU_FRESNELSEL; - -/// Bump map modes. -typedef enum -{ - GPU_BUMP_NOT_USED = 0, ///< Disabled. - GPU_BUMP_AS_BUMP = 1, ///< Bump as bump mapping. - GPU_BUMP_AS_TANG = 2, ///< Bump as tangent/normal mapping. -} GPU_BUMPMODE; - -/// LUT IDs. -typedef enum -{ - GPU_LUT_D0 = 0, ///< D0 LUT. - GPU_LUT_D1 = 1, ///< D1 LUT. - GPU_LUT_SP = 2, ///< Spotlight LUT. - GPU_LUT_FR = 3, ///< Fresnel LUT. - GPU_LUT_RB = 4, ///< Reflection-Blue LUT. - GPU_LUT_RG = 5, ///< Reflection-Green LUT. - GPU_LUT_RR = 6, ///< Reflection-Red LUT. - GPU_LUT_DA = 7, ///< Distance attenuation LUT. -} GPU_LIGHTLUTID; - -/// LUT inputs. -typedef enum -{ - GPU_LUTINPUT_NH = 0, ///< Normal*HalfVector - GPU_LUTINPUT_VH = 1, ///< View*HalfVector - GPU_LUTINPUT_NV = 2, ///< Normal*View - GPU_LUTINPUT_LN = 3, ///< LightVector*Normal - GPU_LUTINPUT_SP = 4, ///< -LightVector*SpotlightVector - GPU_LUTINPUT_CP = 5, ///< cosine of phi -} GPU_LIGHTLUTINPUT; - -/// LUT scalers. -typedef enum -{ - GPU_LUTSCALER_1x = 0, ///< 1x scale. - GPU_LUTSCALER_2x = 1, ///< 2x scale. - GPU_LUTSCALER_4x = 2, ///< 4x scale. - GPU_LUTSCALER_8x = 3, ///< 8x scale. - GPU_LUTSCALER_0_25x = 6, ///< 0.25x scale. - GPU_LUTSCALER_0_5x = 7, ///< 0.5x scale. -} GPU_LIGHTLUTSCALER; - -/// LUT selection. -typedef enum -{ - GPU_LUTSELECT_COMMON = 0, ///< LUTs that are common to all lights. - GPU_LUTSELECT_SP = 1, ///< Spotlight LUT. - GPU_LUTSELECT_DA = 2, ///< Distance attenuation LUT. -} GPU_LIGHTLUTSELECT; - -/// Supported primitives. -typedef enum -{ - GPU_TRIANGLES = 0x0000, ///< Triangles. - GPU_TRIANGLE_STRIP = 0x0100, ///< Triangle strip. - GPU_TRIANGLE_FAN = 0x0200, ///< Triangle fan. - GPU_GEOMETRY_PRIM = 0x0300, ///< Geometry shader primitive. -} GPU_Primitive_t; - -/// Shader types. -typedef enum -{ - GPU_VERTEX_SHADER = 0x0, ///< Vertex shader. - GPU_GEOMETRY_SHADER = 0x1, ///< Geometry shader. -} GPU_SHADER_TYPE; - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/Includes/ctrulib/gpu/gpu-old.h b/Includes/ctrulib/gpu/gpu-old.h deleted file mode 100644 index 5ef29a9..0000000 --- a/Includes/ctrulib/gpu/gpu-old.h +++ /dev/null @@ -1,241 +0,0 @@ -/** - * @file gpu-old.h - * @brief Deprecated GPU functions which should not be used in new code. - * @description These functions have been superseeded by direct GPU register writes, or external GPU libraries. - * @deprecated - */ -#pragma once -#ifdef __cplusplus -extern "C" { -#endif -#include "gpu.h" - -/** - * @brief Initializes the GPU. - * @param gsphandle GSP handle to use. - * @deprecated - */ - -//void GPU_Init(Handle *gsphandle) DEPRECATED; - -/** - * @brief Resets the GPU. - * @param gxbuf GX command buffer to use. - * @param gpuBuf GPU command buffer to use. - * @param gpuBufSize GPU command buffer size. - * @deprecated - */ -//void GPU_Reset(u32* gxbuf, u32* gpuBuf, u32 gpuBufSize) DEPRECATED; - -/** - * @brief Sets a shader float uniform. - * @param type Type of shader to set the uniform of. - * @param startreg Start of the uniform register to set. - * @param data Data to set. - * @param numreg Number of registers to set. - * @deprecated - */ -//void GPU_SetFloatUniform(GPU_SHADER_TYPE type, u32 startreg, u32* data, u32 numreg) DEPRECATED; - -/** - * @brief Sets the viewport. - * @param depthBuffer Buffer to output depth data to. - * @param colorBuffer Buffer to output color data to. - * @param x X of the viewport. - * @param y Y of the viewport. - * @param w Width of the viewport. - * @param h Height of the viewport. - * @deprecated - */ -//void GPU_SetViewport(u32* depthBuffer, u32* colorBuffer, u32 x, u32 y, u32 w, u32 h) DEPRECATED; - -/** - * @brief Sets the current scissor test mode. - * @param mode Scissor test mode to use. - * @param x X of the scissor region. - * @param y Y of the scissor region. - * @param w Width of the scissor region. - * @param h Height of the scissor region. - * @deprecated - */ -//void GPU_SetScissorTest(GPU_SCISSORMODE mode, u32 left, u32 bottom, u32 right, u32 top) DEPRECATED; - -/** - * @brief Sets the depth map. - * @param zScale Z scale to use. - * @param zOffset Z offset to use. - * @deprecated - */ -//void GPU_DepthMap(float zScale, float zOffset) DEPRECATED; - -/** - * @brief Sets the alpha test parameters. - * @param enable Whether to enable alpha testing. - * @param function Test function to use. - * @param ref Reference value to use. - * @deprecated - */ -//void GPU_SetAlphaTest(bool enable, GPU_TESTFUNC function, u8 ref) DEPRECATED; - -/** - * @brief Sets the depth test parameters and pixel write mask. - * @note GPU_WRITEMASK values can be ORed together. - * @param enable Whether to enable depth testing. - * @param function Test function to use. - * @param writemask Pixel write mask to use. - * @deprecated - */ -//void GPU_SetDepthTestAndWriteMask(bool enable, GPU_TESTFUNC function, GPU_WRITEMASK writemask) DEPRECATED; - -/** - * @brief Sets the stencil test parameters. - * @param enable Whether to enable stencil testing. - * @param function Test function to use. - * @param ref Reference value to use. - * @param input_mask Input mask to use. - * @param write_mask Write mask to use. - * @deprecated - */ -//void GPU_SetStencilTest(bool enable, GPU_TESTFUNC function, u8 ref, u8 input_mask, u8 write_mask) DEPRECATED; - -/** - * @brief Sets the stencil test operators. - * @param sfail Operator to use on source test failure. - * @param dfail Operator to use on destination test failure. - * @param pass Operator to use on test passing. - * @deprecated - */ -//void GPU_SetStencilOp(GPU_STENCILOP sfail, GPU_STENCILOP dfail, GPU_STENCILOP pass) DEPRECATED; - -/** - * @brief Sets the face culling mode. - * @param mode Face culling mode to use. - * @deprecated - */ -//void GPU_SetFaceCulling(GPU_CULLMODE mode) DEPRECATED; - -/** - * @brief Sets the combiner buffer write parameters. - * @note Use GPU_TEV_BUFFER_WRITE_CONFIG to build the parameters. - * @note Only the first four TEV stages can write to the combiner buffer. - * @param rgb_config RGB configuration to use. - * @param alpha_config Alpha configuration to use. - * @deprecated - */ -//void GPU_SetCombinerBufferWrite(u8 rgb_config, u8 alpha_config) DEPRECATED; - -/** - * @brief Sets the alpha blending parameters. - * @note Cannot be used with GPU_SetColorLogicOp. - * @param colorEquation Blend equation to use for color components. - * @param alphaEquation Blend equation to use for the alpha component. - * @param colorSrc Source factor of color components. - * @param colorDst Destination factor of color components. - * @param alphaSrc Source factor of the alpha component. - * @param alphaDst Destination factor of the alpha component. - * @deprecated - */ -//void GPU_SetAlphaBlending(GPU_BLENDEQUATION colorEquation, GPU_BLENDEQUATION alphaEquation, -// GPU_BLENDFACTOR colorSrc, GPU_BLENDFACTOR colorDst, -// GPU_BLENDFACTOR alphaSrc, GPU_BLENDFACTOR alphaDst) DEPRECATED; - -/** - * @brief Sets the color logic operator. - * @note Cannot be used with GPU_SetAlphaBlending. - * @param op Operator to set. - * @deprecated - */ -//void GPU_SetColorLogicOp(GPU_LOGICOP op) DEPRECATED; - -/** - * @brief Sets the blending color. - * @param r Red component. - * @param g Green component. - * @param b Blue component. - * @param a Alpha component. - * @deprecated - */ -//void GPU_SetBlendingColor(u8 r, u8 g, u8 b, u8 a) DEPRECATED; - -/** - * @brief Sets the VBO attribute buffers. - * @param totalAttributes Total number of attributes. - * @param baseAddress Base address of the VBO. - * @param attributeFormats Attribute format data. - * @param attributeMask Attribute mask. - * @param attributePermutation Attribute permutations. - * @param numBuffers Number of buffers. - * @param bufferOffsets Offsets of the buffers. - * @param bufferPermutations Buffer permutations. - * @param bufferNumAttributes Numbers of attributes of the buffers. - * @deprecated - */ -//void GPU_SetAttributeBuffers(u8 totalAttributes, u32* baseAddress, u64 attributeFormats, u16 attributeMask, u64 attributePermutation, u8 numBuffers, u32 bufferOffsets[], u64 bufferPermutations[], u8 bufferNumAttributes[]) DEPRECATED; - -/** - * @brief Sets the enabled texture units. - * @param units Units to enable. OR texture unit values together to create this value. - * @deprecated - */ -//void GPU_SetTextureEnable(GPU_TEXUNIT units) DEPRECATED; - -/** - * @brief Sets the texture data of a texture unit. - * @param unit Texture unit to use. - * @param data Data to load. Must be in linear memory or VRAM. - * @param width Width of the texture. - * @param height Height of the texture. - * @param Parameters of the texture, such as filters and wrap modes. - * @param colorType Color type of the texture. - * @deprecated - */ -//void GPU_SetTexture(GPU_TEXUNIT unit, u32* data, u16 width, u16 height, u32 param, GPU_TEXCOLOR colorType) DEPRECATED; - -/** - * @brief Sets the border color of a texture unit. - * @param unit Texture unit to use. - * @param borderColor The color used for the border when using the @ref GPU_CLAMP_TO_BORDER wrap mode. - * @deprecated - */ -//void GPU_SetTextureBorderColor(GPU_TEXUNIT unit,u32 borderColor) DEPRECATED; - -/** - * @brief Sets the parameters of a texture combiner. - * @param id ID of the combiner. - * @param rgbSources RGB source configuration. - * @param alphaSources Alpha source configuration. - * @param rgbOperands RGB operand configuration. - * @param alphaOperands Alpha operand configuration. - * @param rgbCombine RGB combiner function. - * @param alphaCombine Alpha combiner function. - * @param constantColor Constant color to provide. - * @deprecated - */ -//void GPU_SetTexEnv(u8 id, u16 rgbSources, u16 alphaSources, u16 rgbOperands, u16 alphaOperands, GPU_COMBINEFUNC rgbCombine, GPU_COMBINEFUNC alphaCombine, u32 constantColor) DEPRECATED; - -/** - * @brief Draws an array of vertex data. - * @param primitive Primitive to draw. - * @param first First vertex to draw. - * @param count Number of vertices to draw. - * @deprecated - */ -//void GPU_DrawArray(GPU_Primitive_t primitive, u32 first, u32 count) DEPRECATED; - -/** - * @brief Draws vertex elements. - * @param primitive Primitive to draw. - * @param indexArray Array of vertex indices to use. - * @param n Number of vertices to draw. - * @deprecated - */ -//void GPU_DrawElements(GPU_Primitive_t primitive, u32* indexArray, u32 n) DEPRECATED; - -/** - * @brief Finishes drawing. - * @deprecated - */ -//void GPU_FinishDrawing() DEPRECATED; -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/Includes/ctrulib/gpu/gpu.h b/Includes/ctrulib/gpu/gpu.h deleted file mode 100644 index 605282e..0000000 --- a/Includes/ctrulib/gpu/gpu.h +++ /dev/null @@ -1,115 +0,0 @@ -/** - * @file gpu.h - * @brief Barebones GPU communications driver. - */ -#pragma once -#ifdef __cplusplus -extern "C" { -#endif -#include "../../types.h" -#include "registers.h" -#include "enums.h" - -/// Creates a GPU command header from its write increments, mask, and register. -#define GPUCMD_HEADER(incremental, mask, reg) (((incremental)<<31)|(((mask)&0xF)<<16)|((reg)&0x3FF)) - -extern u32* gpuCmdBuf; ///< GPU command buffer. -extern u32 gpuCmdBufSize; ///< GPU command buffer size. -extern u32 gpuCmdBufOffset; ///< GPU command buffer offset. - -/** - * @brief Sets the GPU command buffer to use. - * @param adr Pointer to the command buffer. - * @param size Size of the command buffer. - * @param offset Offset of the command buffer. - */ -void GPUCMD_SetBuffer(u32* adr, u32 size, u32 offset); - -/** - * @brief Sets the offset of the GPU command buffer. - * @param offset Offset of the command buffer. - */ -void GPUCMD_SetBufferOffset(u32 offset); - -/** - * @brief Gets the current GPU command buffer. - * @param adr Pointer to output the command buffer to. - * @param size Pointer to output the size of the command buffer to. - * @param offset Pointer to output the offset of the command buffer to. - */ -void GPUCMD_GetBuffer(u32** adr, u32* size, u32* offset); - -/** - * @brief Adds raw GPU commands to the current command buffer. - * @param cmd Buffer containing commands to add. - * @param size Size of the buffer. - */ -void GPUCMD_AddRawCommands(u32* cmd, u32 size); - -/// Executes the GPU command buffer. -void GPUCMD_Run(void); - -/// Flushes linear memory and executes the GPU command buffer. -void GPUCMD_FlushAndRun(void); - -/** - * @brief Adds a GPU command to the current command buffer. - * @param header Header of the command. - * @param param Parameters of the command. - * @param paramlength Size of the parameter buffer. - */ -void GPUCMD_Add(u32 header, u32* param, u32 paramlength); - -/// Finalizes the GPU command buffer. -void GPUCMD_Finalize(void); - -/** - * @brief Converts a 32-bit float to a 16-bit float. - * @param f Float to convert. - * @return The converted float. - */ -u32 f32tof16(float f); - -/** - * @brief Converts a 32-bit float to a 20-bit float. - * @param f Float to convert. - * @return The converted float. - */ -u32 f32tof20(float f); - -/** - * @brief Converts a 32-bit float to a 24-bit float. - * @param f Float to convert. - * @return The converted float. - */ -u32 f32tof24(float f); - -/** - * @brief Converts a 32-bit float to a 31-bit float. - * @param f Float to convert. - * @return The converted float. - */ -u32 f32tof31(float f); - -/// Adds a command with a single parameter to the current command buffer. -static inline void GPUCMD_AddSingleParam(u32 header, u32 param) -{ - GPUCMD_Add(header, ¶m, 1); -} - -/// Adds a masked register write to the current command buffer. -#define GPUCMD_AddMaskedWrite(reg, mask, val) GPUCMD_AddSingleParam(GPUCMD_HEADER(0, (mask), (reg)), (val)) -/// Adds a register write to the current command buffer. -#define GPUCMD_AddWrite(reg, val) GPUCMD_AddMaskedWrite((reg), 0xF, (val)) -/// Adds multiple masked register writes to the current command buffer. -#define GPUCMD_AddMaskedWrites(reg, mask, vals, num) GPUCMD_Add(GPUCMD_HEADER(0, (mask), (reg)), (vals), (num)) -/// Adds multiple register writes to the current command buffer. -#define GPUCMD_AddWrites(reg, vals, num) GPUCMD_AddMaskedWrites((reg), 0xF, (vals), (num)) -/// Adds multiple masked incremental register writes to the current command buffer. -#define GPUCMD_AddMaskedIncrementalWrites(reg, mask, vals, num) GPUCMD_Add(GPUCMD_HEADER(1, (mask), (reg)), (vals), (num)) -/// Adds multiple incremental register writes to the current command buffer. -#define GPUCMD_AddIncrementalWrites(reg, vals, num) GPUCMD_AddMaskedIncrementalWrites((reg), 0xF, (vals), (num)) - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/Includes/ctrulib/gpu/gx.h b/Includes/ctrulib/gpu/gx.h deleted file mode 100644 index eba61e4..0000000 --- a/Includes/ctrulib/gpu/gx.h +++ /dev/null @@ -1,138 +0,0 @@ -/** - * @file gx.h - * @brief GX commands. - */ -#pragma once -#ifdef __cplusplus -extern "C" { -#endif -#include "../../types.h" -/** - * @brief Creates a buffer dimension parameter from width and height values. - * @param w buffer width for GX_DisplayTransfer, linesize for GX_TextureCopy - * @param h buffer height for GX_DisplayTransfer, gap for GX_TextureCopy - */ -#define GX_BUFFER_DIM(w, h) (((h)<<16)|((w)&0xFFFF)) - -/** - * @brief Supported transfer pixel formats. - * @sa GSPGPU_FramebufferFormats - */ -typedef enum -{ - GX_TRANSFER_FMT_RGBA8 = 0, ///< 8-bit Red + 8-bit Green + 8-bit Blue + 8-bit Alpha - GX_TRANSFER_FMT_RGB8 = 1, ///< 8-bit Red + 8-bit Green + 8-bit Blue - GX_TRANSFER_FMT_RGB565 = 2, ///< 5-bit Red + 6-bit Green + 5-bit Blue - GX_TRANSFER_FMT_RGB5A1 = 3, ///< 5-bit Red + 5-bit Green + 5-bit Blue + 1-bit Alpha - GX_TRANSFER_FMT_RGBA4 = 4 ///< 4-bit Red + 4-bit Green + 4-bit Blue + 4-bit Alpha -} GX_TRANSFER_FORMAT; - -/** - * @brief Anti-aliasing modes - * - * Please remember that the framebuffer is sideways. - * Hence if you activate 2x1 anti-aliasing the destination dimensions are w = 240*2 and h = 400 - */ -typedef enum -{ - GX_TRANSFER_SCALE_NO = 0, ///< No anti-aliasing - GX_TRANSFER_SCALE_X = 1, ///< 2x1 anti-aliasing - GX_TRANSFER_SCALE_XY = 2, ///< 2x2 anti-aliasing -} GX_TRANSFER_SCALE; - -/// GX transfer control flags -typedef enum -{ - GX_FILL_TRIGGER = 0x001, ///< Trigger the PPF event - GX_FILL_FINISHED = 0x002, ///< Indicates if the memory fill is complete. You should not use it when requesting a transfer. - GX_FILL_16BIT_DEPTH = 0x000, ///< The buffer has a 16 bit per pixel depth - GX_FILL_24BIT_DEPTH = 0x100, ///< The buffer has a 24 bit per pixel depth - GX_FILL_32BIT_DEPTH = 0x200, ///< The buffer has a 32 bit per pixel depth -} GX_FILL_CONTROL; - -/// Creates a transfer vertical flip flag. -#define GX_TRANSFER_FLIP_VERT(x) ((x)<<0) -/// Creates a transfer tiled output flag. -#define GX_TRANSFER_OUT_TILED(x) ((x)<<1) -/// Creates a transfer raw copy flag. -#define GX_TRANSFER_RAW_COPY(x) ((x)<<3) -/// Creates a transfer input format flag. -#define GX_TRANSFER_IN_FORMAT(x) ((x)<<8) -/// Creates a transfer output format flag. -#define GX_TRANSFER_OUT_FORMAT(x) ((x)<<12) -/// Creates a transfer scaling flag. -#define GX_TRANSFER_SCALING(x) ((x)<<24) - -/// Command list flag bit 0. -#define GX_CMDLIST_BIT0 BIT(0) -/// Flushes the command list. -#define GX_CMDLIST_FLUSH BIT(1) - -extern u32* gxCmdBuf; ///< GX command buffer. - -/** - * @brief Requests a DMA. - * @param src Source to DMA from. - * @param dst Destination to DMA to. - * @param length Length of data to transfer. - */ -Result GX_RequestDma(u32* src, u32* dst, u32 length); - -/** - * @brief Processes a GPU command list. - * @param buf0a Command list address. - * @param buf0s Command list size. - * @param flags Flags to process with. - */ -Result GX_ProcessCommandList(u32* buf0a, u32 buf0s, u8 flags); - -/** - * @brief Fills the memory of two buffers with the given values. - * @param buf0a Start address of the first buffer. - * @param buf0v Dimensions of the first buffer. - * @param buf0e End address of the first buffer. - * @param control0 Value to fill the first buffer with. - * @param buf1a Start address of the second buffer. - * @param buf1v Dimensions of the second buffer. - * @param buf1e End address of the second buffer. - * @param control1 Value to fill the second buffer with. - */ -Result GX_MemoryFill(u32* buf0a, u32 buf0v, u32* buf0e, u16 control0, u32* buf1a, u32 buf1v, u32* buf1e, u16 control1); - -/** - * @brief Initiates a display transfer. - * @note The PPF event will be signaled on completion. - * @param inadr Address of the input. - * @param indim Dimensions of the input. - * @param outadr Address of the output. - * @param outdim Dimensions of the output. - * @param flags Flags to transfer with. - */ -Result GX_DisplayTransfer(u32* inadr, u32 indim, u32* outadr, u32 outdim, u32 flags); - -/** - * @brief Initiates a texture copy. - * @note The PPF event will be signaled on completion. - * @param inadr Address of the input. - * @param indim Dimensions of the input. - * @param outadr Address of the output. - * @param outdim Dimensions of the output. - * @param size Size of the data to transfer. - * @param flags Flags to transfer with. - */ -Result GX_TextureCopy(u32* inadr, u32 indim, u32* outadr, u32 outdim, u32 size, u32 flags); - -/** - * @brief Flushes the cache regions of three buffers. - * @param buf0a Address of the first buffer. - * @param buf0s Size of the first buffer. - * @param buf1a Address of the second buffer. - * @param buf1s Size of the second buffer. - * @param buf2a Address of the third buffer. - * @param buf2s Size of the third buffer. - */ -Result GX_FlushCacheRegions(u32* buf0a, u32 buf0s, u32* buf1a, u32 buf1s, u32* buf2a, u32 buf2s); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/Includes/ctrulib/gpu/registers.h b/Includes/ctrulib/gpu/registers.h deleted file mode 100644 index bf28cb2..0000000 --- a/Includes/ctrulib/gpu/registers.h +++ /dev/null @@ -1,773 +0,0 @@ -/** - * @file registers.h - * @description GPU registers. - */ -#pragma once -#ifdef __cplusplus -extern "C" { -#endif - -///@name Miscellaneous registers (0x000-0x03F) -///@{ -#define GPUREG_0000 0x0000 ///< Unknown. -#define GPUREG_0001 0x0001 ///< Unknown. -#define GPUREG_0002 0x0002 ///< Unknown. -#define GPUREG_0003 0x0003 ///< Unknown. -#define GPUREG_0004 0x0004 ///< Unknown. -#define GPUREG_0005 0x0005 ///< Unknown. -#define GPUREG_0006 0x0006 ///< Unknown. -#define GPUREG_0007 0x0007 ///< Unknown. -#define GPUREG_0008 0x0008 ///< Unknown. -#define GPUREG_0009 0x0009 ///< Unknown. -#define GPUREG_000A 0x000A ///< Unknown. -#define GPUREG_000B 0x000B ///< Unknown. -#define GPUREG_000C 0x000C ///< Unknown. -#define GPUREG_000D 0x000D ///< Unknown. -#define GPUREG_000E 0x000E ///< Unknown. -#define GPUREG_000F 0x000F ///< Unknown. -#define GPUREG_FINALIZE 0x0010 ///< Used to finalize GPU drawing. -#define GPUREG_0011 0x0011 ///< Unknown. -#define GPUREG_0012 0x0012 ///< Unknown. -#define GPUREG_0013 0x0013 ///< Unknown. -#define GPUREG_0014 0x0014 ///< Unknown. -#define GPUREG_0015 0x0015 ///< Unknown. -#define GPUREG_0016 0x0016 ///< Unknown. -#define GPUREG_0017 0x0017 ///< Unknown. -#define GPUREG_0018 0x0018 ///< Unknown. -#define GPUREG_0019 0x0019 ///< Unknown. -#define GPUREG_001A 0x001A ///< Unknown. -#define GPUREG_001B 0x001B ///< Unknown. -#define GPUREG_001C 0x001C ///< Unknown. -#define GPUREG_001D 0x001D ///< Unknown. -#define GPUREG_001E 0x001E ///< Unknown. -#define GPUREG_001F 0x001F ///< Unknown. -#define GPUREG_0020 0x0020 ///< Unknown. -#define GPUREG_0021 0x0021 ///< Unknown. -#define GPUREG_0022 0x0022 ///< Unknown. -#define GPUREG_0023 0x0023 ///< Unknown. -#define GPUREG_0024 0x0024 ///< Unknown. -#define GPUREG_0025 0x0025 ///< Unknown. -#define GPUREG_0026 0x0026 ///< Unknown. -#define GPUREG_0027 0x0027 ///< Unknown. -#define GPUREG_0028 0x0028 ///< Unknown. -#define GPUREG_0029 0x0029 ///< Unknown. -#define GPUREG_002A 0x002A ///< Unknown. -#define GPUREG_002B 0x002B ///< Unknown. -#define GPUREG_002C 0x002C ///< Unknown. -#define GPUREG_002D 0x002D ///< Unknown. -#define GPUREG_002E 0x002E ///< Unknown. -#define GPUREG_002F 0x002F ///< Unknown. -#define GPUREG_0030 0x0030 ///< Unknown. -#define GPUREG_0031 0x0031 ///< Unknown. -#define GPUREG_0032 0x0032 ///< Unknown. -#define GPUREG_0033 0x0033 ///< Unknown. -#define GPUREG_0034 0x0034 ///< Unknown. -#define GPUREG_0035 0x0035 ///< Unknown. -#define GPUREG_0036 0x0036 ///< Unknown. -#define GPUREG_0037 0x0037 ///< Unknown. -#define GPUREG_0038 0x0038 ///< Unknown. -#define GPUREG_0039 0x0039 ///< Unknown. -#define GPUREG_003A 0x003A ///< Unknown. -#define GPUREG_003B 0x003B ///< Unknown. -#define GPUREG_003C 0x003C ///< Unknown. -#define GPUREG_003D 0x003D ///< Unknown. -#define GPUREG_003E 0x003E ///< Unknown. -#define GPUREG_003F 0x003F ///< Unknown. -///@} - -///@name Rasterizer registers (0x040-0x07F) -///@{ -#define GPUREG_FACECULLING_CONFIG 0x0040 ///< Face culling configuration. -#define GPUREG_VIEWPORT_WIDTH 0x0041 ///< Viewport width. -#define GPUREG_VIEWPORT_INVW 0x0042 ///< Inverted viewport width. -#define GPUREG_VIEWPORT_HEIGHT 0x0043 ///< Viewport height. -#define GPUREG_VIEWPORT_INVH 0x0044 ///< Inverted viewport height. -#define GPUREG_0045 0x0045 ///< Unknown -#define GPUREG_0046 0x0046 ///< Unknown -#define GPUREG_FRAGOP_CLIP 0x0047 ///< Unknown -#define GPUREG_FRAGOP_CLIP_DATA0 0x0048 ///< Unknown -#define GPUREG_FRAGOP_CLIP_DATA1 0x0049 ///< Unknown -#define GPUREG_FRAGOP_CLIP_DATA2 0x004A ///< Unknown -#define GPUREG_FRAGOP_CLIP_DATA3 0x004B ///< Unknown -#define GPUREG_004C 0x004C ///< Unknown -#define GPUREG_DEPTHMAP_SCALE 0x004D ///< Depth map scale. -#define GPUREG_DEPTHMAP_OFFSET 0x004E ///< Depth map offset. -#define GPUREG_SH_OUTMAP_TOTAL 0x004F ///< Shader output map total. -#define GPUREG_SH_OUTMAP_O0 0x0050 ///< Shader output map 0. -#define GPUREG_SH_OUTMAP_O1 0x0051 ///< Shader output map 1. -#define GPUREG_SH_OUTMAP_O2 0x0052 ///< Shader output map 2. -#define GPUREG_SH_OUTMAP_O3 0x0053 ///< Shader output map 3. -#define GPUREG_SH_OUTMAP_O4 0x0054 ///< Shader output map 4. -#define GPUREG_SH_OUTMAP_O5 0x0055 ///< Shader output map 5. -#define GPUREG_SH_OUTMAP_O6 0x0056 ///< Shader output map 6. -#define GPUREG_0057 0x0057 ///< Unknown -#define GPUREG_0058 0x0058 ///< Unknown -#define GPUREG_0059 0x0059 ///< Unknown -#define GPUREG_005A 0x005A ///< Unknown -#define GPUREG_005B 0x005B ///< Unknown -#define GPUREG_005C 0x005C ///< Unknown -#define GPUREG_005D 0x005D ///< Unknown -#define GPUREG_005E 0x005E ///< Unknown -#define GPUREG_005F 0x005F ///< Unknown -#define GPUREG_0060 0x0060 ///< Unknown -#define GPUREG_EARLYDEPTH_FUNC 0x0061 ///< Unknown -#define GPUREG_EARLYDEPTH_TEST1 0x0062 ///< Unknown -#define GPUREG_EARLYDEPTH_CLEAR 0x0063 ///< Unknown -#define GPUREG_SH_OUTATTR_MODE 0x0064 ///< Shader output attributes mode. -#define GPUREG_SCISSORTEST_MODE 0x0065 ///< Scissor test mode. -#define GPUREG_SCISSORTEST_POS 0x0066 ///< Scissor test position. -#define GPUREG_SCISSORTEST_DIM 0x0067 ///< Scissor text dimensions. -#define GPUREG_VIEWPORT_XY 0x0068 ///< Viewport X and Y. -#define GPUREG_0069 0x0069 ///< Unknown -#define GPUREG_EARLYDEPTH_DATA 0x006A ///< Unknown -#define GPUREG_006B 0x006B ///< Unknown -#define GPUREG_006C 0x006C ///< Unknown -#define GPUREG_DEPTHMAP_ENABLE 0x006D ///< Depth map enable. -#define GPUREG_RENDERBUF_DIM 0x006E ///< Renderbuffer dimensions. -#define GPUREG_SH_OUTATTR_CLOCK 0x006F ///< Shader output attributes clock enable. -#define GPUREG_0070 0x0070 ///< Unknown -#define GPUREG_0071 0x0071 ///< Unknown -#define GPUREG_0072 0x0072 ///< Unknown -#define GPUREG_0073 0x0073 ///< Unknown -#define GPUREG_0074 0x0074 ///< Unknown -#define GPUREG_0075 0x0075 ///< Unknown -#define GPUREG_0076 0x0076 ///< Unknown -#define GPUREG_0077 0x0077 ///< Unknown -#define GPUREG_0078 0x0078 ///< Unknown -#define GPUREG_0079 0x0079 ///< Unknown -#define GPUREG_007A 0x007A ///< Unknown -#define GPUREG_007B 0x007B ///< Unknown -#define GPUREG_007C 0x007C ///< Unknown -#define GPUREG_007D 0x007D ///< Unknown -#define GPUREG_007E 0x007E ///< Unknown -#define GPUREG_007F 0x007F ///< Unknown -///@} - -///@name Texturing registers (0x080-0x0FF) -///@{ -#define GPUREG_TEXUNIT_CONFIG 0x0080 ///< Texture unit configuration. -#define GPUREG_TEXUNIT0_BORDER_COLOR 0x0081 ///< Texture unit 0 border color. -#define GPUREG_TEXUNIT0_DIM 0x0082 ///< Texture unit 0 dimensions. -#define GPUREG_TEXUNIT0_PARAM 0x0083 ///< Texture unit 0 parameters. -#define GPUREG_TEXUNIT0_LOD 0x0084 ///< Texture unit 0 LOD. -#define GPUREG_TEXUNIT0_ADDR1 0x0085 ///< Texture unit 0 address. -#define GPUREG_TEXUNIT0_ADDR2 0x0086 ///< Unknown. -#define GPUREG_TEXUNIT0_ADDR3 0x0087 ///< Unknown. -#define GPUREG_TEXUNIT0_ADDR4 0x0088 ///< Unknown. -#define GPUREG_TEXUNIT0_ADDR5 0x0089 ///< Unknown. -#define GPUREG_TEXUNIT0_ADDR6 0x008A ///< Unknown. -#define GPUREG_TEXUNIT0_SHADOW 0x008B ///< Unknown. -#define GPUREG_008C 0x008C ///< Unknown. -#define GPUREG_008D 0x008D ///< Unknown. -#define GPUREG_TEXUNIT0_TYPE 0x008E ///< Texture unit 0 type. -#define GPUREG_LIGHTING_ENABLE0 0x008F ///< Lighting toggle. -#define GPUREG_0090 0x0090 ///< Unknown. -#define GPUREG_TEXUNIT1_BORDER_COLOR 0x0091 ///< Texture unit 1 border color. -#define GPUREG_TEXUNIT1_DIM 0x0092 ///< Texture unit 1 dimensions. -#define GPUREG_TEXUNIT1_PARAM 0x0093 ///< Texture unit 1 parameters. -#define GPUREG_TEXUNIT1_LOD 0x0094 ///< Texture unit 1 LOD. -#define GPUREG_TEXUNIT1_ADDR 0x0095 ///< Texture unit 1 address. -#define GPUREG_TEXUNIT1_TYPE 0x0096 ///< Texture unit 1 type. -#define GPUREG_0097 0x0097 ///< Unknown. -#define GPUREG_0098 0x0098 ///< Unknown. -#define GPUREG_TEXUNIT2_BORDER_COLOR 0x0099 ///< Texture unit 2 border color. -#define GPUREG_TEXUNIT2_DIM 0x009A ///< Texture unit 2 dimensions. -#define GPUREG_TEXUNIT2_PARAM 0x009B ///< Texture unit 2 parameters. -#define GPUREG_TEXUNIT2_LOD 0x009C ///< Texture unit 2 LOD. -#define GPUREG_TEXUNIT2_ADDR 0x009D ///< Texture unit 2 address. -#define GPUREG_TEXUNIT2_TYPE 0x009E ///< Texture unit 2 type. -#define GPUREG_009F 0x009F ///< Unknown. -#define GPUREG_00A0 0x00A0 ///< Unknown. -#define GPUREG_00A1 0x00A1 ///< Unknown. -#define GPUREG_00A2 0x00A2 ///< Unknown. -#define GPUREG_00A3 0x00A3 ///< Unknown. -#define GPUREG_00A4 0x00A4 ///< Unknown. -#define GPUREG_00A5 0x00A5 ///< Unknown. -#define GPUREG_00A6 0x00A6 ///< Unknown. -#define GPUREG_00A7 0x00A7 ///< Unknown. -#define GPUREG_TEXUNIT3_PROCTEX0 0x00A8 ///< Unknown. -#define GPUREG_TEXUNIT3_PROCTEX1 0x00A9 ///< Unknown. -#define GPUREG_TEXUNIT3_PROCTEX2 0x00AA ///< Unknown. -#define GPUREG_TEXUNIT3_PROCTEX3 0x00AB ///< Unknown. -#define GPUREG_TEXUNIT3_PROCTEX4 0x00A ///< Unknown. -#define GPUREG_TEXUNIT3_PROCTEX5 0x00D ///< Unknown. -#define GPUREG_00AE 0x00AE ///< Unknown. -#define GPUREG_PROCTEX_LUT 0x00AF ///< Unknown. -#define GPUREG_PROCTEX_LUT_DATA0 0x00B0 ///< Unknown. -#define GPUREG_PROCTEX_LUT_DATA1 0x00B1 ///< Unknown. -#define GPUREG_PROCTEX_LUT_DATA2 0x00B2 ///< Unknown. -#define GPUREG_PROCTEX_LUT_DATA3 0x00B3 ///< Unknown. -#define GPUREG_PROCTEX_LUT_DATA4 0x00B4 ///< Unknown. -#define GPUREG_PROCTEX_LUT_DATA5 0x00B5 ///< Unknown. -#define GPUREG_PROCTEX_LUT_DATA6 0x00B6 ///< Unknown. -#define GPUREG_PROCTEX_LUT_DATA7 0x00B7 ///< Unknown. -#define GPUREG_00B8 0x00B8 ///< Unknown. -#define GPUREG_00B9 0x00B9 ///< Unknown. -#define GPUREG_00BA 0x00BA ///< Unknown. -#define GPUREG_00BB 0x00BB ///< Unknown. -#define GPUREG_00BC 0x00BC ///< Unknown. -#define GPUREG_00BD 0x00BD ///< Unknown. -#define GPUREG_00BE 0x00BE ///< Unknown. -#define GPUREG_00BF 0x00BF ///< Unknown. -#define GPUREG_TEXENV0_SOURCE 0x00C0 ///< Texture env 0 source. -#define GPUREG_TEXENV0_OPERAND 0x00C1 ///< Texture env 0 operand. -#define GPUREG_TEXENV0_COMBINER 0x00C2 ///< Texture env 0 combiner. -#define GPUREG_TEXENV0_COLOR 0x00C3 ///< Texture env 0 color. -#define GPUREG_TEXENV0_SCALE 0x00C4 ///< Texture env 0 scale. -#define GPUREG_00C5 0x00C5 ///< Unknown. -#define GPUREG_00C6 0x00C6 ///< Unknown. -#define GPUREG_00C7 0x00C7 ///< Unknown. -#define GPUREG_TEXENV1_SOURCE 0x00C8 ///< Texture env 1 source. -#define GPUREG_TEXENV1_OPERAND 0x00C9 ///< Texture env 1 operand. -#define GPUREG_TEXENV1_COMBINER 0x00CA ///< Texture env 1 combiner. -#define GPUREG_TEXENV1_COLOR 0x00CB ///< Texture env 1 color. -#define GPUREG_TEXENV1_SCALE 0x00CC ///< Texture env 1 scale. -#define GPUREG_00CD 0x00CD ///< Unknown. -#define GPUREG_00CE 0x00CE ///< Unknown. -#define GPUREG_00CF 0x00CF ///< Unknown. -#define GPUREG_TEXENV2_SOURCE 0x00D0 ///< Texture env 2 source. -#define GPUREG_TEXENV2_OPERAND 0x00D1 ///< Texture env 2 operand. -#define GPUREG_TEXENV2_COMBINER 0x00D2 ///< Texture env 2 combiner. -#define GPUREG_TEXENV2_COLOR 0x00D3 ///< Texture env 2 color. -#define GPUREG_TEXENV2_SCALE 0x00D4 ///< Texture env 2 scale. -#define GPUREG_00D5 0x00D5 ///< Unknown. -#define GPUREG_00D6 0x00D6 ///< Unknown. -#define GPUREG_00D7 0x00D7 ///< Unknown. -#define GPUREG_TEXENV3_SOURCE 0x00D8 ///< Texture env 3 source. -#define GPUREG_TEXENV3_OPERAND 0x00D9 ///< Texture env 3 operand. -#define GPUREG_TEXENV3_COMBINER 0x00DA ///< Texture env 3 combiner. -#define GPUREG_TEXENV3_COLOR 0x00DB ///< Texture env 3 color. -#define GPUREG_TEXENV3_SCALE 0x00DC ///< Texture env 3 scale. -#define GPUREG_00DD 0x00DD ///< Unknown. -#define GPUREG_00DE 0x00DE ///< Unknown. -#define GPUREG_00DF 0x00DF ///< Unknown. -#define GPUREG_TEXENV_UPDATE_BUFFER 0x00E0 ///< Texture env buffer update flag. -#define GPUREG_FOG_COLOR 0x00E1 ///< Unknown. -#define GPUREG_00E2 0x00E2 ///< Unknown. -#define GPUREG_00E3 0x00E3 ///< Unknown. -#define GPUREG_GAS_ATTENUATION 0x00E4 ///< Unknown. -#define GPUREG_GAS_ACCMAX 0x00E5 ///< Unknown. -#define GPUREG_FOG_LUT_INDEX 0x00E6 ///< Unknown. -#define GPUREG_00E7 0x00E7 ///< Unknown. -#define GPUREG_FOG_LUT_DATA0 0x00E8 ///< Unknown. -#define GPUREG_FOG_LUT_DATA1 0x00E9 ///< Unknown. -#define GPUREG_FOG_LUT_DATA2 0x00EA ///< Unknown. -#define GPUREG_FOG_LUT_DATA3 0x00EB ///< Unknown. -#define GPUREG_FOG_LUT_DATA4 0x00EC ///< Unknown. -#define GPUREG_FOG_LUT_DATA5 0x00ED ///< Unknown. -#define GPUREG_FOG_LUT_DATA6 0x00EE ///< Unknown. -#define GPUREG_FOG_LUT_DATA7 0x00EF ///< Unknown. -#define GPUREG_TEXENV4_SOURCE 0x00F0 ///< Texture env 4 source. -#define GPUREG_TEXENV4_OPERAND 0x00F1 ///< Texture env 4 operand. -#define GPUREG_TEXENV4_COMBINER 0x00F2 ///< Texture env 4 combiner. -#define GPUREG_TEXENV4_COLOR 0x00F3 ///< Texture env 4 color. -#define GPUREG_TEXENV4_SCALE 0x00F4 ///< Texture env 4 scale. -#define GPUREG_00F5 0x00F5 ///< Unknown. -#define GPUREG_00F6 0x00F6 ///< Unknown. -#define GPUREG_00F7 0x00F7 ///< Unknown. -#define GPUREG_TEXENV5_SOURCE 0x00F8 ///< Texture env 5 source. -#define GPUREG_TEXENV5_OPERAND 0x00F9 ///< Texture env 5 operand. -#define GPUREG_TEXENV5_COMBINER 0x00FA ///< Texture env 5 combiner. -#define GPUREG_TEXENV5_COLOR 0x00FB ///< Texture env 5 color. -#define GPUREG_TEXENV5_SCALE 0x00FC ///< Texture env 5 scale. -#define GPUREG_TEXENV_BUFFER_COLOR 0x00FD ///< Texture env buffer color. -#define GPUREG_00FE 0x00FE ///< Unknown. -#define GPUREG_00FF 0x00FF ///< Unknown. -///@} - -///@name Framebuffer registers (0x100-0x13F) -///@{ -#define GPUREG_COLOR_OPERATION 0x0100 ///< Configures fragment operation and blend mode. -#define GPUREG_BLEND_FUNC 0x0101 ///< Blend function configuration. -#define GPUREG_LOGIC_OP 0x0102 ///< Logical operator configuration. -#define GPUREG_BLEND_COLOR 0x0103 ///< Blend color. -#define GPUREG_FRAGOP_ALPHA_TEST 0x0104 ///< Alpha test configuration. -#define GPUREG_STENCIL_TEST 0x0105 ///< Stencil test configuration. -#define GPUREG_STENCIL_OP 0x0106 ///< Stencil test operation. -#define GPUREG_DEPTH_COLOR_MASK 0x0107 ///< Depth test and color mask configuration. -#define GPUREG_0108 0x0108 ///< Unknown. -#define GPUREG_0109 0x0109 ///< Unknown. -#define GPUREG_010A 0x010A ///< Unknown. -#define GPUREG_010B 0x010B ///< Unknown. -#define GPUREG_010C 0x010C ///< Unknown. -#define GPUREG_010D 0x010D ///< Unknown. -#define GPUREG_010E 0x010E ///< Unknown. -#define GPUREG_010F 0x010F ///< Unknown. -#define GPUREG_FRAMEBUFFER_INVALIDATE 0x0110 ///< Invalidates the frame buffer. -#define GPUREG_FRAMEBUFFER_FLUSH 0x0111 ///< Flushes the frame buffer. -#define GPUREG_COLORBUFFER_READ 0x0112 ///< Reads from the color buffer. -#define GPUREG_COLORBUFFER_WRITE 0x0113 ///< Writes to the color buffer. -#define GPUREG_DEPTHBUFFER_READ 0x0114 ///< Reads from the depth buffer. -#define GPUREG_DEPTHBUFFER_WRITE 0x0115 ///< Writes to the depth buffer. -#define GPUREG_DEPTHBUFFER_FORMAT 0x0116 ///< Depth buffer format. -#define GPUREG_COLORBUFFER_FORMAT 0x0117 ///< Color buffer format. -#define GPUREG_EARLYDEPTH_TEST2 0x0118 ///< Unknown. -#define GPUREG_0119 0x0119 ///< Unknown. -#define GPUREG_011A 0x011A ///< Unknown. -#define GPUREG_FRAMEBUFFER_BLOCK32 0x011B ///< Frame buffer block 32. -#define GPUREG_DEPTHBUFFER_LOC 0x011C ///< Depth buffer location. -#define GPUREG_COLORBUFFER_LOC 0x011D ///< Color buffer location. -#define GPUREG_FRAMEBUFFER_DIM 0x011E ///< Frame buffer dimensions. -#define GPUREG_011F 0x011F ///< Unknown. -#define GPUREG_GAS_LIGHT_XY 0x0120 ///< Unknown. -#define GPUREG_GAS_LIGHT_Z 0x0121 ///< Unknown. -#define GPUREG_GAS_LIGHT_Z_COLOR 0x0122 ///< Unknown. -#define GPUREG_GAS_LUT_INDEX 0x0123 ///< Unknown. -#define GPUREG_GAS_LUT_DATA 0x0124 ///< Unknown. -#define GPUREG_0125 0x0125 ///< Unknown. -#define GPUREG_GAS_DELTAZ_DEPTH 0x0126 ///< Unknown. -#define GPUREG_0127 0x0127 ///< Unknown. -#define GPUREG_0128 0x0128 ///< Unknown. -#define GPUREG_0129 0x0129 ///< Unknown. -#define GPUREG_012A 0x012A ///< Unknown. -#define GPUREG_012B 0x012B ///< Unknown. -#define GPUREG_012C 0x012C ///< Unknown. -#define GPUREG_012D 0x012D ///< Unknown. -#define GPUREG_012E 0x012E ///< Unknown. -#define GPUREG_012F 0x012F ///< Unknown. -#define GPUREG_FRAGOP_SHADOW 0x0130 ///< Unknown. -#define GPUREG_0131 0x0131 ///< Unknown. -#define GPUREG_0132 0x0132 ///< Unknown. -#define GPUREG_0133 0x0133 ///< Unknown. -#define GPUREG_0134 0x0134 ///< Unknown. -#define GPUREG_0135 0x0135 ///< Unknown. -#define GPUREG_0136 0x0136 ///< Unknown. -#define GPUREG_0137 0x0137 ///< Unknown. -#define GPUREG_0138 0x0138 ///< Unknown. -#define GPUREG_0139 0x0139 ///< Unknown. -#define GPUREG_013A 0x013A ///< Unknown. -#define GPUREG_013B 0x013B ///< Unknown. -#define GPUREG_013C 0x013C ///< Unknown. -#define GPUREG_013D 0x013D ///< Unknown. -#define GPUREG_013E 0x013E ///< Unknown. -#define GPUREG_013F 0x013F ///< Unknown. -///@} - -///@name Fragment lighting registers (0x140-0x1FF) -///@{ -#define GPUREG_LIGHT0_SPECULAR0 0x0140 ///< Light 0 specular lighting. -#define GPUREG_LIGHT0_SPECULAR1 0x0141 ///< Light 0 specular lighting. -#define GPUREG_LIGHT0_DIFFUSE 0x0142 ///< Light 0 diffuse lighting. -#define GPUREG_LIGHT0_AMBIENT 0x0143 ///< Light 0 ambient lighting. -#define GPUREG_LIGHT0_XY 0x0144 ///< Light 0 X and Y. -#define GPUREG_LIGHT0_Z 0x0145 ///< Light 0 Z. -#define GPUREG_LIGHT0_SPOTDIR_XY 0x0146 ///< Light 0 spotlight direction X and Y. -#define GPUREG_LIGHT0_SPOTDIR_Z 0x0147 ///< Light 0 spotlight direction Z. -#define GPUREG_0148 0x0148 ///< Unknown. -#define GPUREG_LIGHT0_CONFIG 0x0149 ///< Light 0 configuration. -#define GPUREG_LIGHT0_ATTENUATION_BIAS 0x014A ///< Light 0 attenuation bias. -#define GPUREG_LIGHT0_ATTENUATION_SCALE 0x014B ///< Light 0 attenuation scale. -#define GPUREG_014C 0x014C ///< Unknown. -#define GPUREG_014D 0x014D ///< Unknown. -#define GPUREG_014E 0x014E ///< Unknown. -#define GPUREG_014F 0x014F ///< Unknown. -#define GPUREG_LIGHT1_SPECULAR0 0x0150 ///< Light 1 specular lighting. -#define GPUREG_LIGHT1_SPECULAR1 0x0151 ///< Light 1 specular lighting. -#define GPUREG_LIGHT1_DIFFUSE 0x0152 ///< Light 1 diffuse lighting. -#define GPUREG_LIGHT1_AMBIENT 0x0153 ///< Light 1 ambient lighting. -#define GPUREG_LIGHT1_XY 0x0154 ///< Light 1 X and Y. -#define GPUREG_LIGHT1_Z 0x0155 ///< Light 1 Z. -#define GPUREG_LIGHT1_SPOTDIR_XY 0x0156 ///< Light 1 spotlight direction X and Y. -#define GPUREG_LIGHT1_SPOTDIR_Z 0x0157 ///< Light 1 spotlight direction Z. -#define GPUREG_0158 0x0158 ///< Unknown. -#define GPUREG_LIGHT1_CONFIG 0x0159 ///< Light 1 configuration. -#define GPUREG_LIGHT1_ATTENUATION_BIAS 0x015A ///< Light 1 attenuation bias. -#define GPUREG_LIGHT1_ATTENUATION_SCALE 0x015B ///< Light 1 attenuation scale. -#define GPUREG_015C 0x015C ///< Unknown. -#define GPUREG_015D 0x015D ///< Unknown. -#define GPUREG_015E 0x015E ///< Unknown. -#define GPUREG_015F 0x015F ///< Unknown. -#define GPUREG_LIGHT2_SPECULAR0 0x0160 ///< Light 2 specular lighting. -#define GPUREG_LIGHT2_SPECULAR1 0x0161 ///< Light 2 specular lighting. -#define GPUREG_LIGHT2_DIFFUSE 0x0162 ///< Light 2 diffuse lighting. -#define GPUREG_LIGHT2_AMBIENT 0x0163 ///< Light 2 ambient lighting. -#define GPUREG_LIGHT2_XY 0x0164 ///< Light 2 X and Y. -#define GPUREG_LIGHT2_Z 0x0165 ///< Light 2 Z. -#define GPUREG_LIGHT2_SPOTDIR_XY 0x0166 ///< Light 2 spotlight direction X and Y. -#define GPUREG_LIGHT2_SPOTDIR_Z 0x0167 ///< Light 2 spotlight direction Z. -#define GPUREG_0168 0x0168 ///< Unknown. -#define GPUREG_LIGHT2_CONFIG 0x0169 ///< Light 2 configuration. -#define GPUREG_LIGHT2_ATTENUATION_BIAS 0x016A ///< Light 2 attenuation bias. -#define GPUREG_LIGHT2_ATTENUATION_SCALE 0x016B ///< Light 2 attenuation scale. -#define GPUREG_016C 0x016C ///< Unknown. -#define GPUREG_016D 0x016D ///< Unknown. -#define GPUREG_016E 0x016E ///< Unknown. -#define GPUREG_016F 0x016F ///< Unknown. -#define GPUREG_LIGHT3_SPECULAR0 0x0170 ///< Light 3 specular lighting. -#define GPUREG_LIGHT3_SPECULAR1 0x0171 ///< Light 3 specular lighting. -#define GPUREG_LIGHT3_DIFFUSE 0x0172 ///< Light 3 diffuse lighting. -#define GPUREG_LIGHT3_AMBIENT 0x0173 ///< Light 3 ambient lighting. -#define GPUREG_LIGHT3_XY 0x0174 ///< Light 3 X and Y. -#define GPUREG_LIGHT3_Z 0x0175 ///< Light 3 Z. -#define GPUREG_LIGHT3_SPOTDIR_XY 0x0176 ///< Light 3 spotlight direction X and Y. -#define GPUREG_LIGHT3_SPOTDIR_Z 0x0177 ///< Light 3 spotlight direction Z. -#define GPUREG_0178 0x0178 ///< Unknown. -#define GPUREG_LIGHT3_CONFIG 0x0179 ///< Light 3 configuration. -#define GPUREG_LIGHT3_ATTENUATION_BIAS 0x017A ///< Light 3 attenuation bias. -#define GPUREG_LIGHT3_ATTENUATION_SCALE 0x017B ///< Light 3 attenuation scale. -#define GPUREG_017C 0x017C ///< Unknown. -#define GPUREG_017D 0x017D ///< Unknown. -#define GPUREG_017E 0x017E ///< Unknown. -#define GPUREG_017F 0x017F ///< Unknown. -#define GPUREG_LIGHT4_SPECULAR0 0x0180 ///< Light 4 specular lighting. -#define GPUREG_LIGHT4_SPECULAR1 0x0181 ///< Light 4 specular lighting. -#define GPUREG_LIGHT4_DIFFUSE 0x0182 ///< Light 4 diffuse lighting. -#define GPUREG_LIGHT4_AMBIENT 0x0183 ///< Light 4 ambient lighting. -#define GPUREG_LIGHT4_XY 0x0184 ///< Light 4 X and Y. -#define GPUREG_LIGHT4_Z 0x0185 ///< Light 4 Z. -#define GPUREG_LIGHT4_SPOTDIR_XY 0x0186 ///< Light 4 spotlight direction X and Y. -#define GPUREG_LIGHT4_SPOTDIR_Z 0x0187 ///< Light 4 spotlight direction Z. -#define GPUREG_0188 0x0188 ///< Unknown. -#define GPUREG_LIGHT4_CONFIG 0x0189 ///< Light 4 configuration. -#define GPUREG_LIGHT4_ATTENUATION_BIAS 0x018A ///< Light 4 attenuation bias. -#define GPUREG_LIGHT4_ATTENUATION_SCALE 0x018B ///< Light 4 attenuation scale. -#define GPUREG_018C 0x018C ///< Unknown. -#define GPUREG_018D 0x018D ///< Unknown. -#define GPUREG_018E 0x018E ///< Unknown. -#define GPUREG_018F 0x018F ///< Unknown. -#define GPUREG_LIGHT5_SPECULAR0 0x0190 ///< Light 5 specular lighting. -#define GPUREG_LIGHT5_SPECULAR1 0x0191 ///< Light 5 specular lighting. -#define GPUREG_LIGHT5_DIFFUSE 0x0192 ///< Light 5 diffuse lighting. -#define GPUREG_LIGHT5_AMBIENT 0x0193 ///< Light 5 ambient lighting. -#define GPUREG_LIGHT5_XY 0x0194 ///< Light 5 X and Y. -#define GPUREG_LIGHT5_Z 0x0195 ///< Light 5 Z. -#define GPUREG_LIGHT5_SPOTDIR_XY 0x0196 ///< Light 5 spotlight direction X and Y. -#define GPUREG_LIGHT5_SPOTDIR_Z 0x0197 ///< Light 5 spotlight direction Z. -#define GPUREG_0198 0x0198 ///< Unknown. -#define GPUREG_LIGHT5_CONFIG 0x0199 ///< Light 5 configuration. -#define GPUREG_LIGHT5_ATTENUATION_BIAS 0x019A ///< Light 5 attenuation bias. -#define GPUREG_LIGHT5_ATTENUATION_SCALE 0x019B ///< Light 5 attenuation scale. -#define GPUREG_019C 0x019C ///< Unknown. -#define GPUREG_019D 0x019D ///< Unknown. -#define GPUREG_019E 0x019E ///< Unknown. -#define GPUREG_019F 0x019F ///< Unknown. -#define GPUREG_LIGHT6_SPECULAR0 0x01A0 ///< Light 6 specular lighting. -#define GPUREG_LIGHT6_SPECULAR1 0x01A1 ///< Light 6 specular lighting. -#define GPUREG_LIGHT6_DIFFUSE 0x01A2 ///< Light 6 diffuse lighting. -#define GPUREG_LIGHT6_AMBIENT 0x01A3 ///< Light 6 ambient lighting. -#define GPUREG_LIGHT6_XY 0x01A4 ///< Light 6 X and Y. -#define GPUREG_LIGHT6_Z 0x01A5 ///< Light 6 Z. -#define GPUREG_LIGHT6_SPOTDIR_XY 0x01A6 ///< Light 6 spotlight direction X and Y. -#define GPUREG_LIGHT6_SPOTDIR_Z 0x01A7 ///< Light 6 spotlight direction Z. -#define GPUREG_01A8 0x01A8 ///< Unknown. -#define GPUREG_LIGHT6_CONFIG 0x01A9 ///< Light 6 configuration. -#define GPUREG_LIGHT6_ATTENUATION_BIAS 0x01AA ///< Light 6 attenuation bias. -#define GPUREG_LIGHT6_ATTENUATION_SCALE 0x01AB ///< Light 6 attenuation scale. -#define GPUREG_01AC 0x01AC ///< Unknown. -#define GPUREG_01AD 0x01AD ///< Unknown. -#define GPUREG_01AE 0x01AE ///< Unknown. -#define GPUREG_01AF 0x01AF ///< Unknown. -#define GPUREG_LIGHT7_SPECULAR0 0x01B0 ///< Light 7 specular lighting. -#define GPUREG_LIGHT7_SPECULAR1 0x01B1 ///< Light 7 specular lighting. -#define GPUREG_LIGHT7_DIFFUSE 0x01B2 ///< Light 7 diffuse lighting. -#define GPUREG_LIGHT7_AMBIENT 0x01B3 ///< Light 7 ambient lighting. -#define GPUREG_LIGHT7_XY 0x01B4 ///< Light 7 X and Y. -#define GPUREG_LIGHT7_Z 0x01B5 ///< Light 7 Z. -#define GPUREG_LIGHT7_SPOTDIR_XY 0x01B6 ///< Light 7 spotlight direction X and Y. -#define GPUREG_LIGHT7_SPOTDIR_Z 0x01B7 ///< Light 7 spotlight direction Z. -#define GPUREG_01B8 0x01B8 ///< Unknown. -#define GPUREG_LIGHT7_CONFIG 0x01B9 ///< Light 7 configuration. -#define GPUREG_LIGHT7_ATTENUATION_BIAS 0x01BA ///< Light 7 attenuation bias. -#define GPUREG_LIGHT7_ATTENUATION_SCALE 0x01BB ///< Light 7 attenuation scale. -#define GPUREG_01BC 0x01BC ///< Unknown. -#define GPUREG_01BD 0x01BD ///< Unknown. -#define GPUREG_01BE 0x01BE ///< Unknown. -#define GPUREG_01BF 0x01BF ///< Unknown. -#define GPUREG_LIGHTING_AMBIENT 0x01C0 ///< Ambient lighting. -#define GPUREG_01C1 0x01C1 ///< Unknown. -#define GPUREG_LIGHTING_NUM_LIGHTS 0x01C2 ///< Number of lights. -#define GPUREG_LIGHTING_CONFIG0 0x01C3 ///< Lighting configuration. -#define GPUREG_LIGHTING_CONFIG1 0x01C4 ///< Lighting configuration. -#define GPUREG_LIGHTING_LUT_INDEX 0x01C5 ///< LUT index. -#define GPUREG_LIGHTING_ENABLE1 0x01C6 ///< Lighting toggle. -#define GPUREG_01C7 0x01C7 ///< Unknown. -#define GPUREG_LIGHTING_LUT_DATA0 0x01C8 ///< LUT data 0. -#define GPUREG_LIGHTING_LUT_DATA1 0x01C9 ///< LUT data 1. -#define GPUREG_LIGHTING_LUT_DATA2 0x01CA ///< LUT data 2. -#define GPUREG_LIGHTING_LUT_DATA3 0x01CB ///< LUT data 3. -#define GPUREG_LIGHTING_LUT_DATA4 0x01CC ///< LUT data 4. -#define GPUREG_LIGHTING_LUT_DATA5 0x01CD ///< LUT data 5. -#define GPUREG_LIGHTING_LUT_DATA6 0x01CE ///< LUT data 6. -#define GPUREG_LIGHTING_LUT_DATA7 0x01CF ///< LUT data 7. -#define GPUREG_LIGHTING_LUTINPUT_ABS 0x01D0 ///< LUT input abs. -#define GPUREG_LIGHTING_LUTINPUT_SELECT 0x01D1 ///< LUT input selector. -#define GPUREG_LIGHTING_LUTINPUT_SCALE 0x01D2 ///< LUT input scale. -#define GPUREG_01D3 0x01D3 ///< Unknown. -#define GPUREG_01D4 0x01D4 ///< Unknown. -#define GPUREG_01D5 0x01D5 ///< Unknown. -#define GPUREG_01D6 0x01D6 ///< Unknown. -#define GPUREG_01D7 0x01D7 ///< Unknown. -#define GPUREG_01D8 0x01D8 ///< Unknown. -#define GPUREG_LIGHTING_LIGHT_PERMUTATION 0x01D9 ///< Light permutation. -#define GPUREG_01DA 0x01DA ///< Unknown. -#define GPUREG_01DB 0x01DB ///< Unknown. -#define GPUREG_01DC 0x01DC ///< Unknown. -#define GPUREG_01DD 0x01DD ///< Unknown. -#define GPUREG_01DE 0x01DE ///< Unknown. -#define GPUREG_01DF 0x01DF ///< Unknown. -#define GPUREG_01E0 0x01E0 ///< Unknown. -#define GPUREG_01E1 0x01E1 ///< Unknown. -#define GPUREG_01E2 0x01E2 ///< Unknown. -#define GPUREG_01E3 0x01E3 ///< Unknown. -#define GPUREG_01E4 0x01E4 ///< Unknown. -#define GPUREG_01E5 0x01E5 ///< Unknown. -#define GPUREG_01E6 0x01E6 ///< Unknown. -#define GPUREG_01E7 0x01E7 ///< Unknown. -#define GPUREG_01E8 0x01E8 ///< Unknown. -#define GPUREG_01E9 0x01E9 ///< Unknown. -#define GPUREG_01EA 0x01EA ///< Unknown. -#define GPUREG_01EB 0x01EB ///< Unknown. -#define GPUREG_01EC 0x01EC ///< Unknown. -#define GPUREG_01ED 0x01ED ///< Unknown. -#define GPUREG_01EE 0x01EE ///< Unknown. -#define GPUREG_01EF 0x01EF ///< Unknown. -#define GPUREG_01F0 0x01F0 ///< Unknown. -#define GPUREG_01F1 0x01F1 ///< Unknown. -#define GPUREG_01F2 0x01F2 ///< Unknown. -#define GPUREG_01F3 0x01F3 ///< Unknown. -#define GPUREG_01F4 0x01F4 ///< Unknown. -#define GPUREG_01F5 0x01F5 ///< Unknown. -#define GPUREG_01F6 0x01F6 ///< Unknown. -#define GPUREG_01F7 0x01F7 ///< Unknown. -#define GPUREG_01F8 0x01F8 ///< Unknown. -#define GPUREG_01F9 0x01F9 ///< Unknown. -#define GPUREG_01FA 0x01FA ///< Unknown. -#define GPUREG_01FB 0x01FB ///< Unknown. -#define GPUREG_01FC 0x01FC ///< Unknown. -#define GPUREG_01FD 0x01FD ///< Unknown. -#define GPUREG_01FE 0x01FE ///< Unknown. -#define GPUREG_01FF 0x01FF ///< Unknown. -///@} - -///@name Geometry pipeline registers (0x200-0x27F) -///@{ -#define GPUREG_ATTRIBBUFFERS_LOC 0x0200 ///< Attribute buffers location. -#define GPUREG_ATTRIBBUFFERS_FORMAT_LOW 0x0201 ///< Attribute buffers format low. -#define GPUREG_ATTRIBBUFFERS_FORMAT_HIGH 0x0202 ///< Attribute buffers format high. -#define GPUREG_ATTRIBBUFFER0_OFFSET 0x0203 ///< Attribute buffers 0 offset. -#define GPUREG_ATTRIBBUFFER0_CONFIG1 0x0204 ///< Attribute buffers 0 configuration. -#define GPUREG_ATTRIBBUFFER0_CONFIG2 0x0205 ///< Attribute buffers 0 configuration. -#define GPUREG_ATTRIBBUFFER1_OFFSET 0x0206 ///< Attribute buffers 1 offset. -#define GPUREG_ATTRIBBUFFER1_CONFIG1 0x0207 ///< Attribute buffers 1 configuration. -#define GPUREG_ATTRIBBUFFER1_CONFIG2 0x0208 ///< Attribute buffers 1 configuration. -#define GPUREG_ATTRIBBUFFER2_OFFSET 0x0209 ///< Attribute buffers 2 offset. -#define GPUREG_ATTRIBBUFFER2_CONFIG1 0x020A ///< Attribute buffers 2 configuration. -#define GPUREG_ATTRIBBUFFER2_CONFIG2 0x020B ///< Attribute buffers 2 configuration. -#define GPUREG_ATTRIBBUFFER3_OFFSET 0x020C ///< Attribute buffers 3 offset. -#define GPUREG_ATTRIBBUFFER3_CONFIG1 0x020D ///< Attribute buffers 3 configuration. -#define GPUREG_ATTRIBBUFFER3_CONFIG2 0x020E ///< Attribute buffers 3 configuration. -#define GPUREG_ATTRIBBUFFER4_OFFSET 0x020F ///< Attribute buffers 4 offset. -#define GPUREG_ATTRIBBUFFER4_CONFIG1 0x0210 ///< Attribute buffers 4 configuration. -#define GPUREG_ATTRIBBUFFER4_CONFIG2 0x0211 ///< Attribute buffers 4 configuration. -#define GPUREG_ATTRIBBUFFER5_OFFSET 0x0212 ///< Attribute buffers 5 offset. -#define GPUREG_ATTRIBBUFFER5_CONFIG1 0x0213 ///< Attribute buffers 5 configuration. -#define GPUREG_ATTRIBBUFFER5_CONFIG2 0x0214 ///< Attribute buffers 5 configuration. -#define GPUREG_ATTRIBBUFFER6_OFFSET 0x0215 ///< Attribute buffers 6 offset. -#define GPUREG_ATTRIBBUFFER6_CONFIG1 0x0216 ///< Attribute buffers 6 configuration. -#define GPUREG_ATTRIBBUFFER6_CONFIG2 0x0217 ///< Attribute buffers 6 configuration. -#define GPUREG_ATTRIBBUFFER7_OFFSET 0x0218 ///< Attribute buffers 7 offset. -#define GPUREG_ATTRIBBUFFER7_CONFIG1 0x0219 ///< Attribute buffers 7 configuration. -#define GPUREG_ATTRIBBUFFER7_CONFIG2 0x021A ///< Attribute buffers 7 configuration. -#define GPUREG_ATTRIBBUFFER8_OFFSET 0x021B ///< Attribute buffers 8 offset. -#define GPUREG_ATTRIBBUFFER8_CONFIG1 0x021C ///< Attribute buffers 8 configuration. -#define GPUREG_ATTRIBBUFFER8_CONFIG2 0x021D ///< Attribute buffers 8 configuration. -#define GPUREG_ATTRIBBUFFER9_OFFSET 0x021E ///< Attribute buffers 9 offset. -#define GPUREG_ATTRIBBUFFER9_CONFIG1 0x021F ///< Attribute buffers 9 configuration. -#define GPUREG_ATTRIBBUFFER9_CONFIG2 0x0220 ///< Attribute buffers 9 configuration. -#define GPUREG_ATTRIBBUFFERA_OFFSET 0x0221 ///< Attribute buffers A offset. -#define GPUREG_ATTRIBBUFFERA_CONFIG1 0x0222 ///< Attribute buffers A configuration. -#define GPUREG_ATTRIBBUFFERA_CONFIG2 0x0223 ///< Attribute buffers A configuration. -#define GPUREG_ATTRIBBUFFERB_OFFSET 0x0224 ///< Attribute buffers B offset. -#define GPUREG_ATTRIBBUFFERB_CONFIG1 0x0225 ///< Attribute buffers B configuration. -#define GPUREG_ATTRIBBUFFERB_CONFIG2 0x0226 ///< Attribute buffers B configuration. -#define GPUREG_INDEXBUFFER_CONFIG 0x0227 ///< Index buffer configuration. -#define GPUREG_NUMVERTICES 0x0228 ///< Number of vertices. -#define GPUREG_GEOSTAGE_CONFIG 0x0229 ///< Geometry stage configuration. -#define GPUREG_VERTEX_OFFSET 0x022A ///< Vertex offset. -#define GPUREG_022B 0x022B ///< Unknown. -#define GPUREG_022C 0x022C ///< Unknown. -#define GPUREG_POST_VERTEX_CACHE_NUM 0x022D ///< Unknown. -#define GPUREG_DRAWARRAYS 0x022E ///< Draw arrays trigger. -#define GPUREG_DRAWELEMENTS 0x022F ///< Draw arrays elements. -#define GPUREG_0230 0x0230 ///< Unknown. -#define GPUREG_VTX_FUNC 0x0231 ///< Unknown. -#define GPUREG_FIXEDATTRIB_INDEX 0x0232 ///< Fixed attribute index. -#define GPUREG_FIXEDATTRIB_DATA0 0x0233 ///< Fixed attribute data 0. -#define GPUREG_FIXEDATTRIB_DATA1 0x0234 ///< Fixed attribute data 1. -#define GPUREG_FIXEDATTRIB_DATA2 0x0235 ///< Fixed attribute data 2. -#define GPUREG_0236 0x0236 ///< Unknown. -#define GPUREG_0237 0x0237 ///< Unknown. -#define GPUREG_CMDBUF_SIZE0 0x0238 ///< Command buffer size 0. -#define GPUREG_CMDBUF_SIZE1 0x0239 ///< Command buffer size 1. -#define GPUREG_CMDBUF_ADDR0 0x023A ///< Command buffer address 0. -#define GPUREG_CMDBUF_ADDR1 0x023B ///< Command buffer address 1. -#define GPUREG_CMDBUF_JUMP0 0x023C ///< Command buffer jump 0. -#define GPUREG_CMDBUF_JUMP1 0x023D ///< Command buffer jump 1. -#define GPUREG_023E 0x023E ///< Unknown. -#define GPUREG_023F 0x023F ///< Unknown. -#define GPUREG_0240 0x0240 ///< Unknown. -#define GPUREG_0241 0x0241 ///< Unknown. -#define GPUREG_VSH_NUM_ATTR 0x0242 ///< Unknown. -#define GPUREG_0243 0x0243 ///< Unknown. -#define GPUREG_VSH_COM_MODE 0x0244 ///< Unknown. -#define GPUREG_START_DRAW_FUNC0 0x0245 ///< Unknown. -#define GPUREG_0246 0x0246 ///< Unknown. -#define GPUREG_0247 0x0247 ///< Unknown. -#define GPUREG_0248 0x0248 ///< Unknown. -#define GPUREG_0249 0x0249 ///< Unknown. -#define GPUREG_VSH_OUTMAP_TOTAL1 0x024A ///< Unknown. -#define GPUREG_024B 0x024B ///< Unknown. -#define GPUREG_024C 0x024C ///< Unknown. -#define GPUREG_024D 0x024D ///< Unknown. -#define GPUREG_024E 0x024E ///< Unknown. -#define GPUREG_024F 0x024F ///< Unknown. -#define GPUREG_0250 0x0250 ///< Unknown. -#define GPUREG_VSH_OUTMAP_TOTAL2 0x0251 ///< Unknown. -#define GPUREG_GSH_MISC0 0x0252 ///< Unknown. -#define GPUREG_GEOSTAGE_CONFIG2 0x0253 ///< Unknown. -#define GPUREG_GSH_MISC1 0x0254 ///< Unknown. -#define GPUREG_0255 0x0255 ///< Unknown. -#define GPUREG_0256 0x0256 ///< Unknown. -#define GPUREG_0257 0x0257 ///< Unknown. -#define GPUREG_0258 0x0258 ///< Unknown. -#define GPUREG_0259 0x0259 ///< Unknown. -#define GPUREG_025A 0x025A ///< Unknown. -#define GPUREG_025B 0x025B ///< Unknown. -#define GPUREG_025C 0x025C ///< Unknown. -#define GPUREG_025D 0x025D ///< Unknown. -#define GPUREG_PRIMITIVE_CONFIG 0x025E ///< Primitive configuration. -#define GPUREG_RESTART_PRIMITIVE 0x025F ///< Restart primitive flag. -#define GPUREG_0260 0x0260 ///< Unknown. -#define GPUREG_0261 0x0261 ///< Unknown. -#define GPUREG_0262 0x0262 ///< Unknown. -#define GPUREG_0263 0x0263 ///< Unknown. -#define GPUREG_0264 0x0264 ///< Unknown. -#define GPUREG_0265 0x0265 ///< Unknown. -#define GPUREG_0266 0x0266 ///< Unknown. -#define GPUREG_0267 0x0267 ///< Unknown. -#define GPUREG_0268 0x0268 ///< Unknown. -#define GPUREG_0269 0x0269 ///< Unknown. -#define GPUREG_026A 0x026A ///< Unknown. -#define GPUREG_026B 0x026B ///< Unknown. -#define GPUREG_026C 0x026C ///< Unknown. -#define GPUREG_026D 0x026D ///< Unknown. -#define GPUREG_026E 0x026E ///< Unknown. -#define GPUREG_026F 0x026F ///< Unknown. -#define GPUREG_0270 0x0270 ///< Unknown. -#define GPUREG_0271 0x0271 ///< Unknown. -#define GPUREG_0272 0x0272 ///< Unknown. -#define GPUREG_0273 0x0273 ///< Unknown. -#define GPUREG_0274 0x0274 ///< Unknown. -#define GPUREG_0275 0x0275 ///< Unknown. -#define GPUREG_0276 0x0276 ///< Unknown. -#define GPUREG_0277 0x0277 ///< Unknown. -#define GPUREG_0278 0x0278 ///< Unknown. -#define GPUREG_0279 0x0279 ///< Unknown. -#define GPUREG_027A 0x027A ///< Unknown. -#define GPUREG_027B 0x027B ///< Unknown. -#define GPUREG_027C 0x027C ///< Unknown. -#define GPUREG_027D 0x027D ///< Unknown. -#define GPUREG_027E 0x027E ///< Unknown. -#define GPUREG_027F 0x027F ///< Unknown. -///@} - -///@name Geometry shader registers (0x280-0x2AF) -///@{ -#define GPUREG_GSH_BOOLUNIFORM 0x0280 ///< Geometry shader bool uniforms. -#define GPUREG_GSH_INTUNIFORM_I0 0x0281 ///< Geometry shader integer uniform 0. -#define GPUREG_GSH_INTUNIFORM_I1 0x0282 ///< Geometry shader integer uniform 1. -#define GPUREG_GSH_INTUNIFORM_I2 0x0283 ///< Geometry shader integer uniform 2. -#define GPUREG_GSH_INTUNIFORM_I3 0x0284 ///< Geometry shader integer uniform 3. -#define GPUREG_0285 0x0285 ///< Unknown. -#define GPUREG_0286 0x0286 ///< Unknown. -#define GPUREG_0287 0x0287 ///< Unknown. -#define GPUREG_0288 0x0288 ///< Unknown. -#define GPUREG_GSH_INPUTBUFFER_CONFIG 0x0289 ///< Geometry shader input buffer configuration. -#define GPUREG_GSH_ENTRYPOINT 0x028A ///< Geometry shader entry point. -#define GPUREG_GSH_ATTRIBUTES_PERMUTATION_LOW 0x028B ///< Geometry shader attribute permutations low. -#define GPUREG_GSH_ATTRIBUTES_PERMUTATION_HIGH 0x028C ///< Geometry shader attribute permutations high. -#define GPUREG_GSH_OUTMAP_MASK 0x028D ///< Geometry shader output map mask. -#define GPUREG_028E 0x028E ///< Unknown. -#define GPUREG_GSH_CODETRANSFER_END 0x028F ///< Geometry shader code transfer end trigger. -#define GPUREG_GSH_FLOATUNIFORM_CONFIG 0x0290 ///< Geometry shader float uniform configuration. -#define GPUREG_GSH_FLOATUNIFORM_DATA 0x0291 ///< Geometry shader float uniform data. -#define GPUREG_0299 0x0299 ///< Unknown. -#define GPUREG_029A 0x029A ///< Unknown. -#define GPUREG_GSH_CODETRANSFER_CONFIG 0x029B ///< Geometry shader code transfer configuration. -#define GPUREG_GSH_CODETRANSFER_DATA 0x029C ///< Geometry shader code transfer data. -#define GPUREG_02A4 0x02A4 ///< Unknown. -#define GPUREG_GSH_OPDESCS_CONFIG 0x02A5 ///< Geometry shader operand description configuration. -#define GPUREG_GSH_OPDESCS_DATA 0x02A6 ///< Geometry shader operand description data. -#define GPUREG_02AE 0x02AE ///< Unknown. -#define GPUREG_02AF 0x02AF ///< Unknown. -///@} - -///@name Vertex shader registers (0x2B0-0x2DF) -///@{ -#define GPUREG_VSH_BOOLUNIFORM 0x02B0 ///< Vertex shader bool uniforms. -#define GPUREG_VSH_INTUNIFORM_I0 0x02B1 ///< Vertex shader integer uniform 0. -#define GPUREG_VSH_INTUNIFORM_I1 0x02B2 ///< Vertex shader integer uniform 1. -#define GPUREG_VSH_INTUNIFORM_I2 0x02B3 ///< Vertex shader integer uniform 2. -#define GPUREG_VSH_INTUNIFORM_I3 0x02B4 ///< Vertex shader integer uniform 3. -#define GPUREG_02B5 0x02B5 ///< Unknown. -#define GPUREG_02B6 0x02B6 ///< Unknown. -#define GPUREG_02B7 0x02B7 ///< Unknown. -#define GPUREG_02B8 0x02B8 ///< Unknown. -#define GPUREG_VSH_INPUTBUFFER_CONFIG 0x02B9 ///< Vertex shader input buffer configuration. -#define GPUREG_VSH_ENTRYPOINT 0x02BA ///< Vertex shader entry point. -#define GPUREG_VSH_ATTRIBUTES_PERMUTATION_LOW 0x02BB ///< Vertex shader attribute permutations low. -#define GPUREG_VSH_ATTRIBUTES_PERMUTATION_HIGH 0x02BC ///< Vertex shader attribute permutations high. -#define GPUREG_VSH_OUTMAP_MASK 0x02BD ///< Vertex shader output map mask. -#define GPUREG_02BE 0x02BE ///< Unknown. -#define GPUREG_VSH_CODETRANSFER_END 0x02BF ///< Vertex shader code transfer end trigger. -#define GPUREG_VSH_FLOATUNIFORM_CONFIG 0x02C0 ///< Vertex shader float uniform configuration. -#define GPUREG_VSH_FLOATUNIFORM_DATA 0x02C1 ///< Vertex shader float uniform data. -#define GPUREG_02C9 0x02C9 ///< Unknown. -#define GPUREG_02CA 0x02CA ///< Unknown. -#define GPUREG_VSH_CODETRANSFER_CONFIG 0x02CB ///< Vertex shader code transfer configuration. -#define GPUREG_VSH_CODETRANSFER_DATA 0x02CC ///< Vertex shader code transfer data. -#define GPUREG_02D4 0x02D4 ///< Unknown. -#define GPUREG_VSH_OPDESCS_CONFIG 0x02D5 ///< Vertex shader operand description configuration. -#define GPUREG_VSH_OPDESCS_DATA 0x02D6 ///< Vertex shader operand description data. -#define GPUREG_02DE 0x02DE ///< Unknown. -#define GPUREG_02DF 0x02DF ///< Unknown. -///@} - -///@name Unknown registers (0x2E0-0x2FF) -///@{ -#define GPUREG_02E0 0x02E0 ///< Unknown. -#define GPUREG_02E1 0x02E1 ///< Unknown. -#define GPUREG_02E2 0x02E2 ///< Unknown. -#define GPUREG_02E3 0x02E3 ///< Unknown. -#define GPUREG_02E4 0x02E4 ///< Unknown. -#define GPUREG_02E5 0x02E5 ///< Unknown. -#define GPUREG_02E6 0x02E6 ///< Unknown. -#define GPUREG_02E7 0x02E7 ///< Unknown. -#define GPUREG_02E8 0x02E8 ///< Unknown. -#define GPUREG_02E9 0x02E9 ///< Unknown. -#define GPUREG_02EA 0x02EA ///< Unknown. -#define GPUREG_02EB 0x02EB ///< Unknown. -#define GPUREG_02EC 0x02EC ///< Unknown. -#define GPUREG_02ED 0x02ED ///< Unknown. -#define GPUREG_02EE 0x02EE ///< Unknown. -#define GPUREG_02EF 0x02EF ///< Unknown. -#define GPUREG_02F0 0x02F0 ///< Unknown. -#define GPUREG_02F1 0x02F1 ///< Unknown. -#define GPUREG_02F2 0x02F2 ///< Unknown. -#define GPUREG_02F3 0x02F3 ///< Unknown. -#define GPUREG_02F4 0x02F4 ///< Unknown. -#define GPUREG_02F5 0x02F5 ///< Unknown. -#define GPUREG_02F6 0x02F6 ///< Unknown. -#define GPUREG_02F7 0x02F7 ///< Unknown. -#define GPUREG_02F8 0x02F8 ///< Unknown. -#define GPUREG_02F9 0x02F9 ///< Unknown. -#define GPUREG_02FA 0x02FA ///< Unknown. -#define GPUREG_02FB 0x02FB ///< Unknown. -#define GPUREG_02FC 0x02FC ///< Unknown. -#define GPUREG_02FD 0x02FD ///< Unknown. -#define GPUREG_02FE 0x02FE ///< Unknown. -#define GPUREG_02FF 0x02FF ///< Unknown. -///@} -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/Includes/ctrulib/gpu/shaderProgram.h b/Includes/ctrulib/gpu/shaderProgram.h deleted file mode 100644 index 15d99ec..0000000 --- a/Includes/ctrulib/gpu/shaderProgram.h +++ /dev/null @@ -1,142 +0,0 @@ -/** - * @file shaderProgram.h - * @brief Functions for working with shaders. - */ -#pragma once -#ifdef __cplusplus -extern "C" { -#endif -#include "../../types.h" -#include "shbin.h" - -/// 24-bit float uniforms. -typedef struct -{ - u32 id; ///< Uniform ID. - u32 data[3]; ///< Uniform data. -}float24Uniform_s; - -/// Describes an instance of either a vertex or geometry shader. -typedef struct -{ - DVLE_s* dvle; ///< Shader DVLE. - u16 boolUniforms; ///< Boolean uniforms. - u16 boolUniformMask; ///< Used boolean uniform mask. - u32 intUniforms[4]; ///< Integer uniforms. - float24Uniform_s* float24Uniforms; ///< 24-bit float uniforms. - u8 intUniformMask; ///< Used integer uniform mask. - u8 numFloat24Uniforms; ///< Float uniform count. -}shaderInstance_s; - -/// Describes an instance of a full shader program. -typedef struct -{ - shaderInstance_s* vertexShader; ///< Vertex shader. - shaderInstance_s* geometryShader; ///< Geometry shader. - u32 geoShaderInputPermutation[2]; ///< Geometry shader input permutation. - u8 geoShaderInputStride; ///< Geometry shader input stride. - u8 geoShaderMode; ///< Geometry shader operation mode. -}shaderProgram_s; - -/// Geometry shader operation modes. -typedef enum -{ - GSH_NORMAL = 0, ///< Normal operation. - GSH_PARTICLE = 1, ///< Particle system. - GSH_SUBDIVISION_LOOP = 2, ///< Loop subdivision surface. - GSH_SUBDIVISION_CATMULL_CLARK = 3, ///< Catmull-Clark subdivision surface. -} geoShaderMode; - -/** - * @brief Initializes a shader instance. - * @param si Shader instance to initialize. - * @param dvle DVLE to initialize the shader instance with. - */ -Result shaderInstanceInit(shaderInstance_s* si, DVLE_s* dvle); - -/** - * @brief Frees a shader instance. - * @param si Shader instance to free. - */ -Result shaderInstanceFree(shaderInstance_s* si); - -/** - * @brief Sets a bool uniform of a shader. - * @param si Shader instance to use. - * @param id ID of the bool uniform. - * @param value Value to set. - */ -Result shaderInstanceSetBool(shaderInstance_s* si, int id, bool value); - -/** - * @brief Gets a bool uniform of a shader. - * @param si Shader instance to use. - * @param id ID of the bool uniform. - * @param value Pointer to output the value to. - */ -Result shaderInstanceGetBool(shaderInstance_s* si, int id, bool* value); - -/** - * @brief Gets the location of a shader's uniform. - * @param si Shader instance to use. - * @param name Name of the uniform. - */ -s8 shaderInstanceGetUniformLocation(shaderInstance_s* si, const char* name); - -/** - * @brief Initializes a shader program. - * @param sp Shader program to initialize. - */ -Result shaderProgramInit(shaderProgram_s* sp); - -/** - * @brief Frees a shader program. - * @param sp Shader program to free. - */ -Result shaderProgramFree(shaderProgram_s* sp); - -/** - * @brief Sets the vertex shader of a shader program. - * @param sp Shader program to use. - * @param dvle Vertex shader to set. - */ -Result shaderProgramSetVsh(shaderProgram_s* sp, DVLE_s* dvle); - -/** - * @brief Sets the geometry shader of a shader program. - * @param sp Shader program to use. - * @param dvle Geometry shader to set. - * @param stride Stride of the geometry shader. - */ -Result shaderProgramSetGsh(shaderProgram_s* sp, DVLE_s* dvle, u8 stride); - -/** - * @brief Configures the permutation of the input attributes of the geometry shader of a shader program. - * @param sp Shader program to use. - * @param permutation Attribute permutation to use. - */ -Result shaderProgramSetGshInputPermutation(shaderProgram_s* sp, u64 permutation); - -/** - * @brief Configures the operation mode of the geometry shader of a shader program. - * @param sp Shader program to use. - * @param mode Operation mode to use. - */ -Result shaderProgramSetGshMode(shaderProgram_s* sp, geoShaderMode mode); - -/** - * @brief Configures the shader units to use the specified shader program. - * @param sp Shader program to use. - * @param sendVshCode When true, the vertex shader's code and operand descriptors are uploaded. - * @param sendGshCode When true, the geometry shader's code and operand descriptors are uploaded. - */ -Result shaderProgramConfigure(shaderProgram_s* sp, bool sendVshCode, bool sendGshCode); - -/** - * @brief Same as shaderProgramConfigure, but always loading code/operand descriptors and uploading DVLE constants afterwards. - * @param sp Shader program to use. - */ -Result shaderProgramUse(shaderProgram_s* sp); -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/Includes/ctrulib/gpu/shbin.h b/Includes/ctrulib/gpu/shbin.h deleted file mode 100644 index e3f016d..0000000 --- a/Includes/ctrulib/gpu/shbin.h +++ /dev/null @@ -1,121 +0,0 @@ -/** - * @file shbin.h - * @brief Shader binary support. - */ -#pragma once -#ifdef __cplusplus -extern "C" { -#endif -#include "gpu.h" - -/// DVLE type. -typedef enum{ - VERTEX_SHDR=GPU_VERTEX_SHADER, ///< Vertex shader. - GEOMETRY_SHDR=GPU_GEOMETRY_SHADER ///< Geometry shader. -}DVLE_type; - -/// Constant type. -typedef enum{ - DVLE_CONST_BOOL=0x0, ///< Bool. - DVLE_CONST_u8=0x1, ///< Unsigned 8-bit integer. - DVLE_CONST_FLOAT24=0x2, ///< 24-bit float. -}DVLE_constantType; - -/// Output attribute. -typedef enum{ - RESULT_POSITION = 0x0, ///< Position. - RESULT_NORMALQUAT = 0x1, ///< Normal Quaternion. - RESULT_COLOR = 0x2, ///< Color. - RESULT_TEXCOORD0 = 0x3, ///< Texture coordinate 0. - RESULT_TEXCOORD0W = 0x4, ///< Texture coordinate 0 W. - RESULT_TEXCOORD1 = 0x5, ///< Texture coordinate 1. - RESULT_TEXCOORD2 = 0x6, ///< Texture coordinate 2. - RESULT_VIEW = 0x8 ///< View. -}DVLE_outputAttribute_t; - -/// DVLP data. -typedef struct{ - u32 codeSize; ///< Code size. - u32* codeData; ///< Code data. - u32 opdescSize; ///< Operand description size. - u32* opcdescData; ///< Operand description data. -}DVLP_s; - -/// DVLE constant entry data. -typedef struct{ - u16 type; ///< Constant type. See @ref DVLE_constantType - u16 id; ///< Constant ID. - u32 data[4]; ///< Constant data. -}DVLE_constEntry_s; - -/// DVLE output entry data. -typedef struct{ - u16 type; ///< Output type. See @ref DVLE_outputAttribute_t - u16 regID; ///< Output register ID. - u8 mask; ///< Output mask. - u8 unk[3]; ///< Unknown. -}DVLE_outEntry_s; - -/// DVLE uniform entry data. -typedef struct{ - u32 symbolOffset; ///< Symbol offset. - u16 startReg; ///< Start register. - u16 endReg; ///< End register. -}DVLE_uniformEntry_s; - -/// DVLE data. -typedef struct{ - DVLE_type type; ///< DVLE type. - DVLP_s* dvlp; ///< Contained DVLPs. - u32 mainOffset; ///< Offset of the start of the main function. - u32 endmainOffset; ///< Offset of the end of the main function. - u32 constTableSize; ///< Constant table size. - DVLE_constEntry_s* constTableData; ///< Constant table data. - u32 outTableSize; ///< Output table size. - DVLE_outEntry_s* outTableData; ///< Output table data. - u32 uniformTableSize; ///< Uniform table size. - DVLE_uniformEntry_s* uniformTableData; ///< Uniform table data. - char* symbolTableData; ///< Symbol table data. - u8 outmapMask; ///< Output map mask. - u32 outmapData[8]; ///< Output map data. - u32 outmapMode; ///< Output map mode. - u32 outmapClock; ///< Output map attribute clock. -}DVLE_s; - -/// DVLB data. -typedef struct{ - u32 numDVLE; ///< DVLE count. - DVLP_s DVLP; ///< Primary DVLP. - DVLE_s* DVLE; ///< Contained DVLE. -}DVLB_s; - -/** - * @brief Parses a shader binary. - * @param shbinData Shader binary data. - * @param shbinSize Shader binary size. - * @return The parsed shader binary. - */ -DVLB_s* DVLB_ParseFile(u32* shbinData, u32 shbinSize); - -/** - * @brief Frees shader binary data. - * @param dvlb DVLB to free. - */ -void DVLB_Free(DVLB_s* dvlb); - -/** - * @brief Gets a uniform register index from a shader. - * @param dvle Shader to get the register from. - * @param name Name of the register. - * @return The uniform register index. - */ -s8 DVLE_GetUniformRegister(DVLE_s* dvle, const char* name); - -/** - * @brief Generates a shader output map. - * @param dvle Shader to generate an output map for. - */ -void DVLE_GenerateOutmap(DVLE_s* dvle); -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/Includes/ctrulib/ipc.h b/Includes/ctrulib/ipc.h deleted file mode 100644 index 4cbbb8b..0000000 --- a/Includes/ctrulib/ipc.h +++ /dev/null @@ -1,118 +0,0 @@ -/** - * @file ipc.h - * @brief Inter Process Communication helpers - */ -#pragma once -#ifdef __cplusplus -extern "C" { -#endif -#include "../types.h" -//#define BIT(x) (1U << x) -/// IPC buffer access rights. -typedef enum -{ - IPC_BUFFER_R = BIT(1), ///< Readable - IPC_BUFFER_W = BIT(2), ///< Writable - IPC_BUFFER_RW = IPC_BUFFER_R | IPC_BUFFER_W ///< Readable and Writable -} IPC_BufferRights; - -/** - * @brief Creates a command header to be used for IPC - * @param command_id ID of the command to create a header for. - * @param normal_params Size of the normal parameters in words. Up to 63. - * @param translate_params Size of the translate parameters in words. Up to 63. - * @return The created IPC header. - * - * Normal parameters are sent directly to the process while the translate parameters might go through modifications and checks by the kernel. - * The translate parameters are described by headers generated with the IPC_Desc_* functions. - * - * @note While #normal_params is equivalent to the number of normal parameters, #translate_params includes the size occupied by the translate parameters headers. - */ -static inline u32 IPC_MakeHeader(u16 command_id, unsigned normal_params, unsigned translate_params) -{ - return ((u32) command_id << 16) | (((u32) normal_params & 0x3F) << 6) | (((u32) translate_params & 0x3F) << 0); -} - -/** - * @brief Creates a header to share handles - * @param number The number of handles following this header. Max 64. - * @return The created shared handles header. - * - * The #number next values are handles that will be shared between the two processes. - * - * @note Zero values will have no effect. - */ -static inline u32 IPC_Desc_SharedHandles(unsigned number) -{ - return ((u32)(number - 1) << 26); -} - -/** - * @brief Creates the header to transfer handle ownership - * @param number The number of handles following this header. Max 64. - * @return The created handle transfer header. - * - * The #number next values are handles that will be duplicated and closed by the other process. - * - * @note Zero values will have no effect. - */ -static inline u32 IPC_Desc_MoveHandles(unsigned number) -{ - return ((u32)(number - 1) << 26) | 0x10; -} - -/** - * @brief Returns the code to ask the kernel to fill the handle with the current process handle. - * @return The code to request the current process handle. - * - * The next value is a placeholder that will be replaced by the current process handle by the kernel. - */ -static inline u32 IPC_Desc_CurProcessHandle(void) -{ - return 0x20; -} - -/** - * @brief Creates a header describing a static buffer. - * @param size Size of the buffer. Max ?0x03FFFF?. - * @param buffer_id The Id of the buffer. Max 0xF. - * @return The created static buffer header. - * - * The next value is a pointer to the buffer. It will be copied to TLS offset 0x180 + static_buffer_id*8. - */ -static inline u32 IPC_Desc_StaticBuffer(size_t size, unsigned buffer_id) -{ - return (size << 14) | ((buffer_id & 0xF) << 10) | 0x2; -} - -/** - * @brief Creates a header describing a buffer to be sent over PXI. - * @param size Size of the buffer. Max 0x00FFFFFF. - * @param buffer_id The Id of the buffer. Max 0xF. - * @param is_read_only true if the buffer is read-only. If false, the buffer is considered to have read-write access. - * @return The created PXI buffer header. - * - * The next value is a phys-address of a table located in the BASE memregion. - */ -static inline u32 IPC_Desc_PXIBuffer(size_t size, unsigned buffer_id, bool is_read_only) -{ - u8 type = 0x4; - if(is_read_only)type = 0x6; - return (size << 8) | ((buffer_id & 0xF) << 4) | type; -} - -/** - * @brief Creates a header describing a buffer from the main memory. - * @param size Size of the buffer. Max 0x0FFFFFFF. - * @param rights The rights of the buffer for the destination process. - * @return The created buffer header. - * - * The next value is a pointer to the buffer. - */ -static inline u32 IPC_Desc_Buffer(size_t size, IPC_BufferRights rights) -{ - return (size << 4) | 0x8 | rights; -} -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/Includes/ctrulib/netinet/in.h b/Includes/ctrulib/netinet/in.h deleted file mode 100644 index 663a8f6..0000000 --- a/Includes/ctrulib/netinet/in.h +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include -#include - -#define INADDR_LOOPBACK 0x7f000001 -#define INADDR_ANY 0x00000000 -#define INADDR_BROADCAST 0xFFFFFFFF -#define INADDR_NONE 0xFFFFFFFF - -#define INET_ADDRSTRLEN 16 - -/* - * Protocols (See RFC 1700 and the IANA) - */ -#define IPPROTO_IP 0 /* dummy for IP */ -#define IPPROTO_UDP 17 /* user datagram protocol */ -#define IPPROTO_TCP 6 /* tcp */ - -#define IP_TOS 7 -#define IP_TTL 8 -#define IP_MULTICAST_LOOP 9 -#define IP_MULTICAST_TTL 10 -#define IP_ADD_MEMBERSHIP 11 -#define IP_DROP_MEMBERSHIP 12 - -typedef uint16_t in_port_t; -typedef uint32_t in_addr_t; - -struct in_addr { - in_addr_t s_addr; -}; - -struct sockaddr_in { - sa_family_t sin_family; - in_port_t sin_port; - struct in_addr sin_addr; - unsigned char sin_zero[8]; -}; - -/* Request struct for multicast socket ops */ -struct ip_mreq { - struct in_addr imr_multiaddr; /* IP multicast address of group */ - struct in_addr imr_interface; /* local IP address of interface */ -}; diff --git a/Includes/ctrulib/netinet/tcp.h b/Includes/ctrulib/netinet/tcp.h deleted file mode 100644 index 3619f94..0000000 --- a/Includes/ctrulib/netinet/tcp.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#define SOL_TCP 6 /* TCP level */ - -enum{ - _CTRU_TCP_OPT = 0x2000, /* Flag for tcp opt values */ - TCP_NODELAY = 1 | _CTRU_TCP_OPT, /* Don't delay send to coalesce packets */ - TCP_MAXSEG = 2 | _CTRU_TCP_OPT, -}; diff --git a/Includes/ctrulib/os.h b/Includes/ctrulib/os.h deleted file mode 100644 index a2dcce3..0000000 --- a/Includes/ctrulib/os.h +++ /dev/null @@ -1,190 +0,0 @@ -/** - * @file os.h - * @brief OS related stuff. - */ -#pragma once -#ifdef __cplusplus -extern "C" { -#endif -#include "../types.h" -/// Packs a system version from its components. -#define SYSTEM_VERSION(major, minor, revision) \ - (((major)<<24)|((minor)<<16)|((revision)<<8)) - -/// Retrieves the major version from a packed system version. -#define GET_VERSION_MAJOR(version) ((version) >>24) - -/// Retrieves the minor version from a packed system version. -#define GET_VERSION_MINOR(version) (((version)>>16)&0xFF) - -/// Retrieves the revision version from a packed system version. -#define GET_VERSION_REVISION(version) (((version)>> 8)&0xFF) - -/// Memory regions. -typedef enum -{ - MEMREGION_ALL = 0, ///< All regions. - MEMREGION_APPLICATION = 1, ///< APPLICATION memory. - MEMREGION_SYSTEM = 2, ///< SYSTEM memory. - MEMREGION_BASE = 3, ///< BASE memory. -} MemRegion; - -/// OS_VersionBin. Format of the system version: "..-" -typedef struct -{ - u8 build; - u8 minor; - u8 mainver;//"major" in CVER, NUP version in NVer. - u8 reserved_x3; - char region;//"ASCII character for the system version region" - u8 reserved_x5[0x3]; -} OS_VersionBin; - -/** - * @brief Converts an address from virtual (process) memory to physical memory. - * @param vaddr Input virtual address. - * @return The corresponding physical address. - * It is sometimes required by services or when using the GPU command buffer. - */ -u32 osConvertVirtToPhys(const void* vaddr); - -/** - * @brief Converts 0x14* vmem to 0x30*. - * @param vaddr Input virtual address. - * @return The corresponding address in the 0x30* range, the input address if it's already within the new vmem, or 0 if it's outside of both ranges. - */ -void* osConvertOldLINEARMemToNew(const void* vaddr); - -/** - * @brief Retrieves basic information about a service error. - * @param error Error to retrieve information about. - * @return A string containing a summary of an error. - * - * This can be used to get some details about an error returned by a service call. - */ -const char* osStrError(u32 error); - -/** - * @brief Gets the system's FIRM version. - * @return The system's FIRM version. - * - * This can be used to compare system versions easily with @ref SYSTEM_VERSION. - */ -static inline u32 osGetFirmVersion(void) -{ - return (*(vu32*)0x1FF80060) & ~0xFF; -} - -/** - * @brief Gets the system's kernel version. - * @return The system's kernel version. - * - * This can be used to compare system versions easily with @ref SYSTEM_VERSION. - * - * @code - * if(osGetKernelVersion() > SYSTEM_VERSION(2,46,0)) printf("You are running 9.0 or higher\n"); - * @endcode - */ -static inline u32 osGetKernelVersion(void) -{ - return (*(vu32*)0x1FF80000) & ~0xFF; -} - -/** - * @brief Gets the size of the specified memory region. - * @param region Memory region to check. - * @return The size of the memory region, in bytes. - */ -static inline u32 osGetMemRegionSize(MemRegion region) -{ - if(region == MEMREGION_ALL) { - return osGetMemRegionSize(MEMREGION_APPLICATION) + osGetMemRegionSize(MEMREGION_SYSTEM) + osGetMemRegionSize(MEMREGION_BASE); - } else { - return *(vu32*) (0x1FF80040 + (region - 1) * 0x4); - } -} - -/** - * @brief Gets the number of used bytes within the specified memory region. - * @param region Memory region to check. - * @return The number of used bytes of memory. - */ -s64 osGetMemRegionUsed(MemRegion region); - -/** - * @brief Gets the number of free bytes within the specified memory region. - * @param region Memory region to check. - * @return The number of free bytes of memory. - */ -static inline s64 osGetMemRegionFree(MemRegion region) -{ - return (s64) osGetMemRegionSize(region) - osGetMemRegionUsed(region); -} - -/** -* @brief Gets the current time. -* @return The number of milliseconds since 1st Jan 1970 00:00. -*/ -u64 osGetTime1970(void); - -/** - * @brief Gets the current time. - * @return The number of milliseconds since 1st Jan 1900 00:00. - */ -u64 osGetTime(void); - -/** - * @brief Gets the current Wifi signal strength. - * @return The current Wifi signal strength. - * - * Valid values are 0-3: - * - 0 means the singal strength is terrible or the 3DS is disconnected from - * all networks. - * - 1 means the signal strength is bad. - * - 2 means the signal strength is decent. - * - 3 means the signal strength is good. - * - * Values outside the range of 0-3 should never be returned. - * - * These values correspond with the number of wifi bars displayed by Home Menu. - */ -static inline u8 osGetWifiStrength(void) -{ - return *(vu8*)0x1FF81066; -} - -/** - * @brief Gets the state of the 3D slider. - * @return The state of the 3D slider (0.0~1.0) - */ -static inline float osGet3DSliderState(void) -{ - return *(volatile float*)0x1FF81080; -} - -/** - * @brief Configures the New 3DS speedup. - * @param enable Specifies whether to enable or disable the speedup. - */ -void osSetSpeedupEnable(bool enable); - -/** - * @brief Gets the NAND system-version stored in NVer/CVer. - * @param nver_versionbin Output OS_VersionBin structure for the data read from NVer. - * @param cver_versionbin Output OS_VersionBin structure for the data read from CVer. - * @return The result-code. This value can be positive if opening "romfs:/version.bin" fails with stdio, since errno would be returned in that case. In some cases the error can be special negative values as well. - */ -Result osGetSystemVersionData(OS_VersionBin *nver_versionbin, OS_VersionBin *cver_versionbin); - -/** - * @brief This is a wrapper for osGetSystemVersionData. - * @param nver_versionbin Optional output OS_VersionBin structure for the data read from NVer, can be NULL. - * @param cver_versionbin Optional output OS_VersionBin structure for the data read from CVer, can be NULL. - * @param sysverstr Output string where the printed system-version will be written, in the same format displayed by the System Settings title. - * @param sysverstr_maxsize Max size of the above string buffer, *including* NULL-terminator. - * @return See osGetSystemVersionData. - */ -Result osGetSystemVersionDataString(OS_VersionBin *nver_versionbin, OS_VersionBin *cver_versionbin, char *sysverstr, u32 sysverstr_maxsize); -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/Includes/ctrulib/poll.h b/Includes/ctrulib/poll.h deleted file mode 100644 index bd3eb7a..0000000 --- a/Includes/ctrulib/poll.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -#define POLLIN 0x01 -#define POLLPRI 0x02 -#define POLLHUP 0x04 // unknown ??? -#define POLLERR 0x08 // probably -#define POLLOUT 0x10 -#define POLLNVAL 0x20 - -typedef u32 nfds_t; - -struct pollfd -{ - int fd; - int events; - int revents; -}; - -#ifdef __cplusplus -extern "C" { -#endif - - int poll(struct pollfd *fds, nfds_t nfsd, int timeout); - -#ifdef __cplusplus -} -#endif diff --git a/Includes/ctrulib/result.h b/Includes/ctrulib/result.h deleted file mode 100644 index f6e11d9..0000000 --- a/Includes/ctrulib/result.h +++ /dev/null @@ -1,95 +0,0 @@ -/** - * @file result.h - * @brief 3DS result code tools - */ -#pragma once -#ifndef RESULT_H -#define RESULT_H -#ifdef __cplusplus -extern "C" { -#endif -/// Checks whether a result code indicates success. -#define R_SUCCEEDED(res) ((res)>=0) -/// Checks whether a result code indicates failure. -#define R_FAILED(res) ((res)<0) -/// Returns the level of a result code. -#define R_LEVEL(res) (((res)>>27)&0x1F) -/// Returns the summary of a result code. -#define R_SUMMARY(res) (((res)>>21)&0x3F) -/// Returns the module ID of a result code. -#define R_MODULE(res) (((res)>>10)&0xFF) -/// Returns the description of a result code. -#define R_DESCRIPTION(res) ((res)&0x3FF) - -/// Builds a result code from its constituent components. -#define MAKERESULT(level,summary,module,description) \ - ((((level)&0x1F)<<27) | (((summary)&0x3F)<<21) | (((module)&0xFF)<<10) | ((description)&0x3FF)) - -/// Result code level values. -enum -{ - // >= 0 - RL_SUCCESS = 0, - RL_INFO = 1, - - // < 0 - RL_FATAL = 0x1F, - RL_RESET = RL_FATAL - 1, - RL_REINITIALIZE = RL_FATAL - 2, - RL_USAGE = RL_FATAL - 3, - RL_PERMANENT = RL_FATAL - 4, - RL_TEMPORARY = RL_FATAL - 5, - RL_STATUS = RL_FATAL - 6, -}; - -/// Result code summary values. -enum -{ - RS_SUCCESS = 0, - RS_NOP = 1, - RS_WOULDBLOCK = 2, - RS_OUTOFRESOURCE = 3, - RS_NOTFOUND = 4, - RS_INVALIDSTATE = 5, - RS_NOTSUPPORTED = 6, - RS_INVALIDARG = 7, - RS_WRONGARG = 8, - RS_CANCELED = 9, - RS_STATUSCHANGED = 10, - RS_INTERNAL = 11, - RS_INVALIDRESVAL = 63, -}; - -/// Result code generic description values. -enum -{ - RD_SUCCESS = 0, - RD_INVALID_RESULT_VALUE = 0x3FF, - RD_TIMEOUT = RD_INVALID_RESULT_VALUE - 1, - RD_OUT_OF_RANGE = RD_INVALID_RESULT_VALUE - 2, - RD_ALREADY_EXISTS = RD_INVALID_RESULT_VALUE - 3, - RD_CANCEL_REQUESTED = RD_INVALID_RESULT_VALUE - 4, - RD_NOT_FOUND = RD_INVALID_RESULT_VALUE - 5, - RD_ALREADY_INITIALIZED = RD_INVALID_RESULT_VALUE - 6, - RD_NOT_INITIALIZED = RD_INVALID_RESULT_VALUE - 7, - RD_INVALID_HANDLE = RD_INVALID_RESULT_VALUE - 8, - RD_INVALID_POINTER = RD_INVALID_RESULT_VALUE - 9, - RD_INVALID_ADDRESS = RD_INVALID_RESULT_VALUE - 10, - RD_NOT_IMPLEMENTED = RD_INVALID_RESULT_VALUE - 11, - RD_OUT_OF_MEMORY = RD_INVALID_RESULT_VALUE - 12, - RD_MISALIGNED_SIZE = RD_INVALID_RESULT_VALUE - 13, - RD_MISALIGNED_ADDRESS = RD_INVALID_RESULT_VALUE - 14, - RD_BUSY = RD_INVALID_RESULT_VALUE - 15, - RD_NO_DATA = RD_INVALID_RESULT_VALUE - 16, - RD_INVALID_COMBINATION = RD_INVALID_RESULT_VALUE - 17, - RD_INVALID_ENUM_VALUE = RD_INVALID_RESULT_VALUE - 18, - RD_INVALID_SIZE = RD_INVALID_RESULT_VALUE - 19, - RD_ALREADY_DONE = RD_INVALID_RESULT_VALUE - 20, - RD_NOT_AUTHORIZED = RD_INVALID_RESULT_VALUE - 21, - RD_TOO_LARGE = RD_INVALID_RESULT_VALUE - 22, - RD_INVALID_SELECTION = RD_INVALID_RESULT_VALUE - 23, -}; -#ifdef __cplusplus -} -#endif -#endif diff --git a/Includes/ctrulib/sdmc.h b/Includes/ctrulib/sdmc.h deleted file mode 100644 index 3e8a50b..0000000 --- a/Includes/ctrulib/sdmc.h +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @file sdmc.h - * @brief SDMC driver. - */ -#pragma once - -#include - -#include -#include - -#define SDMC_DIRITER_MAGIC 0x73646D63 /* "sdmc" */ - -/*! Open directory struct */ -typedef struct -{ - u32 magic; /*! "sdmc" */ - Handle fd; /*! CTRU handle */ - ssize_t index; /*! Current entry index */ - size_t size; /*! Current batch size */ - FS_DirectoryEntry entry_data[32]; /*! Temporary storage for reading entries */ -} sdmc_dir_t; - -/// Initializes the SDMC driver. -Result sdmcInit(void); - -/// Enable/disable copy in sdmc_write -void sdmcWriteSafe(bool enable); - -/// Exits the SDMC driver. -Result sdmcExit(void); - -/// Get a file's mtime -Result sdmc_getmtime(const char *name, u64 *mtime); diff --git a/Includes/ctrulib/services/ac.h b/Includes/ctrulib/services/ac.h deleted file mode 100644 index 5b50787..0000000 --- a/Includes/ctrulib/services/ac.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include -/// Initializes AC. -Result acInit(void); - -/// Exits AC. -void acExit(void); - -/// Waits for the system to connect to the internet. -Result acWaitInternetConnection(void); - -/** - * @brief Gets the current Wifi status. - * @param out Pointer to output the current Wifi status to. (0 = not connected, 1 = O3DS Internet, 2 = N3DS Internet) - */ -Result ACU_GetWifiStatus(u32 *out); -#ifdef __cplusplus -} -#endif diff --git a/Includes/ctrulib/services/am.h b/Includes/ctrulib/services/am.h deleted file mode 100644 index 89c88f7..0000000 --- a/Includes/ctrulib/services/am.h +++ /dev/null @@ -1,497 +0,0 @@ -/** - * @file am.h - * @brief AM (Application Manager) service. - */ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif -#include - -/// Contains basic information about a title. -typedef struct -{ - u64 titleID; ///< The title's ID. - u64 size; ///< The title's installed size. - u16 version; ///< The title's version. - u8 unk[6]; ///< Unknown title data. -} AM_TitleEntry; - -/// Pending title status mask values. -enum -{ - AM_STATUS_MASK_INSTALLING = BIT(0), ///< Titles currently installing. - AM_STATUS_MASK_AWAITING_FINALIZATION = BIT(1) ///< Titles awaiting finalization. -}; - -/// Pending title status values. -typedef enum -{ - AM_STATUS_ABORTED = 0x0002, ///< Install aborted. - AM_STATUS_SAVED = 0x0003, ///< Title saved, but not installed. - AM_STATUS_INSTALL_IN_PROGRESS = 0x0802, ///< Install in progress. - AM_STATUS_AWAITING_FINALIZATION = 0x0803 ///< Awaiting finalization. -} AM_InstallStatus; - -// Contains basic information about a pending title. -typedef struct -{ - u64 titleId; ///< Title ID - u16 version; ///< Version - u16 status; ///< @ref AM_InstallStatus - u32 titleType; ///< Title Type - u8 unk[0x8]; ///< Unknown -} AM_PendingTitleEntry; - -/// Pending title deletion flags. -enum -{ - AM_DELETE_PENDING_NON_SYSTEM = BIT(0), ///< Non-system titles. - AM_DELETE_PENDING_SYSTEM = BIT(1) ///< System titles. -}; - -/// Information about the TWL NAND partition. -typedef struct { - u64 capacity; ///< Total capacity. - u64 freeSpace; ///< Total free space. - u64 titlesCapacity; ///< Capacity for titles. - u64 titlesFreeSpace; ///< Free space for titles. -} AM_TWLPartitionInfo; - -/// Initializes AM. This doesn't initialize with "am:app", see amAppInit(). -Result amInit(void); - -/// Initializes AM with a service which has access to the amapp-commands. This should only be used when using the amapp commands, not non-amapp AM commands. -Result amAppInit(void); - -/// Exits AM. -void amExit(void); - -/// Gets the current AM session handle. -Handle *amGetSessionHandle(void); - -/** - * @brief Gets the number of titles for a given media type. - * @param mediatype Media type to get titles from. - * @param[out] count Pointer to write the title count to. - */ -Result AM_GetTitleCount(FS_MediaType mediatype, u32 *count); - -/** - * @brief Gets a list of title IDs present in a mediatype. - * @param[out] titlesRead Pointer to output the number of read titles to. - * @param mediatype Media type to get titles from. - * @param titleCount Number of title IDs to get. - * @param titleIds Buffer to output the retrieved title IDs to. - */ -Result AM_GetTitleList(u32* titlesRead, FS_MediaType mediatype, u32 titleCount, u64 *titleIds); - -/** - * @brief Gets a list of details about installed titles. - * @param mediatype Media type to get titles from. - * @param titleCount Number of titles to list. - * @param titleIds List of title IDs to retrieve details for. - * @param titleInfo Buffer to write AM_TitleEntry's to. - */ -Result AM_GetTitleInfo(FS_MediaType mediatype, u32 titleCount, u64 *titleIds, AM_TitleEntry *titleInfo); - -/** - * @brief Gets the number of tickets installed on the system. - * @param[out] count Pointer to output the ticket count to. - */ -Result AM_GetTicketCount(u32 *count); - -/** - * @brief Gets a list of tickets installed on the system. - * @param[out] ticketsRead Pointer to output the number of read tickets to. - * @param ticketCount Number of tickets to read. - * @param skip Number of tickets to skip. - * @param ticketIds Buffer to output the retrieved ticket IDs to. - */ -Result AM_GetTicketList(u32 *ticketsRead, u32 ticketCount, u32 skip, u64 *ticketIds); - -/** - * @brief Gets the number of pending titles on this system. - * @param[out] count Pointer to output the pending title count to. - * @param mediatype Media type of pending titles to count. - * @param statusMask Bit mask of status values to include. - */ -Result AM_GetPendingTitleCount(u32 *count, FS_MediaType mediatype, u32 statusMask); - -/** - * @brief Gets a list of pending titles on this system. - * @param[out] titlesRead Pointer to output the number of read pending titles to. - * @param titleCount Number of pending titles to read. - * @param mediatype Media type of pending titles to list. - * @param statusMask Bit mask of status values to include. - * @param titleIds Buffer to output the retrieved pending title IDs to. - */ -Result AM_GetPendingTitleList(u32 *titlesRead, u32 titleCount, FS_MediaType mediatype, u32 statusMask, u64 *titleIds); - -/** - * @brief Gets information about pending titles on this system. - * @param titleCount Number of pending titles to read. - * @param mediatype Media type of pending titles to get information on. - * @param titleIds IDs of the titles to get information about. - * @param titleInfo Buffer to output the retrieved pending title info to. - */ -Result AM_GetPendingTitleInfo(u32 titleCount, FS_MediaType mediatype, u64 *titleIds, AM_PendingTitleEntry *titleInfo); - -/** - * @brief Gets a 32-bit device-specific ID. - * @param deviceID Pointer to write the device ID to. - */ -Result AM_GetDeviceId(u32 *deviceID); - -/** - * @brief Exports DSiWare to the specified filepath. - * @param titleID TWL titleID. - * @param operation DSiWare operation type. - * @param workbuf Work buffer. - * @param workbuf_size Work buffer size, must be >=0x20000. - * @param filepath UTF-8 filepath(converted to UTF-16 internally). - */ -Result AM_ExportTwlBackup(u64 titleID, u8 operation, void* workbuf, u32 workbuf_size, const char *filepath); - -/** - * @brief Imports DSiWare from the specified file. - * @param filehandle FSUSER file handle. - * @param operation DSiWare operation type. - * @param buffer Work buffer. - * @param size Buffer size, must be >=0x20000. - */ -Result AM_ImportTwlBackup(Handle filehandle, u8 operation, void* buffer, u32 size); - -/** - * @brief Reads info from the specified DSiWare export file. This can only be used with DSiWare exported with certain operation value(s). - * @param filehandle FSUSER file handle. - * @param outinfo Output info buffer. - * @param outinfo_size Output info buffer size. - * @param workbuf Work buffer. - * @param workbuf_size Work buffer size. - * @param banner Output banner buffer. - * @param banner_size Output banner buffer size. - */ -Result AM_ReadTwlBackupInfo(Handle filehandle, void* outinfo, u32 outinfo_size, void* workbuf, u32 workbuf_size, void* banner, u32 banner_size); - -/** - * @brief Retrieves information about the NAND TWL partition. - * @param[out] info Pointer to output the TWL partition info to. - */ -Result AM_GetTWLPartitionInfo(AM_TWLPartitionInfo *info); - -/** - * @brief Initializes the CIA install process, returning a handle to write CIA data to. - * @param mediatype Media type to install the CIA to. - * @param[out] ciaHandle Pointer to write the CIA handle to. - */ -Result AM_StartCiaInstall(FS_MediaType mediatype, Handle *ciaHandle); - -/** - * @brief Initializes the CIA install process for Download Play CIAs, returning a handle to write CIA data to. - * @param[out] ciaHandle Pointer to write the CIA handle to. - */ -Result AM_StartDlpChildCiaInstall(Handle *ciaHandle); - -/** - * @brief Aborts the CIA install process. - * @param ciaHandle CIA handle to cancel. - */ -Result AM_CancelCIAInstall(Handle ciaHandle); - -/** - * @brief Finalizes the CIA install process. - * @param ciaHandle CIA handle to finalize. - */ -Result AM_FinishCiaInstall(Handle ciaHandle); - -/** - * @brief Finalizes the CIA install process without committing the title to title.db or tmp*.db. - * @param ciaHandle CIA handle to finalize. - */ -Result AM_FinishCiaInstallWithoutCommit(Handle ciaHandle); - -/** - * @brief Commits installed CIAs. - * @param mediaType Location of the titles to finalize. - * @param titleCount Number of titles to finalize. - * @param temp Whether the titles being finalized are in the temporary database. - * @param titleIds Title IDs to finalize. - */ -Result AM_CommitImportPrograms(FS_MediaType mediaType, u32 titleCount, bool temp, const u64* titleIds); - -/** - * @brief Deletes a title. - * @param mediatype Media type to delete from. - * @param titleID ID of the title to delete. - */ -Result AM_DeleteTitle(FS_MediaType mediatype, u64 titleID); - -/** - * @brief Deletes a title, provided that it is not a system title. - * @param mediatype Media type to delete from. - * @param titleID ID of the title to delete. - */ -Result AM_DeleteAppTitle(FS_MediaType mediatype, u64 titleID); - -/** - * @brief Deletes a ticket. - * @param titleID ID of the ticket to delete. - */ -Result AM_DeleteTicket(u64 ticketId); - -/** - * @brief Deletes a pending title. - * @param mediatype Media type to delete from. - * @param titleId ID of the pending title to delete. - */ -Result AM_DeletePendingTitle(FS_MediaType mediatype, u64 titleId); - -/** - * @brief Deletes pending titles. - * @param mediatype Media type to delete from. - * @param flags Flags used to select pending titles. - */ -Result AM_DeletePendingTitles(FS_MediaType mediatype, u32 flags); - -/** - * @brief Deletes all pending titles. - * @param mediatype Media type to delete from. - */ -Result AM_DeleteAllPendingTitles(FS_MediaType mediatype); - -/// Installs the current NATIVE_FIRM title to NAND (firm0:/ & firm1:/) -Result AM_InstallNativeFirm(void); - -/** - * @brief Installs a NATIVE_FIRM title to NAND. Accepts 0004013800000002 or 0004013820000002 (N3DS). - * @param titleID Title ID of the NATIVE_FIRM to install. - */ -Result AM_InstallFirm(u64 titleID); - -/** - * @brief Gets the product code of a title. - * @param mediatype Media type of the title. - * @param titleID ID of the title. - * @param[out] productCode Pointer to output the product code to. (length = 16) - */ -Result AM_GetTitleProductCode(FS_MediaType mediatype, u64 titleId, char *productCode); - -/** - * @brief Gets the ext data ID of a title. - * @param[out] extDataId Pointer to output the ext data ID to. - * @param mediatype Media type of the title. - * @param titleID ID of the title. - */ -Result AM_GetTitleExtDataId(u64 *extDataId, FS_MediaType mediatype, u64 titleId); - -/** - * @brief Gets an AM_TitleEntry instance for a CIA file. - * @param mediatype Media type that this CIA would be installed to. - * @param[out] titleEntry Pointer to write the AM_TitleEntry instance to. - * @param fileHandle Handle of the CIA file. - */ -Result AM_GetCiaFileInfo(FS_MediaType mediatype, AM_TitleEntry *titleEntry, Handle fileHandle); - -/** - * @brief Gets the SMDH icon data of a CIA file. - * @param icon Buffer to store the icon data in. Must be of size 0x36C0 bytes. - * @param fileHandle Handle of the CIA file. - */ -Result AM_GetCiaIcon(void *icon, Handle fileHandle); - -/** - * @brief Gets the title ID dependency list of a CIA file. - * @param dependencies Buffer to store dependency title IDs in. Must be of size 0x300 bytes. - * @param fileHandle Handle of the CIA file. - */ -Result AM_GetCiaDependencies(u64 *dependencies, Handle fileHandle); - -/** - * @brief Gets the meta section offset of a CIA file. - * @param[out] metaOffset Pointer to output the meta section offset to. - * @param fileHandle Handle of the CIA file. - */ -Result AM_GetCiaMetaOffset(u64 *metaOffset, Handle fileHandle); - -/** - * @brief Gets the core version of a CIA file. - * @param[out] coreVersion Pointer to output the core version to. - * @param fileHandle Handle of the CIA file. - */ -Result AM_GetCiaCoreVersion(u32 *coreVersion, Handle fileHandle); - -/** - * @brief Gets the free space, in bytes, required to install a CIA file. - * @param[out] requiredSpace Pointer to output the required free space to. - * @param mediaType Media type to check free space needed to install to. - * @param fileHandle Handle of the CIA file. - */ -Result AM_GetCiaRequiredSpace(u64 *requiredSpace, FS_MediaType mediaType, Handle fileHandle); - -/** - * @brief Gets the full meta section of a CIA file. - * @param meta Buffer to store the meta section in. - * @param size Size of the buffer. Must be greater than or equal to the actual section data's size. - * @param fileHandle Handle of the CIA file. - */ -Result AM_GetCiaMetaSection(void *meta, u32 size, Handle fileHandle); - -/** - * @brief Initializes the external (SD) title database. - * @param overwrite Overwrites the database if it already exists. - */ -Result AM_InitializeExternalTitleDatabase(bool overwrite); - -/** - * @brief Queries whether the external title database is available. - * @param[out] available Pointer to output the availability status to. - */ -Result AM_QueryAvailableExternalTitleDatabase(bool* available); - -/** - * @brief Begins installing a ticket. - * @param[out] ticketHandle Pointer to output a handle to write ticket data to. - */ -Result AM_InstallTicketBegin(Handle *ticketHandle); - -/** - * @brief Aborts installing a ticket. - * @param ticketHandle Handle of the installation to abort. - */ -Result AM_InstallTicketAbort(Handle ticketHandle); - -/** - * @brief Finishes installing a ticket. - * @param ticketHandle Handle of the installation to finalize. - */ -Result AM_InstallTicketFinish(Handle ticketHandle); - -/** - * @brief Begins installing a title. - * @param mediaType Destination to install to. - * @param titleId ID of the title to install. - * @param unk Unknown. (usually false) - */ -Result AM_InstallTitleBegin(FS_MediaType mediaType, u64 titleId, bool unk); - -/// Stops installing a title, generally to be resumed later. -Result AM_InstallTitleStop(); - -/** - * @brief Resumes installing a title. - * @param mediaType Destination to install to. - * @param titleId ID of the title to install. - */ -Result AM_InstallTitleResume(FS_MediaType mediaType, u64 titleId); - -/// Aborts installing a title. -Result AM_InstallTitleAbort(); - -/// Finishes installing a title. -Result AM_InstallTitleFinish(); - -/** - * @brief Commits installed titles. - * @param mediaType Location of the titles to finalize. - * @param titleCount Number of titles to finalize. - * @param temp Whether the titles being finalized are in the temporary database. - * @param titleIds Title IDs to finalize. - */ -Result AM_CommitImportTitles(FS_MediaType mediaType, u32 titleCount, bool temp, const u64* titleIds); - -/** - * @brief Begins installing a TMD. - * @param[out] tmdHandle Pointer to output a handle to write TMD data to. - */ -Result AM_InstallTmdBegin(Handle *tmdHandle); - -/** - * @brief Aborts installing a TMD. - * @param tmdHandle Handle of the installation to abort. - */ -Result AM_InstallTmdAbort(Handle tmdHandle); - -/** - * @brief Finishes installing a TMD. - * @param tmdHandle Handle of the installation to finalize. - * @param unk Unknown. (usually true) - */ -Result AM_InstallTmdFinish(Handle tmdHandle, bool unk); - -/** - * @brief Prepares to import title contents. - * @param contentCount Number of contents to be imported. - * @param contentIndices Indices of the contents to be imported. - */ -Result AM_CreateImportContentContexts(u32 contentCount, u16* contentIndices); - -/** - * @brief Begins installing title content. - * @param[out] contentHandle Pointer to output a handle to write content data to. - * @param index Index of the content to install. - */ -Result AM_InstallContentBegin(Handle *contentHandle, u16 index); - -/** - * @brief Stops installing title content, generally to be resumed later. - * @param contentHandle Handle of the installation to abort. - */ -Result AM_InstallContentStop(Handle contentHandle); - -/** - * @brief Resumes installing title content. - * @param[out] contentHandle Pointer to output a handle to write content data to. - * @param[out] resumeOffset Pointer to write the offset to resume content installation at to. - * @param index Index of the content to install. - */ -Result AM_InstallContentResume(Handle *contentHandle, u64* resumeOffset, u16 index); - -/** - * @brief Cancels installing title content. - * @param contentHandle Handle of the installation to finalize. - */ -Result AM_InstallContentCancel(Handle contentHandle); - -/** - * @brief Finishes installing title content. - * @param contentHandle Handle of the installation to finalize. - */ -Result AM_InstallContentFinish(Handle contentHandle); - -/** - * @brief Imports up to four certificates into the ticket certificate chain. - * @param cert1Size Size of the first certificate. - * @param cert1 Data of the first certificate. - * @param cert2Size Size of the second certificate. - * @param cert2 Data of the second certificate. - * @param cert3Size Size of the third certificate. - * @param cert3 Data of the third certificate. - * @param cert4Size Size of the fourth certificate. - * @param cert4 Data of the fourth certificate. - */ -Result AM_ImportCertificates(u32 cert1Size, void* cert1, u32 cert2Size, void* cert2, u32 cert3Size, void* cert3, u32 cert4Size, void* cert4); - -/** - * @brief Imports a certificate into the ticket certificate chain. - * @param certSize Size of the certificate. - * @param cert Data of the certificate. - */ -Result AM_ImportCertificate(u32 certSize, void* cert); - -/** - * @brief Commits installed titles, and updates FIRM if necessary. - * @param mediaType Location of the titles to finalize. - * @param titleCount Number of titles to finalize. - * @param temp Whether the titles being finalized are in the temporary database. - * @param titleIds Title IDs to finalize. - */ -Result AM_CommitImportTitlesAndUpdateFirmwareAuto(FS_MediaType mediaType, u32 titleCount, bool temp, u64* titleIds); - -/// Resets play count of all installed demos by deleting their launch info. -Result AM_DeleteAllDemoLaunchInfos(void); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/Includes/ctrulib/services/apt.h b/Includes/ctrulib/services/apt.h deleted file mode 100644 index 0eacc7e..0000000 --- a/Includes/ctrulib/services/apt.h +++ /dev/null @@ -1,505 +0,0 @@ -/** - * @file apt.h - * @brief APT (Applet) service. - */ -#pragma once -#ifdef __cplusplus -extern "C" { -#endif -#include "../../types.h" -/** - * @brief NS Application IDs. - * - * Retrieved from http://3dbrew.org/wiki/NS_and_APT_Services#AppIDs - */ -typedef enum { - APPID_NONE = 0, - APPID_HOMEMENU = 0x101, ///< Home Menu - APPID_CAMERA = 0x110, ///< Camera applet - APPID_FRIENDS_LIST = 0x112, ///< Friends List applet - APPID_GAME_NOTES = 0x113, ///< Game Notes applet - APPID_WEB = 0x114, ///< Internet Browser - APPID_INSTRUCTION_MANUAL = 0x115, ///< Instruction Manual applet - APPID_NOTIFICATIONS = 0x116, ///< Notifications applet - APPID_MIIVERSE = 0x117, ///< Miiverse applet (olv) - APPID_MIIVERSE_POSTING = 0x118, ///< Miiverse posting applet (solv3) - APPID_AMIIBO_SETTINGS = 0x119, ///< Amiibo settings applet (cabinet) - APPID_APPLICATION = 0x300, ///< Application - APPID_ESHOP = 0x301, ///< eShop (tiger) - APPID_SOFTWARE_KEYBOARD = 0x401, ///< Software Keyboard - APPID_APPLETED = 0x402, ///< appletEd - APPID_PNOTE_AP = 0x404, ///< PNOTE_AP - APPID_SNOTE_AP = 0x405, ///< SNOTE_AP - APPID_ERROR = 0x406, ///< error - APPID_MINT = 0x407, ///< mint - APPID_EXTRAPAD = 0x408, ///< extrapad - APPID_MEMOLIB = 0x409, ///< memolib -} NS_APPID; - -/// APT applet position. -typedef enum { - APTPOS_NONE = -1, ///< No position specified. - APTPOS_APP = 0, ///< Application. - APTPOS_APPLIB = 1, ///< Application library (?). - APTPOS_SYS = 2, ///< System applet. - APTPOS_SYSLIB = 3, ///< System library (?). - APTPOS_RESIDENT = 4, ///< Resident applet. -} APT_AppletPos; - -typedef u8 APT_AppletAttr; - -/// Create an APT_AppletAttr bitfield from its components. -static inline APT_AppletAttr aptMakeAppletAttr(APT_AppletPos pos, bool manualGpuRights, bool manualDspRights) -{ - return (pos&7) | (manualGpuRights ? BIT(3) : 0) | (manualDspRights ? BIT(4) : 0); -} - -/// APT query reply. -typedef enum { - APTREPLY_REJECT = 0, - APTREPLY_ACCEPT = 1, - APTREPLY_LATER = 2, -} APT_QueryReply; - -/// APT signals. -typedef enum { - APTSIGNAL_NONE = 0, ///< No signal received. - APTSIGNAL_HOMEBUTTON = 1, ///< HOME button pressed. - APTSIGNAL_HOMEBUTTON2 = 2, ///< HOME button pressed (again?). - APTSIGNAL_SLEEP_QUERY = 3, ///< Prepare to enter sleep mode. - APTSIGNAL_SLEEP_CANCEL = 4, ///< Triggered when ptm:s GetShellStatus() returns 5. - APTSIGNAL_SLEEP_ENTER = 5, ///< Enter sleep mode. - APTSIGNAL_SLEEP_WAKEUP = 6, ///< Wake from sleep mode. - APTSIGNAL_SHUTDOWN = 7, ///< Shutdown. - APTSIGNAL_POWERBUTTON = 8, ///< POWER button pressed. - APTSIGNAL_POWERBUTTON2 = 9, ///< POWER button cleared (?). - APTSIGNAL_TRY_SLEEP = 10, ///< System sleeping (?). - APTSIGNAL_ORDERTOCLOSE = 11, ///< Order to close (such as when an error happens?). -} APT_Signal; - -/// APT commands. -typedef enum { - APTCMD_NONE = 0, ///< No command received. - APTCMD_WAKEUP = 1, ///< Applet should wake up. - APTCMD_REQUEST = 2, ///< Source applet sent us a parameter. - APTCMD_RESPONSE = 3, ///< Target applet replied to our parameter. - APTCMD_EXIT = 4, ///< Exit (??) - APTCMD_MESSAGE = 5, ///< Message (??) - APTCMD_HOMEBUTTON_ONCE = 6, ///< HOME button pressed once. - APTCMD_HOMEBUTTON_TWICE = 7, ///< HOME button pressed twice (double-pressed). - APTCMD_DSP_SLEEP = 8, ///< DSP should sleep (manual DSP rights related?). - APTCMD_DSP_WAKEUP = 9, ///< DSP should wake up (manual DSP rights related?). - APTCMD_WAKEUP_EXIT = 10, ///< Applet wakes up due to a different applet exiting. - APTCMD_WAKEUP_PAUSE = 11, ///< Applet wakes up after being paused through HOME menu. - APTCMD_WAKEUP_CANCEL = 12, ///< Applet wakes up due to being cancelled. - APTCMD_WAKEUP_CANCELALL = 13, ///< Applet wakes up due to all applets being cancelled. - APTCMD_WAKEUP_POWERBUTTON = 14, ///< Applet wakes up due to POWER button being pressed (?). - APTCMD_WAKEUP_JUMPTOHOME = 15, ///< Applet wakes up and is instructed to jump to HOME menu (?). - APTCMD_SYSAPPLET_REQUEST = 16, ///< Request for sysapplet (?). - APTCMD_WAKEUP_LAUNCHAPP = 17, ///< Applet wakes up and is instructed to launch another applet (?). -} APT_Command; - -/// APT capture buffer information. -typedef struct -{ - u32 size; - u32 is3D; - struct - { - u32 leftOffset; - u32 rightOffset; - u32 format; - } top, bottom; -} aptCaptureBufInfo; - -/// APT hook types. -typedef enum { - APTHOOK_ONSUSPEND = 0, ///< App suspended. - APTHOOK_ONRESTORE, ///< App restored. - APTHOOK_ONSLEEP, ///< App sleeping. - APTHOOK_ONWAKEUP, ///< App waking up. - APTHOOK_ONEXIT, ///< App exiting. - - APTHOOK_COUNT, ///< Number of APT hook types. -} APT_HookType; - -/// APT hook function. -typedef void (*aptHookFn)(APT_HookType hook, void* param); - -/// APT hook cookie. -typedef struct tag_aptHookCookie -{ - struct tag_aptHookCookie* next; ///< Next cookie. - aptHookFn callback; ///< Hook callback. - void* param; ///< Callback parameter. -} aptHookCookie; - -/// APT message callback. -typedef void (*aptMessageCb)(void* user, NS_APPID sender, void* msg, size_t msgsize); - -/// Initializes APT. -Result aptInit(void); - -/// Exits APT. -void aptExit(void); - -/** - * @brief Sends an APT command through IPC, taking care of locking, opening and closing an APT session. - * @param aptcmdbuf Pointer to command buffer (should have capacity for at least 16 words). - */ -Result aptSendCommand(u32* aptcmdbuf); - -/** - * @brief Gets whether to allow the system to enter sleep mode. - * @return Whether sleep mode is allowed. - */ -bool aptIsSleepAllowed(void); - -/** - * @brief Sets whether to allow the system to enter sleep mode. - * @param allowed Whether to allow sleep mode. - */ -void aptSetSleepAllowed(bool allowed); - -/** - * @brief Processes the current APT status. Generally used within a main loop. - * @return Whether the application should continue running. - */ -bool aptMainLoop(void); - -/** - * @brief Sets up an APT status hook. - * @param cookie Hook cookie to use. - * @param callback Function to call when APT's status changes. - * @param param User-defined parameter to pass to the callback. - */ -void aptHook(aptHookCookie* cookie, aptHookFn callback, void* param); - -/** - * @brief Removes an APT status hook. - * @param cookie Hook cookie to remove. - */ -void aptUnhook(aptHookCookie* cookie); - -/** - * @brief Sets the function to be called when an APT message from another applet is received. - * @param callback Callback function. - * @param user User-defined data to be passed to the callback. - */ -void aptSetMessageCallback(aptMessageCb callback, void* user); - -/** - * @brief Launches a library applet. - * @param appId ID of the applet to launch. - * @param buf Input/output buffer that contains launch parameters on entry and result data on exit. - * @param bufsize Size of the buffer. - * @param handle Handle to pass to the library applet. - * @return Whether the application should continue running after the library applet launch. - */ -bool aptLaunchLibraryApplet(NS_APPID appId, void* buf, size_t bufsize, Handle handle); - -/** - * @brief Gets an APT lock handle. - * @param flags Flags to use. - * @param lockHandle Pointer to output the lock handle to. - */ -Result APT_GetLockHandle(u16 flags, Handle* lockHandle); - -/** - * @brief Initializes an application's registration with APT. - * @param appId ID of the application. - * @param attr Attributes of the application. - * @param signalEvent Pointer to output the signal event handle to. - * @param resumeEvent Pointer to output the resume event handle to. - */ -Result APT_Initialize(NS_APPID appId, APT_AppletAttr attr, Handle* signalEvent, Handle* resumeEvent); - -/** - * @brief Terminates an application's registration with APT. - * @param appID ID of the application. - */ -Result APT_Finalize(NS_APPID appId); - -/// Asynchronously resets the hardware. -Result APT_HardwareResetAsync(void); - -/** - * @brief Enables APT. - * @param attr Attributes of the application. - */ -Result APT_Enable(APT_AppletAttr attr); - -/** - * @brief Gets applet management info. - * @param inpos Requested applet position. - * @param outpos Pointer to output the position of the current applet to. - * @param req_appid Pointer to output the AppID of the applet at the requested position to. - * @param menu_appid Pointer to output the HOME menu AppID to. - * @param active_appid Pointer to output the AppID of the currently active applet to. - */ -Result APT_GetAppletManInfo(APT_AppletPos inpos, APT_AppletPos* outpos, NS_APPID* req_appid, NS_APPID* menu_appid, NS_APPID* active_appid); - -/** - * @brief Gets the menu's app ID. - * @return The menu's app ID. - */ -static inline NS_APPID aptGetMenuAppID(void) -{ - NS_APPID menu_appid = APPID_NONE; - APT_GetAppletManInfo(APTPOS_NONE, NULL, NULL, &menu_appid, NULL); - return menu_appid; -} - -/** - * @brief Gets an applet's information. - * @param appID AppID of the applet. - * @param pProgramID Pointer to output the program ID to. - * @param pMediaType Pointer to output the media type to. - * @param pRegistered Pointer to output the registration status to. - * @param pLoadState Pointer to output the load state to. - * @param pAttributes Pointer to output the applet atrributes to. - */ -Result APT_GetAppletInfo(NS_APPID appID, u64* pProgramID, u8* pMediaType, bool* pRegistered, bool* pLoadState, APT_AppletAttr* pAttributes); - -/** - * @brief Gets an applet's program information. - * @param id ID of the applet. - * @param flags Flags to use when retreiving the information. - * @param titleversion Pointer to output the applet's title version to. - * - * Flags: - * - 0x01: Use AM_ListTitles with NAND media type. - * - 0x02: Use AM_ListTitles with SDMC media type. - * - 0x04: Use AM_ListTitles with GAMECARD media type. - * - 0x10: Input ID is an app ID. Must be set if 0x20 is not. - * - 0x20: Input ID is a program ID. Must be set if 0x10 is not. - * - 0x100: Sets program ID high to 0x00040000, else it is 0x00040010. Only used when 0x20 is set. - */ -Result APT_GetAppletProgramInfo(u32 id, u32 flags, u16 *titleversion); - -/** - * @brief Gets the current application's program ID. - * @param pProgramID Pointer to output the program ID to. - */ -Result APT_GetProgramID(u64* pProgramID); - -/// Prepares to jump to the home menu. -Result APT_PrepareToJumpToHomeMenu(void); - -/** - * @brief Jumps to the home menu. - * @param param Parameters to jump with. - * @param Size of the parameter buffer. - * @param handle Handle to pass. - */ -Result APT_JumpToHomeMenu(const void* param, size_t paramSize, Handle handle); - -/** - * @brief Prepares to jump to an application. - * @param exiting Specifies whether the applet is exiting. - */ -Result APT_PrepareToJumpToApplication(bool exiting); - -/** - * @brief Jumps to an application. - * @param param Parameters to jump with. - * @param Size of the parameter buffer. - * @param handle Handle to pass. - */ -Result APT_JumpToApplication(const void* param, size_t paramSize, Handle handle); - -/** - * @brief Gets whether an application is registered. - * @param appID ID of the application. - * @param out Pointer to output the registration state to. - */ -Result APT_IsRegistered(NS_APPID appID, bool* out); - -/** - * @brief Inquires as to whether a signal has been received. - * @param appID ID of the application. - * @param signalType Pointer to output the signal type to. - */ -Result APT_InquireNotification(u32 appID, APT_Signal* signalType); - -/** - * @brief Notifies an application to wait. - * @param appID ID of the application. - */ -Result APT_NotifyToWait(NS_APPID appID); - -/** - * @brief Calls an applet utility function. - * @param id Utility function to call. - * @param out Pointer to write output data to. - * @param outSize Size of the output buffer. - * @param in Pointer to the input data. - * @param inSize Size of the input buffer. - */ -Result APT_AppletUtility(int id, void* out, size_t outSize, const void* in, size_t inSize); - -/// Sleeps if shell is closed (?). -Result APT_SleepIfShellClosed(void); - -/** - * @brief Tries to lock a transition (?). - * @param transition Transition ID. - * @param succeeded Pointer to output whether the lock was successfully applied. - */ -Result APT_TryLockTransition(u32 transition, bool* succeeded); - -/** - * @brief Unlocks a transition (?). - * @param transition Transition ID. - */ -Result APT_UnlockTransition(u32 transition); - -/** - * @brief Glances at a receieved parameter without removing it from the queue. - * @param appID AppID of the application. - * @param buffer Buffer to receive to. - * @param bufferSize Size of the buffer. - * @param sender Pointer to output the sender's AppID to. - * @param command Pointer to output the command ID to. - * @param actualSize Pointer to output the actual received data size to. - * @param parameter Pointer to output the parameter handle to. - */ -Result APT_GlanceParameter(NS_APPID appID, void* buffer, size_t bufferSize, NS_APPID* sender, APT_Command* command, size_t* actualSize, Handle* parameter); - -/** - * @brief Receives a parameter. - * @param appID AppID of the application. - * @param buffer Buffer to receive to. - * @param bufferSize Size of the buffer. - * @param sender Pointer to output the sender's AppID to. - * @param command Pointer to output the command ID to. - * @param actualSize Pointer to output the actual received data size to. - * @param parameter Pointer to output the parameter handle to. - */ -Result APT_ReceiveParameter(NS_APPID appID, void* buffer, size_t bufferSize, NS_APPID* sender, APT_Command* command, size_t* actualSize, Handle* parameter); - -/** - * @brief Sends a parameter. - * @param source AppID of the source application. - * @param dest AppID of the destination application. - * @param command Command to send. - * @param buffer Buffer to send. - * @param bufferSize Size of the buffer. - * @param parameter Parameter handle to pass. - */ -Result APT_SendParameter(NS_APPID source, NS_APPID dest, APT_Command command, const void* buffer, u32 bufferSize, Handle parameter); - -/** - * @brief Cancels a parameter which matches the specified source and dest AppIDs. - * @param source AppID of the source application (use APPID_NONE to disable the check). - * @param dest AppID of the destination application (use APPID_NONE to disable the check). - * @param success Pointer to output true if a parameter was cancelled, or false otherwise. - */ -Result APT_CancelParameter(NS_APPID source, NS_APPID dest, bool* success); - -/** - * @brief Sends capture buffer information. - * @param captureBuf Capture buffer information to send. - */ -Result APT_SendCaptureBufferInfo(const aptCaptureBufInfo* captureBuf); - -/** - * @brief Replies to a sleep query. - * @param appID ID of the application. - * @param reply Query reply value. - */ -Result APT_ReplySleepQuery(NS_APPID appID, APT_QueryReply reply); - -/** - * @brief Replies that a sleep notification has been completed. - * @param appID ID of the application. - */ -Result APT_ReplySleepNotificationComplete(NS_APPID appID); - -/** - * @brief Prepares to close the application. - * @param cancelPreload Whether applet preloads should be cancelled. - */ -Result APT_PrepareToCloseApplication(bool cancelPreload); - -/** - * @brief Closes the application. - * @param param Parameters to close with. - * @param paramSize Size of param. - * @param handle Handle to pass. - */ -Result APT_CloseApplication(const void* param, size_t paramSize, Handle handle); - -/** - * @brief Sets the application's CPU time limit. - * @param percent CPU time limit percentage to set. - */ -Result APT_SetAppCpuTimeLimit(u32 percent); - -/** - * @brief Gets the application's CPU time limit. - * @param percent Pointer to output the CPU time limit percentage to. - */ -Result APT_GetAppCpuTimeLimit(u32 *percent); - -/** - * @brief Checks whether the system is a New 3DS. - * @param out Pointer to write the New 3DS flag to. - */ -Result APT_CheckNew3DS(bool* out); - -/** - * @brief Prepares for an applicaton jump. - * @param flags Flags to use. - * @param programID ID of the program to jump to. - * @param mediatype Media type of the program to jump to. - */ -Result APT_PrepareToDoApplicationJump(u8 flags, u64 programID, u8 mediatype); - -/** - * @brief Performs an application jump. - * @param param Parameter buffer. - * @param paramSize Size of parameter buffer. - * @param hmac HMAC buffer (should be 0x20 bytes long). - */ -Result APT_DoApplicationJump(const void* param, size_t paramSize, const void* hmac); - -/** - * @brief Prepares to start a library applet. - * @param appID AppID of the applet to start. - */ -Result APT_PrepareToStartLibraryApplet(NS_APPID appID); - -/** - * @brief Starts a library applet. - * @param appID AppID of the applet to launch. - * @param param Buffer containing applet parameters. - * @param paramsize Size of the buffer. - * @param handle Handle to pass to the applet. - */ -Result APT_StartLibraryApplet(NS_APPID appID, const void* param, size_t paramSize, Handle handle); - -/** - * @brief Prepares to start a system applet. - * @param appID AppID of the applet to start. - */ -Result APT_PrepareToStartSystemApplet(NS_APPID appID); - -/** - * @brief Starts a system applet. - * @param appID AppID of the applet to launch. - * @param param Buffer containing applet parameters. - * @param paramSize Size of the parameter buffer. - * @param handle Handle to pass to the applet. - */ -Result APT_StartSystemApplet(NS_APPID appID, const void* param, size_t paramSize, Handle handle); - -/** - * @brief Retrieves the shared system font. - * @brief fontHandle Pointer to write the handle of the system font memory block to. - * @brief mapAddr Pointer to write the mapping address of the system font memory block to. - */ -Result APT_GetSharedFont(Handle* fontHandle, u32* mapAddr); -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/Includes/ctrulib/services/cfgu.h b/Includes/ctrulib/services/cfgu.h deleted file mode 100644 index 7fbaab0..0000000 --- a/Includes/ctrulib/services/cfgu.h +++ /dev/null @@ -1,107 +0,0 @@ -/** - * @file cfgu.h - * @brief CFGU (Configuration) Service - **/ -#ifndef CFGU_H -#define CFGU_H -#ifdef __cplusplus -extern "C" { -#endif -#include "../../types.h" -/// Configuration region values. -typedef enum -{ - CFG_REGION_JPN = 0, ///< Japan - CFG_REGION_USA = 1, ///< USA - CFG_REGION_EUR = 2, ///< Europe - CFG_REGION_AUS = 3, ///< Australia - CFG_REGION_CHN = 4, ///< China - CFG_REGION_KOR = 5, ///< Korea - CFG_REGION_TWN = 6, ///< Taiwan -} CFG_Region; - -/// Configuration language values. -typedef enum -{ - CFG_LANGUAGE_JP = 0, ///< Japanese - CFG_LANGUAGE_EN = 1, ///< English - CFG_LANGUAGE_FR = 2, ///< French - CFG_LANGUAGE_DE = 3, ///< German - CFG_LANGUAGE_IT = 4, ///< Italian - CFG_LANGUAGE_ES = 5, ///< Spanish - CFG_LANGUAGE_ZH = 6, ///< Simplified Chinese - CFG_LANGUAGE_KO = 7, ///< Korean - CFG_LANGUAGE_NL = 8, ///< Dutch - CFG_LANGUAGE_PT = 9, ///< Portugese - CFG_LANGUAGE_RU = 10, ///< Russian - CFG_LANGUAGE_TW = 11, ///< Traditional Chinese -} CFG_Language; - -/// Initializes CFGU. -Result cfguInit(void); - -/// Exits CFGU. -void cfguExit(void); - -/** - * @brief Gets the system's region from secure info. - * @param region Pointer to output the region to. (see @ref CFG_Region) - */ -Result CFGU_SecureInfoGetRegion(u8* region); - -/** - * @brief Generates a console-unique hash. - * @param appIDSalt Salt to use. - * @param hash Pointer to output the hash to. - */ -Result CFGU_GenHashConsoleUnique(u32 appIDSalt, u64* hash); - -/** - * @brief Gets whether the system's region is Canada or USA. - * @param value Pointer to output the result to. (0 = no, 1 = yes) - */ -Result CFGU_GetRegionCanadaUSA(u8* value); - -/** - * @brief Gets the system's model. - * @param model Pointer to output the model to. (0 = O3DS, 1 = O3DSXL, 2 = N3DS, 3 = 2DS, 4 = N3DSXL) - */ -Result CFGU_GetSystemModel(u8* model); - -/** - * @brief Gets whether the system is a 2DS. - * @param value Pointer to output the result to. (0 = yes, 1 = no) - */ -Result CFGU_GetModelNintendo2DS(u8* value); - -/** - * @brief Gets a string representing a country code. - * @param code Country code to use. - * @param string Pointer to output the string to. - */ -Result CFGU_GetCountryCodeString(u16 code, u16* string); - -/** - * @brief Gets a country code ID from its string. - * @param string String to use. - * @param code Pointer to output the country code to. - */ -Result CFGU_GetCountryCodeID(u16 string, u16* code); - -/** - * @brief Gets a config info block. - * @param size Size of the data to retrieve. - * @param blkID ID of the block to retrieve. - * @param outData Pointer to write the block data to. - */ -Result CFGU_GetConfigInfoBlk2(u32 size, u32 blkID, u8* outData); - -/** - * @brief Gets the system's language. - * @param language Pointer to write the language to. (see @ref CFG_Language) - */ -Result CFGU_GetSystemLanguage(u8* language); -#ifdef __cplusplus -} -#endif -#endif \ No newline at end of file diff --git a/Includes/ctrulib/services/csnd.h b/Includes/ctrulib/services/csnd.h deleted file mode 100644 index 8fc91e8..0000000 --- a/Includes/ctrulib/services/csnd.h +++ /dev/null @@ -1,433 +0,0 @@ -/** - * @file csnd.h - * @brief CSND service. Usage of this service is deprecated in favor of NDSP. - */ -#pragma once - -#include - -/// Maximum number of CSND channels. -#define CSND_NUM_CHANNELS 32 - -/// Creates a CSND timer value from a sample rate. -#define CSND_TIMER(n) (0x3FEC3FC / ((u32)(n))) - -/** - * @brief Converts a vol-pan pair into a left/right volume pair used by the hardware. - * @param vol Volume to use. - * @param pan Pan to use. - * @return A left/right volume pair for use by hardware. - */ -static inline u32 CSND_VOL(float vol, float pan) -{ - float rpan; - u32 lvol, rvol; - - if (vol < 0.0f) vol = 0.0f; - else if (vol > 1.0f) vol = 1.0f; - - rpan = (pan+1) / 2; - if (rpan < 0.0f) rpan = 0.0f; - else if (rpan > 1.0f) rpan = 1.0f; - - lvol = vol*(1-rpan) * 0x8000; - rvol = vol*rpan * 0x8000; - return lvol | (rvol << 16); -} - -/// CSND encodings. -enum -{ - CSND_ENCODING_PCM8 = 0, ///< PCM8 - CSND_ENCODING_PCM16, ///< PCM16 - CSND_ENCODING_ADPCM, ///< IMA-ADPCM - CSND_ENCODING_PSG, ///< PSG (Similar to DS?) -}; - -/// CSND loop modes. -enum -{ - CSND_LOOPMODE_MANUAL = 0, ///< Manual loop. - CSND_LOOPMODE_NORMAL, ///< Normal loop. - CSND_LOOPMODE_ONESHOT, ///< Do not loop. - CSND_LOOPMODE_NORELOAD, ///< Don't reload. -}; - -/// Creates a sound channel value from a channel number. -#define SOUND_CHANNEL(n) ((u32)(n) & 0x1F) - -/// Creates a sound format value from an encoding. -#define SOUND_FORMAT(n) ((u32)(n) << 12) - -/// Creates a sound loop mode value from a loop mode. -#define SOUND_LOOPMODE(n) ((u32)(n) << 10) - -/// Sound flags. -enum -{ - SOUND_LINEAR_INTERP = BIT(6), ///< Linear interpolation. - SOUND_REPEAT = SOUND_LOOPMODE(CSND_LOOPMODE_NORMAL), ///< Repeat the sound. - SOUND_ONE_SHOT = SOUND_LOOPMODE(CSND_LOOPMODE_ONESHOT), ///< Play the sound once. - SOUND_FORMAT_8BIT = SOUND_FORMAT(CSND_ENCODING_PCM8), ///< PCM8 - SOUND_FORMAT_16BIT = SOUND_FORMAT(CSND_ENCODING_PCM16), ///< PCM16 - SOUND_FORMAT_ADPCM = SOUND_FORMAT(CSND_ENCODING_ADPCM), ///< ADPCM - SOUND_FORMAT_PSG = SOUND_FORMAT(CSND_ENCODING_PSG), ///< PSG - SOUND_ENABLE = BIT(14), ///< Enable sound. -}; - -/// Capture modes. -enum -{ - CAPTURE_REPEAT = 0, ///< Repeat capture. - CAPTURE_ONE_SHOT = BIT(0), ///< Capture once. - CAPTURE_FORMAT_16BIT = 0, ///< PCM16 - CAPTURE_FORMAT_8BIT = BIT(1), ///< PCM8 - CAPTURE_ENABLE = BIT(15), ///< Enable capture. -}; - -/// Duty cycles for a PSG channel. -typedef enum -{ - DutyCycle_0 = 7, ///< 0.0% duty cycle - DutyCycle_12 = 0, ///< 12.5% duty cycle - DutyCycle_25 = 1, ///< 25.0% duty cycle - DutyCycle_37 = 2, ///< 37.5% duty cycle - DutyCycle_50 = 3, ///< 50.0% duty cycle - DutyCycle_62 = 4, ///< 62.5% duty cycle - DutyCycle_75 = 5, ///< 75.0% duty cycle - DutyCycle_87 = 6 ///< 87.5% duty cycle -} CSND_DutyCycle; - -/// Channel info. -typedef union -{ - u32 value[3]; ///< Raw values. - struct - { - u8 active; ///< Channel active. - u8 _pad1; ///< Padding. - u16 _pad2; ///< Padding. - s16 adpcmSample; ///< Current ADPCM sample. - u8 adpcmIndex; ///< Current ADPCM index. - u8 _pad3; ///< Padding. - u32 unknownZero; ///< Unknown. - }; -} CSND_ChnInfo; - -/// Capture info. -typedef union -{ - u32 value[2]; ///< Raw values. - struct - { - u8 active; ///< Capture active. - u8 _pad1; ///< Padding. - u16 _pad2; ///< Padding. - u32 unknownZero; ///< Unknown. - }; -} CSND_CapInfo; - -// See here regarding CSND shared-mem commands, etc: http://3dbrew.org/wiki/CSND_Shared_Memory - -extern vu32* csndSharedMem; ///< CSND shared memory. -extern u32 csndSharedMemSize; ///< CSND shared memory size. -extern u32 csndChannels; ///< Bitmask of channels that are allowed for usage. - -/** - * @brief Acquires a capture unit. - * @param capUnit Pointer to output the capture unit to. - */ -Result CSND_AcquireCapUnit(u32* capUnit); - -/** - * @brief Releases a capture unit. - * @param capUnit Capture unit to release. - */ -Result CSND_ReleaseCapUnit(u32 capUnit); - -/** - * @brief Flushes the data cache of a memory region. - * @param adr Address of the memory region. - * @param size Size of the memory region. - */ -Result CSND_FlushDataCache(const void* adr, u32 size); - -/** - * @brief Stores the data cache of a memory region. - * @param adr Address of the memory region. - * @param size Size of the memory region. - */ -Result CSND_StoreDataCache(const void* adr, u32 size); - -/** - * @brief Invalidates the data cache of a memory region. - * @param adr Address of the memory region. - * @param size Size of the memory region. - */ -Result CSND_InvalidateDataCache(const void* adr, u32 size); - -/** - * @brief Resets CSND. - * Note: Currently breaks sound, don't use for now! - */ -Result CSND_Reset(void); - -/// Initializes CSND. -Result csndInit(void); - -/// Exits CSND. -void csndExit(void); - -/** - * @brief Adds a command to the list, returning a buffer to write arguments to. - * @param cmdid ID of the command to add. - * @return A buffer to write command arguments to. - */ -u32* csndAddCmd(int cmdid); - -/** - * @brief Adds a command to the list, copying its arguments from a buffer. - * @param cmdid ID of the command to add. - * @param cmdparams Buffer containing the command's parameters. - */ -void csndWriteCmd(int cmdid, u8* cmdparams); - -/** - * @brief Executes pending CSND commands. - * @param waitDone Whether to wait until the commands have finished executing. - */ -Result csndExecCmds(bool waitDone); - -/** - * @brief Sets a channel's play state, resetting registers on stop. - * @param channel Channel to use. - * @param value Play state to set. - */ -void CSND_SetPlayStateR(u32 channel, u32 value); - -/** - * @brief Sets a channel's play state. - * @param channel Channel to use. - * @param value Play state to set. - */ -void CSND_SetPlayState(u32 channel, u32 value); - -/** - * @brief Sets a channel's encoding. - * @param channel Channel to use. - * @param value Encoding to set. - */ -void CSND_SetEncoding(u32 channel, u32 value); - -/** - * @brief Sets the data of a channel's block. - * @param channel Channel to use. - * @param block Block to set. - * @param physaddr Physical address to set the block to. - * @param size Size of the block. - */ -void CSND_SetBlock(u32 channel, int block, u32 physaddr, u32 size); - -/** - * @brief Sets whether to loop a channel. - * @param channel Channel to use. - * @param value Whether to loop the channel. - */ -void CSND_SetLooping(u32 channel, u32 value); - -/** - * @brief Sets bit 7 of a channel. - * @param channel Channel to use. - * @param set Value to set. - */ -void CSND_SetBit7(u32 channel, bool set); - -/** - * @brief Sets whether a channel should use interpolation. - * @param channel Channel to use. - * @param interp Whether to use interpolation. - */ -void CSND_SetInterp(u32 channel, bool interp); - -/** - * @brief Sets a channel's duty. - * @param channel Channel to use. - * @param duty Duty to set. - */ -void CSND_SetDuty(u32 channel, CSND_DutyCycle duty); - -/** - * @brief Sets a channel's timer. - * @param channel Channel to use. - * @param timer Timer to set. - */ -void CSND_SetTimer(u32 channel, u32 timer); - -/** - * @brief Sets a channel's volume. - * @param channel Channel to use. - * @param chnVolumes Channel volume data to set. - * @param capVolumes Capture volume data to set. - */ -void CSND_SetVol(u32 channel, u32 chnVolumes, u32 capVolumes); - -/** - * @brief Sets a channel's ADPCM state. - * @param channel Channel to use. - * @param block Current block. - * @param sample Current sample. - * @param index Current index. - */ -void CSND_SetAdpcmState(u32 channel, int block, int sample, int index); - -/** - * @brief Sets a whether channel's ADPCM data should be reloaded when the second block is played. - * @param channel Channel to use. - * @param reload Whether to reload ADPCM data. - */ -void CSND_SetAdpcmReload(u32 channel, bool reload); - -/** - * @brief Sets CSND's channel registers. - * @param flags Flags to set. - * @param physaddr0 Physical address of the first buffer to play. - * @param physaddr1 Physical address of the second buffer to play. - * @param totalbytesize Total size of the data to play. - * @param chnVolumes Channel volume data. - * @param capVolumes Capture volume data. - */ -void CSND_SetChnRegs(u32 flags, u32 physaddr0, u32 physaddr1, u32 totalbytesize, u32 chnVolumes, u32 capVolumes); - -/** - * @brief Sets CSND's PSG channel registers. - * @param flags Flags to set. - * @param chnVolumes Channel volume data. - * @param capVolumes Capture volume data. - * @param duty Duty value to set. - */ -void CSND_SetChnRegsPSG(u32 flags, u32 chnVolumes, u32 capVolumes, CSND_DutyCycle duty); - -/** - * @brief Sets CSND's noise channel registers. - * @param flags Flags to set. - * @param chnVolumes Channel volume data. - * @param capVolumes Capture volume data. - */ -void CSND_SetChnRegsNoise(u32 flags, u32 chnVolumes, u32 capVolumes); - -/** - * @brief Sets whether a capture unit is enabled. - * @param capUnit Capture unit to use. - * @param enable Whether to enable the capture unit. - */ -void CSND_CapEnable(u32 capUnit, bool enable); - -/** - * @brief Sets whether a capture unit should repeat. - * @param capUnit Capture unit to use. - * @param repeat Whether the capture unit should repeat. - */ -void CSND_CapSetRepeat(u32 capUnit, bool repeat); - -/** - * @brief Sets a capture unit's format. - * @param capUnit Capture unit to use. - * @param eightbit Format to use. - */ -void CSND_CapSetFormat(u32 capUnit, bool eightbit); - -/** - * @brief Sets a capture unit's second bit. - * @param capUnit Capture unit to use. - * @param set Value to set. - */ -void CSND_CapSetBit2(u32 capUnit, bool set); - -/** - * @brief Sets a capture unit's timer. - * @param capUnit Capture unit to use. - * @param timer Timer to set. - */ -void CSND_CapSetTimer(u32 capUnit, u32 timer); - -/** - * @brief Sets a capture unit's buffer. - * @param capUnit Capture unit to use. - * @param addr Buffer address to use. - * @param size Size of the buffer. - */ -void CSND_CapSetBuffer(u32 capUnit, u32 addr, u32 size); - -/** - * @brief Sets a capture unit's capture registers. - * @param capUnit Capture unit to use. - * @param flags Capture unit flags. - * @param addr Capture unit buffer address. - * @param size Buffer size. - */ -void CSND_SetCapRegs(u32 capUnit, u32 flags, u32 addr, u32 size); - -/** - * @brief Sets up DSP flags. - * @param waitDone Whether to wait for completion. - */ -Result CSND_SetDspFlags(bool waitDone); - -/** - * @brief Updates CSND information. - * @param waitDone Whether to wait for completion. - */ -Result CSND_UpdateInfo(bool waitDone); - -/** - * @brief Plays a sound. - * @param chn Channel to play the sound on. - * @param flags Flags containing information about the sound. - * @param sampleRate Sample rate of the sound. - * @param vol The volume, ranges from 0.0 to 1.0 included. - * @param pan The pan, ranges from -1.0 to 1.0 included. - * @param data0 First block of sound data. - * @param data1 Second block of sound data. This is the block that will be looped over. - * @param size Size of the sound data. - * - * In this implementation if the loop mode is used, data1 must be in the range [data0 ; data0 + size]. Sound will be played once from data0 to data0 + size and then loop between data1 and data0+size. - */ -Result csndPlaySound(int chn, u32 flags, u32 sampleRate, float vol, float pan, void* data0, void* data1, u32 size); - -/** - * @brief Gets CSND's DSP flags. - * Note: Requires previous CSND_UpdateInfo() - * @param outSemFlags Pointer to write semaphore flags to. - * @param outIrqFlags Pointer to write interrupt flags to. - */ -void csndGetDspFlags(u32* outSemFlags, u32* outIrqFlags); - -/** - * @brief Gets a channel's information. - * Note: Requires previous CSND_UpdateInfo() - * @param channel Channel to get information for. - * @return The channel's information. - */ -CSND_ChnInfo* csndGetChnInfo(u32 channel); - -/** - * @brief Gets a capture unit's information. - * Note: Requires previous CSND_UpdateInfo() - * @param capUnit Capture unit to get information for. - * @return The capture unit's information. - */ -CSND_CapInfo* csndGetCapInfo(u32 capUnit); - -/** - * @brief Gets a channel's state. - * @param channel Channel to get the state of. - * @param out Pointer to output channel information to. - */ -Result csndGetState(u32 channel, CSND_ChnInfo* out); - -/** - * @brief Gets whether a channel is playing. - * @param channel Channel to check. - * @param status Pointer to output the channel status to. - */ -Result csndIsPlaying(u32 channel, u8* status); diff --git a/Includes/ctrulib/services/fs.h b/Includes/ctrulib/services/fs.h deleted file mode 100644 index e1061a8..0000000 --- a/Includes/ctrulib/services/fs.h +++ /dev/null @@ -1,1086 +0,0 @@ -/** - * @file fs.h - * @brief Filesystem Services - */ -#pragma once - -#include -#ifdef __cplusplus -extern "C" { -#endif -/// Open flags. -enum -{ - FS_OPEN_READ = BIT(0), ///< Open for reading. - FS_OPEN_WRITE = BIT(1), ///< Open for writing. - FS_OPEN_CREATE = BIT(2), ///< Create file. -}; - -/// Write flags. -enum -{ - FS_WRITE_FLUSH = BIT(0), ///< Flush. - FS_WRITE_UPDATE_TIME = BIT(8), ///< Update file timestamp. -}; - -/// Attribute flags. -enum -{ - FS_ATTRIBUTE_DIRECTORY = BIT(0), ///< Directory. - FS_ATTRIBUTE_HIDDEN = BIT(8), ///< Hidden. - FS_ATTRIBUTE_ARCHIVE = BIT(16), ///< Archive. - FS_ATTRIBUTE_READ_ONLY = BIT(24), ///< Read-only. -}; - -/// Media types. -typedef enum -{ - MEDIATYPE_NAND = 0, ///< NAND. - MEDIATYPE_SD = 1, ///< SD card. - MEDIATYPE_GAME_CARD = 2, ///< Game card. -} FS_MediaType; - -/// System media types. -typedef enum -{ - SYSTEM_MEDIATYPE_CTR_NAND = 0, ///< CTR NAND. - SYSTEM_MEDIATYPE_TWL_NAND = 1, ///< TWL NAND. - SYSTEM_MEDIATYPE_SD = 2, ///< SD card. - SYSTEM_MEDIATYPE_TWL_PHOTO = 3, ///< TWL Photo. -} FS_SystemMediaType; - -/// Archive IDs. -typedef enum -{ - ARCHIVE_ROMFS = 0x00000003, ///< RomFS archive. - ARCHIVE_SAVEDATA = 0x00000004, ///< Save data archive. - ARCHIVE_EXTDATA = 0x00000006, ///< Ext data archive. - ARCHIVE_SHARED_EXTDATA = 0x00000007, ///< Shared ext data archive. - ARCHIVE_SYSTEM_SAVEDATA = 0x00000008, ///< System save data archive. - ARCHIVE_SDMC = 0x00000009, ///< SDMC archive. - ARCHIVE_SDMC_WRITE_ONLY = 0x0000000A, ///< Write-only SDMC archive. - ARCHIVE_BOSS_EXTDATA = 0x12345678, ///< BOSS ext data archive. - ARCHIVE_CARD_SPIFS = 0x12345679, ///< Card SPI FS archive. - ARCHIVE_EXTDATA_AND_BOSS_EXTDATA = 0x1234567B, ///< Ext data and BOSS ext data archive. - ARCHIVE_SYSTEM_SAVEDATA2 = 0x1234567C, ///< System save data archive. - ARCHIVE_NAND_RW = 0x1234567D, ///< Read-write NAND archive. - ARCHIVE_NAND_RO = 0x1234567E, ///< Read-only NAND archive. - ARCHIVE_NAND_RO_WRITE_ACCESS = 0x1234567F, ///< Read-only write access NAND archive. - ARCHIVE_SAVEDATA_AND_CONTENT = 0x2345678A, ///< User save data and ExeFS/RomFS archive. - ARCHIVE_SAVEDATA_AND_CONTENT2 = 0x2345678E, ///< User save data and ExeFS/RomFS archive (only ExeFS for fs:LDR). - ARCHIVE_NAND_CTR_FS = 0x567890AB, ///< NAND CTR FS archive. - ARCHIVE_TWL_PHOTO = 0x567890AC, ///< TWL PHOTO archive. - ARCHIVE_TWL_SOUND = 0x567890AD, ///< TWL SOUND archive. - ARCHIVE_NAND_TWL_FS = 0x567890AE, ///< NAND TWL FS archive. - ARCHIVE_NAND_W_FS = 0x567890AF, ///< NAND W FS archive. - ARCHIVE_GAMECARD_SAVEDATA = 0x567890B1, ///< Game card save data archive. - ARCHIVE_USER_SAVEDATA = 0x567890B2, ///< User save data archive. - ARCHIVE_DEMO_SAVEDATA = 0x567890B4, ///< Demo save data archive. -} FS_ArchiveID; - -/// Path types. -typedef enum -{ - PATH_INVALID = 0, ///< Invalid path. - PATH_EMPTY = 1, ///< Empty path. - PATH_BINARY = 2, ///< Binary path. Meaning is per-archive. - PATH_ASCII = 3, ///< ASCII text path. - PATH_UTF16 = 4, ///< UTF-16 text path. -} FS_PathType; - -/// Secure value slot. -typedef enum -{ - SECUREVALUE_SLOT_SD = 0x1000, ///< SD application. -} FS_SecureValueSlot; - -/// Card SPI baud rate. -typedef enum -{ - BAUDRATE_512KHZ = 0, ///< 512KHz. - BAUDRATE_1MHZ = 1, ///< 1MHz. - BAUDRATE_2MHZ = 2, ///< 2MHz. - BAUDRATE_4MHZ = 3, ///< 4MHz. - BAUDRATE_8MHZ = 4, ///< 8MHz. - BAUDRATE_16MHZ = 5, ///< 16MHz. -} FS_CardSpiBaudRate; - -/// Card SPI bus mode. -typedef enum -{ - BUSMODE_1BIT = 0, ///< 1-bit. - BUSMODE_4BIT = 1, ///< 4-bit. -} FS_CardSpiBusMode; - -/// Card SPI bus mode. -typedef enum -{ - SPECIALCONTENT_UPDATE = 1, ///< Update. - SPECIALCONTENT_MANUAL = 2, ///< Manual. - SPECIALCONTENT_DLP_CHILD = 3, ///< DLP child. -} FS_SpecialContentType; - -typedef enum -{ - CARD_CTR = 0, ///< CTR card. - CARD_TWL = 1, ///< TWL card. -} FS_CardType; - -/// FS control actions. -typedef enum -{ - FS_ACTION_UNKNOWN = 0, -} FS_Action; - -/// Archive control actions. -typedef enum -{ - ARCHIVE_ACTION_COMMIT_SAVE_DATA = 0, ///< Commits save data changes. No inputs/outputs. - ARCHIVE_ACTION_GET_TIMESTAMP = 1, ///< Retrieves a file's last-modified timestamp. In: "u16*, UTF-16 Path", Out: "u64, Time Stamp". -} FS_ArchiveAction; - -/// Secure save control actions. -typedef enum -{ - SECURESAVE_ACTION_DELETE = 0, ///< Deletes a save's secure value. In: "u64, ((SecureValueSlot << 32) | (TitleUniqueId << 8) | TitleVariation)", Out: "u8, Value Existed" - SECURESAVE_ACTION_FORMAT = 1, ///< Formats a save. No inputs/outputs. -} FS_SecureSaveAction; - -/// File control actions. -typedef enum -{ - FILE_ACTION_UNKNOWN = 0, -} FS_FileAction; - -/// Directory control actions. -typedef enum -{ - DIRECTORY_ACTION_UNKNOWN = 0, -} FS_DirectoryAction; - -/// Directory entry. -typedef struct -{ - u16 name[0x106]; ///< UTF-16 directory name. - char shortName[0x0A]; ///< File name. - char shortExt[0x04]; ///< File extension. - u8 valid; ///< Valid flag. (Always 1) - u8 reserved; ///< Reserved. - u32 attributes; ///< Attributes. - u64 fileSize; ///< File size. -} FS_DirectoryEntry; - -/// Archive resource information. -typedef struct -{ - u32 sectorSize; ///< Size of each sector, in bytes. - u32 clusterSize; ///< Size of each cluster, in bytes. - u32 totalClusters; ///< Total number of clusters. - u32 freeClusters; ///< Number of free clusters. -} FS_ArchiveResource; - -/// Program information. -typedef struct -{ - u64 programId; ///< Program ID. - FS_MediaType mediaType : 8; ///< Media type. - u8 padding[7]; ///< Padding. -} FS_ProgramInfo; - -/// Product information. -typedef struct -{ - char productCode[0x10]; ///< Product code. - char companyCode[0x2]; ///< Company code. - u16 remasterVersion; ///< Remaster version. -} FS_ProductInfo; - -/// Integrity verification seed. -typedef struct -{ - u8 aesCbcMac[0x10]; ///< AES-CBC MAC over a SHA256 hash, which hashes the first 0x110-bytes of the cleartext SEED. - u8 movableSed[0x120]; ///< The "nand/private/movable.sed", encrypted with AES-CTR using the above MAC for the counter. -} FS_IntegrityVerificationSeed; - -/// Ext save data information. -typedef struct PACKED -{ - FS_MediaType mediaType : 8; ///< Media type. - u8 unknown; ///< Unknown. - u16 reserved1; ///< Reserved. - u64 saveId; ///< Save ID. - u32 reserved2; ///< Reserved. -} FS_ExtSaveDataInfo; - -/// System save data information. -typedef struct -{ - FS_MediaType mediaType : 8; ///< Media type. - u8 unknown; ///< Unknown. - u16 reserved; ///< Reserved. - u32 saveId; ///< Save ID. -} FS_SystemSaveDataInfo; - -/// Device move context. -typedef struct -{ - u8 ivs[0x10]; ///< IVs. - u8 encryptParameter[0x10]; ///< Encrypt parameter. -} FS_DeviceMoveContext; - -/// Filesystem path data, detailing the specific target of an operation. -typedef struct -{ - FS_PathType type; ///< FS path type. - u32 size; ///< FS path size. - const void* data; ///< Pointer to FS path data. -} FS_Path; - -/// Filesystem archive handle, providing access to a filesystem's contents. -typedef u64 FS_Archive; - -/// Initializes FS. -Result fsInit(void); - -/// Exits FS. -void fsExit(void); - -/** - * @brief Sets the FSUSER session to use in the current thread. - * @param session The handle of the FSUSER session to use. - */ -void fsUseSession(Handle session); - -/// Disables the FSUSER session override in the current thread. -void fsEndUseSession(void); - -/** - * @brief Exempts an archive from using alternate FS session handles provided with @ref fsUseSession - * Instead, the archive will use the default FS session handle, opened with @ref srvGetSessionHandle - * @param archive Archive to exempt. - */ -void fsExemptFromSession(FS_Archive archive); - -/** - * @brief Unexempts an archive from using alternate FS session handles provided with @ref fsUseSession - * @param archive Archive to remove from the exemption list. - */ -void fsUnexemptFromSession(FS_Archive archive); - -/** - * @brief Creates an FS_Path instance. - * @param type Type of path. - * @param path Path to use. - * @return The created FS_Path instance. - */ -FS_Path fsMakePath(FS_PathType type, const void* path); - -/** - * @brief Gets the current FS session handle. - * @return The current FS session handle. - */ -Handle* fsGetSessionHandle(void); - -/** - * @brief Performs a control operation on the filesystem. - * @param action Action to perform. - * @param input Buffer to read input from. - * @param inputSize Size of the input. - * @param output Buffer to write output to. - * @param outputSize Size of the output. - */ -Result FSUSER_Control(FS_Action action, void* input, u32 inputSize, void* output, u32 outputSize); - -/** - * @brief Initializes a FSUSER session. - * @param session The handle of the FSUSER session to initialize. - */ -Result FSUSER_Initialize(Handle session); - -/** - * @brief Opens a file. - * @param out Pointer to output the file handle to. - * @param archive Archive containing the file. - * @param path Path of the file. - * @param openFlags Flags to open the file with. - * @param attributes Attributes of the file. - */ -Result FSUSER_OpenFile(Handle* out, FS_Archive archive, FS_Path path, u32 openFlags, u32 attributes); - -/** - * @brief Opens a file directly, bypassing the requirement of an opened archive handle. - * @param out Pointer to output the file handle to. - * @param archiveId ID of the archive containing the file. - * @param archivePath Path of the archive containing the file. - * @param filePath Path of the file. - * @param openFlags Flags to open the file with. - * @param attributes Attributes of the file. - */ -Result FSUSER_OpenFileDirectly(Handle* out, FS_ArchiveID archiveId, FS_Path archivePath, FS_Path filePath, u32 openFlags, u32 attributes); - -/** - * @brief Deletes a file. - * @param archive Archive containing the file. - * @param path Path of the file. - */ -Result FSUSER_DeleteFile(FS_Archive archive, FS_Path path); - -/** - * @brief Renames a file. - * @param srcArchive Archive containing the source file. - * @param srcPath Path of the source file. - * @param dstArchive Archive containing the destination file. - * @param dstPath Path of the destination file. - */ -Result FSUSER_RenameFile(FS_Archive srcArchive, FS_Path srcPath, FS_Archive dstArchive, FS_Path dstPath); - -/** - * @brief Deletes a directory, failing if it is not empty. - * @param archive Archive containing the directory. - * @param path Path of the directory. - */ -Result FSUSER_DeleteDirectory(FS_Archive archive, FS_Path path); - -/** - * @brief Deletes a directory, also deleting its contents. - * @param archive Archive containing the directory. - * @param path Path of the directory. - */ -Result FSUSER_DeleteDirectoryRecursively(FS_Archive archive, FS_Path path); - -/** - * @brief Creates a file. - * @param archive Archive to create the file in. - * @param path Path of the file. - * @param attributes Attributes of the file. - * @param fileSize Size of the file. - */ -Result FSUSER_CreateFile(FS_Archive archive, FS_Path path, u32 attributes, u64 fileSize); - -/** - * @brief Creates a directory - * @param archive Archive to create the directory in. - * @param path Path of the directory. - * @param attributes Attributes of the directory. - */ -Result FSUSER_CreateDirectory(FS_Archive archive, FS_Path path, u32 attributes); - -/** - * @brief Renames a directory. - * @param srcArchive Archive containing the source directory. - * @param srcPath Path of the source directory. - * @param dstArchive Archive containing the destination directory. - * @param dstPath Path of the destination directory. - */ -Result FSUSER_RenameDirectory(FS_Archive srcArchive, FS_Path srcPath, FS_Archive dstArchive, FS_Path dstPath); - -/** - * @brief Opens a directory. - * @param out Pointer to output the directory handle to. - * @param archive Archive containing the directory. - * @param path Path of the directory. - */ -Result FSUSER_OpenDirectory(Handle *out, FS_Archive archive, FS_Path path); - -/** - * @brief Opens an archive. - * @param archive Pointer to output the opened archive to. - * @param id ID of the archive. - * @param path Path of the archive. - */ -Result FSUSER_OpenArchive(FS_Archive* archive, FS_ArchiveID id, FS_Path path); - -/** - * @brief Performs a control operation on an archive. - * @param archive Archive to control. - * @param action Action to perform. - * @param input Buffer to read input from. - * @param inputSize Size of the input. - * @param output Buffer to write output to. - * @param outputSize Size of the output. - */ -Result FSUSER_ControlArchive(FS_Archive archive, FS_ArchiveAction action, void* input, u32 inputSize, void* output, u32 outputSize); - -/** - * @brief Closes an archive. - * @param archive Archive to close. - */ -Result FSUSER_CloseArchive(FS_Archive archive); - -/** - * @brief Gets the number of free bytes within an archive. - * @param freeBytes Pointer to output the free bytes to. - * @param archive Archive to check. - */ -Result FSUSER_GetFreeBytes(u64* freeBytes, FS_Archive archive); - -/** - * @brief Gets the inserted card type. - * @param type Pointer to output the card type to. - */ -Result FSUSER_GetCardType(FS_CardType* type); - -/** - * @brief Gets the SDMC archive resource information. - * @param archiveResource Pointer to output the archive resource information to. - */ -Result FSUSER_GetSdmcArchiveResource(FS_ArchiveResource* archiveResource); - -/** - * @brief Gets the NAND archive resource information. - * @param archiveResource Pointer to output the archive resource information to. - */ -Result FSUSER_GetNandArchiveResource(FS_ArchiveResource* archiveResource); - -/** - * @brief Gets the last SDMC fatfs error. - * @param error Pointer to output the error to. - */ -Result FSUSER_GetSdmcFatfsError(u32* error); - -/** - * @brief Gets whether an SD card is detected. - * @param detected Pointer to output the detection status to. - */ -Result FSUSER_IsSdmcDetected(bool *detected); - -/** - * @brief Gets whether the SD card is writable. - * @param detected Pointer to output the writable status to. - */ -Result FSUSER_IsSdmcWritable(bool *writable); - -/** - * @brief Gets the SDMC CID. - * @param out Pointer to output the CID to. - * @param length Length of the CID buffer. (should be 0x10) - */ -Result FSUSER_GetSdmcCid(u8* out, u32 length); - -/** - * @brief Gets the NAND CID. - * @param out Pointer to output the CID to. - * @param length Length of the CID buffer. (should be 0x10) - */ -Result FSUSER_GetNandCid(u8* out, u32 length); - -/** - * @brief Gets the SDMC speed info. - * @param speedInfo Pointer to output the speed info to. - */ -Result FSUSER_GetSdmcSpeedInfo(u32 *speedInfo); - -/** - * @brief Gets the NAND speed info. - * @param speedInfo Pointer to output the speed info to. - */ -Result FSUSER_GetNandSpeedInfo(u32 *speedInfo); - -/** - * @brief Gets the SDMC log. - * @param out Pointer to output the log to. - * @param length Length of the log buffer. - */ -Result FSUSER_GetSdmcLog(u8* out, u32 length); - -/** - * @brief Gets the NAND log. - * @param out Pointer to output the log to. - * @param length Length of the log buffer. - */ -Result FSUSER_GetNandLog(u8* out, u32 length); - -/// Clears the SDMC log. -Result FSUSER_ClearSdmcLog(void); - -/// Clears the NAND log. -Result FSUSER_ClearNandLog(void); - -/** - * @brief Gets whether a card is inserted. - * @param inserted Pointer to output the insertion status to. - */ -Result FSUSER_CardSlotIsInserted(bool* inserted); - -/** - * @brief Powers on the card slot. - * @param status Pointer to output the power status to. - */ -Result FSUSER_CardSlotPowerOn(bool* status); - -/** - * @brief Powers off the card slot. - * @param status Pointer to output the power status to. - */ -Result FSUSER_CardSlotPowerOff(bool* status); - -/** - * @brief Gets the card's power status. - * @param status Pointer to output the power status to. - */ -Result FSUSER_CardSlotGetCardIFPowerStatus(bool* status); - -/** - * @brief Executes a CARDNOR direct command. - * @param commandId ID of the command. - */ -Result FSUSER_CardNorDirectCommand(u8 commandId); - -/** - * @brief Executes a CARDNOR direct command with an address. - * @param commandId ID of the command. - * @param address Address to provide. - */ -Result FSUSER_CardNorDirectCommandWithAddress(u8 commandId, u32 address); - -/** - * @brief Executes a CARDNOR direct read. - * @param commandId ID of the command. - * @param size Size of the output buffer. - * @param output Output buffer. - */ -Result FSUSER_CardNorDirectRead(u8 commandId, u32 size, u8* output); - -/** - * @brief Executes a CARDNOR direct read with an address. - * @param commandId ID of the command. - * @param address Address to provide. - * @param size Size of the output buffer. - * @param output Output buffer. - */ -Result FSUSER_CardNorDirectReadWithAddress(u8 commandId, u32 address, u32 size, u8* output); - -/** - * @brief Executes a CARDNOR direct write. - * @param commandId ID of the command. - * @param size Size of the input buffer. - * @param output Input buffer. - */ -Result FSUSER_CardNorDirectWrite(u8 commandId, u32 size, u8* input); - -/** - * @brief Executes a CARDNOR direct write with an address. - * @param commandId ID of the command. - * @param address Address to provide. - * @param size Size of the input buffer. - * @param input Input buffer. - */ -Result FSUSER_CardNorDirectWriteWithAddress(u8 commandId, u32 address, u32 size, u8* input); - -/** - * @brief Executes a CARDNOR 4xIO direct read. - * @param commandId ID of the command. - * @param address Address to provide. - * @param size Size of the output buffer. - * @param output Output buffer. - */ -Result FSUSER_CardNorDirectRead_4xIO(u8 commandId, u32 address, u32 size, u8* output); - -/** - * @brief Executes a CARDNOR direct CPU write without verify. - * @param address Address to provide. - * @param size Size of the input buffer. - * @param output Input buffer. - */ -Result FSUSER_CardNorDirectCpuWriteWithoutVerify(u32 address, u32 size, u8* input); - -/** - * @brief Executes a CARDNOR direct sector erase without verify. - * @param address Address to provide. - */ -Result FSUSER_CardNorDirectSectorEraseWithoutVerify(u32 address); - -/** - * @brief Gets a process's product info. - * @param info Pointer to output the product info to. - * @param processId ID of the process. - */ -Result FSUSER_GetProductInfo(FS_ProductInfo* info, u32 processId); - -/** - * @brief Gets a process's program launch info. - * @param info Pointer to output the program launch info to. - * @param processId ID of the process. - */ -Result FSUSER_GetProgramLaunchInfo(FS_ProgramInfo* info, u32 processId); - -/** - * @brief Sets the CARDSPI baud rate. - * @param baudRate Baud rate to set. - */ -Result FSUSER_SetCardSpiBaudRate(FS_CardSpiBaudRate baudRate); - -/** - * @brief Sets the CARDSPI bus mode. - * @param baudRate Bus mode to set. - */ -Result FSUSER_SetCardSpiBusMode(FS_CardSpiBusMode busMode); - -/// Sends initialization info to ARM9. -Result FSUSER_SendInitializeInfoTo9(void); - -/** - * @brief Gets a special content's index. - * @param index Pointer to output the index to. - * @param mediaType Media type of the special content. - * @param programId Program ID owning the special content. - * @param type Type of special content. - */ -Result FSUSER_GetSpecialContentIndex(u16* index, FS_MediaType mediaType, u64 programId, FS_SpecialContentType type); - -/** - * @brief Gets the legacy ROM header of a program. - * @param mediaType Media type of the program. - * @param programId ID of the program. - * @param header Pointer to output the legacy ROM header to. (size = 0x3B4) - */ -Result FSUSER_GetLegacyRomHeader(FS_MediaType mediaType, u64 programId, u8* header); - -/** - * @brief Gets the legacy banner data of a program. - * @param mediaType Media type of the program. - * @param programId ID of the program. - * @param header Pointer to output the legacy banner data to. (size = 0x23C0) - */ -Result FSUSER_GetLegacyBannerData(FS_MediaType mediaType, u64 programId, u8* banner); - -/** - * @brief Checks a process's authority to access a save data archive. - * @param access Pointer to output the access status to. - * @param mediaType Media type of the save data. - * @param saveId ID of the save data. - * @param processId ID of the process to check. - */ -Result FSUSER_CheckAuthorityToAccessExtSaveData(bool* access, FS_MediaType mediaType, u64 saveId, u32 processId); - -/** - * @brief Queries the total quota size of a save data archive. - * @param quotaSize Pointer to output the quota size to. - * @param directories Number of directories. - * @param files Number of files. - * @param fileSizeCount Number of file sizes to provide. - * @param fileSizes File sizes to provide. - */ -Result FSUSER_QueryTotalQuotaSize(u64* quotaSize, u32 directories, u32 files, u32 fileSizeCount, u64* fileSizes); - -/** - * @brief Abnegates an access right. - * @param accessRight Access right to abnegate. - */ -Result FSUSER_AbnegateAccessRight(u32 accessRight); - -/// Deletes the 3DS SDMC root. -Result FSUSER_DeleteSdmcRoot(void); - -/// Deletes all ext save data on the NAND. -Result FSUSER_DeleteAllExtSaveDataOnNand(void); - -/// Initializes the CTR file system. -Result FSUSER_InitializeCtrFileSystem(void); - -/// Creates the FS seed. -Result FSUSER_CreateSeed(void); - -/** - * @brief Retrieves archive format info. - * @param totalSize Pointer to output the total size to. - * @param directories Pointer to output the number of directories to. - * @param files Pointer to output the number of files to. - * @param duplicateData Pointer to output whether to duplicate data to. - * @param archiveId ID of the archive. - * @param path Path of the archive. - */ -Result FSUSER_GetFormatInfo(u32* totalSize, u32* directories, u32* files, bool* duplicateData, FS_ArchiveID archiveId, FS_Path path); - -/** - * @brief Gets the legacy ROM header of a program. - * @param headerSize Size of the ROM header. - * @param mediaType Media type of the program. - * @param programId ID of the program. - * @param header Pointer to output the legacy ROM header to. - */ -Result FSUSER_GetLegacyRomHeader2(u32 headerSize, FS_MediaType mediaType, u64 programId, u8* header); - -/** - * @brief Gets the CTR SDMC root path. - * @param out Pointer to output the root path to. - * @param length Length of the output buffer. - */ -Result FSUSER_GetSdmcCtrRootPath(u8* out, u32 length); - -/** - * @brief Gets an archive's resource information. - * @param archiveResource Pointer to output the archive resource information to. - * @param mediaType System media type to check. - */ -Result FSUSER_GetArchiveResource(FS_ArchiveResource* archiveResource, FS_SystemMediaType mediaType); - -/** - * @brief Exports the integrity verification seed. - * @param seed Pointer to output the seed to. - */ -Result FSUSER_ExportIntegrityVerificationSeed(FS_IntegrityVerificationSeed* seed); - -/** - * @brief Imports an integrity verification seed. - * @param seed Seed to import. - */ -Result FSUSER_ImportIntegrityVerificationSeed(FS_IntegrityVerificationSeed* seed); - -/** - * @brief Formats save data. - * @param archiveId ID of the save data archive. - * @param path Path of the save data. - * @param blocks Size of the save data in blocks. (512 bytes) - * @param directories Number of directories. - * @param files Number of files. - * @param directoryBuckets Directory hash tree bucket count. - * @param fileBuckets File hash tree bucket count. - * @param duplicateData Whether to store an internal duplicate of the data. - */ -Result FSUSER_FormatSaveData(FS_ArchiveID archiveId, FS_Path path, u32 blocks, u32 directories, u32 files, u32 directoryBuckets, u32 fileBuckets, bool duplicateData); - -/** - * @brief Gets the legacy sub banner data of a program. - * @param bannerSize Size of the banner. - * @param mediaType Media type of the program. - * @param programId ID of the program. - * @param header Pointer to output the legacy sub banner data to. - */ -Result FSUSER_GetLegacySubBannerData(u32 bannerSize, FS_MediaType mediaType, u64 programId, u8* banner); - -/** - * @brief Hashes the given data and outputs a SHA256 hash. - * @param data Pointer to the data to be hashed. - * @param inputSize The size of the data. - * @param hash Hash output pointer. - */ -Result FSUSER_UpdateSha256Context(const void* data, u32 inputSize, u8* hash); - -/** - * @brief Reads from a special file. - * @param bytesRead Pointer to output the number of bytes read to. - * @param fileOffset Offset of the file. - * @param size Size of the buffer. - * @param data Buffer to read to. - */ -Result FSUSER_ReadSpecialFile(u32* bytesRead, u64 fileOffset, u32 size, u8* data); - -/** - * @brief Gets the size of a special file. - * @param fileSize Pointer to output the size to. - */ -Result FSUSER_GetSpecialFileSize(u64* fileSize); - -/** - * @brief Creates ext save data. - * @param info Info of the save data. - * @param directories Number of directories. - * @param files Number of files. - * @param sizeLimit Size limit of the save data. - * @param smdhSize Size of the save data's SMDH data. - * @param smdh SMDH data. - */ -Result FSUSER_CreateExtSaveData(FS_ExtSaveDataInfo info, u32 directories, u32 files, u64 sizeLimit, u32 smdhSize, u8* smdh); - -/** - * @brief Deletes ext save data. - * @param info Info of the save data. - */ -Result FSUSER_DeleteExtSaveData(FS_ExtSaveDataInfo info); - -/** - * @brief Reads the SMDH icon of ext save data. - * @param bytesRead Pointer to output the number of bytes read to. - * @param info Info of the save data. - * @param smdhSize Size of the save data SMDH. - * @param smdh Pointer to output SMDH data to. - */ -Result FSUSER_ReadExtSaveDataIcon(u32* bytesRead, FS_ExtSaveDataInfo info, u32 smdhSize, u8* smdh); - -/** - * @brief Gets an ext data archive's block information. - * @param totalBlocks Pointer to output the total blocks to. - * @param freeBlocks Pointer to output the free blocks to. - * @param blockSize Pointer to output the block size to. - * @param info Info of the save data. - */ -Result FSUSER_GetExtDataBlockSize(u64* totalBlocks, u64* freeBlocks, u32* blockSize, FS_ExtSaveDataInfo info); - -/** - * @brief Enumerates ext save data. - * @param idsWritten Pointer to output the number of IDs written to. - * @param idsSize Size of the IDs buffer. - * @param mediaType Media type to enumerate over. - * @param idSize Size of each ID element. - * @param shared Whether to enumerate shared ext save data. - * @param ids Pointer to output IDs to. - */ -Result FSUSER_EnumerateExtSaveData(u32* idsWritten, u32 idsSize, FS_MediaType mediaType, u32 idSize, bool shared, u8* ids); - -/** - * @brief Creates system save data. - * @param info Info of the save data. - * @param totalSize Total size of the save data. - * @param blockSize Block size of the save data. (usually 0x1000) - * @param directories Number of directories. - * @param files Number of files. - * @param directoryBuckets Directory hash tree bucket count. - * @param fileBuckets File hash tree bucket count. - * @param duplicateData Whether to store an internal duplicate of the data. - */ -Result FSUSER_CreateSystemSaveData(FS_SystemSaveDataInfo info, u32 totalSize, u32 blockSize, u32 directories, u32 files, u32 directoryBuckets, u32 fileBuckets, bool duplicateData); - -/** - * @brief Deletes system save data. - * @param info Info of the save data. - */ -Result FSUSER_DeleteSystemSaveData(FS_SystemSaveDataInfo info); - -/** - * @brief Initiates a device move as the source device. - * @param context Pointer to output the context to. - */ -Result FSUSER_StartDeviceMoveAsSource(FS_DeviceMoveContext* context); - -/** - * @brief Initiates a device move as the destination device. - * @param context Context to use. - * @param clear Whether to clear the device's data first. - */ -Result FSUSER_StartDeviceMoveAsDestination(FS_DeviceMoveContext context, bool clear); - -/** - * @brief Sets an archive's priority. - * @param archive Archive to use. - * @param priority Priority to set. - */ -Result FSUSER_SetArchivePriority(FS_Archive archive, u32 priority); - -/** - * @brief Gets an archive's priority. - * @param priority Pointer to output the priority to. - * @param archive Archive to use. - */ -Result FSUSER_GetArchivePriority(u32* priority, FS_Archive archive); - -/** - * @brief Configures CTRCARD latency emulation. - * @param latency Latency to apply, in milliseconds. - * @param emulateEndurance Whether to emulate card endurance. - */ -Result FSUSER_SetCtrCardLatencyParameter(u64 latency, bool emulateEndurance); - -/** - * @brief Toggles cleaning up invalid save data. - * @param Whether to enable cleaning up invalid save data. - */ -Result FSUSER_SwitchCleanupInvalidSaveData(bool enable); - -/** - * @brief Enumerates system save data. - * @param idsWritten Pointer to output the number of IDs written to. - * @param idsSize Size of the IDs buffer. - * @param ids Pointer to output IDs to. - */ -Result FSUSER_EnumerateSystemSaveData(u32* idsWritten, u32 idsSize, u32* ids); - -/** - * @brief Initializes a FSUSER session with an SDK version. - * @param session The handle of the FSUSER session to initialize. - * @param version SDK version to initialize with. - */ -Result FSUSER_InitializeWithSdkVersion(Handle session, u32 version); - -/** - * @brief Sets the file system priority. - * @param priority Priority to set. - */ -Result FSUSER_SetPriority(u32 priority); - -/** - * @brief Gets the file system priority. - * @param priority Pointer to output the priority to. - */ -Result FSUSER_GetPriority(u32* priority); - -/** - * @brief Sets the save data secure value. - * @param value Secure value to set. - * @param slot Slot of the secure value. - * @param titleUniqueId Unique ID of the title. (default = 0) - * @param titleVariation Variation of the title. (default = 0) - */ -Result FSUSER_SetSaveDataSecureValue(u64 value, FS_SecureValueSlot slot, u32 titleUniqueId, u8 titleVariation); - -/** - * @brief Gets the save data secure value. - * @param exists Pointer to output whether the secure value exists to. - * @param value Pointer to output the secure value to. - * @param slot Slot of the secure value. - * @param titleUniqueId Unique ID of the title. (default = 0) - * @param titleVariation Variation of the title. (default = 0) - */ -Result FSUSER_GetSaveDataSecureValue(bool* exists, u64* value, FS_SecureValueSlot slot, u32 titleUniqueId, u8 titleVariation); - -/** - * @brief Performs a control operation on a secure save. - * @param action Action to perform. - * @param input Buffer to read input from. - * @param inputSize Size of the input. - * @param output Buffer to write output to. - * @param outputSize Size of the output. - */ -Result FSUSER_ControlSecureSave(FS_SecureSaveAction action, void* input, u32 inputSize, void* output, u32 outputSize); - -/** - * @brief Gets the media type of the current application. - * @param mediaType Pointer to output the media type to. - */ -Result FSUSER_GetMediaType(FS_MediaType* mediaType); - -/** - * @brief Performs a control operation on a file. - * @param handle Handle of the file. - * @param action Action to perform. - * @param input Buffer to read input from. - * @param inputSize Size of the input. - * @param output Buffer to write output to. - * @param outputSize Size of the output. - */ -Result FSFILE_Control(Handle handle, FS_FileAction action, void* input, u32 inputSize, void* output, u32 outputSize); - -/** - * @brief Opens a handle to a sub-section of a file. - * @param handle Handle of the file. - * @param subFile Pointer to output the sub-file to. - * @param offset Offset of the sub-section. - * @param size Size of the sub-section. - */ -Result FSFILE_OpenSubFile(Handle handle, Handle* subFile, u64 offset, u64 size); - -/** - * @brief Reads from a file. - * @param handle Handle of the file. - * @param bytesRead Pointer to output the number of bytes read to. - * @param offset Offset to read from. - * @param buffer Buffer to read to. - * @param size Size of the buffer. - */ -Result FSFILE_Read(Handle handle, u32* bytesRead, u64 offset, void* buffer, u32 size); - -/** - * @brief Writes to a file. - * @param handle Handle of the file. - * @param bytesWritten Pointer to output the number of bytes written to. - * @param offset Offset to write to. - * @param buffer Buffer to write from. - * @param size Size of the buffer. - * @param flags Flags to use when writing. - */ -Result FSFILE_Write(Handle handle, u32* bytesWritten, u64 offset, const void* buffer, u32 size, u32 flags); - -/** - * @brief Gets the size of a file. - * @param handle Handle of the file. - * @param size Pointer to output the size to. - */ -Result FSFILE_GetSize(Handle handle, u64* size); - -/** - * @brief Sets the size of a file. - * @param handle Handle of the file. - * @param size Size to set. - */ -Result FSFILE_SetSize(Handle handle, u64 size); - -/** - * @brief Gets the attributes of a file. - * @param handle Handle of the file. - * @param attributes Pointer to output the attributes to. - */ -Result FSFILE_GetAttributes(Handle handle, u32* attributes); - -/** - * @brief Sets the attributes of a file. - * @param handle Handle of the file. - * @param attributes Attributes to set. - */ -Result FSFILE_SetAttributes(Handle handle, u32 attributes); - -/** - * @brief Closes a file. - * @param handle Handle of the file. - */ -Result FSFILE_Close(Handle handle); - -/** - * @brief Flushes a file's contents. - * @param handle Handle of the file. - */ -Result FSFILE_Flush(Handle handle); - -/** - * @brief Sets a file's priority. - * @param handle Handle of the file. - * @param priority Priority to set. - */ -Result FSFILE_SetPriority(Handle handle, u32 priority); - -/** - * @brief Gets a file's priority. - * @param handle Handle of the file. - * @param priority Pointer to output the priority to. - */ -Result FSFILE_GetPriority(Handle handle, u32* priority); - -/** - * @brief Opens a duplicate handle to a file. - * @param handle Handle of the file. - * @param linkFile Pointer to output the link handle to. - */ -Result FSFILE_OpenLinkFile(Handle handle, Handle* linkFile); - -/** - * @brief Performs a control operation on a directory. - * @param handle Handle of the directory. - * @param action Action to perform. - * @param input Buffer to read input from. - * @param inputSize Size of the input. - * @param output Buffer to write output to. - * @param outputSize Size of the output. - */ -Result FSDIR_Control(Handle handle, FS_DirectoryAction action, void* input, u32 inputSize, void* output, u32 outputSize); - -/** - * @brief Reads one or more directory entries. - * @param handle Handle of the directory. - * @param entriesRead Pointer to output the number of entries read to. - * @param entryCount Number of entries to read. - * @param entryOut Pointer to output directory entries to. - */ -Result FSDIR_Read(Handle handle, u32* entriesRead, u32 entryCount, FS_DirectoryEntry* entries); - -/** - * @brief Closes a directory. - * @param handle Handle of the directory. - */ -Result FSDIR_Close(Handle handle); - -/** - * @brief Sets a directory's priority. - * @param handle Handle of the directory. - * @param priority Priority to set. - */ -Result FSDIR_SetPriority(Handle handle, u32 priority); - -/** - * @brief Gets a directory's priority. - * @param handle Handle of the directory. - * @param priority Pointer to output the priority to. - */ -Result FSDIR_GetPriority(Handle handle, u32* priority); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/Includes/ctrulib/services/gspgpu.h b/Includes/ctrulib/services/gspgpu.h deleted file mode 100644 index ce1b377..0000000 --- a/Includes/ctrulib/services/gspgpu.h +++ /dev/null @@ -1,226 +0,0 @@ -/** - * @file gspgpu.h - * @brief GSPGPU service. - */ -#pragma once -#ifdef __cplusplus -extern "C" { -#endif - -#define GSPGPU_REBASE_REG(r) ((r)-0x1EB00000) - -/// Framebuffer information. -typedef struct -{ - u32 active_framebuf; ///< Active framebuffer. (0 = first, 1 = second) - u32 *framebuf0_vaddr; ///< Framebuffer virtual address, for the main screen this is the 3D left framebuffer. - u32 *framebuf1_vaddr; ///< For the main screen: 3D right framebuffer address. - u32 framebuf_widthbytesize; ///< Value for 0x1EF00X90, controls framebuffer width. - u32 format; ///< Framebuffer format, this u16 is written to the low u16 for LCD register 0x1EF00X70. - u32 framebuf_dispselect; ///< Value for 0x1EF00X78, controls which framebuffer is displayed. - u32 unk; ///< Unknown. -} GSPGPU_FramebufferInfo; - -/// Framebuffer format. -typedef enum -{ - GSP_RGBA8_OES=0, ///< RGBA8. (4 bytes) - GSP_BGR8_OES=1, ///< BGR8. (3 bytes) - GSP_RGB565_OES=2, ///< RGB565. (2 bytes) - GSP_RGB5_A1_OES=3, ///< RGB5A1. (2 bytes) - GSP_RGBA4_OES=4 ///< RGBA4. (2 bytes) -} GSPGPU_FramebufferFormats; - -/// Capture info entry. -typedef struct -{ - u32 *framebuf0_vaddr; ///< Left framebuffer. - u32 *framebuf1_vaddr; ///< Right framebuffer. - u32 format; ///< Framebuffer format. - u32 framebuf_widthbytesize; ///< Framebuffer pitch. -} GSPGPU_CaptureInfoEntry; - -/// Capture info. -typedef struct -{ - GSPGPU_CaptureInfoEntry screencapture[2]; ///< Capture info entries, one for each screen. -} GSPGPU_CaptureInfo; - -/// GSPGPU events. -typedef enum -{ - GSPGPU_EVENT_PSC0 = 0, ///< Memory fill completed. - GSPGPU_EVENT_PSC1, ///< TODO - GSPGPU_EVENT_VBlank0, ///< TODO - GSPGPU_EVENT_VBlank1, ///< TODO - GSPGPU_EVENT_PPF, ///< Display transfer finished. - GSPGPU_EVENT_P3D, ///< Command list processing finished. - GSPGPU_EVENT_DMA, ///< TODO - - GSPGPU_EVENT_MAX, ///< Used to know how many events there are. -} GSPGPU_Event; - -/// Initializes GSPGPU. -Result gspInit(void); - -/// Exits GSPGPU. -void gspExit(void); - -/** - * @brief Configures a callback to run when a GSPGPU event occurs. - * @param id ID of the event. - * @param cb Callback to run. - * @param data Data to be passed to the callback. - * @param oneShot When true, the callback is only executed once. When false, the callback is executed every time the event occurs. - */ -void gspSetEventCallback(GSPGPU_Event id, ThreadFunc cb, void* data, bool oneShot); - -/** - * @brief Initializes the GSPGPU event handler. - * @param gspEvent Event handle to use. - * @param gspSharedMem GSP shared memory. - * @param gspThreadId ID of the GSP thread. - */ -Result gspInitEventHandler(Handle gspEvent, vu8* gspSharedMem, u8 gspThreadId); - -/// Exits the GSPGPU event handler. -void gspExitEventHandler(void); - -/** - * @brief Waits for a GSPGPU event to occur. - * @param id ID of the event. - * @param nextEvent Whether to discard the current event and wait for the next event. - */ -void gspWaitForEvent(GSPGPU_Event id, bool nextEvent); - -/** - * @brief Waits for any GSPGPU event to occur. - * @return The ID of the event that occurred. - * - * The function returns immediately if there are unprocessed events at the time of call. - */ -GSPGPU_Event gspWaitForAnyEvent(void); - -/// Waits for PSC0 -#define gspWaitForPSC0() gspWaitForEvent(GSPGPU_EVENT_PSC0, false) - -/// Waits for PSC1 -#define gspWaitForPSC1() gspWaitForEvent(GSPGPU_EVENT_PSC1, false) - -/// Waits for VBlank. -#define gspWaitForVBlank() gspWaitForVBlank0() - -/// Waits for VBlank0. -#define gspWaitForVBlank0() gspWaitForEvent(GSPGPU_EVENT_VBlank0, true) - -/// Waits for VBlank1. -#define gspWaitForVBlank1() gspWaitForEvent(GSPGPU_EVENT_VBlank1, true) - -/// Waits for PPF. -#define gspWaitForPPF() gspWaitForEvent(GSPGPU_EVENT_PPF, false) - -/// Waits for P3D. -#define gspWaitForP3D() gspWaitForEvent(GSPGPU_EVENT_P3D, false) - -/// Waits for DMA. -#define gspWaitForDMA() gspWaitForEvent(GSPGPU_EVENT_DMA, false) - -/** - * @brief Submits a GX command. - * @param sharedGspCmdBuf Command buffer to use. - * @param gxCommand GX command to execute. - */ -Result gspSubmitGxCommand(u32* sharedGspCmdBuf, u32 gxCommand[0x8]); - -/** - * @brief Acquires GPU rights. - * @param flags Flags to acquire with. - */ -Result GSPGPU_AcquireRight(u8 flags); - -/// Releases GPU rights. -Result GSPGPU_ReleaseRight(void); - -/** - * @brief Retrieves display capture info. - * @param captureinfo Pointer to output capture info to. - */ -Result GSPGPU_ImportDisplayCaptureInfo(GSPGPU_CaptureInfo*captureinfo); - -/// Sames the VRAM sys area. -Result GSPGPU_SaveVramSysArea(void); - -/// Restores the VRAM sys area. -Result GSPGPU_RestoreVramSysArea(void); - -/** - * @brief Sets whether to force the LCD to black. - * @param flags Whether to force the LCD to black. (0 = no, non-zero = yes) - */ -Result GSPGPU_SetLcdForceBlack(u8 flags); - -/** - * @brief Updates a screen's framebuffer state. - * @param screenid ID of the screen to update. - * @param framebufinfo Framebuffer information to update with. - */ -Result GSPGPU_SetBufferSwap(u32 screenid, GSPGPU_FramebufferInfo*framebufinfo); - -/** - * @brief Flushes memory from the data cache. - * @param adr Address to flush. - * @param size Size of the memory to flush. - */ -Result GSPGPU_FlushDataCache(const void* adr, u32 size); - -/** - * @brief Invalidates memory in the data cache. - * @param adr Address to invalidate. - * @param size Size of the memory to invalidate. - */ -Result GSPGPU_InvalidateDataCache(const void* adr, u32 size); - -/** - * @brief Writes to GPU hardware registers. - * @param regAddr Register address to write to. - * @param data Data to write. - * @param size Size of the data to write. - */ -Result GSPGPU_WriteHWRegs(u32 regAddr, u32* data, u8 size); - -/** - * @brief Writes to GPU hardware registers with a mask. - * @param regAddr Register address to write to. - * @param data Data to write. - * @param datasize Size of the data to write. - * @param maskdata Data of the mask. - * @param masksize Size of the mask. - */ -Result GSPGPU_WriteHWRegsWithMask(u32 regAddr, u32* data, u8 datasize, u32* maskdata, u8 masksize); - -/** - * @brief Reads from GPU hardware registers. - * @param regAddr Register address to read from. - * @param data Buffer to read data to. - * @param size Size of the buffer. - */ -Result GSPGPU_ReadHWRegs(u32 regAddr, u32* data, u8 size); - -/** - * @brief Registers the interrupt relay queue. - * @param eventHandle Handle of the GX command event. - * @param flags Flags to register with. - * @param outMemHandle Pointer to output the shared memory handle to. - * @param threadID Pointer to output the GSP thread ID to. - */ -Result GSPGPU_RegisterInterruptRelayQueue(Handle eventHandle, u32 flags, Handle* outMemHandle, u8* threadID); - -/// Unregisters the interrupt relay queue. -Result GSPGPU_UnregisterInterruptRelayQueue(void); - -/// Triggers a handling of commands written to shared memory. -Result GSPGPU_TriggerCmdReqQueue(void); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/Includes/ctrulib/services/hid.h b/Includes/ctrulib/services/hid.h deleted file mode 100644 index 02b50fe..0000000 --- a/Includes/ctrulib/services/hid.h +++ /dev/null @@ -1,189 +0,0 @@ -/** - * @file hid.h - * @brief HID service. - */ -#pragma once -#ifdef __cplusplus -extern "C" { -#endif - -//See also: http://3dbrew.org/wiki/HID_Services http://3dbrew.org/wiki/HID_Shared_Memory - -/// Key values. -enum -{ - KEY_A = BIT(0), ///< A - KEY_B = BIT(1), ///< B - KEY_SELECT = BIT(2), ///< Select - KEY_START = BIT(3), ///< Start - KEY_DRIGHT = BIT(4), ///< D-Pad Right - KEY_DLEFT = BIT(5), ///< D-Pad Left - KEY_DUP = BIT(6), ///< D-Pad Up - KEY_DDOWN = BIT(7), ///< D-Pad Down - KEY_R = BIT(8), ///< R - KEY_L = BIT(9), ///< L - KEY_X = BIT(10), ///< X - KEY_Y = BIT(11), ///< Y - KEY_ZL = BIT(14), ///< ZL (New 3DS only) - KEY_ZR = BIT(15), ///< ZR (New 3DS only) - KEY_TOUCH = BIT(20), ///< Touch (Not actually provided by HID) - KEY_CSTICK_RIGHT = BIT(24), ///< C-Stick Right (New 3DS only) - KEY_CSTICK_LEFT = BIT(25), ///< C-Stick Left (New 3DS only) - KEY_CSTICK_UP = BIT(26), ///< C-Stick Up (New 3DS only) - KEY_CSTICK_DOWN = BIT(27), ///< C-Stick Down (New 3DS only) - KEY_CPAD_RIGHT = BIT(28), ///< Circle Pad Right - KEY_CPAD_LEFT = BIT(29), ///< Circle Pad Left - KEY_CPAD_UP = BIT(30), ///< Circle Pad Up - KEY_CPAD_DOWN = BIT(31), ///< Circle Pad Down - - // Generic catch-all directions - KEY_UP = KEY_DUP | KEY_CPAD_UP, ///< D-Pad Up or Circle Pad Up - KEY_DOWN = KEY_DDOWN | KEY_CPAD_DOWN, ///< D-Pad Down or Circle Pad Down - KEY_LEFT = KEY_DLEFT | KEY_CPAD_LEFT, ///< D-Pad Left or Circle Pad Left - KEY_RIGHT = KEY_DRIGHT | KEY_CPAD_RIGHT, ///< D-Pad Right or Circle Pad Right -}; - -/// Touch position. -typedef struct -{ - u16 px; ///< Touch X - u16 py; ///< Touch Y -} touchPosition; - -/// Circle Pad position. -typedef struct -{ - s16 dx; ///< Pad X - s16 dy; ///< Pad Y -} circlePosition; - -/// Accelerometer vector. -typedef struct -{ - s16 x; ///< Accelerometer X - s16 y; ///< Accelerometer Y - s16 z; ///< Accelerometer Z -} accelVector; - -/// Gyroscope angular rate. -typedef struct -{ - s16 x; ///< Roll - s16 z; ///< Yaw - s16 y; ///< Pitch -} angularRate; - -/// HID events. -typedef enum -{ - HIDEVENT_PAD0 = 0, ///< Event signaled by HID-module, when the sharedmem+0(PAD/circle-pad)/+0xA8(touch-screen) region was updated. - HIDEVENT_PAD1, ///< Event signaled by HID-module, when the sharedmem+0(PAD/circle-pad)/+0xA8(touch-screen) region was updated. - HIDEVENT_Accel, ///< Event signaled by HID-module, when the sharedmem accelerometer state was updated. - HIDEVENT_Gyro, ///< Event signaled by HID-module, when the sharedmem gyroscope state was updated. - HIDEVENT_DebugPad, ///< Event signaled by HID-module, when the sharedmem DebugPad state was updated. - - HIDEVENT_MAX, ///< Used to know how many events there are. -} HID_Event; - -extern Handle hidMemHandle; ///< HID shared memory handle. -extern vu32* hidSharedMem; ///< HID shared memory. - -/// Initializes HID. -Result hidInit(void); - -/// Exits HID. -void hidExit(void); - -/// Scans HID for input data. -void hidScanInput(void); - -/** - * @brief Returns a bitmask of held buttons. - * Individual buttons can be extracted using binary AND. - * @return 32-bit bitmask of held buttons (1+ frames). - */ -u32 hidKeysHeld(void); - -/** - * @brief Returns a bitmask of newly pressed buttons, this frame. - * Individual buttons can be extracted using binary AND. - * @return 32-bit bitmask of newly pressed buttons. - */ -u32 hidKeysDown(void); - -/** -* @brief Returns a bitmask of newly released buttons, this frame. - * Individual buttons can be extracted using binary AND. - * @return 32-bit bitmask of newly released buttons. - */ -u32 hidKeysUp(void); - -/** - * @brief Reads the current touch position. - * @param pos Pointer to output the touch position to. - */ -void hidTouchRead(touchPosition* pos); - -/** - * @brief Reads the current circle pad position. - * @param pos Pointer to output the circle pad position to. - */ -void hidCircleRead(circlePosition* pos); - -/** - * @brief Reads the current accelerometer data. - * @param vector Pointer to output the accelerometer data to. - */ -void hidAccelRead(accelVector* vector); - -/** - * @brief Reads the current gyroscope data. - * @param rate Pointer to output the gyroscope data to. - */ -void hidGyroRead(angularRate* rate); - -/** - * @brief Waits for an HID event. - * @param id ID of the event. - * @param nextEvent Whether to discard the current event and wait for the next event. - */ -void hidWaitForEvent(HID_Event id, bool nextEvent); - - -/** - * @brief Gets the handles for HID operation. - * @param outMemHandle Pointer to output the shared memory handle to. - * @param eventpad0 Pointer to output the pad 0 event handle to. - * @param eventpad1 Pointer to output the pad 1 event handle to. - * @param eventaccel Pointer to output the accelerometer event handle to. - * @param eventgyro Pointer to output the gyroscope event handle to. - * @param eventdebugpad Pointer to output the debug pad event handle to. - */ -Result HIDUSER_GetHandles(Handle* outMemHandle, Handle *eventpad0, Handle *eventpad1, Handle *eventaccel, Handle *eventgyro, Handle *eventdebugpad); - -/// Enables the accelerometer. -Result HIDUSER_EnableAccelerometer(void); - -/// Disables the accelerometer. -Result HIDUSER_DisableAccelerometer(void); - -/// Enables the gyroscope. -Result HIDUSER_EnableGyroscope(void); - -/// Disables the gyroscope. -Result HIDUSER_DisableGyroscope(void); - -/** - * @brief Gets the gyroscope raw to dps coefficient. - * @param coeff Pointer to output the coefficient to. - */ -Result HIDUSER_GetGyroscopeRawToDpsCoefficient(float *coeff); - -/** - * @brief Gets the current volume slider value. (0-63) - * @param volume Pointer to write the volume slider value to. - */ -Result HIDUSER_GetSoundVolume(u8 *volume); -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/Includes/ctrulib/services/irrst.h b/Includes/ctrulib/services/irrst.h deleted file mode 100644 index a666b43..0000000 --- a/Includes/ctrulib/services/irrst.h +++ /dev/null @@ -1,62 +0,0 @@ -/** - * @file irrst.h - * @brief IRRST service. - */ -#pragma once - -//See also: http://3dbrew.org/wiki/IR_Services http://3dbrew.org/wiki/IRRST_Shared_Memory - -#include "ctrulib/services/hid.h" // for circlePosition definition - -/// IRRST's shared memory handle. -extern Handle irrstMemHandle; - -/// IRRST's shared memory. -extern vu32* irrstSharedMem; - -/// Initializes IRRST. -Result irrstInit(void); - -/// Exits IRRST. -void irrstExit(void); - -/// Scans IRRST for input. -void irrstScanInput(void); - -/** - * @brief Gets IRRST's held keys. - * @return IRRST's held keys. - */ -u32 irrstKeysHeld(void); - -/** - * @brief Reads the current c-stick position. - * @param pos Pointer to output the current c-stick position to. - */ -void irrstCstickRead(circlePosition* pos); - -/** - * @brief Waits for the IRRST input event to trigger. - * @param nextEvent Whether to discard the current event and wait until the next event. - */ -void irrstWaitForEvent(bool nextEvent); - -/// Macro for irrstCstickRead. -#define hidCstickRead irrstCstickRead - -/** - * @brief Gets the shared memory and event handles for IRRST. - * @param outMemHandle Pointer to write the shared memory handle to. - * @param outEventHandle Pointer to write the event handle to. - */ -Result IRRST_GetHandles(Handle* outMemHandle, Handle* outEventHandle); - -/** - * @brief Initializes IRRST. - * @param unk1 Unknown. - * @param unk2 Unknown. - */ -Result IRRST_Initialize(u32 unk1, u8 unk2); - -/// Shuts down IRRST. -Result IRRST_Shutdown(void); diff --git a/Includes/ctrulib/services/soc.h b/Includes/ctrulib/services/soc.h deleted file mode 100644 index 4481855..0000000 --- a/Includes/ctrulib/services/soc.h +++ /dev/null @@ -1,149 +0,0 @@ -/** - * @file soc.h - * @brief SOC service for sockets communications - * - * After initializing this service you will be able to use system calls from netdb.h, sys/socket.h etc. - */ -#pragma once -#include "types.h" -#include -#include - -/// The config level to be used with @ref SOCU_GetNetworkOpt -#define SOL_CONFIG 0xfffe - -/// Options to be used with @ref SOCU_GetNetworkOpt -typedef enum -{ - NETOPT_MAC_ADDRESS = 0x1004, ///< The mac address of the interface (u32 mac[6]) - NETOPT_ARP_TABLE = 0x3002, ///< The ARP table @see SOCU_ARPTableEntry - NETOPT_IP_INFO = 0x4003, ///< The cureent IP setup @see SOCU_IPInfo - NETOPT_IP_MTU = 0x4004, ///< The value of the IP MTU (u32) - NETOPT_ROUTING_TABLE = 0x4006, ///< The routing table @see SOCU_RoutingTableEntry - NETOPT_UDP_NUMBER = 0x8002, ///< The number of sockets in the UDP table (u32) - NETOPT_UDP_TABLE = 0x8003, ///< The table of opened UDP sockets @see SOCU_UDPTableEntry - NETOPT_TCP_NUMBER = 0x9002, ///< The number of sockets in the TCP table (u32) - NETOPT_TCP_TABLE = 0x9003, ///< The table of opened TCP sockets @see SOCU_TCPTableEntry - NETOPT_DNS_TABLE = 0xB003, ///< The table of the DNS servers @see SOCU_DNSTableEntry -- Returns a buffer of size 336 but only 2 entries are set ? - NETOPT_DHCP_LEASE_TIME = 0xC001, ///< The DHCP lease time remaining, in seconds -} NetworkOpt; - -/// One entry of the ARP table retrieved by using @ref SOCU_GetNetworkOpt and @ref NETOPT_ARP_TABLE -typedef struct -{ - u32 unk0; // often 2 ? state ? - struct in_addr ip; ///< The IPv4 address associated to the entry - u8 mac[6]; ///< The MAC address of associated to the entry - u8 padding[2]; -} SOCU_ARPTableEntry; - -/// Structure returned by @ref SOCU_GetNetworkOpt when using @ref NETOPT_IP_INFO -typedef struct -{ - struct in_addr ip; ///< Current IPv4 address - struct in_addr netmask; ///< Current network mask - struct in_addr broadcast; ///< Current network broadcast address -} SOCU_IPInfo; - -// Linux netstat flags -// NOTE : there are probably other flags supported, if you can forge ICMP requests please check for D and M flags - -/** The route uses a gateway */ -#define ROUTING_FLAG_G 0x01 - -/// One entry of the routing table retrieved by using @ref SOCU_GetNetworkOpt and @ref NETOPT_ROUTING_TABLE -typedef struct -{ - struct in_addr dest_ip; ///< Destination IP address of the route - struct in_addr netmask; ///< Mask used for this route - struct in_addr gateway; ///< Gateway address to reach the network - u32 flags; ///< Linux netstat flags @see ROUTING_FLAG_G - u64 time; ///< number of milliseconds since 1st Jan 1900 00:00. -} SOCU_RoutingTableEntry; - -/// One entry of the UDP sockets table retrieved by using @ref SOCU_GetNetworkOpt and @ref NETOPT_UDP_TABLE -typedef struct -{ - struct sockaddr_storage local; ///< Local address information - struct sockaddr_storage remote; ///< Remote address information -} SOCU_UDPTableEntry; - -///@name TCP states -///@{ -#define TCP_STATE_CLOSED 1 -#define TCP_STATE_LISTEN 2 -#define TCP_STATE_ESTABLISHED 5 -#define TCP_STATE_FINWAIT1 6 -#define TCP_STATE_FINWAIT2 7 -#define TCP_STATE_CLOSE_WAIT 8 -#define TCP_STATE_LAST_ACK 9 -#define TCP_STATE_TIME_WAIT 11 -///@} - -/// One entry of the TCP sockets table retrieved by using @ref SOCU_GetNetworkOpt and @ref NETOPT_TCP_TABLE -typedef struct -{ - u32 state; ///< @see TCP states defines - struct sockaddr_storage local; ///< Local address information - struct sockaddr_storage remote; ///< Remote address information -} SOCU_TCPTableEntry; - -/// One entry of the DNS servers table retrieved by using @ref SOCU_GetNetworkOpt and @ref NETOPT_DNS_TABLE -typedef struct -{ - u32 family; /// Family of the address of the DNS server - struct in_addr ip; /// IP of the DNS server - u8 padding[12]; // matches the length required for IPv6 addresses -} SOCU_DNSTableEntry; - - -/** - * @brief Initializes the SOC service. - * @param context_addr Address of a page-aligned (0x1000) buffer to be used. - * @param context_size Size of the buffer, a multiple of 0x1000. - * @note The specified context buffer can no longer be accessed by the process which called this function, since the userland permissions for this block are set to no-access. - */ -Result socInit(u32 *context_addr, u32 context_size); - -/** - * @brief Closes the soc service. - * @note You need to call this in order to be able to use the buffer again. - */ -Result socExit(void); - -// this is supposed to be in unistd.h but newlib only puts it for cygwin, waiting for newlib patch from dkA -/** - * @brief Gets the system's host ID. - * @return The system's host ID. - */ -long gethostid(void); - -// this is supposed to be in unistd.h but newlib only puts it for cygwin, waiting for newlib patch from dkA -int gethostname(char *name, size_t namelen); - -int SOCU_ShutdownSockets(); - -int SOCU_CloseSockets(); - -/** - * @brief Retrieves information from the network configuration. Similar to getsockopt(). - * @param level Only value allowed seems to be @ref SOL_CONFIG - * @param optname The option to be retrieved - * @param optval Will contain the output of the command - * @param optlen Size of the optval buffer, will be updated to hold the size of the output - * @return 0 if successful. -1 if failed, and errno will be set accordingly. Can also return a system error code. - */ -int SOCU_GetNetworkOpt(int level, NetworkOpt optname, void * optval, socklen_t * optlen); - -/** - * @brief Gets the system's IP address, netmask, and subnet broadcast - * @return error - */ -int SOCU_GetIPInfo(struct in_addr *ip, struct in_addr *netmask, struct in_addr *broadcast); - -/** - * @brief Adds a global socket. - * @param sockfd The socket fd. - * @return error - */ -int SOCU_AddGlobalSocket(int sockfd); diff --git a/Includes/ctrulib/services/sslc.h b/Includes/ctrulib/services/sslc.h deleted file mode 100644 index 9a86f2a..0000000 --- a/Includes/ctrulib/services/sslc.h +++ /dev/null @@ -1,251 +0,0 @@ -/** - * @file sslc.h - * @brief SSLC(TLS) service. https://3dbrew.org/wiki/SSL_Services - */ -#pragma once - -/// sslc context. -typedef struct { - Handle servhandle; ///< Service handle. - u32 sslchandle; ///< SSLC handle. - Handle sharedmem_handle; -} sslcContext; - -typedef enum { - SSLC_DefaultRootCert_Nintendo_CA = 0x1, //"Nintendo CA" - SSLC_DefaultRootCert_Nintendo_CA_G2 = 0x2, //"Nintendo CA - G2" - SSLC_DefaultRootCert_Nintendo_CA_G3 = 0x3, //"Nintendo CA - G3" - SSLC_DefaultRootCert_Nintendo_Class2_CA = 0x4, //"Nintendo Class 2 CA" - SSLC_DefaultRootCert_Nintendo_Class2_CA_G2 = 0x5, //"Nintendo Class 2 CA - G2" - SSLC_DefaultRootCert_Nintendo_Class2_CA_G3 = 0x6, //"Nintendo Class 2 CA - G3" - SSLC_DefaultRootCert_CyberTrust = 0x7, //"GTE CyberTrust Global Root" - SSLC_DefaultRootCert_AddTrust_External_CA = 0x8, //"AddTrust External CA Root" - SSLC_DefaultRootCert_COMODO = 0x9, //"COMODO RSA Certification Authority" - SSLC_DefaultRootCert_USERTrust = 0xA, //"USERTrust RSA Certification Authority" - SSLC_DefaultRootCert_DigiCert_EV = 0xB //"DigiCert High Assurance EV Root CA" -} SSLC_DefaultRootCert; - -typedef enum { - SSLC_DefaultClientCert_ClCertA = 0x40 -} SSLC_DefaultClientCert; - -/// sslc options. https://www.3dbrew.org/wiki/SSL_Services#SSLOpt -enum { - SSLCOPT_Default = 0, - SSLCOPT_DisableVerify = BIT(9), // "Disables server cert verification when set." - SSLCOPT_TLSv10 = BIT(11) // "Use TLSv1.0." -}; - -/// Initializes SSLC. Normally session_handle should be 0. When non-zero this will use the specified handle for the main-service-session without using the Initialize command, instead of using srvGetServiceHandle. -Result sslcInit(Handle session_handle); - -/// Exits SSLC. -void sslcExit(void); - -/** - * @brief Creates a RootCertChain. - * @param RootCertChain_contexthandle Output contexthandle. - */ -Result sslcCreateRootCertChain(u32 *RootCertChain_contexthandle); - -/** - * @brief Destroys a RootCertChain. - * @param RootCertChain_contexthandle RootCertChain contexthandle. - */ -Result sslcDestroyRootCertChain(u32 RootCertChain_contexthandle); - -/** - * @brief Adds a trusted RootCA cert to a RootCertChain. - * @param RootCertChain_contexthandle RootCertChain to use. - * @param cert Pointer to the DER cert. - * @param certsize Size of the DER cert. - */ -Result sslcAddTrustedRootCA(u32 RootCertChain_contexthandle, const u8 *cert, u32 certsize, u32 *cert_contexthandle); - -/** - * @brief Adds a default RootCA cert to a RootCertChain. - * @param RootCertChain_contexthandle RootCertChain to use. - * @param certID ID of the cert to add. - * @param cert_contexthandle Optional, the cert contexthandle can be written here. - */ -Result sslcRootCertChainAddDefaultCert(u32 RootCertChain_contexthandle, SSLC_DefaultRootCert certID, u32 *cert_contexthandle); - -/** - * @brief Removes the specified cert from the RootCertChain. - * @param RootCertChain_contexthandle RootCertChain to use. - * @param cert_contexthandle Cert contexthandle to remove from the RootCertChain. - */ -Result sslcRootCertChainRemoveCert(u32 RootCertChain_contexthandle, u32 cert_contexthandle); - -/** - * @brief Creates an unknown CertChain. - * @param CertChain_contexthandle Output contexthandle. - */ -Result sslcCreate8CertChain(u32 *CertChain_contexthandle); - -/** - * @brief Destroys a CertChain from sslcCreate8CertChain(). - * @param CertChain_contexthandle CertChain contexthandle. - */ -Result sslcDestroy8CertChain(u32 CertChain_contexthandle); - -/** - * @brief Adds a cert to a CertChain from sslcCreate8CertChain(). - * @param CertChain_contexthandle CertChain to use. - * @param cert Pointer to the cert. - * @param certsize Size of the cert. - */ -Result sslc8CertChainAddCert(u32 CertChain_contexthandle, const u8 *cert, u32 certsize, u32 *cert_contexthandle); - -/** - * @brief Adds a default cert to a CertChain from sslcCreate8CertChain(). Not actually usable since no certIDs are implemented in SSL-module for this. - * @param CertChain_contexthandle CertChain to use. - * @param certID ID of the cert to add. - * @param cert_contexthandle Optional, the cert contexthandle can be written here. - */ -Result sslc8CertChainAddDefaultCert(u32 CertChain_contexthandle, u8 certID, u32 *cert_contexthandle); - -/** - * @brief Removes the specified cert from the CertChain from sslcCreate8CertChain(). - * @param CertChain_contexthandle CertChain to use. - * @param cert_contexthandle Cert contexthandle to remove from the CertChain. - */ -Result sslc8CertChainRemoveCert(u32 CertChain_contexthandle, u32 cert_contexthandle); - -/** - * @brief Opens a new ClientCert-context. - * @param cert Pointer to the DER cert. - * @param certsize Size of the DER cert. - * @param key Pointer to the DER key. - * @param keysize Size of the DER key. - * @param ClientCert_contexthandle Output contexthandle. - */ -Result sslcOpenClientCertContext(const u8 *cert, u32 certsize, const u8 *key, u32 keysize, u32 *ClientCert_contexthandle); - -/** - * @brief Opens a ClientCert-context with a default certID. - * @param certID ID of the ClientCert to use. - * @param ClientCert_contexthandle Output contexthandle. - */ -Result sslcOpenDefaultClientCertContext(SSLC_DefaultClientCert certID, u32 *ClientCert_contexthandle); - -/** - * @brief Closes the specified ClientCert-context. - * @param ClientCert_contexthandle ClientCert-context to use. - */ -Result sslcCloseClientCertContext(u32 ClientCert_contexthandle); - -/** - * @brief This uses ps:ps SeedRNG internally. - */ -Result sslcSeedRNG(void); - -/** - * @brief This uses ps:ps GenerateRandomData internally. - * @param buf Output buffer. - * @param size Output size. - */ -Result sslcGenerateRandomData(u8 *buf, u32 size); - -/** - * @brief Creates a sslc context. - * @param context sslc context. - * @param sockfd Socket fd, this code automatically uses the required SOC command before using the actual sslc command. - * @param input_opt Input sslc options bitmask. - * @param hostname Server hostname. - */ -Result sslcCreateContext(sslcContext *context, int sockfd, u32 input_opt, const char *hostname); - -/* - * @brief Destroys a sslc context. The associated sockfd must be closed manually. - * @param context sslc context. - */ -Result sslcDestroyContext(sslcContext *context); - -/* - * @brief Starts the TLS connection. If successful, this will not return until the connection is ready for data-transfer via sslcRead/sslcWrite. - * @param context sslc context. - * @param internal_retval Optional ptr where the internal_retval will be written. The value is only copied to here by this function when no error occurred. - * @param out Optional ptr where an output u32 will be written. The value is only copied to here by this function when no error occurred. - */ -Result sslcStartConnection(sslcContext *context, int *internal_retval, u32 *out); - -/* - * @brief Receive data over the network connection. - * @param context sslc context. - * @param buf Output buffer. - * @param len Size to receive. - * @param peek When true, this is equivalent to setting the recv() MSG_PEEK flag. - * @return When this isn't an error-code, this is the total transferred data size. - */ -Result sslcRead(sslcContext *context, void *buf, size_t len, bool peek); - -/* - * @brief Send data over the network connection. - * @param context sslc context. - * @param buf Input buffer. - * @param len Size to send. - * @return When this isn't an error-code, this is the total transferred data size. - */ -Result sslcWrite(sslcContext *context, const void *buf, size_t len); - -/* - * @brief Set the RootCertChain for the specified sslc context. - * @param context sslc context. - * @param handle RootCertChain contexthandle. - */ -Result sslcContextSetRootCertChain(sslcContext *context, u32 handle); - -/* - * @brief Set the ClientCert-context for the specified sslc context. - * @param context sslc context. - * @param handle ClientCert contexthandle. - */ -Result sslcContextSetClientCert(sslcContext *context, u32 handle); - -/* - * @brief Set the context for a CertChain from sslcCreate8CertChain(), for the specified sslc context. This needs updated once it's known what this context is for. - * @param context sslc context. - * @param handle contexthandle. - */ -Result sslcContextSetHandle8(sslcContext *context, u32 handle); - -/* - * @brief Clears the options field bits for the context using the specified bitmask. - * @param context sslc context. - * @param bitmask opt bitmask. - */ -Result sslcContextClearOpt(sslcContext *context, u32 bitmask); - -/* - * @brief This copies two strings from context state to the specified output buffers. Each string is only copied if it was successfully loaded. The maxsizes include the nul-terminator. This can only be used if sslcStartConnection() was already used successfully. - * @param context sslc context. - * @param outprotocols Output buffer for a string containing all protocol versions supported by SSL-module. - * @param outprotocols_maxsize Max size of the above output buffer. - * @param outcipher Output buffer for a string containing the cipher suite currently being used. - * @param outcipher_maxsize Max size of the above output buffer. - */ -Result sslcContextGetProtocolCipher(sslcContext *context, char *outprotocols, u32 outprotocols_maxsize, char *outcipher, u32 outcipher_maxsize); - -/* - * @brief This loads an u32 from the specified context state. This needs updated once it's known what this field is for. - * @param context sslc context. - * @param out Output ptr to write the value to. - */ -Result sslcContextGetState(sslcContext *context, u32 *out); - -/* - * @brief This initializes sharedmem for the specified context. - * @param context sslc context. - * @param buf Sharedmem buffer with address aligned to 0x1000-bytes. - * @param size Sharedmem size aligned to 0x1000-bytes. - */ -Result sslcContextInitSharedmem(sslcContext *context, u8 *buf, u32 size); - -/* - * @brief This loads the specified cert. This needs updated once it's known what the cert format is and what the cert is used for later. - * @param buf Input cert. - * @param size Cert size. - */ -Result sslcAddCert(sslcContext *context, const u8 *buf, u32 size); - diff --git a/Includes/ctrulib/srv.h b/Includes/ctrulib/srv.h deleted file mode 100644 index a33b3fc..0000000 --- a/Includes/ctrulib/srv.h +++ /dev/null @@ -1,125 +0,0 @@ -/** - * @file srv.h - * @brief Service API. - */ - -#ifndef NEWSRV_H -#define NEWSRV_H -#ifdef __cplusplus -extern "C" { -#endif -#include "types.h" -#include "result.h" - -/// Initializes the service API. -Result srvInit(void); - -/// Exits the service API. -void srvExit(void); - -/** - * @brief Gets the current service API session handle. - * @return The current service API session handle. - */ -Handle *srvGetSessionHandle(void); - -/** - * @brief Retrieves a service handle, retrieving from the environment handle list if possible. - * @param out Pointer to write the handle to. - * @param name Name of the service. - */ -Result srvGetServiceHandle(Handle* out, const char* name); - -/// Registers the current process as a client to the service API. -Result srvRegisterClient(void); - -/** - * @brief Enables service notificatios, returning a notification semaphore. - * @param semaphoreOut Pointer to output the notification semaphore to. - */ -Result srvEnableNotification(Handle* semaphoreOut); - -/** - * @brief Registers the current process as a service. - * @param out Pointer to write the service handle to. - * @param name Name of the service. - * @param maxSessions Maximum number of sessions the service can handle. - */ -Result srvRegisterService(Handle* out, const char* name, int maxSessions); - -/** - * @brief Unregisters the current process as a service. - * @param name Name of the service. - */ -Result srvUnregisterService(const char* name); - -/** - * @brief Retrieves a service handle. - * @param out Pointer to output the handle to. - * @param name Name of the service. - */ -Result srvGetServiceHandleDirect(Handle* out, const char* name); - -/** - * @brief Registers a port. - * @param name Name of the port. - * @param clientHandle Client handle of the port. - */ -Result srvRegisterPort(const char* name, Handle clientHandle); - -/** - * @brief Unregisters a port. - * @param name Name of the port. - */ -Result srvUnregisterPort(const char* name); - -/** - * @brief Retrieves a port handle. - * @param out Pointer to output the handle to. - * @param name Name of the port. - */ -Result srvGetPort(Handle* out, const char* name); - -/** - * @brief Subscribes to a notification. - * @param notificationId ID of the notification. - */ -Result srvSubscribe(u32 notificationId); - -/** - * @brief Unsubscribes from a notification. - * @param notificationId ID of the notification. - */ -Result srvUnsubscribe(u32 notificationId); - -/** - * @brief Receives a notification. - * @param notificationIdOut Pointer to output the ID of the received notification to. - */ -Result srvReceiveNotification(u32* notificationIdOut); - -/** - * @brief Publishes a notification to subscribers. - * @param notificationId ID of the notification. - * @param flags Flags to publish with. (bit 0 = only fire if not fired, bit 1 = report errors) - */ -Result srvPublishToSubscriber(u32 notificationId, u32 flags); - -/** - * @brief Publishes a notification to subscribers and retrieves a list of all processes that were notified. - * @param processIdCountOut Pointer to output the number of process IDs to. - * @param processIdsOut Pointer to output the process IDs to. Should have size "60 * sizeof(u32)". - * @param notificationId ID of the notification. - */ -Result srvPublishAndGetSubscriber(u32* processIdCountOut, u32* processIdsOut, u32 notificationId); - -/** - * @brief Checks whether a service is registered. - * @param registeredOut Pointer to output the registration status to. - * @param name Name of the service to check. - */ -Result srvIsServiceRegistered(bool* registeredOut, const char* name); -#ifdef __cplusplus -} -#endif -#endif \ No newline at end of file diff --git a/Includes/ctrulib/svc.h b/Includes/ctrulib/svc.h deleted file mode 100644 index 20fb0cd..0000000 --- a/Includes/ctrulib/svc.h +++ /dev/null @@ -1,1115 +0,0 @@ -/** - * @file svc.h - * @brief Syscall wrappers. - */ -#pragma once - -#include "types.h" -#ifdef __cplusplus -extern "C" { -#endif - -/// Pseudo handle for the current process -#define CUR_PROCESS_HANDLE 0xFFFF8001 - -///@name Memory management -///@{ - -/** - * @brief @ref svcControlMemory operation flags - * - * The lowest 8 bits are the operation - */ -typedef enum { - MEMOP_FREE = 1, ///< Memory un-mapping - MEMOP_RESERVE = 2, ///< Reserve memory - MEMOP_ALLOC = 3, ///< Memory mapping - MEMOP_MAP = 4, ///< Mirror mapping - MEMOP_UNMAP = 5, ///< Mirror unmapping - MEMOP_PROT = 6, ///< Change protection - - MEMOP_REGION_APP = 0x100, ///< APPLICATION memory region. - MEMOP_REGION_SYSTEM = 0x200, ///< SYSTEM memory region. - MEMOP_REGION_BASE = 0x300, ///< BASE memory region. - - MEMOP_OP_MASK = 0xFF, ///< Operation bitmask. - MEMOP_REGION_MASK = 0xF00, ///< Region bitmask. - MEMOP_LINEAR_FLAG = 0x10000, ///< Flag for linear memory operations - - MEMOP_ALLOC_LINEAR = MEMOP_LINEAR_FLAG | MEMOP_ALLOC, ///< Allocates linear memory. -} MemOp; - -/// The state of a memory block. -typedef enum { - MEMSTATE_FREE = 0, ///< Free memory - MEMSTATE_RESERVED = 1, ///< Reserved memory - MEMSTATE_IO = 2, ///< I/O memory - MEMSTATE_STATIC = 3, ///< Static memory - MEMSTATE_CODE = 4, ///< Code memory - MEMSTATE_PRIVATE = 5, ///< Private memory - MEMSTATE_SHARED = 6, ///< Shared memory - MEMSTATE_CONTINUOUS = 7, ///< Continuous memory - MEMSTATE_ALIASED = 8, ///< Aliased memory - MEMSTATE_ALIAS = 9, ///< Alias memory - MEMSTATE_ALIASCODE = 10, ///< Aliased code memory - MEMSTATE_LOCKED = 11, ///< Locked memory -} MemState; - -/// Memory permission flags -typedef enum { - MEMPERM_READ = 1, ///< Readable - MEMPERM_WRITE = 2, ///< Writable - MEMPERM_EXECUTE = 4, ///< Executable - MEMPERM_DONTCARE = 0x10000000, ///< Don't care -} MemPerm; - -/// Memory information. -typedef struct { - u32 base_addr; ///< Base address. - u32 size; ///< Size. - u32 perm; ///< Memory permissions. See @ref MemPerm - u32 state; ///< Memory state. See @ref MemState -} MemInfo; - -/// Memory page information. -typedef struct { - u32 flags; ///< Page flags. -} PageInfo; - -/// Arbitration modes. -typedef enum { - ARBITRATION_SIGNAL = 0, ///< Signal #value threads for wake-up. - ARBITRATION_WAIT_IF_LESS_THAN = 1, ///< If the memory at the address is strictly lower than #value, then wait for signal. - ARBITRATION_DECREMENT_AND_WAIT_IF_LESS_THAN = 2, ///< If the memory at the address is strictly lower than #value, then decrement it and wait for signal. - ARBITRATION_WAIT_IF_LESS_THAN_TIMEOUT = 3, ///< If the memory at the address is strictly lower than #value, then wait for signal or timeout. - ARBITRATION_DECREMENT_AND_WAIT_IF_LESS_THAN_TIMEOUT = 4, ///< If the memory at the address is strictly lower than #value, then decrement it and wait for signal or timeout. -} ArbitrationType; - -/// Special value to signal all the threads -#define ARBITRATION_SIGNAL_ALL (-1) - -///@} - -///@name Multithreading -///@{ - -/// Reset types (for use with events and timers) -typedef enum { - RESET_ONESHOT = 0, ///< When the primitive is signaled, it will wake up exactly one thread and will clear itself automatically. - RESET_STICKY = 1, ///< When the primitive is signaled, it will wake up all threads and it won't clear itself automatically. - RESET_PULSE = 2, ///< Only meaningful for timers: same as ONESHOT but it will periodically signal the timer instead of just once. -} ResetType; - -/// Types of thread info. -typedef enum { - THREADINFO_TYPE_UNKNOWN ///< Unknown. -} ThreadInfoType; - -/// Pseudo handle for the current thread -#define CUR_THREAD_HANDLE 0xFFFF8000 - -///@} - - -///@name Debugging -///@{ - -/// Event relating to the attachment of a process. -typedef struct { - u64 program_id; ///< ID of the program. - char process_name[8]; ///< Name of the process. - u32 process_id; ///< ID of the process. - u32 other_flags; ///< Always 0 -} AttachProcessEvent; - -/// Reasons for an exit process event. -typedef enum { - EXITPROCESS_EVENT_NONE = 0, ///< No reason. - EXITPROCESS_EVENT_TERMINATE = 1, ///< Process terminated. - EXITPROCESS_EVENT_UNHANDLED_EXCEPTION = 2, ///< Unhandled exception occurred. -} ExitProcessEventReason; - -/// Event relating to the exiting of a process. -typedef struct { - ExitProcessEventReason reason; ///< Reason for exiting. See @ref ExitProcessEventReason -} ExitProcessEvent; - -/// Event relating to the attachment of a thread. -typedef struct { - u32 creator_thread_id; ///< ID of the creating thread. - u32 thread_local_storage; ///< Thread local storage. - u32 entry_point; ///< Entry point of the thread. -} AttachThreadEvent; - -/// Reasons for an exit thread event. -typedef enum { - EXITTHREAD_EVENT_NONE = 0, ///< No reason. - EXITTHREAD_EVENT_TERMINATE = 1, ///< Thread terminated. - EXITTHREAD_EVENT_UNHANDLED_EXC = 2, ///< Unhandled exception occurred. - EXITTHREAD_EVENT_TERMINATE_PROCESS = 3, ///< Process terminated. -} ExitThreadEventReason; - -/// Event relating to the exiting of a thread. -typedef struct { - ExitThreadEventReason reason; ///< Reason for exiting. See @ref ExitThreadEventReason -} ExitThreadEvent; - -/// Reasons for a user break. -typedef enum { - USERBREAK_PANIC = 0, ///< Panic. - USERBREAK_ASSERT = 1, ///< Assertion failed. - USERBREAK_USER = 2, ///< User related. - USERBREAK_LOAD_RO = 3, ///< Load RO. - USERBREAK_UNLOAD_RO = 4, ///< Unload RO. -} UserBreakType; - -/// Reasons for an exception event. -typedef enum { - EXCEVENT_UNDEFINED_INSTRUCTION = 0, ///< Undefined instruction. - EXCEVENT_PREFETCH_ABORT = 1, ///< Prefetch abort. - EXCEVENT_DATA_ABORT = 2, ///< Data abort (other than the below kind). - EXCEVENT_UNALIGNED_DATA_ACCESS = 3, ///< Unaligned data access. - EXCEVENT_ATTACH_BREAK = 4, ///< Attached break. - EXCEVENT_STOP_POINT = 5, ///< Stop point reached. - EXCEVENT_USER_BREAK = 6, ///< User break occurred. - EXCEVENT_DEBUGGER_BREAK = 7, ///< Debugger break occurred. - EXCEVENT_UNDEFINED_SYSCALL = 8, ///< Undefined syscall. -} ExceptionEventType; - -/// Event relating to fault exceptions (CPU exceptions other than stop points and undefined syscalls). -typedef struct { - u32 fault_information; ///< FAR (for DATA ABORT / UNALIGNED DATA ACCESS), attempted syscall or 0 -} FaultExceptionEvent; - -/// Stop point types -typedef enum { - STOPPOINT_SVC_FF = 0, ///< See @ref SVC_STOP_POINT. - STOPPOINT_BREAKPOINT = 1, ///< Breakpoint. - STOPPOINT_WATCHPOINT = 2, ///< Watchpoint. -} StopPointType; - -/// Event relating to stop points -typedef struct { - StopPointType type; ///< Stop point type, see @ref StopPointType. - u32 fault_information; ///< FAR for Watchpoints, otherwise 0. -} StopPointExceptionEvent; - -/// Event relating to @ref svcBreak -typedef struct { - UserBreakType type; ///< User break type, see @ref UserBreakType. - u32 croInfo; ///< For LOAD_RO and UNLOAD_RO. - u32 croInfoSize; ///< For LOAD_RO and UNLOAD_RO. -} UserBreakExceptionEvent; - -/// Event relating to @ref svcBreakDebugProcess -typedef struct { - void *threads[4]; ///< KThread instances of the attached process's that were running on each at the time of the function call (only the first 2 values are meaningful on O3DS). -} DebuggerBreakExceptionEvent; - -/// Event relating to exceptions. -typedef struct { - ExceptionEventType type; ///< Type of event. See @ref ExceptionEventType. - u32 address; ///< Address of the exception. - union { - FaultExceptionEvent fault; ///< Fault exception event data. - StopPointExceptionEvent stop_point; ///< Stop point exception event data. - UserBreakExceptionEvent user_break; ///< User break exception event data. - DebuggerBreakExceptionEvent debugger_break; ///< Debugger break exception event data - }; -} ExceptionEvent; - -/// Event relating to the scheduler. -typedef struct { - u64 clock_tick; ///< Clock tick that the event occurred. -} ScheduleInOutEvent; - -/// Event relating to syscalls. -typedef struct { - u64 clock_tick; ///< Clock tick that the event occurred. - u32 syscall; ///< Syscall sent/received. -} SyscallInOutEvent; - -/// Event relating to debug output. -typedef struct { - u32 string_addr; ///< Address of the outputted string. - u32 string_size; ///< Size of the outputted string. -} OutputStringEvent; - -/// Event relating to the mapping of memory. -typedef struct { - u32 mapped_addr; ///< Mapped address. - u32 mapped_size; ///< Mapped size. - MemPerm memperm; ///< Memory permissions. See @ref MemPerm. - MemState memstate; ///< Memory state. See @ref MemState. -} MapEvent; - -/// Debug event type. -typedef enum { - DBGEVENT_ATTACH_PROCESS = 0, ///< Process attached event. - DBGEVENT_ATTACH_THREAD = 1, ///< Thread attached event. - DBGEVENT_EXIT_THREAD = 2, ///< Thread exit event. - DBGEVENT_EXIT_PROCESS = 3, ///< Process exit event. - DBGEVENT_EXCEPTION = 4, ///< Exception event. - DBGEVENT_DLL_LOAD = 5, ///< DLL load event. - DBGEVENT_DLL_UNLOAD = 6, ///< DLL unload event. - DBGEVENT_SCHEDULE_IN = 7, ///< Schedule in event. - DBGEVENT_SCHEDULE_OUT = 8, ///< Schedule out event. - DBGEVENT_SYSCALL_IN = 9, ///< Syscall in event. - DBGEVENT_SYSCALL_OUT = 10, ///< Syscall out event. - DBGEVENT_OUTPUT_STRING = 11, ///< Output string event. - DBGEVENT_MAP = 12, ///< Map event. -} DebugEventType; - -/// Information about a debug event. -typedef struct { - DebugEventType type; ///< Type of event. See @ref DebugEventType - u32 thread_id; ///< ID of the thread. - u32 flags; ///< Flags. Bit0 means that @ref svcContinueDebugEvent needs to be called for this event (except for EXIT PROCESS events, where this flag is disregarded). - u8 remnants[4]; ///< Always 0. - union { - AttachProcessEvent attach_process; ///< Process attachment event data. - AttachThreadEvent attach_thread; ///< Thread attachment event data. - ExitThreadEvent exit_thread; ///< Thread exit event data. - ExitProcessEvent exit_process; ///< Process exit event data. - ExceptionEvent exception; ///< Exception event data. - /* DLL_LOAD and DLL_UNLOAD do not seem to possess any event data */ - ScheduleInOutEvent scheduler; ///< Schedule in/out event data. - SyscallInOutEvent syscall; ///< Syscall in/out event data. - OutputStringEvent output_string; ///< Output string event data. - MapEvent map; ///< Map event data. - }; -} DebugEventInfo; - -/// Debug flags for an attached process, set by @ref svcContinueDebugEvent -typedef enum { - DBG_NO_ERRF_CPU_EXCEPTION_DUMPS = BIT(0), ///< Don't produce err:f-format dumps for CPU exceptions (including watchpoints and breakpoints, regardless of any @ref svcKernelSetState call). - DBG_SIGNAL_FAULT_EXCEPTION_EVENTS = BIT(1), ///< Signal fault exception events. See @ref FaultExceptionEvent. - DBG_SIGNAL_SCHEDULE_EVENTS = BIT(2), ///< Signal schedule in/out events. See @ref ScheduleInOutEvent. - DBG_SIGNAL_SYSCALL_EVENTS = BIT(3), ///< Signal syscall in/out events. See @ref SyscallInOutEvent. - DBG_SIGNAL_MAP_EVENTS = BIT(4), ///< Signal map events. See @ref MapEvent. -} DebugFlags; - -typedef struct { - CpuRegisters cpu_registers; ///< CPU registers. - FpuRegisters fpu_registers; ///< FPU registers. -} ThreadContext; - -/// Control flags for @ref svcGetDebugThreadContext and @ref svcSetDebugThreadContext -typedef enum { - THREADCONTEXT_CONTROL_CPU_GPRS = BIT(0), ///< Control r0-r12. - THREADCONTEXT_CONTROL_CPU_SPRS = BIT(1), ///< Control sp, lr, pc, cpsr. - THREADCONTEXT_CONTROL_FPU_GPRS = BIT(2), ///< Control d0-d15 (or f0-f31). - THREADCONTEXT_CONTROL_FPU_SPRS = BIT(3), ///< Control fpscr, fpexc. - - THREADCONTEXT_CONTROL_CPU_REGS = BIT(0) | BIT(1), ///< Control r0-r12, sp, lr, pc, cpsr. - THREADCONTEXT_CONTROL_FPU_REGS = BIT(2) | BIT(3), ///< Control d0-d15, fpscr, fpexc. - - THREADCONTEXT_CONTROL_ALL = BIT(0) | BIT(1) | BIT(2) | BIT(3), ///< Control all of the above. -} ThreadContextControlFlags; - -/// Thread parameter field for @ref svcGetDebugThreadParameter -typedef enum { - DBGTHREAD_PARAMETER_PRIORITY = 0, ///< Thread priority. - DBGTHREAD_PARAMETER_SCHEDULING_MASK_LOW = 1, ///< Low scheduling mask. - DBGTHREAD_PARAMETER_CPU_IDEAL = 2, ///< Ideal processor. - DBGTHREAD_PARAMETER_CPU_CREATOR = 3, ///< Processor that created the threod. -} DebugThreadParameter; - -///@} - -///@name Processes -///@{ - -/// Information on address space for process. All sizes are in pages (0x1000 bytes) -typedef struct { - u8 name[8]; ///< ASCII name of codeset - u16 unk1; - u16 unk2; - u32 unk3; - u32 text_addr; ///< .text start address - u32 text_size; ///< .text number of pages - u32 ro_addr; ///< .rodata start address - u32 ro_size; ///< .rodata number of pages - u32 rw_addr; ///< .data, .bss start address - u32 rw_size; ///< .data number of pages - u32 text_size_total; ///< total pages for .text (aligned) - u32 ro_size_total; ///< total pages for .rodata (aligned) - u32 rw_size_total; ///< total pages for .data, .bss (aligned) - u32 unk4; - u64 program_id; ///< Program ID -} CodeSetInfo; - -/// Information for the main thread of a process. -typedef struct -{ - int priority; ///< Priority of the main thread. - u32 stack_size; ///< Size of the stack of the main thread. - int argc; ///< Unused on retail kernel. - u16* argv; ///< Unused on retail kernel. - u16* envp; ///< Unused on retail kernel. -} StartupInfo; - -///@} - -/** - * @brief Gets the thread local storage buffer. - * @return The thread local storage bufger. - */ -static inline void* getThreadLocalStorage(void) -{ - void* ret; - __asm__ ("mrc p15, 0, %[data], c13, c0, 3" : [data] "=r" (ret)); - return ret; -} - -/** - * @brief Gets the thread command buffer. - * @return The thread command bufger. - */ -static inline u32* getThreadCommandBuffer(void) -{ - return (u32*)((u8*)getThreadLocalStorage() + 0x80); -} - -/** - * @brief Gets the thread static buffer. - * @return The thread static bufger. - */ -static inline u32* getThreadStaticBuffers(void) -{ - return (u32*)((u8*)getThreadLocalStorage() + 0x180); -} - -///@name Memory management -///@{ -/** - * @brief Controls memory mapping - * @param[out] addr_out The virtual address resulting from the operation. Usually the same as addr0. - * @param addr0 The virtual address to be used for the operation. - * @param addr1 The virtual address to be (un)mirrored by @p addr0 when using @ref MEMOP_MAP or @ref MEMOP_UNMAP. - * It has to be pointing to a RW memory. - * Use NULL if the operation is @ref MEMOP_FREE or @ref MEMOP_ALLOC. - * @param size The requested size for @ref MEMOP_ALLOC and @ref MEMOP_ALLOC_LINEAR. - * @param op Operation flags. See @ref MemOp. - * @param perm A combination of @ref MEMPERM_READ and @ref MEMPERM_WRITE. Using MEMPERM_EXECUTE will return an error. - * Value 0 is used when unmapping memory. - * - * If a memory is mapped for two or more addresses, you have to use MEMOP_UNMAP before being able to MEMOP_FREE it. - * MEMOP_MAP will fail if @p addr1 was already mapped to another address. - * - * More information is available at http://3dbrew.org/wiki/SVC#Memory_Mapping. - * - * @sa svcControlProcessMemory - */ -Result svcControlMemory(u32* addr_out, u32 addr0, u32 addr1, u32 size, MemOp op, MemPerm perm); - -/** - * @brief Controls the memory mapping of a process - * @param addr0 The virtual address to map - * @param addr1 The virtual address to be mapped by @p addr0 - * @param type Only operations @ref MEMOP_MAP, @ref MEMOP_UNMAP and @ref MEMOP_PROT are allowed. - * - * This is the only SVC which allows mapping executable memory. - * Using @ref MEMOP_PROT will change the memory permissions of an already mapped memory. - * - * @note The pseudo handle for the current process is not supported by this service call. - * @sa svcControlProcess - */ -Result svcControlProcessMemory(Handle process, u32 addr0, u32 addr1, u32 size, u32 type, u32 perm); - -/** - * @brief Creates a block of shared memory - * @param[out] memblock Pointer to store the handle of the block - * @param addr Address of the memory to map, page-aligned. So its alignment must be 0x1000. - * @param size Size of the memory to map, a multiple of 0x1000. - * @param my_perm Memory permissions for the current process - * @param other_perm Memory permissions for the other processes - * - * @note The shared memory block, and its rights, are destroyed when the handle is closed. - */ -Result svcCreateMemoryBlock(Handle* memblock, u32 addr, u32 size, MemPerm my_perm, MemPerm other_perm); - -/** - * @brief Maps a block of shared memory - * @param memblock Handle of the block - * @param addr Address of the memory to map, page-aligned. So its alignment must be 0x1000. - * @param my_perm Memory permissions for the current process - * @param other_perm Memory permissions for the other processes - * - * @note The shared memory block, and its rights, are destroyed when the handle is closed. - */ -Result svcMapMemoryBlock(Handle memblock, u32 addr, MemPerm my_perm, MemPerm other_perm); - -/** - * @brief Maps a block of process memory. - * @param process Handle of the process. - * @param startAddr Start address of the memory to map. - * @param endAddr End address of the memory to map. - */ -Result svcMapProcessMemory(Handle process, u32 startAddr, u32 endAddr); - -/** - * @brief Unmaps a block of process memory. - * @param process Handle of the process. - * @param startAddr Start address of the memory to unmap. - * @param endAddr End address of the memory to unmap. - */ -Result svcUnmapProcessMemory(Handle process, u32 startAddr, u32 endAddr); - -/** - * @brief Unmaps a block of shared memory - * @param memblock Handle of the block - * @param addr Address of the memory to unmap, page-aligned. So its alignment must be 0x1000. - */ -Result svcUnmapMemoryBlock(Handle memblock, u32 addr); - -/** - * @brief Begins an inter-process DMA. - * @param[out] dma Pointer to output the handle of the DMA to. - * @param dstProcess Destination process. - * @param dst Buffer to write data to. - * @param srcprocess Source process. - * @param src Buffer to read data from. - * @param size Size of the data to DMA. - * @param dmaConfig DMA configuration data. - */ -Result svcStartInterProcessDma(Handle* dma, Handle dstProcess, void* dst, Handle srcProcess, const void* src, u32 size, void* dmaConfig); - -/** - * @brief Terminates an inter-process DMA. - * @param dma Handle of the DMA. - */ -Result svcStopDma(Handle dma); - -/** - * @brief Gets the state of an inter-process DMA. - * @param[out] dmaState Pointer to output the state of the DMA to. - * @param dma Handle of the DMA. - */ -Result svcGetDmaState(void* dmaState, Handle dma); - -/** - * @brief Queries memory information. - * @param[out] info Pointer to output memory info to. - * @param out Pointer to output page info to. - * @param addr Virtual memory address to query. - */ -Result svcQueryMemory(MemInfo* info, PageInfo* out, u32 addr); - -/** - * @brief Queries process memory information. - * @param[out] info Pointer to output memory info to. - * @param[out] out Pointer to output page info to. - * @param process Process to query memory from. - * @param addr Virtual memory address to query. - */ -Result svcQueryProcessMemory(MemInfo* info, PageInfo* out, Handle process, u32 addr); - -/** - * @brief Invalidates a process's data cache. - * @param process Handle of the process. - * @param addr Address to invalidate. - * @param size Size of the memory to invalidate. - */ -Result svcInvalidateProcessDataCache(Handle process, void* addr, u32 size); - -/** - * @brief Flushes a process's data cache. - * @param process Handle of the process. - * @param addr Address to flush. - * @param size Size of the memory to flush. - */ -Result svcFlushProcessDataCache(Handle process, void const* addr, u32 size); -///@} - - -///@name Process management -///@{ -/** - * @brief Gets the handle of a process. - * @param[out] process The handle of the process - * @param processId The ID of the process to open - */ -Result svcOpenProcess(Handle* process, u32 processId); - -/// Exits the current process. -void svcExitProcess() __attribute__((noreturn)); - -/** - * @brief Terminates a process. - * @param process Handle of the process to terminate. - */ -Result svcTerminateProcess(Handle process); - -/** - * @brief Gets information about a process. - * @param[out] out Pointer to output process info to. - * @param process Handle of the process to get information about. - * @param type Type of information to retreieve. - */ -Result svcGetProcessInfo(s64* out, Handle process, u32 type); - -/** - * @brief Gets the ID of a process. - * @param[out] out Pointer to output the process ID to. - * @param handle Handle of the process to get the ID of. - */ -Result svcGetProcessId(u32 *out, Handle handle); - -/** - * @brief Gets a list of running processes. - * @param[out] processCount Pointer to output the process count to. - * @param[out] processIds Pointer to output the process IDs to. - * @param processIdMaxCount Maximum number of process IDs. - */ -Result svcGetProcessList(s32* processCount, u32* processIds, s32 processIdMaxCount); - -/** - * @brief Gets a list of the threads of a process. - * @param[out] threadCount Pointer to output the thread count to. - * @param[out] threadIds Pointer to output the thread IDs to. - * @param threadIdMaxCount Maximum number of thread IDs. - * @param process Process handle to list the threads of. - */ -Result svcGetThreadList(s32* threadCount, u32* threadIds, s32 threadIdMaxCount, Handle process); - -/** - * @brief Creates a port. - * @param[out] portServer Pointer to output the port server handle to. - * @param[out] portClient Pointer to output the port client handle to. - * @param name Name of the port. - * @param maxSessions Maximum number of sessions that can connect to the port. - */ -Result svcCreatePort(Handle* portServer, Handle* portClient, const char* name, s32 maxSessions); - -/** - * @brief Connects to a port. - * @param[out] out Pointer to output the port handle to. - * @param portName Name of the port. - */ -Result svcConnectToPort(volatile Handle* out, const char* portName); - -/** - * @brief Sets up virtual address space for a new process - * @param[out] out Pointer to output the code set handle to. - * @param info Description for setting up the addresses - * @param code_ptr Pointer to .text in shared memory - * @param ro_ptr Pointer to .rodata in shared memory - * @param data_ptr Pointer to .data in shared memory - */ -Result svcCreateCodeSet(Handle* out, const CodeSetInfo *info, void* code_ptr, void* ro_ptr, void* data_ptr); - -/** - * @brief Sets up virtual address space for a new process - * @param[out] out Pointer to output the process handle to. - * @param codeset Codeset created for this process - * @param arm11kernelcaps ARM11 Kernel Capabilities from exheader - * @param arm11kernelcaps_num Number of kernel capabilities - */ -Result svcCreateProcess(Handle* out, Handle codeset, const u32 *arm11kernelcaps, u32 arm11kernelcaps_num); - -/** - * @brief Sets a process's affinity mask. - * @param process Handle of the process. - * @param affinitymask Pointer to retrieve the affinity masks from. - * @param processorcount Number of processors. - */ -Result svcSetProcessAffinityMask(Handle process, const u8* affinitymask, s32 processorcount); - -/** - * Sets a process's ideal processor. - * @param process Handle of the process. - * @param processorid ID of the thread's ideal processor. - */ -Result svcSetProcessIdealProcessor(Handle process, s32 processorid); - -/** - * Launches the main thread of the process. - * @param process Handle of the process. - * @param info Pointer to a StartupInfo structure describing information for the main thread. - */ -Result svcRun(Handle process, const StartupInfo* info); - -///@} - -///@name Multithreading -///@{ -/** - * @brief Creates a new thread. - * @param[out] thread The thread handle - * @param entrypoint The function that will be called first upon thread creation - * @param arg The argument passed to @p entrypoint - * @param stack_top The top of the thread's stack. Must be 0x8 bytes mem-aligned. - * @param thread_priority Low values gives the thread higher priority. - * For userland apps, this has to be within the range [0x18;0x3F] - * @param processor_id The id of the processor the thread should be ran on. Those are labelled starting from 0. - * For old 3ds it has to be <2, and for new 3DS <4. - * Value -1 means all CPUs and -2 read from the Exheader. - * - * The processor with ID 1 is the system processor. - * To enable multi-threading on this core you need to call APT_SetAppCpuTimeLimit at least once with a non-zero value. - * - * Since a thread is considered as a waitable object, you can use @ref svcWaitSynchronization - * and @ref svcWaitSynchronizationN to join with it. - * - * @note The kernel will clear the @p stack_top's address low 3 bits to make sure it is 0x8-bytes aligned. - */ -Result svcCreateThread(Handle* thread, ThreadFunc entrypoint, u32 arg, u32* stack_top, s32 thread_priority, s32 processor_id); - -/** - * @brief Gets the handle of a thread. - * @param[out] thread The handle of the thread - * @param process The ID of the process linked to the thread - */ -Result svcOpenThread(Handle* thread,Handle process, u32 threadId); - -/** - * @brief Exits the current thread. - * - * This will trigger a state change and hence release all @ref svcWaitSynchronization operations. - * It means that you can join a thread by calling @code svcWaitSynchronization(threadHandle,yourtimeout); @endcode - */ -void svcExitThread(void) __attribute__((noreturn)); - -/** - * @brief Puts the current thread to sleep. - * @param ns The minimum number of nanoseconds to sleep for. - */ -void svcSleepThread(s64 ns); - -/// Retrieves the priority of a thread. -Result svcGetThreadPriority(s32 *out, Handle handle); - -/** - * @brief Changes the priority of a thread - * @param prio For userland apps, this has to be within the range [0x18;0x3F] - * - * Low values gives the thread higher priority. - */ -Result svcSetThreadPriority(Handle thread, s32 prio); - -/** - * @brief Gets a thread's affinity mask. - * @param[out] affinitymask Pointer to output the affinity masks to. - * @param thread Handle of the thread. - * @param processorcount Number of processors. - */ -Result svcGetThreadAffinityMask(u8* affinitymask, Handle thread, s32 processorcount); - -/** - * @brief Sets a thread's affinity mask. - * @param thread Handle of the thread. - * @param affinitymask Pointer to retrieve the affinity masks from. - * @param processorcount Number of processors. - */ -Result svcSetThreadAffinityMask(Handle thread, const u8* affinitymask, s32 processorcount); - -/** - * @brief Gets a thread's ideal processor. - * @param[out] processorid Pointer to output the ID of the thread's ideal processor to. - * @param thread Handle of the thread. - */ -Result svcGetThreadIdealProcessor(s32* processorid, Handle thread); - -/** - * Sets a thread's ideal processor. - * @param thread Handle of the thread. - * @param processorid ID of the thread's ideal processor. - */ -Result svcSetThreadIdealProcessor(Handle thread, s32 processorid); - -/** - * @brief Returns the ID of the processor the current thread is running on. - * @sa svcCreateThread - */ -s32 svcGetProcessorID(void); - -/** - * @brief Gets the ID of a thread. - * @param[out] out Pointer to output the thread ID of the thread @p handle to. - * @param handle Handle of the thread. - */ -Result svcGetThreadId(u32 *out, Handle handle); - -/** - * @brief Gets the resource limit set of a process. - * @param[out] resourceLimit Pointer to output the resource limit set handle to. - * @param process Process to get the resource limits of. - */ -Result svcGetResourceLimit(Handle* resourceLimit, Handle process); - -/** - * @brief Gets the value limits of a resource limit set. - * @param[out] values Pointer to output the value limits to. - * @param resourceLimit Resource limit set to use. - * @param names Resource limit names to get the limits of. - * @param nameCount Number of resource limit names. - */ -Result svcGetResourceLimitLimitValues(s64* values, Handle resourceLimit, u32* names, s32 nameCount); - -/** - * @brief Gets the values of a resource limit set. - * @param[out] values Pointer to output the values to. - * @param resourceLimit Resource limit set to use. - * @param names Resource limit names to get the values of. - * @param nameCount Number of resource limit names. - */ -Result svcGetResourceLimitCurrentValues(s64* values, Handle resourceLimit, u32* names, s32 nameCount); - -/** - * @brief Gets the process ID of a thread. - * @param[out] out Pointer to output the process ID of the thread @p handle to. - * @param handle Handle of the thread. - * @sa svcOpenProcess - */ -Result svcGetProcessIdOfThread(u32 *out, Handle handle); - -/** - * @brief Checks if a thread handle is valid. - * This requests always return an error when called, it only checks if the handle is a thread or not. - * @return 0xD8E007ED (BAD_ENUM) if the Handle is a Thread Handle - * @return 0xD8E007F7 (BAD_HANDLE) if it isn't. - */ -Result svcGetThreadInfo(s64* out, Handle thread, ThreadInfoType type); -///@} - - -///@name Synchronization -///@{ -/** - * @brief Creates a mutex. - * @param[out] mutex Pointer to output the handle of the created mutex to. - * @param initially_locked Whether the mutex should be initially locked. - */ -Result svcCreateMutex(Handle* mutex, bool initially_locked); - -/** - * @brief Releases a mutex. - * @param handle Handle of the mutex. - */ -Result svcReleaseMutex(Handle handle); - -/** - * @brief Creates a semaphore. - * @param[out] semaphore Pointer to output the handle of the created semaphore to. - * @param initial_count Initial count of the semaphore. - * @param max_count Maximum count of the semaphore. - */ -Result svcCreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count); - -/** - * @brief Releases a semaphore. - * @param[out] count Pointer to output the current count of the semaphore to. - * @param semaphore Handle of the semaphore. - * @param release_count Number to increase the semaphore count by. - */ -Result svcReleaseSemaphore(s32* count, Handle semaphore, s32 release_count); - -/** - * @brief Creates an event handle. - * @param[out] event Pointer to output the created event handle to. - * @param reset_type Type of reset the event uses (RESET_ONESHOT/RESET_STICKY). - */ -Result svcCreateEvent(Handle* event, ResetType reset_type); - -/** - * @brief Signals an event. - * @param handle Handle of the event to signal. - */ -Result svcSignalEvent(Handle handle); - -/** - * @brief Clears an event. - * @param handle Handle of the event to clear. - */ -Result svcClearEvent(Handle handle); - -/** - * @brief Waits for synchronization on a handle. - * @param handle Handle to wait on. - * @param nanoseconds Maximum nanoseconds to wait for. - */ -Result svcWaitSynchronization(Handle handle, s64 nanoseconds); - -/** - * @brief Waits for synchronization on multiple handles. - * @param[out] out Pointer to output the index of the synchronized handle to. - * @param handles Handles to wait on. - * @param handles_num Number of handles. - * @param wait_all Whether to wait for synchronization on all handles. - * @param nanoseconds Maximum nanoseconds to wait for. - */ -Result svcWaitSynchronizationN(s32* out, Handle* handles, s32 handles_num, bool wait_all, s64 nanoseconds); - -/** - * @brief Creates an address arbiter - * @param[out] mutex Pointer to output the handle of the created address arbiter to. - * @sa svcArbitrateAddress - */ -Result svcCreateAddressArbiter(Handle *arbiter); - -/** - * @brief Arbitrate an address, can be used for synchronization - * @param arbiter Handle of the arbiter - * @param addr A pointer to a s32 value. - * @param type Type of action to be performed by the arbiter - * @param value Number of threads to signal if using @ref ARBITRATION_SIGNAL, or the value used for comparison. - * - * This will perform an arbitration based on #type. The comparisons are done between #value and the value at the address #addr. - * - * @code - * s32 val=0; - * // Does *nothing* since val >= 0 - * svcCreateAddressArbiter(arbiter,&val,ARBITRATION_WAIT_IF_LESS_THAN,0,0); - * // Thread will wait for a signal or wake up after 10000000 nanoseconds because val < 1. - * svcCreateAddressArbiter(arbiter,&val,ARBITRATION_WAIT_IF_LESS_THAN_TIMEOUT,1,10000000ULL); - * @endcode - */ -Result svcArbitrateAddress(Handle arbiter, u32 addr, ArbitrationType type, s32 value, s64 nanoseconds); - -/** - * @brief Sends a synchronized request to a session handle. - * @param session Handle of the session. - */ -Result svcSendSyncRequest(Handle session); - -/** - * @brief Accepts a session. - * @param[out] session Pointer to output the created session handle to. - * @param port Handle of the port to accept a session from. - */ -Result svcAcceptSession(Handle* session, Handle port); - -/** - * @brief Replies to and receives a new request. - * @param index Pointer to the index of the request. - * @param handles Session handles to receive requests from. - * @param handleCount Number of handles. - * @param replyTarget Handle of the session to reply to. - */ -Result svcReplyAndReceive(s32* index, Handle* handles, s32 handleCount, Handle replyTarget); - -/** - * @brief Binds an event or semaphore handle to an ARM11 interrupt. - * @param interruptId Interrupt identfier (see https://www.3dbrew.org/wiki/ARM11_Interrupts). - * @param eventOrSemaphore Event or semaphore handle to bind to the given interrupt. - * @param priority Priority of the interrupt for the current process. - * @param isManualClear Indicates whether the interrupt has to be manually cleared or not (= level-high active). - */ -Result svcBindInterrupt(u32 interruptId, Handle eventOrSemaphore, s32 priority, bool isManualClear); - -/** - * @brief Unbinds an event or semaphore handle from an ARM11 interrupt. - * @param interruptId Interrupt identfier, see (see https://www.3dbrew.org/wiki/ARM11_Interrupts). - * @param eventOrSemaphore Event or semaphore handle to unbind from the given interrupt. - */ -Result svcUnbindInterrupt(u32 interruptId, Handle eventOrSemaphore); -///@} - -///@name Time -///@{ -/** - * @brief Creates a timer. - * @param[out] timer Pointer to output the handle of the created timer to. - * @param reset_type Type of reset to perform on the timer. - */ -Result svcCreateTimer(Handle* timer, ResetType reset_type); - -/** - * @brief Sets a timer. - * @param timer Handle of the timer to set. - * @param initial Initial value of the timer. - * @param interval Interval of the timer. - */ -Result svcSetTimer(Handle timer, s64 initial, s64 interval); - -/** - * @brief Cancels a timer. - * @param timer Handle of the timer to cancel. - */ -Result svcCancelTimer(Handle timer); - -/** - * @brief Clears a timer. - * @param timer Handle of the timer to clear. - */ -Result svcClearTimer(Handle timer); - -/** - * @brief Gets the current system tick. - * @return The current system tick. - */ -u64 svcGetSystemTick(void); -///@} - -///@name System -///@{ -/** - * @brief Closes a handle. - * @param handle Handle to close. - */ -Result svcCloseHandle(Handle handle); - -/** - * @brief Duplicates a handle. - * @param[out] out Pointer to output the duplicated handle to. - * @param original Handle to duplicate. - */ -Result svcDuplicateHandle(Handle* out, Handle original); - -/** - * @brief Gets a handle info. - * @param[out] out Pointer to output the handle info to. - * @param handle Handle to get the info for. - * @param param Parameter clarifying the handle info type. - */ -Result svcGetHandleInfo(s64* out, Handle handle, u32 param); - -/** - * @brief Gets the system info. - * @param[out] out Pointer to output the system info to. - * @param type Type of system info to retrieve. - * @param param Parameter clarifying the system info type. - */ -Result svcGetSystemInfo(s64* out, u32 type, s32 param); - -/** - * @brief Sets the current kernel state. - * @param type Type of state to set (the other parameters depend on it). - */ -Result svcKernelSetState(u32 type, ...); -///@} - - -///@name Debugging -///@{ -/** - * @brief Breaks execution. - * @param breakReason Reason for breaking. - */ -void svcBreak(UserBreakType breakReason); - -/** - * @brief Breaks execution (LOAD_RO and UNLOAD_RO). - * @param breakReason Debug reason for breaking. - * @param croInfo Library information. - * @param croInfoSize Size of the above structure. - */ -void svcBreakRO(UserBreakType breakReason, const void* croInfo, u32 croInfoSize) __asm__("svcBreak"); - -/** - * @brief Outputs a debug string. - * @param str String to output. - * @param length Length of the string to output, needs to be positive. - */ -Result svcOutputDebugString(const char* str, s32 length); -/** - * @brief Creates a debug handle for an active process. - * @param[out] debug Pointer to output the created debug handle to. - * @param processId ID of the process to debug. - */ -Result svcDebugActiveProcess(Handle* debug, u32 processId); - -/** - * @brief Breaks a debugged process. - * @param debug Debug handle of the process. - */ -Result svcBreakDebugProcess(Handle debug); - -/** - * @brief Terminates a debugged process. - * @param debug Debug handle of the process. - */ -Result svcTerminateDebugProcess(Handle debug); - -/** - * @brief Gets the current debug event of a debugged process. - * @param[out] info Pointer to output the debug event information to. - * @param debug Debug handle of the process. - */ -Result svcGetProcessDebugEvent(DebugEventInfo* info, Handle debug); - -/** - * @brief Continues the current debug event of a debugged process (not necessarily the same as @ref svcGetProcessDebugEvent). - * @param debug Debug handle of the process. - * @param flags Flags to continue with, see @ref DebugFlags. - */ -Result svcContinueDebugEvent(Handle debug, DebugFlags flags); - -/** - * @brief Fetches the saved registers of a thread, either inactive or awaiting @ref svcContinueDebugEvent, belonging to a debugged process. - * @param[out] context Values of the registers to fetch, see @ref ThreadContext. - * @param debug Debug handle of the parent process. - * @param threadId ID of the thread to fetch the saved registers of. - * @param controlFlags Which registers to fetch, see @ref ThreadContextControlFlags. - */ -Result svcGetDebugThreadContext(ThreadContext* context, Handle debug, u32 threadId, ThreadContextControlFlags controlFlags); - -/** - * @brief Updates the saved registers of a thread, either inactive or awaiting @ref svcContinueDebugEvent, belonging to a debugged process. - * @param debug Debug handle of the parent process. - * @param threadId ID of the thread to update the saved registers of. - * @param context Values of the registers to update, see @ref ThreadContext. - * @param controlFlags Which registers to update, see @ref ThreadContextControlFlags. - */ -Result svcSetDebugThreadContext(Handle debug, u32 threadId, ThreadContext* context, ThreadContextControlFlags controlFlags); - -/** - * @brief Queries memory information of a debugged process. - * @param[out] info Pointer to output memory info to. - * @param[out] out Pointer to output page info to. - * @param debug Debug handle of the process to query memory from. - * @param addr Virtual memory address to query. - */ -Result svcQueryDebugProcessMemory(MemInfo* info, PageInfo* out, Handle debug, u32 addr); - -/** - * @brief Reads from a debugged process's memory. - * @param buffer Buffer to read data to. - * @param debug Debug handle of the process. - * @param addr Address to read from. - * @param size Size of the memory to read. - */ -Result svcReadProcessMemory(void* buffer, Handle debug, u32 addr, u32 size); - -/** - * @brief Writes to a debugged process's memory. - * @param debug Debug handle of the process. - * @param buffer Buffer to write data from. - * @param addr Address to write to. - * @param size Size of the memory to write. - */ -Result svcWriteProcessMemory(Handle debug, const void* buffer, u32 addr, u32 size); - -/** - * @brief Sets an hardware breakpoint or watchpoint. This is an interface to the BRP/WRP registers, see http://infocenter.arm.com/help/topic/com.arm.doc.ddi0360f/CEGEBGFC.html . - * @param registerId range 0..5 = breakpoints (BRP0-5), 0x100..0x101 = watchpoints (WRP0-1). The previous stop point for the register is disabled. - * @param control Value of the control regiser. - * @param value Value of the value register: either and address (if bit21 of control is clear) or the debug handle of a process to fetch the context ID of. - */ -Result svcSetHardwareBreakPoint(s32 registerId, u32 control, u32 value); - -/** - * @brief Gets a debugged thread's parameter. - * @param[out] unused Unused. - * @param[out] out Output value. - * @param debug Debug handle of the process. - * @param threadId ID of the thread - * @param parameter Parameter to fetch, see @ref DebugThreadParameter. - */ -Result svcGetDebugThreadParam(s64* unused, u32* out, Handle debug, u32 threadId, DebugThreadParameter parameter); - -///@} - -/** - * @brief Executes a function in supervisor mode. - * @param callback Function to execute. - */ -Result svcBackdoor(s32 (*callback)(void)); - -/// Stop point, does nothing if the process is not attached (as opposed to 'bkpt' instructions) -#define SVC_STOP_POINT __asm__ volatile("svc 0xFF"); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/Includes/ctrulib/synchronization.h b/Includes/ctrulib/synchronization.h deleted file mode 100644 index c7aed21..0000000 --- a/Includes/ctrulib/synchronization.h +++ /dev/null @@ -1,171 +0,0 @@ -/** - * @file synchronization.h - * @brief Provides synchronization locks. - */ -#pragma once -#ifdef __cplusplus -extern "C" { -#endif -#include -#include -#include - -/// A light lock. -typedef _LOCK_T LightLock; - -/// A recursive lock. -typedef _LOCK_RECURSIVE_T RecursiveLock; - -/// A light event. -typedef struct -{ - s32 state; ///< State of the event: -2=cleared sticky, -1=cleared oneshot, 0=signaled oneshot, 1=signaled sticky - LightLock lock; ///< Lock used for sticky timer operation -} LightEvent; - -/// Performs a Data Synchronization Barrier operation. -static inline void __dsb(void) -{ - __asm__ __volatile__("mcr p15, 0, %[val], c7, c10, 4" :: [val] "r" (0) : "memory"); -} - -/// Performs a clrex operation. -static inline void __clrex(void) -{ - __asm__ __volatile__("clrex" ::: "memory"); -} - -/** - * @brief Performs a ldrex operation. - * @param addr Address to perform the operation on. - * @return The resulting value. - */ -static inline s32 __ldrex(s32* addr) -{ - s32 val; - __asm__ __volatile__("ldrex %[val], %[addr]" : [val] "=r" (val) : [addr] "Q" (*addr)); - return val; -} - -/** - * @brief Performs a strex operation. - * @param addr Address to perform the operation on. - * @param val Value to store. - * @return Whether the operation was successful. - */ -static inline bool __strex(s32* addr, s32 val) -{ - bool res; - __asm__ __volatile__("strex %[res], %[val], %[addr]" : [res] "=&r" (res) : [val] "r" (val), [addr] "Q" (*addr)); - return res; -} - -/// Performs an atomic pre-increment operation. -#define AtomicIncrement(ptr) __atomic_add_fetch((u32*)(ptr), 1, __ATOMIC_SEQ_CST) -/// Performs an atomic pre-decrement operation. -#define AtomicDecrement(ptr) __atomic_sub_fetch((u32*)(ptr), 1, __ATOMIC_SEQ_CST) -/// Performs an atomic post-increment operation. -#define AtomicPostIncrement(ptr) __atomic_fetch_add((u32*)(ptr), 1, __ATOMIC_SEQ_CST) -/// Performs an atomic post-decrement operation. -#define AtomicPostDecrement(ptr) __atomic_fetch_sub((u32*)(ptr), 1, __ATOMIC_SEQ_CST) -/// Performs an atomic swap operation. -#define AtomicSwap(ptr, value) __atomic_exchange_n((u32*)(ptr), (value), __ATOMIC_SEQ_CST) - -/** - * @brief Retrieves the synchronization subsystem's address arbiter handle. - * @return The synchronization subsystem's address arbiter handle. - */ -Handle __sync_get_arbiter(void); - -/** - * @brief Initializes a light lock. - * @param lock Pointer to the lock. - */ -void LightLock_Init(LightLock* lock); - -/** - * @brief Locks a light lock. - * @param lock Pointer to the lock. - */ -void LightLock_Lock(LightLock* lock); - -bool LightLock_IsLocked(LightLock *lock); - -/** - * @brief Attempts to lock a light lock. - * @param lock Pointer to the lock. - * @return Zero on success, non-zero on failure. - */ -int LightLock_TryLock(LightLock* lock); - -/** - * @brief Unlocks a light lock. - * @param lock Pointer to the lock. - */ -void LightLock_Unlock(LightLock* lock); - -/** - * @brief Initializes a recursive lock. - * @param lock Pointer to the lock. - */ -void RecursiveLock_Init(RecursiveLock* lock); - -/** - * @brief Locks a recursive lock. - * @param lock Pointer to the lock. - */ -void RecursiveLock_Lock(RecursiveLock* lock); - -/** - * @brief Attempts to lock a recursive lock. - * @param lock Pointer to the lock. - * @return Zero on success, non-zero on failure. - */ -int RecursiveLock_TryLock(RecursiveLock* lock); - -/** - * @brief Unlocks a recursive lock. - * @param lock Pointer to the lock. - */ -void RecursiveLock_Unlock(RecursiveLock* lock); - -/** - * @brief Initializes a light event. - * @param event Pointer to the event. - * @param reset_type Type of reset the event uses (RESET_ONESHOT/RESET_STICKY). - */ -void LightEvent_Init(LightEvent* event, ResetType reset_type); - -/** - * @brief Clears a light event. - * @param event Pointer to the event. - */ -void LightEvent_Clear(LightEvent* event); - -/** - * @brief Wakes up threads waiting on a sticky light event without signaling it. If the event had been signaled before, it is cleared instead. - * @param event Pointer to the event. - */ -void LightEvent_Pulse(LightEvent* event); - -/** - * @brief Signals a light event, waking up threads waiting on it. - * @param event Pointer to the event. - */ -void LightEvent_Signal(LightEvent* event); - -/** - * @brief Attempts to wait on a light event. - * @param event Pointer to the event. - * @return Non-zero if the event was signaled, zero otherwise. - */ -int LightEvent_TryWait(LightEvent* event); - -/** - * @brief Waits on a light event. - * @param event Pointer to the event. - */ -void LightEvent_Wait(LightEvent* event); -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/Includes/ctrulib/sys/ioctl.h b/Includes/ctrulib/sys/ioctl.h deleted file mode 100644 index bbd3f83..0000000 --- a/Includes/ctrulib/sys/ioctl.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#define FIONBIO 1 - -#ifdef __cplusplus -extern "C" { -#endif - - int ioctl(int fd, int request, ...); - -#ifdef __cplusplus -} -#endif diff --git a/Includes/ctrulib/sys/select.h b/Includes/ctrulib/sys/select.h deleted file mode 100644 index f6f6154..0000000 --- a/Includes/ctrulib/sys/select.h +++ /dev/null @@ -1 +0,0 @@ -#include_next \ No newline at end of file diff --git a/Includes/ctrulib/sys/socket.h b/Includes/ctrulib/sys/socket.h deleted file mode 100644 index f117153..0000000 --- a/Includes/ctrulib/sys/socket.h +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once - -#include -#include - -#define SOL_SOCKET 0xFFFF - -#define PF_UNSPEC 0 -#define PF_INET 2 -#define PF_INET6 23 - -#define AF_UNSPEC PF_UNSPEC -#define AF_INET PF_INET -#define AF_INET6 PF_INET6 - -#define SOCK_STREAM 1 -#define SOCK_DGRAM 2 - -// any flags > 0x4 causes send/recv to return EOPNOTSUPP -#define MSG_OOB 0x0001 -#define MSG_PEEK 0x0002 -#define MSG_DONTWAIT 0x0004 -#define MSG_DONTROUTE 0x0000 // ??? -#define MSG_WAITALL 0x0000 // ??? -#define MSG_MORE 0x0000 // ??? -#define MSG_NOSIGNAL 0x0000 // there are no signals - -#define SHUT_RD 0 -#define SHUT_WR 1 -#define SHUT_RDWR 2 - -/* - * SOL_SOCKET options - */ -#define SO_REUSEADDR 0x0004 // reuse address -#define SO_LINGER 0x0080 // linger (no effect?) -#define SO_OOBINLINE 0x0100 // out-of-band data inline (no effect?) -#define SO_SNDBUF 0x1001 // send buffer size -#define SO_RCVBUF 0x1002 // receive buffer size -#define SO_SNDLOWAT 0x1003 // send low-water mark (no effect?) -#define SO_RCVLOWAT 0x1004 // receive low-water mark -#define SO_TYPE 0x1008 // get socket type -#define SO_ERROR 0x1009 // get socket error - -typedef uint32_t socklen_t; -typedef uint16_t sa_family_t; - -struct sockaddr { - sa_family_t sa_family; - char sa_data[]; -}; - -// biggest size on 3ds is 0x1C (sockaddr_in6) -struct sockaddr_storage { - sa_family_t ss_family; - char __ss_padding[26]; -}; - -struct linger { - int l_onoff; - int l_linger; -}; - -#ifdef __cplusplus -extern "C" { -#endif - - int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); - int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); - int closesocket(int sockfd); - int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); - int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen); - int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen); - int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen); - int listen(int sockfd, int backlog); - ssize_t recv(int sockfd, void *buf, size_t len, int flags); - ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); - ssize_t send(int sockfd, const void *buf, size_t len, int flags); - ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); - int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen); - int shutdown(int sockfd, int how); - int socket(int domain, int type, int protocol); - int sockatmark(int sockfd); - -#ifdef __cplusplus -} -#endif diff --git a/Includes/ctrulib/thread.h b/Includes/ctrulib/thread.h deleted file mode 100644 index d8b5791..0000000 --- a/Includes/ctrulib/thread.h +++ /dev/null @@ -1,140 +0,0 @@ -/** - * @file thread.h - * @brief Provides functions to use threads. - */ -#pragma once -#ifdef __cplusplus -extern "C" { -#endif -#include "../types.h" -#include "result.h" -#include "synchronization.h" -#include "svc.h" -#include "errf.h" -#include - -/// Makes the exception handler reuse the stack of the faulting thread as-is -#define RUN_HANDLER_ON_FAULTING_STACK ((void*)1) - -/// Makes the exception handler push the exception data on its stack -#define WRITE_DATA_TO_HANDLER_STACK NULL - -/// Makes the exception handler push the exception data on the stack of the faulting thread -#define WRITE_DATA_TO_FAULTING_STACK ((ERRF_ExceptionData*)1) - - -typedef struct -{ - Handle handle; - ThreadFunc ep; - void* arg; - int rc; - bool detached, finished; - struct _reent reent; - void* stacktop; - u32 renderCtx[2]; -} Thread_tag; - -/// libctru thread handle type -typedef Thread_tag* Thread; - -/// Exception handler type, necessarily an ARM function that does not return. -typedef void (*ExceptionHandler)(ERRF_ExceptionInfo* excep, CpuRegisters* regs); - - -/** - * @brief Creates a new libctru thread. - * @param entrypoint The function that will be called first upon thread creation - * @param arg The argument passed to @p entrypoint - * @param stack_size The size of the stack that will be allocated for the thread (will be rounded to a multiple of 8 bytes) - * @param prio Low values gives the thread higher priority. - * For userland apps, this has to be within the range [0x18;0x3F]. - * The main thread usually has a priority of 0x30, but not always. Use svcGetThreadPriority() if you need - * to create a thread with a priority that is explicitly greater or smaller than that of the main thread. - * @param affinity The ID of the processor the thread should be ran on. Processor IDs are labeled starting from 0. - * On Old3DS it must be <2, and on New3DS it must be <4. - * Pass -1 to execute the thread on all CPUs and -2 to execute the thread on the default CPU (read from the Exheader). - * @param detached When set to true, the thread is automatically freed when it finishes. - * @return The libctru thread handle on success, NULL on failure. - * - * - Processor #0 is the application core. It is always possible to create a thread on this core. - * - Processor #1 is the system core. If APT_SetAppCpuTimeLimit is used, it is possible to create a single thread on this core. - * - Processor #2 is New3DS exclusive. Normal applications can create threads on this core if the exheader kernel flags bitmask has 0x2000 set. - * - Processor #3 is New3DS exclusive. Normal applications cannot create threads on this core. - * - Processes in the BASE memory region can always create threads on processors #2 and #3. - * - * @note Default exit code of a thread is 0. - * @warning @ref svcExitThread should never be called from the thread, use @ref threadExit instead. - */ -Thread threadCreate(ThreadFunc entrypoint, void* arg, size_t stack_size, int prio, int affinity, bool detached); -/** - * @brief Retrieves the OS thread handle of a libctru thread. - * @param thread libctru thread handle - * @return OS thread handle - */ -Handle threadGetHandle(Thread thread); - -/** - * @brief Retrieves the exit code of a finished libctru thread. - * @param thread libctru thread handle - * @return Exit code - */ -int threadGetExitCode(Thread thread); - -/** - * @brief Frees a finished libctru thread. - * @param thread libctru thread handle - */ -void threadFree(Thread thread); - -/** - * @brief Waits for a libctru thread to finish (or returns immediately if it is already finished). - * @param thread libctru thread handle - * @param timeout_ns Timeout in nanoseconds. Pass U64_MAX if a timeout isn't desired - */ -Result threadJoin(Thread thread, u64 timeout_ns); - - /** - * @brief Changes a thread's status from attached to detached. - * @param thread libctru thread handle - */ -void threadDetach(Thread thread); - -/** - * @brief Retrieves the libctru thread handle of the current thread. - * @return libctru thread handle of the current thread, or NULL for the main thread - */ -Thread threadGetCurrent(void); - -/** - * @brief Exits the current libctru thread with an exit code (not usable from the main thread). - * @param rc Exit code - */ -void threadExit(int rc) __attribute__((noreturn)); - -/** - * @brief Sets the exception handler for the current thread. Called from the main thread, this sets the default handler. - * @param handler The exception handler, necessarily an ARM function that does not return - * @param stack_top A pointer to the top of the stack that will be used by the handler. See also @ref RUN_HANDLER_ON_FAULTING_STACK - * @param exception_data A pointer to the buffer that will contain the exception data. - See also @ref WRITE_DATA_TO_HANDLER_STACK and @ref WRITE_DATA_TO_FAULTING_STACK - * - * To have CPU exceptions reported through this mechanism, it is normally necessary that UNITINFO is set to a non-zero value when Kernel11 starts, - * and this mechanism is also controlled by @ref svcKernelSetState type 6, see 3dbrew. - * - * VFP exceptions are always reported this way even if the process is being debugged using the debug SVCs. - * - * The current thread need not be a libctru thread. - */ -static inline void threadOnException(ExceptionHandler handler, void* stack_top, ERRF_ExceptionData* exception_data) -{ - u8* tls = (u8*)getThreadLocalStorage(); - - *(u32*)(tls + 0x40) = (u32)handler; - *(u32*)(tls + 0x44) = (u32)stack_top; - *(u32*)(tls + 0x48) = (u32)exception_data; -} - -#ifdef __cplusplus -} -#endif diff --git a/Includes/ctrulib/util/rbtree.h b/Includes/ctrulib/util/rbtree.h deleted file mode 100644 index 08778b9..0000000 --- a/Includes/ctrulib/util/rbtree.h +++ /dev/null @@ -1,149 +0,0 @@ -/** - * @file rbtree.h - * @brief Red-black trees. - */ -#pragma once - -#include -#include - -/// Retrieves an rbtree item. -#define rbtree_item(ptr, type, member) \ - ((type*)(((char*)ptr) - offsetof(type, member))) - -typedef struct rbtree rbtree_t; ///< rbtree type. -typedef struct rbtree_node rbtree_node_t; ///< rbtree node type. - -typedef void (*rbtree_node_destructor_t)(rbtree_node_t *Node); ///< rbtree node destructor. -typedef int (*rbtree_node_comparator_t)(const rbtree_node_t *lhs, - const rbtree_node_t *rhs); ///< rbtree node comparator. - -/// An rbtree node. -struct rbtree_node -{ - uintptr_t parent_color; ///< Parent color. - rbtree_node_t *child[2]; ///< Node children. -}; - -/// An rbtree. -struct rbtree -{ - rbtree_node_t *root; ///< Root node. - rbtree_node_comparator_t comparator; ///< Node comparator. - size_t size; ///< Size. -}; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Initializes an rbtree. - * @param tree Pointer to the tree. - * @param comparator Comparator to use. - */ -void -rbtree_init(rbtree_t *tree, - rbtree_node_comparator_t comparator); - -/** - * @brief Gets whether an rbtree is empty - * @param tree Pointer to the tree. - * @return A non-zero value if the tree is not empty. - */ -int -rbtree_empty(const rbtree_t *tree); - -/** - * @brief Gets the size of an rbtree. - * @param tree Pointer to the tree. - */ -size_t -rbtree_size(const rbtree_t *tree); - -/** - * @brief Inserts a node into an rbtree. - * @param tree Pointer to the tree. - * @param node Pointer to the node. - * @return The inserted node. - */ -__attribute__((warn_unused_result)) -rbtree_node_t* -rbtree_insert(rbtree_t *tree, - rbtree_node_t *node); - -/** - * @brief Inserts multiple nodes into an rbtree. - * @param tree Pointer to the tree. - * @param node Pointer to the nodes. - */ -void -rbtree_insert_multi(rbtree_t *tree, - rbtree_node_t *node); - -/** - * @brief Finds a node within an rbtree. - * @param tree Pointer to the tree. - * @param node Pointer to the node. - * @return The located node. - */ -rbtree_node_t* -rbtree_find(const rbtree_t *tree, - const rbtree_node_t *node); - -/** - * @brief Gets the minimum node of an rbtree. - * @param tree Pointer to the tree. - * @return The minimum node. - */ -rbtree_node_t* -rbtree_min(const rbtree_t *tree); - -/** - * @brief Gets the maximum node of an rbtree. - * @param tree Pointer to the tree. - * @return The maximum node. - */ -rbtree_node_t* -rbtree_max(const rbtree_t *tree); - -/** - * @brief Gets the next node from an rbtree node. - * @param node Pointer to the node. - * @return The next node. - */ -rbtree_node_t* -rbtree_node_next(const rbtree_node_t *node); - -/** - * @brief Gets the previous node from an rbtree node. - * @param node Pointer to the node. - * @return The previous node. - */ -rbtree_node_t* -rbtree_node_prev(const rbtree_node_t *node); - -/** - * @brief Removes a node from an rbtree. - * @param tree Pointer to the tree. - * @param node Pointer to the node. - * @param destructor Destructor to use when removing the node. - * @return The removed node. - */ -rbtree_node_t* -rbtree_remove(rbtree_t *tree, - rbtree_node_t *node, - rbtree_node_destructor_t destructor); - -/** - * @brief Clears an rbtree. - * @param tree Pointer to the tree. - * @param destructor Destructor to use when clearing the tree's nodes. - */ -void -rbtree_clear(rbtree_t *tree, - rbtree_node_destructor_t destructor); - -#ifdef __cplusplus -} -#endif diff --git a/Includes/ctrulib/util/utf.h b/Includes/ctrulib/util/utf.h deleted file mode 100644 index 34a93c3..0000000 --- a/Includes/ctrulib/util/utf.h +++ /dev/null @@ -1,160 +0,0 @@ -/** - * @file utf.h - * @brief UTF conversion functions. - */ -#pragma once -#ifdef __cplusplus -extern "C" { -#endif -#include -#include - -/** Convert a UTF-8 sequence into a UTF-32 codepoint - * - * @param[out] out Output codepoint - * @param[in] in Input sequence - * - * @returns number of input code units consumed - * @returns -1 for error - */ -ssize_t decode_utf8 (uint32_t *out, const uint8_t *in); - -/** Convert a UTF-16 sequence into a UTF-32 codepoint - * - * @param[out] out Output codepoint - * @param[in] in Input sequence - * - * @returns number of input code units consumed - * @returns -1 for error - */ -ssize_t decode_utf16(uint32_t *out, const uint16_t *in); - -/** Convert a UTF-32 codepoint into a UTF-8 sequence - * - * @param[out] out Output sequence - * @param[in] in Input codepoint - * - * @returns number of output code units produced - * @returns -1 for error - * - * @note \a out must be able to store 4 code units - */ -ssize_t encode_utf8 (uint8_t *out, uint32_t in); - -/** Convert a UTF-32 codepoint into a UTF-16 sequence - * - * @param[out] out Output sequence - * @param[in] in Input codepoint - * - * @returns number of output code units produced - * @returns -1 for error - * - * @note \a out must be able to store 2 code units - */ -ssize_t encode_utf16(uint16_t *out, uint32_t in); - -/** Convert a UTF-8 sequence into a UTF-16 sequence - * - * Fills the output buffer up to \a len code units. - * Returns the number of code units that the input would produce; - * if it returns greater than \a len, the output has been - * truncated. - * - * @param[out] out Output sequence - * @param[in] in Input sequence (null-terminated) - * @param[in] len Output length - * - * @returns number of output code units produced - * @returns -1 for error - * - * @note \a out is not null-terminated - */ -ssize_t utf8_to_utf16(uint16_t *out, const uint8_t *in, size_t len); - -/** Convert a UTF-8 sequence into a UTF-32 sequence - * - * Fills the output buffer up to \a len code units. - * Returns the number of code units that the input would produce; - * if it returns greater than \a len, the output has been - * truncated. - * - * @param[out] out Output sequence - * @param[in] in Input sequence (null-terminated) - * @param[in] len Output length - * - * @returns number of output code units produced - * @returns -1 for error - * - * @note \a out is not null-terminated - */ -ssize_t utf8_to_utf32(uint32_t *out, const uint8_t *in, size_t len); - -/** Convert a UTF-16 sequence into a UTF-8 sequence - * - * Fills the output buffer up to \a len code units. - * Returns the number of code units that the input would produce; - * if it returns greater than \a len, the output has been - * truncated. - * - * @param[out] out Output sequence - * @param[in] in Input sequence (null-terminated) - * @param[in] len Output length - * - * @returns number of output code units produced - * @returns -1 for error - * - * @note \a out is not null-terminated - */ -ssize_t utf16_to_utf8(uint8_t *out, const uint16_t *in, size_t len); - -/** Convert a UTF-16 sequence into a UTF-32 sequence - * - * Fills the output buffer up to \a len code units. - * Returns the number of code units that the input would produce; - * if it returns greater than \a len, the output has been - * truncated. - * - * @param[out] out Output sequence - * @param[in] in Input sequence (null-terminated) - * @param[in] len Output length - * - * @returns number of output code units produced - * @returns -1 for error - * - * @note \a out is not null-terminated - */ -ssize_t utf16_to_utf32(uint32_t *out, const uint16_t *in, size_t len); - -/** Convert a UTF-32 sequence into a UTF-8 sequence - * - * Fills the output buffer up to \a len code units. - * Returns the number of code units that the input would produce; - * if it returns greater than \a len, the output has been - * truncated. - * - * @param[out] out Output sequence - * @param[in] in Input sequence (null-terminated) - * @param[in] len Output length - * - * @returns number of output code units produced - * @returns -1 for error - * - * @note \a out is not null-terminated - */ -ssize_t utf32_to_utf8(uint8_t *out, const uint32_t *in, size_t len); - -/** Convert a UTF-32 sequence into a UTF-16 sequence - * - * @param[out] out Output sequence - * @param[in] in Input sequence (null-terminated) - * @param[in] len Output length - * - * @returns number of output code units produced - * @returns -1 for error - * - * @note \a out is not null-terminated - */ -ssize_t utf32_to_utf16(uint16_t *out, const uint32_t *in, size_t len); -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/Includes/main.hpp b/Includes/main.hpp index 717fa35..c6576ec 100644 --- a/Includes/main.hpp +++ b/Includes/main.hpp @@ -6,7 +6,7 @@ #define TOP_DIR "/OnionFS" #define NUMBER_FILE_OP 9 #define MAJOR_VERSION 2 -#define MINOR_VERSION 0 +#define MINOR_VERSION 1 #define REVISION_VERSION 0 #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) diff --git a/Includes/ptm.h b/Includes/ptm.h deleted file mode 100644 index ce39312..0000000 --- a/Includes/ptm.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#ifdef __cplusplus -extern "C" { -#endif -Result ptmSysmInit(void); -Result PTMSYSM_RebootAsync(u64 timeout); -void ptmSysmExit(void); -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/Includes/types.h b/Includes/types.h index c1fe36f..a97eb4f 100644 --- a/Includes/types.h +++ b/Includes/types.h @@ -3,8 +3,6 @@ * @brief Various system types. */ #pragma once -#ifndef TYPES_H -#define TYPES_H #include #include @@ -60,24 +58,5 @@ typedef void (*voidfn)(void); /// Flags a function as deprecated. #define DEPRECATED #endif - -/// Structure representing CPU registers -typedef struct { - u32 r[13]; ///< r0-r12. - u32 sp; ///< sp. - u32 lr; ///< lr. - u32 pc; ///< pc. May need to be adjusted. - u32 cpsr; ///< cpsr. -} CpuRegisters; - -/// Structure representing FPU registers -typedef struct { - union{ - double d[16]; ///< d0-d15. - float f[32]; ///< f0-f31. - }; - u32 fpscr; ///< fpscr. - u32 fpexc; ///< fpexc. -} FpuRegisters; - -#endif \ No newline at end of file +#define NAKED __attribute__((naked)) +#define NORETURN __attribute__((noreturn)) \ No newline at end of file diff --git a/Lib/libCTRPluginFramework.a b/Lib/libCTRPluginFramework.a deleted file mode 100644 index 52426ee8c6752b265a2c25c69e1cb14207c39cab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1541368 zcmeFa4U{C;RVEnyqkjptT5U;~1~(w@2#&EbvNE%>KzLO@S>36w>Plx;tA)o9%F2wY zN_GA@f2ymDXAwp)hP4I(0?e)%i9Ozhvv_8`gLj8nm|4xP+4b2ooa1xw+4TWt(T^L% zz=C&o2Fwlz?RW2cFXBaHyokuG>Xu}lbDeL%OgXhG1E$fCq&L^xBZ};=h9=1-X z=U+Z$op`&SKi{`bgr1WpK4KZ4yH8ptP0s_rZk>#K-i7Zs`>CC?PCk_p&-Z@ZI{CHo z{J$X{*fBaSJwxs9R)~ws6d4BKn)@?W8x&7qh*3{28 ze#yE$>G`(LS-0QF=X)+#xBqo`K85x*J^y0gy8STEziV5!e~mnMeCMaE#OHe+vhFZF z+fQ3}9Od&I%5&J~zZh9}e62md_a5txzk$!4-}^D^raqtex7M9+$MgAztvjc9?z-(c zEAe^gZtJe2c(y-d-8Jp=v4^d@Zq)OKAG7XC`P_ZtVe3eqm;aS@ciQLI9<%QL+sC@+ zi3>OW=~&i1(>@=4$hv2i=byb|-SZ#N^L0P+5$kPx{=d&!Uw4C_d!PP{bwi%#&sg{B z&wssX-Fwu}zkbuYS9?x<-K$pMS^T7RN`G3r)~WFGk-xM~y$G~l<4e}*@bld#t zK$xDV9utrAigkvbonpG@+U?evqj-M2Vx2KPpM1zV6ZQP!d#p2QpMUyU>kK`=_De_e zeBm?JnY7QVpSRA0pEq;XnOUE&qOT0kJC2{R0?$2S01q*nC1E0zV*Q8KW9Dg zn>q3P?_abYFg?F>yY;~DebRd1jX$;?coS{+$DpULylOr0@9wr9_>0e55B${`>%rrX zSr6Xwm)3)K{JQnvJsIo4GcQ^XKJ*dm!EgAgc+S0GJxI^PpRpc%L_Uu`Z9SO%UGdCc zupU&;cdu9vPWzPCtOx)0Ir=vEdta~~{6X~Z51!fRuJ!88?M+-tqTRXba$j~cs`L9gKsho$PJnq%9m*RIyw(Wuqk8J3KQa~oZSwci?*_Kbj; zazYpp)+Hg?zRt*(eS;^i*7ZePF< zG~pVWC4YI;Y7YxFm(1zPol>dO=~OS)Muk1MG3pJuFW~6nD*Imt|GhYxZ6cT z#=;HU;kbjwal0ckoGsEzfGP?oQOOJSZnN#0lU&$w8oe(1dF-ACJtQQZb%xDOV-XF~ z+C!o{&d#vUC?d1Upw%0+MhDcS7o$k6P-_faw`=FlyCbH*t?~A@J3!NJCE?^&2K8&D z>cva7(Y)g{_V;bu&TiF*t%frk4bZ&hMr~xK(XiYop@$kJ>N&!5^2@z; zZ&0c&IZ2t>Hsw}37;d9&jwI8h9E+4;6_iC}7AS6F%PbITrM2(2LlsTRbD@gS<{|nG z#5qQF-`qxRrEsY?YHc6P*eDVGV9F?08}<67%IX&5NXjt}HY%H)1zl~r`=cwZ=4iLX znA1}WHJhnWB8OgI(6O19acS}>%~EeP>UC0q+qG-;{t^#}VSLKDwO-?DJjnd!;2;^Q zaJk#|lJZ%bX!NKy@VbF`Umm>Ao_E$AaP2nIaa!G>I~bLp0Gp(5rM*iFjsrB2bGVQd|fu&0=ztncSO_AayG|U2r*L&!hcrxg(`NfDLWzj92aw@1)X)SDy z2Ok>uTEnEG&DX9TEVai;V1iB)eGK?OnU#wi~^UyACB6<_LirC8X(?h4OF%L}-@U zb>M|7b%q8bH)@r1c)N&ZkjkNQcQ~qd8?ov!pL1t3wFBt82E8scYFApLT~?-~t5SZm zHEO#{c~+ss71SR!m?&mbywr*@Q-zkkePh#)XH9-N5?GTDn7h!zS|DzOXs|?kDPb4N z!zWwA))oY`bcx&f%R_e)`UtmQ=QTCvTxY=#(G+JGj(!R4A`+2`io>K6!?2^rnO}s% zP#6}ao>De6SCE!sDNaMHO%2P3Ai|?6!mQ)$sPdn+2~y^tNQoW=#c3n-*>#HP$0s&> zis{G4!V0VtWSfcA$w5~-C5oLXkKE31xi^O5IUNtkFSoHrkrKF2bvr%i?xn^(X2jI1 z4%6jw=(;R9H>o;lGs>1)vk6AiHJp8OvN?Qh(ze^-E0i*)ILXf+WwCOf4^}93>+zzQ z4-3WPFg0+JIO!*wOAsb~$RZX?)q1nlE47S5pbw30?$P34M{b8lPHY-5mMsKqo}PSI zyMRT}6XW4%u`z1xVaX=fMhRKic6m4*Mk>)+E7z=ovzEjm#AYp(x#fCy$*s99%x<9tUg6I+l0s>&D4lhcN>cQU6N>0b$m*3$*h6GL46(GOE2oYG4*_joXzw~xC5Be@G(QKQAHn}fsk}?7X zn01cElzB7-n05L-n%rlt{*mM!M{Rm1sfi?snus|IsXdYwBAKI}Poo_}wYlY97aJv` z&E9IeSI2JbEJ}W(4Tz0>9hv+}Z%otS(WYM*j(TJ4lh2fD)woU1$rf@mCd(F0k)4|L zTI2GpsT-TRc+oxB>eUC$nVFA?vG^&^I;@gYo|Rqbx&+#&feNP(qry3SRc6kRYUrz; zW*KEvIkJCAZcXZ^o0L}^v-4Uzj?;NS_FQ=gg*_}<8Z8+9#K<;2N|q#)`u>{R-GK?0 z*{H_HU}oCuKmqD%dmUSqi+eNikmSxNR(kz$o3bIo9RJk8H}kbH%sE66tQg{-+Z(qRPOf2qrm=5JdT|Kl9E*Q zZJl^D8aAcD00yzM)F-*Iu<_VkBpdED!yY=!9!!|bD@u|E$uAd8y~sRt$R~*2H(Gf;37%SaK-A?Q(H8IVgRB+3GS?fz1Y*w${XU z;YOF3j~b*Z@yK{8p>Ux$y6PT4Tw_9x5*QUo%+geW!02=~<)TTNPzl>NDB(E4LFOGN zHb{_q&1`JzgUsGCk$o%^#&-V-8SN!?pPgA8UWH{N1oRkFZJFpi*mFFfou%)ay&4~6 zP^{l9`^bcgVGQF+!k!b9xnA$W^kD!34Q-T~NG6PE&xjaD8lgPmNF)T>+BcI*2y~*Y zj9nZ;%w{*ba#-_(qluV%p+;;OMaNK@SVDW-dzw%m!!PJ0OU=eg!DMew-%{Ay+YX;t zinX^76&9OvG}s(TbX-TR&@&vzp}O3pvjd^Jq#U=aHJpgsZS2jj)*Sj3BbO|!v<7@0 z>>yEu@j;6u%&)eD?!?K7Uufg$&#JI)KZzbYOQskj zj=5!>Czkt1wqlq`PCtO-HnhFAFP4Wm6gwQ@aPCZ8BDs;|>VXzgGv#2E zJp6vZ@Vjwo&#K1ca%)3<1{QpSX0xLy)Ixte+y$3_`7bmOdE;`{@1}_9Vgr&#G6_u} z+9idk)g_)6gwybNX{6XwBQBdl=*c>@93W$b9&-a=JtFH-8|8*LqFIhS9coUXL<*J# zFbQmyIIZpSQ$rXpLlc3M*-rTh{@Lw~oHF=!-f>z(XEeqM9jD#8>f(@jsZ<+fZN!q< z7M<0`Y3DKa(vcYJj)7HFU+cqRYlrg@YUNUXuTDq4_DZ=CZ9GU^3)+Ih-aamm&VC_ogo27DusC82q>7yz~NP`GXG zx*d1L-L8*u=+e9d(cLc;F5r}Q%(4ISaMUkidjR`AQHk*`qCx)Sip#h%QUUML&5d_k8*p}jiPN!pBmZ;Qig;I5Q zsFjm3vKg6)z$kaCto}`tS7y1_Kagd^!K{mWiA@F78L}O!$qkXA zgjG9K6C1*2c%cMDX=Ygtb!ZzTE0TbIvIFyvWYXpC^0J*t{(qaYouazA3%%aeI2C{Z zh*={u0POR9S4KD-X=+^t4j7C^(KSN_O+}-?^6TS~OD1SWRxBZ6N-rRkj=-FY(lVGK z613 zJ4J3-cBh0yny9Jhb0bUg5={vjN6nm895ENB(DJg1Hc`RLP&wlHu%k9}23jlSndf4o zIRS2g;nrI4rH0L=Yrs2ExpHt%Y;j z=8+(pbF~fKL=qH9`tgD_C&q@&%KeyG6c*K98F%_pmWruGx%&)6+7xiw31M?`Q!2Q* zplX$)HUtwIRGfv|AGuvxxCD@*_zGtcH>U^y$ySX@NNe#BtOP;%bAbn8k5BiinEQDPH>NyueIS9D8(GT z*&8=@6Rii}0t{fx3czdO5i?G|z=BHb_#`Ppi9OMrhaeUfhcy>^!=|)UFhkn8#o>CZ z-G(!%Dc~CeSZ-K|Nj)%AHQ|TNgNdmo84IL=gTJ;^VDOZd z3QjAXkw7{ckg?YRwC&|+Y778DYD!p2bo8b$7fOdRma4huHx>m9nIOdDF54bUI;tKHGic|DZwO(?s&8^hTizW$avzW<9YfvkW z$v=#7p(Sy$IHI`R>vka|V(Hf_cj48t8@C&v^2#o6Un>vS#+^D9EyhEoM3~=@cC;pP z%x%_(v_h_|wkvxj=yuI3K!$`7S4v2l&SSfRGUlTRW(KKBw~->DM3~qWA5~7R_zbfg zAoB1Wq}I`9sN5B}5RO}%P-X>kLNt!C04xf>$R*O<&@s(DEGLW;lMhTClomLyMZ6SM zt3=Js9*}Gpv%cSh%stVA>ulqmzXz9QODX`Yw`XlsbgEnMIY*J3F*VIe-p>+SkN!Y;38(8C$R2b_XoZlKpDD%Q%thiDOt^)d?aE zoT+Caz?po^sgtUWG8xQekR@IM!`v{DkAUw+@F> z!6?A=HfYouku#xi;o8`nB~f#?%ZnAn_LNdn;mFO0O}!!zuz1E`%zLky+TYFvd8&`jgoJ9`)< z{t5E8^U93s;4nE6J$$W@Xq=A(QR#vtP4g~p5H4mSBWBH8HFUNn?JOV>(oY)#AqS_p zZN&#ul_{@nwM5Z?m_$VCikK7OVhC4HuYJ@;%X;GamRxj!v26-h8+7kWVvEgOQp{Z@ zMmTet(gHH7QY>J^b&~*y>mO{rj0o6LU7U4F&l~S}3MY8(0Gu_X)Xhq&u{Es{^Zt z?bZ&9Wd5+kuZ&X^c9l=sX5lW7T$ZlUf(fU%6U#jAbfm06s_$X4WV_rZ%*5(wvvlZo zk@F<<)%qS?tppp_l&A}YDh{p0shdAd$!Cd@fz zK2x@Cz!oQE)#L>>!`&XJ%iV5y0;OpL2WyxU9-9~)2g4LkNr#*foliY66(XI~Pq>Lq zCptR^cfM?-hVwg1Bl9%}!K!7*wH#atul8eZd<*0=M;O9yaC)S?v(@Rd%QGS}jEhul zmz{IA)d*N@lX?QT8%=?paT+}EX27-Q7ssO><>rsURAt6?nnaX?J{=ZkSHqZ}DLX=( zDmxhR5BsnmCaN4#En{!03-*7h(GzC1u~*{+$t*{=m9g4kxz`({?0$%+9@cm;gwKj} zZCMm5i=~Y&IlU7;CemSQ104#Fv?Ic%Y$Vf7SH!Hn#W#fc+*ZuM=}K9|6=`WPvpI68 z*y~nZ>TZV_E?k6>c7tX{U91ulF4cvc5pzZSRn{(+J-boMFZCf-@X*Tud!4;`*qvtS zUaZ;H-BqI!y0BPXhJKgC@tG_Vl2fLAk6AP$BIQVhi!8JaogNjQJo~TIahZ*Aa+3&3 z)izs!OtcnC+*k;EPPR34!Z-(kCQl72X(g^PCR91b#Pu$Z*=$l^3Hw$G47bRc7l;Z7 zx5$}+LhYkE%UF*PJQg{gfA44+jPCGky5w8Z%%~2(YRJy(gV&)m?7l#wEqaYZaxTb$ zfDE%;S@0)uIV|q=h*2$Pvw`f{vlwB|I0{WfA7YcZkbz2eBQh!k>Lb@W(hMIQd3rr= z=rC&sjJi`Q6|nC?CzDuNhh3n6daDwt-?DS;BbF~{DPyhY9m7{97&@-t{9k-6vMy5s@r?ve`%FF1_BqGbwjo_P1%jqPpdQd6W4 znLce%aw*GDNXR_PD=+qMqw^^>Uqy*cCX|@viwPyhhqwV{=4DBYzYtSav#wL7&q|kU zH=m505DkT7s)}3%+?YLRJ1d7b-z8V1QAb-ia`Q%webd-5VT+xdS+TRq&qQRy#pFp` zb=soRvUmnG-={~^kTR4}CyNwyi(Nkk`b`e);YbN=L!c&& zS>p!ENcLuoBNU}+(dHe^dZspVKU8j%^xM>J2iyJuk0O}W;RmDv^8)f3g4@=G?~kn# zT#X3tA2Her*ol!$PuQ@ygX!b2Or~Qrn+prF5>c2aM;Nd{V2x5~D^B~c>A=@2ysVaR z=50cvh+e4__SnZ&w7ZpH$9MzSo33>UAiP?Mq`@1or?1HqQ4|`=@#acQN$nR|npqw0 zBs4@~S+Xt`q4frtWHheAWsdOs z2Z=S7?!$Fa{4Jr0C(yhV@Km`)Q^n1Z>FqETh-^J7i0b(uWx+@mR+4h%O4EJZW@>%luc5}`2 zwpaHu>M6aCDz{)MdTh>7HUR9-n>H#W+e|0$kV&LgFAtko0dbLZsfb?ZU6QC}U1qVm z?$CW-!wxwx!+Yp<;Gb)8?XueEEo}4~kTHeTq7Ki_A0+$|sHWlVDR+!Gb6OrtPpK>> z(}qo#SC*xVl}$6GUh3tw52ORc)}I-$sO1g73-$K48CcJLeYvUtjSUchUt3IsFKC6i zyuP-$mWUC^;qsL5)tX9wvQGjD*SxAu0A_8i%oR*~m%DxZs}fGtG?ld#1wWB~fKY2! z%4q>B3eZ%7;tCFGHr))o#q!|Nh+TfNGv-ebSPLS-^~-CMXt-93b6Z=fUYPtUF)<7$ zzo}wIl%*ij6gWQfD8goHiJW2(@4(HPrSODQZP958=*;{nNvpg~8|{iSU_@+DQb~r|kCvC-6HZsL&NQ9h#)y>dR^KIre}ue6%VgK-qY&8=eBE~O<+0mn8r1}#_{*V~-9 zY}exQW>s8H&i9aCgX>s0WY`_Fx>p5QWjAI&PL^P~4v{P&RR$#sG67dL`!Nnd8V&Rq zuHbaY!H#)0DC{^p)R>EH^coa%F=h+-9cLRYnhaT38jnW3t`gv)`bL4oEKn6lj0#GE z#M#425Vp-QuTUkFTF&!&&nXB`#ARHkVVX=O9@h0UUT8oIO9wXejS*#2S%u+XVrDa6 zaxhC~M_IG2n_9Kx++^KmZ2xJ|qH{|wrR?rdc8Pe(Lzi*qNzuG8-%K1E$-cbQP+J50 zPfRY+JC;n%+j=nC6i7faC8R@^Zp@`T3KVQsfKs9cb*_Xpk}M`o(wDh|1v22OwD#RL z?0$KO3B_(QraecfbZn-Mlhy+=8$L>WEWS*9%PTy@3=~0b%|lzzsqn6$uhIsR$5a*!bHD+J>82OJ)t7tN|%f zNRe3D%##d8-9No`1eH53ZPCeMQWgU<4mx%cj6+;l$7RUE5|IaM9ISr4Ar6iXuhHxn z!%swy+VeuI?Ar{+s6b@bEI`>Uu#KcHA?>WtaVJ3A_T@4i>a9ZqL&s%|JSzwoL$3kA zINA>arcF^J&Zu!3NHmr%60xx~61&k5A4R+P>yKy~nIdr}zGz&jG$M6$&>$V5v-CiX z;qrwUgjWy~gYfxTfmj(X(rK_5Pj2Tbc8;WG6?TS|ik+w32wuIEyW2fy*bgYVnq>o z@vSw@>=H`z2$C=tt4gkMQcrtaGI(MU^Jdi@jR#${)h=dFt%AmrMt*Cv0N^D=%^gf) z8?>EFbZkP7RM_kgH+oN|vz4OfRasWqIBqfxV-j{&i9%%dY|p`F6B7Z>U(wk#BWGP8 zUgu$1I6h5JfJwup9cg%JnlfQ4`-)?(@!n9-sW>AO;-KfCgxS9tOLp>f$ zOxG%yIJJQXBlC(Jj0#BjLpEz-6kMVzMgb;XNT~qrY@BIBY@vB&g&BVsqw(>wnR6fw z;x@;o*a(Cy8M8)N9)~~~Rx_}|PM){@X|ke%ZK7@!1BXM?SjALuxKx3sRjPU!WY^ zBFZz}@qlyKJTt4uy;3jGA)16k!X7Ys9$Pvl-r|GNHcm1aZ%|?w7}=tipb#R=9)CiB z%%D=(7DS`V-Tzbet8+D*v7XMSp67#X=s=b!xSgQk@7fK=( zG7AsLB}IcNx7#T|p{OOkn!5jH7GV+_hYLN643U_!oe^^>Z;%_Il?t9zo}2Z-4vsTo z{w~O$iD46ChCC7k!f7)N3_|pjl8K@qj6+&|IK^uoqA8kjLe9N zFoeoNwugBpSKZBPN=hZH>(EOhy%MH6P^CAiw6^zYA?Sr7l9HnEB~5s457Hto^m~10 zdjK*P)7R7qOe`ToN06qa?#NAg%o1citRM4>I!8g15g8hLX2w%z9zIDEs!XK7r066& z2W@vB=CW0C4d^zBWN>8$d6Ck}fklzd2{mj#TpbwUfB2r|Yv+6LW%#&|}G>fjPXvw#hD#%33Oa+*vJXK^kCoHq1 zf63&c+IhO6geUXF`@~fqHiVFI#}yKQIGz!q`l7=C!%@B623m@8%&o(a3&uQcI-H5c zWhLfTT-7KLq%o5Gcyi&C;>x(<^3u(z8k}$Uws4pY*Pe5U z5(_l90XMqXR}@Wa)B<@KDR|jwiRtGzy12whbQzz4OT@q}5;|EV!7r$qn|+7*g}>Ar zwYFP00s-aKP#s7~$^olRoVp|rrg7d#RVKLUw!y~HiOEWHLos9$Tb}F~Q-V@a=(^~{ zG_mRcm^5ulE-!b>aI;r|1IEO(vl$xTXfzmLNUi{ zgr*vheVg8fMBZ@z_kbcnMNa7+lTUsgIaVBmicD+o?+Ct5-vrGBN2XPm6&(*cxJsFL|WZAZdS$bQ{QO zCd9-oJ5_zfM50z&UNPeCR`P*jED}7R#4+JPhEFu>($NBo7V*4aL^<6B8A{ zU&u!vI*>-@O2rqc%sAQ;2VS*~gsZkvktcP_^zEk)IL^mlZI*M@%9C?o*f}tLs3Li^a9jz+=n8t;4rKBo%}q&qLKk+ksx6#?zO; z8MKJ9l8Zr>QHj-K5rk%9JZU{ zD#YO$wu(br*vbYhu@OT>Ux3CQ(+9k{$E|sSDGj+{ zpJjXCf?b)7TqoLV9!wbv6cVPeDdGE(Nt2&lr0e3Yxa~%-P@j@eN;}bl^_ykg96F8 z+1IV`+$HWgmd-}~+~5m0>br;UTQh)3QS#)D)uaiU(L-z+vMNrp%eQOCLF=NZl85#w z-iEfCtBxgm(N6Tpo=1O2J4IFESX*L1h*LZY?r`cq!=wxknLx4eBM1!XZ=z>{l3M+%yigH zrrTq^8c&p zS#ZQ|`Q?5ozR_W|Eg)A|(_&i6iIN(RH&>{;i;3$MPDSkw@Wh>1 zgT`%&W}K_23u~q?{Y{vCMOTBPyMs~6YI&_p>q6=vWsGPXKOTl;35Lxj56nnt9z@*4 zNy_>K$n1g_D5VsNXI(NS&!)%%|?#Gq+RdvOVZx z#Ju@-DMnMbfLPgx9U1OYE-}s_lfdh=w#!KZbi>>z#&*P+%S)IH@{ZH%520Ydq&RS} zM_X?X=?=y6Mci#z!ac|(`X9F#8YPg4K3(9chK(zXV(BD(#+ko){K2+K=p~mDJF%M; zK0*$2>jX|z&-f@saY=I1M~ib_L42143OmP_VL?uiOWMfgy{Q$w+;bPm#KYKb9vqGz z2=!@FZb>tTm!ijeBd3j7PwB=sb&mGN(p1)VVEMw59@vYi4dKC=4K1ig;8K;>uKWGo zV3a_L8rp(`Q)e(dtH()V8ay_a=w>`)cLj!$D9YCRo0gQs0}9gohc@aLylv!CbxSx1i{2m5x`>vI zDbhLothqrQv|wiRTA4Kcn$KUfezdb&^#@q>$5# zt1eYk@-mxJc-po|Y0b{dt%>zs6GuYbL6PN`_?wZ#IOGNbhG~gcBZu(O&CSZ zs*osVy5&_~3547 zop0R4=PxOIQ^+em)B2{E$U7Ul>Nm|Lui;jtCYtf4G2@Inkq6rMsPoYF#V)``hN>|O zCo$F`oIa{BYx>bFA(Vl6<0Og<^{qate$YNC4F+E?kbFIRsFaW&H*u%o4&*7AH6O&t z7n6u_=U&s4I6LPIA$5=y*T8M!biA|CU4~hE%*|loX3A#aY*pD~&z3^Qxhid#XT#6o zo?~(dP<3JddN5lWwzC7#i_N-cO295ULza1G!=8tP2bZ=cqBlqjn)hvg`1AwL8usCa*7Z(V7^%Pxqk?i;Bi1~gC>Rj9 zkv}RJO?woVUHGa9@_;BOyrez~oPmhXW24Vry)-idT?(4PZbA-#dX30r-l$GfjbYD; z?F?Ct8%|sPyt2Ul$)0Sv*AhA;3dPPy7Y9H$_jn{`NF$frtC6Y9lNz0UAS{mLL06-I z;wMlfPxn(**|y6#8I5)FR9N$i!_HI)fmM8khfw4cd}9Qqhz6Rrg9Gg}EwXB^Y4K9e z;eG|72NjOp6SjFY47h?PPi+^lY0-;QmG~&R^Sx28WWGtjheQq5vCB(W6JH}&1V-km zq2SC4P;lHXHO8C+tC;qI;50G2nOY`T{IrG*6lofy1&1nL8Mu3`-gv0(Xh&+R1Gy36 zCAiz30;xcE{7jk!NAY_-r^>3PPQdoRTEL?1{DR3G@kKx#}F|6RQnk@}) zbj^mIFB2!TajRgj!8RH&RD;=Fr-LJZSUF@I)i@MVGqm~UOmC^+H_ahtgkbv|A|bDl z4v~geBeC$)TE-->_;l&x@*-|3+(0ADkarM&`uu%KVus8$9%@vsMIrz>{V!irB> z_!;UaD{&udyWMLzEjETPKY`0bV11P66TZXya}m34Q=LxKN?mZstH?R2_k?REAfR@OHi$q;}JwL)DC}=nSo#Y1m#q1l*LJwF^=THS#iDH`mo#djt6%g zyS%oQK_?a!i2u#tm*3A=6!;moy(=igyBVvScox~u*3)UFAowID7KVYrEY{D@o9;*n zk_a7`pi*J@vq~y(H5nLHGN1=%$Jte0AdGOHIbG@#I`$kZE@>B*jvLI&(+1|1fR}|F zGKSXkz>>?VMpe{M3KcJIn1(@P<}0sou{YWVTV@K-SsS0kh?)Ff!gPvkw6qfhCW$Z9 zNQXHTG-Hml))9_*LOGVmVl3vIP_X}IuIgbkCa09udb1^G=oC~Ao4wKE0L~N5ikMJ8 z7O)g0jMNBr0bW<07!OB_up-#Qo|IhsM{0dSnSmV+XF^*Xdc4NWU&5JrmLkISjd6kq z;VI9+>02b{tfM`aaH#|tzQ^c7LOB&-_3AcoIS<##zz#z=My4oEZm>}dZyClj*)Vka zWMi0PIMGjX$u=>QWp`2wX+TH%qRH^ICtt31TgqGsk<$;hjN$j6nmQFYL+;e zHr5cb3pxm2K9@52#K|+*2C2-HLe!MnE;xS~nn_%`Mq8?=E!?GEY#7}f*$Wa{?c63~ z1gfIBQc68&b)QOUk&5zO4Y74A+~uXj_4J$Odnp1{f;|RbKmeW}vtJ(S9b4cCPL#4> z5ER5s2jkHQw+oi4=3WXEkf!LApmrYIPLTXs{eZ4{V5S$zlGU|I;S07k5h`l3h}kH5 z`z)uG-CVTCs_^AmH}Cv&kZOwXQZ;VVl@3Q~R;XJjrt2`HE7X}z4*CQkwt&Rh!KtZ8 z2`JMePKy3%n<01>uT>?z!IrReP@@CeaHYM7eaFZ>F25<%CTjRz?FMF{jDKU<(I#G9 z%sCfBIpD4`t^8396Qof%H+cUw9PBt)>*4knxO7X;+yvg`zK=F_Uxu42sz%dRC@(8? zsRe7GZnGz9bOc44n`rE5i>BJT#+TWoo_*$JjgG1&A(ENC7Avit*2rHoX>ALUOI=sz zaou#{Dvn#rTcXlZVAh#oO|bx>SWcCY2n+IOx+2c9@(;}HzQ5`e1Jjnh&T>l10v5PQ zWJ6AaNJq%|j;>gw>C|13Qpk<5a?NJ_<3O~1qRwu{=~|39F=`hR4qY*>%mvIG)QBCv za5gZYw3A@uAlgI;#>DduE}=?wnA4a9On&M^xTH*To;N0uO}c#MP>C#%5zlh3>BjI* zQvtFW&wEj-G87i8l#`NEqDHI&nUqLoSk>SB^EIZHf{PtE%b92-ohqkSTBz#XaQi1? zt+1KM_k6@vET)%vKD+7uBm@!qdC%Za!qgxO=wzAvZb#Y-!hs2n-}et3+NWh(r?oA* zK_^=n;M%cX2PfmnQrKzXByb%z^UkQgQ-U#+z$wGFuL8$F7i)74eBjh_yd&q+jWpg9 z2WY~+_9G>1Il{d93)DH|PM@i+SvY1H%M11<`ai1EO$o)Z10&8XGfFy7GNvp&rAP`# z)21{Mw+iUkR>EGvgp2-JWT>b_QXZn8K=m4Cma;E6YDF(RKW!fL-553VMCLFXY}Dc7 zznzK%?FoF^Y(cqwTRWpP5P^%Glu6vT-q(vk!p@;QZ z(JXp*HH9f2a73wj(gW;Hc^e@|PSgzMq{`27 zx_#kgnvxXzy*}<@jfPZ>S|bB$foeYkUQyJ42FwN0 z5m2sj@#@p}(I1$JVn2q4IEpK~{HhpsWPo@($&oq-$bhfz8$ZP0C5Y<9XdZnbe~ z@6-t>KjdUp9c7+6YkNg5o-xlI;mu)&R-D7JDRC=Os4Gd}NUDx$w384+MSuIMl}ELX zmL*|NZA(xMvsaTmW@zSlr#_ek58F7~tpTLQ?r=ma3?n0jQ3zdGJ(tarn~Gtp*{Tn4 zgEPg|`cMJG^J(*PG2}4J20agPKjLsMd!;qn-Do#U(0IZXaSs>P_XeU9iPT}RLn*Dc z>pMf-NRc&)qkb`p=3>}|uZ?odVcF%AIMwsUwZ~k>*dFZEzNF*m6|5O)0nMRJr*KuX5u*rbd+E3IUsG7nP9&CWeY z7&kEYz&J5+jvJVNmgU1qrqPM)UX2=)S-@Om(&*P4mNt5A=CtjF#dfEM3t#ARsj3T8 z*B0(^-QG4@V*9)LU}ZCI5}u!0nL*#HYk zk)xD|)CN?HBItIi`NA7Ui5(jr@!izp^4Ti~59yuXk zZYl=mRH)(@n9THu4}tl06X(AUpNqEk@we)xK9H#&del;kqNzlE2ko<=>z;usQfxsU zNrLtfC&+5Xrn_B-D$A+&;T^asJYF3|X%jv2cyy4RSdOF^`9AiXVI3j(jaHRI&_<*} zmc2jE;H2t^iWIhd5-zi}J=-L|P4;wtn|zsHxNOR&b=l-2lET5;o}Pj5G|@pN6(F-@ zUsco9IbxhoSNDhnRKbsM@TnvNZ4t${yg@^Hpn6lO+d2Vl?rf%vc!S|M%WPQD9@-VY(n)hmS&;m>^=sNT?$rhmX-EQrx^UP^ba+UgM zcN&B|-KH0NW2e`M^OERNm3>~`!j}qop*$2DYdl&_>iWEHC$dhuJ6QlsF(D@Vt*u4kLe%}+|E^dL%1XC)Z7TK(quj3G~xV9K4y^Sd0)YBKF zus9sHcHr+>So6klQ9l#7*cJ^l9a_3$GJZBN!-%`v%Lj~WO${nltB{dzyG?VknehBH z!Sjc>MYrwZh_`XjWbIYB%&qJm;O5kNd$adsYcPVw#GF3)oLj0?O4QLDV4B~%*Dos z#;rljHkqFCyn^oFFID;&d;Pd85w)V^SJ2?n?O&W!#4`)r_Tio)G0~X^Hq;tCD{l6d z)+^4^`D&3(YKjPzJ7B2!N^2imXrL5v9wRbaIh~3$s^^y$XGw&7HK*g|r}&A=$jtB1pNs=tCr)zZIJctY6C>x= zQSz(p@o+bWe)L*G5Z{A9K$o7S!$9gdf5%EPaSAh4HQ@Tht;blv>E*}oYxVvTvnjZD zOV!FY-(LY10WO-Z9%MEmm|!~iBH*vInxm8rE38slJG*hWN@^WJ@HJee4jz}Pli6=j z6_=#KwRB1ho(^!m&9LGQ1dB+Q6V+UsIi|>w+t{CTghQ5U3#-fOA?GBU3bp2L>jjHB zL!&ixBxdqrm&Y>Ir%HXQHAl)^BT-XkOJ+xv-jHU0<#xWqt(azL6yz15X<+B*o^k+Y z?KOMF9X1B7KAp~^YgEYWi3DPN%Eo+JU%$)-DvndV@)Y^@Z?`KF%{G3UU(>#=*ZU-X zUm1{Ubucsv;W^lB_2DMEv)CrV^BLo%0}PnwrGWWn0tT9gdWWnLAtA@7mZL>Nj2z9W zE!6t;hRcw~amIkqX*rG2puY|G;q^WQL5yfqZwZ8~j$ni>tk!5fj)|<Tz$PQhi)v;8n4%`M1 zs{BH<}lfhy|bq1!YK-~cYJo`%ZPEWZWv$#N&loO$g6ZjmY*J5M^H^JpGHt8sd^ zK$i3349*Og7#+A-u+{Wt<8%eJL2#8tqPHg(&8zl68`@dmpnK&3H{)y=M4AJVWU3yLRe z(b_K9WS-ReIka#(x}yyB(WoUI=zTh|oG!(T*8J%(aH6n-`NyA=liO)dE}`WZO_dL> z#B0(m<00loMcWlyABp8oTAlbH$p|B;J58K;rE~x55Y1o%(p6ZX#o; zR`ZrORgzImERx~^rC+G9f`_&>S>c{=>v6E^Uej{R#j&M8p5%s7?4*)?l+4jQxd(6; zNEbeVoUTt7uGC3;&vo@PCR|$lEn&HKRUVHhLE%a9#QG~R=`XIpMFxE@RXkArJ8o9) z)!SI+y1b@0KoxoA$nG~OmF3-W_iBgt##KIcW<{(U8R()1708R`aas%Vq7bq#_TX^H z4GHq{RR%dL`CG0@oSpZ6;Lzcqe&Dp-?#^h}x(tu9ZsV$p`(g3g>g`X)gb`?u ze7K7gFL%|?APANu!))FXuiz(|Hj0F7-3=^D-6lYzql2jM^F1CRSNRTpWN%|g zNWOy~;Svp>_}|cnc5mnkS0mYswXBDNfRG?p>wC0valJA}#08P~wqfD@Q6Qo45piLp zR)4F9`+B{6mfNA25JIT?Lfshx9*_KV{of%VkPXS|8(k`}76^h}09hY+6$^wS0Fe}f zz};AY{#a^3VxyrsZ6`n!OV71-x2;PinIQc(=AR1qwhNXMT z1?LEl7ZMlY>6VV)0Wc5>rRZ^4N>B>~!OmkZ0|4R`{G{rRCiQ;?L458YYED^s3`0c) zQ7#YN0pvjJh^z0`WK)V`z|!Gs?qILga4G6?cOVndA~`Px5qSx1E`f)? z=&4q4Pe?FH6$32wlkBarp|T}2AL_xX+i-E_C0y#tcndzfb~k$-?trq9(Tm+C6-uSU zpUOj78Pz~g)wzSgHn%1H;AWy9TpztvOV#SCgTC%vv;3bR6j-@WM3DOid1s0ER@!g4 zeQIpcYy)c>e4*4Gjt4IGbNVR7jx)q96K-=AAFKv`ViU5q>$)QbJ>Nd)@AC0x(vA@U zRX{HC8#LR1=e<|rz>EN6)dnMBU(D*^w)yTJ+>et*%w~@)Wc)a|nOG}dDlJwa{L*z7 z*YF9IM@X#K!6Tr~blR;g?7@tkol&nTAjmY)UYO7LA^gG?Enm3;3z6)1Hv$VB{F ztAoZt07TB@Eq*dHh8fuM`U;w4Bn&L9o&I>a(?r1kMLYa{Xk&YOh+!H=3`U>#(vxry z1*`RI%e_tq;_OgiSI1rTlZ{ls!?Y;icwb?nO1EZP+jH4bZ`&@&A6QL^m~2k|n6s_( zPdQam;tWSCow~KNFYAM7sYH^+ASZbQjAns~kLF7X;XY-u&Bh9$JA`2zMQ!3z98e5d zc~Ovyx{N6cH;?Xs$qlWQC)bu>O@}o(ewAo{9K?f-9_A@DF{yZLl3_yK7>}?Z7g#t^ zHl(#4=7C+htxx&d;nadr)Jf1|gaDbqgMifflYoAyFkIzS$XTLQcCfbwN#o;%N^Q3TaZDt=+Ui1fAt06VX6Z?AI;z&{Ms% zaouJxypKy)pg-$%e3;8!HzIbue$~ZR;w};a{Raid)!OA+sR~saMMy#=eP#hPALxa`Yy-^uNH-zx&*N2*tzEpa+Q)i>AvI<7y zc)TpEikF>GUS&K82RL)0!(8eO1SQDnFzy>k_=-_z*?37nW$ZO8af z37ztGa{J|t=nC}5UMkS*;@nDW+Z(EZqCzZ$p-u_cNkCOQ+MNJKdt%0Gl1T?GJABfR z^Wa*2+-+dh;(r6T<<980mg-~3KO>JAwJ+l#Pk}PI8s-Y015sj|y#*~VkYEGciH0Xw zD=(3>uWRm3y>U>50Snp$Qioqg@nxyr1s`9jkLv0ZYjI%{w9D2qn>}favk#-LJy!>O z|JWTIu&cE9kKr(lWkQ+!;#L>=j$DDunb)k~ zQ0oCz1kq;^A1Dhgy4-*=#cwoxA$s8*Ha(wG7pF8y>eWycn(Rm3P71e#B%R1_ywX{L zMM}e6C-=X@T3|Mr_)N=btRPqhl_e%gNKARkR7@2LO=kE)qjof)A-#tBbQ=erI|zka zyVfGxG%{`<_oW>`xME&|2$~Lm_DP?(P_21Y9<}qbAT}h7+f)=v9F9U!Rl;Jq3j-xA zX8rDp`6}mrfk$u}+PVwho^oDaEn}@CfdRrnk}p8Ik_0(Q&JFxqv3d>=ZPJ=fqEeBy zAa#QhVQJoC6za8!NZwXa5WF~30f1`_qcROgQJL3T-K(!uue;^46$J+1Q#5SpIcA%NrBFV^s@v_sWgE$tPM2z?pkcA(_@74T^Aj_Nd9@a=NM0>K=z~m6a zVlm#Ni6?K~6i0^9^uFBPmA_CVsfbg@x2;9ooq}?aibm>}D8{EU27q)fL|*!K0R(;x z$~g#WXl~LxF^pV?$n+NbeTcbGurtFAL{7%Y8B+hCqE*`Am#`T}`~U!v@i zD-9`L2q4^Ieh_^airH*YQ~MBli$=$4se{4m@cc#A=Muz~Jtz$Z9ZE$;s-U70l$RDH zyu}766)j~k(NTy*i_qkz8d}7#{3ej_9eON~2K?u6Q4wLKzFMA#tb?ndeA8q0u^Hrqhtj-dVhgEwCWAPN*l~d7nd&+ z?O#FG;25Oms5fZ#rnMSQ&`|4iB^B@(Ew%YFLASKG3PNvXC54Wcrr zQxKvRHC!Ny!1;qgkAGh%udw10HC7vhfaUg3pM|{KR)UoF#7BWh zSq*Xfo*PD*{D4Auk=Wtc?5*^%{pxOGyPfyqRjz=;BCXqeve%{ov@;aeqx6GH&dn-n zGr;Ds`YenMJb^tJ&55ut2lS(di-f6v0qS+6>_kMJ?~naJphxjhh8MfSMUW-EB=DN$ z!W9Up&}0k830f3QCqm^fK2Z+^fguA4k&KQps}y*dLVS<+kyNaI_ zr8Z_%GM^+P(}UsSz^yAZa3g5s z0$)%!K@%FmSgip(>j!$1W5iJ9pN7H8-~8b!f-Jew@aLd6enmRaBQ&n^C@fd2HI`%r zK@A1Cq%QH1+EZ>NFgCX@|MD4*fK=vMA`vEF-v+@YdUnXSp!~1{8IjFzXd|x;PCkH} z2Q~)4USo&N1kjTB)TTA4GG%Cy?CBZr4j_VK=LZpNxFGD0{S&7V@hZwYm8wVJ_XuM7 zc(h$~Mm+~_?9t-ixvU>-!iiPWrEf*c{~dxW5*99S6N$`a1HmE;CHyofAs^2Ff)oc^ zFd=kt92K-Le-BBwAb$_|)+iMM!>tcgfHsy6RG>@c#lF%g5Yfk3C>7Cx;2{(3)c4iT z0W_poG|3Mw*5?O9P6viGEk6!jv(~FOm#Z7JsK=6jvFbp?=KF%GP(@?^%@X!k)auR_ zZc82VcE1Wic(aCkjpZ?hOov4BW)J%$6eDe67GVjqND)ESQ-yme?6k`0Qg;L?&SyS| z_jwY@Ty&xl!kpOsR;WIRzz+jb^4MpEuu9jwg7)b|=RU<=?qVZ6BA&z!m~QK!GD;dW z5i;$^%khQ~udm@OSo$>*0Gx_UUyBjxQUr^eevk&31`ehxLyMTuFn$i0)dSD}Qf|W9 zUqZ5oHn3;SV0hWEoL@fiw9DSYCCo zL5t#$O$J^u^DqHh-LEahjL!u=i zS1~D5q1A68k@`Uz!+wbIM7Od+n#v0b48<_@h2li<4g7 zv=v3g6w)uoKP`w5LCPX3k+hPbDAIw-bW~6zLLr|bu%ZlwH?{+Cil`(QW^mTb3)PQ6 z4aD&W)=dwiP^2lS53q!u<(7dB4J2&VqrwP}YzmON=sZOzHLVy}d{86k~+6E?qL69#WhKr(c#yA7DFz-D7N6 zkhzY)WQ0IGy9^3IgE5hvZy=6Rpq);c;cy5^b*ZSpSPxCQieT7i9`&CB;D6^`Q>}1cEi$dPiQh z7YikCE(pSC7Y*=sFW%|SVB**xMFx*AKr_jQ^XLmE*YNo_ie{-Gc*0FY zhfb_^9`bogh_mi2QziwI2UB5l^-1S?}z5LoOr(S-|vR=GS->g%B z1subid-3{7z??YsKmEb&UwHoY{5 zJ^C6wg#XYN)?W|fJaXSl*YA<#Q*Wx5_uJZh19f?)6#=JU-aPfv^*61TxE`;{w}rO2 z6L^##+Tpch8Ik7a084TApzfcQuqvHTOAC$j8sQuoQ zaa4{q#8decK9wsMDi^^$gnl@MexNqJo&Le!{doQk|FSHin}YmZ#GBfi@b+^rT>r@9 zFI~UwWbKVpmi6r;nRfr&OV>d=Z&;b1ynfuOy@B@mRx9&SZX3cQ+Noryzh6Z8{%4LS zc=~p`^&I!(F|_e5vW*!BG^D;!_>`ore=li47LQ-=LisKreJk@*pvl@Bh`e(Sbn+I` zC?Rj_)bsfE@*8(s&vRbq0DCuR*|L6$%W@_Z=KQq`RQ)ObVXlY3W4Om(;54jLFHF!g zB|+nB6K!Tajq!o$h38*Z%yix9+?LWw|Z0{OYk&Klu8wyMdSa=$Fy%?>zSG z^6R(b+p$;9BfTp1*PX{s{pIyzfAsw8$L{+FuUZcuyMFB4((6d$-&ila{MzxSQO=kD zk3Tq3DZP5@<3IZ9?VtJLAKYbq;58b9l+H=e=WUkYCsbaH_hVl|{>Q%S`Pc9IZ-3}j zEB6i8Pdxo2uik21e(g`*dh6T2fOPxI-|>gL5o4eFBJGoT95jJ;dTQ>a>tDR{rT@!% z{MqZD&Ajs3?UFvebnZ7_`|7#hU_M7_=H7VedhwO#U%%J-7jNEceHxE?|3m!#_?tvq z#H-GsA0Ni^2p+;CoRhCU`zpS_cK74>4qp1mtIuEGefs&=??(MkSpVeBTdgYk>W8kM zJoQ7@kH3QU%KQ+u-#Z@$9HnvY9OxA7bnI3!UaY4puVc*K`KjZA_q>cZ<^RcVdFlGC zfFqob%Wvl_;?dyafT#G6WHENFpL+8)>$x`{2mij~6ph*EuitIG_-0e$JPjBcM-R!d zbQQRj(=S~|*~QqAZ%P;Q$U9X$rH^sWyph`iI21>HtY9df;#4@C#yN~h1@mR_X!Se% zR`{Q@U%LLuI+gdgP|w;Mr*8+X-}>_XpFupeDdqJ`@;8kc3ZJrmhU33v{l;rn=BKZ} z4|wlme)YrGkD=|0nIGZrG*(YqKf-mU-?w|ee;VWSXRg!Op!BE?fAQ8^|AQsR>PeZt zdQ;z=K_4DR8t0CQHaVMl{`H3tcLH&D%Q)f(*0UJzFTDE38T8Fpp8d_&is+k%@cTG; z*kkxjZAs}-{m)e-eegV7d*d$2JO318gv+J%1kpv~j(yw9Z#;r}seV0&dYse34}pi?4gQwVTNH+xrw)R;l(%m8{haRPrX9)^YRh=a-ki^V}m%ckgOzgrk(_213zyF1PS)=Zf#O-JR3G1XD#MfIaOjp|9Ei8Xf#6F(m_^$t*ux<;%-)4Of06yK^rh_B> zJ3{bxgudSy`i?14`#WLX75aV`=Xb$t1dKNA?}T+v2>u?1f5C&f$NNP;PFVMb;O}Ml zO%Li`@0WnTF9d%d!;@?#{_ayh_VC_?@5d<&z+)5r^NtWctsMNn z6V`*F?+1poEck4cE9@IH?3)Snk*oQ1Idcf$Gx{_e+pgZ~r1 zPFUX<`W_CSwEl_2AWEeA{;znG>`M=Y{}gZHQS?l<$GZ^g|DCYT`2qYoVSRHbj1)Xt z;U>233WYa9;h&db>eJJp_g@Ts|L;TLKM94uO&fyL_l;2a=R)D%4uwy9eJ9HMtujpQ z^(`1r9}I-=w0>BI`zXh0jF(>y;r~h~{C|eRzaI)eps@%l|9&X^>!I*jjYSarQ=#y$ zgu<_d!lxmGsz1Wt2!&q=h5sZJevig-2><&+;hznKKOYMJdl`NixTnECzL^M7{!x0_ zQ22X7;U5l#pAUsU84CYmDE!4x_;!s&QvR7x_b{xZ`47V90>pN8Q7EEGO|Hvr`ymG7ZY_*^LbNGSYhC|n4IzdICO z4TYUh_$NZ)&xOK&77E+i6i4NMCKUd7DEzrl`2P)s{~{EAvu53O7UH9}9(l zA{72qDExXTT+^mts?Ya_!vAF`{41gGZ-m1CIuyQ@5|w}S^Xo$42Sed+3WeVt3cn{5 z&V|Bjq3{Pn;lCdW|97GA?}x&tHIaipEr!C~Q26hK!v9bYV=nq-J&g3eAj34x-G>?W zs|eHBr)l6m{Cn=S_^raL2%piu4-uwvsqepla0X#wdxZaUc+*^~zFV3?w$blf57)^> z;Pn2cmvPbT#RlJ!`rg)XP=D`S-g?;RlX=a~U&YZ9v1^BYD)>XRobziNON(nT4jOMc zWyffL=X?OzJ5CQLP++Sv=&|1qlsU>p<(i${aXJB~qd{aoy)qmPa6EptdN08JW`nor zN>$dXBa3Mj5fNr5?g6$N~xT%l0({AZxT-4QMpI-* zo6pLMV}T9XWi^vB$dRu=c)&*y2}9&->ZW;IT})OX^rmJ>=U-fNM_%V+LxwVmE6$ef z(k}i?MNpJN#YlfWT0z+L&2M!1?2ozJ+T~U1f~LqBMlVM4txuv=X#~YwWR%VNLkxz) z&0eR}MX$z82(~^g(>)X*Pa-vCe(G7h8X7!D5+rcM*&jOmEW6(`&+=^9gteCc*4ggL$Jklhmu0hA`0~U7gz#-yhY)R}#DqK>-Q&J5Cr38oM&9bpX?Zr@rEyPuhHT4y zHUm)~M-wy)&;t+v3$%P$qS<43EWP_NHbk-TdqmyJ2CEmX}i;YpzZJo_q7VRmXg)tYYYtJH* zbYf>0gs$xDcZ&V4v)_d{iid*j9KFBWg2f=-?-M$+Z~TwNUh8ov%SeBAc3GykBGW6$ z^j0N4_BI|Nxbp(<>;sDBlN~*?z8lM+Oj@IZ{WRv zH}%(x^sb9`JicXFpQJGMDBeSGO_`sIdQli}G>LWgNkKQqw?+QPcP!ptJ-#dSrDvBU z9XuoZ9r-;(c&N`gdS8|4w*~#2?MOO6x>Qdp*BOHA$$FzQXlm>1hh+W(QD1^X5v}7x z%R<(S_p1aqmig~VI=m+7a9^f-Aj|V%z!LoT%W|Qy9;Wc$ll1wY$a4OGEa$VboIfbb z^-_ z>C^k;XjghakA9>#==wQ&gRWnsH|Y2i^hW1=n%5X=KnBFLVk=`i(EoP^UO0jUkPZhy{`YjlX>o$dw%o%apt+_9;A!* zlW6y}KaciK8;$!3+Q`QMZM38Pw3~%E0J~s5#tqtNS1&00McPjzAIkrra(|Wf{}SRg z+Hri3Q1%fwpyZCwlV{oEu&^4G9? zFNK>+XuOfF&b8Sz6AKe!;U;K0zA%GGKxRS z(2s`Ql3{ebHt=Q`cuy<5MG9{>@E%a_v{<%$xOSq=@q^}!5+P>0ukx?v z`%Ca4uik)}0G|#+M)J|n2CHXU!FOC?a?E6Yqj*?ny6o^O8d3SLmhsIs8jo$(*pB07Sk?H4ZeSx@8=9A@Af#>*g zoLl2rpT0vl)4($=8%NOgN<#5NqjWFs>Ys)rPY*-x|M=bCIvVNfAC2Oy4$sGw3Y^t} zEIrSsxU%XSN6tNOU`pW(oFBkh6Y$JDF0LIp-aIh-o#vZ|``et<-YzFaoMMF+hfI1X z2@K#(#d#F05JyWPpH93A$mEwozMtnPIunPo;c1&S4QtV`xl` zMS1^-3O|`=RS@3Aepq6k`*EBbQ0Ie8OqSa5)hwe!qZ%`e{5oAvk5=?OJzClS&oUh$ z;2*!|`$Igl!ZS!karZ1A&k7u0?Vi2sGV)3cVlofpXa30BrR40%8&2ZfUfjiBfb&c| zYopI)F&v+AxQFBWein}R|BN#HJg>#`gghU}v`=OFQO6yW`)|g%k}i~WpIcwW@x7x7 z)G_M!Nn&C3J;J()LuQ|JG4fF43=Hu+4CAI-sq$mJ7dQ0D^b?0?K6r-F#X(sBhw(>| z51!Yf`@2l*Ah4WA(QY2a8Mo!BWC8QkFj9cHrVH^C;ouAv&hnt<jpfcl5XE5#Wc# z)kEh=_g%vUct_JNiHOe}iHHW2-L9!PKk`ln2gWp|6&NVPjr}|9YOiJ8Kx{hh$oj2Gak6uo35}QSjkR=0nrG zGnFdNf1p3osl)tG(TMXcmId=E;*aqB1LBfp@)pZSz5l$wr0Cc!B`+Lv&lK((ZC{Q0f-y)y)aNeyi(torld3maK`2pl@ z;4I`f98T^{i9WQMew5Jxw1tM{sq=AOu_)9#g7NwRjC><8)=e|&F#dUrADLu|KfA3|I=a$3W^DV9%>4!8Wi zlxW^F8fn-wTAbW7`X0{Ng_oyBA|Vx~d0^;Yk&hyj3(wdRrx|4t!MMOS#=2lzDHvp0 zFun~wH5zg587@Vec@OnVex7fM9Dn)<+YWg#&SMSg;Eg!DM&Cso5sXC<;hq6H z4q6uFhj3~H<>8rAab|?`mv6Xo_6^U71pT=Z_6^U31pOz=-x7@;OVF2RK!PslVTR$E zkD&kQhA-#OGcEr!Wqh?B7gw6T3FDVe5brF>zr$lOe+dzPip4)g@)vuB&XuBX!eW}m z&y}BVc%~y5|2Zz6$HJAJZ+NC7$bYWI&y|~Rc!nd${}IWb^jO>pUz0r35#;Ae%QsdtFus3Ow40tYg?UEAfqy*)Lv6^v(V));{g9$};=K&*`#%hS^2ab>X+yfsqSspV zcP#pCi=M591n#+(p?_R!3=zb?ThVTQr->2Ef13Uw3SRQBQFJNZDbv5r@*fEJpDX^} z^8ar|yXF58ae*-;5&s5@?y%^mE&6XQ`j?7kF_fV-O)JI=j7y&{KB{QCF}}8d|4i|K zq7TAv7W%^(Mu#E)*%m#+qAL{5F{(_=!66#_AW*{7lzCPk`L;nX3ct2rxi;N4T(x@) zGEs%^?5m)56551rhDaDb6UqzhvxTXmLYoPGou*_6udJ8Xbk%KGAw~AmrLRUS+F3?{ zgO=`FAU1=5)#^3l*GL@A7q!-jaq(L(1ZvDm!1p+^fAXR1n8OBHp| zK}O;xS;A^qtjj1SpkrFL5~^iy!pV`$g7!pDEK+hz@~+-G8Og*%!L#<9%UtGi8lPaQTQ=;0S*2ZN zbIyK#g)B?e6)l-lr?ZorlX&JJf&oE`eY#yLU9M;;J9s@XV|K z)?5zpIr`OYzj7Ha5!$*P0!TowWa}VIIUDySKD<}W0Qc0=@#6F zMSBzOs%^SniuGlvHzt2Egp$(qfA?EL44ca3SZ7hDhkMkN>Ctp8=^7y%+ZDF2n}+ciMxAFER`8lZ0=y-LYKfRF3I zg4OO`J7q*tpl86Hzex+$xNFcEYY~Rw@S}pu&jQHyNV`GByI#p=z~Y=fKM8Tg@| zB>y!kz1M<(nSpqu{Rw3wzGl3}khtBne^1E}-H31gq>*mM$Mm7dq%2bh?N7Sj6q(Km ze{0XS9!k5w^*_hvSk;``rEcEQegKQlyyNy4fnyhtd4m{hI%_qUKSajWT>v88_#y|T zQ@Yy9E6PkOiM#@zqJ_dZ;_@bFQ*B?`^!s`WIC2&}N zru@f(f?$3tK=0IvQ}L3lgu9vFr+}A)JMq|lb^5r!im1KzG60%&qK(e)=PkU$z$*t6 z@wlt6@eW&flqX47es5ZM?;7QYR}YW-xn}w(<5&uRZFKr-;cn(Pg3VsGU#8EL|M)`- z???u`J1x9Y1J9KI_-hM~vMK4>A9W9z>6;2X_En~jV}&k1%4nMTt$~NmBiOum%5<7| zwMP25hp+L@#fyn|X$HJ$a5wSR8F>7Pq4CyOc*zWS+&4Gz8V$Ue1|D@P$@HN;(A0uH z=)TIoAf@TWi^NlWHvrFp&jom9;~^jGdlCjOGrz^4cfeg6jaLA7GkrS^yg6Xjcpq1I ztSg#6(2P$T#>Hnf+)*W6+Wi^OIt<;&Lql6-LDFx4kDYHmEc~33@kU`YZNT%)8yKXn zrK2($kA2zXdkXouk(kP8KDn=FNXEEwG4ZN+2DzA}%c?zn@ws$6KkI&0^WYw zFD>-+K63)H3nv`f8%9pV2cFS+VcsZD(2sa0-4;LgGhj}-Yu>T%-Sz%4#?y~D18%_X zzXWcGZ_;Vbu|e=@EXMa1zkeThM%*epj$gkt$G;=3RA&;BQQmz8cWqyGyFPBEMm>+_iOi21S3<)tX8{rnaSOX(z!arbz zf4~aA3*jHl68=dm{F7GrM-hHkmhhKY;V-emFGl#;X81_zBALI?AleD?9v*xsRlxkF z@b27`3gi8RxM3um`s0+4a#^4U-MSX>T`9M|ZyY(1^6P!);5$FJN()^+;3Rq9FbT`&8Ii+y`fr82 z&7ChC>%H?|e=+aY`;Ya&W;=Z4*4t&aTMaNcyZ|(XsE{`TjBH zt^abjk5E=F6Cdlb|N3(z2FC#6uwRk?Pw%|t*rYpGANv{b+&gMqIuw%?I@SR$nK%AE`$3aAJd2agfOyfi`}vn z$$yk|B-w|4_hYoD#*u#bA--o=_MryXzp$Y%RUrMZas3-y|AP2G$~1)IeJMS*=(J2~ z-jn(X#)ItfCS|xNzL_Wi^&w*+CktmjMF$UJ_KN}|0r`~YL^4@SRET6}6HX1~i!88phqMIc*58LRQSpMY-S6A{Q=MN=aOA!Aey zxu6pZATuXk8hQb8K`%u2jmF^i9_SP0sgYk_uwwW!=<#;oHsI_V9RN=S-k-wz@z6^{ zm3S|>;GW?Hu=~IlhrJtqyTMn5_fIXjXSfgYM>Udf#c&t!FU5NY!$)2k+KBg7@KUFJ zE8O0L+YNA|etYV+Uk>b<3-1{|Uii{bGu+p~ox1JUf%n}>FAa6T%^in?IKlt;*Vos_ z*AspC(y_`Wv_ktBL33! zO&BY}ARbqUzM=e8(BD{Kfh`QtwV;2AA6WXIX88xX!}z5VbTNOq5dU<`-nyU0b8aSr5%QZY!Gj%<$t#2 zkHxBC!uUlQ49{Pfz6s-+jG#ZR%~0MBnrZ?3Swe4mK_CTdm@szvgC%Iw=1Q9NbDj~J z^!cJrxiDpASgmv4gGSSzc1iggmGVE+Cos@KmJd;TXmp)B=GvHq;h66O@16AGehYD*muIOe-pDC{M>ek&KX;n1$7|O6? z@}Q!p!Y;$Vmlf@%cdGb#fIeHCrHa(`FBeNecL0kc19d1igWhb=_k(UV=sySDY|#Gz z8lO?T@I0@$(V#B`jn6Wk|FxhS4Ehg1uQTW`gRVE|AAqhk=>G(rH0bj&WL;{|D?!&7 z^ev#dCx~D&e-DF>8}wg*W`ENDKL%ZC(7y#;VbC)%1Ud%28Z`T-4!;#N%U08$0nN6e z=@&q=*K7JP=u(5`<{aCi_MZ)!@0xb-PNQkz{*W{zs)DK^GwhMOGEGb5&BPhS2bA)p zMOl?6<)vZCL&~V&#DkF>X+M&=EK3?YuUWh(^XFift7;W=WzgejfrJN>U>W z8}udR!v_5_d9me(c1wO}x8#S`)sa`)wzO+DC6|{~EYB_KE%`yCtx<2CETJn==F23F z+uPc5v_Ds+TxM|^m5Mbw<>`f*6qi&_mkVoI)|MD-5n{?di>jciC#F!|H*Cw9Z_h@!HN-+)JKEcA&U! z3*x>b7h<9oN>uVIp_UT*#^|j=x4qPUhE50jQx;r~_6+_kP?v`A+tKQJwu|11UA=S*Uz$K7dds}iO zt7_#PEx8g^{fRcn&D@>~DUViI#qN>=XYu;B)*LKLuGD;w@_5|@)a z%-oCcXFR$cv|fjFUuE4Yg$in^5izTR1&?)$@c6P!litkiF=vin&(9uf7F=(Z&WG8X ztMg&@X6(F}^-P-&vp0L^#XKHlZzj(N*_+P;AM3M}wKtjP8z9@X9>B=l7Q6{QPyQ`> zs?V2SPx?N82E`V6EtVyUspKM)CJWhj^ZCQ?jTjF2*-0AyUNH^*XlCN!dzb`FCcb&_ z-NX-DvT>oq_K`i;uDZ>F{2# z_&PH1QRV>uy>{>%_|nxIbt{;B)T7jlaN6j6thD&34{4`ng01;310Q$VlFE;=7!Ka~ z=-;ZWlU@t&J>YTQK^u)n9UUefWhdAc96a2iA|LTyu<%OJ0n*j)^A_G~z+-p^kN#~< z`ly9hkpb_Bh4+Sm#~m=8zH;O*1X}mYOEch21)rH;%3|pBF+Up5mYrw>p2G-~(dB2$ zP8>1txPzwg{uuFc{|uHiy=t#Ok&=(R4_N7Y+rZO%7fkPy;A3*)3SbBDW~+Bv^yBjk z`0(Frnx6-s4x{n0H8N zK3{dUb#L;b3_2%j67ZqPt#jfjcMH?|w!TOtka_3?pstA|&x-erM)2U?+bc2AF-`haH z>EK>iy1Q}yT$T;=MYy^S(8htmx-1osxH=?IM>_4a&F^*Dcyzil*^xNX2fYdUyBE`0 z8huI9e0T3_rQV6YVVCEF|DdJ&B>V5!^ZlkT#{hG*AZ?Bcq$6^?AeL+Ni0M-NUd8dm zHvi`Omfd=UV=imVc$puV1T`7XN&Uf4=2^q2+&}#PgY0L#|;<4k3r8 z3Ck6_?-CZ=2=GlkWXf)n$72O55GW53_jVu!H^NQB~?<;zN`^p% zi1)pK{~4kX-*0H>%--~|09__-S2V+xVKup5(F{Yke+u}YEsBjHg#N1(?c$eJ?{+WgC$ApYuW&^34SSk3a z%a#4wEMIobglPT!X}2;>#_HwjzAUI*SjO9o>Tnx``&lG?SgWa-;cMh=NWE=aWV25n z+!%z+pouucuIlX2H#p=Bja|_OY9Glf(MGH~+{9vBwS9Z$0oE#-nw3hc055HDgXPQ> z_HI4qv~9tPBT==!jVGih5YNP#Qre_>A9|(~)aR&Ud>sll} zzISF;qhyz&9Vk~Mi5fOWYdMy=w;0J=gbQJ|Zra@4xfM4gUDw{bS?aRMQtn3BCGvho ztsP}M)|FffQdN!FYm;sShJY zwQw0%RB{Ou2$6oEH_F3YDVX#9#8HB?|M+n93S#0Z(FiA-3c0KpU*f$5#`uESi-qxp zRttgg1sby?7-#S?)9yIKr=3E_iIILf41nYsbNp#;T)_f!*SJDvn8iGCid+fKIG5#( zV9#g^^Sl}Z(?DM4!;mN7oTQC@kHdl6hkDD4^K-3cg01-$;GNq7#i;v79RI@ z)8SDkf|=i#fyXZv8gB{qa>44=?-39>O>p+!6W}xPDhxcTP(aN@M;O9jK)qB;qAzP_hSpM!@%PgBF0O+kKn~Dzo&plcWrd~&cTaWemjlwbHJ?enk>Bi8Sp-7 z;q5l?W*K<Zn z0-sraPZ@ZX2HrIm-fO_)_@fPyCCz6oKI$3)q-QkWA;q^y`MeE2rdJ!j^Z8fB7grv? z0N-rQq^SbNDAwI5OKS4I8>QHiQ;BnSu;f%)aeu-X`II>1Qyj=A zKt@5zSQs)YT8<$CIR|{m89|wq2+Bg>z7gKdp=BB9PuU6222YK6ebj-T1ms=H9#DRw zCjLX{26$Mp@-RC8UcJIi);ZE`%A}CjbZ0m%L&Eo%k|)u4wyp6Q zuTkz&e#eX_o1c~DF=37Tczz$ofo|MT!h`ZF+~3uPWwTQguu1>BqLZ-6f3@m>T$fOO zQ8Jl0ID&sRaVV z@;vuSW5GbTdlcO){iC8#Eq*ku} zLuvOZ8l)`GuLu0g#XFY2zK?=Eo$@UDJ_?uqi1>6s{v;;8YYaI|!>xy<{{IkSyMYE@r;n&GLV+bQ&o1$I*x#AH;yZn_x7>h3B&~$qF6LbF( zd)5QF`aSkQ2bk^i?9$2c9awFxiaF;9iYn`{d^b zKbgLU1LnR~_n`a)HMp;U?)A)~S4I*}qEDQvBusR~$us^5h)peS+R(JAv+ItgO`BV~ zd+HiC;U)%%flW{fEKebb zKX==4C7E#jPsYoQZ2amxf*8r~N-r{&{)3j^tN6(@jig!HU{(R>1aiINkMa48uQIJ! zF3B-FkxU?YVYrUty%urW*qr0?nfF#m8?qW)m-0RdhyLKJq7A+V+AG}eGqKg~w9R>+WmvTtC;MG2A!7-wh@`u5Fue#1e5B3UTdLGD%loLBGelsqm4C3DORjN1<+1P@ zUnzL=O>iM20w}ra>||O-J`?AMlbCU*Bxi&13YSAmAQL%*j+vdu8GOuan|~v-=G^fF z49vXaOmT2B9baH?njBv+J-Kkg41~*sMiCSEUS?CN+% zq^J_-*`9i_JdA`_ZzsIcu@n7?iw!+Fca@N z_;IbE4f$wpvG@kzhUJcDG~ZuXeD8xJ>2bO7l8h7t4s4n(sCgRSvaS$GccxF^YSX8h!1dH&eKqmGV#xND>FUbpaSfENc7@%R-$^?_bm&LI!_!8ruayH-NJj;z?-Z1n7&_Gc*W=k>C*R(g?GTf zt2FTDV4!Dx;HQ%`6{`O!Qu@)qO7XGJ(op7Uw)-mol84X7zz44`?L{3bIt<;&Lqi)y z;h7!a8$_BH!et2_mLK~)>kM9=se!|{=%|dwvt>A5Kz^@4TC~x8{GB7u+Nircyn8$# zsgX{GV_9NJH8qVmdFUFcbt|Hfb0%jw%5YFtfifE+iYMvo+SmbE0WBvGQE~#4z(cpG zh78BA(u5E9xqKc*5_&`o49Xtp@BhRqR{B6BR+pa^>Lbze5+;@d-6X}1t9!)8s)x>x z03I;Ryp2g4(h|T!TA4QL0Abp6o+*1VUfc>Zomp_F#`lgo&}&i;ogX?5E#oj1@(`J1 zV{{o(=0WmNKL=!Ira*Q^(@}#4|66n)mz_q|W~!52)`tFCerAlUj3sMh@|vP#K%9}PJ(hg;)^VHXV3{~q{L=BG9O8g-MLWtJVwh~cK|ZdZut4sp}-@ZwyXgp>C6)KSz7t zP`63Y-w-4Fqn+_ECN z1tbxUvLD`}05n_Im+@#r`m36NO?sx9w3B#e_)jT%ounrT>fh6b{5Prvh4w$F=mz*v zm&rwHA))EV6}?gVmx$jQ3k~93th%uFe_YY6k{|u65HB#AzE#n2xKWm*U(w_t-Zw4( zAw|=Vx=v14LxM}6B`#4kM*`jz&}s}Bn#p9O$_X7Sg@!yvJC2GiW@y`<-iq`ngD4IQ=x=((n=u0I%Q%qCqx}>CMiBBrJ zLDI9urxneStqlF))c`$Lgw&Ae#y?LiHik&%Z5?p5f?n^}KV%`l^QAL9+a97)w*TyrAk z5P3bp_G0$l(QhW_8X0enu13P``2cww~VQ zn|j-~LzPKZEgZpk#ue6xGO?y-BC+Ke%#SGWSv`}4kI$a-b9x>Sd3;9C17-2bmaQw= zHnerLZDNIFRxV>CK7ls48Zu3*wr$-+MMZL!=fIq!btM>3iad-v;QF?kahc2JEAeqQ zv*3}}of8Q%uH4M~WU@6fKTp>8;@o+uVhp}e7uLC4UsK--f8kQ!N}Tp3?sp2hJIWoe zQr}8B?Qyu*lYd2KJndgWzSZttF7>VO=hF-=i-YizzFOHElzok|uT$xUE%_)-bSm|z z_$7W)YxtZWj88#4x?ywK^`XY+PS)d#@)WFiKHLb$ok>@wO5fR%W2EsH6xk&|{AOY- zD*^?PBO<+U7*`lAv}Fpe<%q{zB#b96WA-0cFmGBPPpGt$^tb@5c{kt63(UUx2Ff`H z=M9v{Ogyeq7&9m5os#r3^SFYKou9{*_C#=|&Npgn{>?vFU>06@vX{*KPm}+77K;w9 zBW(GfC*a0yTD>*di+3yqJj1!2W-lIY=Oyvb3>tV0OFr)F@vdSMZxC+WAJj(U@s1f2 z?@a@bI2!LR3oip5*S-VNY0@#4T^K8a__|2$;jWzv!IZHuoIH1|-o(eeI= z#TNt3c(u`d{|L0(@u+Xm%x`T5y#KcFnhiYuZqRru zExdIZ@Gb+NS$>-hJX8MXE(?!3Ygk{}FkYGi7T;#@@jHPwn(x;ZALWUXnhCb%TZ3;c zX1N>zU%GLl4t!=lx{Q3xR(NdRyDYpalqdVGHagz#T71b2e1#a~%=E1TU%Gx20-u?_ z9Y*@*A#%pcaFoL_@ftJ4+iUSPXW;va;?rYK2l!^|%)(||e4Ym%yt=g4r$Oj2bR!Q9 zZB&702EpebEaiW2{6pp=3Y&R_muFINcv*e7p`*sL<$wB6E(d|9jpkD-WLI?VuynX& zkpHQQSJhDZCm;Er8n*#>@;~R`n>OP`6Oi)(KbNs?wERR2_rFBreMek5lf9#qqkwmb zOS?KfOn&XIZOWxkriXGxl)IsvQ32$8URAP1l)EW%AfFR|SjyQ@M#z-s5r%A#yw3T$6FMWvXGx9NJxsoGWs_H@n>OWtx~Sg-G9gt; zCIphBQg-HdFZ*G(OtwF>1(Mdi8?^-!Mh&yA`le9c8?wN2U<>fg2e0=dmtK!Et@H-J z?5DfuCMb=edy|_d%6^z8EOYO>gwYGI{Ui;?f>|i98x>89W%nl*{bh@OP0>31aYb{k zngz*k-sehFkEaZy#$!ejiT`{x2w+a}4!HoNrV)!+$~1p1*1WE`7RKZPA^I z=8!0$f4 zue!gX@!GUsfpvr#k85iN{V68h2OEzko;hbcYN*TVWcKdxnKluxZExx5yruDut~MUs zPbB1t(hZyRwcgpjv*T=~PR7Z8XwN4pX$w7278Cv8ihadXlYohSTAq09r>YJno&vKm zPP76}N$goanHs6g*8R-p#Em}pd^MA2cZ~F3Sj_O7I*_ahnC0tz8GAO}i0pBFR>pai?$LE!~~l zy3oq5m*uVV zQK#^9-E)r(r-7oRJ^hc?xvJ$V1N4nsHc(9i~}XQ)Se01o&GFWU{{W&BK=Zlib= zH^3uo{It?|_Fljt1Z*=R(0ps#?zpM5rMp!f1#;Z8K#4`mmZU!mv?#Ht#yumH``+OL zbxfh~_5!XI*T{UbzHwEF;BV%F2QT_X1iycasb5rV7#V2TH(G(;&LO;uWdA6VJYB@! z7`+HI_R!?MfM}M#k>#DWk?6z2)P3sxw#M)Mb~c^JoH~GA8bBs<8luJWmJ*`kMsKI9^~U9u^#W( z4;dT?L*H#d!QjAI!nu1i;dG-sMuzEs2GW20 ze(du&%v)-NZc}ysQUfFZ$?(UW5#*2NT=x0@Lf>G&VEH1?vOfSDeF1Lq*JXcT+IS`j zU3>a~!UNA+7&%5nbYP@EzHjt+=%u0EXal8MmoEC0Y~u}nABxIyL?1$5GW(He#-5sJ z913ASjeVomYHzw7F0kAK?GX2W7c(6#FAW_=J~@Wb%*W&InE@MnW+|ju?uj|B9%sf) zI)pln;Lh(C;s=K!@yBF87x72Y_Hf!XesGliQt#U_ox~{s9>a3qk9vnS7TX80iV-dn z|Lo`_!F@p&tB`zfXShS?8wK$VDaOI_m<)GQC$gyznfrv9bRjb>o-Smhjdz)AJ;>C7 z9O>FE>VET&H^5CUKx`Htq(b&$}WPs)ccKWcV68ATb3nkmQQhXP~NAV zNyo8rmu1boMiFLm{E%#WY-6$=I-s4GQ2uIvQlxlq`H(LAV(_ypSoa0dfhnOV`?K4| ziZOmmcVI=)E}36hx5j%T+OKwx;H;u>5JtwQctsb=5_KW->ADG&sSYDhe?=J7^T)I> zZKtxl-7)DtjQvJ=tGS(JPTk=$?k@Co#LxMeY3R#Q7VNk6C71^hMwcbamw7kKSC>;r zwGq4QG{2k9`(--WmpHE<=l=VLR8DEzCCVv!;fA+aP8C);9e2Jj^SRS3rzpRXus{8c z*Iy2Sk7czHd>o5dHpLjrb-uM*zUAbm^Lw%#SLk^IWmJR58?zA~>lFP?wx?`;R*oS? zTh{4fd*S$`F$)@08wGYYT#nVuqn)2z@i4sz2OanM+5E0lkaWK(g^@OnH;h;Gx#OCM z4~+0kwOoIyxpOJ+6u=r(uRnEOy|9?S^}Ol%iEBn8&ePK(&WfmT?wuy%P;p6W=#ljdtuoFvcYIGnr1*rCg_Ap5lC^$Ea-M zKgQWme{^3V+nJdMj=$`q<`~7c&GOc69QSmd^U7y)<~cx*V{AWqO~A2UkNfAVw$YK? zC+A(R&-r`GUOyJXo$E)ok5aT>rneMr7f@J-4~)dH7GV2`qJ3~pV7HH{$TNQ z9Q_sA2Af0-&qUh>>cT6hahDnTXg=!$!L?2N6*&)h>jRY8scIW$9zOiG!MuG>u5CZa zw(;%6!J&NH#lcximuk|l}i#1b-X>*#<6oQ+~m ztC+K}szV0c2B+04S6<>&wzh4*t-W{o`YRlWRkyYDv^iDFE^ulVCKkrU@{7?1TH0D} zY8Rn7crC16D<(}Y4owb~6qH4#hNgwi373b?4NVWlLgz(hVFt8}=`!~I63lRh$wzJ> zs0E@>?mxfiVPKRr4CNMr{6&&~(Bt85tZ#UKNsxcC7>ceHC&WoTwK5iL?Ixm9$oSl3_ofkoWj!?b{3&-+zWPbO1EROfa zmoOwTf_Sqe|JxqdEbq#&fIW9~X+LD9#RTh4= zMj1uE&j`` z^jvQ7ue12qS?O74@n322UumVsrTst=`K^a^1WyQm?}S~f9@6;XAiu@XjdUF*B#ug& z|I45`%D|HTlpE)$0!z}cJQEH`;Icli_Wbw~7V9kG~f1aXW!#nRA`a{eAUPW^Zpj_Eu%fFl%hdF|Wa${QV%cV~juPJ}>Fuort znk|8HVHX=yEd7^Q^q(kN^S`g?%`*I1Vhc8Wv|)HGex=d=*QzP`A-I-d{<81;i59#3 z{LAo-iq`ytie3P}GR$Y#Wbq97&oriR(q}7L^M6#)3|5BuZcBj1FKjFP8v+06Vl{rH zX+!*PE1GSr3@t68mIRfOK2Kb4ED^|mpQ4|Y{*E|c`M+(^b4tOe48wokqF=Y@)6^2< zJ@A%c{;M{Y91MSpMekSi4#{63{!Y;cBt2LB+Tx$D22hv3QZy>s<)1G;rRYW(et|e_ z47iMcmRjO$mi`OHZbiHG5f?86=tbfkV@bsD^Z5tH<*yPCD4K43eJ9{wEn>!!iC$MI z+6`YLZnylu81TPD{HNuAO&Mbn;we0{FyB0;=!Za;VSf3gqRGSfexvATrGHXXs3qA^ zNv{xBDcTKRE54#=mw%P`QGmbR{rHWrF8}4?_xLd!#^qlp?pL&nf29!KM`crrGsAUN zRVzEUZg1=EZR}jt(b>{lxBklUOKH~KR9A)THo9=?Jwq%@yjW^Gw^6yp2NTUAFPdwr zt3LQR7DL$Z11YYApO2akC<>#f64fUgM|!!?Q`59WQ&U@a_tsAQ=<`~O&Bd~qUbldrOCaH42iGN zW8H*h5`mme!g`U8z_@15i*$l_;N{NDM5TChBTrO5+Pq6+Lv<7HMXSzsFIu47Y8pDb zwskWKUh@#^1{mzk{3B{M@s}p1Rzp z8#=wXvPzi;+MSX!SBFN@j($F>x=Au?)QQDwdg|MDw6wNuYTwe*kwrt0hnrYLJwGiw z*0pWDrFV0k9KzGZkqD&R)eh9MW6jpCZN09dx3sdrel$|1xN{4xeQaCV($R5K%ck3) zj_9U_wc97OM#*@D#!Bah6|I-i4`wXMUbt0Pb+v8Ha+DxYb&J<;Q@r_rW}86GsRuWD z_O5HW1FIPx5~^0OnZ|pol9oWPm8$?sh0A=MTp%k6w|3l z?tP6?nElfhrj<{tcV<@H=CvlbX4l`5aT&AZn%?$~p6XSd-CJ6Eb%L;(x|2me{y`c` zv8y&z$=ff}X2?z$*SqPnK891WrW;w@EYvi1Zs_f9-+GJA#LZHDWL~L|%h~)m^Jkqv z>B$B({z6~YbVXB3Pfz{& zRobSyx_rC47srGqs@xr<2BY8dn>xFD-RU}A7YP=Y6(D;N;ij_Ao-BI!g3u;+cHG3` ztG3Ef&>gs`T5vrS2&0Ue64j>1cKqzkx2)5F0?=z=+z7}BzpSb0maW^^2CAD-`JF9m zwrtsSc{?h)G2Ya$st>ZWxi9~_?0-(pT*v< z#N16m4fk>pmc95jXXf?VDcGdRJHeat=aj7J+ql20G~q3uywlN}KW8uYGOO^!y4|x# zv>QnG2(g(q7&?@HAMI^I>{j$%Wxoi!0N*tRX>ZAZcYFSL5(jt(72d0~LHEOs-66z& z!<}?W(J~+SV08oekdIbn@1%`CPtZnwo>J}yXd^$*E1K~!+?%i&-(h8^Xd_?TUyl8u z5Dx86xm&}eD-^ws_C1Qe*OeKif4%Z=qV!pnFOUX~By zZ=^eLnrZ*O5WTPqU^}D{PNo;(lB6~NKE;o8Zl*iZDbo#HnO>c5;5-L^;*BdE+f_PX zJH*eF4wP3j{d1)QIM0Hw0JcmI%1NiElHrl=OKBs2vRs}~?L)^4_bU3sUGjmyLGj<9 z+#|4OfKS?AQuddX{S{^Zxw5~i;zzrWF+6M;FA87c>VC9MwFA(56rW7T4mCa;z};zZ zXTRxF_HNq9ANdRZ!Y{uX&}?V5v>(s2-F{8ATiBHhhw_NiMm`%AUMua1wp-vHMtG(- zrR*cL;V#pQe0G73ebD**OO;R9A4oodn>L?t|4{S!g32fC4T}p7Jf&K;-Gh0WZ@Zz-DY9^6aIiw`Ip2#O}ZO zM8iG8@key?M8ZrYQ0oLDYMn@+32g+8zu+bkjl1_%-gLRN0@Y5OxgCW0?;S5#S}nFH*A?x^29fr0@36(a%`DE-`rvaN}Hcku?02$ z>};Mub~amq(q_ll3!L}{)%f$%JAwT4GEir0OK;0UY=b8jCd8>z!t`^I@MiiBfp}JfDL#@X@R)eLz>C6-cy!lztrp&n0$0`=EYdI!G|k{M@pc<{ z6!Fz~FI#vwpumqv1osd5X#U2++Y7vAxHEmHKHyOgS{sd52|hD@?;7c& z$gRffxA6ABW3vWRd?X*T@FHla<#1>E*nTzMX~>_MzT@zC2>#lTkERHGX8K~lV_PHM z6g(R5ZVPWG8WY=^HX82_EWCBV)Ac(I%o^`G3-4Lr={hB*#ye{99mv3U#ESO@#7jKp zgXN>+t-y;}E-z%jbHHboORIs$(^eYq3l`oW@M7@ShI}+nTX-D?9{Dxic?fT&?=a{} ziQxXxc+=r-rmxq)FvUmmuPnT(CGNfz@hTJ_>-(667lY#gxND=+_m+j% z0lWq<5pOOYoxa(~pIINT0WV$p&Ig}aA1@l|t2FSgv+!yWC|&wCSa|OOZ=*`zd;^bn z0h{T27kG{E*GA`ekA=6c+O1dSm;G4h_g5BPJC*DFl8m|fU zX{PT0@KA)F(dqjn_{{Qq3V7rr9&t6^(-z(f8Sp-5;q5o@FeQ3;|6<_{X2AQ2h4-9+ zhof4jOno z4XEqm3}iy)7xNNL3V2Vsukx?1-xBc2{3^cJfX8&PelNwN@iuBa85-XfFo~y|w;DB` z;)^Wx+uz3xyzf|e#ii-Tzi(Q2RlutU4%3%3@P1|C9RS`@_-mu{`;LXT6L?)#M?%GYYn_Vw(u&>NT1&aEIi%=sPntZ!27O+_Zslh z<(KEP%=EPaPv@7oI=}yA;XRKV&z;c;zg^1X=s z{t|fF=y)%76=gcwtvU4q8JnkDa|ynPGTzyED)8`q9-c}()UR}A z68e0a2S%a|`$ivcbW+sW5=u4>L;q6EZ5f_uP&3nkU1o8YtpVV7JeCntX(LSZ?PP)H^ zFZELA6ZwnUzEJ2mf_@vR?<{S;_9I@oq=#M zbXOHX?hvxw@qljCq7xNkV(T#oj1%}^}9YZ&`V z(_;fDmzn!UFZ|lT&}U9NEfxOS{~dYqwmGTK|JnRh$-p0BX@z(X5cA&QNEEtg#m1qS z(>FYgVbKo?8|qVYt{xcrd|_cKeD%vCkA87ZY7){}EUrgcv;H4&>wn+@S^p7d`Y6*F zbHZrz)MfkdXbgU=H-T~MA5e~w=oHjj-*7Bifbk1)I~+$ImUT-W=x`fl`U{Y@e+0h} z*N$KuF4214n65|nR-{D#{iBhF`_T^WclEM<`ddfCNyN=|77?;9i~fP3uK|N~vF0-s zlVMluF|QQ$7KM&X=njA`ALIq)8c}yBmBO8AD8(4d@eu8ceGd6{?;@fb>sEC2k4DfR zSZ77aRjGsN>bDQ|i*&G@iyD@vD#45OnylZXs^804zXJn9ry-6)@qkQw5%^g@!kG6()Ys=wUuUd;dE~Lh7p5NFHYau3fd^8B zao{`DMSHE(@5Qob8FRcAr~`?q#;0=Up5b!jpZcbVTiCoR^`|YsoisUB)I2bB#%KO^ zM)8%fm3SRB1DH z!|p|WKRh}WPq{41YlpB@ESV~v2F-SNFUrzw3k9l-r^21(z%U%++;J0gq>6)Mo*8GX znYy*y_@QB9g!97`#KCd#@j`dKAay*dc}UOii!ok6%e<_EW5h(7g5#)*S&1=`@& z=kUHmz3<0+zj}WP@6W1tj@N_g{UN-+sor-t>>J$;`naMwcCR?o?K{kK*%|)(mCF4F z@Jv(gjd;IaxpyVMb+q0=8sR3;M$nEhCJ51uXFDEhr$JfFt%D4x&afe4r2 zxDC-h@eH0X;rR+4)42D_Yp>JW>1>0_t(!Z$FDVhug^swy z!3w{#mt1fu(eKU`ovrORx3__<IU}C6m+I832QDJq|BBmx*J2eR%E`Zp>ms zZ%cQtICl4oc)p3}>v+C_=TSVL0pmS*cHw<5p2t2E)nMKlo#ixEHyC=lVba}UW_V+b zKMA+jnP!qWSCL#-7r=ieY_7LmgVES9VeHxj!xwwJJHS^UcXj*#Vbn~Jzr^>%8+C&P z{f!?T(*JbJAFD3IQ1@3bJa^rF6UMKgpg(^V`G$9#1^uytF-#azoI(GovV3-WJjRbH zxP`$T`>U3;!W7+M zH`E;#^yhA~Z^Ghy%l~|tp65N5^Sw8|gy9>+W9#w_b&Cc4XGuIiRkM6%yoJSVi+{G{ z-xJbov-OL#!(xubKgaT)XZg>Qc>F%)8vf$+O;}uD@n0bMD?NVqN30GJ78hFl7m6*) zlVJ+rKNECH2LNrFFh)%J`^KgV<#cdeFbY&^fs)bl)t85QZ(zFx|Vp?ur|cMUeVhBe=FJzf4cYwi~hBu zixHN(m||*(bm^$*HHJ*$euCa6?a8~RVfk0F{qJY^UURw$Zo^uNcV4_b7QQ6=QR z&7z;M=$94kruS_5&4Y2V9I0z*hA|`)?-LgNSw+7o`Og)9Yx$QH!9y8_ztW-~RJ2>( z9}x#F`nQTsA}n<^RWhN<5bt6|C-F}I>lIDEGK??xDtb`T=ZkMEnpPQFdl@zdXdFD$ zy|i4>d(lp2q5pHwR~ur!tmt~Ym!ZGEujnqxKTkZOrkn+!%g}#cF{U7fcZ?~A^rII2 zqD3FG=qaTLqzuE)GHJF&-gsZPwYU2YwO-LTK|-C%rkk7MqCy_<9RFcJh^OK>7$me7 zH!W=M>26uLI3b!=ue)l+@^v^&w(X{-HBA{*d{nzB0f0Qun@)0M-LhMnu(-OiWlP%x zkBBCM7fnK@qoZvrk1<r#x+n%NwP(i(7A<7)CZ-4(SR&mr<7Upqgb--In!hCy=cP z7Od36q0Zc9Px(nCD+_QoWf7`KvfW0gSa57R<3T{5<-;u3yw5bN6?lHOzq<)L>r`2di6H9P)`&P8$-nv`8WRE`)Xj586 zMB2((?6$!xTDIb@=5EfbIJ3RXo3}Hcy0-!*CKynSsM(b2B!W?8Ym^pi`;N>5t;IT~ z(lag(tbmIaUA0xMDdfhAq1j}+RhI4fmL?8HZNo8qnFQmMO1cVEZC0wXNI9Nk>zAZ(DauZ)f+K2C!jCRaaNrbyXuz z*=N&b7OWN7xzKcUdfXOYy}fM{fhV#;pmMGyS#m_bJaV+8NvinLIZCUx$*R(^b5OdH z_l~VhSUDKWC@b;@a3Cg61u&VF-S}feBC)>hW=yr4uk3^_wv7G7D<`+(Hp$BZny{eV z(T-#NO|3nhP3SnS9c}8|?izOwt^mI!`8zjuxjM(WR-KE*M=Ac+h&8Blcr$rULFZj9`4mka^k+}id zx2yD{&<~RSge%uf{Rr=oM!E!XvGE>L@yUH9p)R|-g~ypckP~cwfIWQ5XllbbycEwOJXnH=h7)--}NVvOnmdeQ*80|X%M(GeKc`Abk?6Fh{tt_Hkxk% z946yQDvwHhR*d4E`DIx0F}@XeOg!ds2Oe!S9;bT~uLgMKa3daZG~Oe4H}T#EO+IZj z-nZdk@^Nhv(@d~6-#74X#@m2+86V@tlFEyBCc>L|4v2K|&Vaj#x6#1kmvNns%PqVb z(2Q3boxa;GzGMcz9=MzFHXHG>UUa6*`8wXOSa^+~ z--N$58t+RM-XY*MfQfkg(y#F-IEy5C<+1=BG+q0f3wM*R9&{4nw9)a-g1cFMj^pv+(wSX8miU@gB1Ho&Y_lnP6)^hBxDlJMQm0<`-G_;{CrC-bMhVYtM7wZsxZc zG$1{reHk$8xyvXz^z9$@a3}gCc;~^i@@l(8*@lM4cRS$Pd5XyQns5N+)z9=4+3Gh7gUKzfdmwKd!$2s5R>qmZf zBQ4tKcx&6c{j75uTs;kK8CFH!Fwg?*`duY2GNH;hbzjI2oRPW>FRnjy%qVwYuhNDM62=QbFhJjc**wLHs!F}H+rt%XXi^8-CI z0-1Fw_ltas_#>lCFS^zA2xMkOd=O_99vMYGhIhp&Cya9eppjN7`wsba$wT>C`n?Ca z%%#W+WnP_VpLfB`UUfefjB zH_r=@PoD?Kc1B>5gZ2PkT{o;JGwt|dyw=4-kUSGshBW$Z$)|WQrgiSZf2AlD*-pNN<_Lw*%>y+`K{@gP?>TFG< z0rlQ6I9d)n2HR0*4i+@*9*yIv!lUCmj=SCuH4hFILBLb?p{upj`Gfkn2uOfz;>pbyj;ys{T|e_8tw#?@5K?8%Eg< zF+P`E932>Ol)uI+Rqc{>s?X`LE7BZCx-LcAcajeevweE`!n+Qq-AZ-3k}6$sSMK{z z^GieePV!2~vPT*q>knCWrjN4vMZjX6IN+!3dnh>&9=u9Kr>b-j|5CK+<0vPl>D#r= zt4tSVy_q)lb$9&0nIH7e>BuM3YqmS~fidYtS~%7q%oI#l(~}v}%QWir>a-$#sdVXM z+ooaq*k^i?zKvf^Bdj}? zGkJ+w3pc(Op^S0fV7N%^I{IGo_lFh$!_UuSN6q}KQ*qW9arYkb%bj_uMSd#NsMF zT#TP}v%rX-ZY)RHcA8UDDp40s^TWf>5A2g=d#LaK3@t!j$yX#EKgx4a%wsX~sLM$- zHw`GRmWbzeIq!r}XJOPC{YWz``OR}^tVjB#tH-ow3Hwg& ztXV9}S+kgN){JNH4)yOF<=H@oIN+W&OLs;vU0oc&aFp z_2g#vEOIe$i2VzcO-M`|DZ%(u&`>x0#in~xFXMbD+SqjFWjEu*`l`QeW~v|IiCKuS zJm;+E-dI1*H8<3{VZqO{v!83NOkof2&py{yk>WZ*j~`46f6s94E*5SZ4aMtZeu?`M z!t;(v1BdIxH8`^%{)eswphdN zVfx`WZwbdxJ?^tT@@&4Qi&Z#B#TCMOiDwayuf%$z4{ILd@=l4)f6%yMCw=scRb2y}jl6Gz#y-Sa%LtW)Gy_JL-u39c9} z>FP@r;{0pT>5U_sk@o#KufDF6?O(U&!uYCG3~R_3%4IF$oaDH3pbqz+CpEh1{5Hio>$St22bk_Kc=&sk_)<>*cw+ID!^q3@)6n0MwoBMXxvt@w zhFDLKw|QXbe<6QNpNW46dk#EvZMw6q9EO`*%VGV&K0|#9p`Tna97kR9w>$feuAe<2 zwMQVwxCW`;p%M98(Esr8B&4I&!S8?6VYxcL%6!#hUF4>J!$=)?Mb`lKK~Q!B%pdnk zHVnOU;>44o`RLO~^JL_MdFF3gtglPrXa_>ePOY zKM9OK;eu4z#hpXvJ2zqdH864ycms8bHjemyQgj8+%=_(><0hTWc z%ir#A$=|qLdr=y>=vF2WYa)}H)f$~~Egf=~0r?Xys_GlP$F3;?~f-&f^Nt06Xe()#3 zk32-;92-9&&q_y}siPsM3}c(XPrd7L))_b`1KswS=U*bvtP73LIz<^z=h#)wxRSN< zocv=L7bf9d&j;k^o*47UbKm*qZ=RXI{>=H?W9Dzb&foR;4TQRjBY$EF^M$GQ6B+X- z(B|zt;w<)bjydDWqj>|@C71BTN#|A^TG_U#*V&5ea-FT6y^g#YnP=)&uUvVFQ`y?K z{kHbru6bqdfnT1wh8PjF#xnC5CVR(+#G-3JG*LMj+yCv2=hB+N)p(7C(BnVR#NUh<}0P zf5PLrzX;Jgy79H<$k+i~k}kJ^b3^8=i9w;$JNJ`Tf~77wZ>k^W1BY zKVkVVw)_`MJpWuUzi#*@ES6aO{Nmx8uvlvO^DBsN!eW`_zs!n{UrKxv79X|v`Srv% zVev7`|6}4s<<0MO1@JdbSX^fDUnU+_Ww!&21@LEo@AU#*=DqPHES6j0my2t#c}0UY zD8et7@A^+zthD%7iVF3i>p984QpWeJ4gh}Bghibd9xEHegvDyhf3-NK@DI!Uua@}y zuJ4-F`bFAde60(%k2RA2Igfvh#lP0#Un}_!dt7V1H@<|$6&C*$l0W5fUE#g)B`mHI z&toF=O<24Ups|864Ax-=#qd{Kw3iX-&U43pqHBRQ3-ix!6wS|t_}SuOGR@O56^x7-15J` z$Rhb~wdg;$X#6Pg4Eg67MMC;Ei~d_hb7rBIiVzmMG@4$fXsrL?UoN&Nnmok&szo1H zG-u8-%x@Q{B?P14Iqho{os{$pahI{gAl}oK|4WLlg5NC6XJ@G;NV5z-Q!F)>BnZ4>F^m2KMZ5U(#6Mg9 z?^^UnD6jxCfQRSG?@~0~i2rSiPAU2g$$z0(X$&yrzh2RMrT<0ZMa%yOie87VTZZ|r zih-2j>*I>vi1#wgZ@;wYE7cN=awM}LkuYK`$;kR|ioO)@voN2nR7*0pw^^9Kc3Sjb zD%!N~kK7#i$jJLuUlGxPMB`R8Q@+iYa(91m5B~9zvdvFM??#i{-bWkQe-jt~F zeC4VBIvy5l!jV$g-ckGnj^a<`q&uas184fHYh3*RxDj}9Q&UUpt=oEfn>M$#bgjvC zj4kb{DnDmqv(c*$s^PdU&z)8AY*}49Y-W2&Q&VSGPhv^a8XT0vZ=)?;^2pp86d`i$ zl@m*e;cHPQJetM5v-qi~R+cvDkXXV-_Co0H1PhSg2@zaAM< z`B)_Lu?R)8?f-H2KJalB*S+{%t!xV+$l4a5IC5CqB8bF>U0b$gLW01Ov4aVUC5%hm zNLfI!l;kG_v<@e)#zcX|0&K>XFUD+gUG9O*dJu_#%bLP*Td+zManW61Fdq(}H%<`{?4VYSPVuqlmTi{li0Dqd4UGXVulLQp~)Yp=JDrXU7OYFt}aYbq&8&mY~pn4)|KJA4a1-EwJWg` z8o+(2-r>Gf*UrqgX79hSWeyY`n{_igMuu-f`)$Vw=_wwaZg#&HTJpbYT}OLQW=HRh ztJigO@lMxL!HqNdYVuEI3fXxNBT>Zo$IQz2ng zGTEwKLWJh4VQyhv|3FG*(xmTB%Bo1e?lv<$TVCzp#n63nsZV{Mzp*#*&TR9a`3@EA zITITJGf(W;x(VwJY*cd!I?wMq`PMDe+48;FeYHcW7;Fzc#Jotlq@*j+ce&4vmVz!{ ziIeP;#$wKuGq1*#Bis5dlOrdAunKmMFrKw(D?ug1P9`DuI?U~!D0}e=#^ymjt>p~B zsQb`O;d&&&a~H~yZyVvVc3~Bl(d`6k2i9`vWGj0yRXtKpo@JP&&_$3TuDC?P75YXq zRTUavRz)pezE+u_xORBthW?@Ld0qYF9=EWe-MnYeEGJ{u;pE2HLI#Rv{*bLn?;PC$ zRigKXHf2MmP@|dB;T>vTb|E90;ak39?aq;r)KJE)bQuuBYBArxSFJVny-sRS#LM^^ z>>2LTAby*NWebgJv~RHYvXR~${jiV}#%4*kDK$6@&Xey$Coz_-rV`&Xl2XQgOaWW* zJ5wg*7jRRmcjw3`$}n(qS%ny)Ik%H5L`QR%)bgejaeN_4=iIzuv~3r@qeo9NZ^@X0 z?hLX$)mN=Dc~s=_NG3bbi`Mn;QhFwI!^})|t}?nFULYseV4>3IyR}mJPDX5F3`!;p zP6pzqW7)>o>apIEC($S(nl(~FD_yBH<3imbU!m?x7mcSrw?c-`A_-}+NEq<8q+5n{i(=h#`UD(GB&Vl|LQX4u^!j8=HBtkiQ=YP=e2iOK$ zL_(@&iR~F3?cc8QQBhEo@N550*z{>@%G{jBu!#hi$l_>MLa&s`u&{x#X+7reR$fNy zRItvczauxLdip$kjwe@jWrp>4c}S;Gshie~r0`-WVxh<%C)aQWlV2VfeNX+lK&4?k zLRF}GnEAuiq%?f>k*CZGmZ-|)N=h$f>3^roz$xVVVZCRKKIg9M)5d1fCyec*5ziZA z_^4j*P|>63tLtIAr;*_|8Gigw+D`fwV-x7V8CylS8e2ubW^jJp*ed#@vGoIgg6YPL ztsl^bNdxCO`bhsGeWc@Dwx2(Kf2m{mxUnI0hq2j&bd-a9{B4IgO3vTV`}FF8&!0x> z?=iNfb{bnm2ybQhUeDV||I^0S6v9Sc`l z`*e9LK7+lspesHbj;Hd^nELxIC;jJ4{Xb~rhCIzio)-F$r;k3;qw2i+hfIAV{|7*` zUXawQ0FJ6Zq;DV}%CnR{(kncKtNK8=k_X|t7!TZW<3C3KptdQ+@*O4(|0sOo*OCTK zoW50GQa&Z;@0$LBel$itq{p91Ur!qKnxKz%>ZFf$>!uIf0s6p&NJ?&&i}F2AAGpua zN1>0I@V88OEQ0U@dM|GM!@wtvOlc>8?ZtHylwakGexv05J=3p|@2$i^e?Dq_?&)Q{ zDID~ZEu{Z@zJ8m?_XnokkZvpK&l?>03I~1|PK^BM|LyegJL(Slk9poB##iM<`mBk6 z!-Uf&6#0~GEXY^SaPX<;0pYEN-a>z!saNnReE78{zJWgSRs2ZTNgBQ?2l$#y{CdMb zVB*J&e;0l5p((t2{1jD3A95&M;3N!Rv*AzM`+%_m9z@h8{5fW5z#1AMr{)^t(85{=|$chfKf!qCV5KzS{GiWjy5k z9(~C5CjCD`{Ss%h=e5vBqqWmVxw(FZw95BOC(mF)`H96qro{`5Lc#==Z_Eg4qow8*PwIZJ_@4~^ zBw+xzIG8s76_g|7x2qE*E{^<8&*{yeP^UOAHItl9ZH{SXIi2D}&0!4)*)L|+rMX6mQ((<2+4RzWXdbOuhJg z*pKXCTEw^U_#p0W$2hu0xOg8W0T;%1KH}I;rT7xyaq~?hOdQKWw-gt*6tv)?dux@R z-(&lpfs1_1?*UvkUJZ!55GGFW4j{nBtHBnjMuZU$UCzgQ8TSg$Y+0e*##V%h6FkoO zDLxbNB8ZK`1Yh_#=V<5Kgna7|&wS?@K9=KS4qgNDe+A*<1n(*bZzJ$_fQfjuxX4Gm zzjE+u&@lA~7bkenICzf(kLihbHZH+C9rA$H?=OwO<1->o@aBNeF7H#oi-U=HEVtlo zaPV#g9_1G&cx?{e_bmAqfLZYFa`13AyDEo^_ce!)wnJNl$>5QE(#iLjmG45s$9j5Q z@Zi(E2)rhJtNu$lUKKpU_nL)wE;ywe>yX~A=Nd$G7r?t5e0Dv*0X#litmj3z1n)+{ zGx-i6B93@*9PruYy%l))Q+OPE1n&+9?6TB_pv&*{`TQpn1M7(9V1n*e~ zkLPJ_WCq3w-Vq1yLEw#nhj_Dm?lr5tmm*B?K92UZ@wQ@L+l~Tw+rVez)uWJ&;G=w(S$Jzv|2Ezc;5}9V?^5vD zc&)&b{9W$>0W5nR<-T6ffx z&Wrh-j(VlfHl=F<-x7VR{xgnOE%@;2N=wwW;FB~ABM%*Y)3l1d3w+#j+5u`97t0&N z#WDcTcdx{e2Nf&h1drc5HsAM9-VZ<)al*ImrW-m^nGDt*k1A`-zAfhFcwt-2Fw-1Y zuCy)Y<9J8F&C>cyBlK)^IvmOE!ImlPUrmyDB5^QxT-p2DpF4#6LoEk$UV4A-G2GYE z-c%RJjZu{?Lj4TZjG^hkmzJC48nn z?9kgCdY?o8nW0$|b6FnyAu_vl8`Lq`g{IS!NsE02_H=}AZb&BEM^f8TSgYQf8f}*6 zG;|qm06Do5{GB^eSo)mW*0Xb$unqM3;gR7IjH_Gw2aDnbYH<}7KlZUG?4=bL zKli||#{+Vh^gMmeT?O7@&zkt>=;Hx6N*`nRi}W!*e~&&p_Q{>&R(Qu=KvdI}0&{vL z`(L46av@go4`O?ScOh&=UD%V!jPzfRO@yNmzC8CHu<;Rr3a*?U{|y089;Zd-UfxsW zvqu-XKOf<&f8lG!z3l{#?^Qcr@~JnDVHUilplw~?HAD~}Dxk`re56yjY`j*`SzO`- zuLl7(-W!N$K^XB^2ZHx7?ukb^>A22miN00;8OQ4}TqtW=1>)Zo2$VDoBM%*YTW8pX z0FG5q8`Sv}%r}OMvPs?H)~f<>Oh7=(t*bLM;r;y-6Bs9a?IXh&kF>r(RY2nQs zRzsol8&ameKm6@+IT$9Qz81O_cZN_PO=7B zXLYEnxv)0}yM@ZetkhQmSc%xd+|l^cejUczVT-W^HZNl@91~lDk@jn*Xm7tx>eTcD z)gCCb*8;or?FVy_*msUaV80Kuj>_hxq_6Tir(wHq0o$V;X)CkKa9>%_L<$9)EuF%*5{LH{sJx`WdKCwh8$fL08354)8Lp#l$nN0(HwU z%p6TW5q$||_ntho@+H()$7Ix-SVX(pmB$}Cc4+xapxYUiWZSdYb;!Tf`*yA^{_Wg4 zo)b|yHW{rNoAhQ+_;p?b9<~vlLgqhT+JgNO`2q*F?$Q3dmun9DR0910bpl(Mxr*3c zWrLSzSx^=)F)zUjs9!xBxhskmp^ z4;kNb_o3JQ_`Am!R^0Q|*J8*cz;lnqb5EY9ko-sE&&)j@KQcE=28366upb(Uzkq&> zt7-RS6!($l-IEoU?8bN09ex>4kU#OlSx9#l(#$=ScqX5RQ-@ySJ7;+bUDiS}dWriH zKc25AC%s(;+Fw@B3+jrtP%FS29W(U~oBk2LQ@SUnp}yhS-7*dJZ9&!8UOZ2E8@I+r zX>}F)k=Ndq<+xpqXUZGHdj{_qylSgCriz_YjwgzjXMuPf^KrJ1vfaw(i#C@d$S2zV z%=}sHfth#C+ z#>TNNQ;_T8NbG+F+ST$2f-2mM;60;C}^iw0HWvh5gTO zzkLF>YAe=rx2|XDm+Ui@hd%@Pwz8gqh5Tcmfn8f~LCxXYvXPe7Yz@vt(tYb&I9KTF zFGpgxDf_q)@J8Z$SQcfIHr?{oS8k6h`Cgrs&~{`QRm%>trM`o+W=I{;gxPAfp=ZFphiir*j-h7W`12IrBRBJ|U_!Un43MYQ06Ti}l zU+u*6*RH&yZP}pw{PimDXiGL2j~^~9M_aPNc>cPSceEWFjOVXKc}Lr@!T8Jak+`ER z*kJrxC%(;zZ*$_WaN@6U;x{<-M;!Xfz?vD37LQsSr2o{=yq|~ha?*)E+YISCzS>)7 z4e<=SF%VzlJ>tawy`i@%{4>2Ky!ga1{RbU-twY~oXwJ{f!+6LK1#wJ27cWaX&OOi; z>ZOKe7~`)tG@ne`I{kG+b0nhe(LZ$fxrTy{ZwA^PwO>KRTUNO{-~jKehoNmgei5q z)3)e`tXCwHUVGx*3Foa1}Dud*5 zgcZhB?&ijfmUSKG1V>+hAzkSHrF& zpSI+t)acH^)VdMcObTTWw2y`^DFGzS^zOjU)EftljhDi|D#@crX_l)rCWM<>izSt! zN=C>jw73RR4K5j&8NCXYu0~KlgZKE}+STVqG^d3@u<#y%h>Qdp>(ov9}KIgvFq?!O#^5!oP}U zd{_~iO4fv8WkqZ%Srdwt6|t#gO{}ByeJ%6Z9EQA0l}5 zH|QVM>5m)w3HZc|(>LiWhV*CR!nFQeSvaEQT4@u^cMjTTFg8 z>HHYZIW^j$Nf^Jy`0d6Ypbxt-x6=QlS!*(;_sB5(5rh+mZXs~^ZBoBmuQRVeVHAyU z)+h6EeTf&}jW0#3ass!7_^8Y@ebhVaul_z`_h~=s3*S);Z>A5r&(Mfu_nDg zTy`2)MJ_*~t1OqD(pH;imdGg3GfQMt>9P}9N_E+39QC^FbXsw?6zv(N^i|xGnS?5& zYL=h>Pf5rA*$Pm&3Wode^?%`LW+ZuG(mUnVyqv^Hd`3`EJa_8eer|hGe4D4@Z zknknUz5HB3J)SzExJq-g6h5c$TMYfiLahsL1Wg`Z%v2_97K0A3}2 zf~M|DJf;=A=W%c2QQsw>IKlfX1laP`0*~?#kG|kVk>18zAAEZ>NK|12n&>#7TKS;ovO=UL%-TUap1^`LM_?P~Ib;n+449k$lO) z>ja*(2YtbF_kh2JbWah$IFZlY1KtNb=1cjwnnLhy!|#%S$oCh}4WPvd-mf9tuD=JZ z`s25a;BgPQjrTp!bpmGiNPfk^d&I)yY7D{qk%RXJX!a*@BHuqbc#m0l%wO;p;eoW} zdkg6b_2-4)v&;K9@T5Js+C%U*Ie4@gATm)#x&Nqxcf^vf-om@v!Ha>86UaEhyVJpY z&ceg3FW>)g@DiZePsIt|UpRO#Smlj_nS8AGw;a4Jpfd;;CwOl$y5T@i@klk9fy%W0&Jr(Bu(EK05Bhu<+*Blv8* zt(JUTH6wUE4&Ez>;CLWT@P5U?>$C8dfm!fAbwA*()1g{Bvc6*Flcw8kU zcq0zpqri(JUL5)8h8(;-79Lj>3EqEq@SX+UB?>|R6TF8VyaN`Vy@&pL4qheb#sYXR zI(QFScwDt4^3BCum|cHMkuF{U?+ozS_4kN{_aO_f&B5Ckf_IsN_n3uusfG7z4&Fcr z-pvl);}+g!7T%vZczb}ywHM-~J-+PVJq5fLFmdcyi%aTnH3kK{{@z5oJ%|@4cq_nX z*WX*flX15V%!2oXgEtQP5dkxNB)Ja7#;c9z@vbm@VDVOgiSjMSMb`+L;o=y_tIhBw zOhf|o5@9kt*BcejzI~E zoz6S$1kc?cwlwZ}zskhM3E%qR;TzOu^0;>Xp7J$?_lK>(T4&8!dVkn@ou9uyEJkZf zSaXd%AXs-jhW#RAxhh;WxMH}xcoyro59exeulM70U@iS^6_qi~Q4~B3ru`jn|>BQu#-lpjo_LD;|UNE-kU~X*g!Q9(TPopfCXBS60uvg`> zEXubc5}#PIh;(9NNhDE$u7v$z$h!i0>pd>{d}_V%-^U~MdD$aSfxQ6SUlWBNg$&>3 zntklgsPyI%V?h;smIv$6r@s_=VbX&fm51*;R)c*o8273pi4L_7>^1Cfs*OW->~X3C z@BWG<*$SkMV^941!FM!<{ZFyox#!?l!G9Kh4gBQUw@pRrZkwvZz2qB<9XRW;*uhzq z2zwNKG59ry59DeOgXi!I*tb_d9XovBth){$oE1l0J;JME2XYO#uS1>QTd_FHy-=~( zH?SY$0QS?Y#lF6^Q%jN)ldQj2n|4pv#%@PF--Zi&P_SPN`$lqT)9L+Kd(ZuEl$CN) zM(m|{br$0Gz<=}Ymm_b!>lNwF=t94ldsi0in*H>YcRW5_dHh^p>b`(`aWzr>+EHCWq53$EL^9Lq~K3}OCgXKw}zW7^lYrf`&5U(Zlx zux)vA+wjQs{e69@A&X@+?6>76!Yh;SAxmL2Ly@x*6+<$yVW>aTk0mcy;x!n)8bdL! zYE$PT6e-$eQK#O9^A@Z;c2|y#EcWw5@`Ty{5X5BC5;VD7ox$|c z)J+U5w#Lg!)C{8tnI4#r2wjAystiUEMtNpccsNjGfi!&bS`22C+i_c>{^tg8Vz?so+ z#yA-{b74r`>yD{R|CeMtp?j8`1$H`WdHhx@8FQ(pKD+y$HMh(5<4`3dIOld5CQjZI z9SE@bxVBc3E!OvpbFVyBC=3?nsI*yF3LhazBQi2W#c^xERLz- z1n(;du<`1UxDjE*BaYy`jC6jOt zohRuu_$UPDVdvwbeCj;}pHbq{coh$dum}`9_Zy%Eh2(knnil5ZXxPa!FYKBCBDjuXD`k>>QKS-L5+(#QZT+IpBQ)CFKN3dzTYH- zV?1>#yC1V}t~CiHK4oY=XVj@aWoUZjf6&kp|20FiCa4ol8=4;Z|IN@EzuJ4RbYc@P zI+;$7^61W8e0PUAE}Jh9|J++D2wl`o= zOu36AukIYVnOrB7)`S;Ny-Ev@#A?i}$NU3c`Ck25x?vV#pk&?G^T!3ag$#cu?I>Ao zRq{=2H9(oXQm19ITUA+RihT8*`j5T;S^5B zOdejO`L4F{)`RAFAWrbMAi&0}M1fP1%sG!KaP7Fug1b7F8S#5yU@nV zfG$+tFC*N>tF`br@(SJ$96ZX)IB{~HLx7D}Z{cyI7Ci0|rF?7`x;?m-s5||SalFpO zKQsZWL%Bb}e@Vjt^3c(@)Cn&O`Y-~iPw-;CFN&4d*BGn*l(NSnddL6#@+Ysd z`6c{#{IIeqlrTCC?fB3Zrr7X-4UYXGSH0@cwdQ$jR`I8KZPxS2{N*;{Kj7M(Be0r@{hrtjcO&<`;tcLo&-MLXI|r6;8dTLq z+dxkm`yEYPgiLn~_UA!665;2D8{8G^dqxS^j&sPdl`*;7^jbUAoe-#Az|O7-$)}MRgTTH|_<|gpD;_Ecz zV_)SrD~B`DZ~Ji1z9~-ddJtgaJqSFer@mwBqkBQyc)LK8Pn_U=9RW7q7-){i;)L(3 z2(a^g1o?7|X1)w3AMxM9W#c^ox=_8miEtb5aSM;{Ey1JhWgG7m#I@oQC-PkkCL8aF zg~vCa;PIV8JdtTBh(dZR*D~6A>(!to4f7@j9erDG9Ya720r*7q_!-K4Sx=PB)?4?1 z_!j{|oZPy4>kBBy9TI8r@nhOjTaAs?L{kz5Rtwo!UB0}jY`wK!cS2upor@B1UQBdR z5A$REeLMo4Qgl7ehrv!|NuFpKJSrbEFGstos4CcR(>5)s$Ev*ae4QT-dy%h35%zDe zODDYl@^d;r7o0JZ9*)L`EA*SEj?w?i`HeG(AEY=xXFKYVqB%Aog7a?|Sq$vkA2zha zcL(U%-ra_#NB)Nlt@&qr-we=I-j5AUkNoGD{;&C~yvq%}5pnY{-`HzCALP$C^lv!y zAt$}39;V`IqyC)_hvW`;8~eBK$S_G4|ApydIzf^NLR2arvbn2kfN&XSCa^5{eBx5s zKnc^6Q=z~01?TvR;-O%r@l*-bLE8B`GxLza3B+5XnaZ@wW*YEph0s|m_Wq)#dGE>L>h$Cl4>uTXAtX5WQ;)?i+B4BOe{ZZT&)Q!V}NdyY_*$@%W8g z2yc&r_XaW&`RFrW`p@99@g_iX+!H7AeH{U|d~YFweVy`ggcrQma8Eq;e>&1j)Sdpv zI9~sX3-8^u4#k;;2$VDoBM%*YTmNZ6z)@VBUEsxhW4K)XCkF6u2?*ll*42M%q5sU1 zNQ-Y>|3GRc`cHC2qHG)U$1gxe*1X*Zy^EE6Y-fscKCVVwUgF*ye>X%sEvSTE<0THm z{_MS6OE$F|^I(zEr!eLxt{1F2LGI1dv)d;kKZfj$i37Rr^ub&lm|l7!%JrRiz7`x^d}Q(s%!PWe z{amZcWY+Ydy&yNrbY!xYWooy}bY$`+lqnt?M;+w(Q3s#rTEhrBTAK5&EtsQ4Th&@^ zKHEF+3gxElVw6EG=~8Xlt>1-6=mempOTGj{J^V(^A zt5jFO$COBQG@ZqHNtmvS>wZ-M8_%3ejwZg7g}weKQFin<*o2ScO6nP(<;6YQvxd*wasIraR9(m>Mw?D_Vs%OL| zChNS<=zft_w%$LFxL1!>=y`9hr(_xV+(;i6SxFy9eY0(4y`-$aw4X7*&Mge~VM&uP z&n4%(r9O%2Kbv?KVD>$V=doJyCMIQPU6Ge-I*+zI|GSX$i-)@=z9@CWd}e`9=Hu)1 zx6P~n7xu=zF>M1|WX-qTi@NQQ=XuDpG4X)kw-RS_BExI2U z&KB4=!6hB)d!|R$1=~+c}}p5`?!X~lyf3q&d40~{3avUPAs8q@>y27Jd8PbexKyn zNqokM{c_e#kdSF|#PaXf1u7{=G zQMJxIX8M6LL%XqGG$K9U zO?)RMym2+|Qg)VE>Vaogs6L7^N|_jc9QD+SXRxtluR0^eFEh$tYsMN0t8J$pd)S9> z$=r(KaKIzoNr;qG@cET;2749cM)vo*I-QL^Mm#Hs!k7I?PcpN{8qLh zM6ZfI*v-8ox7W6^(hIaf02f5h? zSO%$=R#TQakeTP3%<*==@@Dt*sNaWjEQ2o3{jb<%*=X`?w(`y#&6nvY%G8YV#9L0R zXP%uWdDG_^cxoJgteC4?aEVpVe5aGAF(AuqHA9A@re4z+|JHN7Eg*y47R0Y_ zH*MXXosYS;1(EKF=}yQ|kNj1ekLmh~p?zzhYp||POQ3zdy{}Zo`F=6|0na&fgD2~7 zwg++XuAgi$ajf_CkS}ekXjTlE!t_GBm>EdB<}Kg7KUo&pVz=5RA8f{ouFg*-ktrb1WCd*KRO9 zzkc&BitSp#czq7Ri$054JZ5N~LlETG=Mq##BmsUzv>eYR2=Zg`x#gnXxlTNubjwA( zMNa%8)qd?h541eXMe)@h%x{U}=RAdWOXNoRQSUs5|2!xDd?%h?xp~KP2!i?Pa|!nO zEc&BaNS;Fw`kaC>pJkbU$D1fdg&@8@x8Oma>mvV7^CumC zeU3rCJ(CXq3Wr~xYp}!Ta?d$%pZ}F=-os}P%#u+4Rrx5~MZMJy?RPX4&T~}~hNBh! zV$3@IvY|8Z=V83K&Cv8>xE^!pKX+)(@rWb8*!_P3_wz8`&_0Mb#t%94ErvdhIIhq5 zJtzK89Qtd9hE5OuGrR?O@ronLn3^6qispLggpsno-5#WfG( z%UVOXD*8OH&(P!{{+&)d_tDeEaV_@F_rB@SFB|#*;(2bs<<={Xcn>)A_Z<3lhdzr9 z3HJgno+~hFXoeB*4nvQt_+?(!iT|;oCsh1J-c{BsmFa)Q(7L^n-d{NJ5o-V*{pM^Kd4Dfd#@eLUL}`zZHDdW;gPQEdqz_mG95h|GHq?GE3x<` zpEawdq?k$tJigO@lLZATo2O3EV+_ow8-8r{c}U`7oT+<>o#m`>ryEx$jptz z_jI(iUm0qLUgat4(ZfY=q9I=#j8M|*@QHisObG}OR+GARl+k3!icCxz6(R&ziecMf zQH(Vz#m4?2E^|6LbNVw+mfk28T%`UwQmGr-c6}6UuCSObbwm5`sQPuVNQ%zXz(A=U z1rvBT^$!^n`r%kBl}U1dnR-6I@t$h|Zc*U;TF!XVZGrG`2H+?*; zeq^JkV+FM9y1oHzmp{DiR&5x)8XJX6b)F;*rmovLFz`{FRdD&r-d($rW_9Gup8*_N zzUj)2rttNOs<(&<*+6Dj&OEo3Biq>PF|4WTI|+nUqdTw1#_G0@Yk)$_=yd<)X((;G zGN~aRiV=`IG)=K>)@FxGkyWTFTU4id?S#ITxbH~44MJX9r7~Exb|i&!2+(LJJ5ClV zzIh`;`jbVSd0$8-x~}T#>mN<)SL?ctYdYFCb?M^qr5pBqq2fmS2750X>D|$PV=8p1 zhH4HBvqL=3PO?8=<5*JIxV>0ZyJDXk8>%+t0FyUaEHzL z3Tb1D0pZA6)lVJyta#?jdTVC*s3|}4sU?kcar(PVyWXtV!PH-A-)+64y@gJlAYv%j{;2tIo|0sOomy)ZG{GZhQjp@cp zq+`7>e^ixMf14=}`tKgnNdKToFa0vXa0uT*ALUWyKp{Fwqnrw7x9JBcl)?f2A;ts$ z82vj;I|4t@jwoLXM4 z)iAZv`syn$#i@Sd1#$^5cvGP-Hh-f?k#y#}t;}rlUvOn6@W18CJz_H%1o$E04eaf5J(o|XH z|7zKUgw$oIFW|MQ^e(>sT)s;XR)dRt>u`~W*L!e5CBiQ?+O0Rfc#NZ4gp2p`b3z#3 z`QV{EHXrj5C-+Mcpz^KIF~n;XCiueFgL}ni;;0{F%soBfgGw4$Tb#vDmyHNxc{wFd zKFW13E*p=;69^M0czY4Rsq_{TQ5E+*{3$$!3*I+yZ{s}y;yA*@3EtNbVBK=gSX_T=upIpLUGn|0gLfQw?EB&b?{x=nUp!xq zS}+UVV$=gz{eDl|3j+dX_(;ANe0IG&8qedMZTMLJP6uxv@CwySyMuQac;sVw>u`yD zcRP3wAcEg=;>bsLr-S!wTz|t5kE;a)@6R2)%q--~3NTLa{?x&XEz-I*@u<@a-pdZ& ztr$QGmA4M1N++)ByVD9M&-nqE3>+cZoSXN#a z7(U9!--m6y76iV4aB+e+?%=%wylyZN?*q8VM?BZgel3I;N4Pk_bM5S}U!0e38JGp{ z8uW8pz6XFeAz+4&h7HzAaxEm+npYlw=$L~0IkbapH4}1LeTR88y zw$OG_Xklzqy7joYN0)s=9Q#JM5b#OwbLfK(?dir3EJi5wEw@tf<&AfQ{j9M)ljkXB zKSUWgNj6r~Rt?op?_-cyYr3D-{za0$Yb~ zGD{l@4G&2i2Rf7)86Fr&ji^b$D^oX@NTQJyGnVDRy!kNkcl7tE9M!rd-Pbv`;m@mo z$Hz3MY$d053X6Q|BjJg2DPd#WBGdz)S9$Kk_)cXkthM?{*jTs)V+hAS8INQv>@o7m z*t#Ax`=2<$bLU*TEj*?byaTvrc@qX84S$Kbr^h&658*6XKj39}#VsCQWDloiG{BkeMBFPhho*}yURCl^gj zlZSiWI6gCuG|!I_+l+H=`Th^jzoq+i@^jD7zUp(7ZO7x@5w*8R@Q8Kq;-|BcPJG!D z8}TO4Y!mZ|ZH3K8Sd?KEID;jc_*NEtUq;x&48s@tWF+zJu&{^0_hl!oALhkJu-|Wb zO62fj59K29`?8hv6A$}xR%VywDq8lvQW3v58%=ycg)9AA@ozHx`ErrpYbXC!@c*sP z&-$SbUvbZ}AF`gP)3@AxNY&M8w`kj#pStCnuitgc_SZj!OX{)Wp0B><)+J^14nLH; zFA~W}5={e$}J1^CF)6h{#X`U20ISV zh}yqaslG>_R?oISZ2cU5U-CVack-6eA%)J_;XF6zB(=kYi{<#e8N|axm*q>aYLK(!5pY4U-bjJNOvhEmwMP+*wZg zv#iuCf2qB5=Q!zMK+|%i_tw4JNv~hH0ui?Nj=GO_rT5+mC;h0m(8+J1`ducEx6oz> zf2qB9aR)E1@LGM8xPQl+sJGbRU+lye-kX<~Z;8V{^Sya|KJ)TXo6WmId-d|Ml)v!a zycVD71O6Rv3hm9a84B&i3&x+g_fDRmIxtpvdM{pHuTI*@k-xjw&ZVIuSuX0?UwV{( zm3O&`XC9m%>viaHD?Me~XXrS5p40WDq3JRHuMJK4x%ciThOScdY2N#dVyo$D?@EUj z+r~^ryqisYqe_3e_uGbM9QVpS9Y}ws2ZIpG>GHhGn+Ls`PSY`OO@N;3@%tekKhOJA zfS&JtAwbu9-!Zh#|19s{4Xw+2wih>5uIY2U^#Quh8xGL#_C9OqjSylUem#52&~ZiA zdr)qb)A0+v*_E1(!{gqz4;Y%y&^#~heJl{a*t^NlI{gywK|?nv{`0)A8(OD7-+S56 ze8+Jw+8O2**Q)3bcuj`Z>6dxGY-r7Y5hT)%?K>Ae%u^pQ)^zC=8?V0nvW;C`SkT|K zp(|uphnnp)^OeO|iY?t&7MqB#|q$t_XNU12lGQcf@!iMK5uxFw9cv}x|-@~ir-f~Ymz1!r!+XH7+i z%9r}Y2{YV<;M5i{W1YK*rR#wc=gSMB6_{2p#DO1r+L2Uk+g60Hfcf!4Ze4<#q;8}cX&K2Q&M>0L%-Sib6!X=(`g?Zn+?`jb5)cR>XB&stA z?VqQ@hws3^ADGPzPg7vX_kRd0mC717Z}j|Bg?hgfWmjp7sn*b56!L@tz9hFLF61b- za@`&5i!!@IeoU-;bL)tV8xVP6LRAGTD^P*K9e!7v5^gXz2yaCX4xWozGrx0M{#VkC|b_(9tac|>|gO)Pl z)|c=9I(&OV_!a}q#ybGMMqJ`VKAu5o%U5T~C%@BCj*mEaPa%x@ia5dBR( zfB(nf+X}uy{pxf)Kz6=7tDq3y8i#LB2;Vk`?~xF`2OPeqz{h7vob-bO;IsQx9Q}&r z<#V(E7x~yPo_6r6Q2sc=#R=Yz9ll2J70UN@C*OpXFK2Tl--Wn==zf36gyg%?;X44n z^&*_XBe@=Yc6nQ@eB*|X<=y4reJ>>6M;*SmLdyGylW)6~?-DED?>cy#XKO&bI7BP= zZ3nL#c$Ay%b{;PBk)Dmg(5}A$;1#Nu3h>$Wvcr;(W4z$4a_}Ap9_Pr!iG0f)yj_-j z7l2vtwmEo5f!8WvhL7a+4&In0A7`%x@3Rgb&&O;afN|ub+wb7*v*cTbc)@$t!D~iD zq4FMa@E)-6>^09naqv2US7LYBNHx z#a+q9@rJTV8F1^3*LdD;)PXp`bJv#~LOFUNi#Xxahxz4KnCP|4$>ls0KrbZG|C5Qt zs#OTXc}ZojFR9b{`Rhw~UJ`#d_PlTB^m+`G%c0FWzG<%Gqdk27#$AcE9QY0Ti-3Ew z5;j^%qYkQLNV^SKptD%#F<)$yd$BjqRli|pVN3a4!;`dkJW)aWzqEth0ejRFNZvjT zePF?oXD23aJ^Z78T(WUu@=Vxsk9b=b;WzN+C6%xv@BQc>xsC+Cd9Og4C2DO7e*e}! zYVzms_il6-%T=ngDDq)^0`iV)3-fUdpY8Bl9SX5LV=2gArTANYNIp4v$1~A`{MCxT z+h@_VPX>BE^9!ct@7?I;%JEs@?^%}^njXVGZfG5!KbuqHpEL0s`*}7eZ8wNx8nFf0 zhkIIXy~2s7zDUQKRKI_i2h92f<`?GCN00Ai*ZxwwpGLZrnN8!;09kV@Fs5TTrYdU3cx~)Cdhf zg_;L4wXyo@q06ox#z~o~2UTEM0DDr!Il7P3<7fJA(p+dhlR3#!ANvK`IREt<^7~KG z_A57ac-xeVP@qjtdHL$kVjaIdqRD*%&C17AMz1E^^Vt?Bd`l5v>jHcya|ELvK^|VD z`*7KKt)L6xbtBxydkz4CM_B~#_i%6Hb%N%2B#wM^zk|!hd%?mZuHYTRy^Z%E=ssNH z$VZpOW#fGh5h5Sg36YQVdjLi})}wMDmdHJP#_{4eCSJ5@iCO~MPh)r(M_ya^=|q5> zmBepZ=F9q|Y{2tf1BeMGHcoC`-RBqpnj{jua@*N6THvfm=sv4Mbe}aV%ihN|z>2c= zE%1zU|C}D^5YaL0T}WeHXSZI*7mw?8bv#3aI**65EWCD}D{)8e$#>0p{otkdW9{nh zsr?t-F^P4o(?7v^jtuu;AD*`BtHy4}c?}10wdvi;k9EVxxhr+vn14nA&+<`cGr>N+ z!n|nzWF&t3)P3jf2Ij|nOr@Lg3@5Q;pSVrwYf7gw=TB0PLZ7J4<6IuVp^S_}UE}ju zpW_1^Zc^z^#6WuV`D$5fSm*8b<&3rH^Lx-Er?o7aANpE#Wqg0GGXD3_;k*SkIM;;n zE(Ys?aavCcVpMwjG1_O<8sVQu{f*CI-to!EyOXi4pHHpzw;;am#KJ>;Ef^o9sE-9h zT>Y%{dPB*JeiTnV*K^U0G1D!=x-XD<(P;1e9eh}%g|ar zyouBxR(vZ?6M3*yrhOeuk+yXtyLj{_O_>g+21ipFeQ;;njX3wcYXj!c!;~!zlMKQX z)MX_@SntzEq8CzQ1+EOHp(}o&e3hD^Bq4L4eJd15;1m7V{&+m?W+RfYpsODNLjSkPfeU&(~sscXGzXEP9 z4cYTD?>mdQ73MrYg%9iqv2jiyc&ln+2h@3N{LZOrKcLFb`&r=mSDc|I^-vWHo^5{| zXC+e3%85ItC|5;#VzL@(P`>G^7`|8V4THXgb0M1C{SaH8s ziF~g3@c7iMINCafHaWC=suJh0u|D34;|w$O{krz?DOl{C_TuBY8uX(oeB(xuj%UwR z1MhT{SJfZR&t&*%g5}+lW%#-a^>;Gshx9it9iOTP&Y2$?pNhl(|3NpvkErJj`&XA9 znHN(J9gdc@}I_muK55YzN`vK~q9mUQ%W)4~FrIIdyyG6ZU_53GEXUsng7NZ&shPOvEf`Nr zba}^b(qKH_XnDsyZ^3xJDe^9gw?!~szhHzT>Ye4p^No^sQSTfl{v4%G@Exxm6nx7? zy>~nO@Ah?pKJZl_o)UKYY1}<(?@{r7G_=fMiDvsYb*Rflpaot5pZC;BNO!=`JL^S{ zK<-(y9nXuiT~xhQ^C3L%%XU#9>@@*R@cGUDq{YD2`70;>-wYjx&-1)EpDB*~aYM&( z&-gY&vyOP4*RaF?Ylfyy$vsKG@5JZZM(clnVd9w=&+~f4(9|*Kp?{raipcUTMs3r6 zj5wyb$Iz_f#pqAZIP}|weoMul<$W3hsW_(pnnNFP=p}~vDCC-l{w8~l7|itU`CT8h z9&yHB?$8??`r{6LqeG85^d5(nJxn6c*PQt0Z5nm)4>rw2zQSnzD(9>@?CQ;oq_=f# zPh~Xo=AIG$Y_)MsS64=vT2j>NuCBqISP#ul@s7-j!JhPn!S-Y#pQIzxG>{q{-7wgO z^Ql0jd-_K@OOT8YnOzM6UVO_y5OS*FZQ9~tf+YP;Ucs9GjrZr7C~THq|9kYCh% z5y|Y&lBgDJ?%H&HR|Xkv7|b_Tph4SU;yKaPfulNlGs)4+1{_a;AiI$f(AJC-EK(yq zI6SN!{3`^tYiPJHrIMiOvM;uJ0M>8R|`4AA$g(Hg%|zj|$EJZXE8tfyX0ZW0F4o2eWg7 zJp%*7y-t^63&!2ThTUTaaRCj+o2E0!VVJBf%rmrW{(={;IW8dqz!cVDv z4w2dAhvR^DaT2hrZ*;h82TC4(c8*T1rZpQd{MEl-f3Mar)8Fy+2{Q+{+|2#001x?A znK?sDy7OI5dI$Xvdfub-F@boLJ|^M$E~>v&pT$t$;(1SzzRaAVa5=vH@h&0Fxeodd z(7#y!epkO1XD@)Rz&QOl{Z`mVrr!n}`s+MpqpSjoMJ;jhqE+SCfUjH73*qzK%=BC6 z;{#?Z{VVlcQpFk&aPMQG-pM&leLa98xPod)K3=_O3+$i>Pgc&RiJ2OV zZ-PE)eT)^SSfi91CoRp+vbw_|JQY zsazP}`G}=XZu4>65l8vxFnlUJOiwCDJeFCU@GV6EzgAmJ#BqEG5})Uo5;NHf23^d0}ae{Xr0&F}k#uNGY6)kvwje8r9#CicU zd?f!8myK5iycoh*UVe28-kZ3$@z#SNpE!~40|>YIwt%2~;)L&d;WOVs-JlD#$FCw> z$!GZLEcw`fMZW*-;2i*6Cz%>PlHYak8m;={SH9q#i~PXq%{KWy2I4IO7$@a;58`e4 z62N1=tUsAgXZfEHJd>XG`}yrAPVl&A!)}lDz}o>P;&IkM z>#wV@Rz|I}K@zU1uEaWN%yUiRw+nPzZBLJAjN=;Wu(+xsaSAhWl$fXqZMTn@jWJ?k z?mj+0i)zREo_q1z!fx2^3-VTAuG5xL<>l}w8S#6@vzX6~WGALC!Tc)MM@0|cp8c|S z`{b8m&rMdwcTahT58!v0-BXvpt7Ez%yXR&6=CFWsulhHd1Gz`zyK`?=Kdsj)QAXg^ z9|l(J!CW+c@5^5N_Q`1cwwGhTcog&QZz8=f8}cU>uUh8sVNM$NmBz1vuYZRD@PGQ; ztn@_I9Q&;O6p*$$t%|P+I31iBEBr7o?M*GW~FujGzD|1eHp)W=|*_sWb zNTkd>W6op+?n9T~+sTs4Rl4>O%#R|g86{nzlKNuKC~ZQe)i$O>k7Nx9s&g9^Ny|&r zq_gp5EH713pEj=SOSfe*H1E$zO0{pJv%mKSnz`=S(KC|jyDC){;u;OeMk$Mb)ir6% zO>u7sbL#CG+Ax&fnIXZB!A6$*^{IhAxxXeIHWwDG$gUgg-c?STH7W`7DyvgzcGVa4 z^T;_Nj_UOJ9x3K0oOtT8^_UZDXZQ*|7e=4YCg;NV9M@xRjAL6pm^miZW3GwgEAx3r z=b8c)$&=uvJ?Fr+;%#xot zLd-0^J66mnbzoeWQOf)X@$<4~(bnqtSkm!Xrz#+GEYu(P9E%e^>H+-jYcUZGAk=dY znmoKn58|@%)`O-#Ax`l65n$sjweTp5;C%u2Hr^J{9ACr<-scfu<26}$luPh_gnJt= z1G*62KRI}pSa{T?1+NKUHr~DvyabqR`C2VJwu|81;@~|Nf_I~Xx6#6*HZFKyaqyl+ z9NSnN`RKmn;B{JfY(K&KR|oGc#1*Q)e|GS;T6omv1#czvKCt@zuMR{fXmKK65`2L0 z`(Gaj%Ei3dUj=W}!QKMl5FYheTfSRCGy;e6@qH_J zS%a5A7+u&}(;t8jDsWnJdEU#&SJE&Hq;mAZ>N~DArA-8`Cb<9?^JP6zHv22(6-+V| znu~GgY#u>EvF!>7Ki`f0Ln$6Hk{WU5Y*rMWvsu2PsVS~p>9wXu^y3CA#ZF_w!|>ve`Tm`~t3FwQ9mUyWJ&DdBHo?I72Yd6-+N#9l5h@eQ?B6xMum zk#@7*ZXe<&u$J=B#N=~hoVU<>w!H4^vXS)PWFsEdf+oH@^#W|fqY6LIb&>EduJrB) z@4l%B=5*e~x;KVny6gR1dsvBei4|C1h`GS`bIoT2d%QRg5{-T9bFdu_CrfJT#Fh7RB4WWJ!=3Ceo#TA-gkvRHc^C|o-Ry)2S@{aQ< zw&Pkl`F`iK&+m8q1nWCKUjv4c_=gP5XP@8q&ls8>`Cm1(#LqLb@H|6){}1`HY5vbR zw5**Hy#LRM$0iy70WITuInRxsaFxZ?b^Wjh81`k-v_937UU?Z81GIfSj47G0Q1wEB zrlP2J0<%Y{@U|-E-o$klQ}(hqiC%#X^i^FFrc4G6vg@MmO|wF;g#=cTk4Hn_F03>m>W4d`+FHfdPEQfNAD3 ztV!=2-GPN6y*IS=78j?9!!{~zP`#V#F&@;Q6V>CT9H);TRGR6d!#_qJKZqQq&yM;| zt{Jc!JJ{#S(8BXgR^HM9JF}B+&891hd9CG@3%JIJ`2y*@i|u7c)LJz z926&bzl8uB?*ZV&5k~nar^xpTP{(PBdKk2%VHkPn=-WEh z3kcYUi@)89t{uZYWs^3;t=9*l!AdB2u8#Et%0azXoZMcM=^q%C%{@IW(l=hFZ6ofp5go4)`#@Up+gZ$RJ`xs1nEuTR`$G)= znclJ=B!C^+3S7u>`S-7yng#hhlvnmoth;pYRPCaNa(Z70>dWjMsZwRrx*_Z4^6&4R zN^su;u=%^&xvCvBZUmStBll`BeHE@6k;lP_8QIvr3ve#k%hivobID>q`DdJ&q|e=| zLp>Ao@ZEp*I-aw?o-2Idxg>V*8YI1r`!(bo-ntKTyr#~;f}E@a38&n3$d6|+vA&Nl z$!x&&SL}Bj6IeHu?fY_TQ7@`LEk${(y79bgrt!OawXQS#erejhD)Cb8M`#OREI1AK ze}Q{EehaE`|37elddpruiPcptd%0%{ZTbTGUWeK@RtG=QGG6iT(7oS-`%2vZ8}98s z6YFi%NI~bU(5PO8I;T|M&@?3{|Pd8P9t-ri%S~zNiTN)$;l6$p3jt& z;T6crGT>FdAY#ge@o<6q*5NbQ(i&5H?$GY?Z9)5C+)ow39;payV?U?G1e7uDuMGFFx+}OjCe2p!pmM_Jj?HrX?~Yr@83Uwm)~;e zS8U_SIDcElZ{SNVU6Orp$&xH>a-4tWChPKu{HyOD^<1lc zKkA%4w6WS##J?szgok65-1nh>sruzGJ?;ZaUtO-I@r z)%%R~LmtU5Zt&wsBXZW^{-Z{|81Bz9GFIXKIuq{Ue)bt!X12*8>@|EG*Auvi?@dfh z?m9F!b;v{5p}o0zAIAGKwi`Of-PyVpE!!^ax8?Y82=(zSOp7#HcF0{fF)_`w zpKFS%{gsiH&MCCR`++~b6zQZKYQCi<8^!ZbO)Mn?`V@4~YVzg7woD&KpIVCd58M2Q z$Ul)_pXIwI8%2L#fWG@`ZG7(((@A^GR_~dKN%W%tK7LMH5cM+95xfPphaSr1_lLHt z_Z-I$*13eofhqMo@4b0^$tN$TepVl>)MMys^!0dhFZPLY|Lxw~T}@~&^rslsG%b(u zy}1|9|HR~#mzrlBZNfUh{%5?CMyJ1wa#cdk5%mZdo|f#iZ#tOb$uxt z@t98X$RJ;72iENzw3WieI6++@fqe2|x{m9uFiGph+NW6mm9g6_4Cx~i(>qb#O4L;p z&&Ol9kK&%=xTLQEW-ZD;X5_0yS>M9`>@~4(=iW>n#Cz{!)7aAI2e=|2Zw%6kM@tRtz13e?+J95kLE)?1y)SK=j|gtLELfbub)cJNAGl#}$D z#JAP=!aXRHuD|x_yWf8M$#%#fb-f-kNSl)962wVIIG+`km9n$kq*-o;@w@0FrtAsiCGSVRBe&uD2(I_x zx(U~BNKeJ={Ld^XGd-7QJU~c;F#-Oj=hdy>+ zt|A$os+jwAd>ihbY&!eC+{3X&(8K0Wotc=J8%Zq5RwiygR^e@({4wg|`oA5UdIae! z<1JG)hxbhFTXA3R!2BRaW$a4<45lT{o)x#}i18HU@#6b*zKgyw&9$S6_wCDVL>V8B zFIIU+kaq>rJhcYj>gYp<;jr;l&UgyDS^=J~6Fq`?b@CuvZ;vxed<%^a9wgQ+3*n zbFM2ZvyITX^5aG4+wP6*?Rb_bCE}wu> z?Yr|5&0D+Uajd~Y()!3~wl8Ij&*P9sQnH{Nk@6M4C zY`KeX8y>(fTli?XNMg5PBDdP(e@{nxuaAvg9KSl98Zz7nxb5Qj+JWKGl%#)s>~_O4 zoX)@;>!`O@ZCjNTLJ@USYN%&0<+WnTStjMJ<;J}MuXQ+n^YG3%5)BO89KWdtqGg8T zeTqj3>_L7neyMkD&&UwwsJ#tC+lD;|h0TS?FFv}nw>OpQOZ8b{+j@{)-^FoNNk5C9 zg4E+DZByy}GpFZ#$KP&jN4p2M<8L>%qum4U!N|M39R$uBR;XFHd@O&v3G$z=&I}>P zR>gn1_XYS{7@%B`n|2a{A)KkmJK9MI#`6cZyrUh2VEkN_UyIMe*}%M`U4$S%&fY|{ zKS`-pqT2jtIsEp6!1>5?oOo!imZM#SV1Dmb`Q_)5ISZI~JgYazzd-Tl=YRR-lXp?f z9tQb2o0xaBa}bPwulGe0-3eu(0`V+=EAF*(?IOgT^l@QSKF{I};xAVASQ*)Zu2z9~ z;=kZ`!^J9{{EOl%E|}haYq5Uc=fuBH;k5{WdZYOS_!}MmM#Z0hNE-9ZxZ_#9!Tc{! z{Cz$bG!D!0?A{>%2dr4)Epy_Rd3*VOgk#H8AfENX_p5fx2cC;R%e%?SpY!;??$F6- zU-X|PjsF8fU!wTyz17wb&-_1ZXo>%S+`S86+{Jb8|68qW3nAk5D^VOl7F!SpTxTWA zvP@~Se#qE~0b!X(5)w(ag)NXRMUssnG!fVa$1$k@69|`-y$S8*pVD0CmbPw6Q&UXC zZK2oYkr3h}D~SybCB$uLLlT1T=R3cd-QWJaD@(FTbN^%iboR`gIWu$S{W`NJ#L;Qtqhz^xYA{?+M|*3gH(7DyYJ1 z4dE|_@KxI2!YIFId2w%72tR0X(TLydKo=!^bqN1_2>;6vo(|z9?+|C-h~K6V{{MyW zXF~WHfi6-0n?v}gLinGC@IxW|=OKKam|CNsmxu5_3gQ14!v8IV&j@tMa;gvE9}VF< zLij(1@H5z3cSig+h43ds`1vfZIwSheh43GS@X5Kx+T{PmA^f2b{%Q#SP+-WQ@One| ze-Gh@Lio=@_`BU<8F-1`5{s)EPNhHn9~Sr9uXDW$J0z)~y_rS-czBH;Lu{ytHUPo_F+r0S;iybUkrSlw@FjgPuS&?e< zgm$5$D648}R(16DEjN>oUULkmrtaeQ&0BmMy>nrd<&OP;%G#odscC3l*0`;^v#Y1Q z$A7A#ZJdW-5Z;0o0tzV*DttO;fyuJ^VpH6ejx~}dUT68F>x3Os*0&HGbRHI7+Hzn3~we_r* zR+kTtM|9&$D|&)1Zdu>a+s(|_7kR<6QrYO$X;MAD%0(HhKXLlqaj=5XSg^E<%CK(h zc;rLstSa%Xy_>r^G}c%2MQpzUELhXEqJ5hy|C_wt(RgZD)75NFq&a`r6n&fC4<&m5 zZJfDowfvxwNXmz{^j*_XtU2++tKo>*rmn5+tJ-?|mQpmwmzU!!Y;DbIMtr}u^EdGf zPCHNWwDet1!`j}1YM~9Bi(Gl_s%z)hHmtIyZAxTP#3$vD6lV1pNoub zsH8`0T+M0GUb!Z5F_%GknrcbcwsAMs%?&Nw2dzmgqil6;SaU;nyY80O)R^Qo)A`WI zO5lY>8HfP~CW{L%KRkIZwN`y=4$z*V`3KI^aez6rWC7?kgN>vP$3zGeX2BJAxyF5KX zmMk*kR@RkIeO?rbU(I}_p>cCx&kY(BpNs^XkjSDeH#@u>$AB=aif|l$M^Gba+NP6A z-|~)*j^g#)@UNNAjAnILmz{a|wSDY$pnH|8z=iT`VN*}nI$E^_O>JA;IIs|14U%N2 zeR11n+P@x>UbO9@q4rf27NuC&yk)KO)(G&_v=POsOn$T%HFfDIzoraEf1>}hm|qvo z`jx$A=zGHS)YMvG+92qCTI>v^SQvgrhy3NdHK`utT83g=e336)-EI`D70((In!6yY z&XMG;=#XH|JfgAa&^#N>hQ`h7m-lErp=f*T z>P}r#XWIz+3!H#lqg|+a89|Rk;F!2xzj$^@Nus|pG2RwKv*5Pg-i{4S_iV>`$%n_@ z@GM-{wW%9j5F<4|xh}2V-*r8SDR4o#>ZZ@z!#WUkf0KBeQD;C{tX}5@p{d(AgDA$o zlX1bghRAkASWx0>*=wZ4!Qa4dUvCCArtutm8KU#b7Qup{nf&$Vwc|{SgfsSt)%!|? z8?PNz^mK+`oY5Phc+{<2*R{Dp?VY61*ip1mvu$Wi?UJs(zOGGvi)vc^LNcwXL6yuk zG}WAS=xw02?&AnUZ&7l;MV-Hz*>tgT=9AQ4+QZYnes5DKT%U?D>!$XLveTe~gl3hp zCZSX}p>?KxoJ$#GUGZfpyJoV$O=xa7nUMT4_S>=W;rAd`OY@eF^&LgWHNFVy?efQ_ zq6&KQ>9(@`Z|6#P@!|4$pf~@LGH4^E!X8So|NAJ@ANNr{}#ch<~HUdK2-A`0mn!q41M}o6&6NBTsNAPfzIu*O^A8vq6wRn*{&B$`N@3rZIn|% z5_`YkXMG*3Rl7--@XvYPQ-WK39jJ=eVc~l?hbeeFdO-z0Pr2tzMAaWsJ_Hfk8bRc! zJCarGk8cwsy*mUcKYIl4AbdgiJ}5~1AGY`-7CtG6|HFd#NAZI3e^l^J~IY&%IPZPN-H0{t@!F?$a%-v{15;zqp0f7S6G7uHXa6#o~2>Ddc1E3oRsj zy))0t^*e~lyf2UtM4m~Y!ZGd5gSLJCifw1WuNEEndeN2o_nFW9WB+b*u-(VmJNI|_ zGv2%SV;_MQ+8aON9sQHtCC>|>;2hK+#f^KTE-!%MgTF#s)T8to-rO6dw?f-{qx5>R z8-1e;<`nJkW#3ic1(V;Zow^f>VT3)qJijNu9v%rLY8*@4qfEl7 zK8%tV@j_Cwldn@W!y9dIr)aMCTUUY1jBk`e2+a1z=p(4-v)Dr)h4;1W{IS5PBNK(- z8z4PhdYWh+XMAer)p$i!zl`-s5brj|3scmITT=(D;1gt+X6Acz|HsiKu`A;f9n-*~ zbSrRk{FaPBwO%a|xS9A_x&-_bAMw-iTgR^v|H1g(TZG?Y?1SlTfS*h6 z&zT@}0<7as^FhA59fHR_#(L6dBzoU{12@}7w_#D4a^24Op^3WOnWny5BOpXTz4-z+}SiQjpoFUT)OrI5Wd zj^DY^1=HKjTuXG~SIy`6eKEvOZ{{p>%q*SIyF>i8!7q-z_?^q=_?6O-2IY4({B$1L z8PUo7k)!ibZzGwz(f$^2boW6QOvk;1I|p}#`+iHObR7!uI|M)VAI>;_n!gA69SF$f ze285-BIHp}&WGVwsNDZL#P3P?xpMkD0e;Q!dj~kh(3m$Ma&eM{e(Spwx?ucX2*mFL zmPYAqvGJ?rx6GUH(|bzJ=%>ETmM&o(-Z!g#BgPL$T<14f6@ zHzrSdEz&e?2$7&W!s!-hl5T9>_>{ieeX(y(u#Z?n`qY9lcqRY<$rJYwjs?x1Br1Wu@pHD??u^tB}^- zLc&MiQAYQUonQGYvvi7+-1LTzxetv#9?66Bm3vKhpg&_T`qH+ill{CW-@22fuglTf zp*Mff4cqT(Um?j;||?a#gtv=7#WKNfv(m`#Qc)|8F6EuNp&iW{GHA0;Z7u z*MKwOm7BVkvqNYBQ|!H*jaiyti>de*elI6W4#hhyqOuqPZvyJK#%#iahRgM4zaeL* zmLg|#$2e&8o(@az#?0Zb^woaT;sWwLY;otVeFvF-KIyAn9>_A$e>8+Y6v7`3;qJW| zyqdRVUI@8QwMAfs39roi{XmgWcMDIlC+~-)4s*Fsf zhudj!$$KjK_4RwPtPl*oB>F}1>_8(0&@{`V^yz92LwQShJrIVJnb)VeAF>Zf{daNhJ zi{Et#gwW$Z*F&gn?QLs2T8g|3JoXjvky3+F*=HzDO*9hLi4Uffp9ejaE2mn z%v}Bk=Tpy7a8-8QT8-$0U&p7ox^!I4?|wdK9KQ`%1o<7t^9t<5PktT0|H1Ddzr*07 zbH?%e3Kl_r)gY>i;-`2ye&6SJkY6=OA-Q}Px*$Kj_oBKhei{urev|PZg@bBhHefw&zi$rvkZN= zoP5Ycn44<;hkmVL=^4}9(6e*XNc?d#PgH!n?Yy`I{aB)xPEj|<6VzOFG&Gct-^7$I zD`VxyshHEbIgj{>OO zMsvKgEpj1HbEZq2BT!}cev4NFHAgyXaRIrzH#r^NWecfKU*i&Wh0$8mr+gYg{vtz(&7=;i_$NMt#1_T)yB~V;2r;k0?rJ zTp&8Njv9jn`E`St)#l!WQ|JCn!Xgrh%=n@yMF_G5Mk1h816Qqy7q%}2IXLU|%yfrbN8kF94 z&yK0wc*^U~jjhnpZ}jM=pe=1OZ($5QWXE1*-Mov@>U8&`dsyr6oseT{z>_5U%RdR zwr}dK5T!$Jdl;GaBR}|vzt@_R+a&bTmvI7pz6MXot1N-6 z%jNrDD=Y7RO*{_V`0LjO?t9m310S7qoW1gH;M#W?I?2W5;c4(U=_8EO2qQQ)E+!+r zjdz-NWds>Sn4^`ua^d1B9xh!@eh%vW5#^m^s4;f}eZahtV#3bup3dy8(H_-Z znMywG7g62Icc7Em=?1=OvA>5Uw-rovq(j*0RSv$j;OtCUu=GmI-R9uxV=TCXa@@=`xhes%< zj>iFhJHAS{vsato?6Y>X!`goy2>2-_p3yk80l$vkLB~hsI2f;9%IAszFQr*;gSdFE z36-CXxGi;s8F(4r$M|mIJHYo0-;emDdt7DP)gSSpZ601`<+6;pIycE?4{@O2&RmZ! z_8qKQc)WXhHNR&^^iGvGRN?)7<}3F18T@ANap)bgqwLCkGQVe+_`hTN9rb@t5e@cV zneXF~M3nvezt2q5o2tCwqd2HdM21nqoFLh#?nr+)$uK5HUENPwT;960thZ^|lR)2p z{8`%F)#i=Ve$rBA-PA^_EGmCoSqMW%>-g^{e2pj8<4<_97S8#;ZKL zc&Lw>o;a9sZO+e${b=Go<2M-h)Ch5(5s3RVGIgwFXaePDPk_Jrt7SGHTv>B@t9R2b zOzO=s|9vg>%U&XF*2U(Kf8jhbeJ#97iKEJhdne5n5wm923BR%?ox`}?w8J|0p?nhW z2<5+taw4}<*4l_`wk>dV&6E|L7qL8w(P-VSJL#XB2!>C8Fuad)`p{*5zv;C;VdA>N z);-r2?4g~zI>8vi^WOmIU;IEO>V4%%q%JkQo;OO~flRvT-xYV_G;Ler_8Aq}^|jv4 zFraz3FY%=rl4ogR`?NmXCR-WG9)14C?u>w4nYB}2To^W|6=-O83U(uPI=O|N*6Nck<&T))9 zI@tX{=3wgsnK_h$xqJz}I=%+J3;B|KEBIFNHSw+CyNd5>zE-~Vd>i>X`MUY~__p!g z#MjTagKrY;)c|j$>AizpguM&9Jxx0@15JMUe+W0x$UTL73ik(bf5^HYz69KE+yU{7~0dGxL_YxkD z-Oz)wwDt4WZtC{@EBql#!)jR@C*#+4Y<8~>l$U#X_VKN#-P7{}n>u;b$a5UryUK4?a=ggZEBC}C_axI97h>=)u8xG2maF! zsUZPV=&V%0*^7D;LZ^Wy zWOcc3gRlhmpwW8^TCd0%tq|ml-do6b*D6TP=zWEJ_wc&<86kJAO682sO6B|4s!Pu3 z>{Gsb%=@@?eu}=V1o!^|zMtQ|(MnCu=qyye|EY%l(X3b*^#x26Y30*TH}nUyG%Uyl zj81ap)4$WuKa!=%-=&DMs+&(=8KT#!Z_enwg?xJLrsa&@SIBp-GW?i}TBDg!&gi{` zeEPEty~>7fbgDaNqFy{iA2;;5^Iq{BF~9WQLO%alA@}N#d$spfOYthOgcU^PXWH83 zuPBQDxyC)~T;P2L`OleXh`u!E#4o+C@UuLdY(X-%QSZDwSG}(gGg!*I=yPS=_pi>_8O866 zsKb2sh7i6bgx?p!|GUNSh0RpjgQ1Z76f5$CaX-UbXmOoy*V#MW32;X7=?&q!TknkA z|4#@%J7X1w&{5v81SO`C#fweR8zdD3(v-nfEO{Km3 zvyl5ghw$eu{-~jUr#C&&MVRzh+;^|^{yOCT-U>f9R~!E`y^mR3w(|dX7H=}{Ro>4- z?q>(O9MNAC!Z%vH-}pbv`?AG#-e9U1_g)Cmn~eczWyG&5&}9jKHiR$We6}-k|7ZyR zLI{7t;wt7-X(8SSxxZUXtkKUoL7XzVAc*7M1->7so@ENV8D9fW1@M0b-xa{CX~0F> z%_sV1aGhIGvn2ep;OaFU{x{(K&*Dcx6nEb}>gnzT6P&F3HQ?$+o&PU`OT-TU9=Nj5 z;Zq1)B5?SJz$Idb_k$k_;D4jY2JoZc{}RB@C2*3Q_5X43X9D;=;Hpwe!xVamrxjU@ z!I*aP#GACL8pH!Cb$J}al9mT=YBARp;T)d^P zeVaQeJNEMn$Lr27bcDf=>>Mma=C4>aLDJ5;kpG{ozf` zwJodBz+LRDaMrWU1E=!5kQi%gFYj({L!of{<(vCDI#>4fHg4|PvSDK(SrycqoDHnO zF+w%<2yv6zT|Lx?Mm>`O1({O&x_bMZ!q?-nZC!guXVF&%auMQ?he?@?kP!Ioa-H{(tU+NpTp+6y(S*OWYx6Z78_ZRa+@%qIC0ZJM zW>?e{WoL5aWcBGAwUh-#XV_=8;~1$Gr{ndCHgwT*??Mk>uo70JZI=j)N^9vLw`#46 zs_;Fj^HRkkkSKI?s|fM9BQU~?GNR&5soL)&1?#of{N_>*x#hE_ubp*W_Hh zA9Yc_9-Y+1Yq?c-`jPg|&aUf=)~)=iTC1kR)$-!3O$2DevM<^cDOP#RYklUd?XGX! z+_siyX8l#y;=$A)2rWlTm#?Z(tr@uHc~*z-H!9L2o)=!OUCA{#Bh}V+r);*S!AL<7 z&9429A(A!no%Q&(L~xOUSkcvYUHc8a*#L?*_hB*C6!dNsv7aIV9zVe-CiuEFZN1k~ zlA4xl{=vkfQ;zgpiHYeHOw$`F%YWPwftz!OLtavWGw0W6Yo|;;t&mRv`c0J0*G?9C| zsdxzH=>yZ0{$?+x2DNL~)cY^~^lt28D$#yTNA}UNVsgnVcQthZ?`?e>-K~Ssc~1Df zfHHDS9#5&*`-E&N#CgRuz6$G^=yAG?=G%-JU^WI^5Jifj@}b*BW~*E zS@$JWdNXz(mF#Ngw_M{kCl~u$mt*pt;B7$ddyd0z&BDc7`nnWaw#gV}t*CPzZSOy- zl={J`!j3CAQ`1dSM;S?;Jm}Tdw@Rg%PElw^>2-eNx~_|P;jZU~i)mX%>B+n+vZiax zx{XV_x_Z`+($@ktO1`fxJ-uC{osTuF+sN z7umbmE3A&)l~#B6hx|L-(iMM`_^q=3poViQGO*w_orh{u+8!lMNStZ^#~h zS|}G^?bnHKToCuUg1FZS!Z#@h-xY$;H3`CZqab{Br$V~#w^{c+f~0G&AnAV4;tyL~ zd-^3Dg4AAfNdxi`WO-e8T7^GpVWr~9p4l8h4hLK)_zA)nBpyZ{EmpqRAC`TqO;4NE zt&V>a&$Tw5>&P$oOQ-mNAoeK>9}#T#<0bxzkKj`lK4;-!3tzJERl#e>N5RFE=Mo^{ z8XfJxxbO{DS3CUbgaf71UUXLr60XtB4xdip8%dv~yGgKv8>!ZQuOR*&6ucHadV;Oxi$P5 z@BPNHFH;|<+ngP?6W&fVYa^pnSuu)@mlK9J`hAJ4M&Ls8&xZW%h7$(Mpm(H=hoJvc zwIvzkS!^>T_heAb=$DpFd&Gc^;b{>HKsR+z>ack5?!?>dVPvRV-aP!9Rmx8d3h#@u@$Y z%crZLG`Hq^50K{Co5&}VG=Fn{JOc9{Ckl!-+t-wzF zPUmy{F2H|~UySrfrp`Ei*M{hl&{fEzHID8Y?1JI$A>3|g6z)6tT)1Bi@mobktG{=~ z@%xhyzc=Bh@rd}v_#D5tLi{Sp)U?eT@pSxt8RA#LxIi)#KaK}w`CW-$th43$4Knp9 zaAzF9X6S4e@H;`a#rTCo?uck;RP{xHO^pGXwq zC;f%N_)VXmN^wXQ*0}h+8shgR z{8Zn>FV5%qCHN8K*TBIu#{;tL@3~k8<+qmxRrOl@W?4GnI=dR=cOm><#oigmyCcN! ze)zfcRzoa0@q3aVs(&QMm^mPFb4I`Q9pq0ie$NHscdn%oKfOPt_))x!nF~MJJ0mw4 zy-%gz6k}uRpsRI`*yyJ|E?yew+Ma7B7uLP-I&`E#O^Pv}h0ghrg<~z~;wJk?p-Ypn z-{Ch)Kqjp*pwjAO!cXu1cjG=ozkK8PO#uzk9Y!v}^TCd8@oMc0nB9ti?gjKlEi9~i zp{{OWZQPg>>qUM;85q#LAiYu2uW)oJcaszS+^yoyW)t@&xkptBUY0nJ@sf9B2DpDT z(EmWDn!9Ed-WQHU6St(J-kL%BZ0_Gbmnruy8%C@%%eWil?zTmeJBEJ7ou>ETMzAxZ z(3NoKDx&+rx)T+XnzKk~Gsf1ld9{n*}9t>zxp(d~bG#L4r& zN=JmRbK$a~7089MLi3dxUZJ>gcYje6_sfu@?*A>t?Fe_h6ZVc-g7i-G>>bZ;WF6a) zy`QFgW|IPLkKoVUWz=1_pqsg4b^<%+*WFojad7$}CZL~zuIWDMBye`z+Z}ZAi!|*t z`IsmcfAYx1BkR9_oeMXDjQ)arlJW92V!_t3fL$)@Re*|@Txa{3_tT>2!N zpqq=6vvYJ|Iqcx><*t78X`}1<^TcJ%9S>wAi-Pg#&ZX7mgQGhfe_}9-er)>Ka<4lz zEW9MKG`%!(gm zp66b0+{%!CsXP@cF2kx&`EoMx$fr*HIoU{tBjur^3(L^S+Lf7|#B&-A&Aa$Cu8;Gn zZ>r{-$EWu8>doG#XP=X(y~=%`_C9w0`QG{Gf86`n@B9vbxJ`9VqT#Bz{&=7ASRVR+ zQn#Gi{hTQ^V>;mn`AXDx*7Tt0o7;a}w% z%Df&{{SkwpfYF_~ppovmZw4&X-~BR#2j3`=dxz`D_$}PsDUvtgKMlG6X9&L_(CLbP zm&Gq64O5B#iy`-g*|homJ3@FWgg+I+yt)=40ovs2knaEo-?%+_=u;-K@^` z&Eu2XqLzzW)^SU>kC)7^y>@&&it7t6yi{3R7d$u8V#bBR<12~WI~x9JaC2a-uYFVT z-OhlQai6^`x@Q|;9@5ra>}*v{oua(FtCLf`=DbT{CDHF)%6;z<&fbT8b!=-ae#*Aq zuj9u(V98d9zgIcc^ZNNM-G+Mvr`tUO#_y+h)eviAD~ ziKq4s#m~I^jJx&(g{KAK^Qy&P7bLtlEi9!!5MCw--E=|xsn1k?$1T+QhVVHS&b2UM zVV#A#qbj;_?-jj`Jx^{~d0b6-p$;gIWud5_L<9E!Ykip-|2gAEeRHu0uAS%|BegFq z-I(HEG3ln#dWe@GTy$$${ddC= z=FoB0oGMvgs%YxZ#Q3K3Rq@4}4rJd%Ku6Zd3d#EmrXHhj^^n)_y&BrAJbY_*KYjJo&+}FYB=B=_rhvTr;o!lH&y7HX6blXTjp>vZ?Kriua zWT&;O?Z{aAk^TYQbm-wr9GpQjKT|rNX3tFx_QZbrqgk_3gB9MAp~=Vyy_eID)jfXK z=1HAe({@4*-f+l z81Yt5W2knY^3T;5%F@g#yM975Hd8t&B}3JjD*Fc8FDOTqF)K6N<^OfoU5*lt(e1>$ zXjSMu^3W~!8g?!ZOr47#$W+8B-+a^gD)~zJ%J`H|E*{Ut9~+Du_?Jut>o65_Z!v3W z*}6+*R(^Vke_PZ`}cp9ryvp?k4Vc(_UQ0dhn7ob-Y~Zn;5ri zRPw`HaiXn^?PUGZ&sW7=WlC*}mrf189zS5}yO$>JF=Ub^PJGk()CN=m8+%edf{OOOh4)$~9L(*>tqytxJmJY4Mtp`}syh418 z%p@DhiPetsiO8Utg*6ZeF^7NNpV_ z(K2P}9ho^zx0^7c-lN3%YV5ZYx9yZi>B`+Mxe>nl>+Pca(DB3*$)?us{(;oKXAd8E=3fpy_x!iN^TKyu{9gL|KltI%fBW~Jz5XBn z`SUk^@ylPm`RliiCd!I*z66-;1x(aCGvppF4`+E71?Y35K;JUzG1(0m>8T1D>1ArQ z7IEM#%F_)N7m&33^#c>vvOl| z+sciNjYfxwnazhCd=(*1tweKQ*nLE;9Kl7$rk;+i3waTy_VW3><;Y#vzOm{}Xk1>-+zv42A<%^ZQSG09@tk)L(I3uiF{P5W0Ti?57 zEo;|}<6d`8kl^*)EXqDgSSYnFH+Wt1ByywRbxF&*rfwxmyBu)n=-ViDoyBh_S`YQU zqKI)usMtDnhBjJPRN$b-vC)hl1q zOLJch^|o(gPuKNqhVbkuck|aNHPWtwLWxaXTig96W~|lQXcQTt4!O9fRE?l@#*x)F zZuFJAjFhgLk%&UM=8Dj0vyQhF+uM4I=XBkQuCD7Aa!pT~1VlE%v#w^pw`#84CrH>k z6g7SyU&W%B*60LNf^3fOv(T*5b5^XHKDP=Omp%TM2||CBg`I-yPhB&b53v(9|mT-?#Dkpyxd-JZZyS=$|hWAB_o=9uw~JoWFzEpUJ>T zd>vTfi zMVp|p`ph;)Igew#6OcEEG;Dr@=l}OJ_79#((HOjfPh;fw@zF$>PqQ$Zy6m1tlHWli zHyQcUZ#$*%lKc)DMx{ycp{ex4wR4^%c%07}M@N(A?|oRhG>H;_#Ye+` z(FwnlPjS%Nyi6BLiQ zwKI-iYlyB%>5)fk9G&)ogW=9$nxBN`Y(A|(xNyG}=7+#{;O>m$_jrikM))cI;-?i0 z$L~Kv{GNkfwPR-Kgq}ydA!+JDqX- z)`s}?!!Hhz`0+E#@2(KP7hs^W?~LR3_aV9p3RBV%0Ug~pL*b?Z^3w{6=p;|=YX{}B z3Vs9FJLCAh5#sj{{3;<*I<(^A_$@%LL4Jqf_kv?)>4erm7nJh>_^ED*pH^TTznh@b zejLD)&S}~tKfMlj;R?FA$!!^QDI!0M-{E1vte;2TDbpE`>=;Y|p&ZK?AZ+@bt@Hz6DhKBmlzTx*|(nM;4 zU!Lc1kE_ARPWjBjviW@u@Lc;_ZL#X6;`V;N^XzY>Uv_F+86ukB%DWHnx&4u1`0_ypQAG~ zBgvgZ+P5(K3)qp4nI$2+>DWa>cBQQUQ=R8h`z6i8 z^f~2vuZk?184QCY&YVbmO0^~*%bn}iKBjp;FAyKS0ThlSdr;WzFlT~|EZDOmoa5y2 zbI$fl2A-A4#DQJu(~!&ZHp%1)BNNj5qTavJ8-z{H+e}4@)vCLq_aHaz;L1MiuN&=ng`gP}Zgxr2;2TOm`$yV)jIyVveav4P zUcQ}pc5APZy|-3x;K;<*o#~03iKkB~FXIiei1++Uv}5LMf$9x=d}S(sG2FyUytVJA zcb2s8=E@O%XcE{6w>Hy<5`dlr7qTX_4+pMBz&I-ggWc zxy19|$E&Djzl*Zv+61NP2;pCi{|^&)d zuWZ2&@2bt@eYN3I%CGJeXs`eD?x#&1tK{9PitgJpF}_DW`84_XZ02h1>zllLHY5KL z&KaDZc-ovZklacL6P*24>IwJ?_(@);gS+2q_uTK(tz4;_XvjQ{>;m~ z8;aag&yu#sXOmuj(^NJO(6W9;z2HphZO|Hx~An$f%`ha>Ls~gx4 z>;&!rZUpWEt_SV`nz&LfR~+c44&9omIB;v`wi_Eb#@>`325VT*>{h+cW1=SG?Fg^h?y)m<=<=TXux& z?Mn@oWA9{EN?BCja(ev5mp@IpU@SUQc~uhs+)y|lOXK&LeDrt^GMG=wPrVzdd~$iG z{M5UV!9339C;3=LTAu;#Jw$)LAB>r8p~f^aZk*|3 zc3c~$A3ngjhQyNeQe>@mc!AFI@aAn9_R-klbjg8L=~WTVTwLa#+flur(4@OVx6uAx zKKLeiP}ePpsrZ4{z3k&lrs5rqrD`IvyVBTGz2u&%@jjXBM?LO6 znK$bO6ql<8%UYMhhcgo7kH#b>ZwP;4{Ih8n2hM+)IH)azFMWegH>vxxX>UMp*>MJ; zdxwc1ea+dCDSJ%ZN@M*q)b~gprk`QFqWG)st6i>c9pD_;K&G_yR`UCbLE>>=sdx8F zii6)z?KSBtB|P;r!M;;=>RT$|S%r)le+^c1KB_b^Z36F(meBqTDeRxqr?gW3lM(v2 zrWNVN)v3X|Cd^>WmYPC)6pc3BomTr9K^`UhkbiPh#0`(R_sdgSYCu&)TyqU!>0r zoLw3C>=5I`R}?4D)oSp0XND6a#fhOQwRO}sCwtcq2pXgB7V!z_n_0b zP7sNgGE^K@AH9CXwcpgKNPJ0JZI!80o?n)| ze(Fp2j*QwLjdw2oA!i?38UNe<^eAm{jNe|;Ka;2PcyVNXKlyhrWAYT=gM1J1JG<0diD|hj(PQlyz=&;HkyDd5|TkhiF(YC3LGI>v%;2}d-w;G7c zg#(1!ihcj%naTZ6XLfnsD~_+~IDJX^2e)k9XulM}=W5S8!A0A5gapg04g7QhZF?rza_RD8-*E72Zb&OH&`3>Lmv<`%<^hpuo*^`QX=~rM3=D%hsXKd~o}a z>XG8;_$Z$wN6#BD@jgVHl@}50iPxy}f_gLT^5S*Ioi4BT+PpYm^Fetc`8apgsmX+? zdO3@F^C{B#F2+$=neh&=;u0y^Qah80UE9syCAJF6=aZ(3`O@So)_t$*O7i>u()1 zYX<+5c&gn~9__Gc(>z~!@+oMtWkq8^Ti46ulo|ZEe)E&?U@O}DT|VYmo_`eTf(vxC zrTv<=EuDQWZQb4No7d}h`SlxlIMrL*$-Pgnr+vM*p{JdTpKCj}w0rArXxr@ReW=ZS zZQc#$kpi6CZZJ2{{p;tyiDRl}y^~}ZbNo3~dXRw8d#6ED=ifUDwne#rg&ko(+_`&<*B&TM?Ni;y!>c7gK4o0oIsSCrkUeD{RmH)oO~^KpmK z+~FPj3(~I_KUMh@a}z))4;b5S|I)uZHkMAPDjMw8g9WJ&XGG zK*;@x5dLxqKi}q^^S{dCYQLsZKX1?GE&EH@{c8xXwoUFDLw}~XHqZo%ewW3U8Ta>k zKMlFRVeu8l{cNu-&}7U1Qx<=Yter}IT*#oo8M$u_;rm1QTOs^|bi&Ta|Mn36havpy zA^eFD{!bzNhavp65dNPb{5`4&)+j#75WX&i?+W1$hwwuoJp6v@nL0RNjlx?T#3}xl zSiFp?F^l%9Gw2Te?ht;b#g)IaXwSYI!s85}WYnh5qCIO3;VFy9jr;kYHn(JShkh2j zoNaCq5j(|qm&J8FIGxuJz~_x2?4Z$nh54+rIwPva#_L74CiZBbF>G!p@ zFYwQqQ;2F>mbHI!OFM`2d)rqw74#C;def-ps8-EUmd%3oVlqzu=C)8rZ*OEGN7hDv~Cd9uM*}i!lwWeiD-!%=z zilzV9E0@5iPK-X=S~hHH>*0Rcx=(KD=utOfo^KDh^t5xosu!31dsAF*+&sdo#(pph zuGF$_^Z8J~ctZV5}uC!$%(it`C*7GCTxNS}bL{sfQe z`eLfPh~;cJwXE;$YT4Mfd3|TQlA4>XY+~fFsj-oPYj4Mm?TylA*xXl}a2Ev8k+`96 zV@rEaPgjphbl&~IlN+gICr&5F#!h;g`^Guo$wp(G{!cReI-`%$+(^u2O2ILoy+mb( zdNquh7*Ac?f)+|$-)!+)os}P=vdXP->xl+lkTuWOfU*11H7&(Tzq`5?xUe~1IoH;j z*wQv`ZExAs*4@(9=d0rMOI(pFsRacQ>Tb0vpx(CE=)F8{WLzw5X1wA*dRllUP-9eB z>Z$ei9^Gus4uQn6_;{~=Wv>QL#cz!U`HuKXa3K73o#UID7fXDtc@MF1b6?L5!J$j; zf?ko4PFTA2i_JD$NaLvgYWUcDzJ=?$Hg&i4v^%Y|W9QJ;+<55-7m&lzHy4)2F_Ud% zJ!6cbJ=vhfE(^5#`dzna@5g$VyP>}Z)`RQ5-IH^=#5Pi?`D79S8rq*y32k1%&Yu0<&uy1 z=_vV_f9Fka<{5ui+jzFHrY?RTwfD%|>>HA6?R{Mt-;zWaa}-ZtouK>+67E%k zoFr6k1*APF})5Rw)2%iSQ4aiLpe*=PR?OTo;;mcl`-h506 zUJD<=>$nFlhnz_aI2yP}^i|-Ze zBK{Va&X|&J!ngQ?f}ccRt;MC2vZRN2S^N>fUgT%-M+N&l?|{V*3U2Y=K`Gfvc@j?M z91`Rs$zIhqtH+mg?-PE5eKVDEt9{cF?$^(iJ$QqKCVy|V_wf7u`}4}57p(iMg4oBD zFF=!z_&51RIHr6O&U2!>#pXNq6{5#pd*uo*CiflWpWsegE}JNtR!@_r=msgN_@q*x|;V<}Es|R?uEmxFp z-9uIRT5sVtLCV=f79JENe52nNSf=s=zv+VTs}_Wx^zur7b5am~s{}uXdR9(x>~8 zRi7bU>`^J*F+uVpE=YQ{pRRg5*TRH_r$GNh;qlwsu%b|K^Cx#7pN@81yAQwdy_dWw z7h3o^xm}n%_T!SsN$hvzcB4*yKPE3Bh2?Y-F+H*Jh*c-EN0S%%u@4`Y)@m5e2y(vN zvtzd=k7Xfwm`T;>9-bZjg7XPO9pxJD3HgL3mM6WAd*T4|7pG6bLhgx!%v;huC0pY8 z#Ui(gaoo~UUgS=8qsu7!VFfX(tYy3_6Mk`(RF)V`o?ho)g12@r$-!_;9`8|r=>wL~Qeti%H`8^1~Bt*)$$$XCAcS8KkoEvv% z9KUBn{9X#gPvzI~OO@ou?GyqgOAKc@M{03`Rn*; zPG|U8x-|iQ?}pN)_j`_?<)JxZq4M$_$IsGr2GXm#f5#aY;+(jq;KjcR+eiwqTz}^|r$$XC= zL4JDz@;e)M(TU$`=9WQzTD#GiS7+SMOP~w#dk}sDcvO04^ErOsa{O$*U42${N zd))D}bae~-bwcqwhtKi*X^3BId13keYlz>~@Kd=LKec6!Uy_1s(rd$g5PnR#v&O~m zLg-9-EnO%4T>id4!0*-&Kb-@PXSw;|3Vk+2_X2cko1Ags{-02|eT3TpkMW}>j^AH7e%9eR_-Q>+@l#*m z;x`FlDLOP$#yo_OSt7|Ax#_D5(fvJii?dWdjp&wII)xzlzAF1$?H0-Nj!G{~H}{aan^(eJGVX&8Pdsp2TKB&xp5>Eyt6*Y!CwIBO zcBGQ~rBUyGmWV%pM0eUJC6}eAqu1cU#i_x8($aJ#_x;|%-S~ku@$^yd{p*f-BzCjz zqP-&B0ulJ@KApP<$m-d!*R*3s1b@;UP>g0@)4?exqTwx*d_JVdQ&@y)?qn*g#NCF5 zw;E<-!z)0yFY&wyZ(rizl#%GX#PgQlLBsD2?utJu{Xgh2n1H^3gUIEs(&=e*3HW*p zl6%w0caVF0gCzsppWC-MJpesgOk0#K63hj-N^o7Wd6k? zx_1}#_8gfM%iX<`J_z10;V!&OC-1tzpZqR&_wy>bn|RlQ)oCwvEBD%O&6Fi?&AcHU z0ZHk;Ne#0$n$;07NM1=t0H$2|p}bPQO(1^AqRhP~Qo)@=lYfLG`6kfqp)w&|4i`FI z4#;2`IunkQf#NrS4EAx~x@mDb2K|Lr1{YWvP`r%{q&Hzg5nT>yW)kG_bG(gl4!Ruf zbh;d-oRglgZ+H5Rb?2l{PvD=hq^E(gUHNJ7iz2Jw9qR--8gx%`4}8#>WOOy;xm#Tg zY1}3>txWr2O-M`s!sOLY42!4kjo_E0(Xh>y|F6i2t(4=x@mMMu+g?)*mgk>(U1exh;e zMfX7F-jDMxF?WH#S^MA{hX3Z;EIcTlBY;fzUMd1?Ri8E-&uvRpO%1Tv2# zzLR-|yQz#-cw77)>@ORp@1gjv8TR%`Z_w&tx|DJc9+4z(Sb2TadH7CKaz9r0J#td^TLB8IMr&)%^!9YsGx8SkM?_x^VVJsX(>x?##l$MeWZVJfUc#AiYv zKD75UBl|u!6iE`FWGb5AK65uTk$s=Lv!p+D2j9)Q@2j}7244OzxY4fjZWM7&G^5Aq zcHUnmO~PB1hOOL{FOUZGr{$%gKQ;Vq_^#ldt@JqQPA=VOx$3Oy$qMX<&#=myWFCS3 z9~BSWCy}PCe4vrryvZXOl_sCa{4eN9zhoj^P_OjEkGq@bF7bA^@_PxtB_oCL$As~X>X>mSJO6@dFb`~0lK;l`MNT`4WGZnAMMfZ z=lDIq@8>P=i{O2lch8Ug`jMQfwCz~DGlt$buabVNGI8q!;t)|hE+lT>!QVIV|AO_u z5dSIzCOz0i5=*B>649yKYj(yeW6#b|c@ZyHUW`m*-=5&gjNDajjJtH$c~4{_=uRn% zZ_mUD?{$SU!7IO!xc`vfFA+AwpWTP~y^!DP!(Qa~-}3u=q9vYFiIduPl2;AY)(oH^N{)v7GVM?liw+{61>K<-Wg>yL2_wV?TMKpY~_5PaHvK*n!)J zCVSsJqP~2x_eXqtj#R`HH@$=AmAATfk#hJCg!S+6`3QV|X8AuRKFQ}ZWv%kFX84v; zwYOJL?oyF&a8G}vcEIaz8Y-jA?1N72b%OG#bjpv~oorqsEBMhr-jZ!UB zKPNtnO?LmB-(Ti8YdO3BgWsRy_kY@W-a|a4qp%X4V`bt~>+cWnSLWUcBW*X3Hoc8z44vJ-nUHsHSzauHE~}Dz1~}s+)B+~PG#yNY`Ih)dxiWU+p^eqGOk>^a_{PyqyI3pYGW5tr$)*{(Ffb|1<<>;`~rA* zH$L-|*aeebyXeN(UyJ?n-(DlFkE0jv#re2J;LrTVBY&Gx9G(CY0LXG?3G_G%x_uyDE0-?wsh57$3FVzug8?O#UI4aPw^8> z8?rl3Y5OtuCy}MVG37mLHrc%Y8+dr-cl{(; z?&l%;M6W$?8$ns`xV0b?t;C&e0&%nE){QFtn-x2Tr)bL(-tKU|i?eY~JGc)Bz zdo;KQcgdW2sOjIQ$G@9VS<;wH<%#iF`NZ-sX2X|URhH26XyWnbfp~m_ch`Td~qJibmm%4|Gb{dw5NqXhe49{q{6fAdYhot-z*_}A0;w`o}Y7_!gSo1fq} zO4`avo66k&_;*Y{_(<)u^na`K#<2gUazx*e#*gx0f-SEa?~0Z-^FF!1fVc75*d06e8EpyG@fkx|_B0<4kHtBCd6MD3>a=IM9k`r?dQx;TyRTfmXL-Utx zxIeY!Y&m`l$?IjcO~~u_ahJSY*>&Zt+Pf=LnMBvC7f*M4njbX{zv%lJtig|y8}nwv zXD)VQN#DJ1=F)d2en*+UsGFa;^t}VWMbc;L*+kq6rVrVvoeIj2^cg?D_*Gu|jNR+l zDSes;M5Wg?&iE~UCvWI39*V|pX1gpmPgeUN*}jY)jn$N2%$w{yXuEMsTYee~n(+?v zBl%%|1mEqM7jQT84eScdB@f{qSN~ST{YmRzbBM3odGq5oOqa*gc~`fR^*gN-l%bQZ zl(il8cYiIv#EZ26e+?ip4V`C<6AtJN@ufq&M?JXbF?2%5`_sHjJy>yIXL>v3ak_Vy z_jE}IWo2OIq_Y@9o^{)e*Pm5!rZa%ABjg<5Bvw#AN6kg zbm=dRoc}B8v^Q;tG5eW(XKc9fjk8|9@y&Nkyzw7Qo&wJh-Pwe5tU5g`ev?ws66~T? z_??>zBTt-uST}v9>m|gmPRKyDKx5GOn_1@|Aa$6~@n? z<;{1~C!07xTN$8L9jNqahmSz3uoOn-m&fwrtaclF^p)R|`GMuh9Lmr{&-Uw*sYlS1 zLGyfo*E5z^n64VSe}b-}Rdf0)6mIleztmh_W%UY;L86a?yS1hR{66Xk~x;-nixp`rZO=f2jruwAm$#0vsRsC|dZ#YkV!-lgo4`5Hmb8U&% zF4aH0Lvo0z%wIN4yi}H=rx6#&uhR2*O`t3eluvq%zJ@&gmew?e;q{ZZe!&_JeV)oh zCF?Z51ef3ZHK*-n9qDHU-DaEhs8WXgZjAbYLl+Pg7h3hC%&tx;o9rJ*vdu>$(u5A4nSQT;sjT|Y6% z*uMN7=$rR0d~fC{`s}+ZD$<<%AFfP)o_#*=#YF2RLzM%Uu%7tWtRw!(k;s8no3}mV z)+DvwrQfqie@Q$&7)i_?io~KrT9b{$ONL4kj}PCR*v_8Xx%_nEL8?s?BGe0KK()f2_4v=1h!LQiHAO+&XELbyDqj`svv|q>`8m;qnU`m_w-5yyyXww%`aDqp7y&67)dNi$AMM2RkH3q5qHHmhMo4d z)Xqm)|E<7H@vFw(w5g<3dVtxlo2j)=l@GJ_Nq_ZT%2Eva<-dRX5c!<;>ZWC)t+x^m z{NX)(?AUo)mz)8e+PuF8Mu2|>%+_z#hE-1_!$b6qiWB|dd8*HopwqnKU$ED_-1QG` zP2jO#`fHKDe#56@EKrbc*)M#4KZCANxIebxUhoT_-;XUn##06P&B9*s`(c2ezqhbv z_$=Ji{%I|s($YO|`3)4|w}o+y`2AA>exD5RyUx-*2AyQ~)EgR8tsedna9iww%xBwD zgWsjBO^n~1j(Dj-t#RD_i(|X@VfS~;*DmCD6Te@geJ$a4oZnaSoAmBh8NG<#F(7$7 z?IC!o&)gsL*Fwr%Kb}-Omfs(LiTIeKG1PB=e;WPsN#0GN&8bQp%t(KK86SIAtd|dD z>bxD9>Ns}%uAnWN4vlpGa~6X&KWM-cd~={t8LU>DnAnN#d+AW$>F;lAMTGhqCIO#?V8S=3S77&+x9c_#tR! zQGQ>rxco3*_kI|{GZvSOq=PrX2*VlC_gQ=m@t8&V{r8ajyG;Y=$7dGhb&bWvL;lxV zypJ+BmGb&$A@>(UcqGt-$^Y~aeo+Vy>nKiz+@A^IzX;(xaFsO*@1hXCDTMch@IMLR ze-XkTwRktYr&7Ou1+FA3Tc=PS=Tju-@>_Po+iekb_+D_u%i&LeSA(m3iT)_K`b*IW z-(%gJJ33X}VbQEY)#kqWbuBGhHtSjFjNPd?7U6;gM(5*2t1ex#cvVYF@0PVKD_gkq zQ|JoOqHGlFFTLiP-uAwtDv?$#Z0l+68%fvGs+yWLT^lxZwlDAOY8!#kA}M^^tlMBk z0}I_;w72#auV0T2rQXI(MK$CtwEAajYK<1UtcRl7=N4YsgO02DwT(P9UPMGbNlks@ zrlQ*7>J68M#!VZGF{zi58wInvXgG#M!K^MC&H`~EnAIkn+%>?0S!)Z6Eh(o~m61_i zX|;_>)m2Sx%d&QEj&Rq0s z=;-avs(?I!TwJiO4xL)b6wC@6q)|}QoG^NA#u&*3>(JxYBaKH^k=vGz^&Lgk#^h=> z`jfY{uj8hk6xH;(OMmED3Q9p*O^X%W1#7yttlL;qb5VO=Q&%r-R@Vr6mwaN>GcD`7 zUSx|`x47_EcWvqG*laYT6>5jF6*sZ8tNVtF+c$Of+|byxwduoKi`JI~m-lu2U*_Hi zu*%}h_n(tL5MwHbe{D*meSuJ^rg#G3pT#yvqEN9$z)Gv$B#;1U100i}*mb*6uu?1C zDA=NFo70xv<#ye@^j^A4t=&tjc5PR;w9>76Yul5=Q!Hy+cCWkZ?seDu`OZ6Y^5*p% z5bECF?}f=Tf1Y{fnP;B)KWC=9cfl%-<8R%3iuzl>cxm_Mt-XECH*ah2Ue(#%-q&?Y zXY+;)8;WJQ9v-;1X=`_PXHR`7QdFtqM-yu%grK? zWWH}8Tc=KRLGu=uCfCN%d>6}8UcU9VVO-U@Q3XkBwAu9Dvi{m_ojp$Ix_<5yHv^7p z*227E>Hg(;;TzZz+^O32(dhMyo40rM=~A&3{IIm6tG%zYTes+)uA3sI^(w&C+i)!Z*%JL&$^16X&y#q;W&dd*3+JIHra%N56x6 z1)I3{MX)*ieMrrf;doH~YvsR!`%xTx+CdF~YOWw%LGYFc5?^x#`5zEm>F9pIm~MsR z?ia+J5rpnjg3I~cE92OjMt9E(@%J)L72U=%;QQUZESH1F_)qshH3@#um?MJMFot4W zrucP&SMmED!OQR`ue#T%N$^_6!-Du95ENZO;vHk^D_C0zTm_#FRxst2J1t1~Q_elR zD)c|-U=?$;nx)*g0xW^&qk@-^E{nGE?`FOuxRL@BY+$M@dano~k0+S8i?3RyxHa$N zcVU8rKPCwN^Mb39_gjIKcb$V7LGX?W691%g*D)b9!&v+}FO2 z`)c}nLb%D>)U22}9n@hnXI(G9JC_Hy3H-kqPoMs$_+#&Oe*J*;v=pKv(Km=3j!938 z92uRS9yc;hePhUO#Clrf$k=rZZe&zaXkhT4H;RpM@#YL+V?^@XGV6+o_j zzFixk`?cRD2R%qQ%XFaZrOsUp??S@W_DAuaqc8QJ!t~W)L~k792z{d0CX4$d6MbL6 zSUl?r@9*<8#_WW&#(bKqZHsSsgp1yT4 zdb1<+q`#ito*2E3BJ_SgMlThi$IvKG??{ZE)@uv#r+W^g@>>+4r(Fck-%FmJ)2l-Fx1M^>meM}yq@mFtvc*KPj3tUmOn?Y4SK$wYgfYa_g67` zhjDAI*MFYg<1u<^=%qjsf2y;d-ZfOTD1TK16q4Un;6?e%MC5mVgr3InmL7ik8lb1O zWdC{o_^sQR@;D&*!L#_&E{ErjLjhyx9hkwG(i3xdal+3f`g6u&{n^h&%X%jci$3k$ai=yCK?X!_Fe^@ z;V5g-IiK*{&usYFp1SLWa%d>6Qv79K%pSblRfLO96MOSM4HeDFrSGwK0;KqD`F8g4 zgkkj?P;?*44+oXn}ieBWPIs?qJcJ`Z+1H^b%;acebzVG6^*e#j6^7AaD-#X+Qjm0Nwe|K$F-bNl$}OZC-|?j+=S zexyAX{?#$}XJYQZj=6sra|bk@{u8~vnEP|it^7@-e7+kCPefEm@#|x5b9LvIZLfPp zVNQNOwcvis%GmQwZmHTn7}a8ztMgP>Y)*GKhi~K+esQ9H-Wc5a`W3x)J(&gTj^Zo% zqch`EPhyL#cNcj)!oP%BXf8gtzNLHH#;z@v+i=fk<<_m~MXT6LxutXID*J#$5xRC+ z{7u+;bK8Oi%OobpQ)eYFa*2BDmQ|hU?)KYG^^!-Cj5Vc-7g3QYT*|xZshw>jjNOeIga7}* zGhhD26qd4i>q%Q&XHnJWwXWvWMEbVY^_$vzc!y^_H%G5tSoDdM?%uO4j^Z@K=dS!) zUTZ#7u$mVsvr{N)UYXStFJzzjgIoJLFQ3oby7i~nDvedC(S6V&EouxuvRNChndyFh z&AHBJ4@Lcu-UFB|$N)tCHFRJt4z3ksqTB&2VF5#8r2^mr0RI5JA_PE3^EPTZR?{`2%cfd_L{)93;^peJ5LPcrcI{wMY* zy_axn?CL*H?;ChT>Ftg1C%!zrSFuOwsjjZ{#2lWSs?$+=`=K`*Kk=tok*9Yv@uT## zUZ}CX|2%)2@r%-X8hUF%5HkJ%5^IdH%lP=t;Kv z?u8yrU;a~CGEeXaT}k_Z{|26qBR}Ej6ZE{voyEaLQueufzc!o1U%YwU6W&SY8SA`q zp9?@ z7uerp4K+AC{XVXg@Y%`1@_*y*fHLesa&Rhl_)RMXx7y)x5yuIVwx4uIYctnllxOiH zUP?@6=y~`GDh^t{UaJZwy=DTc&5a{H{5Ba~XJpVaLif$@y>{mgLA%WG+g##l-6_hm z!uQ$mFbsb9-SUn0cgv!IzFHcJ-v{2W#2<0Gv2)Lc%@gU^^jJ-vidkrR3z-_9lovztdD6sBRDGw>)L6{dxX$_adp--wlm}KdljRLdce{ ze&Z}WixcR#K|6D$$!{N5nQML0m{1S2uckFll~EaMe_BU0S_4e|!0L}*8%*Grz|Xr& zaF^iL`k(hJ#qV|H^q)*S1>aM+&-K;d$WR^denWf55KPL{UpD`sbl;;e8A!~EwzTA`}cfL>+^ygGA zbw~P#lh~&OM{>1C`uSZ}f36ODS#TewpZjutFmxCmA5H#%I}7d{c{F*%y7fCO-9dUd zb#!PY{H4w05d&Z73BSFZJhBw1--A6$cvX_SI2!whOWW@|uHQkH-hAJ2@%qv`!?GNo z;$BsF%i{Lyu{Hem(CR?)^OTofLL-*`fZ>3FR&7a@e16Qd{t4st(bE)8Rg+?#wIi6nyrcbmuC`6pB8n*^oM%Ey~m{SZ0_e_ z8q>;xJvrjirmRBOb)Tz#%l{pCSUXZRaMy5c`mSN70+qL4Fe-P$??AO1A!2X(?Uk|yO+o!n{5 zCc)l&jW>pF%%8 zzutdu1c&ygAkOTBIicTF(zbGUhPkH^`!C?P4Vc3(4V+GTO%Ym3E2?uoz1j#)vGmHo zVLW!?2z0+de$bP9GGUsP2Z49sHvp7Q9R+4^{{)0Z*mBM<$NxW#0)DS{*VOQ!>iLq^ZO2Hh*!};$4?xM zgcXwo_vGc}RZJFpBRF0bl7BkluRQv+ZQJQ&y%wDJfZG(o6<#6zuZ!VGcj7Yf`->Im zjfvn_ySyjNZhH@>*8#OtzFqRPxD$mj$!^90y6=EHp|DrjF~G5$?#}&p^z=OmV}Cb& z6#L8QXAAyMV*fez06S+%Dxbw}u(MZVe>csXsB-Pw2Xp@$*{=b59*X66NeoB%{e5Ir z9rG`wKPHA#NLJc&6@S#>X~(JubGxB^2pHvSLID{ch~Z2Hr;E7#G5j`zC5I;3BI)(Uo^{r#`RfwM_VmN9e;&MD3!wJCQ0#AFd zigdRSe`{iK#NTS-Nar+W{vv&!?mb?|UAoI7xT004ou~sRP5cybe@WeL1lBDWEWe0x z!8q;(@n!x1b*rDSUw}g!a8DcdA?#_O0sn#+{-?knAnbW?GQjNo!E)}xt(-!cX#Bw7 zh`Jm0kD|%g`JN-f!~QMcp{axA=Rnhs)jqCv6@LcX_MZ5Cgfl;@G|3ZqhQF6b#Q<$gBV)!)W`z4ihW8)R zISuX^Y22L)8lTBcYj}GWnO2rf{Db4Z3>)m+ZuQ7v^6LE(ycrQNPW?w@9UU8cU2Tb^ z$z0NoS9phryLH05$G=V*S@`<`{P{kDJWZ{cGB~x4boQZJy0iNM;^;o@W5E-NvMGb* z_k-_w&=}U|%lm15aX$Ez4|CM)$OY)R#|h`Ct4B2EZ<{clhY~i$kBR!^m*>O-WVT^h2 z(cRpv;Z^F6Y~j^`$J+*#Yr)eviQnW@)=VCJ-~)`Ckik%C^8TSDIGCxAA^RrMl7AWb zVN8BPb42OJE0YFuhj3Rg?w0!{+y`;rJ9jYmR$vyWI@J&4j`tI3U=8popxQshIWlQ5 z_g&f1t;5*4Yi{Jw3}BF%s4{y5zds;cdb}U|Upo84*uQ~&A5b)ftGM@08k~wLf1C3& zsq2eGqOaqlDg+aefPB^x>N6oiG$_3ukOgi!KteW zPfj1q>8>QrlW4o9Nfyb*(&7EQowA>>{S(DUCgJH8(re8LuS73y2X{6!)n|%c8T9&~ z!Q5-OwEoWQz0Ak{C%WVB_7fkyMGksqbY1+Q8Kz$3};V|Z73|goY=1$CRjQ>6xv3oxcp=mVO(L|PoKU0U$ zcVYHpxI@!?7xS-}OR3CvV3>E9yMUW8Gs(QA%=33&e!2D0_KfwGL!v$CN z`w0H)Feh=3gNF&2g_x@_otPfXy_g3vIw$!vOaht1YF_3o!8@(Y4V&PU0Y?2lpJh+S>V6WH%@_NTGm?d->}@5KHbFlXk=*34YO8%k@7xy%g*8LtV{d6CP_7E$I5ksxs^TivnkdY zg3QQF;#V-vD#PeKqA5v#wpDL7Wk%BAOkwSFSp-k%8OlQ8Uw7e$V&RG-oTkxeW;~Ef&V3*^@e_9qYYh^;nC90C zmq_-kl}6)MLT^0u{xbQap~uXRY+37lsw8w+1LiKV-QoBXI0d?8ZSr51U8Xyq=kCZ> za!+1q!;b8Cwti=*bkUBiNv$6~xABwcGI#eiX1@CJLEiluz+|*P^C8{W_?0F7jBmNC zQR~logG^rnmwPv3U`#JUDugPn=QRPiuz)RBREPZEYq|NPbDBtH+4*u#q z?spW9)-$x0Aw1!$T*}YSjI_R=bs-n$kD;qhCXMdKzuRMe{kT7cnS7pYUrzY*>k~sa zQ>T^@_FJkoR++MHZ*B)`@H-d-TuC`R#-4)O$mFWMxyoSKu-bmgAyZl(;;aVeFTv5- zbL2i`%;ULuyRgKy3(8j_^+f*OH|-gevF9OuVf;*=#rinyiLHa&Ey*vRL-|hFI+Q61 z>zzU0v>%~5Cn#K%RWgDjy5Xc zd1L(t-pX6<E|>od1#+22iCOuzQF7zYkO$E+QyXww~&jPub$&7;M?(jOOmD(iVDM<(Jy zV@~KYzXsgjFyLjB9pwj=QIp&`z*+xO+h zweSW+{G)GKOY`ilIb5tF{Uj^W=5W;jhi(+GxT6dNw#$Qw@2>RJBi5XzIC&* zrIJks9Wx&pVl89Zl0Z7XJUa`Wf3UnfI}ScduYGdl{`s@AdP|Y{Y-O$al+}kS2bUmE z?OUVcR=$<+v4lD=8Hm3U++{)7UzM?swZU!G@fRDG?az6?<=mM86fDa|tOj8xy82ncih%6*O*;2p(f z*_B5IbIWK)mZM{POewmt5*=uf9$zH-%8PU;U#C;5)0vsHIrFOMR}!XwhuX?gZonYz ziK=JrJ;$%u`qD_*wy4a)cQsWHL{IN%YFuP-RDZZP_*8E`+Pp&Rs5xTet6oLNQ+^C0 z-Afz{bt!=^Xntn;!!-L#_PuCYT876rUX`7NysFT%Qrb0|g@-Ipl6AS$>9)*}%Cd}c zpTfpx!nZFg%?(2-_Wn5=Fs+t5a8r$$k*5waw=XTtPMG`n$ll(IvU{3pv$|`%EPzHT z)KBS=^hNSiKW4ms(9aokMDHY~C@LZoD`Z=Yq-|nQ)Bjh~vQyaD-JAG1S z=noQ!Z0aEIb58o!i0o=#S#QcFlJ|sl(_C-$&9}QL>09TltZCcD*lHK!#9jF}I@Lb< zw>Ty5isZmARmN7g8kLVwj%v5Xug)fT-STxoZjA%itRKuh!Z@&kd$TnrOf*gzesse4 zUo$VAR$)GA>yye)eVg1>y!DX8Ou;C>)iYUZW1XhT;ZA>_#!%?6mq%$h&#qz5H;JxS zHSV!vgd}p+z3@robvXS~cwS@cxyDQ3IBImfq_L78CzY}9t3H=G;XL#P{boLw%si_( z+8{j3U6#D-Ymc~bTN!23ZNhm-H{)8}O)S0#oZof_?Klm-|9kH;r?)L5pCr#o=1o<| zQEA?ZTYJ7*!wQ(2O5P{2Cz-33lD40Z$=#?sm($@`=y~R0e*CAmFZ7P-R&;s%9q3s9 zF4l$aKmI&(p7GP~KVIwjnHlUJu7zL!cA$6|KYh>fMk}{H#~;39FxMpc9o)y*Y#;pH zFhrkIxr8{rKS|=R@=vCAao6)_bCN@fw?>rz)5;?G`P`z$(wxS|;^ELd_U5@$`_R10 zha@X6C(myQZ=gPbzE_!D!&9iss?$oRDzlGz-7;L6x{9~FcH1*Juh52REHS1&SGf8- zpt^V!?c1la%8O{I?^FFu1)R+wpNv;?>eHpmTIUr`HF~787|O5euIgt6w0N)Tgx=)U zICW<*n43vkF#0a<#aZ~oUCeqHu@m%zV`3P zeMR)4srC`MP=>p6SK*i7tVCIGS8fe<)l>gzok#0Q`h4Bh7)R$)G=H||QW~j$ZJD8| z@94)2Xy59bwkz&@VBEN@Y1xyjVSF?3 zLr)G(`p{iNre#MidcKCf`9x34Z+>wOV+elBc|SV)P-UulxSVttW8Sln@svsGuJ-%v z-Q4&OT|)XLDdq*pp_;jvpVMld>*w?d_?n&i`~%}!9{-%`vwmOM3{A4jIh3#r2_NI{ zqhhGArJPSKO)hLAOz6r7hn+elF>Yj`Z?e?z)$L z(7#VcFtmG|>!W^9PG2;s^sv@W#~U-uOYo}{2Hvv?lX?8x3Fd*pm07iu2e`Zc7;U%b z`)TYxFHg{}r%BJ}(IBU_0dD-%*HyuX^g_JIE=YUFxF)pwc%B}o6-SiLJ@6`A<>Lo- zo%VW-&zW!Y-UxE~9rUmyxB{JAHF7(4ofG;G?6-l#`)ems@HpG0p?tCSO!oKY*iXpo zg6PafZub3?;D_|vk8?&%Z(^< z%oE5wfz0a-%IdzLzkcw)Y#u6SAIw zT;->8YL#Z-m(rEeWQOMATKo3T_|!zZ{{O{^JF<7sU+AuP(R`Km-1FvTww?5)8O!ZHF89!gPR!2={2kqMZD(9D2KUQ18S`cT&!uHY2c`f>uP7d09_%aZVaHI7~ z^~uN4_%~i|YDKrN_593(zHY27~YR_X|L#~!nFiH*HT^;2i!{KYrMHDYqVy- zSzPJR`1Fo!8S4jSCZn|h`yPi+lQoI^pmQH>-$SKI-Vp*vG>)1l$rE&mU&`7_se35>k7ir+JxfycRjS;4$WhLhlzL&)Q5_a*exQe&^=x)1qo;W8wt5^bL&%d(d+|?tTKcAMI z!Me~~=Cv)<`N$e=bk3o<=Z{(Mw`%~iW@S}=sr2Mw-Ve5W?$s`>wVDf2pHt4gl0Ip< zvs1rDmIoSt(|@K}OLhJpnsjE!+kG5Q$J3WwzefA0F=i$%a)f-(U zK|gxEYUoqSA9*>tiZuhu_kq%K%9b%-fB*2El&@d6OHjsIo6{Oea#ARV8rnYTSyc;b z66yZ(cR)*HF1x-ld1m%-@>$LfO&r-n-XBdrOZvRSXUB$nbN4U2kaVscxsm8SL1QQozV<;#$^qhOk($Jq*MKaZ=rrt#{EXRxk5mvajR>PBfQYui-zW0`ZUR@?TYvS8rJ$u@n>eP?O?`qrc-`>D_5@Qdw71id+a>-7zN$}1hZu~PNZATeHefpa(shyno z3C7NiTBoJmLYBfc1IV;3GZd8Vd$F8#NZPVWwJrI+i}#gE&{6q$eXC*)rMc%QPRq#T z|FU!Vr^NMsMmOwTVWMb42#usT2hFW0F0g+@&jTC2kG!QQlY!tz6P3 zUD<2f>~RrY(V9(lzwl14E8`-%;(7Pb>j=Lt%hBGPsBRO@4~anjIilg>GZKdWCYWLJWO6I-|G|1iCeLUX|`ZUDT_u;9A z{?3o(YhhjGk^-;aJ0x7THzZ7HPB+K1EnDd!2owm!i+D{C_vpFYdDQhl!GZ)yX| zDTnI0qdI2$G1@_^V^${L$? z%FW44?TwdD9C~?qIVoLlU(H@!g)0;FsVz}=|1(2A?p5~;{_3iGe*UYq?I91*IKp|Q z_8D78^d8>vkH7Nk1NV&ob?Rp1fy|dz9{jc8%{--R?f4nm87muPq%c2jNmw_17j?*n zgIi)kIm)g2%UG^ba>(;wo*AkL7+a*mIBFlJfBfgaI(|?1<~;rKLtf^bFFFxz_eJk= zbS6ogHifoL?biEnFF8V;LXVa+Z+w{kv;rMb`f8UZQ157uen?yOBe^SZtDVAKehKuA z>1P`xSo-_l{--6YR-Aw7Lk~XqKDAf=Q@hnkyY(5&HDu-ijJ~fqDEmpqjW04MSwlNk z)+ilYGtxl585@t(Xxtk)FEIVQa7^TNy@v8gwos2S)fn;3nF-eYKA)RHew0U&sMPwK z+A85&*``}KYbgKlJvQ5h;~sAwcu{*)@~@&D=64Mz%8_>|ag#2t&PXLG6VHR{t8d>_ zFIg9-UWVx;4QoGY^PsJC*BsqFeA3P(&)F!Oa}AEm_Nn*H_TTt{{!j`;>g=N@F(9W+NGZtwqi%M2^Fz#!FwbFrg83Py0`o4+`!P3SZpZvH ze7%P8JRZaTGt4cW>-lxzL(R;%iS&Hx-JaH0Klx;7a>3^lhdJq#H81uD!QweJl5hbZyya#mKuV zxVEkD3$|?Q?hdwW?F(+5rNJ=C`2iC_T6MCdq>uxT@F6Y^biE3v3 zO`&JhZ?5<2t?U88RiAfS!_r3|_@)Y%J$1Cgs+-`&GCZyU|1mqqN_U@R5k z7+Ywbr!e^dr?t&RG7^wQnu*K#*L#1PS*z8`WN)41c=2Top|D=(Kevc~eJG?nv0f*& zhzBZo1>frst^X)lTZWM`r>61aa$5}>)&@&13;Ogx$Q)}OTRrk&9~N2|W<_($hID}Z z`Z~#(eccsv>#mq*mae|q7T6dzy~Lw= zyvS)r)bA4KXL<1m)-fjJT~V~#qmKU)bzByFLUF@FUt%-rN;i1l`y8U)G_j>_OOsN+ z?0qWMne}E94>|?yeYUc6_DQV1u61n*ZUE;}DGLpm(~8vnk!QLzaphCuz&eunvJ)P`d!g%u4ppXxA*Yw)kgE-t=lf_ zA^ml{34{6s9gd%{4&K_;w<)Z6eHZoy$~P*)yCPj%wsi*YH@5N=p)ji>=;o1`*}d;Z zps$bGv^BVG>o%${IlnEqwS7x8^}bDAy*4&!oDwlFHW2mR2@l2eURoLOy(jo}{~ebG zde|i3NfX-nU^dq^ZQ0m~S}Vipbaz*0N6^vLL(kWJ+q?6zc3c{`LRr79r>7IfR4_jH zj{7eSR@ja)Xb-k@-WtkjT_;tdGbk8gPoW6y8z|wi_{On)$KFc=t2a?KY3~J!S-9aHmYi)zkQovk9?T$7Plb0#*KvXDiv5IbGj2&!ux2@BL&anzmFd*N|=R<837R@;YXgaP6QT0JK z{!()}4Ous3YgX$@dREo{gGUhG&ZQVD&06ze^O2S2Bdd&kQOT@cWmc~=tFJSwo6NFR zX4y)!>^ifo>Hoz;rp&YQ-|O!bWy>P+l^SNwkx%b(M!!;Slj6Kbry7)1yF-7)-k$HFg;g@60Sn)k%;-xCYJBo=;2 ztbEulk9?)3K89Z(2~~dQ#lq*s!so}r=iBtk^75D;!(SM~UlYZf!mo_QUl9vmVfk5-&)^tf;8#lo+Tg?S;lIJHw7k0kT@!yHzi%_Q;#RNb>0!-(rDlEJE=#HD zh`Bq>-{f^yK_%uN#<<6u_bB1~$I5EtD>WM;F45l@bBn9d?~U9MK8h`REDlA!H}bA| z1fBS-_(wk70UrJIPI>ezwNf4R(L3eQPj`Grzf!|aOXMpx`Hs^1>YeiFR~pk+y;C0j zO3|{8h`dGZftdT@m^&MD&xwdk@vm}jjVET9z@8&eni>;L!Y3QUpOkN#!aEPIiMjVU zw~zk==Wem|YR&lZqRwg|W|FBj?~A#&#oT}5+-nfUBs0rsvDkm&|3WFh`{eG3xwY2l zKZR?N-+yv9MpQuVy)pL>WA0=`MTEaH=Kgfd{Y=dL4>9+Yh>D5c;+VTL=KgfdeK6)e z7IXirbMK|9O=A2tQw@XrlwNbp{jr$)=9v5Wn42FOwxkLSEHZPBHUuiCOQ^GL(O0&+n zm)rDKn4d+ajN<2CV(tsv6f)%JDzn+S`|0;4nXAnoJ2z2nYyORx`};BX&tmRmWQwWu zKN@wTD8V>$%V(!%2#Yy;y-XFx=zlpiiktwS1AB?%b<=iR4W|(Wu z+c>bH?-*u=S#27ed!=<>XKrwA;fUTBox2hHBy+v_v2!2BJ%eS2evWopnlHpI_bA!-LXX9Pi${D0q!`9>0FUDE?X9 zS^sscS@{j)`G+-|=eOE*x#IEX>TU0QqMMr+eN1jWHCsH+Y0_M%RYW%7ehUiW zB4_W}Q)oC%wojJ@zp7c}V)m8w3per@!IqAt;i793i?l^A_+MGScw;Mz)>1(suGzYA zBaft$xq|NptgLU~iTj>W{TAkxA1aJoKQ~$v>KC-G>g?Xy-l53ShTi5|niuqSZceus zFO4^y#QN^$RgpJsSGUe@z6A|!UfsT8_1xCx=H~i&UA-%|u+idnRf-70DRC3gC9Bna z_4Tbyoi}gmY-QKCb45YnMUv8kvZHa&=p9-gtx)qY|GK`e?%oAgZ0*_H-sc}_pq77} zrTepg-C{8(0M@fD(?lp7yT3-WBU5+4T}@ z(HAm^vbeRiZ&T0KTU)!gZe+{cZdR)yM6y>E%%^RR*57g#PjxgGe{yE5vMus@N<+Dd zXI*@=Rg@`*u*f%9Uj9x&&QxOlT@tHZXBxRaMVWDSAicG>^UO2MV==J|7b=9};<{#a zebJ{+ipA0cHD?h`&jFo9wEE_=;BoY=hqEe^1>xzL=8wX0gO$&jKQzNjLD!shWHicE zsxwb`L3qGN(hhkqq!F$LcsZTji$khkg^2&QZ|0nNo)LCFyJsFdz4Et=eb!|)zq5xv zsQGN0>c#18y_@L9)_<(ow!no7BOLoRT*-6XMaK#uj(?D-V3~#}^Dn3A-*Or{_4V{> zoxOcm_H=fh4tK#doVwUpd=%r8?N%O(>6^>q<=xv(OX$=*jcxJhO>BoySgIVd``D>o z16#~EEj$b2u(sT4JLE#t7Ovj5POmqGYTTC}WSqGw+tJZNhAhbHl#j@1z-|w<=&>l9 z?%DLv#Y&`p4EeC8O zwBJfg^=1}So~1=1zKRnU&0Ty-#LpVnbrmZqueKp$Me9mFjrx=laT8P8%&t{kqsbIY zWHk0X8~e82F$5wMHZUzHM#YJ6G365q^E8dg!qp$U?G3ai_4Q4io#{7*JOBDkU5v|% zaTqpYJg2sqHmZ12U0>hQ)42g9+Ood0cM*ETajuQMMXAQrbe>bw%eVIRZQWd4Q^(d{ zW(1+;o<3T18o99bx-|3WQ;cf80xek4dku$@EkCRKI&Wqg@^J_V%pqBe1L2zTmfFO=~klZVu{zgO_bN0nN>; zn_JE1&duvLrzxwDojAUqE3G?KZCum3Ce^w|^T(E}R?oMpc@~c*vJ9emcjxGU(031; znXhebZeBoN+x2k<5tiGzsr&@3bIZoQO`|h3vZM!0rGJrWb)oKPtkUFXSNWOu{Pm+R zTS_vmXF8pBP48L7b#3x#vJjiV*DrkC(fAb~u+tIB`kuUNS*)!a;N=J2fi zRhtDPE36gb<4hG*jThA1 zdd<4_j#f_GZe3rrpLU#tgV2CtEbtG#vOHjZGowy(c= z8>fE9`0<2gC(|hW>;v(w^f{ayRt+sYoC-Us`i2#~S~$9%W72lv^$iK;YzAMe*1=jw z@77k1Fn4s@7Wnj%$TzzUTHa*4!RF`8X9Np+x2>aYo%I}ZQF?1SoMIN0PyK@E>(VVf zUAHV`j5hbWd1w0qv;_7hFDhW`9l5Nv68g2)ljO% z68BM0RlP=+Y{0VZZ6W0w%|^qOTl=;)Z!X$cEm(b9FS}-oR`h5+4{CJl#@0=K1M(ErOk47cS5g&Ev;G(n%RDV56)WMW z{1&)bc~RUkl{XwssO_nr7mkBir)0d;S3E6-zwEnS-M)n`vd3#oVbMh~7q@KfrZ3Z$ z?Hg$7^2KIVX-tfKPng_T6 zL+;OpeAav}{0)ub>s(R|XZAc?F84$H+FtMv!rvOyJj@;Ya&uPA(jgy@$o*yauKj-Q z&vN)r3xa>l!RH+m|22PTOd$A2@FDoe#vB#g#~ZbR2l#D}AnCp$2px`4TUaGXe7)sS z^IthLE(kvd1;vLT_)j?hW6uA1=dX9Bg&zolKU)xdo&T19lk;Ec{P#KkV-CLH!e4UX zuQ>ljl$qi$7yL5k8wH`e-TCXRz5Kaz+WPCfvG5;p{)e3Z5$Au@`9J6UUvU1fI#|W| zV$qu-NIHQa^is}$k@IhI{%f57jn03Q^WW*R)Hs_yq{@b1ZKIebH`5$!tk2!zcXQ1?6aN#ex@K>C_?nDqDNkRCi5d^=^`8PQK zM(5w+{MR~vowpYLy$sKTw+nK{`f0&Ggg@+R7oQizovZ@V9@PpGZ;9YnsGrW=BKRl#MnsT!hXm1=$6WYx zf{)OS2tw~wLBh*8H*Mu1NW3YeQS+zht044s?pfjef`s2INW8tyzna5*^4EE0`PT`8 zuix^O{2Ax`1Zhu~IN0c5lY`3zslzJ;|66ztTKH?^K1jPN_*L3l!T(M_A^1NypD%cb zJCOvxM*ky7ygmoFJ9xW;{SNMQaF>JkIym6qUI+I%sB_mPn`l>^d%uGR9DKyVgAN{Y z@UVlAIe5guCmejr!KWQO>fkX4pL6he2eS^o;NXi6zU1IZ2VZvZ6$f8+P(Kloe99cG zaInh3q=Qo&tah-*!N9><2WLB2=U_?@IW;)0pb4YaCqb;EfKp zIoRRgQ=BK49v>4#@299g{R@oXVf0oI9c^&1(ZQ7t+WwmG4(Hx3_;t!z@V~nL`%&tn z-01TQg5LO!%U!+fQnwrNkf}~$3_=L+Re6`8_q#MrwGtT{#gD*L#@saQ>-`}C$Irr0o)aR_= zUxjazDZdpOFW|0qaJhrG3qpJsQ2D%9@VoR=g5RT^5d3Rn_6Z`)hXujYI7RhXcbJtt zL%SvTH}wB5T;mt3ukd^RQ74BV8q+QQzvRYg$fs6r231&1&EL`<2tEfNf|Tb$!N24F z9zo=1$B7iSl^^-CdIGF-;fowhyLfvAe-{4sPVr&I((MrZ;_JtAFUfx}9ES>8`4Z3S z1N>CGcvdfe?$U)h>;Em{Dty@G7iitYx8XyyrwTt#yDtd6HG(g?aVHQ_Shp=-#aB5J zU%y2yxz*7D&!+ziC%?a^zfnAxZxQ^J)1&|85J$+ZKs^IIR5sqZ_AF?;&k!{yt~Bkp4&zzB?RLJ(pYcTJ>_TAaoyb@US3so)84j)-&KS=eBa#L-{ISFNgI=a#X$1 zJV5oM=AYa+{-232_rIXmg0E0t1)=w%gReNagnWwcHG=ScyC8Tw9o*}}4>)+#K|8J| zo*mBvtB|Sqs1byZ*@EP=Nf3Tk3c}A?LHKDCB%MtTrX957e)u>b_aDQr;0feg9^x+% z#DBZskKt30@OxeOBZBbroFMXjNf17a#>Kd+1d(&KAnDt2H*k^Me+Zw>U%!o(9;|in zMhDv*)Hqz@jZMzo?O@tLjn5T-yMr31%iS+Xo&xF7-?@5<{;rh!>#kn?tD7&QuZQH1 z`)LPlz5F-ogWRvWe(nFb`igR{l|OJm5dZxSJ|g%FH!n4bupLY!%wGAIpk&fB$}cHM z`Pp^>xi!d5`Kf(S`C0v@{A_=K+}6q;*yi9tLDH>}e!)kb;C~P<2)(r6Z_qQrU%LAH zEvL`WQGcNF%m@-+?Y;0034-^kAarcKhE9$25&EjX3Rk^VduH_*dG3-MI{RJtBQ9L} zr}ES9Tvaa8LqX}GU`leKGq_RkhtLz`mSHQ`*Id7ezb&6}2|JH3X`|f%Pf+D0c+|mT z4nF6gZ7<-rE&*NmwQ`2vM!Dg4rQi=-zwm9>o;HwTMCD#$^g&^{uEjS+i5UfaqDS5)wCf4nNS%`VFVHi=a}#EzU{%7b6?{v=s9lzx z_6weuFd4xK33JfFBZ4TeZJ&V8%RMn+vV!pYvf!kIDWiOACMQfFNct(kDT%N>`Ul1z zDt}ByaB9Nr7er6g9!W2>{vdeJL9Ii`eb~Xr1mBu4N1Xc!!M7#MQ-amxlk%^j-&`b! zoNc|IM*ie}2XYqtDf2SHQsN0x8J`pUiR*tT_m^>tPkl;XR>2Afs~k)^IK{zg2WuP* z9ISP4wu5yJieJ%fa8P{9y~M#r2b&yR?x6A|ycP%7IJnlq8y#$Ou*1Pk4t6^zxrk1m zgWDav-NAkbcRIMs!FwGXaB#1K`y71O!Hk3Z9X#ORBMu&P@Q{OMPVa4-``Xt5`+7pS z$=kFRYvyons@=?4*V}96u)94+o^y(9iLT85&@B4Hv@?hn{e9Y)XlK6J%#m3(TG=R! z{8DWU$wJGBlRzQo-Ggl{QfPc zSCg?E*t5;2P1SAcHt7J&X_3b!5IYfjrmXf5LgE7=5ov@sm$u&Seg^8a5sI`O z{v6Yo_-CqHzuk$ZF-aH7>sZ!Lb++jYNuBm=&>7M@#eoM)sb_0A)()Wt*=H*0H>(zF zGEhIKo{^SiX)G)8UObNMB zZRg~_25flQH6P7?%AASgHRA8_K7IENvKKo{!+MWLOmM#RwitbVc!Aj^O?4Dew$yQC`k0aTcY=vQQrH|C|Dk<(51i zON4oP@4!xwmW1u6wYcc#ozwA@ouwoD6~nub&A8@TAXQ@*e={(i-j8DRb`sFy z;s|(pQ{fBLydE4QK=%&%&*M!5FDmB>*1>j-57V6mvhXCQ>tpn0!`xma;66`pb&TFX zf4J|dd`O2qy-$03Kz)y)%(FwQ{p;!7?ddtZO?QO*&!YEkjHh?l({nUlfS%U#{pab) zFPh)&&^rl|=v|EQ^!_{^;w=2S5J>i~SDHhA0!|R6L6i>|I z$@yB0-av%jJcpW@Sbht@ zi}JS!dR~6-kI?&ajNSnBItcfl&+lN2-g4+Ef8uW`#^?9t7`>OFSL=y6JULIs=(R-X zEpvFHzk)U_0UTGtAHM1th1-{A@S^!$8===sJkQ@}V)Pn|(7Pu_uMK)$epg25eLqHT z6ZDpgVfT6Y{dJ698hXpYk^EL*Jb%}b>1cir&MaKM*Mb+#@8Jl4S4HUknWu-JzL%ia zUmDu=*Yo!kPtOHC1wApc32?Q;1I7Gfj9&MJ?8{P?{`2&H9jCXG{a?yZ^sd49{LUj2 z(fppIu}yhm4o}WYz>DTLxO-Ipu620gZ%>R~Feg06A{zQUf4?82Hye6NSNyGZc%t`c zjNZ%8TZzB_JiR}U(OU~WuP@hu?DPBgo}MGnNN3RKi8(wuk9&G9Y*Qq^*E>A%cX8!d z`SnBZu!|$$`MVH2NZPY8@=rr=Hc#K^xU!Zw$pgOA_DI7q%Q-{=GXaG ze>xmrDZi~4&!6rt7JsOw{nD2fmfzhmdYhn^cKK~5rl+^Z(VOe&&89QZxY>V7OXdP5 zFM=NL@*;Rw#qe$fZ%Bf0pQrZ`hv)0gWlhFV)$^anTMr)9KkWnB!1HnBCp>+EUM6x6 zfOnLIf-dZPFv@QdBN<1U6Vvt~_QR*+={`@7sAKS+yVsbH!;AksUVG1GU6aO3X>+z- z5(Gj0{D!%U>QfDK8-gH(+yAXkr4}q$5Cn7Qr4|sx*H-y^%`2}+Bs?YMVRk-0N@u$o z9%IT;LB83H6PDR~SMVOC-d;CmFvNq8 zq~3AoeNmIe@HXgq$$PVU7aKNF%llreYP>UBYIeR@apc}%y`O!aS(ar)olWWu_iK2= zop(Dsc*`?L@y;#pZY~0*fY0$}?3eD%49)mTW@r}g$m-q9l1AR-W=kj4W9-SWfX&E`r}O;?=Dh%$2re z66f4^H~CyU(wKQLHGn1L<`;VBx1w=(t_)*%V_f{`ty}+& zu&3d9@p({q2jz3}_rLk#MdVxZKl0jZmtO1SfSh-H1NkSAx8AR=os=2c&zt8HOxbWE znHVlbCi`b*hTa*J44XSXcf8cxfj-CI>B4rwGsaR zhO|o)lFhXv{R6!7{RU)H+XSDDWy59lpF93CZ|_ziBgyM%axf=(c{zC*=`ChzxZZ%C zR>~W+L6DhDyMOw8K(nkLdJ&pw((rT#q3dNaB?#Y-EmW3zOIG}eSJA2hSLG-^YoT|{ z@@MR)dHO||i!ticnlM*kG=A8ONmIW{$|sM^+>#l3t?BWRwY+^>O?`Q-Y3JmM$1 z>gm!uvTvdMOD68I@0u?HNA7X;JF<y?7$KOa=>XVdbwIgc3rq_~>8JVG; z;I&^&NJ%g69I7JCsvxYRYM0b@+(#VsYo5nIJho+q*0v1h)`IWfKn{7l%kr4_Q=OJR zO@H9H+5$uQi09J!2Q1INygk0$K}0_4J3o(6yQem6`kc(r7az(Dr5_*6O|QueHNlJO zRASuZks!G{cO&n8S0ytO*Akw{zJ0hRyF1siXE4_?g8x7!q4HHZ&b$Rvkr`UD9{;w? z#035m==vt4#}C&n8_bnV|4g>35&W{rBja!W!f|uQ7mhb(?$5CnF|G7bctpo82I~Fu z8PqFdZWx(Oos{mYoTaOBTYbPTX!^sv^Va;()3j?|H$0x)O|D%jMniEMD|Y{~Y5-b} z-p&ZEzenF|;H~d|>MOh{&z^oEp3ZT+dAgqFq6p2uh31z_&_Cp3zWSML|G_`VeVO)4 z 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 z

6=>T2rH*5ImZc0@^64E5L&;NzUJ!D^&MiKToY!K_&h+ZPHoBDOXbm-=Iz9g9uX zc=+ncSRh}S*47r&%CMI8QiFCLK^Yd6A$V}1z+Qydq7*X$^`<0+PwEdJ(s1@;B^9XY zYL-D}v;@07vyDP+&aAbbcN0rU4hb2s6uF+IzBL0VP)lI zI#%*Qhh{N_(yrq}hmr}4Kom#}I^{#G^3^y`K%^FpO+E{uOlwD5EZq@fy)BEydSkH- zk_%fUHNf1YPv$0l$U|uoVajKhl3MF0y`tP#Ii&t1XZXOIby>Auw~h72QzldHKpwX2^r6-)yTt-Q;qjLa z9T5InjpclL3d72`ei>@hu4g`Fm>#Jes4bU1z}f*s*64rx>-E1kdh|ckh2hR>|JjiA zq93m~%|Ei;o!7oh?CHYOGSK;hoXF~$NEfkhP%>06m6c>m} z7nXk+VaF16V#6UB%{=Du58XU#nPRid(t&TQ#ANceO$Is{D;Z1H2!Gp-Wfpb{(mGNh zjJZo$6qAYyJ2M1B7L~7(ir6xT?t=7@b4Gke8Nx0l#|^fVoTNADxUl17gvv}*VF-X0 zR#sk9TU%4JK8nUt!`B8paCra9`rA<+Dh!qHkYUS^A|ie8)b>cq9gqyY55^>Dxw6-T z2aNb^$tR_PPT~|a)j#xabcBG_a0N%QVv6y8E(HM)xWQb@CS#jHk zf=H(^34aUsz1mYGx)eb<$JC=yXI9S+;J#Nk{S-+b$6(lYoH@=o?t^vH7fSja4!wGR zs3ZX#PjJ)YOTcgetPZ;4izUC44nO;qr;`M5g2zpd69R_gzE?}*$jay0l^Ia&MU&9B z!3Px556FF!%{mg$!tW~v&Ia}W7`O%h&kUULnLW7zyYBD}?3BgEKdbOvfZUh)*G4?k zd(ZOU;Ll{h_*_+oL7!Xq*s`qQVN8!|hhy62m_ z_UhzO=v+HVob6ppnLgIu+uE_Jz1`d!#&z-9tn1=V+RDWZUFtCQN}ONDvM;uGsAI{v z2)Cu7C!U+j(pXpf19Ash<-+<-d57%AZJRc=cIDh6QW;r?`*mBl(r#NNSMcjvH}#ka z+uJ8BZdQ@AZ_k;$fEmTeJ##Cu0ja6E2PMKTBadpcD%LFEQn^E+tG#8MeGewRJbAm~ zp`O-moaVRdGv|H@SGvm8-3x2%9Uv{aw^+E6P`0)0o7*O>{PER-tD7gTzxT2OFjFt% zr5a_)cq1VuTG*faLDviT>1**C zCl0zk;@CRQK_2;VXy)*ltHvF%Bd&miNG?x3Q3n{ck$3j!wGW5W0e;y#02BQk+A?sTBdA5Z# z{BZ=x{>kKb2socj?KHnQ0!)6j;I|85@ix4z6SALZjnR`Xlu;m5rL9B*l-`Q7Q^*9d-nAR<4GbTz+c zJ^UJ>4Azl$n%@aU2X#m{K&2T&Y%K!&CHggwfl&6fWi0-<)|S5sI-Q0YXnuq`Plmq< zx&Z`me*xBWWH}Hdb*F}#z|by0@VF76`OQR}5iF9>%fIVL#A)w6?OR(qAIx%AeNpzc z$m>IIA5U4kck{5PpC1kzv{fEd?%cwm6tvIXnY)dCP#8BiqN^e+X+Jf|HQ!R4Uk$?kV=dM#c*dLSj(V+$YgM%SH{HT|Z^%B|ZN-=;WqD#a z0@+w7o{25TS~F$DNu?3A=^}yklmgIk9mT@B7|VzAs)Z~cZ2%Xdj9lw3!}?$_v_hV7 zER9fpaZWsrvhhqh*YkurckF{c1mqwMt|yj(^(5CQp^I`) zS;~yEoHW*ZZbyUD<%|)$Qu^|S7wd4O<+>vI=yv5popJ3@*8y!U!v7Y} z<5KU^rla*_y4>1{v({L9guf1c#JPf| zLx;D147Ma=&^gx8*hZM|ROpgx*c!hU?W`1Xo%bI}S@2&$f8a>!@)?PdBkkRO+Cf!gHN1KH|{x4V7`(&K754nSZe-f44N*&KkSZ&+w%8&cTE{ z@q80x9OqozIofBBEr-PJh&7t+>@nY$bo=pxjR%ju`4-AJo=tY2&Gq8un}_J>13^PPSFASQA^lrD?M~ z-8PPaL%lPnmD0mF5*dCd=RsNxMn5gGnW`+)ok9Npb4Esu8R zPUC8K3o19t9xId5=|8g1ADfM~vbv`;J~rj#t%j=JZfSjI+%C{6^vRqnpuNmpgdeo; z2>0IvKk@l$?(;*oy-(WH)os+ic<-Zw=Q3+;~rg?x81{;5~L*&LrG;B6<3bywc?ELGnuO>PPZch0~+t zm50#@xN;b0)R4V9$fTZ}P0<`<8_Djs&8}!nK7IBdJ(T3wlEY?mj+5g-?KIuJ2r%i` z-y}2lix}3iz1Bt7_RxMwA1_=Jan-fbbsWbYs*2W z=Pq@9^ns3bq@B+9IQW_6D8uJw2t+IgzdUt0{77$>;{b5YgFLl=v4?IjN4^UXZsuEo z%yj+o3svXaIF+-4!?f{9rePz=yrkMT-z)EGLFBKphHw#M|~ZLPQx(L&=G>vac__g0%7?} z+<+ft3*krIAe8g^MLA%&(Q%sYL)A;|sa*BfIah=;MD~dy`>%7Z zh!?O)H}O4d>+MXOd)6+YCi9r5x*1YRL;Auu7v6%!cZeyM6#6dll>|$Dm;0^^l=-gm z&GLnP*9Pb4aySKp#|*m|_nMfzIWOhj+acHT<<5>tjY)nB&f;RY=W<%Fy3g0`m~^Zt z?MTPpBK*(>owk1u@cH;@r}+^YO;e6pnTY+f?xVA{{qu-7`&7-(+xA0?f?B)e;)mV#BRE)>z3nfIEX7knH*woP&rZWw_bA1D8uR5@+hWFGK3TwCW)QzZ z{5bcl=dXoY7Xg(#SH(GGu7_~F;dpci>kIWMt|k;9Fo8&)bQ}AEu{@ds79G$4;SL z6cs=oo{!Pz0fShhC}Mom({e`qe0oSEx-hyceg5~qdpfW@ITG~Q@dA0%e(Y4PCt05u#{E;U(JPAlp@Co0UM-$z*!z7L zb%8Y~tO>DBc#es8H(_l^uF?F4bMATcUHCN8eb@EyX8Nuoe_p+pZktGpKL1zm5^9&v z9ZZ^*kbM=Og^WW<4aa?o?sz?Fu!*=Y(H(C$YR!Uk=huw^*zOElfseTY8iEO#jgIR}hSQ0X+jN#PbC_YMBO!U@>td`aOJAmjf= z;pGx96#uGl_JN!O{(!1LJHAM4Q1}tV&p~;AW>hfwb8T2V;^z7`acv(m3P0}*5@x5R zCR%gMm{e98wD@GrIS=9{9B0zhMW`lV$Frd4rq7qL{yNU5Sh+tz^GRJ9QKpM26BgV4M;K(^kX|xIU%3xOyHWZgMtidkJCf;<^0JC$gT|KLBhv6~Ct$N_& zOB)(CZ`~%1purZ}*3PaiO&tyG*mKw*f!7Fa>3pD-usQw^<{QVE zg?8ySUbjllU~{jiluow$Fb1uSXg6VW$o+(tvP*>UL&RrecQzsRR!wT`GTwZOOD@^! zGM~=*)QLS2lXnifu{g5<*}m*uGUaYE`Sb8J99IedYnzZulnHe)w%z2s;AB3hM&oEG z`MKE`(3yQV`$vv@7{=xnR6lG7l;a}(=7|C~o$emdR3#n81kyzn)Iig5ijZ%qiRkng z*36gh1nnpvT?2mPt?BCFxA4I1)&F>?iljTr!`ysrAc$R~2XVS48$233q z=?(&qN}v5l^E;~fskoztUidcG{CI~3NS$xvb3o>*Gz5&}Zzkwaw@yR65_p6J%8`bS z5K)e+B^`cTW`(kAo{7gd1#B{`9l;$Cetf$Xfw%nD z(0k&zk4WsU9{nZgYjJ-rze%WDewVN`{9cr0iN=NtQI?x!IZmX5QL`K;jB=c?%MtDO zgQg(5`|M~rWcEdQXM09&^vOk#nfvk_nfaZ_vf%NMVLsRhkbBFJp0)y5o_{mSgZsK& z<$+G+w=BzZdbfS|GkAOt?erh`ZN_h0-ZjDU@mp8c7WP|-$iwztHq@7hJi_l}AL~l* z`HDaXXtyIl)~TdDj&HX$!>mWv=R|e61oBf4{-|wBqxRWB+^wC_MTM$E^nJ60^>lhQ z>Vfx03+vIez#SV$)m_eFcmEn)zkK#+LxVbD`+y#0J+m$Ges$`N^?6Q~J5%TA4{aT7 z?;Sm@_--y5{Fk@hefM?VB|`opGB#h@aPi6_zh9xth|(qParhb&shQVxrr5q-D8ctS zbcVX0iC@6pUsw+vKas|JW>)Bfg`;BoPtP3PeQ5MX)EVzNkKp^5_uR`nabQ=ax)1yI z2EHV1aB$BgZS5RQ>`NaV%rTulOK<%lWOjtw6KSD;1A?|K|$0F>&e;Ay8EYRPE!YvabWkAqavC}S+KKW zePdtxA7SqV%e$}O$ovT2hegy$p~&b&wtMI@s_rny^IsI&jr+}apCA3x-E61-F-o4a zp%jSUmYfRSg`T><(^K~cjJl`(b=~7m@N^yOm3M>Nb@Is(+I%tf%KMp0jk?$AX`_dB zR07fdGtDq z2Y#$0K0kb3Snt)*=hMrflfWR~y>`EZIff$Iyz$4_Cf3RJ8%Vg@2W{TS_Dfqgc#f!l z(fD)$=0`C};?CbGf_Tz4>0^Q$XW@Q#>ac9mj-`VVUcy|`-Swv{( zW!(sE7EOf?$cJ>K;ar}!T_pQI@C`+uEg)~aCuBcJ-u?*oaig#CMSh%qH+p0w7~Khb zS$3G8VRc7F0yX`ZXSBlt468+0ZGY-#sNZGKhaYACmv`TNiFdBc_A(F~ejRzxKd{{% zWAqg*86Ehx?LSpyzjsis7a;Q=Pqk$Ez6!bjSVYmzP!7&DI_)3j|DNgtUi8`Lve+2( zb4vS0G1PzUU+znnwK>siO29PuHYe*iX_Q0E0jPn_xLd*>GqG`{nTZLxQL5jNU$ z7-ir%VF~J-G6xqJZ354V3cODP=2-}f8(p^AaL?w zylh9YSI6*rmGuhwI8He6?z^v`UhFm$iVcU*&i~QVj*f0WG}?#p=MU6-`3Fc-u>EJ~ zW6q6+e)Fr*q3sX;c?fzc*#4tGJB&7Iw`sd9x*Vku?73%IpewdLj?*ZEwk5^>`Oj2) zH}U>tkMXMtlP~km_?|uZ|K;=T zMg^cE@|l0$~hT|S~H+`|BuXgD1v>T3g1Kjj8Bt7RyY&S!DB;@?On?5Az_d5LfMV@iI z-N{W~BI!9dU^~5I-Npi#^>ovhO8Q1TOSUW39ti`WcGJ5t?ooG#lzGz6^2E<_Y?U%6 zKRy|_Zy-}DuI6VP@4sSv#(8n{&V~!fnX^m)@3VR=gUWnvQg{S9;-301dE&qB!4G-x z?<@QmAlEy7?TMf5=-w`uZc9l?UntKIGfADyzevst5vQXbzOT|VT?yLTRZiX5@%097 zfqu7vGySt3{Dgs%zR*w^>u#9`->Pu#KPo}{#RZj)v*6>xq;^bywR&Xv{^y?h&nP^I zd`s}}+r}eJ`F^Qz?q4ZEd;Cy=%`FbV*1S#O3?==G3h$8dW#W`4o)@svkuCS!XZ9Z8 z#-B}CzBX-2S(@=m&M0AyH~|3rBMovH+08hm5X>!%RTKaJ#DME zZt864Zr{WkXXO5jhW3{B2ex#!2nvGjwmj(UP>RhB-N0L0n2R727(Q6n*4o-L@kZ)= z?^}^~jJvN3#~MS{eU6J{p%zK;axaBtl(PWk;V$fzxUH#&cfO$1+3irc)6~Pt1{DQm z-qF0aeXXIbZCYIuF_K&CrMz-k$F%Jr1MIS3fB3|gE179?+vLb$NW`$PvFO&W&Ml@b z52p=e42k4WytE;Ln~`9Ngg5d;8a|HSQi-qWg!v5Ub>jTM3^i*oH*h5YdoN<-*Mk%{aHwxy8N|j_(wF>&w0TQ9?`}4=7lH zcbz|C+Xvy^{shA@Npye^lY=iRd{E)16@E_Pe7A;|sjjc z@J*5qeBUHQx?=F--9Iv4ILD#P{~1DrKL^PC6NJb=%Jj?C*$L3|olQKh_%a>! z#IXYPbea(IalA_T&I3}u3kqU@DEzAwKg8E7KD!iOt+$h)Ctt}Ad^tu6uN0z@>5;Al zkbK(|>|i(s4BQ(_{`1HW%98wVRrP*5X0aF!JOoI3x*Kl5pNn~SP^Q(t_u$kv7XKf0C)Qy!`X$kaz!V^v>^@d$w2AduEpBt0aH^mHEC@Cc!eV_r)am<@M&6 z1V1fb?w3M_+2qckWS)-q`3PRj11soeuEq~to7^7(;M(6noN;us@uOdVnxPAHIZfx? z`$0O@tx0qv+G&345oYpB z82mU>rTP7Zhu?lA;(UR2n%~zw{LX`4BZw^gO7YYD-u3X~T{CgSYp41BFAu-P^@^WaDMwbSxFp*)PzAz;CYYm46w>AMfQso{nl4 zf=;I)A!+Ccjp`IFpc_Kk*$BTGKjs_4kFx19z$?npNLK4k3ApBmeIzcrT`0##$V53! z=NRl%rkp0;d$c6)^9&oVk(oJXdFF|mq2XUbo_Gld;e>36GM z9udVmQ#{+iIPRlixF0m4aA)e>U?1)F$T%4u>`V16NTkkN{^5^(I56CI3DzGXJ5#u$ zeK;Wc#-;x#=*4*SkkP*wcMS>u@TIo|hR<3)ta(6ILk_MnVx1mq?or74W0WZ>*C+je z0=N&5^2#{S<%;K;>O8Dx_(9{Z3M75NADNv9z_#}pZlgr(`L|A!@oh%tcM?W{z#gbK~oBUjiQOd|4({N4&``1&eU5d zg0)_2=u|OaFv~~6kmhC3z6xIQY>}?( z3dkb_(#dBPd#KJnUy6Fc`dnYyXAQwl7tY4u7s5}shd5i<&l z2d6I;{l8>c3s6qlK{LzRkMM5tz*;P1N^#v0dXQ`4OwV=B7SPZh8}~r)&KmRw&&ExfLa0@yz&B1iBHy@u!b2!5}@e*|IJ-w4RPI5<;v zn)>J1gWcymr6kmXl)y`C39hmdHcazC2~!kVRI!|BGZDLf)}` zC3UznRblN*>pqVCWG=aT4Y{AoLvFT_>TZkhr*@VK_V$hT|H!JKh)|fsS_H-0^tY4aYTe zcRWXY8OJkh?s$&MGLCEL?s$F)WgO42x#RH^8IEh}?)YM?1KQ_qY%&an4aYNYZu;qx zzQ&Y=|>(w92)Zf>+I=MI@E=`Dxej;}IsmhYT_J6?Eb zch1f4GRd#pA-c@*(UZ;2oJqhnd^f)<1jnRwnBv7a{0hmxT88iszjQK=Yy9r?WgdEd z$z)srUm|Y$S(1K_L&7hWjN=-=n?5Y*`yCQ~iDVqt_}%o^O8Vy<68jKj-2;O0L^(!b~s&2fD61aO*!^{L$y;Fd-JiGL7~eGq@dO&1W?d(vMo78?Xp z5O2DGxY0zBe}xD4iKq%;PCV238HH1m+_R8SIKRzG&_Dddg%^q-1%)GLp4nXF!iz+= z!Yvs;O$;iW?TLF9-cfk1#HWk-s>`d9_zc1McRIG55@_4IXW=CkUkyGbc)tFJ!k>}! zv&16RWe!L@EFM%i$I>NeAKy{S}R9Be~Y;jdk8g z!&+Q_vG%qV%d1z#+9po0RMM}wZEb$!m6e+RqQ#5y%D_mmyfVKOnKD%6m!PuYo-Uj` z)ulGg^-ZjS%7~p>>0pwH7dTnl3VH9zrFJHn+$cCzHM!KhOXF4^+m(jo#$29~^^|a? zr7eYJLX~>KqTANRZj0U3VCqq_4@|6)gj%d1y*G;N7bx*(N{GBx-fIV^F6KsCO9 z9?L7=BM(CvRqu^O^)2Z%o1*^aX>##qqFa=}mbT`uMtT_w$;VZRsm^ek^_>1yrnUbSUy`?|_J z?sv&{rBL=9Geum|u*rUc@@VLjQ{K{sZMq`!;GO68o{Zp?W4Ar2_f)vvp2O}~Wxvaa zTZr>tXYWrSnT|Z&7fUf_%R-{J4VW0LlM6pntV}PfEvfAb64bKaTe$ z;oZoe@OFD&ga1yvcZtK;PATCX7>5wXz?*PAdC z%al!ypz=*-3@4})*Ki_V9^;Ir@?|mZnCd++89TDdmx-Z}G2^Suo`oEnUX4a$jBsdzc4Pf84(zqCwk{%S7~OrpLLKl8Dz-(z1^%=l5*v?p9Z1wKVlKiHl`01>N@-3v4?Z@Jd&OzwFyTfFE9i z&Ns4m-wfZUrt>LeHX!|KdO*&HWuxPa3-g(XZXRgJPtU+I-*Wu4q2o9z8{JM1-8|ryW(KJF z@!kmhcl5%&HPnrEnr<5Ac}%)pKx#D+pr(s?=#GP~CJWs&9=cNC9204$`RzqGXSJg$ zVjd<)L-4a*aW0T_tpDR4e)E8Hj!HYt@0f?*GVn`+i2P>ar}@o6gEGt80-S9~JI(J} zgq!k(F{xyMi2OJktohxg`5}M00pM}lEB|VKdo-PnLqxXvpv_h@-(|>G>xJ`LI^P#O z{FWgis(C9qqR)Hy)qx4y70bbT(foel;kN@3d=|7L9UV43xa8{rzbL}VkF(60-$Hmy zJ(r>%89=;tn%{@uG0S_<;1>q5=Jz=dKkmokGpC*A_q!f`=L~+FrPlm-?}#a13?0ZJ z%}mh|{h^0n)s>m@T8fVC^lHds@+-uW&q0K1$9(Co1f5yl9)sT;#B2FlKu5j-mGCh5 zm6CySn%`EHuSr*|i2ya-{hoXeB46FEu2*!-k7vPHjtG8qN0IMb+bjPvj=#@>4oxAh zqy80iIt{}}Lr16{4T*=5NgTT7{QPSCC?DmZPQcG`d$2_GyzbNys`>F*HtCL_98W_Q z?KIuW&Mg}|adtxAAm{8m%3()!an;fVmUI)_Q7yJB!r6B;2fL`4FUwGbA6MI02Ml9h zL2~*bswhx<7-%!*GVU+H-hv?ZAGKlqmitXwLRcTh-iAOZ;nR1o6%OG%wAe9%ezB-b zBu2uxSFP0An=ZoLabNq`&g4L`NWL6-B+0YYA)LFmlK6oi?S#_yQUPrxh(D719=L|@ z*s_56*h(5(s!>RsoW32{Tke- z!1g2eh=3ROIxt*A=E;1H&lv*GwW$jGta#u$@CY_?57ynZ$y!vb{Mc4lggqN_??nsN z%*${V-j6*Nw8uf7A)Fz{nfT$-810y#oUxbfaQGQ-g2tG(QX<)xj=)d*I|q}*lOu%)6UoF#DAboejIc0tWg)B_ zzY6@g2Zg%uq0(s!>-feY*u1?v#kxk5E}DY9B-APO$@~k%Jt^2-npNJ|550pw&b`wH z%dctIBaZzfsE-)zDNK#tnmn>Rk$Ngvin`8i>$U>4EAWT~U}ra~?A?A0-E%OJNKJzd z3&d`@7iH>TB2`2=B7N9raj&!ifJdo_G?YuA%w>a*qsvdEq`Il_WL7GFT5%F)VAxB(*}1Z3nJieaUaaxDLe~BXu~N#(z0C&*gcRuVPAr}EQ7tG zGMw>;eWtg{z_+0B*5scwf$x+{l2aQKsToiHaO9~=E=gVzdlYteA5TsZcgeP>Z3L7x zJ|^2DZSO+Oj@@1Idg{gUo}Gc9u=n945~=SX@2|fkT@hfB zZoB2!!&8B0EFfYj)T3EcKMpLIXd{u*sI5cvb}N(2r^hI|Z1vmeL(=WhgIKdaqX zTgCcqXj4eL>6#dj`#Ma=eH`wc3RC4+a+gDdm!9FcZ^KP*+aj)YX!wT6IPTMM(|h-6 zO!vgwwufJISa|ncT3NUyGyUvHK$2^caL2 zj`!`k~?2)^>qYFiDclw#HJG zcrPH=@tZU=K#pVn)Pv*2<~TXdF|r`Oz=PkT@H)iJL3`Tai68RdKk(4Mt#FQ=Y1^5$ zDe3m(M_bLj6GJ=Z-|xZy#e;vs7;KS#y9eK=aLUVl1wZiM?(7iwlKe4fa2)XpypXgbK40N6_)Em)Vz7qKpcasqe{Oafg-5H4QE8-EnDqT|#(A>q8qmv2A2!rM$)PBHjk5IakLzlAQM9J3$*0O-yc;(V<~(2SR4r7P z7aevCv^I6w(!GC$EE>o5I^*)Ny}qbHs@1l=4&6@vfsw5T2HaUQ?TuE0Jr`1KuyeoRvA z0nR%L2MFicbIZJ|knc0zImoe{9}`Q3#3S|?K!@{ud?UlFY&)Gy*F$`f5PgJ;?RDeu z65D=(-?Haa$q!z6C*lS|WG3bMh+2mS^koD{XmshatyJ{sne=|8gJ~^}N0JB{|{phf}fn-GP`PXP2HociFk;Pp*5P{8Kpn ziz~_h|9Tpicv)?n=qh|akG!+inE!*HzhJq$0Li1P(_R|0;e5QjE9X~U#Fa9PbIq?O zJo56H!u%Fy2km)IIkffA@j2zQNIE>Oay~R0T|MIX?2;~uA8GjWuDkI$HyyeK=_mvJ z$X>c!bm$7~dFKh}(1l2T`iq(T_Np`lvJ8OeGUdEz6p-#5K0zx0Sq^?ZlaA%uh#%#f zqP{=Q!e57^_V97_RyK0sJPvWkA9R(@yhy0s$t!D)7U9DIdSa zHNPSFB|ktq_P6_Oul%d|9R?=(skj<2tA?NQ@oQc4dk21#pFnxCmG@skXY$(te!3k% zl@7nzU}o~G1HWa6*G|iK4TwyB{RTg_UoBs~=BM<$3y|Mz+G&0<%}>$o0lx@{SYC6T z?B6s$#o#;|VoWmw)cm-Q-IVVz_~F0g$JqoeAMd@VIJ&*mA|ei4JI!y8rc)7z5YexR z05u)UXXbm%$d|Jaq@&*TdZa3@ScdP*Z0*Xs9{C3NRUkd}Vy=_%E=HCEuU_fagCBA2 z=;!a0qKl}AdqFo>6Db!^bJ;&mF5Yu<#q3=BU&Iuz1^pM3z!3z4Nxbe{oK zya6R$t{-~fnjhPaNf$)GR3kvs-P+OFglp053&F8CW3S6ZsuosSS?_jSur&X5nM14~ z<1PxG;^En7o>k>JPR@y*6ho=Y5Qe$il)yU6Y^=S^wq8z?PS5{x9+YbroY%!!R?hRL znlVor!5r$GwPUNfw51&KUM=hpgpE5lUcQdu@t# z?F&QrS>R!T2l9L;)Pej}dV~w>N!VlFDecHdAah~zskATj#iUPsDm5dDbGFgM3o}BA z7qELVaV>2bM^Sila}ZgUKh6{~n|RT`ciJFoyHINLK(pzM;g|#8Bd! zBA> zvLRnT^@Vw5jFh3H*a+SUuY?gl1M#oG-myRVal}K{$*qY0)X4X7?*Q}oSMaeomyI*t zbFAZ+`>Z)7vvC&K&T9yH4aqv?T24f+h4slbEv(%PL;jR~{`ZTgX?wjGbzK(O16$F1 z(t`_*rRGGAIcqp{*HRH0`2F}D%UiWM=@8-k0 zqI4`dZPBjs;Ga=AzlV5^E8)VYI5u?b_^EOqv?7uH<+}CHS>dvSeQHg|5>(h9r6^Ovt(Gry?^)59CL^|W@Q!t!(8 zZ@DT@GSyYc?@9UtDn1w8jfiI(n}}{6Xvk0Z=HzF-8ML3@UM3yCYuGlm({xWEz@+1M zO*Xn8dgvN+(0w1_d{ad6qvJhiEEk^-zG0Xz@&ARNnQss9AqFU?<+~MOCS8?3!<(d< zZUuv}3YJd`X*8XNS~lWu62XsSc8vXGzLbGw)ole{@g@ZNB{Ne_d%a_Q?sXf~ zk)YLHTAnnvU|G%{tfkq<`jrbR)lKdb@4>2I<2J_nRbrvcm-WK@`R3>MG0R1H8Fnpx z{Qjcf!f&?n&jF-<8D5Ux_4o;qkanQ>U2t}#eFsvp82F_>vN9R72GakBy0?Lkvbyud z&%A_$kirmS4eVGSAV^fi83-X*T8F$qP}GqGrCqj3AOi{JWts#;>fMgKi7eO=@r|ox zT5aoE|NUoo?Jes?|552`TiZ)lyrr)0&P*7g-kQ>VWqa-Ae!u5AXXcrQnIvHEe(wLk z)Uh1F=iF`~rZ_WxDk=a4;=`>Ia%2g7_{ zF!jiwEX7;b9Zt;+?o7gxZ;EH%A5BQ!^CpX z{!SryV>ZHW8STS7dq3>7fPOHF`uO(1&dL`O*w&tR4;@TRbfEk`=nVp28f}0`-XPx- zvJ9lnGO#SrbbHzneNghGjNq)_Jj2Y-?Wr~SRPYW^KlN~GiQ=~*FVC&M6KKz-;iaf2 z+tTMT+lTK9u%89~B-3us8pIWa8&J18@W;U(8{Wr0#ydixst@A}TN`8?)5Z};+e8yo zJi~}1!-6Iqr|15-EI)7tfzNiC4qI%eX^U#QX^Tph19+{Z4?Gv%!N4OmW38mMANpZ1 zb`%}j6C(}AF`aJrH3+ws!%PdiL#i%JUj-c9H)-2qJ6=9>=*cHvkwe?|hhv`Wkaqe# z*b6$)sU-DY!LGX;tH4R~{PF!*uEUCtk>$1X{OutP#)C(WW3SwZB+r7cj=Gz)-llTj z5csVk&`$GBE{MO>viXUl{uc;l+9r%S6 zKNH6-%XAy`1L^WIY$fP$ZZn;JUWvN^hW#7LyE4dk%hkhZ7t9&xS;M%RO&&Vm!;*h0 z0Qh>uVcqyKbXN_7SJAaHI8=ajzZhfv$4-Z|GdI2669dl__#<0Q9;)NUPr(DI`0K*3 z>jV4=;^40wp4xb`aS(Mom|8kxU7U8Lu*6-_tQTZG2 zXMzU%Tk^W0PaLkMVSHLD#(MVS2;$$v+;AeSo?$2#c<#n57wr2Lvn-rX1xTmM@done z8ppCshb_wqn6IoK`@S$3OE9n772g@&{h_-lHr!#Lf8e_ikF_#IJ4d&xclYDKDaN|$ z@YKbdaZfXCTlAx){`GO%+uTT7o3P{g`c1DVrf(bii2d#ajn|Pr+!{&hwq@S-c6~{e zpZ$hAheOlQj?>YO-$D5~S6Kdyc&0tQv1okZEPw9uy#xEGVU+LAVX^IpA0h8zZO0OIc$aBe|Gz_-CyFTA zsxIzw#D~p&I1qQ>z76egE!P^S8jo^)6*0d<#AXQbNF3|vER4eig^n=VKlTXLfgLX2 zfduGWCf5S2$1=SS`%hqL9LJwx;X(ZjuGN|+7BF}%*$vjaUXb@9as}&pM*R?f6HhVMB2fZ1M7rm;FGSU|c(~w_IL{Fn195eVBs+Z3sJ(Xk)hJ{uJ#l z%0A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

-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

D$ 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 bc_wbv05a6in+PO-VISupoD(60BKQ9RbWd4U diff --git a/Makefile b/Makefile index 0e1ea8c..2e6f929 100644 --- a/Makefile +++ b/Makefile @@ -5,39 +5,34 @@ $(error "Please set DEVKITARM in your environment. export DEVKITARM=dev endif TOPDIR ?= $(CURDIR) - include $(DEVKITARM)/3ds_rules -TARGET := OnionFS -PLGINFO := OnionFS.plgInfo +CTRPFLIB ?= $(DEVKITPRO)/libctrpf + +TARGET := $(notdir $(CURDIR)) +PLGINFO := OnionFS.plgInfo + BUILD := Build INCLUDES := Includes -LIBDIRS := $(TOPDIR) -SOURCES := Sources \ - Sources\Helpers - -IP := 19 -FTP_HOST := 192.168.1. -FTP_PORT := "5000" -FTP_PATH := "luma/plugins/" +SOURCES := Sources #--------------------------------------------------------------------------------- # options for code generation #--------------------------------------------------------------------------------- -ARCH := -march=armv6k -mlittle-endian -mtune=mpcore -mfloat-abi=hard -mtp=soft +ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft -CFLAGS := -Os -mword-relocations \ - -fomit-frame-pointer -ffunction-sections -fno-strict-aliasing \ - $(ARCH) +CFLAGS := $(ARCH) -Os -mword-relocations \ + -fomit-frame-pointer -ffunction-sections -fno-strict-aliasing CFLAGS += $(INCLUDE) -DARM11 -D_3DS CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 -ASFLAGS := $(ARCH) -LDFLAGS := -T $(TOPDIR)/3ds.ld $(ARCH) -Os -Wl,-Map,$(notdir $*.map),--gc-sections +ASFLAGS := $(ARCH) +LDFLAGS := -T $(TOPDIR)/3gx.ld $(ARCH) -Os -Wl,--gc-sections,--strip-discarded,--strip-debug -LIBS := -lCTRPluginFramework +LIBS := -lctrpf -lctru +LIBDIRS := $(CTRPFLIB) $(CTRULIB) $(PORTLIBS) #--------------------------------------------------------------------------------- # no real need to edit anything past this point unless you need to add additional @@ -56,7 +51,6 @@ export DEPSDIR := $(CURDIR)/$(BUILD) CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -# BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) export LD := $(CXX) export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) @@ -66,7 +60,7 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I $(CURDIR)/$(dir) ) \ export LIBPATHS := $(foreach dir,$(LIBDIRS),-L $(dir)/lib) -.PHONY: $(BUILD) re clean all snd send +.PHONY: $(BUILD) clean all #--------------------------------------------------------------------------------- all: $(BUILD) @@ -78,14 +72,10 @@ $(BUILD): #--------------------------------------------------------------------------------- clean: @echo clean ... - @-rm -fr $(BUILD) $(OUTPUT).3gx + @rm -fr $(BUILD) $(OUTPUT).3gx re: clean all -send: - @echo "Sending plugin over FTP" - @$(CURDIR)/sendfile.py $(TARGET).3gx $(FTP_PATH) "$(FTP_HOST)$(IP)" $(FTP_PORT) - #--------------------------------------------------------------------------------- else @@ -107,12 +97,11 @@ $(OUTPUT).3gx : $(OFILES) #--------------------------------------------------------------------------------- %.3gx: %.elf +#--------------------------------------------------------------------------------- @echo creating $(notdir $@) - @$(OBJCOPY) -O binary $(OUTPUT).elf $(TOPDIR)/objdump -S - @3gxtool.exe -s $(TOPDIR)/objdump $(TOPDIR)/$(PLGINFO) $@ - @- rm $(TOPDIR)/objdump + @3gxtool -s $(word 1, $^) $(TOPDIR)/$(PLGINFO) $@ -include $(DEPENDS) -#--------------------------------------------------------------------------------------- +#--------------------------------------------------------------------------------- endif diff --git a/OnionFS.plgInfo b/OnionFS.plgInfo index 4969158..906b5fa 100644 --- a/OnionFS.plgInfo +++ b/OnionFS.plgInfo @@ -2,7 +2,7 @@ Author: PabloMK7 Version: # Plugin version Major: 2 - Minor: 0 + Minor: 1 Revision: 0 Targets: # Low TitleId of games which are compatibles with this plugin (empty for all) @@ -12,4 +12,4 @@ Title: OnionFS Summary: ROMFS and SAVE redirection. Description: | - This plugin redirects ROMFS and SAVE access to the SD cards allowing multiple save slots and rom hacks. + This plugin redirects ROMFS and SAVE access to the SD card allowing multiple save slots and rom hacks. diff --git a/OnionFS.sln b/OnionFS.sln deleted file mode 100644 index 209ab35..0000000 --- a/OnionFS.sln +++ /dev/null @@ -1,31 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27428.2037 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OnionFS", "OnionFS.vcxproj", "{5DF9CE17-A431-445B-AF47-B09CF964BA9D}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {5DF9CE17-A431-445B-AF47-B09CF964BA9D}.Debug|x64.ActiveCfg = Debug|x64 - {5DF9CE17-A431-445B-AF47-B09CF964BA9D}.Debug|x64.Build.0 = Debug|x64 - {5DF9CE17-A431-445B-AF47-B09CF964BA9D}.Debug|x86.ActiveCfg = Debug|Win32 - {5DF9CE17-A431-445B-AF47-B09CF964BA9D}.Debug|x86.Build.0 = Debug|Win32 - {5DF9CE17-A431-445B-AF47-B09CF964BA9D}.Release|x64.ActiveCfg = Release|x64 - {5DF9CE17-A431-445B-AF47-B09CF964BA9D}.Release|x64.Build.0 = Release|x64 - {5DF9CE17-A431-445B-AF47-B09CF964BA9D}.Release|x86.ActiveCfg = Release|Win32 - {5DF9CE17-A431-445B-AF47-B09CF964BA9D}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {9984EB76-C3D8-47E8-B0FA-76C521D738CF} - EndGlobalSection -EndGlobal diff --git a/OnionFS.vcxproj b/OnionFS.vcxproj deleted file mode 100644 index 0fa528c..0000000 --- a/OnionFS.vcxproj +++ /dev/null @@ -1,235 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {5DF9CE17-A431-445B-AF47-B09CF964BA9D} - Win32Proj - - - - Makefile - true - v141 - - - Makefile - false - v141 - - - Makefile - true - v141 - - - Makefile - false - v141 - - - - - - - - - - - - - - - - - - - - - make - make clean - make re - WIN32;_DEBUG;$(NMakePreprocessorDefinitions) - $(NMakeForcedIncludes) - D:\Documentos\3dshack\OnionFS\Includes;$(NMakeIncludeSearchPath) - - - make - make clean - make re - _DEBUG;$(NMakePreprocessorDefinitions) - D:\Documentos\3dshack\OnionFS\v2\Includes;$(NMakeForcedIncludes) - - - make - make clean - make re - WIN32;NDEBUG;$(NMakePreprocessorDefinitions) - D:\Documentos\3dshack\OnionFS\v2\Includes;$(NMakeForcedIncludes) - - - make - make clean - make re - NDEBUG;$(NMakePreprocessorDefinitions) - D:\Documentos\3dshack\OnionFS\v2\Includes;$(NMakeForcedIncludes) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/OnionFS.vcxproj.filters b/OnionFS.vcxproj.filters deleted file mode 100644 index fcac09c..0000000 --- a/OnionFS.vcxproj.filters +++ /dev/null @@ -1,401 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Archivos de origen - - - Archivos de origen - - - Archivos de origen - - - Archivos de origen - - - Archivos de origen - - - Archivos de origen - - - Archivos de origen - - - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - Archivos de encabezado - - - - - - - - - - - \ No newline at end of file diff --git a/Sources/bootloader.s b/Sources/bootloader.s deleted file mode 100644 index 859506d..0000000 --- a/Sources/bootloader.s +++ /dev/null @@ -1,47 +0,0 @@ -.arm -.align(4); -.section .text -.global _start -_start: - stmfd sp!, {r0-r12, lr} - mrs r0, cpsr - stmfd sp!, {r0} - - @ Clear the BSS section - ldr r0, = __c_bss_start - ldr r1, = __c_bss_end - sub r1, r1, r0 - bl ClearMem - - bl LaunchMainThread - - ldmfd sp!, {r0} - msr cpsr, r0 - ldmfd sp!, {r0-r12, pc} - -@--------------------------------------------------------------------------------- -@ Clear memory to 0x00 if length != 0 -@ r0 = Start Address -@ r1 = Length -@--------------------------------------------------------------------------------- -ClearMem: -@--------------------------------------------------------------------------------- - mov r2, #3 @ Round down to nearest word boundary - add r1, r1, r2 @ Shouldnt be needed - bics r1, r1, r2 @ Clear 2 LSB (and set Z) - bxeq lr @ Quit if copy size is 0 - - mov r2, #0 -ClrLoop: - stmia r0!, {r2} - subs r1, r1, #4 - bne ClrLoop - bx lr - -.section .__bss_start -.global __c_bss_start -__c_bss_start: - -.section .__bss_end -.global __c_bss_end -__c_bss_end: diff --git a/Sources/hooked_func.cpp b/Sources/hooked_func.cpp index e5633e6..6cffd70 100644 --- a/Sources/hooked_func.cpp +++ b/Sources/hooked_func.cpp @@ -8,6 +8,9 @@ namespace CTRPluginFramework { LightLock regLock; LightLock openLock; + Mutex debugMutex; + #define DEBUGLOCK do{if (ENABLE_DEBUG) debugMutex.Lock();} while (0) + #define DEBUGUNLOCK do{if (ENABLE_DEBUG) debugMutex.Unlock();} while (0) int strlen16(u16* str) { int sz = 0; while (*str++) sz++; @@ -50,6 +53,7 @@ namespace CTRPluginFramework { u16* calculateNewPath(u16* initialPath, bool isReadOnly, bool isSecondary = false, bool* shouldReopen = nullptr) { u8 mode; if (shouldReopen) *shouldReopen = true; + DEBUGLOCK; DEBUG("Checking: "); DEBUGU16(initialPath); if (OnionSave::getArchive(initialPath, &mode, isReadOnly)) { @@ -70,18 +74,22 @@ namespace CTRPluginFramework { DEBUG(" redirected: "); DEBUGU16(dst); DEBUG("\n"); + DEBUGUNLOCK; return dst; } else { DEBUG(" not redirected.\n"); + DEBUGUNLOCK; return initialPath; } } u32 fsOpenFileFunc(u32 a1, u16* path, u32 a2) { bool reopen; + DEBUGLOCK; DEBUG("fsOpenFile: "); u16* newPath = calculateNewPath(path, 0, false, &reopen); + DEBUGUNLOCK; int ret = ((fsu32u16u32)fileOpHooks[OPEN_FILE_OP].callCode)(a1, newPath, a2); if (newPath != path) { if (!reopen) return ret; @@ -106,8 +114,10 @@ namespace CTRPluginFramework { u32 fsOpenDirectoryFunc(u32 a1, u16* path) { //customBreak(0xbaca, 1, 0); + DEBUGLOCK; DEBUG("fsOpenDirectory: "); u16* newPath = calculateNewPath(path, 0); + DEBUGUNLOCK; if (newPath != path) { int res = checkFileExistsWithDir(newPath); if (res) return res; @@ -119,58 +129,72 @@ namespace CTRPluginFramework { u32 fsDeleteFileFunc(u16* path) { //customBreak(0xbaca, 2, 0); + DEBUGLOCK; DEBUG("fsDeleteFile: "); u16* newPath = calculateNewPath(path, 1); + DEBUGUNLOCK; int ret = ((fsu16)fileOpHooks[DELETE_FILE_OP].callCode)(newPath); return ret; } u32 fsRenameFileFunc(u16* path1, u16* path2) { //customBreak(0xbaca, 3, 0); + DEBUGLOCK; DEBUG("fsRenameFileFrom: "); u16* newPath1 = calculateNewPath(path1, 1); DEBUG("fsRenameFileTo: "); u16* newPath2 = calculateNewPath(path2, 1, true); + DEBUGUNLOCK; int ret = ((fsu16u16)fileOpHooks[RENAME_FILE_OP].callCode)(newPath1, newPath2); return ret; } u32 fsDeleteDirectoryFunc(u16* path) { //customBreak(0xbaca, 4, 0); + DEBUGLOCK; DEBUG("fsDeleteDirectory: "); u16* newPath = calculateNewPath(path, 1); + DEBUGUNLOCK; int ret = ((fsu16)fileOpHooks[DELETE_DIRECTORY_OP].callCode)(newPath); return ret; } u32 fsDeleteDirectoryRecFunc(u16* path) { //customBreak(0xbaca, 5, 0); + DEBUGLOCK; DEBUG("fsDeleteDirectoryRecursive: "); u16* newPath = calculateNewPath(path, 1); + DEBUGUNLOCK; int ret = ((fsu16)fileOpHooks[DELETE_DIRECTORY_RECURSIVE_OP].callCode)(newPath); return ret; } u32 fsCreateFileFunc(u16* path, u64 a2) { //customBreak(0xbaca, 6, 0); + DEBUGLOCK; DEBUG("fsCreateFile: "); u16* newPath = calculateNewPath(path, 1); + DEBUGUNLOCK; int ret = ((fsu16u64)fileOpHooks[CREATE_FILE_OP].callCode)(newPath, a2); return ret; } u32 fsCreateDirectoryFunc(u16* path) { //customBreak(0xbaca, 7, 0); + DEBUGLOCK; DEBUG("fsCreateDirectory: "); u16* newPath = calculateNewPath(path, 1); + DEBUGUNLOCK; int ret = ((fsu16)fileOpHooks[CREATE_DIRECTORY_OP].callCode)(newPath); return ret; } u32 fsRenameDirectoryFunc(u16* path1, u16* path2) { //customBreak(0xbaca, 8, 0); + DEBUGLOCK; DEBUG("fsRenameDirectoryFrom: "); u16* newPath1 = calculateNewPath(path1, 1); DEBUG("fsRenameDirectoryTo: "); u16* newPath2 = calculateNewPath(path2, 1, true); + DEBUGUNLOCK; int ret = ((fsu16u16)fileOpHooks[RENAME_DIRECTORY_OP].callCode)(newPath1, newPath2); return ret; } @@ -183,9 +207,11 @@ namespace CTRPluginFramework { u32 sdmcArchive = 0; ret = ((fsRegArchiveTypeDef)regArchiveHook.callCode)(path, arch, isAddOnContent, isAlias); if (!ret) { + DEBUGLOCK; LightLock_Lock(®Lock); OnionSave::addArchive(path, arch[2] | (u64)(arch[3]) << 32); LightLock_Unlock(®Lock); + DEBUGUNLOCK; } if (isFisrt) { isFisrt = 0; @@ -212,29 +238,39 @@ namespace CTRPluginFramework { if (R_FAILED(ret = svcSendSyncRequest(*fsHandle))) customBreak(0xbad, ret, 0); *out = cmdbuf[2] | ((u64)(cmdbuf[3]) << 32); + DEBUGLOCK; DEBUG("fsOpenArch return 0x%08X%08X\n", cmdbuf[3], cmdbuf[2]); if ((u32)(*out) < 0x100000) OnionSave::addArchiveHnd(*out, archiveID); + DEBUGUNLOCK; return cmdbuf[1]; } //Stubbed functions, this prevents formatting the save data archive as well as updating secure nand values int fsFormatSaveData(int *a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, char a11) { + DEBUGLOCK; DEBUG("fsFormatSaveData called, removing save directory.\n"); + DEBUGUNLOCK; Directory::Remove(TOP_DIR "/" << std::string(OnionSave::settings.entries[OnionSave::settings.header.lastLoadedPack].name) << "/save"); Directory::Create(TOP_DIR "/" << std::string(OnionSave::settings.entries[OnionSave::settings.header.lastLoadedPack].name) << "/save"); return 0; } int fsSetThisSaveDataSecureValue(u32 a1, u64 a2) { //0x086E00C0 + DEBUGLOCK; DEBUG("fsSetThisSaveDataSecureValue called with secure value 0x%016llX, ignoring.\n", a2); + DEBUGUNLOCK; return 0; } int Obsoleted_5_0_fsSetSaveDataSecureValue(u64 a1, u32 a2, u32 a3, u8 a4) { // 0x08650140 + DEBUGLOCK; DEBUG("fsSetThisSaveDataSecureValue called with secure value 0x%016llX, ignoring.\n", a1); + DEBUGUNLOCK; return 0; } int fsSetSaveDataSecureValue(u64 a1, u32 a2, u64 a3, u8 a4 ) { // 0x08750180 + DEBUGLOCK; DEBUG("fsSetThisSaveDataSecureValue called with secure value 0x%016llX, ignoring.\n", a1); + DEBUGUNLOCK; return 0; } } \ No newline at end of file diff --git a/Sources/main.cpp b/Sources/main.cpp index 5f3904f..b7cd90a 100644 --- a/Sources/main.cpp +++ b/Sources/main.cpp @@ -1,7 +1,6 @@ #include "CTRPluginFramework.hpp" #include "main.hpp" #include "save.hpp" -#include "ptm.h" #include "patches.hpp" u8 fsMountArchivePat1[] = { 0x10, 0x00, 0x97, 0xE5, 0xD8, 0x20, 0xCD, 0xE1, 0x00, 0x00, 0x8D }; diff --git a/Sources/ptm.c b/Sources/ptm.c deleted file mode 100644 index 5089151..0000000 --- a/Sources/ptm.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "ptm.h" - -static int ptmSysmRefCount; -static Handle ptmSysmHandle; - -Result ptmSysmInit(void) -{ - if (AtomicPostIncrement(&ptmSysmRefCount)) return 0; - Result res = srvGetServiceHandle(&ptmSysmHandle, "ptm:sysm"); - if (R_FAILED(res)) AtomicDecrement(&ptmSysmRefCount); - return res; -} - -void ptmSysmExit(void) -{ - if (AtomicDecrement(&ptmSysmRefCount)) return; - svcCloseHandle(ptmSysmHandle); -} - -Result PTMSYSM_RebootAsync(u64 timeout) -{ - Result ret; - u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x409, 2, 0); // 0x04090080 - cmdbuf[1] = timeout & 0xffffffff; - cmdbuf[2] = (timeout >> 32) & 0xffffffff; - - if (R_FAILED(ret = svcSendSyncRequest(ptmSysmHandle)))return ret; - - return (Result)cmdbuf[1]; -} \ No newline at end of file diff --git a/Sources/rt.c b/Sources/rt.c index 8777758..03bcd7f 100644 --- a/Sources/rt.c +++ b/Sources/rt.c @@ -1,6 +1,7 @@ #include "3ds.h" #include "rt.h" +#include Handle hCurrentProcess = 0; u32 currentPid = 0; @@ -31,7 +32,7 @@ u32 rtGetPageOfAddress(u32 addr) { } u32 rtFlushInstructionCache(void* ptr, u32 size) { - return svcFlushProcessDataCache(getCurrentProcessHandle(), (const void*)ptr, size); + return svcFlushProcessDataCache(getCurrentProcessHandle(), (u32)ptr, size); } u32 rtGenerateJumpCode(u32 dst, u32* buf) { diff --git a/Sources/save.cpp b/Sources/save.cpp index 8f305e7..20a855a 100644 --- a/Sources/save.cpp +++ b/Sources/save.cpp @@ -1,6 +1,5 @@ #include "save.hpp" #include "main.hpp" -#include "ctrulib/util/utf.h" #include "Unicode.h" namespace CTRPluginFramework {