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:
LiquidFenrir
2017-09-01 03:57:08 +02:00
committed by Alex Taber
parent 4811fa1c4c
commit 70e086b20c
10 changed files with 117 additions and 68 deletions

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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);
} }