Net installing with UI

This commit is contained in:
Huntereb 2019-10-18 15:01:51 -04:00
parent e3ed8a5220
commit 5d5c4adeb4
16 changed files with 329 additions and 259 deletions

View file

@ -1,3 +1,8 @@
namespace netInstStuff {
void InitializeServerSocket();
void OnUnwound();
bool OnDestinationSelected(int ourStorage);
bool OnNSPSelected(std::string ourUrl, int ourStorage);
std::vector<std::string> OnSelected();
bool installNspLan ();
}

View file

@ -1,6 +1,7 @@
#pragma once
#include <pu/Plutonium>
#include "ui/mainPage.hpp"
#include "ui/netInstPage.hpp"
namespace inst::ui {
class MainApplication : public pu::ui::Application {
@ -9,5 +10,6 @@ namespace inst::ui {
PU_SMART_CTOR(MainApplication)
void OnLoad() override;
MainPage::Ref mainPage;
netInstPage::Ref netinstPage;
};
}

16
include/ui/netInstPage.hpp Executable file
View file

@ -0,0 +1,16 @@
#pragma once
#include <pu/Plutonium>
using namespace pu::ui::elm;
namespace inst::ui {
class netInstPage : public pu::ui::Layout
{
public:
netInstPage();
PU_SMART_CTOR(netInstPage)
void onInput(u64 Down, u64 Up, u64 Held, pu::ui::Touch Pos);
TextBlock::Ref pageInfoText;
private:
TextBlock::Ref topText;
};
}

View file

@ -2,4 +2,9 @@
namespace appVariables {
static const std::string appDir = "sdmc:/switch/AwooInstaller";
}
namespace util {
void initApp ();
void deinitApp ();
}

View file

@ -81,7 +81,7 @@ namespace tin::install::nsp
size_t startSizeBuffered = 0;
double speed = 0.0;
consoleUpdate(NULL);
//consoleUpdate(NULL);
while (!bufferedPlaceholderWriter.IsBufferDataComplete())
{
@ -103,7 +103,7 @@ namespace tin::install::nsp
int downloadProgress = (int)(((double)bufferedPlaceholderWriter.GetSizeBuffered() / (double)bufferedPlaceholderWriter.GetTotalDataSize()) * 100.0);
printf("> Download Progress: %lu/%lu MB (%i%s) (%.2f MB/s)\r", downloadSizeMB, totalSizeMB, downloadProgress, "%", speed);
consoleUpdate(NULL);
//consoleUpdate(NULL);
}
u64 totalSizeMB = bufferedPlaceholderWriter.GetTotalDataSize() / 1000000;
@ -114,12 +114,12 @@ namespace tin::install::nsp
int installProgress = (int)(((double)bufferedPlaceholderWriter.GetSizeWrittenToPlaceholder() / (double)bufferedPlaceholderWriter.GetTotalDataSize()) * 100.0);
printf("> Install Progress: %lu/%lu MB (%i%s)\r", installSizeMB, totalSizeMB, installProgress, "%");
consoleUpdate(NULL);
//consoleUpdate(NULL);
}
thrd_join(curlThread, NULL);
thrd_join(writeThread, NULL);
consoleUpdate(NULL);
//consoleUpdate(NULL);
}
void HTTPNSP::BufferData(void* buf, off_t offset, size_t size)

View file

