diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..08ad8ba --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/Build +*.3gx \ No newline at end of file diff --git a/3ds.ld b/3ds.ld new file mode 100644 index 0000000..477b8cf --- /dev/null +++ b/3ds.ld @@ -0,0 +1,193 @@ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +PHDRS +{ + code PT_LOAD FLAGS(5) /* Read | Execute */; + rodata PT_LOAD FLAGS(4) /* Read */; + data PT_LOAD FLAGS(6) /* Read | Write */; +} + +SECTIONS +{ + /* =========== CODE section =========== */ + . = 0x07000100; + __start__ = . ; + .text ALIGN(4) : + { + /* .init */ + bootloader.o (.text*) + KEEP( *(.init) ) + . = ALIGN(4); + + /* .text */ + *(.text) + *(.text.*) + *(.glue_7) + *(.glue_7t) + *(.stub) + *(.gnu.warning) + *(.gnu.linkonce.t*) + . = ALIGN(4); + + /* .fini */ + KEEP( *(.fini) ) + . = ALIGN(4); + } : code + + /* =========== RODATA section =========== */ + + .rodata ALIGN(0x4) : + { + *(.rodata) + *(.roda) + *(.rodata.*) + *all.rodata*(*) + *(.gnu.linkonce.r*) + SORT(CONSTRUCTORS) + . = ALIGN(4); + } : rodata + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } : rodata + __exidx_start = .; + ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } : rodata + __exidx_end = .; + + /* =========== DATA section =========== */ + + .data ALIGN(4): + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + CONSTRUCTORS + . = ALIGN(4); + } : data + + .tdata ALIGN(4) : + { + __tdata_lma = .; + *(.tdata) + *(.tdata.*) + *(.gnu.linkonce.td.*) + . = ALIGN(4); + __tdata_lma_end = .; + } : data + + .tbss ALIGN(4) : + { + *(.tbss) + *(.tbss.*) + *(.gnu.linkonce.tb.*) + *(.tcommon) + . = ALIGN(4); + } : data + + .preinit_array ALIGN(4) : + { + PROVIDE (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE (__preinit_array_end = .); + } : data + + .init_array ALIGN(4) : + { + PROVIDE (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE (__init_array_end = .); + } : data + + .fini_array ALIGN(4) : + { + PROVIDE (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE (__fini_array_end = .); + } : data + + .ctors ALIGN(4) : + { + KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */ + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } : data + + .dtors ALIGN(4) : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } : data + + .rel.plt ALIGN(4): + { + *(.__rel_dyn_start) + *(.rel*) + *(.rel.*) + *(.rel.dyn) + *(.__rel_dyn_end) + } : data + + + .bss ALIGN(4): + { *(.__bss_start) + *(.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 + + __end__ = ABSOLUTE(.) ; + + /* ================== + ==== Metadata ==== + ================== */ + + /* Discard sections that difficult post-processing */ + /DISCARD/ : { *(.group .comment .note) } + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } +} diff --git a/CTRPluginFramework.plgInfo b/CTRPluginFramework.plgInfo new file mode 100644 index 0000000..14c5024 --- /dev/null +++ b/CTRPluginFramework.plgInfo @@ -0,0 +1,23 @@ +Author: Nanquitas + +Version: # Plugin version + Major: 0 + Minor: 5 + Revision: 1 + +Targets: # Low TitleId of games which are compatibles with this plugin (0 for all) + +Title: CTRPF - Blank Template + +Summary: A CTRPF Plugin, with a lot of tools + +Description: | + This plugin gives you access to a set of tools to edit your games + + Features: + - Memory searcher + - Hex Editor + - Code creator + - Code import from file + - Action Replay engine with extra capabilities + - Super fast screenshot engine diff --git a/Includes/3ds.h b/Includes/3ds.h new file mode 100644 index 0000000..b936524 --- /dev/null +++ b/Includes/3ds.h @@ -0,0 +1,38 @@ +#ifndef _3DS_H +#define _3DS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "types.h" + +#include "ctrulib/allocator/newlibHeap.h" +#include "ctrulib/services/ac.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/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 "csvc.h" +#include "ctrulib/synchronization.h" +#include "ctrulib/thread.h" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Includes/CTRPluginFramework.hpp b/Includes/CTRPluginFramework.hpp new file mode 100644 index 0000000..39f5015 --- /dev/null +++ b/Includes/CTRPluginFramework.hpp @@ -0,0 +1,13 @@ +#ifndef CTRPLUGINFRAMEWORK_HPP +#define CTRPLUGINFRAMEWORK_HPP + +#include "types.h" + +using CallbackPointer = void (*)(void); + +#include "CTRPluginFramework/Graphics.hpp" +#include "CTRPluginFramework/Menu.hpp" +#include "CTRPluginFramework/System.hpp" +#include "CTRPluginFramework/Utils.hpp" + +#endif diff --git a/Includes/CTRPluginFramework/Graphics.hpp b/Includes/CTRPluginFramework/Graphics.hpp new file mode 100644 index 0000000..0356714 --- /dev/null +++ b/Includes/CTRPluginFramework/Graphics.hpp @@ -0,0 +1,7 @@ +#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 new file mode 100644 index 0000000..5e1b973 --- /dev/null +++ b/Includes/CTRPluginFramework/Graphics/Color.hpp @@ -0,0 +1,102 @@ +#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 new file mode 100644 index 0000000..7ead1c1 --- /dev/null +++ b/Includes/CTRPluginFramework/Graphics/OSD.hpp @@ -0,0 +1,131 @@ +#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 new file mode 100644 index 0000000..39bf5e6 --- /dev/null +++ b/Includes/CTRPluginFramework/Menu.hpp @@ -0,0 +1,11 @@ +#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 new file mode 100644 index 0000000..e11aea7 --- /dev/null +++ b/Includes/CTRPluginFramework/Menu/Keyboard.hpp @@ -0,0 +1,258 @@ +#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 new file mode 100644 index 0000000..aa416d0 --- /dev/null +++ b/Includes/CTRPluginFramework/Menu/MenuEntry.hpp @@ -0,0 +1,150 @@ +#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 new file mode 100644 index 0000000..dec46b7 --- /dev/null +++ b/Includes/CTRPluginFramework/Menu/MenuEntryHotkeys.hpp @@ -0,0 +1,133 @@ +#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 new file mode 100644 index 0000000..dcac520 --- /dev/null +++ b/Includes/CTRPluginFramework/Menu/MenuFolder.hpp @@ -0,0 +1,172 @@ +#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 new file mode 100644 index 0000000..e34b0fa --- /dev/null +++ b/Includes/CTRPluginFramework/Menu/MessageBox.hpp @@ -0,0 +1,45 @@ +#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 new file mode 100644 index 0000000..5fe16e5 --- /dev/null +++ b/Includes/CTRPluginFramework/Menu/PluginMenu.hpp @@ -0,0 +1,163 @@ +#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 new file mode 100644 index 0000000..0b76f7e --- /dev/null +++ b/Includes/CTRPluginFramework/System.hpp @@ -0,0 +1,19 @@ +#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 new file mode 100644 index 0000000..b594a90 --- /dev/null +++ b/Includes/CTRPluginFramework/System/Clock.hpp @@ -0,0 +1,22 @@ +#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 new file mode 100644 index 0000000..0ad3c2a --- /dev/null +++ b/Includes/CTRPluginFramework/System/Controller.hpp @@ -0,0 +1,73 @@ +#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 new file mode 100644 index 0000000..d6a4865 --- /dev/null +++ b/Includes/CTRPluginFramework/System/Directory.hpp @@ -0,0 +1,146 @@ +#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 new file mode 100644 index 0000000..6c95298 --- /dev/null +++ b/Includes/CTRPluginFramework/System/File.hpp @@ -0,0 +1,219 @@ +#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 new file mode 100644 index 0000000..71bad2b --- /dev/null +++ b/Includes/CTRPluginFramework/System/FwkSettings.hpp @@ -0,0 +1,82 @@ +#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 new file mode 100644 index 0000000..71f6087 --- /dev/null +++ b/Includes/CTRPluginFramework/System/Hook.hpp @@ -0,0 +1,62 @@ +#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 new file mode 100644 index 0000000..021e052 --- /dev/null +++ b/Includes/CTRPluginFramework/System/Lock.hpp @@ -0,0 +1,29 @@ +#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 new file mode 100644 index 0000000..04732c3 --- /dev/null +++ b/Includes/CTRPluginFramework/System/Mutex.hpp @@ -0,0 +1,24 @@ +#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 new file mode 100644 index 0000000..aa99509 --- /dev/null +++ b/Includes/CTRPluginFramework/System/Process.hpp @@ -0,0 +1,284 @@ +#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 new file mode 100644 index 0000000..8a803c6 --- /dev/null +++ b/Includes/CTRPluginFramework/System/Rect.hpp @@ -0,0 +1,147 @@ +#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 new file mode 100644 index 0000000..a40baac --- /dev/null +++ b/Includes/CTRPluginFramework/System/Sleep.hpp @@ -0,0 +1,12 @@ +#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 new file mode 100644 index 0000000..7a4cb6d --- /dev/null +++ b/Includes/CTRPluginFramework/System/System.hpp @@ -0,0 +1,63 @@ +#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 new file mode 100644 index 0000000..31a66c1 --- /dev/null +++ b/Includes/CTRPluginFramework/System/Task.hpp @@ -0,0 +1,73 @@ +#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 new file mode 100644 index 0000000..37f4a91 --- /dev/null +++ b/Includes/CTRPluginFramework/System/Time.hpp @@ -0,0 +1,118 @@ +#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 new file mode 100644 index 0000000..f38e5a2 --- /dev/null +++ b/Includes/CTRPluginFramework/System/Touch.hpp @@ -0,0 +1,16 @@ +#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 new file mode 100644 index 0000000..f99855d --- /dev/null +++ b/Includes/CTRPluginFramework/System/Vector.hpp @@ -0,0 +1,127 @@ +#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 new file mode 100644 index 0000000..4b0f0bb --- /dev/null +++ b/Includes/CTRPluginFramework/Utils.hpp @@ -0,0 +1,9 @@ +#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 new file mode 100644 index 0000000..b870e12 --- /dev/null +++ b/Includes/CTRPluginFramework/Utils/LineReader.hpp @@ -0,0 +1,27 @@ +#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 new file mode 100644 index 0000000..9e8fbdc --- /dev/null +++ b/Includes/CTRPluginFramework/Utils/LineWriter.hpp @@ -0,0 +1,34 @@ +#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 new file mode 100644 index 0000000..a3e2ecb --- /dev/null +++ b/Includes/CTRPluginFramework/Utils/StringExtensions.hpp @@ -0,0 +1,27 @@ +#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 new file mode 100644 index 0000000..0a94177 --- /dev/null +++ b/Includes/CTRPluginFramework/Utils/Utils.hpp @@ -0,0 +1,149 @@ +#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/Unicode.h b/Includes/Unicode.h new file mode 100644 index 0000000..d3f034d --- /dev/null +++ b/Includes/Unicode.h @@ -0,0 +1,22 @@ +#ifndef UNICODE_H +#define UNICODE_H + +// HID Symbols +#define FONT_A "\uE000" // System Font A button +#define FONT_B "\uE001" // System Font B button +#define FONT_X "\uE002" // System Font X button +#define FONT_Y "\uE003" // System Font Y button +#define FONT_L "\uE052" // System Font L button +#define FONT_R "\uE053" // System Font R button +#define FONT_ZL "\uE054" // System Font ZL button +#define FONT_ZR "\uE055" // System Font ZR button +#define FONT_DU "\uE079" // System Font D-Pad Up button +#define FONT_DD "\uE07A" // System Font D-Pad Down button +#define FONT_DL "\uE07B" // System Font D-Pad Left button +#define FONT_DR "\uE07C" // System Font D-Pad Right button +#define FONT_DUD "\uE07D" // System Font D-Pad Up and Down button +#define FONT_DLR "\uE07E" // System Font D-Pad Left and Right button +#define FONT_CP "\uE077" // System Font Circle Pad button +#define FONT_T "\uE058" // System Font Touch button + +#endif \ No newline at end of file diff --git a/Includes/csvc.h b/Includes/csvc.h new file mode 100644 index 0000000..c79f358 --- /dev/null +++ b/Includes/csvc.h @@ -0,0 +1,164 @@ +/* This paricular file is licensed under the following terms: */ + +/* +* This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable +* for any damages arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it +* and redistribute it freely, subject to the following restrictions: +* +* The origin of this software must not be misrepresented; you must not claim that you wrote the original software. +* If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +* +* Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +* This notice may not be removed or altered from any source distribution. +*/ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "types.h" + +#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)) + +/// Operations for svcControlService +typedef enum ServiceOp +{ + SERVICEOP_STEAL_CLIENT_SESSION = 0, ///< Steal a client session given a service or global port name + SERVICEOP_GET_NAME, ///< Get the name of a service or global port given a client or session handle +} ServiceOp; + +/** + * @brief Executes a function in supervisor mode, using the supervisor-mode stack. + * @param func Function to execute. + * @param ... Function parameters, up to 3 registers. +*/ +Result svcCustomBackdoor(void *func, ...); + +///@name I/O +///@{ +/** + * @brief Gives the physical address corresponding to a virtual address. + * @param VA Virtual address. + * @param writeCheck whether to check if the VA is writable in supervisor mode + * @return The corresponding physical address, or NULL. +*/ +u32 svcConvertVAToPA(const void *VA, bool writeCheck); + +/** + * @brief Flushes a range of the data cache (L2C included). + * @param addr Start address. + * @param len Length of the range. +*/ +void svcFlushDataCacheRange(void *addr, u32 len); + +/** + * @brief Flushes the data cache entirely (L2C included). +*/ +void svcFlushEntireDataCache(void); + +/** + * @brief Invalidates a range of the instruction cache. + * @param addr Start address. + * @param len Length of the range. +*/ +void svcInvalidateInstructionCacheRange(void *addr, u32 len); + +/** + * @brief Invalidates the data cache entirely. +*/ +void svcInvalidateEntireInstructionCache(void); +///@} + +///@name Memory management +///@{ +/** + * @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). +*/ +Result svcMapProcessMemoryEx(Handle dstProcessHandle, u32 vaDst, Handle srcProcessHandle, u32 vaSrc, 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 size Size of the block of memory to unmap (truncated to a multiple of 0x1000 bytes). + */ +Result svcUnmapProcessMemoryEx(Handle process, u32 destAddress, u32 size); + +/** + * @brief Controls memory mapping, with the choice to use region attributes or not. + * @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. + * @param isLoader Whether to use the region attributes + * 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. + * + * @sa svcControlMemory + */ +Result svcControlMemoryEx(u32* addr_out, u32 addr0, u32 addr1, u32 size, MemOp op, MemPerm perm, bool isLoader); +///@} + +///@name System +///@{ +/** + * @brief Performs actions related to services or global handles. + * @param op The operation to perform, see @ref ServiceOp. + * + * Examples: + * svcControlService(SERVICEOP_GET_NAME, (char [12])outName, (Handle)clientOrSessionHandle); + * svcControlService(SERVICEOP_STEAL_CLIENT_SESSION, (Handle *)&outHandle, (const char *)name); + */ +Result svcControlService(ServiceOp op, ...); + +/** + * @brief Copy a handle from a process to another one. + * @param[out] out The output handle. + * @param outProcess Handle of the process of the output handle. + * @param in The input handle. Pseudo-handles are not accepted. + * @param inProcess Handle of the process of the input handle. +*/ +Result svcCopyHandle(Handle *out, Handle outProcess, Handle in, Handle inProcess); + +/** + * @brief Get the address and class name of the underlying kernel object corresponding to a handle. + * @param[out] outKAddr The output kernel address. + * @param[out] outName Output class name. The buffer should be large enough to contain it. + * @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 + ///< 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; + +Result svcControlProcess(Handle process, ProcessOp op, u32 varg2, u32 varg3); + +#ifdef __cplusplus +} +#endif diff --git a/Includes/ctrulib/allocator/linear.h b/Includes/ctrulib/allocator/linear.h new file mode 100644 index 0000000..8b09781 --- /dev/null +++ b/Includes/ctrulib/allocator/linear.h @@ -0,0 +1,41 @@ +/** + * @file linear.h + * @brief Linear memory allocator. + */ +#pragma once + +/** + * @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); diff --git a/Includes/ctrulib/allocator/mappable.h b/Includes/ctrulib/allocator/mappable.h new file mode 100644 index 0000000..826bc74 --- /dev/null +++ b/Includes/ctrulib/allocator/mappable.h @@ -0,0 +1,24 @@ +/** + * @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 new file mode 100644 index 0000000..b492e49 --- /dev/null +++ b/Includes/ctrulib/allocator/newlibHeap.h @@ -0,0 +1,18 @@ +#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 new file mode 100644 index 0000000..4355b2f --- /dev/null +++ b/Includes/ctrulib/allocator/vram.h @@ -0,0 +1,41 @@ +/** + * @file vram.h + * @brief VRAM allocator. + */ +#pragma once + +/** + * @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); diff --git a/Includes/ctrulib/env.h b/Includes/ctrulib/env.h new file mode 100644 index 0000000..56807a7 --- /dev/null +++ b/Includes/ctrulib/env.h @@ -0,0 +1,85 @@ +/** + * @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 new file mode 100644 index 0000000..3723716 --- /dev/null +++ b/Includes/ctrulib/errf.h @@ -0,0 +1,122 @@ +/** + * @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 new file mode 100644 index 0000000..9477d0c --- /dev/null +++ b/Includes/ctrulib/font.h @@ -0,0 +1,218 @@ +/** + * @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 new file mode 100644 index 0000000..79d8985 --- /dev/null +++ b/Includes/ctrulib/gfx.h @@ -0,0 +1,176 @@ +/** + * @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 new file mode 100644 index 0000000..650c213 --- /dev/null +++ b/Includes/ctrulib/gpu/enums.h @@ -0,0 +1,464 @@ +/** + * @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 new file mode 100644 index 0000000..5ef29a9 --- /dev/null +++ b/Includes/ctrulib/gpu/gpu-old.h @@ -0,0 +1,241 @@ +/** + * @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 new file mode 100644 index 0000000..605282e --- /dev/null +++ b/Includes/ctrulib/gpu/gpu.h @@ -0,0 +1,115 @@ +/** + * @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 new file mode 100644 index 0000000..eba61e4 --- /dev/null +++ b/Includes/ctrulib/gpu/gx.h @@ -0,0 +1,138 @@ +/** + * @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 new file mode 100644 index 0000000..bf28cb2 --- /dev/null +++ b/Includes/ctrulib/gpu/registers.h @@ -0,0 +1,773 @@ +/** + * @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 new file mode 100644 index 0000000..15d99ec --- /dev/null +++ b/Includes/ctrulib/gpu/shaderProgram.h @@ -0,0 +1,142 @@ +/** + * @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 new file mode 100644 index 0000000..e3f016d --- /dev/null +++ b/Includes/ctrulib/gpu/shbin.h @@ -0,0 +1,121 @@ +/** + * @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 new file mode 100644 index 0000000..4cbbb8b --- /dev/null +++ b/Includes/ctrulib/ipc.h @@ -0,0 +1,118 @@ +/** + * @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/os.h b/Includes/ctrulib/os.h new file mode 100644 index 0000000..a2dcce3 --- /dev/null +++ b/Includes/ctrulib/os.h @@ -0,0 +1,190 @@ +/** + * @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/result.h b/Includes/ctrulib/result.h new file mode 100644 index 0000000..f6e11d9 --- /dev/null +++ b/Includes/ctrulib/result.h @@ -0,0 +1,95 @@ +/** + * @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 new file mode 100644 index 0000000..3e8a50b --- /dev/null +++ b/Includes/ctrulib/sdmc.h @@ -0,0 +1,34 @@ +/** + * @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 new file mode 100644 index 0000000..5b50787 --- /dev/null +++ b/Includes/ctrulib/services/ac.h @@ -0,0 +1,24 @@ +#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 new file mode 100644 index 0000000..89c88f7 --- /dev/null +++ b/Includes/ctrulib/services/am.h @@ -0,0 +1,497 @@ +/** + * @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 new file mode 100644 index 0000000..0eacc7e --- /dev/null +++ b/Includes/ctrulib/services/apt.h @@ -0,0 +1,505 @@ +/** + * @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 new file mode 100644 index 0000000..7fbaab0 --- /dev/null +++ b/Includes/ctrulib/services/cfgu.h @@ -0,0 +1,107 @@ +/** + * @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/fs.h b/Includes/ctrulib/services/fs.h new file mode 100644 index 0000000..e1061a8 --- /dev/null +++ b/Includes/ctrulib/services/fs.h @@ -0,0 +1,1086 @@ +/** + * @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 new file mode 100644 index 0000000..ce1b377 --- /dev/null +++ b/Includes/ctrulib/services/gspgpu.h @@ -0,0 +1,226 @@ +/** + * @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 new file mode 100644 index 0000000..02b50fe --- /dev/null +++ b/Includes/ctrulib/services/hid.h @@ -0,0 +1,189 @@ +/** + * @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 new file mode 100644 index 0000000..a666b43 --- /dev/null +++ b/Includes/ctrulib/services/irrst.h @@ -0,0 +1,62 @@ +/** + * @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/srv.h b/Includes/ctrulib/srv.h new file mode 100644 index 0000000..a33b3fc --- /dev/null +++ b/Includes/ctrulib/srv.h @@ -0,0 +1,125 @@ +/** + * @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 new file mode 100644 index 0000000..20fb0cd --- /dev/null +++ b/Includes/ctrulib/svc.h @@ -0,0 +1,1115 @@ +/** + * @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 new file mode 100644 index 0000000..989f580 --- /dev/null +++ b/Includes/ctrulib/synchronization.h @@ -0,0 +1,171 @@ +/** + * @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/thread.h b/Includes/ctrulib/thread.h new file mode 100644 index 0000000..d8b5791 --- /dev/null +++ b/Includes/ctrulib/thread.h @@ -0,0 +1,140 @@ +/** + * @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 new file mode 100644 index 0000000..08778b9 --- /dev/null +++ b/Includes/ctrulib/util/rbtree.h @@ -0,0 +1,149 @@ +/** + * @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 new file mode 100644 index 0000000..34a93c3 --- /dev/null +++ b/Includes/ctrulib/util/utf.h @@ -0,0 +1,160 @@ +/** + * @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/types.h b/Includes/types.h new file mode 100644 index 0000000..4412ce6 --- /dev/null +++ b/Includes/types.h @@ -0,0 +1,104 @@ +/** + * @file types.h + * @brief Various system types. + */ +#pragma once +#ifndef TYPES_H +#define TYPES_H + +#include +#include +#include +/// The maximum value of a u64. +#define U64_MAX UINT64_MAX + +/// would be nice if newlib had this already +#ifndef SSIZE_MAX +#ifdef SIZE_MAX +#define SSIZE_MAX ((SIZE_MAX) >> 1) +#endif +#endif + +typedef uint8_t u8; ///< 8-bit unsigned integer +typedef uint16_t u16; ///< 16-bit unsigned integer +typedef uint32_t u32; ///< 32-bit unsigned integer +typedef uint64_t u64; ///< 64-bit unsigned integer + +typedef int8_t s8; ///< 8-bit signed integer +typedef int16_t s16; ///< 16-bit signed integer +typedef int32_t s32; ///< 32-bit signed integer +typedef int64_t s64; ///< 64-bit signed integer + +typedef volatile u8 vu8; ///< 8-bit volatile unsigned integer. +typedef volatile u16 vu16; ///< 16-bit volatile unsigned integer. +typedef volatile u32 vu32; ///< 32-bit volatile unsigned integer. +typedef volatile u64 vu64; ///< 64-bit volatile unsigned integer. + +typedef volatile s8 vs8; ///< 8-bit volatile signed integer. +typedef volatile s16 vs16; ///< 16-bit volatile signed integer. +typedef volatile s32 vs32; ///< 32-bit volatile signed integer. +typedef volatile s64 vs64; ///< 64-bit volatile signed integer. + +typedef u32 Handle; ///< Resource handle. +typedef s32 Result; ///< Function result. +typedef void (*ThreadFunc)(void *); ///< Thread entrypoint function. +typedef void (*voidfn)(void); + +/// Creates a bitmask from a bit number. +#define BIT(n) (1U<<(n)) + +/// Aligns a struct (and other types?) to m, making sure that the size of the struct is a multiple of m. +#define ALIGN(m) __attribute__((aligned(m))) +/// Packs a struct (and other types?) so it won't include padding bytes. +#define PACKED __attribute__((packed)) +#define UNUSED __attribute__((unused)) + +#ifndef LIBCTRU_NO_DEPRECATION +/// Flags a function as deprecated. +#define DEPRECATED __attribute__ ((deprecated)) +#else +/// Flags a function as deprecated. +#define DEPRECATED +#endif + +#define USED __attribute__((used)) +#define UNUSED __attribute__((unused)) + +#define CUR_THREAD_HANDLE 0xFFFF8000 +#define CUR_PROCESS_HANDLE 0xFFFF8001 + +#define MPCORE_REGS_BASE (0x17E00000 | (1u << 31)) +#define MPCORE_SCU_CFG (*(vu32 *)(MPCORE_REGS_BASE + 4)) +#define MPCORE_INT_ACK (*(vu32 *)(MPCORE_REGS_BASE + 0x10C)) + +#define MPCORE_GID_REGS_BASE (MPCORE_REGS_BASE + 0x1000) +#define MPCORE_GID_SGI (*(vu32 *)(MPCORE_GID_REGS_BASE + 0xF00)) + +#define CFG11_REGS_BASE (0x10140000 | (1u << 31)) +#define CFG11_WIFICNT (*(vu8 *)(CFG11_REGS_BASE + 0x180)) +#define CFG11_MPCORE_CFG (*(vu16 *)(CFG11_REGS_BASE + 0xFFC)) +#define CFG11_MPCORE_CLKCNT (*(vu16 *)(CFG11_REGS_BASE + 0x1300)) + +#define L2C_REGS_BASE (0x17E10000 | (1u << 31)) +#define L2C_CTRL (*(vu32 *)(L2C_REGS_BASE + 0x100)) + +/// 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 diff --git a/Lib/libCTRPluginFramework.a b/Lib/libCTRPluginFramework.a new file mode 100644 index 0000000..07dcb6f Binary files /dev/null and b/Lib/libCTRPluginFramework.a differ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7e5a773 --- /dev/null +++ b/Makefile @@ -0,0 +1,107 @@ +.SUFFIXES: + +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") +endif + +TOPDIR ?= $(CURDIR) +include $(DEVKITARM)/3ds_rules + +TARGET := $(notdir $(CURDIR)) +PLGINFO := CTRPluginFramework.plgInfo + +BUILD := Build +INCLUDES := Includes +LIBDIRS := $(TOPDIR) +SOURCES := Sources + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -march=armv6k -mlittle-endian -mtune=mpcore -mfloat-abi=hard + +CFLAGS := -Os -mword-relocations \ + -fomit-frame-pointer -ffunction-sections -fno-strict-aliasing \ + $(ARCH) + +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 + +LIBS := -lCTRPluginFramework + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGET) +export TOPDIR := $(CURDIR) +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +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) +export INCLUDE := $(foreach dir,$(INCLUDES),-I $(CURDIR)/$(dir) ) \ + $(foreach dir,$(LIBDIRS),-I $(dir)/include) \ + -I $(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L $(dir)/lib) + +.PHONY: $(BUILD) clean all + +#--------------------------------------------------------------------------------- +all: $(BUILD) + +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(OUTPUT).3gx + +re: clean all + +#--------------------------------------------------------------------------------- + +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT).3gx : $(OFILES) +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +#--------------------------------------------------------------------------------- +%.3gx: %.elf + @echo creating $(notdir $@) + @$(OBJCOPY) -O binary $(OUTPUT).elf $(TOPDIR)/objdump -S + @3gxtool.exe -s $(TOPDIR)/objdump $(TOPDIR)/$(PLGINFO) $@ + @- rm $(TOPDIR)/objdump + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif diff --git a/Sources/bootloader.s b/Sources/bootloader.s new file mode 100644 index 0000000..5a007c1 --- /dev/null +++ b/Sources/bootloader.s @@ -0,0 +1,48 @@ +.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} +bx lr + +@--------------------------------------------------------------------------------- +@ 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/main.cpp b/Sources/main.cpp new file mode 100644 index 0000000..cf17515 --- /dev/null +++ b/Sources/main.cpp @@ -0,0 +1,95 @@ +#include "3ds.h" +#include "csvc.h" +#include "CTRPluginFramework.hpp" + +#include + +namespace CTRPluginFramework +{ + // This patch the NFC disabling the touchscreen when scanning an amiibo, which prevents ctrpf to be used + static void ToggleTouchscreenForceOn(void) + { + static u32 original = 0; + static u32 *patchAddress = nullptr; + + if (patchAddress && original) + { + *patchAddress = original; + return; + } + + static const std::vector pattern = + { + 0xE59F10C0, 0xE5840004, 0xE5841000, 0xE5DD0000, + 0xE5C40008, 0xE28DD03C, 0xE8BD80F0, 0xE5D51001, + 0xE1D400D4, 0xE3510003, 0x159F0034, 0x1A000003 + }; + + Result res; + Handle processHandle; + s64 textTotalSize = 0; + s64 startAddress = 0; + u32 * found; + + if (R_FAILED(svcOpenProcess(&processHandle, 16))) + return; + + svcGetProcessInfo(&textTotalSize, processHandle, 0x10002); + svcGetProcessInfo(&startAddress, processHandle, 0x10005); + if(R_FAILED(svcMapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x14000000, processHandle, (u32)startAddress, textTotalSize))) + goto exit; + + found = (u32 *)Utils::Search(0x14000000, (u32)textTotalSize, pattern); + + if (found != nullptr) + { + original = found[13]; + patchAddress = (u32 *)PA_FROM_VA((found + 13)); + found[13] = 0xE1A00000; + } + + svcUnmapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x14000000, textTotalSize); +exit: + svcCloseHandle(processHandle); + } + + // This function is called before main and before the game starts + // Useful to do code edits safely + void PatchProcess(FwkSettings &settings) + { + ToggleTouchscreenForceOn(); + } + + // This function is called when the process exits + // Useful to save settings, undo patchs or clean up things + void OnProcessExit(void) + { + ToggleTouchscreenForceOn(); + } + + void InitMenu(PluginMenu &menu) + { + // Create your entries here, or elsewhere + // You can create your entries whenever/wherever you feel like it + } + + int main(void) + { + PluginMenu *menu = new PluginMenu("Action Replay", 0, 5, 1, + "A blank template plugin.\nGives you access to the ActionReplay and others tools."); + + // Synnchronize the menu with frame event + menu->SynchronizeWithFrame(true); + + // Init our menu entries & folders + InitMenu(*menu); + + // Launch menu and mainloop + menu->Run(); + + delete menu; + + // Exit plugin + return (0); + } +}