Major refactor; see details

* Broke the "prepare" methods up into smaller methods

* Removed the usage of linked lists and replaced them with arrays. Given
that themes won't be added/removed throughout the execution of the
program, we don't need to be able to dynamically add or remove elements
to the list. In addition, once you got to ~50 themes, it took about .2
seconds to iterate through the entire list, which, while it may not
sound like much, is a huge time sink when you're going through a list.
Being able to randomly access any element in the list at the same speed
is hugely beneficial. The downside to this is we need to keep track of
the number of themes/splashes at all times, and, for splashes, have to
do some weird type magic in order to properly iterate over it. However,
these negatives are outweighed by the speed improvements.
This commit is contained in:
2017-07-28 17:41:20 -04:00
parent eb74a8ba02
commit ac69ceda51
7 changed files with 120 additions and 104 deletions

View File

@@ -1,10 +0,0 @@
#include <stdlib.h>
#include "linked_lists.h"
void add_node(node *current, node *new_node)
{
while (current->next != NULL) current = current->next;
current->next = new_node;
}

View File

@@ -1,11 +0,0 @@
#pragma once
#include "3ds.h"
typedef struct
{
void *data;
void *next;
} node;
void add_node(node*, node*);

View File

@@ -16,22 +16,26 @@ int main(void)
fsInit(); fsInit();
ptmSysmInit(); ptmSysmInit();
consoleInit(GFX_TOP, NULL); consoleInit(GFX_TOP, NULL);
prepare_archives();
unzip_themes();
int theme_count = get_number_entries("/Themes");
theme_data **themes_list = calloc(theme_count, sizeof(theme_data));
prepare_themes(themes_list);
int splash_count = get_number_entries("/Splashes");
u16 *splashes_list = calloc(splash_count, PATH_LENGTH);
prepare_splashes(splashes_list);
printf("Theme count: %i\nSplash count: %i\n", theme_count, splash_count);
while (aptMainLoop()) while (aptMainLoop())
{ {
hidScanInput(); hidScanInput();
u32 kDown = hidKeysDown(); u32 kDown = hidKeysDown();
if (kDown & KEY_A) { if (kDown & KEY_A) {
node *theme_node = malloc(sizeof(node)); for (int iter = 0; iter < splash_count; iter++)
theme_node->data = NULL; {
theme_node->next = NULL; printu(&splashes_list[iter * PATH_LENGTH/sizeof(u16)]);
prepareThemes(theme_node); }
node *splashes_node = malloc(sizeof(node));
splashes_node->data = NULL;
splashes_node->next = NULL;
prepare_splashes(splashes_node);
printf("%li\n", shuffle_install(theme_node));
} }
if (kDown & KEY_START) if (kDown & KEY_START)
{ {

View File

@@ -6,9 +6,8 @@
#include "theme.h" #include "theme.h"
#include "unicode.h" #include "unicode.h"
#include "splashes.h" #include "splashes.h"
#include "linked_lists.h"
Result prepare_splashes(node* first_node) Result unzip_splashes()
{ {
Handle splashes_dir; Handle splashes_dir;
FSUSER_OpenDirectory(&splashes_dir, ArchiveSD, fsMakePath(PATH_ASCII, "/Splashes"));; // Open up splashes directory FSUSER_OpenDirectory(&splashes_dir, ArchiveSD, fsMakePath(PATH_ASCII, "/Splashes"));; // Open up splashes directory
@@ -42,7 +41,13 @@ Result prepare_splashes(node* first_node)
} }
} }
FSDIR_Close(splashes_dir); FSDIR_Close(splashes_dir);
}
Result prepare_splashes(u16* splash_list)
{
Handle splashes_dir;
FSUSER_OpenDirectory(&splashes_dir, ArchiveSD, fsMakePath(PATH_ASCII, "/Splashes")); FSUSER_OpenDirectory(&splashes_dir, ArchiveSD, fsMakePath(PATH_ASCII, "/Splashes"));
int iter = 0;
while (true) while (true)
{ {
FS_DirectoryEntry *entry = malloc(sizeof(FS_DirectoryEntry)); FS_DirectoryEntry *entry = malloc(sizeof(FS_DirectoryEntry));
@@ -52,14 +57,9 @@ Result prepare_splashes(node* first_node)
{ {
if (entry->attributes == 1) if (entry->attributes == 1)
{ {
u16 *splash_path = malloc(533); atow(&splash_list[iter * PATH_LENGTH/sizeof(u16)], "/Splashes/");
memset(splash_path, 0, 533); strucat(&splash_list[iter * PATH_LENGTH/sizeof(u16)], entry->name);
atow(splash_path, "/Splashes/"); iter++;
strucat(splash_path, entry->name);
node *current_splash = malloc(sizeof(node));
current_splash->data = splash_path;
current_splash->next = NULL;
add_node(first_node, current_splash);
} }
free(entry); free(entry);
} else { } else {

View File

@@ -1,7 +1,9 @@
#pragma once #pragma once
#include "minizip/unzip.h" #include "minizip/unzip.h"
#include "linked_lists.h"
Result prepare_splashes(node*); #define PATH_LENGTH 524
Result prepare_splashes(u16*);
Result unzip_splashes();
Result install_splash(u16 *); Result install_splash(u16 *);

View File

@@ -6,7 +6,78 @@
#include "theme.h" #include "theme.h"
#include "unicode.h" #include "unicode.h"
#include "minizip/unzip.h" #include "minizip/unzip.h"
#include "linked_lists.h"
Result prepare_archives()
{
Result retValue;
FS_Path home;
FS_Path theme;
CFGU_SecureInfoGetRegion(&regionCode);
switch(regionCode)
{
case 1:
archive1 = 0x000002cd;
archive2 = 0x0000008f;
break;
case 2:
archive1 = 0x000002ce;
archive2 = 0x00000098;
break;
case 3:
archive1 = 0x000002cc;
archive2 = 0x00000082;
break;
default:
archive1 = 0x00;
archive2 = 0x00;
}
retValue = FSUSER_OpenArchive(&ArchiveSD, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""));
if(R_FAILED(retValue)) return retValue;
u32 homeMenuPath[3] = {MEDIATYPE_SD, archive2, 0};
home.type = PATH_BINARY;
home.size = 0xC;
home.data = homeMenuPath;
retValue = FSUSER_OpenArchive(&ArchiveHomeExt, ARCHIVE_EXTDATA, home);
if(R_FAILED(retValue)) return retValue;
u32 themePath[3] = {MEDIATYPE_SD, archive1, 0};
theme.type = PATH_BINARY;
theme.size = 0xC;
theme.data = themePath;
retValue = FSUSER_OpenArchive(&ArchiveThemeExt, ARCHIVE_EXTDATA, theme);
if(R_FAILED(retValue)) return retValue;
return 0;
}
int get_number_entries(char *path)
{
int count = 0;
Handle dir;
FSUSER_OpenDirectory(&dir, ArchiveSD, fsMakePath(PATH_ASCII, path));
while (true)
{
FS_DirectoryEntry *entry = malloc(sizeof(FS_DirectoryEntry));
u32 entries_read;
FSDIR_Read(dir, &entries_read, 1, entry);
if (entries_read)
{
if (entry->attributes == 1)
{
count++;
}
free(entry);
} else {
free(entry);
break;
}
}
FSDIR_Close(dir);
return count;
}
Result extract_current_file(unzFile zip_handle, u16 *theme_path) Result extract_current_file(unzFile zip_handle, u16 *theme_path)
{ {
@@ -109,6 +180,7 @@ Result unzip_file(char* base_path, FS_DirectoryEntry *entry, u16 *sanitized_name
while(unzGoToNextFile(zip_handle) == UNZ_OK) extract_current_file(zip_handle, theme_path_u16); // While next file exists, unzip it while(unzGoToNextFile(zip_handle) == UNZ_OK) extract_current_file(zip_handle, theme_path_u16); // While next file exists, unzip it
unzClose(zip_handle); unzClose(zip_handle);
res = FSUSER_DeleteFile(ArchiveSD, fsMakePath(PATH_ASCII, zipfile)); res = FSUSER_DeleteFile(ArchiveSD, fsMakePath(PATH_ASCII, zipfile));
if (R_FAILED(res)) if (R_FAILED(res))
{ {
free(zipfile); free(zipfile);
@@ -118,52 +190,8 @@ Result unzip_file(char* base_path, FS_DirectoryEntry *entry, u16 *sanitized_name
return MAKERESULT(RL_SUCCESS, RS_SUCCESS, RM_COMMON, RD_SUCCESS); // And return success \o/ return MAKERESULT(RL_SUCCESS, RS_SUCCESS, RM_COMMON, RD_SUCCESS); // And return success \o/
} }
Result prepareThemes(node *first_node) Result unzip_themes()
{ {
printf("Preparing themes...\n");
Result retValue;
FS_Path home;
FS_Path theme;
CFGU_SecureInfoGetRegion(&regionCode);
switch(regionCode)
{
case 1:
archive1 = 0x000002cd;
archive2 = 0x0000008f;
break;
case 2:
archive1 = 0x000002ce;
archive2 = 0x00000098;
break;
case 3:
archive1 = 0x000002cc;
archive2 = 0x00000082;
break;
default:
archive1 = 0x00;
archive2 = 0x00;
}
retValue = FSUSER_OpenArchive(&ArchiveSD, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""));
if(R_FAILED(retValue)) return retValue;
u32 homeMenuPath[3] = {MEDIATYPE_SD, archive2, 0};
home.type = PATH_BINARY;
home.size = 0xC;
home.data = homeMenuPath;
retValue = FSUSER_OpenArchive(&ArchiveHomeExt, ARCHIVE_EXTDATA, home);
if(R_FAILED(retValue)) return retValue;
u32 themePath[3] = {MEDIATYPE_SD, archive1, 0};
theme.type = PATH_BINARY;
theme.size = 0xC;
theme.data = themePath;
retValue = FSUSER_OpenArchive(&ArchiveThemeExt, ARCHIVE_EXTDATA, theme);
if(R_FAILED(retValue)) return retValue;
// This is where the fun begins
Handle themes_dir; Handle themes_dir;
FSUSER_OpenDirectory(&themes_dir, ArchiveSD, fsMakePath(PATH_ASCII, "/Themes")); // Open up the Themes directory and iterate over each file FSUSER_OpenDirectory(&themes_dir, ArchiveSD, fsMakePath(PATH_ASCII, "/Themes")); // Open up the Themes directory and iterate over each file
while (true) while (true)
@@ -196,7 +224,14 @@ Result prepareThemes(node *first_node)
} }
} }
FSDIR_Close(themes_dir); FSDIR_Close(themes_dir);
return 0;
}
Result prepare_themes(theme_data** themes_list)
{
Handle themes_dir;
FSUSER_OpenDirectory(&themes_dir, ArchiveSD, fsMakePath(PATH_ASCII, "/Themes")); FSUSER_OpenDirectory(&themes_dir, ArchiveSD, fsMakePath(PATH_ASCII, "/Themes"));
int iter = 0;
while (true) while (true)
{ {
FS_DirectoryEntry *entry = malloc(sizeof(FS_DirectoryEntry)); FS_DirectoryEntry *entry = malloc(sizeof(FS_DirectoryEntry));
@@ -218,10 +253,7 @@ Result prepareThemes(node *first_node)
/* /*
FOR TESTING PURPOSES ONLY, REMOVE ABOVE LINE LATER!!! FOR TESTING PURPOSES ONLY, REMOVE ABOVE LINE LATER!!!
*/ */
node *current_theme = malloc(sizeof(node)); themes_list[iter++] = theme_info;
current_theme->data = theme_info;
current_theme->next = NULL;
add_node(first_node, current_theme);
} }
free(entry); free(entry);
} else { } else {
@@ -539,23 +571,20 @@ Result themeInstall(theme_data theme_to_install)
return 0; return 0;
} }
Result shuffle_install(node *first_node) Result shuffle_install(theme_data **themes, int len)
{ {
node *current_node = first_node->next;
u8 count = 0; u8 count = 0;
theme_data *themes_to_be_shuffled[10] = {0}; theme_data *themes_to_be_shuffled[10] = {0};
u32 body_sizes[10] = {0}; u32 body_sizes[10] = {0};
u32 bgm_sizes[10] = {0}; u32 bgm_sizes[10] = {0};
// Load themes that are selected for shuffle // Load themes that are selected for shuffle
while (current_node != NULL) for (int iter = 0; iter < len; iter++)
{ {
if (((theme_data*)current_node->data)->selected) count++; if (themes[iter]->selected == true)
count++;
if (count > 10) return(MAKERESULT(RL_USAGE, RS_INVALIDARG, RM_COMMON, RD_INVALID_SELECTION)); if (count > 10) return(MAKERESULT(RL_USAGE, RS_INVALIDARG, RM_COMMON, RD_INVALID_SELECTION));
themes_to_be_shuffled[iter] = themes[iter];
themes_to_be_shuffled[count - 1] = (theme_data *) current_node->data; // -1 because arrays are zero indexed, so the pos is one less than the count
current_node = current_node->next;
} }
// Load and edit SaveData // Load and edit SaveData

View File

@@ -1,7 +1,6 @@
#pragma once #pragma once
#include "minizip/unzip.h" #include "minizip/unzip.h"
#include "linked_lists.h"
struct theme_data struct theme_data
{ {
@@ -24,9 +23,12 @@ FS_Archive ArchiveSD;
FS_Archive ArchiveHomeExt; FS_Archive ArchiveHomeExt;
FS_Archive ArchiveThemeExt; FS_Archive ArchiveThemeExt;
Result prepare_archives();
int get_number_entries(char*);
Result unzip_file(char*, FS_DirectoryEntry*, u16*); Result unzip_file(char*, FS_DirectoryEntry*, u16*);
Result prepareThemes(node*); Result unzip_themes();
Result prepare_themes(theme_data**);
Result themeInstall(theme_data); Result themeInstall(theme_data);
Result shuffle_install(node*); Result shuffle_install(theme_data**, int);
Result closeThemeArchives(); Result closeThemeArchives();
Result parseSmdh(theme_data*, u16*); Result parseSmdh(theme_data*, u16*);