mirror of
https://github.com/Huntereb/Awoo-Installer
synced 2024-11-26 05:30:19 +00:00
idk validation isn't working...
This commit is contained in:
parent
0910512d24
commit
fe18b58f9a
24 changed files with 582 additions and 86 deletions
|
@ -34,7 +34,6 @@ namespace tin::install::nsp
|
|||
|
||||
HTTPNSP(std::string url);
|
||||
|
||||
virtual void BufferNCAHeader(void* buf, NcmContentId placeholderId) override;
|
||||
virtual void StreamToPlaceholder(std::shared_ptr<nx::ncm::ContentStorage>& contentStorage, NcmContentId placeholderId) override;
|
||||
virtual void BufferData(void* buf, off_t offset, size_t size) override;
|
||||
};
|
||||
|
|
|
@ -40,12 +40,12 @@ namespace tin::install::nsp
|
|||
RemoteNSP();
|
||||
|
||||
public:
|
||||
virtual void BufferNCAHeader(void* buf, NcmContentId placeholderId) = 0;
|
||||
virtual void StreamToPlaceholder(std::shared_ptr<nx::ncm::ContentStorage>& contentStorage, NcmContentId placeholderId) = 0;
|
||||
virtual void BufferData(void* buf, off_t offset, size_t size) = 0;
|
||||
|
||||
virtual void RetrieveHeader();
|
||||
virtual const PFS0BaseHeader* GetBaseHeader();
|
||||
virtual void BufferNCAHeader(void* buf, NcmContentId placeholderId);
|
||||
virtual u64 GetDataOffset();
|
||||
|
||||
virtual const PFS0FileEntry* GetFileEntry(unsigned int index);
|
||||
|
|
19
include/install/usb_nsp.hpp
Normal file
19
include/install/usb_nsp.hpp
Normal file
|
@ -0,0 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "install/remote_nsp.hpp"
|
||||
|
||||
namespace tin::install::nsp
|
||||
{
|
||||
class USBNSP : public RemoteNSP
|
||||
{
|
||||
private:
|
||||
std::string m_nspName;
|
||||
|
||||
public:
|
||||
USBNSP(std::string nspName);
|
||||
|
||||
virtual void StreamToPlaceholder(std::shared_ptr<nx::ncm::ContentStorage>& contentStorage, NcmContentId placeholderId) override;
|
||||
virtual void BufferData(void* buf, off_t offset, size_t size) override;
|
||||
};
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
#include "ui/mainPage.hpp"
|
||||
#include "ui/netInstPage.hpp"
|
||||
#include "ui/nspInstPage.hpp"
|
||||
#include "ui/usbInstPage.hpp"
|
||||
#include "ui/instPage.hpp"
|
||||
#include "ui/optionsPage.hpp"
|
||||
|
||||
|
@ -15,6 +16,7 @@ namespace inst::ui {
|
|||
MainPage::Ref mainPage;
|
||||
netInstPage::Ref netinstPage;
|
||||
nspInstPage::Ref nspinstPage;
|
||||
usbInstPage::Ref usbinstPage;
|
||||
instPage::Ref instpage;
|
||||
optionsPage::Ref optionspage;
|
||||
};
|
||||
|
|
30
include/ui/usbInstPage.hpp
Normal file
30
include/ui/usbInstPage.hpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
#include <pu/Plutonium>
|
||||
|
||||
using namespace pu::ui::elm;
|
||||
namespace inst::ui {
|
||||
class usbInstPage : public pu::ui::Layout
|
||||
{
|
||||
public:
|
||||
usbInstPage();
|
||||
PU_SMART_CTOR(usbInstPage)
|
||||
void startInstall();
|
||||
void startUsb();
|
||||
void onInput(u64 Down, u64 Up, u64 Held, pu::ui::Touch Pos);
|
||||
TextBlock::Ref pageInfoText;
|
||||
private:
|
||||
static std::vector<std::string> ourNsps;
|
||||
static std::vector<std::string> selectedNsps;
|
||||
std::string lastUrl;
|
||||
std::string lastFileID;
|
||||
TextBlock::Ref butText;
|
||||
Rectangle::Ref topRect;
|
||||
Rectangle::Ref infoRect;
|
||||
Rectangle::Ref botRect;
|
||||
Image::Ref titleImage;
|
||||
TextBlock::Ref appVersionText;
|
||||
pu::ui::elm::Menu::Ref menu;
|
||||
void drawMenuItems(bool clearItems);
|
||||
void selectNsp(int selectedIndex);
|
||||
};
|
||||
}
|
8
include/usbInstall.hpp
Normal file
8
include/usbInstall.hpp
Normal file
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace usbInstStuff {
|
||||
std::vector<std::string> OnSelected();
|
||||
void installNspUsb(std::vector<std::string> ourNspList, int ourStorage);
|
||||
}
|
|
@ -29,12 +29,7 @@ extern "C" {
|
|||
#include <stdio.h>
|
||||
#include <switch/types.h>
|
||||
|
||||
extern FILE *nxlinkout;
|
||||
|
||||
int nxLinkInitialize(void);
|
||||
void nxLinkExit(void);
|
||||
|
||||
void printBytes(FILE* out, u8 *bytes, size_t size, bool includeHeader);
|
||||
void printBytes(u8 *bytes, size_t size, bool includeHeader);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ SOFTWARE.
|
|||
strncat(error_prefix, formatted_msg, 512-1); throw std::runtime_error(error_prefix); }
|
||||
|
||||
#ifdef NXLINK_DEBUG
|
||||
#define LOG_DEBUG(format, ...) { fprintf(nxlinkout, "%s:%u: ", __func__, __LINE__); fprintf(nxlinkout, format, ##__VA_ARGS__); }
|
||||
#define LOG_DEBUG(format, ...) { printf("%s:%u: ", __func__, __LINE__); printf(format, ##__VA_ARGS__); }
|
||||
#else
|
||||
#define LOG_DEBUG(format, ...) ;
|
||||
#endif
|
37
include/util/usb_util.hpp
Normal file
37
include/util/usb_util.hpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
#pragma once
|
||||
|
||||
#include <switch.h>
|
||||
#include <string>
|
||||
|
||||
namespace tin::util
|
||||
{
|
||||
enum USBCmdType : u8
|
||||
{
|
||||
REQUEST = 0,
|
||||
RESPONSE = 1
|
||||
};
|
||||
|
||||
struct USBCmdHeader
|
||||
{
|
||||
u32 magic;
|
||||
USBCmdType type;
|
||||
u8 padding[0x3] = {0};
|
||||
u32 cmdId;
|
||||
u64 dataSize;
|
||||
u8 reserved[0xC] = {0};
|
||||
} PACKED;
|
||||
|
||||
static_assert(sizeof(USBCmdHeader) == 0x20, "USBCmdHeader must be 0x20!");
|
||||
|
||||
class USBCmdManager
|
||||
{
|
||||
public:
|
||||
static void SendCmdHeader(u32 cmdId, size_t dataSize);
|
||||
|
||||
static void SendExitCmd();
|
||||
static USBCmdHeader SendFileRangeCmd(std::string nspName, u64 offset, u64 size);
|
||||
};
|
||||
|
||||
size_t USBRead(void* out, size_t len);
|
||||
size_t USBWrite(const void* in, size_t len);
|
||||
}
|
|
@ -208,7 +208,7 @@ namespace tin::data
|
|||
for (int i = 0; i < NUM_BUFFER_SEGMENTS; i++)
|
||||
{
|
||||
printf("Buffer %u:\n", i);
|
||||
printBytes(nxlinkout, m_bufferSegments[i].data, BUFFER_SEGMENT_DATA_SIZE, true);
|
||||
printBytes(m_bufferSegments[i].data, BUFFER_SEGMENT_DATA_SIZE, true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -49,7 +49,7 @@ namespace tin::data
|
|||
|
||||
void ByteBuffer::DebugPrintContents()
|
||||
{
|
||||
fprintf(nxlinkout, "Buffer Size: 0x%lx\n", this->GetSize());
|
||||
printBytes(nxlinkout, this->GetData(), this->GetSize(), true);
|
||||
printf("Buffer Size: 0x%lx\n", this->GetSize());
|
||||
printBytes(this->GetData(), this->GetSize(), true);
|
||||
}
|
||||
}
|
|
@ -80,13 +80,6 @@ namespace tin::install::nsp
|
|||
return 0;
|
||||
}
|
||||
|
||||
void HTTPNSP::BufferNCAHeader(void* buf, NcmContentId placeholderId)
|
||||
{
|
||||
const PFS0FileEntry* fileEntry = this->GetFileEntryByNcaId(placeholderId);
|
||||
u64 pfs0Offset = this->GetDataOffset() + fileEntry->dataOffset;
|
||||
this->BufferData(buf, pfs0Offset, 0xc00);
|
||||
}
|
||||
|
||||
void HTTPNSP::StreamToPlaceholder(std::shared_ptr<nx::ncm::ContentStorage>& contentStorage, NcmContentId placeholderId)
|
||||
{
|
||||
const PFS0FileEntry* fileEntry = this->GetFileEntryByNcaId(placeholderId);
|
||||
|
@ -133,7 +126,7 @@ namespace tin::install::nsp
|
|||
u64 downloadSizeMB = bufferedPlaceholderWriter.GetSizeBuffered() / 1000000;
|
||||
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);
|
||||
//printf("> Download Progress: %lu/%lu MB (%i%s) (%.2f MB/s)\r", downloadSizeMB, totalSizeMB, downloadProgress, "%", speed);
|
||||
inst::ui::setInstInfoText("Downloading " + inst::util::formatUrlString(ncaFileName) + " at " + std::to_string(speed).substr(0, std::to_string(speed).size()-4) + "MB/s");
|
||||
inst::ui::setInstBarPerc((double)downloadProgress);
|
||||
}
|
||||
|
@ -150,7 +143,7 @@ namespace tin::install::nsp
|
|||
u64 installSizeMB = bufferedPlaceholderWriter.GetSizeWrittenToPlaceholder() / 1000000;
|
||||
int installProgress = (int)(((double)bufferedPlaceholderWriter.GetSizeWrittenToPlaceholder() / (double)bufferedPlaceholderWriter.GetTotalDataSize()) * 100.0);
|
||||
|
||||
printf("> Install Progress: %lu/%lu MB (%i%s)\r", installSizeMB, totalSizeMB, installProgress, "%");
|
||||
//printf("> Install Progress: %lu/%lu MB (%i%s)\r", installSizeMB, totalSizeMB, installProgress, "%");
|
||||
inst::ui::setInstBarPerc((double)installProgress);
|
||||
//consoleUpdate(NULL);
|
||||
}
|
||||
|
|
|
@ -230,9 +230,9 @@ namespace tin::install
|
|||
}
|
||||
|
||||
printf("Application content meta key: \n");
|
||||
printBytes(nxlinkout, (u8*)&latestApplicationContentMetaKey, sizeof(NcmContentMetaKey), true);
|
||||
printBytes((u8*)&latestApplicationContentMetaKey, sizeof(NcmContentMetaKey), true);
|
||||
printf("Application content meta: \n");
|
||||
printBytes(nxlinkout, appContentRecordBuf.get(), appContentRecordSize, true);
|
||||
printBytes(appContentRecordBuf.get(), appContentRecordSize, true);
|
||||
|
||||
if (hasUpdate)
|
||||
{
|
||||
|
@ -249,9 +249,9 @@ namespace tin::install
|
|||
}
|
||||
|
||||
printf("Patch content meta key: \n");
|
||||
printBytes(nxlinkout, (u8*)&latestPatchContentMetaKey, sizeof(NcmContentMetaKey), true);
|
||||
printBytes((u8*)&latestPatchContentMetaKey, sizeof(NcmContentMetaKey), true);
|
||||
printf("Patch content meta: \n");
|
||||
printBytes(nxlinkout, patchContentRecordBuf.get(), patchContentRecordsSize, true);
|
||||
printBytes(patchContentRecordBuf.get(), patchContentRecordsSize, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -263,7 +263,7 @@ namespace tin::install
|
|||
ASSERT_OK(nsListApplicationRecordContentMeta(0, baseTitleId, appRecordBuf.get(), 0x100, &numEntriesRead), "Failed to list application record content meta");
|
||||
|
||||
printf("Application record content meta: \n");
|
||||
printBytes(nxlinkout, appRecordBuf.get(), 0x100, true);
|
||||
printBytes(appRecordBuf.get(), 0x100, true);
|
||||
}
|
||||
catch (std::runtime_error& e)
|
||||
{
|
||||
|
|
|
@ -164,7 +164,7 @@ namespace tin::install::nsp
|
|||
progress = (float)fileOff / (float)ncaSize;
|
||||
|
||||
if (fileOff % (0x400000 * 3) == 0) {
|
||||
printf("> Progress: %lu/%lu MB (%d%s)\r", (fileOff / 1000000), (ncaSize / 1000000), (int)(progress * 100.0), "%");
|
||||
//printf("> Progress: %lu/%lu MB (%d%s)\r", (fileOff / 1000000), (ncaSize / 1000000), (int)(progress * 100.0), "%");
|
||||
inst::ui::setInstBarPerc((double)(progress * 100.0));
|
||||
}
|
||||
|
||||
|
@ -186,7 +186,7 @@ namespace tin::install::nsp
|
|||
writer.close();
|
||||
|
||||
// Clean up the line for whatever comes next
|
||||
printf(" \r");
|
||||
//printf(" \r");
|
||||
printf("Registering placeholder...\n");
|
||||
|
||||
if (!failed)
|
||||
|
|
|
@ -69,7 +69,6 @@ namespace tin::install::nsp
|
|||
cnmtContentInfo.content_id = cnmtContentId;
|
||||
*(u64*)&cnmtContentInfo.size = cnmtNcaSize & 0xFFFFFFFFFFFF;
|
||||
cnmtContentInfo.content_type = NcmContentType_Meta;
|
||||
//consoleUpdate(NULL);
|
||||
|
||||
return { tin::util::GetContentMetaFromNCA(cnmtNCAFullPath), cnmtContentInfo };
|
||||
}
|
||||
|
@ -115,7 +114,7 @@ namespace tin::install::nsp
|
|||
m_remoteNSP->StreamToPlaceholder(contentStorage, ncaId);
|
||||
|
||||
// Clean up the line for whatever comes next
|
||||
printf(" \r");
|
||||
//printf(" \r");
|
||||
printf("Registering placeholder...\n");
|
||||
|
||||
try
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace tin::install::nsp
|
|||
this->BufferData(m_headerBytes.data(), 0x0, sizeof(PFS0BaseHeader));
|
||||
|
||||
printf("Base header: \n");
|
||||
printBytes(nxlinkout, m_headerBytes.data(), sizeof(PFS0BaseHeader), true);
|
||||
printBytes(m_headerBytes.data(), sizeof(PFS0BaseHeader), true);
|
||||
|
||||
// Retrieve the full header
|
||||
size_t remainingHeaderSize = this->GetBaseHeader()->numFiles * sizeof(PFS0FileEntry) + this->GetBaseHeader()->stringTableSize;
|
||||
|
@ -53,7 +53,7 @@ namespace tin::install::nsp
|
|||
this->BufferData(m_headerBytes.data() + sizeof(PFS0BaseHeader), sizeof(PFS0BaseHeader), remainingHeaderSize);
|
||||
|
||||
printf("Full header: \n");
|
||||
printBytes(nxlinkout, m_headerBytes.data(), m_headerBytes.size(), true);
|
||||
printBytes(m_headerBytes.data(), m_headerBytes.size(), true);
|
||||
}
|
||||
|
||||
const PFS0FileEntry* RemoteNSP::GetFileEntry(unsigned int index)
|
||||
|
@ -134,6 +134,13 @@ namespace tin::install::nsp
|
|||
return reinterpret_cast<PFS0BaseHeader*>(m_headerBytes.data());
|
||||
}
|
||||
|
||||
void RemoteNSP::BufferNCAHeader(void* buf, NcmContentId placeholderId)
|
||||
{
|
||||
const PFS0FileEntry* fileEntry = this->GetFileEntryByNcaId(placeholderId);
|
||||
u64 pfs0Offset = this->GetDataOffset() + fileEntry->dataOffset;
|
||||
this->BufferData(buf, pfs0Offset, 0xc00);
|
||||
}
|
||||
|
||||
u64 RemoteNSP::GetDataOffset()
|
||||
{
|
||||
if (m_headerBytes.empty())
|
||||
|
|
145
source/install/usb_nsp.cpp
Normal file
145
source/install/usb_nsp.cpp
Normal file
|
@ -0,0 +1,145 @@
|
|||
#include "install/usb_nsp.hpp"
|
||||
|
||||
|
||||
#include <switch.h>
|
||||
#include <algorithm>
|
||||
#include <malloc.h>
|
||||
#include <threads.h>
|
||||
#include "data/byte_buffer.hpp"
|
||||
#include "data/buffered_placeholder_writer.hpp"
|
||||
#include "util/usb_util.hpp"
|
||||
#include "error.hpp"
|
||||
#include "debug.h"
|
||||
|
||||
namespace tin::install::nsp
|
||||
{
|
||||
USBNSP::USBNSP(std::string nspName) :
|
||||
m_nspName(nspName)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
struct USBFuncArgs
|
||||
{
|
||||
std::string nspName;
|
||||
tin::data::BufferedPlaceholderWriter* bufferedPlaceholderWriter;
|
||||
u64 pfs0Offset;
|
||||
u64 ncaSize;
|
||||
};
|
||||
|
||||
int USBThreadFunc(void* in)
|
||||
{
|
||||
USBFuncArgs* args = reinterpret_cast<USBFuncArgs*>(in);
|
||||
tin::util::USBCmdHeader header = tin::util::USBCmdManager::SendFileRangeCmd(args->nspName, args->pfs0Offset, args->ncaSize);
|
||||
|
||||
u8* buf = (u8*)memalign(0x1000, 0x800000);
|
||||
u64 sizeRemaining = header.dataSize;
|
||||
size_t tmpSizeRead = 0;
|
||||
|
||||
try
|
||||
{
|
||||
while (sizeRemaining)
|
||||
{
|
||||
tmpSizeRead = usbCommsRead(buf, std::min(sizeRemaining, (u64)0x800000));
|
||||
sizeRemaining -= tmpSizeRead;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (args->bufferedPlaceholderWriter->CanAppendData(tmpSizeRead))
|
||||
break;
|
||||
}
|
||||
|
||||
args->bufferedPlaceholderWriter->AppendData(buf, tmpSizeRead);
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
LOG_DEBUG("An error occurred:\n%s", e.what());
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int USBPlaceholderWriteFunc(void* in)
|
||||
{
|
||||
USBFuncArgs* args = reinterpret_cast<USBFuncArgs*>(in);
|
||||
|
||||
while (!args->bufferedPlaceholderWriter->IsPlaceholderComplete())
|
||||
{
|
||||
if (args->bufferedPlaceholderWriter->CanWriteSegmentToPlaceholder())
|
||||
args->bufferedPlaceholderWriter->WriteSegmentToPlaceholder();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void USBNSP::StreamToPlaceholder(std::shared_ptr<nx::ncm::ContentStorage>& contentStorage, NcmContentId placeholderId)
|
||||
{
|
||||
const PFS0FileEntry* fileEntry = this->GetFileEntryByNcaId(placeholderId);
|
||||
std::string ncaFileName = this->GetFileEntryName(fileEntry);
|
||||
|
||||
LOG_DEBUG("Retrieving %s\n", ncaFileName.c_str());
|
||||
size_t ncaSize = fileEntry->fileSize;
|
||||
|
||||
tin::data::BufferedPlaceholderWriter bufferedPlaceholderWriter(contentStorage, placeholderId, ncaSize);
|
||||
USBFuncArgs args;
|
||||
args.nspName = m_nspName;
|
||||
args.bufferedPlaceholderWriter = &bufferedPlaceholderWriter;
|
||||
args.pfs0Offset = this->GetDataOffset() + fileEntry->dataOffset;
|
||||
args.ncaSize = ncaSize;
|
||||
thrd_t usbThread;
|
||||
thrd_t writeThread;
|
||||
|
||||
thrd_create(&usbThread, USBThreadFunc, &args);
|
||||
thrd_create(&writeThread, USBPlaceholderWriteFunc, &args);
|
||||
|
||||
u64 freq = armGetSystemTickFreq();
|
||||
u64 startTime = armGetSystemTick();
|
||||
size_t startSizeBuffered = 0;
|
||||
double speed = 0.0;
|
||||
|
||||
while (!bufferedPlaceholderWriter.IsBufferDataComplete())
|
||||
{
|
||||
u64 newTime = armGetSystemTick();
|
||||
|
||||
if (newTime - startTime >= freq)
|
||||
{
|
||||
size_t newSizeBuffered = bufferedPlaceholderWriter.GetSizeBuffered();
|
||||
double mbBuffered = (newSizeBuffered / 1000000.0) - (startSizeBuffered / 1000000.0);
|
||||
double duration = ((double)(newTime - startTime) / (double)freq);
|
||||
speed = mbBuffered / duration;
|
||||
|
||||
startTime = newTime;
|
||||
startSizeBuffered = newSizeBuffered;
|
||||
}
|
||||
|
||||
u64 totalSizeMB = bufferedPlaceholderWriter.GetTotalDataSize() / 1000000;
|
||||
u64 downloadSizeMB = bufferedPlaceholderWriter.GetSizeBuffered() / 1000000;
|
||||
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);
|
||||
}
|
||||
|
||||
u64 totalSizeMB = bufferedPlaceholderWriter.GetTotalDataSize() / 1000000;
|
||||
|
||||
while (!bufferedPlaceholderWriter.IsPlaceholderComplete())
|
||||
{
|
||||
u64 installSizeMB = bufferedPlaceholderWriter.GetSizeWrittenToPlaceholder() / 1000000;
|
||||
int installProgress = (int)(((double)bufferedPlaceholderWriter.GetSizeWrittenToPlaceholder() / (double)bufferedPlaceholderWriter.GetTotalDataSize()) * 100.0);
|
||||
|
||||
//printf("> Install Progress: %lu/%lu MB (%i%s)\r", installSizeMB, totalSizeMB, installProgress, "%");
|
||||
}
|
||||
|
||||
thrd_join(usbThread, NULL);
|
||||
thrd_join(writeThread, NULL);
|
||||
}
|
||||
|
||||
void USBNSP::BufferData(void* buf, off_t offset, size_t size)
|
||||
{
|
||||
printf("buffering 0x%lx-0x%lx", offset, offset + size);
|
||||
tin::util::USBCmdHeader header = tin::util::USBCmdManager::SendFileRangeCmd(m_nspName, offset, size);
|
||||
tin::util::USBRead(buf, header.dataSize);
|
||||
}
|
||||
}
|
|
@ -64,8 +64,7 @@ namespace inst::ui {
|
|||
mainApp->instpage->installInfoText->SetText("");
|
||||
mainApp->instpage->installBar->SetProgress(0);
|
||||
mainApp->instpage->installBar->SetVisible(false);
|
||||
if (inst::config::gayMode) mainApp->instpage->awooImage->SetVisible(false);
|
||||
else mainApp->instpage->awooImage->SetVisible(true);
|
||||
mainApp->instpage->awooImage->SetVisible(!inst::config::gayMode);
|
||||
mainApp->LoadLayout(mainApp->instpage);
|
||||
mainApp->CallForRender();
|
||||
}
|
||||
|
|
|
@ -9,11 +9,13 @@ namespace inst::ui {
|
|||
this->mainPage = MainPage::New();
|
||||
this->netinstPage = netInstPage::New();
|
||||
this->nspinstPage = nspInstPage::New();
|
||||
this->usbinstPage = usbInstPage::New();
|
||||
this->instpage = instPage::New();
|
||||
this->optionspage = optionsPage::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->nspinstPage->SetOnInput(std::bind(&nspInstPage::onInput, this->nspinstPage, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
|
||||
this->usbinstPage->SetOnInput(std::bind(&usbInstPage::onInput, this->usbinstPage, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
|
||||
this->instpage->SetOnInput(std::bind(&instPage::onInput, this->instpage, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
|
||||
this->optionspage->SetOnInput(std::bind(&optionsPage::onInput, this->optionspage, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
|
||||
this->LoadLayout(this->mainPage);
|
||||
|
|
|
@ -116,5 +116,8 @@ namespace inst::ui {
|
|||
this->eggImage->SetVisible(false);
|
||||
if (!inst::config::gayMode) this->awooImage->SetVisible(true);
|
||||
}
|
||||
if (Down & KEY_Y) {
|
||||
mainApp->usbinstPage->startUsb();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
127
source/ui/usbInstPage.cpp
Normal file
127
source/ui/usbInstPage.cpp
Normal file
|
@ -0,0 +1,127 @@
|
|||
#include "ui/usbInstPage.hpp"
|
||||
#include "ui/MainApplication.hpp"
|
||||
#include "util/util.hpp"
|
||||
#include "util/config.hpp"
|
||||
#include "usbInstall.hpp"
|
||||
|
||||
|
||||
#define COLOR(hex) pu::ui::Color::FromHex(hex)
|
||||
|
||||
namespace inst::ui {
|
||||
extern MainApplication *mainApp;
|
||||
|
||||
std::vector<std::string> usbInstPage::ourNsps;
|
||||
std::vector<std::string> usbInstPage::selectedNsps;
|
||||
|
||||
usbInstPage::usbInstPage() : Layout::Layout() {
|
||||
usbCommsInitialize();
|
||||
this->SetBackgroundColor(COLOR("#670000FF"));
|
||||
this->SetBackgroundImage("romfs:/background.jpg");
|
||||
this->topRect = Rectangle::New(0, 0, 1280, 93, COLOR("#170909FF"));
|
||||
this->infoRect = Rectangle::New(0, 93, 1280, 60, COLOR("#17090980"));
|
||||
this->botRect = Rectangle::New(0, 660, 1280, 60, COLOR("#17090980"));
|
||||
this->titleImage = Image::New(0, 0, "romfs:/logo.png");
|
||||
this->appVersionText = TextBlock::New(480, 49, "v" + inst::config::appVersion, 22);
|
||||
this->appVersionText->SetColor(COLOR("#FFFFFFFF"));
|
||||
this->pageInfoText = TextBlock::New(10, 109, "", 30);
|
||||
this->pageInfoText->SetColor(COLOR("#FFFFFFFF"));
|
||||
this->butText = TextBlock::New(10, 678, "", 24);
|
||||
this->butText->SetColor(COLOR("#FFFFFFFF"));
|
||||
this->menu = pu::ui::elm::Menu::New(0, 154, 1280, COLOR("#FFFFFF00"), 84, (506 / 84));
|
||||
this->menu->SetOnFocusColor(COLOR("#00000033"));
|
||||
this->menu->SetScrollbarColor(COLOR("#17090980"));
|
||||
this->Add(this->topRect);
|
||||
this->Add(this->infoRect);
|
||||
this->Add(this->botRect);
|
||||
this->Add(this->titleImage);
|
||||
this->Add(this->appVersionText);
|
||||
this->Add(this->butText);
|
||||
this->Add(this->pageInfoText);
|
||||
this->Add(this->menu);
|
||||
}
|
||||
|
||||
void usbInstPage::drawMenuItems(bool clearItems) {
|
||||
if (clearItems) usbInstPage::selectedNsps = {};
|
||||
this->menu->ClearItems();
|
||||
for (auto& url: usbInstPage::ourNsps) {
|
||||
pu::String itm = inst::util::shortenString(inst::util::formatUrlString(url), 56, true);
|
||||
auto ourEntry = pu::ui::elm::MenuItem::New(itm);
|
||||
ourEntry->SetColor(COLOR("#FFFFFFFF"));
|
||||
ourEntry->SetIcon("romfs:/checkbox-blank-outline.png");
|
||||
for (long unsigned int i = 0; i < usbInstPage::selectedNsps.size(); i++) {
|
||||
if (usbInstPage::selectedNsps[i] == url) {
|
||||
ourEntry->SetIcon("romfs:/check-box-outline.png");
|
||||
}
|
||||
}
|
||||
this->menu->AddItem(ourEntry);
|
||||
}
|
||||
}
|
||||
|
||||
void usbInstPage::selectNsp(int selectedIndex) {
|
||||
if (this->menu->GetItems()[selectedIndex]->GetIcon() == "romfs:/check-box-outline.png") {
|
||||
for (long unsigned int i = 0; i < usbInstPage::selectedNsps.size(); i++) {
|
||||
if (usbInstPage::selectedNsps[i] == usbInstPage::ourNsps[selectedIndex]) usbInstPage::selectedNsps.erase(usbInstPage::selectedNsps.begin() + i);
|
||||
}
|
||||
} else usbInstPage::selectedNsps.push_back(usbInstPage::ourNsps[selectedIndex]);
|
||||
usbInstPage::drawMenuItems(false);
|
||||
}
|
||||
|
||||
void usbInstPage::startUsb() {
|
||||
this->pageInfoText->SetText("");
|
||||
this->butText->SetText("\ue0e2 Help \ue0e1 Cancel ");
|
||||
this->menu->SetVisible(false);
|
||||
this->menu->ClearItems();
|
||||
mainApp->LoadLayout(mainApp->usbinstPage);
|
||||
usbInstPage::ourNsps = usbInstStuff::OnSelected();
|
||||
if (!usbInstPage::ourNsps.size()) {
|
||||
mainApp->LoadLayout(mainApp->mainPage);
|
||||
return;
|
||||
} else {
|
||||
this->pageInfoText->SetText("Select what files you want to install from the usb, then press the Plus button!");
|
||||
this->butText->SetText("\ue0e0 Select File \ue0e3 Select All \ue0ef Install File(s) \ue0e1 Cancel ");
|
||||
usbInstPage::drawMenuItems(true);
|
||||
}
|
||||
this->menu->SetVisible(true);
|
||||
return;
|
||||
}
|
||||
|
||||
void usbInstPage::startInstall() {
|
||||
int dialogResult = -1;
|
||||
if (usbInstPage::selectedNsps.size() == 1) dialogResult = mainApp->CreateShowDialog("Where should " + selectedNsps[0] + " be installed to?", "Press B to cancel", {"SD Card", "Internal Storage"}, false);
|
||||
else dialogResult = mainApp->CreateShowDialog("Where should the selected " + std::to_string(usbInstPage::selectedNsps.size()) + " files be installed to?", "Press B to cancel", {"SD Card", "Internal Storage"}, false);
|
||||
if (dialogResult == -1) return;
|
||||
usbInstStuff::installNspUsb(usbInstPage::selectedNsps, dialogResult);
|
||||
return;
|
||||
}
|
||||
|
||||
void usbInstPage::onInput(u64 Down, u64 Up, u64 Held, pu::ui::Touch Pos) {
|
||||
if (Down & KEY_B) {
|
||||
usbCommsExit();
|
||||
mainApp->LoadLayout(mainApp->mainPage);
|
||||
}
|
||||
if ((Down & KEY_A) || (Up & KEY_TOUCH)) {
|
||||
usbInstPage::selectNsp(this->menu->GetSelectedIndex());
|
||||
if (this->menu->GetItems().size() == 1 && usbInstPage::selectedNsps.size() == 1) {
|
||||
usbInstPage::startInstall();
|
||||
}
|
||||
}
|
||||
if ((Down & KEY_Y)) {
|
||||
if (usbInstPage::selectedNsps.size() == this->menu->GetItems().size()) usbInstPage::drawMenuItems(true);
|
||||
else {
|
||||
for (long unsigned int i = 0; i < this->menu->GetItems().size(); i++) {
|
||||
if (this->menu->GetItems()[i]->GetIcon() == "romfs:/check-box-outline.png") continue;
|
||||
else usbInstPage::selectNsp(i);
|
||||
}
|
||||
usbInstPage::drawMenuItems(false);
|
||||
}
|
||||
}
|
||||
if (Down & KEY_PLUS) {
|
||||
if (usbInstPage::selectedNsps.size() == 0) {
|
||||
usbInstPage::selectNsp(this->menu->GetSelectedIndex());
|
||||
usbInstPage::startInstall();
|
||||
return;
|
||||
}
|
||||
usbInstPage::startInstall();
|
||||
}
|
||||
}
|
||||
}
|
95
source/usbInstall.cpp
Normal file
95
source/usbInstall.cpp
Normal file
|
@ -0,0 +1,95 @@
|
|||
#include "usbInstall.hpp"
|
||||
#include "install/usb_nsp.hpp"
|
||||
#include "install/install_nsp_remote.hpp"
|
||||
#include "util/usb_util.hpp"
|
||||
#include "util/util.hpp"
|
||||
#include "util/config.hpp"
|
||||
#include "ui/usbInstPage.hpp"
|
||||
|
||||
#include "nspInstall.hpp"
|
||||
#include "ui/MainApplication.hpp"
|
||||
|
||||
namespace inst::ui {
|
||||
extern MainApplication *mainApp;
|
||||
}
|
||||
|
||||
namespace usbInstStuff {
|
||||
struct TUSHeader
|
||||
{
|
||||
u32 magic; // TUL0 (Tinfoil Usb List 0)
|
||||
u32 nspListSize;
|
||||
u64 padding;
|
||||
} PACKED;
|
||||
|
||||
std::vector<std::string> OnSelected() {
|
||||
Result rc = 0;
|
||||
inst::ui::setInstInfoText("waiting for usb...\n");
|
||||
|
||||
while(true) {
|
||||
hidScanInput();
|
||||
if (hidKeysDown(CONTROLLER_P1_AUTO) & KEY_B)
|
||||
break;
|
||||
rc = usbDsWaitReady(1000000);
|
||||
if (R_SUCCEEDED(rc)) break;
|
||||
else if ((rc & 0x3FFFFF) != 0xEA01)
|
||||
return {};
|
||||
}
|
||||
|
||||
inst::ui::setInstInfoText("USB install ready!\n");
|
||||
TUSHeader header;
|
||||
tin::util::USBRead(&header, sizeof(TUSHeader));
|
||||
|
||||
if (header.magic != 0x304C5554)
|
||||
return {};
|
||||
|
||||
auto nspListBuf = std::make_unique<char[]>(header.nspListSize+1);
|
||||
std::vector<std::string> nspNames;
|
||||
memset(nspListBuf.get(), 0, header.nspListSize+1);
|
||||
|
||||
tin::util::USBRead(nspListBuf.get(), header.nspListSize);
|
||||
|
||||
// Split the string up into individual nsp names
|
||||
std::stringstream nspNameStream(nspListBuf.get());
|
||||
std::string segment;
|
||||
std::string nspExt = ".nsp";
|
||||
std::string nszExt = ".nsz";
|
||||
|
||||
while (std::getline(nspNameStream, segment, '\n')) {
|
||||
if (segment.compare(segment.size() - nspExt.size(), nspExt.size(), nspExt) == 0 || segment.compare(segment.size() - nszExt.size(), nszExt.size(), nszExt) == 0)
|
||||
nspNames.push_back(segment);
|
||||
}
|
||||
|
||||
return nspNames;
|
||||
}
|
||||
|
||||
void installNspUsb(std::vector<std::string> ourNspList, int ourStorage) {
|
||||
inst::util::initInstallServices();
|
||||
|
||||
inst::ui::loadInstallScreen();
|
||||
NcmStorageId m_destStorageId = NcmStorageId_SdCard;
|
||||
|
||||
if (ourStorage) m_destStorageId = NcmStorageId_BuiltInUser;
|
||||
|
||||
for (std::string nspName: ourNspList) {
|
||||
try {
|
||||
tin::install::nsp::USBNSP usbNSP(nspName);
|
||||
inst::ui::setInstInfoText("installing" + nspName);
|
||||
tin::install::nsp::RemoteNSPInstall install(m_destStorageId, inst::config::ignoreReqVers, &usbNSP);
|
||||
|
||||
install.Prepare();
|
||||
install.Begin();
|
||||
} catch(...) {
|
||||
int rc = inst::ui::mainApp->CreateShowDialog("install failed", nspName + " failed\ndo you want to continue?", {"yes", "cancel"}, true);
|
||||
if (rc == 1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tin::util::USBCmdManager::SendExitCmd();
|
||||
|
||||
inst::ui::setInstInfoText("finished installation");
|
||||
inst::ui::mainApp->CreateShowDialog("Done", "Back to menu?", {"ok"}, true);
|
||||
inst::ui::loadMainMenu();
|
||||
inst::util::deinitInstallServices();
|
||||
}
|
||||
}
|
|
@ -29,69 +29,23 @@ SOFTWARE.
|
|||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <switch/runtime/nxlink.h>
|
||||
|
||||
#ifdef NXLINK_DEBUG
|
||||
static int sock = -1;
|
||||
#endif
|
||||
FILE *nxlinkout;
|
||||
|
||||
int nxLinkInitialize(void)
|
||||
void printBytes(u8 *bytes, size_t size, bool includeHeader)
|
||||
{
|
||||
#ifdef NXLINK_DEBUG
|
||||
int ret = -1;
|
||||
struct sockaddr_in srv_addr;
|
||||
|
||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (!sock) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
bzero(&srv_addr, sizeof srv_addr);
|
||||
srv_addr.sin_family = AF_INET;
|
||||
srv_addr.sin_addr = __nxlink_host;
|
||||
srv_addr.sin_port = htons(NXLINK_CLIENT_PORT);
|
||||
|
||||
ret = connect(sock, (struct sockaddr *) &srv_addr, sizeof(srv_addr));
|
||||
if (ret != 0) {
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fflush(nxlinkout);
|
||||
nxlinkout = fdopen(sock, "w");
|
||||
setvbuf(nxlinkout, NULL, _IONBF, 0);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nxLinkExit(void)
|
||||
{
|
||||
#ifdef NXLINK_DEBUG
|
||||
fclose(nxlinkout);
|
||||
#endif
|
||||
}
|
||||
|
||||
void printBytes(FILE* out, u8 *bytes, size_t size, bool includeHeader)
|
||||
{
|
||||
if (out == NULL)
|
||||
return;
|
||||
|
||||
int count = 0;
|
||||
|
||||
if (includeHeader)
|
||||
{
|
||||
fprintf(out, "\n\n00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
|
||||
fprintf(out, "-----------------------------------------------\n");
|
||||
printf("\n\n00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
|
||||
printf("-----------------------------------------------\n");
|
||||
}
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
fprintf(out, "%02x ", bytes[i]);
|
||||
printf("%02x ", bytes[i]);
|
||||
count++;
|
||||
if ((count % 16) == 0)
|
||||
fprintf(out, "\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
fprintf(out, "\n");
|
||||
printf("\n");
|
||||
}
|
82
source/util/usb_util.cpp
Normal file
82
source/util/usb_util.cpp
Normal file
|
@ -0,0 +1,82 @@
|
|||
#include "util/usb_util.hpp"
|
||||
|
||||
#include "data/byte_buffer.hpp"
|
||||
#include "debug.h"
|
||||
#include "error.hpp"
|
||||
|
||||
namespace tin::util
|
||||
{
|
||||
void USBCmdManager::SendCmdHeader(u32 cmdId, size_t dataSize)
|
||||
{
|
||||
USBCmdHeader header;
|
||||
header.magic = 0x30435554; // TUC0 (Tinfoil USB Command 0)
|
||||
header.type = USBCmdType::REQUEST;
|
||||
header.cmdId = cmdId;
|
||||
header.dataSize = dataSize;
|
||||
|
||||
USBWrite(&header, sizeof(USBCmdHeader));
|
||||
}
|
||||
|
||||
void USBCmdManager::SendExitCmd()
|
||||
{
|
||||
USBCmdManager::SendCmdHeader(0, 0);
|
||||
}
|
||||
|
||||
USBCmdHeader USBCmdManager::SendFileRangeCmd(std::string nspName, u64 offset, u64 size)
|
||||
{
|
||||
struct FileRangeCmdHeader
|
||||
{
|
||||
u64 size;
|
||||
u64 offset;
|
||||
u64 nspNameLen;
|
||||
u64 padding;
|
||||
} fRangeHeader;
|
||||
|
||||
fRangeHeader.size = size;
|
||||
fRangeHeader.offset = offset;
|
||||
fRangeHeader.nspNameLen = nspName.size();
|
||||
fRangeHeader.padding = 0;
|
||||
|
||||
USBCmdManager::SendCmdHeader(1, sizeof(FileRangeCmdHeader) + fRangeHeader.nspNameLen);
|
||||
USBWrite(&fRangeHeader, sizeof(FileRangeCmdHeader));
|
||||
USBWrite(nspName.c_str(), fRangeHeader.nspNameLen);
|
||||
|
||||
USBCmdHeader responseHeader;
|
||||
USBRead(&responseHeader, sizeof(USBCmdHeader));
|
||||
return responseHeader;
|
||||
}
|
||||
|
||||
size_t USBRead(void* out, size_t len)
|
||||
{
|
||||
u8* tmpBuf = (u8*)out;
|
||||
size_t sizeRemaining = len;
|
||||
size_t tmpSizeRead = 0;
|
||||
|
||||
while (sizeRemaining)
|
||||
{
|
||||
tmpSizeRead = usbCommsRead(tmpBuf, sizeRemaining);
|
||||
tmpBuf += tmpSizeRead;
|
||||
sizeRemaining -= tmpSizeRead;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t USBWrite(const void* in, size_t len)
|
||||
{
|
||||
const u8 *bufptr = (const u8 *)in;
|
||||
size_t cursize = len;
|
||||
size_t tmpsize = 0;
|
||||
|
||||
while (cursize)
|
||||
{
|
||||
tmpsize = usbCommsWrite(bufptr, cursize);
|
||||
LOG_DEBUG("USB Bytes Written: \n");
|
||||
printBytes((u8*)bufptr, tmpsize, true);
|
||||
bufptr += tmpsize;
|
||||
cursize -= tmpsize;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue