Merge pull request #30 from TraceEntertains/main

This commit is contained in:
Jonathan Barrow 2024-04-07 17:56:09 -04:00 committed by GitHub
commit 6376b0b96b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 326 additions and 288 deletions

View file

@ -36,7 +36,7 @@ APP_DESCRIPTION := Nimbus
APP_AUTHOR := Zaksabeast, shutterbug2000
TARGET := nimbus
BUILD := build
SOURCES := source
SOURCES := source source/states source/sysmodules
DATA := data
INCLUDES := include
ROMFS := romfs

View file

@ -1,9 +1,6 @@
#include "common.hpp"
#include <3ds/services/cfgu.h>
NascEnvironment AccountToNascEnvironment(Account accountId) {
return static_cast<NascEnvironment>(static_cast<u8>(accountId) - 1);
}
#include <format>
// credit to the universal-team for most/all of the code past here
C2D_Font font;
@ -104,3 +101,9 @@ std::tuple<u8, u8> UnpackConfigVersion(s64 packed_config_version) {
return { (packed_config_version >> 16) & 0xFF, packed_config_version & 0xFF };
}
void drawLumaInfo(MainStruct *mainStruct) {
DrawString(0.5f, defaultColor, std::format("Luma version is {}.{}.{}\nLuma config version is {}.{}\n\nLuma3DS config bits are:\n{:016b}\n{:016b}\n{:016b}\n{:016b}",
std::get<0>(mainStruct->lumaVersion), std::get<1>(mainStruct->lumaVersion), std::get<2>(mainStruct->lumaVersion),
std::get<0>(mainStruct->lumaConfigVersion), std::get<1>(mainStruct->lumaConfigVersion), mainStruct->lumaOptions >> 48,
(mainStruct->lumaOptions >> 32) & 0xFFFF, (mainStruct->lumaOptions >> 16) & 0xFFFF, mainStruct->lumaOptions & 0xFFFF), 0);
}

View file

