adds dynamic preview loading and silence minizip warnings (#11)
* make use of the return value for safety * get rid of warnings (sizeof(wchar_t) is the same as sizeof(u32), so no problem there) * dynamic preview loading fix crash when too many themes have previews available
This commit is contained in:
@@ -41,7 +41,7 @@ enum TextureID {
|
|||||||
TEXTURE_FONT_RESERVED = 0, //used by pp2d for the font
|
TEXTURE_FONT_RESERVED = 0, //used by pp2d for the font
|
||||||
TEXTURE_ARROW,
|
TEXTURE_ARROW,
|
||||||
TEXTURE_SHUFFLE,
|
TEXTURE_SHUFFLE,
|
||||||
MAX_TEXTURE,
|
TEXTURE_PREVIEW,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -38,14 +38,14 @@ typedef struct {
|
|||||||
ssize_t icon_id;
|
ssize_t icon_id;
|
||||||
|
|
||||||
bool has_preview;
|
bool has_preview;
|
||||||
ssize_t preview_id;
|
|
||||||
|
|
||||||
u16 path[262];
|
u16 path[0x106];
|
||||||
bool is_zip;
|
bool is_zip;
|
||||||
|
|
||||||
bool in_shuffle;
|
bool in_shuffle;
|
||||||
} Theme_s;
|
} Theme_s;
|
||||||
|
|
||||||
|
void load_theme_preview(Theme_s *theme);
|
||||||
Result get_themes(Theme_s **themes_list, int *theme_count);
|
Result get_themes(Theme_s **themes_list, int *theme_count);
|
||||||
Result single_install(Theme_s theme);
|
Result single_install(Theme_s theme);
|
||||||
Result shuffle_install(Theme_s *themes_list, int theme_count);
|
Result shuffle_install(Theme_s *themes_list, int theme_count);
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
ssize_t strulen(u16*, ssize_t);
|
ssize_t strulen(const u16*, ssize_t);
|
||||||
void struacat(u16 *input, const char *addition);
|
void struacat(u16 *input, const char *addition);
|
||||||
void printu(u16 *input);
|
void printu(u16 *input);
|
||||||
u16 *strucat(u16 *destination, const u16 *source);
|
u16 *strucat(u16 *destination, const u16 *source);
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ void draw_interface(Theme_s * themes_list, int theme_count, int selected_theme,
|
|||||||
{
|
{
|
||||||
if (current_theme.has_preview)
|
if (current_theme.has_preview)
|
||||||
{
|
{
|
||||||
pp2d_draw_texture_part(current_theme.preview_id, 0, 0, 6, 0, 400, 240);
|
pp2d_draw_texture_part(TEXTURE_PREVIEW, 0, 0, 6, 0, 400, 240);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -119,7 +119,7 @@ void draw_interface(Theme_s * themes_list, int theme_count, int selected_theme,
|
|||||||
if (current_theme.has_preview)
|
if (current_theme.has_preview)
|
||||||
{
|
{
|
||||||
//skip the weird 6 pixels to the left
|
//skip the weird 6 pixels to the left
|
||||||
pp2d_texture_select_part(current_theme.preview_id, 220, 35, 6, 0, 400, 480);
|
pp2d_texture_select_part(TEXTURE_PREVIEW, 220, 35, 6, 0, 400, 480);
|
||||||
pp2d_texture_scale(0.4, 0.4);
|
pp2d_texture_scale(0.4, 0.4);
|
||||||
pp2d_texture_draw();
|
pp2d_texture_draw();
|
||||||
}
|
}
|
||||||
@@ -131,7 +131,7 @@ void draw_interface(Theme_s * themes_list, int theme_count, int selected_theme,
|
|||||||
{
|
{
|
||||||
if (current_theme.has_preview)
|
if (current_theme.has_preview)
|
||||||
{
|
{
|
||||||
pp2d_draw_texture_part(current_theme.preview_id, 0, 0, 46, 240, 320, 240);
|
pp2d_draw_texture_part(TEXTURE_PREVIEW, 0, 0, 46, 240, 320, 240);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -50,8 +50,15 @@ int main(void)
|
|||||||
int theme_count = 0;
|
int theme_count = 0;
|
||||||
Theme_s * themes_list = NULL;
|
Theme_s * themes_list = NULL;
|
||||||
Result res = get_themes(&themes_list, &theme_count);
|
Result res = get_themes(&themes_list, &theme_count);
|
||||||
|
if (R_FAILED(res))
|
||||||
|
{
|
||||||
|
//don't need to worry about possible textures (icons, previews), that's freed by pp2d itself
|
||||||
|
free(themes_list);
|
||||||
|
themes_list = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int selected_theme = 0;
|
int selected_theme = 0;
|
||||||
|
int previously_selected = ~selected_theme; //make sure it loads the preview the first time
|
||||||
bool preview_mode = false;
|
bool preview_mode = false;
|
||||||
|
|
||||||
while(aptMainLoop())
|
while(aptMainLoop())
|
||||||
@@ -124,6 +131,15 @@ int main(void)
|
|||||||
{
|
{
|
||||||
selected_theme = theme_count-1;
|
selected_theme = theme_count-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if the selected theme changed, load the preview
|
||||||
|
if (selected_theme != previously_selected)
|
||||||
|
{
|
||||||
|
current_theme->has_preview = false; //will be freed anyway
|
||||||
|
current_theme = &themes_list[selected_theme]; //update current_theme
|
||||||
|
load_theme_preview(current_theme);
|
||||||
|
previously_selected = selected_theme;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(themes_list);
|
free(themes_list);
|
||||||
|
|||||||
@@ -11,6 +11,14 @@
|
|||||||
See the accompanying LICENSE file for the full text of the license.
|
See the accompanying LICENSE file for the full text of the license.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//taken and adapted from https://stackoverflow.com/a/13492589
|
||||||
|
|
||||||
|
// save diagnostic state
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
|
||||||
|
// turn off the specific warning. Can also use "-Wall"
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -367,3 +375,6 @@ void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def)
|
|||||||
pzlib_filefunc_def->zerror_file = ferror_file_func;
|
pzlib_filefunc_def->zerror_file = ferror_file_func;
|
||||||
pzlib_filefunc_def->opaque = NULL;
|
pzlib_filefunc_def->opaque = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// turn the warnings back on
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
|||||||
@@ -18,6 +18,13 @@
|
|||||||
with.
|
with.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//taken and adapted from https://stackoverflow.com/a/13492589
|
||||||
|
|
||||||
|
// save diagnostic state
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
|
||||||
|
// turn off the specific warning. Can also use "-Wall"
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -190,3 +197,6 @@ void fill_memory_filefunc (pzlib_filefunc_def, ourmem)
|
|||||||
pzlib_filefunc_def->zerror_file = ferror_mem_func;
|
pzlib_filefunc_def->zerror_file = ferror_mem_func;
|
||||||
pzlib_filefunc_def->opaque = ourmem;
|
pzlib_filefunc_def->opaque = ourmem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// turn the warnings back on
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
|||||||
@@ -21,6 +21,14 @@
|
|||||||
access functions to crctables and pkeys
|
access functions to crctables and pkeys
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//taken and adapted from https://stackoverflow.com/a/13492589
|
||||||
|
|
||||||
|
// save diagnostic state
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
|
||||||
|
// turn off the specific warning. Can also use "-Wall"
|
||||||
|
#pragma GCC diagnostic ignored "-Wtype-limits"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -1949,3 +1957,6 @@ extern int ZEXPORT unzeof(unzFile file)
|
|||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// turn the warnings back on
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
|||||||
119
source/themes.c
119
source/themes.c
@@ -31,19 +31,74 @@
|
|||||||
#include "pp2d/pp2d/pp2d.h"
|
#include "pp2d/pp2d/pp2d.h"
|
||||||
#include "pp2d/pp2d/lodepng.h"
|
#include "pp2d/pp2d/lodepng.h"
|
||||||
|
|
||||||
static void parse_smdh(Theme_s *theme, u16 *path, ssize_t textureID)
|
void load_theme_preview(Theme_s *theme)
|
||||||
|
{
|
||||||
|
//free the previously loaded preview. wont do anything if there wasnt one
|
||||||
|
pp2d_free_texture(TEXTURE_PREVIEW);
|
||||||
|
|
||||||
|
char *preview_buffer = NULL;
|
||||||
|
u64 size = 0;
|
||||||
|
if (!(theme->is_zip))
|
||||||
|
{
|
||||||
|
u16 path_to_preview[0x106] = {0};
|
||||||
|
strucat(path_to_preview, theme->path);
|
||||||
|
struacat(path_to_preview, "/preview.png");
|
||||||
|
size = file_to_buf(fsMakePath(PATH_UTF16, path_to_preview), ArchiveSD, &preview_buffer);
|
||||||
|
} else {
|
||||||
|
size = zip_file_to_buf("preview.png", theme->path, &preview_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!size)
|
||||||
|
{
|
||||||
|
free(preview_buffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 * image = NULL;
|
||||||
|
unsigned int width = 0, height = 0;
|
||||||
|
|
||||||
|
int result = lodepng_decode32(&image, &width, &height, (u8*)preview_buffer, size);
|
||||||
|
if (result == 0) // no error
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < width; i++)
|
||||||
|
{
|
||||||
|
for (u32 j = 0; j < height; j++)
|
||||||
|
{
|
||||||
|
u32 p = (i + j*width) * 4;
|
||||||
|
|
||||||
|
u8 r = *(u8*)(image + p);
|
||||||
|
u8 g = *(u8*)(image + p + 1);
|
||||||
|
u8 b = *(u8*)(image + p + 2);
|
||||||
|
u8 a = *(u8*)(image + p + 3);
|
||||||
|
|
||||||
|
*(image + p) = a;
|
||||||
|
*(image + p + 1) = b;
|
||||||
|
*(image + p + 2) = g;
|
||||||
|
*(image + p + 3) = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
theme->has_preview = true;
|
||||||
|
pp2d_load_texture_memory(TEXTURE_PREVIEW, image, (u32)width, (u32)height);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(image);
|
||||||
|
free(preview_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse_smdh(Theme_s *theme, ssize_t textureID)
|
||||||
{
|
{
|
||||||
char *info_buffer = NULL;
|
char *info_buffer = NULL;
|
||||||
u64 size = 0;
|
u64 size = 0;
|
||||||
if (!(theme->is_zip))
|
if (!(theme->is_zip))
|
||||||
{
|
{
|
||||||
u16 path_to_smdh[0x106] = {0};
|
u16 path_to_smdh[0x106] = {0};
|
||||||
strucat(path_to_smdh, path);
|
strucat(path_to_smdh, theme->path);
|
||||||
struacat(path_to_smdh, "/info.smdh");
|
struacat(path_to_smdh, "/info.smdh");
|
||||||
|
|
||||||
size = file_to_buf(fsMakePath(PATH_UTF16, path_to_smdh), ArchiveSD, &info_buffer);
|
size = file_to_buf(fsMakePath(PATH_UTF16, path_to_smdh), ArchiveSD, &info_buffer);
|
||||||
} else {
|
} else {
|
||||||
size = zip_file_to_buf("info.smdh", path, &info_buffer);
|
size = zip_file_to_buf("info.smdh", theme->path, &info_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!size)
|
if (!size)
|
||||||
@@ -87,59 +142,6 @@ static void parse_smdh(Theme_s *theme, u16 *path, ssize_t textureID)
|
|||||||
free(info_buffer);
|
free(info_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void load_preview(Theme_s *theme, u16 *path, ssize_t textureID)
|
|
||||||
{
|
|
||||||
char *preview_buffer = NULL;
|
|
||||||
u64 size = 0;
|
|
||||||
if (!(theme->is_zip))
|
|
||||||
{
|
|
||||||
u16 path_to_preview[0x106] = {0};
|
|
||||||
strucat(path_to_preview, path);
|
|
||||||
struacat(path_to_preview, "/preview.png");
|
|
||||||
size = file_to_buf(fsMakePath(PATH_UTF16, path_to_preview), ArchiveSD, &preview_buffer);
|
|
||||||
} else {
|
|
||||||
size = zip_file_to_buf("preview.png", path, &preview_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!size)
|
|
||||||
{
|
|
||||||
free(preview_buffer);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 * image = NULL;
|
|
||||||
unsigned int width = 0, height = 0;
|
|
||||||
|
|
||||||
int result = lodepng_decode32(&image, &width, &height, (u8*)preview_buffer, size);
|
|
||||||
if (result == 0) // no error
|
|
||||||
{
|
|
||||||
for (u32 i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
for (u32 j = 0; j < height; j++)
|
|
||||||
{
|
|
||||||
u32 p = (i + j*width) * 4;
|
|
||||||
|
|
||||||
u8 r = *(u8*)(image + p);
|
|
||||||
u8 g = *(u8*)(image + p + 1);
|
|
||||||
u8 b = *(u8*)(image + p + 2);
|
|
||||||
u8 a = *(u8*)(image + p + 3);
|
|
||||||
|
|
||||||
*(image + p) = a;
|
|
||||||
*(image + p + 1) = b;
|
|
||||||
*(image + p + 2) = g;
|
|
||||||
*(image + p + 3) = r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
theme->has_preview = true;
|
|
||||||
pp2d_load_texture_memory(textureID, image, (u32)width, (u32)height);
|
|
||||||
theme->preview_id = textureID;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(image);
|
|
||||||
free(preview_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result get_themes(Theme_s **themes_list, int *theme_count)
|
Result get_themes(Theme_s **themes_list, int *theme_count)
|
||||||
{
|
{
|
||||||
Result res = 0;
|
Result res = 0;
|
||||||
@@ -177,9 +179,8 @@ Result get_themes(Theme_s **themes_list, int *theme_count)
|
|||||||
memcpy(current_theme->path, theme_path, 0x106 * sizeof(u16));
|
memcpy(current_theme->path, theme_path, 0x106 * sizeof(u16));
|
||||||
current_theme->is_zip = !strcmp(entry.shortExt, "ZIP");
|
current_theme->is_zip = !strcmp(entry.shortExt, "ZIP");
|
||||||
|
|
||||||
ssize_t textureID = MAX_TEXTURE + (*theme_count * 2);
|
ssize_t iconID = TEXTURE_PREVIEW + *theme_count;
|
||||||
parse_smdh(current_theme, theme_path, textureID);
|
parse_smdh(current_theme, iconID);
|
||||||
load_preview(current_theme, theme_path, textureID+1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FSDIR_Close(dir_handle);
|
FSDIR_Close(dir_handle);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
#include "unicode.h"
|
#include "unicode.h"
|
||||||
|
|
||||||
ssize_t strulen(u16 *input, ssize_t max_len)
|
ssize_t strulen(const u16 *input, ssize_t max_len)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < max_len; i++) if (input[i] == 0) return i;
|
for (int i = 0; i < max_len; i++) if (input[i] == 0) return i;
|
||||||
return max_len;
|
return max_len;
|
||||||
@@ -47,7 +47,7 @@ void printu(u16 *input)
|
|||||||
ssize_t in_len = strulen(input, 0x106);
|
ssize_t in_len = strulen(input, 0x106);
|
||||||
ssize_t buf_len = in_len + 1; // Plus 1 for proper null termination
|
ssize_t buf_len = in_len + 1; // Plus 1 for proper null termination
|
||||||
wchar_t *buf = calloc(buf_len, sizeof(wchar_t));
|
wchar_t *buf = calloc(buf_len, sizeof(wchar_t));
|
||||||
utf16_to_utf32(buf, input, buf_len);
|
utf16_to_utf32((u32*)buf, input, buf_len);
|
||||||
printf("%ls\n", buf);
|
printf("%ls\n", buf);
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user