mirror of
https://github.com/PretendoNetwork/nimbus.git
synced 2024-05-16 20:00:46 -04:00
Merge pull request #30 from TraceEntertains/main
This commit is contained in:
commit
6376b0b96b
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
|
@ -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);
|
|
@ -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(¤tEnv);
|
||||
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;
|
||||
|
|
63
app/source/states/LumaValidation.cpp
Normal file
63
app/source/states/LumaValidation.cpp
Normal 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;
|
||||
}
|
8
app/source/states/LumaValidation.hpp
Normal file
8
app/source/states/LumaValidation.hpp
Normal 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);
|
||||
}
|
105
app/source/states/MainUI.cpp
Normal file
105
app/source/states/MainUI.cpp
Normal 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;
|
||||
}
|
10
app/source/states/MainUI.hpp
Normal file
10
app/source/states/MainUI.hpp
Normal 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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
|
@ -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];
|
||||
}
|
12
app/source/sysmodules/frda.hpp
Normal file
12
app/source/sysmodules/frda.hpp
Normal 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);
|
Loading…
Reference in a new issue