Many changes. Good things are coming.

This commit is contained in:
Pablo Curiel 2019-04-21 12:27:33 -04:00
parent 59e48748ae
commit edd7eee294
11 changed files with 4060 additions and 3712 deletions

View file

@ -56,6 +56,7 @@ CFLAGS := -g -Wall -O2 -ffunction-sections \
$(ARCH) $(DEFINES) $(ARCH) $(DEFINES)
CFLAGS += $(INCLUDE) -D__SWITCH__ -D__LINUX_ERRNO_EXTENSIONS__ CFLAGS += $(INCLUDE) -D__SWITCH__ -D__LINUX_ERRNO_EXTENSIONS__
CFLAGS += `freetype-config --cflags`
CFLAGS += `aarch64-none-elf-pkg-config zlib --cflags` CFLAGS += `aarch64-none-elf-pkg-config zlib --cflags`
CFLAGS += `aarch64-none-elf-pkg-config libxml-2.0 --cflags` CFLAGS += `aarch64-none-elf-pkg-config libxml-2.0 --cflags`
CFLAGS += `aarch64-none-elf-pkg-config json-c --cflags` CFLAGS += `aarch64-none-elf-pkg-config json-c --cflags`
@ -65,7 +66,7 @@ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH) ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lcurl -lxml2 -lz -lnx -ljson-c -lm LIBS := -lcurl -lmbedtls -lmbedx509 -lmbedcrypto -lxml2 -lz -lnx -ljson-c -lm `freetype-config --libs`
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing # list of directories containing libraries, this must be the top level containing

View file

@ -13,8 +13,8 @@
u32 crc32_for_byte(u32 r) u32 crc32_for_byte(u32 r)
{ {
for(int j = 0; j < 8; ++j) r = (r & 1? 0: (u32)0xEDB88320L) ^ r >> 1; for(int j = 0; j < 8; ++j) r = (r & 1? 0: (u32)0xEDB88320L) ^ r >> 1;
return r ^ (u32)0xFF000000L; return r ^ (u32)0xFF000000L;
} }
/* Any unsigned integer type with at least 32 bits may be used as /* Any unsigned integer type with at least 32 bits may be used as
@ -24,29 +24,29 @@ typedef unsigned long accum_t;
void init_tables(u32* table, u32* wtable) void init_tables(u32* table, u32* wtable)
{ {
for(u64 i = 0; i < 0x100; ++i) table[i] = crc32_for_byte(i); for(u64 i = 0; i < 0x100; ++i) table[i] = crc32_for_byte(i);
for(u64 k = 0; k < sizeof(accum_t); ++k) for(u64 k = 0; k < sizeof(accum_t); ++k)
{ {
for(u64 w, i = 0; i < 0x100; ++i) for(u64 w, i = 0; i < 0x100; ++i)
{ {
for(u64 j = w = 0; j < sizeof(accum_t); ++j) w = table[(u8)(j == k? w ^ i: w)] ^ w >> 8; for(u64 j = w = 0; j < sizeof(accum_t); ++j) w = table[(u8)(j == k? w ^ i: w)] ^ w >> 8;
wtable[(k << 8) + i] = w ^ (k? wtable[0]: 0); wtable[(k << 8) + i] = w ^ (k? wtable[0]: 0);
} }
} }
} }
void crc32(const void* data, u64 n_bytes, u32* crc) void crc32(const void* data, u64 n_bytes, u32* crc)
{ {
static u32 table[0x100], wtable[0x100*sizeof(accum_t)]; static u32 table[0x100], wtable[0x100*sizeof(accum_t)];
u64 n_accum = n_bytes / sizeof(accum_t); u64 n_accum = n_bytes / sizeof(accum_t);
if (!*table) init_tables(table, wtable); if (!*table) init_tables(table, wtable);
for(u64 i = 0; i < n_accum; ++i) for(u64 i = 0; i < n_accum; ++i)
{ {
accum_t a = *crc ^ ((accum_t*)data)[i]; accum_t a = *crc ^ ((accum_t*)data)[i];
for(u64 j = *crc = 0; j < sizeof(accum_t); ++j) *crc ^= wtable[(j << 8) + (u8)(a >> 8*j)]; for(u64 j = *crc = 0; j < sizeof(accum_t); ++j) *crc ^= wtable[(j << 8) + (u8)(a >> 8*j)];
} }
for(u64 i = n_accum*sizeof(accum_t); i < n_bytes; ++i) *crc = table[(u8)*crc ^ ((u8*)data)[i]] ^ *crc >> 8; for(u64 i = n_accum*sizeof(accum_t); i < n_bytes; ++i) *crc = table[(u8)*crc ^ ((u8*)data)[i]] ^ *crc >> 8;
} }

File diff suppressed because it is too large Load diff

View file

@ -5,71 +5,80 @@
#include <switch.h> #include <switch.h>
#define DUMP_BUFFER_SIZE (u64)0x100000 // 1 MiB #define DUMP_BUFFER_SIZE (u64)0x100000 // 1 MiB
#define ISTORAGE_PARTITION_CNT 2 #define ISTORAGE_PARTITION_CNT 2
#define SPLIT_FILE_MIN (u64)0xEE6B2800 // 4 GB (4000000000 bytes) #define SPLIT_FILE_MIN (u64)0xEE6B2800 // 4 GB (4000000000 bytes)
#define SPLIT_FILE_2GiB (u64)0x80000000 #define SPLIT_FILE_2GiB (u64)0x80000000
#define MEDIA_UNIT_SIZE 0x200 #define MEDIA_UNIT_SIZE 0x200
#define CERT_OFFSET 0x7000 #define CERT_OFFSET 0x7000
#define CERT_SIZE 0x200 #define CERT_SIZE 0x200
#define GAMECARD_HEADER_SIZE 0x200 #define GAMECARD_HEADER_SIZE 0x200
#define GAMECARD_SIZE_ADDR 0x10D #define GAMECARD_SIZE_ADDR 0x10D
#define GAMECARD_DATAEND_ADDR 0x118 #define GAMECARD_DATAEND_ADDR 0x118
#define HFS0_OFFSET_ADDR 0x130 #define HFS0_OFFSET_ADDR 0x130
#define HFS0_SIZE_ADDR 0x138 #define HFS0_SIZE_ADDR 0x138
#define HFS0_MAGIC 0x48465330 // "HFS0" #define HFS0_MAGIC 0x48465330 // "HFS0"
#define HFS0_FILE_COUNT_ADDR 0x04 #define HFS0_FILE_COUNT_ADDR 0x04
#define HFS0_ENTRY_TABLE_ADDR 0x10 #define HFS0_STR_TABLE_SIZE_ADDR 0x08
#define HFS0_ENTRY_TABLE_ADDR 0x10
#define GAMECARD_TYPE1_PARTITION_CNT 3 // "update" (0), "normal" (1), "update" (2) #define GAMECARD_TYPE1_PARTITION_CNT 3 // "update" (0), "normal" (1), "update" (2)
#define GAMECARD_TYPE2_PARTITION_CNT 4 // "update" (0), "logo" (1), "normal" (2), "update" (3) #define GAMECARD_TYPE2_PARTITION_CNT 4 // "update" (0), "logo" (1), "normal" (2), "update" (3)
#define GAMECARD_TYPE(x) ((x) == GAMECARD_TYPE1_PARTITION_CNT ? "Type 0x01" : ((x) == GAMECARD_TYPE2_PARTITION_CNT ? "Type 0x02" : "Unknown")) #define GAMECARD_TYPE(x) ((x) == GAMECARD_TYPE1_PARTITION_CNT ? "Type 0x01" : ((x) == GAMECARD_TYPE2_PARTITION_CNT ? "Type 0x02" : "Unknown"))
#define GAMECARD_TYPE1_PART_NAMES(x) ((x) == 0 ? "Update" : ((x) == 1 ? "Normal" : ((x) == 2 ? "Secure" : "Unknown"))) #define GAMECARD_TYPE1_PART_NAMES(x) ((x) == 0 ? "Update" : ((x) == 1 ? "Normal" : ((x) == 2 ? "Secure" : "Unknown")))
#define GAMECARD_TYPE2_PART_NAMES(x) ((x) == 0 ? "Update" : ((x) == 1 ? "Logo" : ((x) == 2 ? "Normal" : ((x) == 3 ? "Secure" : "Unknown")))) #define GAMECARD_TYPE2_PART_NAMES(x) ((x) == 0 ? "Update" : ((x) == 1 ? "Logo" : ((x) == 2 ? "Normal" : ((x) == 3 ? "Secure" : "Unknown"))))
#define GAMECARD_PARTITION_NAME(x, y) ((x) == GAMECARD_TYPE1_PARTITION_CNT ? GAMECARD_TYPE1_PART_NAMES(y) : ((x) == GAMECARD_TYPE2_PARTITION_CNT ? GAMECARD_TYPE2_PART_NAMES(y) : "Unknown")) #define GAMECARD_PARTITION_NAME(x, y) ((x) == GAMECARD_TYPE1_PARTITION_CNT ? GAMECARD_TYPE1_PART_NAMES(y) : ((x) == GAMECARD_TYPE2_PARTITION_CNT ? GAMECARD_TYPE2_PART_NAMES(y) : "Unknown"))
#define GAMECARD_SIZE_1GiB (u64)0x40000000 #define GAMECARD_SIZE_1GiB (u64)0x40000000
#define GAMECARD_SIZE_2GiB (u64)0x80000000 #define GAMECARD_SIZE_2GiB (u64)0x80000000
#define GAMECARD_SIZE_4GiB (u64)0x100000000 #define GAMECARD_SIZE_4GiB (u64)0x100000000
#define GAMECARD_SIZE_8GiB (u64)0x200000000 #define GAMECARD_SIZE_8GiB (u64)0x200000000
#define GAMECARD_SIZE_16GiB (u64)0x400000000 #define GAMECARD_SIZE_16GiB (u64)0x400000000
#define GAMECARD_SIZE_32GiB (u64)0x800000000 #define GAMECARD_SIZE_32GiB (u64)0x800000000
#define GAMECARD_UPDATE_TITLEID (u64)0x0100000000000816 /* Reference: https://switchbrew.org/wiki/Title_list */
#define GAMECARD_UPDATE_TITLEID (u64)0x0100000000000816
#define SYSUPDATE_100 (u32)450 #define SYSUPDATE_100 (u32)450
#define SYSUPDATE_200 (u32)65796 #define SYSUPDATE_200 (u32)65796
#define SYSUPDATE_210 (u32)131162 #define SYSUPDATE_210 (u32)131162
#define SYSUPDATE_220 (u32)196628 #define SYSUPDATE_220 (u32)196628
#define SYSUPDATE_230 (u32)262164 #define SYSUPDATE_230 (u32)262164
#define SYSUPDATE_300 (u32)201327002 #define SYSUPDATE_300 (u32)201327002
#define SYSUPDATE_301 (u32)201392178 #define SYSUPDATE_301 (u32)201392178
#define SYSUPDATE_302 (u32)201457684 #define SYSUPDATE_302 (u32)201457684
#define SYSUPDATE_400 (u32)268435656 #define SYSUPDATE_400 (u32)268435656
#define SYSUPDATE_401 (u32)268501002 #define SYSUPDATE_401 (u32)268501002
#define SYSUPDATE_410 (u32)269484082 #define SYSUPDATE_410 (u32)269484082
#define SYSUPDATE_500 (u32)335544750 #define SYSUPDATE_500 (u32)335544750
#define SYSUPDATE_501 (u32)335609886 #define SYSUPDATE_501 (u32)335609886
#define SYSUPDATE_502 (u32)335675432 #define SYSUPDATE_502 (u32)335675432
#define SYSUPDATE_510 (u32)336592976 #define SYSUPDATE_510 (u32)336592976
#define SYSUPDATE_600 (u32)402653544
#define SYSUPDATE_601 (u32)402718730
#define SYSUPDATE_610 (u32)403701850
#define SYSUPDATE_620 (u32)404750376
#define SYSUPDATE_700 (u32)469762248
#define SYSUPDATE_701 (u32)469827614
#define SYSUPDATE_800 (u32)536871442
#define bswap_32(a) ((((a) << 24) & 0xff000000) | (((a) << 8) & 0xff0000) | (((a) >> 8) & 0xff00) | (((a) >> 24) & 0xff)) #define bswap_32(a) ((((a) << 24) & 0xff000000) | (((a) << 8) & 0xff0000) | (((a) >> 8) & 0xff00) | (((a) >> 24) & 0xff))
#define round_up(x, y) ((x) + (((y) - ((x) % (y))) % (y))) // Aligns 'x' bytes to a 'y' bytes boundary #define round_up(x, y) ((x) + (((y) - ((x) % (y))) % (y))) // Aligns 'x' bytes to a 'y' bytes boundary
#define SMOOTHING_FACTOR (double)0.01 #define SMOOTHING_FACTOR (double)0.01
typedef struct typedef struct
{ {
u64 file_offset; u64 file_offset;
u64 file_size; u64 file_size;
u32 filename_offset; u32 filename_offset;
u32 hashed_region_size; u32 hashed_region_size;
u64 reserved; u64 reserved;
u8 hashed_region_sha256[0x20]; u8 hashed_region_sha256[0x20];
} PACKED hfs0_entry_table; } PACKED hfs0_entry_table;
void workaroundPartitionZeroAccess(FsDeviceOperator* fsOperator); void workaroundPartitionZeroAccess(FsDeviceOperator* fsOperator);

View file

@ -5,196 +5,167 @@
#include "fsext.h" #include "fsext.h"
// IFileSystemProxy // IFileSystemProxy
Result fsOpenGameCardStorage(FsStorage* out, u32 handle, u32 partition) Result fsOpenGameCardStorage(FsStorage* out, const FsGameCardHandle* handle, u32 partition)
{ {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
struct { struct {
u64 magic; u64 magic;
u64 cmd_id; u64 cmd_id;
u32 handle; u32 handle;
u32 partition; u32 partition;
} *raw; } *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw)); raw = serviceIpcPrepareHeader(fsGetServiceSession(), &c, sizeof(*raw));
raw->magic = SFCI_MAGIC; raw->magic = SFCI_MAGIC;
raw->cmd_id = 30; raw->cmd_id = 30;
raw->handle = handle; raw->handle = handle->value;
raw->partition = partition; raw->partition = partition;
Result rc = serviceIpcDispatch(fsGetServiceSession()); Result rc = serviceIpcDispatch(fsGetServiceSession());
if (R_SUCCEEDED(rc)) if (R_SUCCEEDED(rc))
{ {
IpcParsedCommand r; IpcParsedCommand r;
ipcParse(&r);
struct { struct {
u64 magic; u64 magic;
u64 result; u64 result;
} *resp = r.Raw; } *resp;
rc = resp->result; serviceIpcParse(fsGetServiceSession(), &r, sizeof(*resp));
resp = r.Raw;
if (R_SUCCEEDED(rc)) serviceCreate(&out->s, r.Handles[0]); rc = resp->result;
}
return rc; if (R_SUCCEEDED(rc)) serviceCreateSubservice(&out->s, fsGetServiceSession(), &r, 0);
}
return rc;
} }
Result fsOpenGameCardFileSystem(FsFileSystem* out, u32 handle, u32 partition) Result fsOpenGameCardFileSystem(FsFileSystem* out, const FsGameCardHandle* handle, u32 partition)
{ {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
struct { struct {
u64 magic; u64 magic;
u64 cmd_id; u64 cmd_id;
u32 handle; u32 handle;
u32 partition; u32 partition;
} *raw; } *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw)); raw = serviceIpcPrepareHeader(fsGetServiceSession(), &c, sizeof(*raw));
raw->magic = SFCI_MAGIC; raw->magic = SFCI_MAGIC;
raw->cmd_id = 31; raw->cmd_id = 31;
raw->handle = handle; raw->handle = handle->value;
raw->partition = partition; raw->partition = partition;
Result rc = serviceIpcDispatch(fsGetServiceSession()); Result rc = serviceIpcDispatch(fsGetServiceSession());
if (R_SUCCEEDED(rc)) if (R_SUCCEEDED(rc))
{ {
IpcParsedCommand r; IpcParsedCommand r;
ipcParse(&r);
struct { struct {
u64 magic; u64 magic;
u64 result; u64 result;
} *resp = r.Raw; } *resp;
rc = resp->result; serviceIpcParse(fsGetServiceSession(), &r, sizeof(*resp));
resp = r.Raw;
if (R_SUCCEEDED(rc)) serviceCreate(&out->s, r.Handles[0]); rc = resp->result;
}
return rc; if (R_SUCCEEDED(rc)) serviceCreateSubservice(&out->s, fsGetServiceSession(), &r, 0);
}
return rc;
}
Result fsOpenGameCardDetectionEventNotifier(FsEventNotifier* out)
{
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = serviceIpcPrepareHeader(fsGetServiceSession(), &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 501;
Result rc = serviceIpcDispatch(fsGetServiceSession());
if (R_SUCCEEDED(rc))
{
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(fsGetServiceSession(), &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) serviceCreateSubservice(&out->s, fsGetServiceSession(), &r, 0);
}
return rc;
} }
// IDeviceOperator // IDeviceOperator
Result fsDeviceOperatorIsGameCardInserted(FsDeviceOperator* d, bool* out) Result fsDeviceOperatorUpdatePartitionInfo(FsDeviceOperator* d, const FsGameCardHandle* handle, u32* out_title_version, u64* out_title_id)
{ {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
struct { struct {
u64 magic; u64 magic;
u64 cmd_id; u64 cmd_id;
} *raw; u32 handle;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw)); raw = serviceIpcPrepareHeader(&d->s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC; raw->magic = SFCI_MAGIC;
raw->cmd_id = 200; raw->cmd_id = 203;
raw->handle = handle->value;
Result rc = serviceIpcDispatch(&d->s); Result rc = serviceIpcDispatch(&d->s);
if (R_SUCCEEDED(rc)) if (R_SUCCEEDED(rc))
{ {
IpcParsedCommand r; IpcParsedCommand r;
ipcParse(&r);
struct { struct {
u64 magic; u64 magic;
u64 result; u64 result;
u8 is_inserted; u32 title_ver;
} *resp = r.Raw; u64 title_id;
} *resp;
rc = resp->result; serviceIpcParse(&d->s, &r, sizeof(*resp));
resp = r.Raw;
if (R_SUCCEEDED(rc)) *out = resp->is_inserted != 0; rc = resp->result;
}
return rc; if (R_SUCCEEDED(rc))
} {
if (out_title_version != NULL) *out_title_version = resp->title_ver;
Result fsDeviceOperatorGetGameCardHandle(FsDeviceOperator* d, u32* out) if (out_title_id != NULL) *out_title_id = resp->title_id;
{ }
IpcCommand c; }
ipcInitialize(&c);
return rc;
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 202;
Result rc = serviceIpcDispatch(&d->s);
if (R_SUCCEEDED(rc))
{
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
u32 handle;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) *out = resp->handle;
}
return rc;
}
Result fsDeviceOperatorUpdatePartitionInfo(FsDeviceOperator* d, u32 handle, u32* out_title_version, u64* out_title_id)
{
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u32 handle;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 203;
raw->handle = handle;
Result rc = serviceIpcDispatch(&d->s);
if (R_SUCCEEDED(rc))
{
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
u32 title_ver;
u64 title_id;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc))
{
if (out_title_version != NULL) *out_title_version = resp->title_ver;
if (out_title_id != NULL) *out_title_id = resp->title_id;
}
}
return rc;
} }