@ -43,7 +43,7 @@ namespace tin::install
}
serviceClose(&contentMetaDatabase.s);
consoleUpdate(NULL);
//consoleUpdate(NULL);
}
void Install::InstallApplicationRecord()
@ -98,7 +98,7 @@ namespace tin::install
printf("Pushing application record...\n");
ASSERT_OK(nsPushApplicationRecord(baseTitleId, 0x3, storageRecords.data(), storageRecords.size() * sizeof(ContentStorageRecord)), "Failed to push application record");
consoleUpdate(NULL);
//consoleUpdate(NULL);
}
// Validate and obtain all data needed for install
@ -141,17 +141,17 @@ namespace tin::install
printf("WARNING: Ticket installation failed! This may not be an issue, depending on your use case.\nProceed with caution!\n");
}
consoleUpdate(NULL);
//consoleUpdate(NULL);
}
void Install::Begin()
{
printf("Installing NCAs...\n");
consoleUpdate(NULL);
//consoleUpdate(NULL);
for (auto& record : m_contentMeta.GetContentInfos())
{
printf("Installing from %s\n", tin::util::GetNcaIdString(record.content_id).c_str());
consoleUpdate(NULL);
//consoleUpdate(NULL);
this->InstallNCA(record.content_id);
}

View file

@ -52,7 +52,7 @@ namespace tin::install::nsp
// Finally, let's actually import the ticket
ASSERT_OK(esImportTicket(tikBuf.get(), tikSize, certBuf.get(), certSize), "Failed to import ticket");
consoleUpdate(NULL);
//consoleUpdate(NULL);
}
void NSPInstallTask::InstallNCA(const NcmNcaId &ncaId)
@ -94,7 +94,7 @@ namespace tin::install::nsp
float progress;
consoleUpdate(NULL);
//consoleUpdate(NULL);
while (fileOff < ncaSize)
{
@ -109,7 +109,7 @@ namespace tin::install::nsp
ncaFile.Read(fileOff, readBuffer.get(), readSize);
contentStorage.WritePlaceholder(ncaId, fileOff, readBuffer.get(), readSize);
fileOff += readSize;
consoleUpdate(NULL);
//consoleUpdate(NULL);
}
// Clean up the line for whatever comes next
@ -131,6 +131,6 @@ namespace tin::install::nsp
}
catch (...) {}
consoleUpdate(NULL);
//consoleUpdate(NULL);
}
}

View file

@ -39,7 +39,7 @@ namespace tin::install::nsp
cnmtContentInfo.content_id = cnmtContentId;
*(u64*)&cnmtContentInfo.size = cnmtNcaSize & 0xFFFFFFFFFFFF;
cnmtContentInfo.content_type = NcmContentType_Meta;
consoleUpdate(NULL);
//consoleUpdate(NULL);
return { tin::util::GetContentMetaFromNCA(cnmtNCAFullPath), cnmtContentInfo };
}
@ -84,7 +84,7 @@ namespace tin::install::nsp
}
catch (...) {}
consoleUpdate(NULL);
//consoleUpdate(NULL);
}
void RemoteNSPInstall::InstallTicketCert()
@ -119,6 +119,6 @@ namespace tin::install::nsp
// Finally, let's actually import the ticket
ASSERT_OK(esImportTicket(tikBuf.get(), tikSize, certBuf.get(), certSize), "Failed to import ticket");
consoleUpdate(NULL);
//consoleUpdate(NULL);
}
}

View file

@ -22,18 +22,16 @@ namespace tin::install::nsp
m_headerBytes.resize(sizeof(PFS0BaseHeader), 0);
this->BufferData(m_headerBytes.data(), 0x0, sizeof(PFS0BaseHeader));
printf("Base header: \n");
//printBytes(nxlinkout, m_headerBytes.data(), sizeof(PFS0BaseHeader), true);
printf("%.*s",sizeof(PFS0BaseHeader),m_headerBytes.data());
printf("Base header: ");
printf("%.*s\n",(int)sizeof(PFS0BaseHeader),m_headerBytes.data());
// Retrieve the full header
size_t remainingHeaderSize = this->GetBaseHeader()->numFiles * sizeof(PFS0FileEntry) + this->GetBaseHeader()->stringTableSize;
m_headerBytes.resize(sizeof(PFS0BaseHeader) + remainingHeaderSize, 0);
this->BufferData(m_headerBytes.data() + sizeof(PFS0BaseHeader), sizeof(PFS0BaseHeader), remainingHeaderSize);
printf("Full header: \n");
//printBytes(nxlinkout, m_headerBytes.data(), m_headerBytes.size(), true);
printf("%.*s",m_headerBytes.size(),m_headerBytes.data());
printf("Full header: ");
printf("%.*s\n",(int)m_headerBytes.size(),m_headerBytes.data());
}
const PFS0FileEntry* RemoteNSP::GetFileEntry(unsigned int index)

View file