@ -4,19 +4,11 @@
#define M_PI 3.14159265358979323846
#endif
#include <stdint.h>
#include "../build/version.hpp"
#include <citro2d.h>
#include <3ds.h>
#include <algorithm>
#include <string>
#include <format>
#include "../build/version.hpp"
enum class Account : u8 {
Undefined = 0,
Nintendo = 1, // prod
Pretendo = 2 // test
};
enum class NascEnvironment : u8 {
NASC_ENV_Prod = 0, // nintendo
@ -39,6 +31,46 @@ enum class LumaConfigBitIndex : s32 {
const int targetLumaVersion = 13;
const int GetSystemInfoCFW = 0x10000; // the type for Luma3DS' GetSystemInfo hook that returns CFW info
const u32 defaultColor = C2D_Color32(255, 255, 255, 0xFF);
struct MainStruct {
C2D_Sprite debug_button;
C2D_Sprite debug_header;
C2D_Sprite go_back;
C2D_Sprite header;
C2D_Sprite nintendo_unloaded_deselected;
C2D_Sprite nintendo_unloaded_selected;
C2D_Sprite nintendo_loaded_selected;
C2D_Sprite nintendo_loaded_deselected;
C2D_Sprite pretendo_unloaded_deselected;
C2D_Sprite pretendo_unloaded_selected;
C2D_Sprite pretendo_loaded_selected;
C2D_Sprite pretendo_loaded_deselected;
C2D_Sprite top;
u32 screen = 0;
u32 state = 0;
u32 lastState = 0;
NascEnvironment currentAccount = NascEnvironment::NASC_ENV_Prod;
NascEnvironment buttonSelected = NascEnvironment::NASC_ENV_Prod;
bool firstRunOfState = true;
bool buttonWasPressed = false;
bool needsReboot = false;
// startup checking variables
s64 firmwareVersion;
std::tuple<u8, u8, u8> lumaVersion;
s64 configVersion;
std::tuple<u8, u8> lumaConfigVersion;
s64 lumaOptions;
bool gamePatchingEnabled;
bool externalFirmsAndModulesEnabled;
};
#define handleResult(action, name) \
rc = action; \
@ -46,8 +78,6 @@ const int GetSystemInfoCFW = 0x10000; // the type for Luma3DS' GetSystemInfo hoo
printf("%s error: %08lx\n\n", name, rc); \
}
extern NascEnvironment AccountToNascEnvironment(Account accountId);
// credit to the universal-team for most/all of the code past here
extern C2D_Font font;
extern C2D_TextBuf textBuf;
@ -75,4 +105,6 @@ void DrawVersionString();
bool GetLumaOptionByIndex(LumaConfigBitIndex index, s64 options);
s64 GetSystemInfoField(s32 category, CFWSystemInfoField accessor);
std::tuple<u8, u8, u8> UnpackLumaVersion(s64 packed_version);
std::tuple<u8, u8> UnpackConfigVersion(s64 packed_config_version);
std::tuple<u8, u8> UnpackConfigVersion(s64 packed_config_version);
void drawLumaInfo(MainStruct *mainStruct);

View file

@ -1,11 +0,0 @@
#pragma once
#include "common.hpp"
Result frdAInit();
void frdAExit();
Handle *frdAGetSessionHandle();
Result FRDA_CreateLocalAccount(Account localAccountId, NascEnvironment nascEnvironment, u8 serverTypeField1, u8 serverTypeField2);
Result FRDA_GetLocalAccountId(Account *localAccountId);
Result FRDA_SetLocalAccountId(Account localAccountId);
Result FRDA_SetClientSdkVersion(u32 sdkVer);

View file

@ -1,246 +1,47 @@
#include "acta.hpp"
#include "frda.hpp"
#include "sysmodules/acta.hpp"
#include "sysmodules/frda.hpp"
#include "sheet.h"
#include "sheet_t3x.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.hpp"
#include "states/LumaValidation.hpp"
#include "states/MainUI.hpp"
C2D_Sprite debug_button;
C2D_Sprite debug_header;
C2D_Sprite go_back;
C2D_Sprite header;
C2D_Sprite nintendo_unloaded_deselected;
C2D_Sprite nintendo_unloaded_selected;
C2D_Sprite nintendo_loaded_selected;
C2D_Sprite nintendo_loaded_deselected;
C2D_Sprite pretendo_unloaded_deselected;
C2D_Sprite pretendo_unloaded_selected;
C2D_Sprite pretendo_loaded_selected;
C2D_Sprite pretendo_loaded_deselected;
C2D_Sprite top;
u32 screen = 0;
u32 state = 0;
u32 lastState = 0;
Account currentEnv = Account::Undefined;
Account buttonSelected = Account::Undefined;
NascEnvironment environment;
u32 defaultColor = C2D_Color32(255, 255, 255, 0xFF);
bool firstStateRun = true;
bool buttonWasPressed = false;
bool needsReboot = false;
// startup checking variables
s64 firmwareVersion;
std::tuple<u8, u8, u8> lumaVersion;
s64 configVersion;
std::tuple<u8, u8> lumaConfigVersion;
s64 lumaOptions;
bool gamePatchingEnabled;
bool externalFirmsAndModulesEnabled;
MainStruct mainStruct = MainStruct();
static void sceneInit(void)
{
C2D_SpriteSheet spriteSheet = C2D_SpriteSheetLoadFromMem(sheet_t3x, sheet_t3x_size);
C2D_SpriteFromSheet(&top, spriteSheet, sheet_top_idx);
C2D_SpriteFromSheet(&go_back, spriteSheet, sheet_go_back_idx);
C2D_SpriteFromSheet(&header, spriteSheet, sheet_header_idx);
C2D_SpriteFromSheet(&nintendo_unloaded_deselected, spriteSheet, sheet_nintendo_unloaded_deselected_idx);
C2D_SpriteFromSheet(&nintendo_unloaded_selected, spriteSheet, sheet_nintendo_unloaded_selected_idx);
C2D_SpriteFromSheet(&nintendo_loaded_selected, spriteSheet, sheet_nintendo_loaded_selected_idx);
C2D_SpriteFromSheet(&nintendo_loaded_deselected, spriteSheet, sheet_nintendo_loaded_deselected_idx);
C2D_SpriteFromSheet(&pretendo_unloaded_deselected, spriteSheet, sheet_pretendo_unloaded_deselected_idx);
C2D_SpriteFromSheet(&pretendo_unloaded_selected, spriteSheet, sheet_pretendo_unloaded_selected_idx);
C2D_SpriteFromSheet(&pretendo_loaded_selected, spriteSheet, sheet_pretendo_loaded_selected_idx);
C2D_SpriteFromSheet(&pretendo_loaded_deselected, spriteSheet, sheet_pretendo_loaded_deselected_idx);
C2D_SpriteSetCenter(&top, 0.49f, 0.49f);
C2D_SpriteSetPos(&top, 400/2, 240/2);
C2D_SpriteSetPos(&go_back, 0, 214);
C2D_SpriteSetPos(&header, 95, 14);
C2D_SpriteSetPos(&pretendo_loaded_selected, 49, 59);
C2D_SpriteSetPos(&pretendo_unloaded_selected, 49, 59);
C2D_SpriteSetPos(&pretendo_unloaded_deselected, 49, 59);
C2D_SpriteSetPos(&pretendo_loaded_deselected, 49, 59);
C2D_SpriteSetPos(&nintendo_loaded_selected, 165, 59);
C2D_SpriteSetPos(&nintendo_unloaded_selected, 165, 59);
C2D_SpriteSetPos(&nintendo_unloaded_deselected, 165, 59);
C2D_SpriteSetPos(&nintendo_loaded_deselected, 165, 59);
C2D_SpriteFromSheet(&mainStruct.top, spriteSheet, sheet_top_idx);
C2D_SpriteFromSheet(&mainStruct.go_back, spriteSheet, sheet_go_back_idx);
C2D_SpriteFromSheet(&mainStruct.header, spriteSheet, sheet_header_idx);
C2D_SpriteFromSheet(&mainStruct.nintendo_unloaded_deselected, spriteSheet, sheet_nintendo_unloaded_deselected_idx);
C2D_SpriteFromSheet(&mainStruct.nintendo_unloaded_selected, spriteSheet, sheet_nintendo_unloaded_selected_idx);
C2D_SpriteFromSheet(&mainStruct.nintendo_loaded_selected, spriteSheet, sheet_nintendo_loaded_selected_idx);
C2D_SpriteFromSheet(&mainStruct.nintendo_loaded_deselected, spriteSheet, sheet_nintendo_loaded_deselected_idx);
C2D_SpriteFromSheet(&mainStruct.pretendo_unloaded_deselected, spriteSheet, sheet_pretendo_unloaded_deselected_idx);
C2D_SpriteFromSheet(&mainStruct.pretendo_unloaded_selected, spriteSheet, sheet_pretendo_unloaded_selected_idx);
C2D_SpriteFromSheet(&mainStruct.pretendo_loaded_selected, spriteSheet, sheet_pretendo_loaded_selected_idx);
C2D_SpriteFromSheet(&mainStruct.pretendo_loaded_deselected, spriteSheet, sheet_pretendo_loaded_deselected_idx);
C2D_SpriteSetCenter(&mainStruct.top, 0.49f, 0.49f);
C2D_SpriteSetPos(&mainStruct.top, 400/2, 240/2);
C2D_SpriteSetPos(&mainStruct.go_back, 0, 214);
C2D_SpriteSetPos(&mainStruct.header, 95, 14);
C2D_SpriteSetPos(&mainStruct.pretendo_loaded_selected, 49, 59);
C2D_SpriteSetPos(&mainStruct.pretendo_unloaded_selected, 49, 59);
C2D_SpriteSetPos(&mainStruct.pretendo_unloaded_deselected, 49, 59);
C2D_SpriteSetPos(&mainStruct.pretendo_loaded_deselected, 49, 59);
C2D_SpriteSetPos(&mainStruct.nintendo_loaded_selected, 165, 59);
C2D_SpriteSetPos(&mainStruct.nintendo_unloaded_selected, 165, 59);
C2D_SpriteSetPos(&mainStruct.nintendo_unloaded_deselected, 165, 59);
C2D_SpriteSetPos(&mainStruct.nintendo_loaded_deselected, 165, 59);
textBuf = C2D_TextBufNew(4096); // initialize the text buffer with a max glyph count of 4096
}
/**
* Switches the friends and act accounts.
*
* This will also create the act account if it's missing, just to be safe.
* This will fail if the friend account hasn't been created yet.
*/
Result switchAccounts(Account friend_account_id) {
Result rc = 0;
handleResult(FRDA_SetLocalAccountId(friend_account_id), "Switch account");
if (rc) {
return rc;
}
u32 act_account_index = 0;
handleResult(ACTA_GetAccountIndexOfFriendAccountId(&act_account_index, friend_account_id), "Get persistent id for creation");
if (act_account_index == 0) {
handleResult(ACTA_CreateLocalAccount(), "Create act account");
handleResult(ACTA_GetAccountIndexOfFriendAccountId(&act_account_index, friend_account_id),
"Get persistent id after creation");
}
handleResult(ACTA_SetDefaultAccount(act_account_index), "Set default account");
return rc;
}
Result createAccount(Account friend_account_id) {
Result rc = 0;
// (Re)Create the friend account
handleResult(FRDA_CreateLocalAccount(friend_account_id, environment, 0, 1), "Create account");
// Switch to the friend/act accounts
handleResult(switchAccounts(friend_account_id), "Switch account");
// Reset the act account
handleResult(ACTA_ResetAccount(static_cast<u8>(friend_account_id), true), "Reset account");
return rc;
}
void drawLumaInfo() {
DrawString(0.5f, defaultColor, std::format("Luma version is {}.{}.{}\nLuma config version is {}.{}\n\nLuma3DS config bits are:\n{:016b}\n{:016b}\n{:016b}\n{:016b}",
std::get<0>(lumaVersion), std::get<1>(lumaVersion), std::get<2>(lumaVersion), std::get<0>(lumaConfigVersion), std::get<1>(lumaConfigVersion), lumaOptions >> 48, (lumaOptions >> 32) & 0xFFFF, (lumaOptions >> 16) & 0xFFFF, lumaOptions & 0xFFFF), 0);
}
bool checkIfLumaOptionsEnabled(C3D_RenderTarget* top_screen, C3D_RenderTarget* bottom_screen, u32 kDown, u32 kHeld, touchPosition touch)
{
kDown |= kHeld; // make kDown have held keys aswell
C2D_SceneBegin(top_screen);
DrawVersionString();
C2D_SceneBegin(bottom_screen);
// if this is the first time the function has been run, get luma information
if (firstStateRun) {
firmwareVersion = GetSystemInfoField(GetSystemInfoCFW, CFWSystemInfoField::FirmwareVersion);
lumaVersion = UnpackLumaVersion(firmwareVersion);
configVersion = GetSystemInfoField(GetSystemInfoCFW, CFWSystemInfoField::ConfigVersion); // this
lumaConfigVersion = UnpackConfigVersion(configVersion);
lumaOptions = GetSystemInfoField(GetSystemInfoCFW, CFWSystemInfoField::ConfigBits); // this
externalFirmsAndModulesEnabled = GetLumaOptionByIndex(LumaConfigBitIndex::ExternalFirmsAndModules, lumaOptions); // this
gamePatchingEnabled = GetLumaOptionByIndex(LumaConfigBitIndex::GamePatching, lumaOptions); // and this might need multiple updates due to the fact that they fluctuate occasionally, if need be i can make a function that handles multiple versions though
}
// if the major version of luma3ds is under the targetLumaVersion (defined earlier in the file), send an error
if (std::get<0>(lumaVersion) < targetLumaVersion) {
DrawString(0.5f, defaultColor, std::format("Your Luma3DS version is out of date, it should be Luma3DS {} or newer for {} to function. Press A to exit.", targetLumaVersion, APP_TITLE), 0);
// if A is pressed, return true to exit
if (kDown & KEY_A) return true;
}
// else if either external firms and modules or game patching is not enabled, send another error and draw luma info if b is pressed
else if (!externalFirmsAndModulesEnabled || !gamePatchingEnabled) {
if (kDown & KEY_B) {
drawLumaInfo();
}
else {
DrawString(0.5f, defaultColor, std::format("Enable external FIRMs and modules: {}\nEnable game patching: {}\n\nFor {} to work, both of these Luma3DS options should be ENABLED. To open Luma3DS settings, hold SELECT while booting your system.\n\n\
If you are sure both options are enabled and the options shown don't match your Luma3DS settings, please contact @traceentertains on Discord with an image of the more information screen attached.\nPress A to exit, or hold B for more information.", externalFirmsAndModulesEnabled, gamePatchingEnabled, APP_TITLE), 0);
}
// if A is pressed, return true to exit, else if X and Y is pressed
if (kDown & KEY_A) return true;
else if (kDown & KEY_X && kDown & KEY_Y) state = 2; // bypass if I need some time to fix it and get it released
}
else {
if (kDown & KEY_A) drawLumaInfo();
else state = 2; // if A is held, show information, else go to the main menu
}
return false;
}
bool drawUI(C3D_RenderTarget* top_screen, C3D_RenderTarget* bottom_screen, u32 kDown, u32 kHeld, touchPosition touch)
{
// if start is pressed, exit to hbl/the home menu depending on if the app was launched from cia or 3dsx
if (kDown & KEY_START) return true;
C2D_SceneBegin(top_screen);
DrawVersionString();
C2D_DrawSprite(&top);
C2D_SceneBegin(bottom_screen);
if (buttonSelected == Account::Nintendo) {
if (currentEnv == Account::Nintendo) {
C2D_DrawSprite(&nintendo_loaded_selected);
C2D_DrawSprite(&pretendo_unloaded_deselected);
}
else {
C2D_DrawSprite(&nintendo_unloaded_selected);
C2D_DrawSprite(&pretendo_loaded_deselected);
}
}
else if (buttonSelected == Account::Pretendo) {
if (currentEnv == Account::Pretendo) {
C2D_DrawSprite(&nintendo_unloaded_deselected);
C2D_DrawSprite(&pretendo_loaded_selected);
}
else {
C2D_DrawSprite(&nintendo_loaded_deselected);
C2D_DrawSprite(&pretendo_unloaded_selected);
}
}
C2D_DrawSprite(&header);
if (kDown & KEY_TOUCH) {
if ((touch.px >= 165 && touch.px <= 165 + 104) && (touch.py >= 59 && touch.py <= 59 + 113)) {
buttonSelected = Account::Nintendo;
buttonWasPressed = true;
}
else if ((touch.px >= 49 && touch.px <= 49 + 104) && (touch.py >= 59 && touch.py <= 59 + 113)) {
buttonSelected = Account::Pretendo;
buttonWasPressed = true;
}
}
else if (kDown & KEY_LEFT || kDown & KEY_RIGHT) {
buttonSelected = buttonSelected == Account::Pretendo ? Account::Nintendo : Account::Pretendo;
}
environment = AccountToNascEnvironment(buttonSelected);
if (kDown & KEY_A) {
buttonWasPressed = true;
}
if (buttonWasPressed) {
if (switchAccounts(buttonSelected) && buttonSelected == Account::Pretendo) {
createAccount(buttonSelected);
}
needsReboot = true;
return true;
}
return false;
}
int main()
{
// Initialize the libs
@ -263,13 +64,12 @@ int main()
// Initialize the scene
sceneInit();
// get the local account id for the current enviroment and set the selected button to it
FRDA_GetLocalAccountId(&currentEnv);
environment = AccountToNascEnvironment(currentEnv);
// set button selected and current account to nasc environment
u32 serverTypes[3] = {};
FRDA_GetServerTypes(serverTypes);
if (currentEnv == Account::Undefined) currentEnv = Account::Nintendo;
buttonSelected = currentEnv;
mainStruct.buttonSelected = static_cast<NascEnvironment>(serverTypes[0]);
mainStruct.currentAccount = mainStruct.buttonSelected;
// Main loop
while (aptMainLoop()) {
@ -288,17 +88,17 @@ int main()
C2D_TargetClear(top_screen, C2D_Color32(21, 22, 28, 0xFF));
C2D_TargetClear(bottom_screen, C2D_Color32(21, 22, 28, 0xFF));
if (lastState != state) firstStateRun = true;
// TODO: change firstRunOfState into stateRunIndex, incrementing every time the state is run
if (mainStruct.lastState != mainStruct.state) mainStruct.firstRunOfState = true;
if (state == 0) {
exit = checkIfLumaOptionsEnabled(top_screen, bottom_screen, kDown, kHeld, touch);
}
else {
exit = drawUI(top_screen, bottom_screen, kDown, kHeld, touch);
if (mainStruct.state == 0) {
exit = LumaValidation::checkIfLumaOptionsEnabled(&mainStruct, top_screen, bottom_screen, kDown, kHeld, touch);
} else {
exit = MainUI::drawUI(&mainStruct, top_screen, bottom_screen, kDown, kHeld, touch);
}
lastState = state;
firstStateRun = false;
mainStruct.lastState = mainStruct.state;
mainStruct.firstRunOfState = false;
C3D_FrameEnd(0);
@ -309,7 +109,7 @@ int main()
C2D_Fini();
C3D_Fini();
gfxExit();
if(needsReboot){
if (mainStruct.needsReboot) {
NS_RebootSystem();
}
return 0;

View file

@ -0,0 +1,63 @@
#include "LumaValidation.hpp"
#include <format>
bool LumaValidation::checkIfLumaOptionsEnabled(MainStruct *mainStruct, C3D_RenderTarget* top_screen, C3D_RenderTarget* bottom_screen, u32 kDown, u32 kHeld, touchPosition touch)
{
kDown |= kHeld; // make kDown have held keys aswell
C2D_SceneBegin(top_screen);
DrawVersionString();
C2D_SceneBegin(bottom_screen);
// if running on citra, skip all luma checks
s64 isCitra = 0;
svcGetSystemInfo(&isCitra, 0x20000, 0);
if (isCitra) {
mainStruct->state = 1;
return false;
}
// if this is the first time the function has been run, get luma information
if (mainStruct->firstRunOfState) {
mainStruct->firmwareVersion = GetSystemInfoField(GetSystemInfoCFW, CFWSystemInfoField::FirmwareVersion);
mainStruct->lumaVersion = UnpackLumaVersion(mainStruct->firmwareVersion);
mainStruct->configVersion = GetSystemInfoField(GetSystemInfoCFW, CFWSystemInfoField::ConfigVersion); // this
mainStruct->lumaConfigVersion = UnpackConfigVersion(mainStruct->configVersion);
mainStruct->lumaOptions = GetSystemInfoField(GetSystemInfoCFW, CFWSystemInfoField::ConfigBits); // this
mainStruct->externalFirmsAndModulesEnabled = GetLumaOptionByIndex(LumaConfigBitIndex::ExternalFirmsAndModules, mainStruct->lumaOptions); // this
mainStruct->gamePatchingEnabled = GetLumaOptionByIndex(LumaConfigBitIndex::GamePatching, mainStruct->lumaOptions); // and this might need multiple updates due to the fact that they fluctuate occasionally, if need be i can make a function that handles multiple versions though
}
// if the major version of luma3ds is under the targetLumaVersion (defined earlier in the file), send an error
if (std::get<0>(mainStruct->lumaVersion) < targetLumaVersion) {
DrawString(0.5f, defaultColor, std::format("Your Luma3DS version is out of date, it should be Luma3DS {} or newer for {} to function. Press A to exit.", targetLumaVersion, APP_TITLE), 0);
// if A is pressed, return true to exit
if (kDown & KEY_A) return true;
}
// else if either external firms and modules or game patching is not enabled, send another error and draw luma info if b is pressed
else if (!mainStruct->externalFirmsAndModulesEnabled || !mainStruct->gamePatchingEnabled) {
if (kDown & KEY_B) {
drawLumaInfo(mainStruct);
}
else {
DrawString(0.5f, defaultColor, std::format("Enable external FIRMs and modules: {}\nEnable game patching: {}\n\nFor {} to work, both of these Luma3DS options should be ENABLED. To open Luma3DS settings, hold SELECT while booting your system.\n\n\
If you are sure both options are enabled and the options shown don't match your Luma3DS settings, please contact @traceentertains on Discord with an image of the more information screen attached.\nPress A to exit, or hold B for more information.", mainStruct->externalFirmsAndModulesEnabled, mainStruct->gamePatchingEnabled, APP_TITLE), 0);
}
// if A is pressed, return true to exit, else if X and Y is pressed
if (kDown & KEY_A) return true;
else if (kDown & KEY_X && kDown & KEY_Y) mainStruct->state = 1; // bypass if I need some time to fix it and get it released
}
else {
if (kDown & KEY_A) drawLumaInfo(mainStruct);
else mainStruct->state = 1; // if A is held, show information, else go to the main menu
}
return false;
}

View file

@ -0,0 +1,8 @@
#pragma once
#include "../common.hpp"
namespace LumaValidation
{
bool checkIfLumaOptionsEnabled(MainStruct *mainStruct, C3D_RenderTarget* top_screen, C3D_RenderTarget* bottom_screen, u32 kDown, u32 kHeld, touchPosition touch);
}

View file

@ -0,0 +1,105 @@
#include "MainUI.hpp"
#include "../sysmodules/frda.hpp"
#include "../sysmodules/acta.hpp"
Result MainUI::switchAccounts(u8 friend_account_id) {
Result rc = 0;
handleResult(FRDA_SetLocalAccountId(friend_account_id), "Switch account");
if (rc) {
return rc;
}
u32 act_account_index = 0;
handleResult(ACTA_GetAccountIndexOfFriendAccountId(&act_account_index, friend_account_id), "Get persistent id for creation");
if (act_account_index == 0) {
handleResult(ACTA_CreateLocalAccount(), "Create act account");
handleResult(ACTA_GetAccountIndexOfFriendAccountId(&act_account_index, friend_account_id),
"Get persistent id after creation");
}
handleResult(ACTA_SetDefaultAccount(act_account_index), "Set default account");
return rc;
}
Result MainUI::createAccount(u8 friend_account_id, NascEnvironment environmentId) {
Result rc = 0;
// (Re)Create the friend account
handleResult(FRDA_CreateLocalAccount(friend_account_id, environmentId, 0, 1), "Create account");
// Switch to the friend/act accounts
handleResult(switchAccounts(friend_account_id), "Switch account");
// Reset the act account
handleResult(ACTA_ResetAccount(friend_account_id, true), "Reset account");
return rc;
}
bool MainUI::drawUI(MainStruct *mainStruct, C3D_RenderTarget* top_screen, C3D_RenderTarget* bottom_screen, u32 kDown, u32 kHeld, touchPosition touch)
{
// if start is pressed, exit to hbl/the home menu depending on if the app was launched from cia or 3dsx
if (kDown & KEY_START) return true;
C2D_SceneBegin(top_screen);
DrawVersionString();
C2D_DrawSprite(&mainStruct->top);
C2D_SceneBegin(bottom_screen);
if (mainStruct->buttonSelected == NascEnvironment::NASC_ENV_Prod) {
if (mainStruct->currentAccount == NascEnvironment::NASC_ENV_Prod) {
C2D_DrawSprite(&mainStruct->nintendo_loaded_selected);
C2D_DrawSprite(&mainStruct->pretendo_unloaded_deselected);
}
else {
C2D_DrawSprite(&mainStruct->nintendo_unloaded_selected);
C2D_DrawSprite(&mainStruct->pretendo_loaded_deselected);
}
}
else if (mainStruct->buttonSelected == NascEnvironment::NASC_ENV_Test) {
if (mainStruct->currentAccount == NascEnvironment::NASC_ENV_Test) {
C2D_DrawSprite(&mainStruct->nintendo_unloaded_deselected);
C2D_DrawSprite(&mainStruct->pretendo_loaded_selected);
}
else {
C2D_DrawSprite(&mainStruct->nintendo_loaded_deselected);
C2D_DrawSprite(&mainStruct->pretendo_unloaded_selected);
}
}
C2D_DrawSprite(&mainStruct->header);
// handle touch input
if (kDown & KEY_TOUCH) {
if ((touch.px >= 165 && touch.px <= 165 + 104) && (touch.py >= 59 && touch.py <= 59 + 113)) {
mainStruct->buttonSelected = NascEnvironment::NASC_ENV_Prod;
mainStruct->buttonWasPressed = true;
}
else if ((touch.px >= 49 && touch.px <= 49 + 104) && (touch.py >= 59 && touch.py <= 59 + 113)) {
mainStruct->buttonSelected = NascEnvironment::NASC_ENV_Test;
mainStruct->buttonWasPressed = true;
}
}
else if (kDown & KEY_LEFT || kDown & KEY_RIGHT) {
mainStruct->buttonSelected = mainStruct->buttonSelected == NascEnvironment::NASC_ENV_Test ? NascEnvironment::NASC_ENV_Prod : NascEnvironment::NASC_ENV_Test;
}
if (kDown & KEY_A) {
mainStruct->buttonWasPressed = true;
}
if (mainStruct->buttonWasPressed) {
u8 accountId = (u8)mainStruct->buttonSelected + 1; // by default set accountId to nasc environment + 1
if (switchAccounts(accountId) && accountId == 2) {
createAccount(accountId, NascEnvironment::NASC_ENV_Test);
}
mainStruct->needsReboot = true;
return true;
}
return false;
}

View file

@ -0,0 +1,10 @@
#pragma once
#include "../common.hpp"
namespace MainUI
{
Result switchAccounts(u8 friend_account_id);
Result createAccount(u8 friend_account_id, NascEnvironment environmentId);
bool drawUI(MainStruct *mainStruct, C3D_RenderTarget* top_screen, C3D_RenderTarget* bottom_screen, u32 kDown, u32 kHeld, touchPosition touch);
}

View file

@ -86,8 +86,8 @@ Result ACTA_GetAccountInfo(void *out, u32 out_size, u32 block_id, u8 account_ind
return (Result)cmdbuf[1];
}
Result ACTA_GetFriendLocalAccountId(Account *out, u32 index) {
return ACTA_GetAccountInfo(reinterpret_cast<u8*>(out), sizeof(u32), 0x2b, index);
Result ACTA_GetFriendLocalAccountId(u8 *out, u32 index) {
return ACTA_GetAccountInfo(out, sizeof(u32), 0x2b, index);
}
Result ACTA_GetPersistentId(u32 *out, u32 index) {
@ -119,7 +119,7 @@ Result ACTA_GetAccountCount(u32 *out) {
return ret; \
}
Result ACTA_GetAccountIndexOfFriendAccountId(u32 *index, Account friend_account_id) {
Result ACTA_GetAccountIndexOfFriendAccountId(u32 *index, u8 friend_account_id) {
Result ret = 0;
u32 account_count = 0;
@ -127,16 +127,15 @@ Result ACTA_GetAccountIndexOfFriendAccountId(u32 *index, Account friend_account_
return ret;
}
for (u32 i = 0; i < account_count; i++) {
u32 account_index = i + 1;
Account found_friend_account_id = Account::Undefined;
for (u32 account_index = 1; account_index < account_count; account_index++) {
u8 found_friend_account_id = 0;
if (R_FAILED(ret = ACTA_GetFriendLocalAccountId(&found_friend_account_id, account_index))) {
return ret;
}
if (friend_account_id == found_friend_account_id) {
*index = static_cast<u32>(account_index);
*index = account_index;
return 0;
}
}

View file

@ -1,6 +1,6 @@
#pragma once
#include "common.hpp"
#include "../common.hpp"
#define ACT_CURRENT_ACCOUNT 0xfe
@ -9,8 +9,8 @@ void actAExit();
Result ACTA_CreateLocalAccount();
Result ACTA_GetAccountInfo(void *out, u32 out_size, u32 block_id, u8 account_index);
Result ACTA_GetAccountCount(u32 *out);
Result ACTA_GetFriendLocalAccountId(Account *out, u32 index);
Result ACTA_GetFriendLocalAccountId(u8 *out, u32 index);
Result ACTA_GetPersistentId(u32 *out, u32 index);
Result ACTA_GetAccountIndexOfFriendAccountId(u32 *index, Account friend_account_id);
Result ACTA_GetAccountIndexOfFriendAccountId(u32 *index, u8 friend_account_id);
Result ACTA_ResetAccount(u8 account_index, bool format_nnid);
Result ACTA_SetDefaultAccount(u8 account_index);

View file

@ -35,12 +35,12 @@ Handle *frdAGetSessionHandle(void) {
return &frdHandle;
}
Result FRDA_CreateLocalAccount(Account localAccountId, NascEnvironment nascEnvironment, u8 serverTypeField1, u8 serverTypeField2) {
Result FRDA_CreateLocalAccount(u8 localAccountId, NascEnvironment nascEnvironment, u8 serverTypeField1, u8 serverTypeField2) {
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x401, 4, 0);
cmdbuf[1] = static_cast<u32>(localAccountId);
cmdbuf[1] = localAccountId;
cmdbuf[2] = static_cast<u32>(nascEnvironment);
cmdbuf[3] = serverTypeField1;
cmdbuf[4] = serverTypeField2;
@ -51,24 +51,25 @@ Result FRDA_CreateLocalAccount(Account localAccountId, NascEnvironment nascEnvir
return (Result)cmdbuf[1];
}
Result FRDA_GetLocalAccountId(Account *localAccountId) {
Result FRDA_GetLocalAccountId(u8 *localAccountId) {
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0xB, 2, 0);
if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) return ret;
if (R_FAILED(ret = svcSendSyncRequest(frdHandle)))
return ret;
*localAccountId = static_cast<Account>(cmdbuf[2]);
*localAccountId = cmdbuf[2];
return (Result)cmdbuf[1];
}
Result FRDA_SetLocalAccountId(Account localAccountId) {
Result FRDA_SetLocalAccountId(u8 localAccountId) {
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x403, 1, 0);
cmdbuf[1] = static_cast<u32>(localAccountId);
cmdbuf[1] = localAccountId;
if (R_FAILED(ret = svcSendSyncRequest(frdHandle)))
return ret;
@ -89,3 +90,19 @@ Result FRDA_SetClientSdkVersion(u32 sdkVer) {
return (Result)cmdbuf[1];
}
Result FRDA_GetServerTypes(u32 *out) {
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x30, 4, 0);
if (R_FAILED(ret = svcSendSyncRequest(frdHandle)))
return ret;
out[0] = cmdbuf[2];
out[1] = cmdbuf[3];
out[2] = cmdbuf[4];
return (Result)cmdbuf[1];
}

View file

@ -0,0 +1,12 @@
#pragma once
#include "../common.hpp"
Result frdAInit();
void frdAExit();
Handle *frdAGetSessionHandle();
Result FRDA_CreateLocalAccount(u8 localAccountId, NascEnvironment nascEnvironment, u8 serverTypeField1, u8 serverTypeField2);
Result FRDA_GetLocalAccountId(u8 *localAccountId);
Result FRDA_SetLocalAccountId(u8 localAccountId);
Result FRDA_SetClientSdkVersion(u32 sdkVer);
Result FRDA_GetServerTypes(u32 *out);