View file

@ -7,12 +7,11 @@
#include <switch/services/fs.h> #include <switch/services/fs.h>
// IFileSystemProxy // IFileSystemProxy
Result fsOpenGameCardStorage(FsStorage* out, u32 handle, u32 partition); Result fsOpenGameCardStorage(FsStorage* out, const FsGameCardHandle* handle, u32 partition);
Result fsOpenGameCardFileSystem(FsFileSystem* out, u32 handle, u32 partition); Result fsOpenGameCardFileSystem(FsFileSystem* out, const FsGameCardHandle* handle, u32 partition);
Result fsOpenGameCardDetectionEventNotifier(FsEventNotifier* out);
// IDeviceOperator // IDeviceOperator
Result fsDeviceOperatorIsGameCardInserted(FsDeviceOperator* d, bool* out); Result fsDeviceOperatorUpdatePartitionInfo(FsDeviceOperator* d, const FsGameCardHandle* handle, u32* out_title_version, u64* out_title_id);
Result fsDeviceOperatorGetGameCardHandle(FsDeviceOperator* d, u32* out);
Result fsDeviceOperatorUpdatePartitionInfo(FsDeviceOperator* d, u32 handle, u32* out_title_version, u64* out_title_id);
#endif #endif

View file

@ -1,4 +1,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h> #include <malloc.h>
#include <switch.h> #include <switch.h>
#include <memory.h> #include <memory.h>
@ -6,241 +8,235 @@
#include "dumper.h" #include "dumper.h"
#include "ui.h" #include "ui.h"
#include "util.h" #include "util.h"
#include "fsext.h"
FsDeviceOperator fsOperatorInstance; /* Extern variables */
bool gameCardInserted; extern FsDeviceOperator fsOperatorInstance;
u64 gameCardSize = 0, trimmedCardSize = 0; extern FsEventNotifier fsGameCardEventNotifier;
char gameCardSizeStr[32] = {'\0'}, trimmedCardSizeStr[32] = {'\0'}; extern Handle fsGameCardEventHandle;
extern Event fsGameCardKernelEvent;
extern UEvent exitEvent;
char *hfs0_header = NULL; extern char *hfs0_header;
u64 hfs0_offset = 0, hfs0_size = 0; extern char *partitionHfs0Header;
u32 hfs0_partition_cnt = 0;
//char *partitionHfs0Header = NULL; extern bool gameCardInserted;
//u64 partitionHfs0HeaderSize = 0;
u64 gameCardTitleID = 0; int main(int argc, char *argv[])
u32 gameCardVersion = 0;
char gameCardName[0x201] = {'\0'}, fixedGameCardName[0x201] = {'\0'}, gameCardAuthor[0x101] = {'\0'}, gameCardVersionStr[64] = {'\0'};
u64 gameCardUpdateTitleID = 0;
u32 gameCardUpdateVersion = 0;
char gameCardUpdateVersionStr[128] = {'\0'};
u32 currentFBWidth, currentFBHeight;
u8 *currentFB;
int main(int argc, char **argv)
{ {
gfxInitResolutionDefault(); /* Initialize UI */
gfxInitDefault(); if (!uiInit()) return -1;
gfxConfigureAutoResolutionDefault(true);
uiInit(); int ret = 0;
Result result;
char strbuf[512] = {'\0'};
currentFB = gfxGetFramebuffer(&currentFBWidth, &currentFBHeight); /* Initialize the fsp-srv service */
result = fsInitialize();
if (R_SUCCEEDED(result))
{
/* Open device operator */
result = fsOpenDeviceOperator(&fsOperatorInstance);
if (R_SUCCEEDED(result))
{
/* Initialize the ncm service */
result = ncmInitialize();
if (R_SUCCEEDED(result))
{
/* Initialize the ns service */
result = nsInitialize();
if (R_SUCCEEDED(result))
{
/* Initialize the time service */
result = timeInitialize();
if (R_SUCCEEDED(result))
{
/* Open gamecard detection event notifier */
result = fsOpenGameCardDetectionEventNotifier(&fsGameCardEventNotifier);
if (R_SUCCEEDED(result))
{
/* Retrieve kernel event handle */
result = fsEventNotifierGetEventHandle(&fsGameCardEventNotifier, &fsGameCardEventHandle);
if (R_SUCCEEDED(result))
{
/* Retrieve initial gamecard status */
gameCardInserted = isGameCardInserted();
int ret = 0; /* Load gamecard detection kernel event */
Result result; eventLoadRemote(&fsGameCardKernelEvent, fsGameCardEventHandle, false);
char strbuf[512] = {'\0'};
if (R_SUCCEEDED(result = fsInitialize())) /* Create usermode exit event */
{ ueventCreate(&exitEvent, false);
if (R_SUCCEEDED(result = fsOpenDeviceOperator(&fsOperatorInstance)))
{
if (R_SUCCEEDED(result = ncmInitialize()))
{
if (R_SUCCEEDED(result = nsInitialize()))
{
if (R_SUCCEEDED(result = timeInitialize()))
{
bool exitLoop = false;
while(appletMainLoop()) /* Create gamecard detection thread */
{ Thread thread;
currentFB = gfxGetFramebuffer(&currentFBWidth, &currentFBHeight); result = threadCreate(&thread, fsGameCardDetectionThreadFunc, NULL, 0x10000, 0x2C, -2);
if (R_SUCCEEDED(result))
{
/* Start gamecard detection thread */
result = threadStart(&thread);
if (R_SUCCEEDED(result))
{
/* Main application loop */
bool exitLoop = false;
while(appletMainLoop())
{
UIResult result = uiProcess();
switch(result)
{
case resultShowMainMenu:
uiSetState(stateMainMenu);
break;
case resultShowXciDumpMenu:
uiSetState(stateXciDumpMenu);
break;
case resultDumpXci:
uiSetState(stateDumpXci);
break;
case resultShowRawPartitionDumpMenu:
uiSetState(stateRawPartitionDumpMenu);
break;
case resultDumpRawPartition:
uiSetState(stateDumpRawPartition);
break;
case resultShowPartitionDataDumpMenu:
uiSetState(statePartitionDataDumpMenu);
break;
case resultDumpPartitionData:
uiSetState(stateDumpPartitionData);
break;
case resultShowViewGameCardFsMenu:
uiSetState(stateViewGameCardFsMenu);
break;
case resultShowViewGameCardFsGetList:
uiSetState(stateViewGameCardFsGetList);
break;
case resultShowViewGameCardFsBrowser:
uiSetState(stateViewGameCardFsBrowser);
break;
case resultViewGameCardFsBrowserCopyFile:
uiSetState(stateViewGameCardFsBrowserCopyFile);
break;
case resultDumpGameCardCertificate:
uiSetState(stateDumpGameCardCertificate);
break;
case resultUpdateNSWDBXml:
uiSetState(stateUpdateNSWDBXml);
break;
case resultUpdateApplication:
uiSetState(stateUpdateApplication);
break;
case resultExit:
exitLoop = true;
break;
default:
break;
}
uiPrintHeadline(); if (exitLoop) break;
}
gameCardInserted = isGameCardInserted(&fsOperatorInstance); /* Signal the exit event to terminate the gamecard detection thread */
ueventSignal(&exitEvent);
if (gameCardInserted) /* Wait for the gamecard detection thread to exit */
{ threadWaitForExit(&thread);
if (hfs0_header == NULL) } else {
{ snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Failed to start gamecard detection thread! (0x%08X)", result);
// Don't access the gamecard immediately to avoid conflicts with the fsp-srv, ncm and ns services uiDrawString(strbuf, 0, 0, 255, 255, 255);
uiPleaseWait(); uiRefreshDisplay();
delay(5);
ret = -10;
}
if (getRootHfs0Header(&fsOperatorInstance)) /* Close gamecard detection thread */
{ threadClose(&thread);
if (getGameCardTitleIDAndVersion(&gameCardTitleID, &gameCardVersion)) } else {
{ snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Failed to create gamecard detection thread! (0x%08X)", result);
convertTitleVersionToDecimal(gameCardVersion, gameCardVersionStr, sizeof(gameCardVersionStr)); uiDrawString(strbuf, 0, 0, 255, 255, 255);
uiRefreshDisplay();
delay(5);
ret = -9;
}
getGameCardControlNacp(gameCardTitleID, gameCardName, sizeof(gameCardName), gameCardAuthor, sizeof(gameCardAuthor)); /* Close kernel event */
eventClose(&fsGameCardKernelEvent);
} else {
snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Failed to retrieve gamecard detection event handle! (0x%08X)", result);
uiDrawString(strbuf, 0, 0, 255, 255, 255);
uiRefreshDisplay();
delay(5);
ret = -8;
}
strtrim(gameCardName); /* Close gamecard event notifier */
if (strlen(gameCardName)) fsEventNotifierClose(&fsGameCardEventNotifier);
{ } else {
snprintf(fixedGameCardName, sizeof(fixedGameCardName) / sizeof(fixedGameCardName[0]), "%s", gameCardName); snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Failed to open gamecard detection event notifier! (0x%08X)", result);
removeIllegalCharacters(fixedGameCardName); uiDrawString(strbuf, 0, 0, 255, 255, 255);
} uiRefreshDisplay();
} delay(5);
} ret = -7;
}
uiPrintHeadline(); /* Denitialize the time service */
uiUpdateStatusMsg(); timeExit();
} } else {
} else { snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Failed to initialize the time service! (0x%08X)", result);
if (hfs0_header != NULL) uiDrawString(strbuf, 0, 0, 255, 255, 255);
{ uiRefreshDisplay();
gameCardSize = 0; delay(5);
memset(gameCardSizeStr, 0, sizeof(gameCardSizeStr)); ret = -6;
}
trimmedCardSize = 0; /* Denitialize the ns service */
memset(trimmedCardSizeStr, 0, sizeof(trimmedCardSizeStr)); nsExit();
} else {
snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Failed to initialize the ns service! (0x%08X)", result);
uiDrawString(strbuf, 0, 0, 255, 255, 255);
uiRefreshDisplay();
delay(5);
ret = -5;
}
free(hfs0_header); /* Denitialize the ncm service */
hfs0_header = NULL; ncmExit();
hfs0_offset = hfs0_size = 0; } else {
hfs0_partition_cnt = 0; snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Failed to initialize the ncm service! (0x%08X)", result);
uiDrawString(strbuf, 0, 0, 255, 255, 255);
uiRefreshDisplay();
delay(5);
ret = -4;
}
/*if (partitionHfs0Header != NULL) /* Close device operator */
{ fsDeviceOperatorClose(&fsOperatorInstance);
free(partitionHfs0Header); } else {
partitionHfs0Header = NULL; snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Failed to open device operator! (0x%08X)", result);
partitionHfs0HeaderSize = 0; uiDrawString(strbuf, 0, 0, 255, 255, 255);
}*/ uiRefreshDisplay();
delay(5);
ret = -3;
}
gameCardTitleID = 0; /* Denitialize the fs-srv service */
gameCardVersion = 0; fsExit();
} else {
snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Failed to initialize the fsp-srv service! (0x%08X)", result);
uiDrawString(strbuf, 0, 0, 255, 255, 255);
uiRefreshDisplay();
delay(5);
ret = -2;
}
memset(gameCardName, 0, sizeof(gameCardName)); /* Free resources */
memset(fixedGameCardName, 0, sizeof(fixedGameCardName)); if (hfs0_header != NULL) free(hfs0_header);
memset(gameCardAuthor, 0, sizeof(gameCardAuthor)); if (partitionHfs0Header != NULL) free(partitionHfs0Header);
memset(gameCardVersionStr, 0, sizeof(gameCardVersionStr));
gameCardUpdateTitleID = 0; /* Deinitialize UI */
gameCardUpdateVersion = 0; uiDeinit();
memset(gameCardUpdateVersionStr, 0, sizeof(gameCardUpdateVersionStr)); return ret;
}
}
hidScanInput();
u32 keysDown = hidKeysDown(CONTROLLER_P1_AUTO);
UIResult result = uiLoop(keysDown);
switch(result)
{
case resultShowMainMenu:
uiSetState(stateMainMenu);
break;
case resultShowXciDumpMenu:
uiSetState(stateXciDumpMenu);
break;
case resultDumpXci:
uiSetState(stateDumpXci);
break;
case resultShowRawPartitionDumpMenu:
uiSetState(stateRawPartitionDumpMenu);
break;
case resultDumpRawPartition:
uiSetState(stateDumpRawPartition);
break;
case resultShowPartitionDataDumpMenu:
uiSetState(statePartitionDataDumpMenu);
break;
case resultDumpPartitionData:
uiSetState(stateDumpPartitionData);
break;
case resultShowViewGameCardFsMenu:
uiSetState(stateViewGameCardFsMenu);
break;
case resultShowViewGameCardFsGetList:
uiSetState(stateViewGameCardFsGetList);
break;
case resultShowViewGameCardFsBrowser:
uiSetState(stateViewGameCardFsBrowser);
break;
case resultViewGameCardFsBrowserCopyFile:
uiSetState(stateViewGameCardFsBrowserCopyFile);
break;
case resultDumpGameCardCertificate:
uiSetState(stateDumpGameCardCertificate);
break;
case resultUpdateNSWDBXml:
uiSetState(stateUpdateNSWDBXml);
break;
case resultUpdateApplication:
uiSetState(stateUpdateApplication);
break;
case resultExit:
exitLoop = true;
break;
default:
break;
}
if (exitLoop) break;
syncDisplay();
}
timeExit();
} else {
snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Failed to initialize the time service! (0x%08X)", result);
uiDrawString(strbuf, 0, 0, 255, 255, 255);
syncDisplay();
delay(5);
ret = -5;
}
nsExit();
} else {
snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Failed to initialize the ns service! (0x%08X)", result);
uiDrawString(strbuf, 0, 0, 255, 255, 255);
syncDisplay();
delay(5);
ret = -4;
}
ncmExit();
} else {
snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Failed to initialize the ncm service! (0x%08X)", result);
uiDrawString(strbuf, 0, 0, 255, 255, 255);
syncDisplay();
delay(5);
ret = -3;
}
fsDeviceOperatorClose(&fsOperatorInstance);
} else {
snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Failed to open device operator! (0x%08X)", result);
uiDrawString(strbuf, 0, 0, 255, 255, 255);
syncDisplay();
delay(5);
ret = -2;
}
fsExit();
} else {
snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Failed to initialize the fsp-srv service! (0x%08X)", result);
uiDrawString(strbuf, 0, 0, 255, 255, 255);
syncDisplay();
delay(5);
ret = -1;
}
if (hfs0_header != NULL) free(hfs0_header);
//if (partitionHfs0Header != NULL) free(partitionHfs0Header);
uiDeinit();
gfxExit();
return ret;
} }