@ -123,7 +123,7 @@ namespace tin::install::nsp
int downloadProgress = (int)(((double)bufferedPlaceholderWriter.GetSizeBuffered() / (double)bufferedPlaceholderWriter.GetTotalDataSize()) * 100.0);
printf("> Download Progress: %lu/%lu MB (%i%s) (%.2f MB/s)\r", downloadSizeMB, totalSizeMB, downloadProgress, "%", speed);
consoleUpdate(NULL);
//consoleUpdate(NULL);
}
u64 totalSizeMB = bufferedPlaceholderWriter.GetTotalDataSize() / 1000000;
@ -134,7 +134,7 @@ namespace tin::install::nsp
int installProgress = (int)(((double)bufferedPlaceholderWriter.GetSizeWrittenToPlaceholder() / (double)bufferedPlaceholderWriter.GetTotalDataSize()) * 100.0);
printf("> Install Progress: %lu/%lu MB (%i%s)\r", installSizeMB, totalSizeMB, installProgress, "%");
consoleUpdate(NULL);
//consoleUpdate(NULL);
}
thrd_join(usbThread, NULL);

View file

@ -1,19 +1,13 @@
#include "switch.h"
#include "ui/MainApplication.hpp"
#include "main.hpp"
#include "util.hpp"
#include <filesystem>
using namespace pu::ui::render;
int main(int argc, char* argv[])
{
socketInitializeDefault();
#ifdef __DEBUG__
nxlinkStdio();
#endif
printf("Application started!\n");
util::initApp();
try {
if (!std::filesystem::exists("sdmc:/switch")) std::filesystem::create_directory("sdmc:/switch");
if (!std::filesystem::exists(appVariables::appDir)) std::filesystem::create_directory(appVariables::appDir);
auto renderer = Renderer::New(SDL_INIT_TIMER | SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER,
RendererInitOptions::RendererNoSound, RendererHardwareFlags);
auto main = inst::ui::MainApplication::New(renderer);
@ -30,8 +24,6 @@ int main(int argc, char* argv[])
kDown = hidKeysDown(CONTROLLER_P1_AUTO);
}
}
printf("Application closing!\n");
socketExit();
util::deinitApp();
return 0;
}

View file

