From 4ed0ea3c52652aef0d64b52e3e7e62c61277264a Mon Sep 17 00:00:00 2001 From: Alex Taber Date: Fri, 1 Sep 2017 03:18:06 -0400 Subject: [PATCH] Added splash support --- include/common.h | 3 +- include/draw.h | 4 +- include/splashes.h | 41 ++++++++++++++++++ source/draw.c | 98 ++++++++++++++++++++++++++++++++++------- source/main.c | 101 ++++++++++++++++++++++++++++++++---------- source/splashes.c | 106 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 312 insertions(+), 41 deletions(-) create mode 100644 include/splashes.h create mode 100644 source/splashes.c diff --git a/include/common.h b/include/common.h index 8e3791e..9f954b8 100644 --- a/include/common.h +++ b/include/common.h @@ -33,7 +33,8 @@ #include #include -#define THEMES_PATH "/Themes/" +#define THEMES_PATH "/Themes/" +#define SPLASHES_PATH "/Splashes/" static const int THEMES_PER_SCREEN = 4; diff --git a/include/draw.h b/include/draw.h index 3643add..43f0726 100644 --- a/include/draw.h +++ b/include/draw.h @@ -28,11 +28,13 @@ #define DRAW_H #include "themes.h" +#include "splashes.h" void init_screens(void); void exit_screens(void); -void draw_theme_interface(Theme_s * themes_list, int theme_count, int selected_theme, bool preview_mode); void draw_theme_install(bool shuffle_install); +void draw_theme_interface(Theme_s * themes_list, int theme_count, int selected_theme, bool preview_mode); +void draw_splash_interface(Splash_s *splashes_list, int splash_count, int selected_splash, bool preview_mode); #endif \ No newline at end of file diff --git a/include/splashes.h b/include/splashes.h new file mode 100644 index 0000000..8dde014 --- /dev/null +++ b/include/splashes.h @@ -0,0 +1,41 @@ +/* +* This file is part of Anemone3DS +* Copyright (C) 2016-2017 Alex Taber ("astronautlevel"), Dawid Eckert ("daedreth") +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* +* Additional Terms 7.b and 7.c of GPLv3 apply to this file: +* * Requiring preservation of specified reasonable legal notices or +* author attributions in that material or in the Appropriate Legal +* Notices displayed by works containing it. +* * Prohibiting misrepresentation of the origin of that material, +* or requiring that modified versions of such material be marked in +* reasonable ways as different from the original version. +*/ + +#ifndef SPLASHES_H +#define SPLASHES_H + +#include "common.h" + +typedef struct{ + u16 name[0x106]; + u16 top_path[0x106]; + u16 bottom_path[0x106]; +} Splash_s; + +Result get_splashes(Splash_s** splashes_list, int *splash_count); +void splash_install(Splash_s splash_to_install); + +#endif \ No newline at end of file diff --git a/source/draw.c b/source/draw.c index 97c2e37..c7e9c4f 100644 --- a/source/draw.c +++ b/source/draw.c @@ -69,7 +69,8 @@ static Result MCUHWC_GetBatteryLevel(u8 *out) // Code taken from daedreth's fork #undef TRY } -static int vertical_scroll = 0; +static int theme_vertical_scroll = 0; +static int splash_vertical_scroll = 0; void draw_base_interface(void) { @@ -138,6 +139,9 @@ void draw_theme_interface(Theme_s * themes_list, int theme_count, int selected_t utf16_to_utf32((u32*)description, current_theme.desc, 0x80); pp2d_draw_wtext(20, 65, 0.5, 0.5, COLOR_WHITE, description); + pp2d_draw_wtext_center(GFX_TOP, 150, 0.7, 0.7, COLOR_WHITE, L"\uE000 Install Theme \uE004 Switch to Splashes"); + pp2d_draw_wtext_center(GFX_TOP, 180, 0.7, 0.7, COLOR_WHITE, L"\uE001 Queue Shuffle \uE046 Install shuffle"); + pp2d_draw_wtext_center(GFX_TOP, 210, 0.7, 0.7, COLOR_WHITE, L"\uE003 Preview Theme"); pp2d_draw_on(GFX_BOTTOM); @@ -147,23 +151,24 @@ void draw_theme_interface(Theme_s * themes_list, int theme_count, int selected_t if (theme_count <= THEMES_PER_SCREEN) break; - if (vertical_scroll > selected_theme) - vertical_scroll--; + if (theme_vertical_scroll > selected_theme) + theme_vertical_scroll--; if ((i < selected_theme) && \ - ((selected_theme - vertical_scroll) >= THEMES_PER_SCREEN) && \ - (vertical_scroll != ( - THEMES_PER_SCREEN))) - vertical_scroll++; + ((selected_theme - theme_vertical_scroll) >= THEMES_PER_SCREEN) && \ + (theme_vertical_scroll != ( - THEMES_PER_SCREEN))) + theme_vertical_scroll++; } //---------------------------------------------------------------- // Show arrows if there are themes out of bounds //---------------------------------------------------------------- - pp2d_draw_rectangle(0, 0, 320, 24, COLOR_ACCENT); - pp2d_draw_rectangle(0, 216, 320, 24, COLOR_ACCENT); - //---------------------------------------------------------------- + if (theme_vertical_scroll > 0) + pp2d_draw_texture(TEXTURE_ARROW, 155, 6); + if (theme_vertical_scroll + THEMES_PER_SCREEN < theme_count) + pp2d_draw_texture_flip(TEXTURE_ARROW, 155, 224, VERTICAL); - for (int i = vertical_scroll; i < (THEMES_PER_SCREEN + vertical_scroll); i++) + for (int i = theme_vertical_scroll; i < (THEMES_PER_SCREEN + theme_vertical_scroll); i++) { if (i >= theme_count) break; @@ -172,22 +177,85 @@ void draw_theme_interface(Theme_s * themes_list, int theme_count, int selected_t wchar_t name[0x80] = {0}; utf16_to_utf32((u32*)name, current_theme.name, 0x80); - int vertical_offset = 48 * (i-vertical_scroll); - u32 front_color = COLOR_WHITE; + int vertical_offset = 48 * (i-theme_vertical_scroll); + u32 font_color = COLOR_WHITE; if (i == selected_theme) { - front_color = COLOR_BLACK; + font_color = COLOR_BLACK; pp2d_draw_rectangle(0, 24 + vertical_offset, 320, 48, COLOR_CURSOR); } - pp2d_draw_wtext(54, 40 + vertical_offset, 0.55, 0.55, front_color, name); + pp2d_draw_wtext(54, 40 + vertical_offset, 0.55, 0.55, font_color, name); if (current_theme.has_icon) pp2d_draw_texture(current_theme.icon_id, 0, 24 + vertical_offset); if (current_theme.in_shuffle) - pp2d_draw_texture_blend(TEXTURE_SHUFFLE, 280, 32 + vertical_offset, front_color); + pp2d_draw_texture_blend(TEXTURE_SHUFFLE, 280, 32 + vertical_offset, font_color); } } pp2d_end_draw(); } + +void draw_splash_interface(Splash_s *splashes_list, int splash_count, int selected_splash, bool preview_mode) +{ + if (splashes_list == NULL) + { + pp2d_begin_draw(GFX_TOP); + pp2d_draw_text_center(GFX_TOP, 100, 1, 1, COLOR_WHITE, "FAILURE"); + pp2d_end_draw(); + return; + } + + Splash_s current_splash = splashes_list[selected_splash]; + + if (preview_mode) + { + // TODO: Splash Previews + } else { + draw_base_interface(); + pp2d_draw_text_center(GFX_TOP, 4, 0.5, 0.5, COLOR_WHITE, "Splash mode"); + + pp2d_draw_wtext_center(GFX_TOP, 210, 0.7, 0.7, COLOR_WHITE, L"\uE000 Install Splash \uE004 Switch to Themes"); + + pp2d_draw_on(GFX_BOTTOM); + for (int i = 0; i < splash_count; i++) { + if (splash_count <= THEMES_PER_SCREEN) + break; + + if (splash_vertical_scroll > selected_splash) + splash_vertical_scroll--; + + if ((i < selected_splash) && \ + ((selected_splash - splash_vertical_scroll) >= THEMES_PER_SCREEN) && \ + (splash_vertical_scroll != ( - THEMES_PER_SCREEN))) + splash_vertical_scroll++; + } + + if (splash_vertical_scroll > 0) + pp2d_draw_texture(TEXTURE_ARROW, 155, 6); + if (splash_vertical_scroll + THEMES_PER_SCREEN < splash_count) + pp2d_draw_texture_flip(TEXTURE_ARROW, 155, 224, VERTICAL); + + for (int i = splash_vertical_scroll; i < (THEMES_PER_SCREEN + splash_vertical_scroll); i++) + { + if (i >= splash_count) + break; + + current_splash = splashes_list[i]; + wchar_t name[0x106] = {0}; + utf16_to_utf32((u32*)name, current_splash.name, 0x106); + + int vertical_offset = 48 * (i-splash_vertical_scroll); + u32 font_color = COLOR_WHITE; + + if (i == selected_splash) + { + font_color = COLOR_BLACK; + pp2d_draw_rectangle(0, 24 + vertical_offset, 320, 48, COLOR_CURSOR); + } + pp2d_draw_wtext(15, 40 + vertical_offset, 0.55, 0.55, font_color, name); + } + } + pp2d_end_draw(); +} diff --git a/source/main.c b/source/main.c index 99e5df1..5015cd1 100644 --- a/source/main.c +++ b/source/main.c @@ -26,6 +26,7 @@ #include "fs.h" #include "themes.h" +#include "splashes.h" #include "draw.h" int init_services(void) @@ -47,6 +48,7 @@ int main(void) { init_services(); init_screens(); + int theme_count = 0; Theme_s * themes_list = NULL; @@ -57,7 +59,18 @@ int main(void) free(themes_list); themes_list = NULL; } - + int splash_count = 0; + Splash_s *splashes_list = NULL; + res = get_splashes(&splashes_list, &splash_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; + } + + bool splash_mode = false; + int selected_splash = 0; int selected_theme = 0; int shuffle_theme_count = 0; bool preview_mode = false; @@ -67,12 +80,17 @@ int main(void) hidScanInput(); u32 kDown = hidKeysDown(); - draw_theme_interface(themes_list, theme_count, selected_theme, preview_mode); + if (!splash_mode) draw_theme_interface(themes_list, theme_count, selected_theme, preview_mode); + else draw_splash_interface(splashes_list, splash_count, selected_splash, preview_mode); - if (themes_list == NULL) + if (themes_list == NULL && !splash_mode) continue; + if (splashes_list == NULL && splash_mode) + continue; + Theme_s * current_theme = &themes_list[selected_theme]; + Splash_s *current_splash = &splashes_list[selected_splash]; if (kDown & KEY_Y) { @@ -93,61 +111,96 @@ int main(void) continue; // Actions + else if (kDown & KEY_L) + { + splash_mode = !splash_mode; + } else if (kDown & KEY_X) { // install_bgm(current_theme); } else if (kDown & KEY_A) { - draw_theme_install(false); - single_install(*current_theme); + if (splash_mode) + { + splash_install(*current_splash); + } else { + draw_theme_install(false); + single_install(*current_theme); + } } else if (kDown & KEY_B) { - if (shuffle_theme_count < 10) + if (splash_mode) { - if (current_theme->in_shuffle) shuffle_theme_count--; - else shuffle_theme_count++; - current_theme->in_shuffle = !(current_theme->in_shuffle); + } else { - if (current_theme->in_shuffle) { - shuffle_theme_count--; - current_theme->in_shuffle = false; - } + if (shuffle_theme_count < 10) + { + if (current_theme->in_shuffle) shuffle_theme_count--; + else shuffle_theme_count++; + current_theme->in_shuffle = !(current_theme->in_shuffle); + } else { + if (current_theme->in_shuffle) { + shuffle_theme_count--; + current_theme->in_shuffle = false; + } + } } } else if (kDown & KEY_SELECT) { - if (shuffle_theme_count > 0) + if (splash_mode) { - draw_theme_install(true); - shuffle_install(themes_list, theme_count); + + } else { + if (shuffle_theme_count > 0) + { + draw_theme_install(true); + shuffle_install(themes_list, theme_count); + } } } // Movement in the UI else if (kDown & KEY_DOWN) { - selected_theme++; - if (selected_theme >= theme_count) - selected_theme = theme_count-1; + if (splash_mode) + { + selected_splash++; + if (selected_splash >= splash_count) + selected_splash = splash_count-1; + } else { + selected_theme++; + if (selected_theme >= theme_count) + selected_theme = theme_count-1; + } } else if (kDown & KEY_UP) { - selected_theme--; - if (selected_theme < 0) - selected_theme = 0; + if (splash_mode) + { + selected_splash--; + if (selected_splash < 0) + selected_splash = 0; + } else { + selected_theme--; + if (selected_theme < 0) + selected_theme = 0; + } } // Quick moving else if (kDown & KEY_LEFT) { - selected_theme = 0; + if (splash_mode) selected_splash = 0; + else selected_theme = 0; } else if (kDown & KEY_RIGHT) { - selected_theme = theme_count-1; + if (splash_mode) selected_splash = splash_count - 1; + else selected_theme = theme_count-1; } if (kDown & KEY_START) diff --git a/source/splashes.c b/source/splashes.c new file mode 100644 index 0000000..81f2275 --- /dev/null +++ b/source/splashes.c @@ -0,0 +1,106 @@ +/* +* This file is part of Anemone3DS +* Copyright (C) 2016-2017 Alex Taber ("astronautlevel"), Dawid Eckert ("daedreth") +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* +* Additional Terms 7.b and 7.c of GPLv3 apply to this file: +* * Requiring preservation of specified reasonable legal notices or +* author attributions in that material or in the Appropriate Legal +* Notices displayed by works containing it. +* * Prohibiting misrepresentation of the origin of that material, +* or requiring that modified versions of such material be marked in +* reasonable ways as different from the original version. +*/ +#include "splashes.h" +#include "unicode.h" +#include "fs.h" + +Result get_splashes(Splash_s** splashes_list, int *splash_count) +{ + Result res = 0; + Handle dir_handle; + res = FSUSER_OpenDirectory(&dir_handle, ArchiveSD, fsMakePath(PATH_ASCII, SPLASHES_PATH)); + if (R_FAILED(res)) + return res; + + u32 entries_read = 1; + while (entries_read) + { + FS_DirectoryEntry entry = {0}; + res = FSDIR_Read(dir_handle, &entries_read, 1, &entry); + if (R_FAILED(res) || entries_read == 0) + break; + + if (!(entry.attributes & FS_ATTRIBUTE_DIRECTORY)) + continue; + + *splash_count += entries_read; + *splashes_list= realloc(*splashes_list, (*splash_count) * sizeof(Splash_s)); + if (splashes_list == NULL) + break; + + Splash_s *current_splash = &(*splashes_list)[*splash_count-1]; + memset(current_splash, 0, sizeof(Splash_s)); + + u16 splash_path[0x106] = {0}; + struacat(splash_path, SPLASHES_PATH); + strucat(splash_path, entry.name); + u16 top_path[0x106] = {0}; + memcpy(top_path, splash_path, 0x106); + struacat(top_path, "/splash.bin"); + u16 bottom_path[0x106] = {0}; + memcpy(bottom_path, splash_path, 0x106); + struacat(bottom_path, "/splashbottom.bin"); + + char *temp_buf = NULL; + u32 bytes = file_to_buf(fsMakePath(PATH_UTF16, top_path), ArchiveSD, &temp_buf); + if (!bytes) + { + memset(top_path, 0, 0x106); + } + free(temp_buf); + temp_buf = NULL; + bytes = file_to_buf(fsMakePath(PATH_UTF16, bottom_path), ArchiveSD, &temp_buf); + if (!bytes) + { + memset(bottom_path, 0, 0x106); + } + free(temp_buf); + memcpy(current_splash->name, entry.name, 0x106); + memcpy(current_splash->top_path, top_path, 0x106); + memcpy(current_splash->bottom_path, bottom_path, 0x106); + } + FSDIR_Close(dir_handle); + + return res; +} + +void splash_install(Splash_s splash_to_install) +{ + char *screen_buf; + u32 size = file_to_buf(fsMakePath(PATH_UTF16, splash_to_install.top_path), ArchiveSD, &screen_buf); + if (size) + { + buf_to_file(size, "/luma/splash.bin", ArchiveSD, screen_buf); + free(screen_buf); + } + + size = file_to_buf(fsMakePath(PATH_UTF16, splash_to_install.bottom_path), ArchiveSD, &screen_buf); + if (size) + { + buf_to_file(size, "/luma/splashbottom.bin", ArchiveSD, screen_buf); + free(screen_buf); + } +} \ No newline at end of file