File diff suppressed because it is too large Load diff

View file

@ -3,64 +3,88 @@
#ifndef __UI_H__ #ifndef __UI_H__
#define __UI_H__ #define __UI_H__
#define FILENAME_BUFFER_SIZE (1024 * 32) // 32 KiB #define FB_WIDTH 1280
#define FILENAME_MAX_CNT 2048 #define FB_HEIGHT 720
#define CHAR_PT_SIZE 12
#define SCREEN_DPI_CNT 96
#define BG_COLOR_RGB 50
#define HIGHLIGHT_BG_COLOR_R 33
#define HIGHLIGHT_BG_COLOR_G 34
#define HIGHLIGHT_BG_COLOR_B 39
#define HIGHLIGHT_FONT_COLOR_R 0
#define HIGHLIGHT_FONT_COLOR_G 255
#define HIGHLIGHT_FONT_COLOR_B 197
#define XCIDUMP_OPTIONS_X_POS (35 * CHAR_PT_SIZE)
#define TAB_WIDTH 4
typedef enum { typedef enum {
resultNone, resultNone,
resultShowMainMenu, resultShowMainMenu,
resultShowXciDumpMenu, resultShowXciDumpMenu,
resultDumpXci, resultDumpXci,
resultShowRawPartitionDumpMenu, resultShowRawPartitionDumpMenu,
resultDumpRawPartition, resultDumpRawPartition,
resultShowPartitionDataDumpMenu, resultShowPartitionDataDumpMenu,
resultDumpPartitionData, resultDumpPartitionData,
resultShowViewGameCardFsMenu, resultShowViewGameCardFsMenu,
resultShowViewGameCardFsGetList, resultShowViewGameCardFsGetList,
resultShowViewGameCardFsBrowser, resultShowViewGameCardFsBrowser,
resultViewGameCardFsBrowserCopyFile, resultViewGameCardFsBrowserCopyFile,
resultDumpGameCardCertificate, resultDumpGameCardCertificate,
resultUpdateNSWDBXml, resultUpdateNSWDBXml,
resultUpdateApplication, resultUpdateApplication,
resultExit resultExit
} UIResult; } UIResult;
typedef enum { typedef enum {
stateMainMenu, stateMainMenu,
stateXciDumpMenu, stateXciDumpMenu,
stateDumpXci, stateDumpXci,
stateRawPartitionDumpMenu, stateRawPartitionDumpMenu,
stateDumpRawPartition, stateDumpRawPartition,
statePartitionDataDumpMenu, statePartitionDataDumpMenu,
stateDumpPartitionData, stateDumpPartitionData,
stateViewGameCardFsMenu, stateViewGameCardFsMenu,
stateViewGameCardFsGetList, stateViewGameCardFsGetList,
stateViewGameCardFsBrowser, stateViewGameCardFsBrowser,
stateViewGameCardFsBrowserCopyFile, stateViewGameCardFsBrowserCopyFile,
stateDumpGameCardCertificate, stateDumpGameCardCertificate,
stateUpdateNSWDBXml, stateUpdateNSWDBXml,
stateUpdateApplication stateUpdateApplication
} UIState; } UIState;
void uiFill(int x, int y, int width, int height, u8 r, u8 g, u8 b); void uiFill(int x, int y, int width, int height, u8 r, u8 g, u8 b);
void uiDrawString(const char* string, int x, int y, u8 r, u8 g, u8 b);
void uiStatusMsg(const char* fmt, ...); void uiDrawString(const char *string, int x, int y, u8 r, u8 g, u8 b);
void uiRefreshDisplay();
void uiStatusMsg(const char *fmt, ...);
void uiUpdateStatusMsg(); void uiUpdateStatusMsg();
void uiPleaseWait(); void uiPleaseWait();
void uiUpdateFreeSpace(); void uiUpdateFreeSpace();
void uiInit(); void uiClearScreen();
void uiPrintHeadline();
int uiInit();
void uiDeinit(); void uiDeinit();
void uiSetState(UIState state); void uiSetState(UIState state);
UIState uiGetState(); UIState uiGetState();
void uiClearScreen(); UIResult uiProcess();
void uiPrintHeadline();
UIResult uiLoop(u32 keysDown);
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -5,17 +5,24 @@
#include <switch.h> #include <switch.h>
#define APP_VERSION "1.0.6" #define KiB (1024.0)
#define MiB (1024.0 * KiB)
#define GiB (1024.0 * MiB)
#define NAME_BUF_LEN 4096 #define APP_VERSION "1.0.6"
#define SOCK_BUFFERSIZE 65536 #define NAME_BUF_LEN 4096
#define META_DATABASE_FILTER 0x80 // Regular Application #define SOCK_BUFFERSIZE 65536
bool isGameCardInserted(FsDeviceOperator* o); #define META_DATABASE_FILTER 0x80 // Regular Application
void syncDisplay(); #define FILENAME_BUFFER_SIZE (1024 * 512) // 512 KiB
#define FILENAME_MAX_CNT 2048
bool isGameCardInserted();
void fsGameCardDetectionThreadFunc(void *arg);
void delay(u8 seconds); void delay(u8 seconds);
@ -25,6 +32,12 @@ void convertTitleVersionToDecimal(u32 version, char *versionBuf, int versionBufS
bool getGameCardControlNacp(u64 titleID, char *nameBuf, int nameBufSize, char *authorBuf, int authorBufSize); bool getGameCardControlNacp(u64 titleID, char *nameBuf, int nameBufSize, char *authorBuf, int authorBufSize);
void removeIllegalCharacters(char *name);
void strtrim(char *str);
void loadGameCardInfo();
int getSdCardFreeSpace(u64 *out); int getSdCardFreeSpace(u64 *out);
void convertSize(u64 size, char *out, int bufsize); void convertSize(u64 size, char *out, int bufsize);
@ -37,14 +50,12 @@ void addString(char **filenames, int *filenamesCount, char **nextFilename, const
void getDirectoryContents(char *filenameBuffer, char **filenames, int *filenamesCount, const char *directory, bool skipParent); void getDirectoryContents(char *filenameBuffer, char **filenames, int *filenamesCount, const char *directory, bool skipParent);
void enterDirectory(const char *path);
void gameCardDumpNSWDBCheck(u32 crc); void gameCardDumpNSWDBCheck(u32 crc);
void updateNSWDBXml(); void updateNSWDBXml();
void updateApplication(); void updateApplication();
void removeIllegalCharacters(char *name);
void strtrim(char *str);
#endif #endif