@ -8,12 +8,10 @@
#include <curl/curl.h>
#include <switch.h>
#include "nx/ipc/tin_ipc.h"
#include "util/network_util.hpp"
#include "install/install_nsp_remote.hpp"
#include "install/http_nsp.hpp"
#include "install/install.hpp"
#include "debug.h"
#include "error.hpp"
const unsigned int MAX_URL_SIZE = 1024;
@ -25,226 +23,197 @@ static int m_clientSocket = 0;
std::vector<std::string> m_urls;
FsStorageId m_destStorageId = FsStorageId_SdCard;
void InitializeServerSocket() try
{
// Create a socket
m_serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (m_serverSocket < -1)
{
THROW_FORMAT("Failed to create a server socket. Error code: %u\n", errno);
}
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(REMOTE_INSTALL_PORT);
server.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(m_serverSocket, (struct sockaddr*) &server, sizeof(server)) < 0)
{
THROW_FORMAT("Failed to bind server socket. Error code: %u\n", errno);
}
// Set as non-blocking
fcntl(m_serverSocket, F_SETFL, fcntl(m_serverSocket, F_GETFL, 0) | O_NONBLOCK);
if (listen(m_serverSocket, 5) < 0)
{
THROW_FORMAT("Failed to listen on server socket. Error code: %u\n", errno);
}
}
catch (std::exception& e)
{
printf("Failed to initialize server socket!\n");
fprintf(stdout, "%s", e.what());
if (m_serverSocket != 0)
{
close(m_serverSocket);
m_serverSocket = 0;
}
}
void OnUnwound()
{
printf("unwinding view\n");
if (m_clientSocket != 0)
{
close(m_clientSocket);
m_clientSocket = 0;
}
curl_global_cleanup();
#ifndef NXLINK_DEBUG
socketExit();
#endif
}
void OnDestinationSelected()
{
printf("Setting storage device to sd card automatically\n");
m_destStorageId = FsStorageId_SdCard;
//if (destStr == translate(Translate::NAND))
//{
// m_destStorageId = FsStorageId_NandUser;
//}
for (auto& url : m_urls)
{
tin::install::nsp::HTTPNSP httpNSP(url);
printf("%s %s\n", "NSP_INSTALL_FROM", url.c_str());
// second var is ignoring required version
tin::install::nsp::RemoteNSPInstall install(m_destStorageId, true, &httpNSP);
printf("%s\n", "NSP_INSTALL_PREPARING");
install.Prepare();
printf("Pre Install Records: \n");
install.DebugPrintInstallData();
install.Begin();
printf("Post Install Records: \n");
install.DebugPrintInstallData();
printf("\n");
}
printf("%s\n", "NSP_INSTALL_NETWORK_SENDING_ACK");
// Send 1 byte ack to close the server
u8 ack = 0;
tin::network::WaitSendNetworkData(m_clientSocket, &ack, sizeof(u8));
printf("\n %s", "Done! Press B to stop");
}
void OnNSPSelected(std::string ourUrl)
{
printf("Selecting first nsp automatically\n");
m_urls.push_back(ourUrl);
//select storage type
OnDestinationSelected();
}
void OnSelected()
{
try
{
#ifndef NXLINK_DEBUG
ASSERT_OK(socketInitializeDefault(), "Failed to initialize socket");
#endif
ASSERT_OK(curl_global_init(CURL_GLOBAL_ALL), "Curl failed to initialized");
// Initialize the server socket if it hasn't already been
if (m_serverSocket == 0)
{
InitializeServerSocket();
if (m_serverSocket <= 0)
{
THROW_FORMAT("Server socket failed to initialize.\n");
}
}
struct in_addr addr = {(in_addr_t) gethostid()};
printf("%s %s\n", "Switch IP is ", inet_ntoa(addr));
printf("%s\n", "Waiting for network");
printf("%s\n", "B to cancel");
std::vector<std::string> urls;
bool canceled = false;
// Do this now because otherwise we won't get an opportunity whilst waiting
// in the loop
//consoleUpdate(NULL);
while (true)
{
// Break on input pressed
hidScanInput();
u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO);
//consoleUpdate(NULL);
if (kDown & KEY_B)
{
canceled = true;
break;
}
struct sockaddr_in client;
socklen_t clientLen = sizeof(client);
m_clientSocket = accept(m_serverSocket, (struct sockaddr*)&client, &clientLen);
if (m_clientSocket >= 0)
{
printf("%s\n", "NSP_INSTALL_NETWORK_ACCEPT");
u32 size = 0;
tin::network::WaitReceiveNetworkData(m_clientSocket, &size, sizeof(u32));
size = ntohl(size);
printf("Received url buf size: 0x%x\n", size);
if (size > MAX_URL_SIZE * MAX_URLS)
{
THROW_FORMAT("URL size %x is too large!\n", size);
}
// Make sure the last string is null terminated
auto urlBuf = std::make_unique<char[]>(size+1);
memset(urlBuf.get(), 0, size+1);
tin::network::WaitReceiveNetworkData(m_clientSocket, urlBuf.get(), size);
// Split the string up into individual URLs
std::stringstream urlStream(urlBuf.get());
std::string segment;
std::string nspExt = ".nsp";
while (std::getline(urlStream, segment, '\n'))
{
if (segment.compare(segment.size() - nspExt.size(), nspExt.size(), nspExt) == 0)
urls.push_back(segment);
}
break;
}
else if (errno != EAGAIN)
{
THROW_FORMAT("Failed to open client socket with code %u\n", errno);
}
}
if (!canceled)
{
OnNSPSelected(urls[0]);
}
}
catch (std::runtime_error& e)
{
printf("Failed to perform remote install!\n");
printf("%s", e.what());
fprintf(stdout, "%s", e.what());
}
}
namespace netInstStuff{
bool installNspLan () {
plInitialize();
setInitialize();
ncmInitialize();
nsInitialize();
nsextInitialize();
esInitialize();
OnSelected();
plExit();
setExit();
ncmExit();
nsExit();
nsextExit();
esExit();
printf("Exited install...\n");
void InitializeServerSocket() try
{
// Create a socket
m_serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (m_serverSocket < -1)
{
THROW_FORMAT("Failed to create a server socket. Error code: %u\n", errno);
}
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(REMOTE_INSTALL_PORT);
server.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(m_serverSocket, (struct sockaddr*) &server, sizeof(server)) < 0)
{
THROW_FORMAT("Failed to bind server socket. Error code: %u\n", errno);
}
// Set as non-blocking
fcntl(m_serverSocket, F_SETFL, fcntl(m_serverSocket, F_GETFL, 0) | O_NONBLOCK);
if (listen(m_serverSocket, 5) < 0)
{
THROW_FORMAT("Failed to listen on server socket. Error code: %u\n", errno);
}
}
catch (std::exception& e)
{
printf("Failed to initialize server socket!\n");
fprintf(stdout, "%s", e.what());
if (m_serverSocket != 0)
{
close(m_serverSocket);
m_serverSocket = 0;
}
}
void OnUnwound()
{
printf("unwinding view\n");
if (m_clientSocket != 0)
{
close(m_clientSocket);
m_clientSocket = 0;
}
curl_global_cleanup();
}
bool OnDestinationSelected(int ourStorage)
{
if (ourStorage == 0) m_destStorageId = FsStorageId_NandUser;
else m_destStorageId = FsStorageId_SdCard;
for (auto& url : m_urls)
{
tin::install::nsp::HTTPNSP httpNSP(url);
printf("%s %s\n", "NSP_INSTALL_FROM", url.c_str());
// second var is ignoring required version
tin::install::nsp::RemoteNSPInstall install(m_destStorageId, true, &httpNSP);
printf("%s\n", "NSP_INSTALL_PREPARING");
install.Prepare();
printf("Pre Install Records: \n");
install.DebugPrintInstallData();
install.Begin();
printf("Post Install Records: \n");
install.DebugPrintInstallData();
printf("\n");
}
printf("%s\n", "NSP_INSTALL_NETWORK_SENDING_ACK");
// Send 1 byte ack to close the server
u8 ack = 0;
tin::network::WaitSendNetworkData(m_clientSocket, &ack, sizeof(u8));
printf("Clearing buffer\n");
m_urls.clear();
return true;
}
bool OnNSPSelected(std::string ourUrl, int ourStorage)
{
m_urls.push_back(ourUrl);
return OnDestinationSelected(ourStorage);
}
std::vector<std::string> OnSelected()
{
OnUnwound();
try
{
ASSERT_OK(curl_global_init(CURL_GLOBAL_ALL), "Curl failed to initialized");
// Initialize the server socket if it hasn't already been
if (m_serverSocket == 0)
{
InitializeServerSocket();
if (m_serverSocket <= 0)
{
THROW_FORMAT("Server socket failed to initialize.\n");
}
}
struct in_addr addr = {(in_addr_t) gethostid()};
printf("%s %s\n", "Switch IP is ", inet_ntoa(addr));
printf("%s\n", "Waiting for network");
printf("%s\n", "B to cancel");
std::vector<std::string> urls;
bool canceled = false;
// Do this now because otherwise we won't get an opportunity whilst waiting
// in the loop
//consoleUpdate(NULL);
while (true)
{
// Break on input pressed
hidScanInput();
u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO);
//consoleUpdate(NULL);
if (kDown & KEY_B)
{
canceled = true;
break;
}
struct sockaddr_in client;
socklen_t clientLen = sizeof(client);
m_clientSocket = accept(m_serverSocket, (struct sockaddr*)&client, &clientLen);
if (m_clientSocket >= 0)
{
printf("%s\n", "NSP_INSTALL_NETWORK_ACCEPT");
u32 size = 0;
tin::network::WaitReceiveNetworkData(m_clientSocket, &size, sizeof(u32));
size = ntohl(size);
printf("Received url buf size: 0x%x\n", size);
if (size > MAX_URL_SIZE * MAX_URLS)
{
THROW_FORMAT("URL size %x is too large!\n", size);
}
// Make sure the last string is null terminated
auto urlBuf = std::make_unique<char[]>(size+1);
memset(urlBuf.get(), 0, size+1);
tin::network::WaitReceiveNetworkData(m_clientSocket, urlBuf.get(), size);
// Split the string up into individual URLs
std::stringstream urlStream(urlBuf.get());
std::string segment;
std::string nspExt = ".nsp";
while (std::getline(urlStream, segment, '\n'))
{
if (segment.compare(segment.size() - nspExt.size(), nspExt.size(), nspExt) == 0)
urls.push_back(segment);
}
break;
}
else if (errno != EAGAIN)
{
THROW_FORMAT("Failed to open client socket with code %u\n", errno);
}
}
return urls;
}
catch (std::runtime_error& e)
{
printf("Failed to perform remote install!\n");
printf("%s", e.what());
fprintf(stdout, "%s", e.what());
}
}
}

