diff --git a/README.md b/README.md index 1c93b86..1b3d046 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Since Luma3DS v8.0, Luma3DS has its own in-game menu, triggerable by `L+Down+Sel First you need to clone the repository with: `git clone https://github.com/AuroraWright/Luma3DS.git` To compile, you'll need [armips](https://github.com/Kingcom/armips) and a build of a recent commit of [makerom](https://github.com/profi200/Project_CTR) added to your PATH. You'll also need to install [firmtool](https://github.com/TuxSH/firmtool), its README contains installation instructions. For now, you'll also need to update your [libctru](https://github.com/smealum/ctrulib) install, building from the latest commit. -For your convenience, here are [Windows](http://www91.zippyshare.com/v/ePGpjk9r/file.html) and [Linux](https://mega.nz/#!uQ1T1IAD!Q91O0e12LXKiaXh_YjXD3D5m8_W3FuMI-hEa6KVMRDQ) builds of armips (thanks to who compiled them!). +For your convenience, here are [Windows](http://www91.zippyshare.com/v/ePGpjk9r/file.html) and [Linux](https://mega.nz/#!uQ1T1IAD!Q91O0e12LXKiaXh_YjXD3D5m8_W3FuMI-hEa6KVMRDQ) builds of armips (thanks to who compiled them!) and [makerom](https://github.com/Steveice10/buildtools/tree/master/3ds) (thanks @Steveice10!). Finally just run `make` and everything should work! You can find the compiled files in the `out` folder. diff --git a/sysmodules/rosalina/include/mcu.h b/sysmodules/rosalina/include/mcu.h new file mode 100644 index 0000000..7472853 --- /dev/null +++ b/sysmodules/rosalina/include/mcu.h @@ -0,0 +1,9 @@ +#include <3ds.h> + +Handle mcuhwcHandle; + +Result mcuInit(void); +Result mcuExit(void); +Result mcuReadRegister(u8 reg, u8* data, u32 size); +Result mcuWriteRegister(u8 reg, u8* data, u32 size); +Result mcuGetLEDState(u8* out); diff --git a/sysmodules/rosalina/include/menus/miscellaneous.h b/sysmodules/rosalina/include/menus/miscellaneous.h index c628c65..fa8bbd4 100644 --- a/sysmodules/rosalina/include/menus/miscellaneous.h +++ b/sysmodules/rosalina/include/menus/miscellaneous.h @@ -35,6 +35,7 @@ void MiscellaneousMenu_SwitchBoot3dsxTargetTitle(void); void MiscellaneousMenu_ChangeMenuCombo(void); void MiscellaneousMenu_SaveSettings(void); void MiscellaneousMenu_InputRedirection(void); +void MiscellaneousMenu_ToggleLEDs(void); void MiscellaneousMenu_ToggleWireless(void); void MiscellaneousMenu_PowerOff(void); void MiscellaneousMenu_Reboot(void); diff --git a/sysmodules/rosalina/source/mcu.c b/sysmodules/rosalina/source/mcu.c new file mode 100644 index 0000000..ce3177b --- /dev/null +++ b/sysmodules/rosalina/source/mcu.c @@ -0,0 +1,42 @@ +#include "mcu.h" + +Result mcuInit(void) +{ + return srvGetServiceHandle(&mcuhwcHandle, "mcu::HWC"); +} + +Result mcuExit(void) +{ + return svcCloseHandle(mcuhwcHandle); +} + +Result mcuReadRegister(u8 reg, u8* data, u32 size) +{ + u32* ipc = getThreadCommandBuffer(); + ipc[0] = 0x10082; + ipc[1] = reg; + ipc[2] = size; + ipc[3] = size << 4 | 0xC; + ipc[4] = (u32)data; + Result ret = svcSendSyncRequest(mcuhwcHandle); + if(ret < 0) return ret; + return ipc[1]; +} + +Result mcuWriteRegister(u8 reg, u8* data, u32 size) +{ + u32* ipc = getThreadCommandBuffer(); + ipc[0] = 0x20082; + ipc[1] = reg; + ipc[2] = size; + ipc[3] = size << 4 | 0xA; + ipc[4] = (u32)data; + Result ret = svcSendSyncRequest(mcuhwcHandle); + if(ret < 0) return ret; + return ipc[1]; +} + +Result mcuGetLEDState(u8* out) +{ + return mcuReadRegister(0x28, out, 1); +} diff --git a/sysmodules/rosalina/source/menu.c b/sysmodules/rosalina/source/menu.c index c320b77..cb8c097 100644 --- a/sysmodules/rosalina/source/menu.c +++ b/sysmodules/rosalina/source/menu.c @@ -28,6 +28,7 @@ #include "menu.h" #include "draw.h" #include "fmt.h" +#include "mcu.h" #include "memory.h" #include "ifile.h" #include "menus.h" @@ -125,11 +126,10 @@ u32 waitCombo(void) static Result _MCUHWC_GetBatteryLevel(u8 *out) { - #define TRY(expr) if(R_FAILED(res = (expr))) { svcCloseHandle(mcuhwcHandle); return res; } + #define TRY(expr) if(R_FAILED(res = (expr))) { mcuExit(); return res; } Result res; - Handle mcuhwcHandle; - TRY(srvGetServiceHandle(&mcuhwcHandle, "mcu::HWC")); + TRY(mcuInit()); u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = 0x50000; diff --git a/sysmodules/rosalina/source/menus/miscellaneous.c b/sysmodules/rosalina/source/menus/miscellaneous.c index 797046d..f4fa47a 100644 --- a/sysmodules/rosalina/source/menus/miscellaneous.c +++ b/sysmodules/rosalina/source/menus/miscellaneous.c @@ -27,6 +27,7 @@ #include <3ds.h> #include "menus/miscellaneous.h" #include "input_redirection.h" +#include "mcu.h" #include "memory.h" #include "draw.h" #include "hbloader.h" @@ -37,14 +38,15 @@ Menu miscellaneousMenu = { "Miscellaneous options menu", - .nbItems = 7, + .nbItems = 8, { { "Switch the hb. title to the current app.", METHOD, .method = &MiscellaneousMenu_SwitchBoot3dsxTargetTitle }, { "Change the menu combo", METHOD, .method = MiscellaneousMenu_ChangeMenuCombo }, { "Save settings", METHOD, .method = &MiscellaneousMenu_SaveSettings }, { "Start InputRedirection", METHOD, .method = &MiscellaneousMenu_InputRedirection }, + { "Toggle LEDs", METHOD, .method = &MiscellaneousMenu_ToggleLEDs }, { "Toggle Wireless", METHOD, .method = &MiscellaneousMenu_ToggleWireless }, - { "Power off", METHOD, .method = &MiscellaneousMenu_PowerOff }, + { "Power Off", METHOD, .method = &MiscellaneousMenu_PowerOff }, { "Reboot", METHOD, .method = &MiscellaneousMenu_Reboot }, } }; @@ -130,6 +132,7 @@ static void MiscellaneousMenu_ConvertComboToString(char *out, u32 combo) out[-1] = 0; } + void MiscellaneousMenu_ChangeMenuCombo(void) { char comboStrOrig[64], comboStr[64]; @@ -336,6 +339,40 @@ void MiscellaneousMenu_InputRedirection(void) while(!(waitInput() & BUTTON_B) && !terminationRequest); } +void MiscellaneousMenu_ToggleLEDs(void) +{ + Draw_Lock(); + Draw_ClearFramebuffer(); + Draw_FlushFramebuffer(); + Draw_Unlock(); + + do + { + Draw_Lock(); + Draw_DrawString(10, 10, COLOR_TITLE, "Miscellaneous options menu"); + Draw_DrawString(10, 30, COLOR_WHITE, "Press A to toggle, press B to go back."); + Draw_DrawString(10, 40, COLOR_RED, "NOTE: Entering sleep mode will reset the LED state!"); + + Draw_FlushFramebuffer(); + Draw_Unlock(); + + u32 pressed = waitInputWithTimeout(1000); + + if(pressed & BUTTON_A) + { + mcuInit(); + u8 result; + mcuGetLEDState(&result); + u8 value = ~result; + mcuWriteRegister(40, &value, 1); + mcuExit(); + } + else if(pressed & BUTTON_B) + return; + } + while(!terminationRequest); +} + void MiscellaneousMenu_ToggleWireless(void) { Draw_Lock();