View file

@ -7,7 +7,9 @@ namespace inst::ui {
mainApp = this;
this->mainPage = MainPage::New();
this->netinstPage = netInstPage::New();
this->mainPage->SetOnInput(std::bind(&MainPage::onInput, this->mainPage, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
this->netinstPage->SetOnInput(std::bind(&netInstPage::onInput, this->netinstPage, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
this->LoadLayout(this->mainPage);
}
}

View file

@ -2,7 +2,7 @@
#include "MainApplication.hpp"
#include "ui/mainPage.hpp"
#include "curl.hpp"
#include "main.hpp"
#include "util.hpp"
#include "unzip.hpp"
#include "netInstall.hpp"
@ -10,6 +10,7 @@
namespace inst::ui {
extern MainApplication *mainApp;
extern MainApplication *netinstPage;
MainPage::MainPage() : Layout::Layout() {
this->SetBackgroundColor(COLOR("#670000FF"));
@ -38,12 +39,12 @@ namespace inst::ui {
}
void MainPage::installMenuItem_Click() {
if (!netInstStuff::installNspLan()) mainApp->CreateShowDialog("Failure!", "", {"OK"}, true);
mainApp->CreateShowDialog("Not implemented yet", "", {"OK"}, true);
return;
}
void MainPage::netInstallMenuItem_Click() {
mainApp->CreateShowDialog("Not implemented yet", "", {"OK"}, true);
mainApp->LoadLayout(mainApp->netinstPage);
return;
}

49
source/ui/netInstPage.cpp Executable file
View file

@ -0,0 +1,49 @@
#include <filesystem>
#include "ui/MainApplication.hpp"
#include "ui/mainPage.hpp"
#include "ui/netInstPage.hpp"
#include "util.hpp"
#include "netInstall.hpp"
#define COLOR(hex) pu::ui::Color::FromHex(hex)
namespace inst::ui {
extern MainApplication *mainApp;
extern MainApplication *netinstPage;
std::vector<std::string> ourUrls;
netInstPage::netInstPage() : Layout::Layout() {
this->SetBackgroundColor(COLOR("#670000FF"));
this->topText = TextBlock::New(10, 2, "Awoo Installer", 35);
this->topText->SetColor(COLOR("#FFFFFFFF"));
this->pageInfoText = TextBlock::New(10, 45, "Press A to start net install", 35);
this->pageInfoText->SetColor(COLOR("#FFFFFFFF"));
this->Add(this->topText);
this->Add(this->pageInfoText);
}
void netInstPage::onInput(u64 Down, u64 Up, u64 Held, pu::ui::Touch Pos) {
if (Down & KEY_B) {
mainApp->LoadLayout(mainApp->mainPage);
}
if (Down & KEY_A) {
this->pageInfoText->SetText("Waiting for connect... Press B to cancel.");
mainApp->CallForRender();
//gets our list of urls of nsps
ourUrls = netInstStuff::OnSelected();
if (ourUrls.size() == 0) {
this->pageInfoText->SetText("Canceled... Press A to try again.");
return;
}
//make it so we fill a page with nsps here?
std::string ourSelectedNsp = "installing: " + ourUrls[0];
this->pageInfoText->SetText(ourSelectedNsp);
mainApp->CallForRender();
//automatically selecting first nsp and SD as storage
printf("Selecting SD as storage and first NSP automatically\n");
if (netInstStuff::OnNSPSelected(ourUrls[0], 1)) this->pageInfoText->SetText("NSP Installed! Press B to return, or A to start another.");
else this->pageInfoText->SetText("Install failed for some reason!");
}
}
}

31
source/util.cpp Executable file
View file

@ -0,0 +1,31 @@
#include <filesystem>
#include "switch.h"
#include "util.hpp"
#include "nx/ipc/tin_ipc.h"
namespace util {
void initApp () {
if (!std::filesystem::exists("sdmc:/switch")) std::filesystem::create_directory("sdmc:/switch");
if (!std::filesystem::exists(appVariables::appDir)) std::filesystem::create_directory(appVariables::appDir);
socketInitializeDefault();
#ifdef __DEBUG__
nxlinkStdio();
#endif
plInitialize();
setInitialize();
ncmInitialize();
nsInitialize();
nsextInitialize();
esInitialize();
}
void deinitApp () {
socketExit();
plExit();
setExit();
ncmExit();
nsExit();
nsextExit();
esExit();
}
}