diff --git a/assets/back.png b/assets/back.png
new file mode 100644
index 0000000..acb3d95
Binary files /dev/null and b/assets/back.png differ
diff --git a/assets/bgm_only.png b/assets/bgm_only.png
new file mode 100644
index 0000000..5fa9eed
Binary files /dev/null and b/assets/bgm_only.png differ
diff --git a/assets/dump.png b/assets/dump.png
new file mode 100644
index 0000000..195fd28
Binary files /dev/null and b/assets/dump.png differ
diff --git a/assets/download.png b/assets/install.png
similarity index 100%
rename from assets/download.png
rename to assets/install.png
diff --git a/assets/list.png b/assets/menu.png
similarity index 100%
rename from assets/list.png
rename to assets/menu.png
diff --git a/assets/qr.png b/assets/qr.png
new file mode 100644
index 0000000..c6615ef
Binary files /dev/null and b/assets/qr.png differ
diff --git a/assets/sprites.t3s b/assets/sprites.t3s
index 86b990d..ce0db62 100644
--- a/assets/sprites.t3s
+++ b/assets/sprites.t3s
@@ -11,10 +11,10 @@ battery4.png
battery5.png
browse.png
charging.png
-download.png
+install.png
exit.png
installed.png
-list.png
+menu.png
no_home.png
preview.png
select.png
@@ -22,3 +22,7 @@ shuffle.png
shuffle_no_bgm.png
sort.png
start.png
+qr.png
+bgm_only.png
+back.png
+dump.png
diff --git a/include/common.h b/include/common.h
index 9e1abcc..609242b 100644
--- a/include/common.h
+++ b/include/common.h
@@ -54,6 +54,8 @@ static inline int max(const int a, const int b)
#define FASTSCROLL_WAIT 1e8
+#define BETWEEN(min, x, max) (min < x && x < max)
+
typedef enum {
MODE_THEMES = 0,
MODE_SPLASHES,
@@ -61,6 +63,14 @@ typedef enum {
MODE_AMOUNT,
} EntryMode;
+typedef enum {
+ DRAW_MODE_LIST = 0,
+ DRAW_MODE_INSTALL,
+ DRAW_MODE_EXTRA,
+
+ DRAW_MODE_AMOUNT,
+} DrawMode;
+
extern const char * main_paths[MODE_AMOUNT];
extern const int entries_per_screen_v[MODE_AMOUNT];
extern const int entries_per_screen_h[MODE_AMOUNT];
diff --git a/include/conversion.h b/include/conversion.h
index e2976dd..bc5d23f 100644
--- a/include/conversion.h
+++ b/include/conversion.h
@@ -4,6 +4,6 @@
#include "common.h"
size_t bin_to_abgr(char ** bufp, size_t size);
-size_t png_to_abgr(char ** bufp, size_t size);
+size_t png_to_abgr(char ** bufp, size_t size, u32 *height);
-#endif
\ No newline at end of file
+#endif
diff --git a/include/draw.h b/include/draw.h
index 2c02c96..7d1e7aa 100644
--- a/include/draw.h
+++ b/include/draw.h
@@ -163,7 +163,7 @@ void end_frame(void);
void set_screen(C3D_RenderTarget * screen);
void throw_error(const char * error, ErrorLevel level);
-bool draw_confirm(const char * conf_msg, Entry_List_s * list);
+bool draw_confirm(const char * conf_msg, Entry_List_s * list, DrawMode draw_mode);
void draw_preview(C2D_Image preview, int preview_offset);
@@ -178,6 +178,6 @@ void draw_home(u64 start_time, u64 cur_time);
void draw_base_interface(void);
void draw_grid_interface(Entry_List_s * list, Instructions_s instructions);
-void draw_interface(Entry_List_s * list, Instructions_s instructions);
+void draw_interface(Entry_List_s * list, Instructions_s instructions, DrawMode draw_mode);
#endif
diff --git a/include/instructions.h b/include/instructions.h
deleted file mode 100644
index 5d7cc36..0000000
--- a/include/instructions.h
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
-* This file is part of Anemone3DS
-* Copyright (C) 2016-2020 Contributors in CONTRIBUTORS.md
-*
-* 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 INSTRUCTIONS_H
-#define INSTRUCTIONS_H
-
-#include "draw.h"
-#include "colors.h"
-
-Instructions_s normal_instructions[MODE_AMOUNT] = {
- {
- .info_line = NULL,
- .instructions = {
- {
- "\uE000 Hold to install",
- "\uE001 Queue shuffle theme"
- },
- {
- "\uE002 Hold for more",
- "\uE003 Preview theme"
- },
- {
- "\uE004 Switch to splashes",
- "\uE005 Scan QR code"
- },
- {
- "Exit",
- "Delete from SD"
- }
- }
- },
- {
- .info_line = NULL,
- .instructions = {
- {
- "\uE000 Install splash",
- "\uE001 Delete installed splash"
- },
- {
- "\uE002 Hold for more",
- "\uE003 Preview splash"
- },
- {
- "\uE004 Switch to themes",
- "\uE005 Scan QR code"
- },
- {
- "Exit",
- "Delete from SD"
- }
- }
- }
-};
-
-Instructions_s install_instructions = {
- .info_line = "Release \uE000 to cancel or hold \uE006 and release \uE000 to install",
- .instructions = {
- {
- "\uE079 Normal install",
- "\uE07A Shuffle install"
- },
- {
- "\uE07B BGM-only install",
- "\uE07C No-BGM install"
- },
- {
- NULL,
- NULL
- },
- {
- "Exit",
- NULL
- }
- }
-};
-
-Instructions_s extra_instructions[3] = {
- {
- .info_line = "Release \uE002 to cancel or hold \uE006 and release \uE002 to sort",
- .instructions = {
- {
- "\uE079 Sort by name",
- "\uE07A Sort by author"
- },
- {
- "\uE07B Sort by filename",
- NULL
- },
- {
- NULL,
- NULL
- },
- {
- "Exit",
- NULL
- }
- }
- },
- {
- .info_line = "Release \uE002 to cancel or hold \uE006 and release \uE002 to do stuff",
- .instructions = {
- {
- "\uE079 Jump in the list",
- "\uE07A Reload broken icons"
- },
- {
- "\uE07B Browse ThemePlaza",
- NULL
- },
- {
- "\uE004 Sorting menu",
- "\uE005 Dumping menu"
- },
- {
- "Exit",
- NULL
- }
- }
- },
- {
- .info_line = "Release \uE002 to cancel or hold \uE006 and release \uE002 to dump",
- .instructions = {
- {
- "\uE079 Dump Current Theme",
- "\uE07A Dump All Themes"
- },
- {
- NULL,
- NULL
- },
- {
- NULL,
- NULL
- },
- {
- "Exit",
- NULL
- }
- }
- }
-};
-
-#endif
diff --git a/include/loading.h b/include/loading.h
index 5855566..9363608 100644
--- a/include/loading.h
+++ b/include/loading.h
@@ -68,7 +68,7 @@ void copy_texture_data(C3D_Tex * texture, const u16 * src, const Entry_Icon_s *
void parse_smdh(Icon_s * icon, Entry_s * entry, const u16 * fallback_name);
-bool load_preview_from_buffer(char * row_pointers, u32 size, C2D_Image * preview_image, int * preview_offset);
+bool load_preview_from_buffer(char * row_pointers, u32 size, C2D_Image * preview_image, int * preview_offset, int height);
bool load_preview(const Entry_List_s * list, C2D_Image * preview_image, int * preview_offset);
void free_preview(C2D_Image preview_image);
Result load_audio(const Entry_s *, audio_s *);
diff --git a/include/ui_strings.h b/include/ui_strings.h
new file mode 100644
index 0000000..592bcdb
--- /dev/null
+++ b/include/ui_strings.h
@@ -0,0 +1,188 @@
+/*
+* This file is part of Anemone3DS
+* Copyright (C) 2016-2020 Contributors in CONTRIBUTORS.md
+*
+* 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 UISTRINGS_H
+#define UISTRINGS_H
+
+#include "colors.h"
+#include "draw.h"
+#include "common.h"
+
+#define SPLASHES_STRINGS 2
+#define THEMES_STRINGS 6
+
+typedef struct {
+ const char *quit;
+ const char *thread_error;
+ const char *zip_not_theme_splash;
+ const char *file_not_zip;
+ const char *download_failed;
+} Camera_Strings_s;
+
+typedef struct {
+ const char *theme_mode;
+ const char *splash_mode;
+ const char *no_themes;
+ const char *no_splashes;
+ const char *qr_download;
+ const char *switch_splashes;
+ const char *switch_themes;
+ const char *quit;
+ const char *by;
+ const char *selected;
+ const char *sel;
+ const char *tp_theme_mode;
+ const char *tp_splash_mode;
+ const char *search;
+ const char *page;
+ const char *err_quit;
+ const char *warn_continue;
+ const char *yes_no;
+ const char *load_themes;
+ const char *load_splash;
+ const char *load_icons;
+ const char *install_splash;
+ const char *delete_splash;
+ const char *install_theme;
+ const char *install_shuffle;
+ const char *install_bgm;
+ const char *install_no_bgm;
+ const char *downloading;
+ const char *checking_dl;
+ const char *delete_sd;
+ const char *download_themes;
+ const char *download_splashes;
+ const char *download_preview;
+ const char *download_bgm;
+ const char *dump_single;
+ const char *dump_all_official;
+ float start_pos;
+} Draw_Strings_s;
+
+typedef struct {
+ const char *illegal_input;
+ const char *new_or_overwrite;
+ const char *cancel;
+ const char *overwrite;
+ const char *rename;
+ const char *swkbd_fail;
+ const char *sd_full;
+ const char *fs_error;
+} FS_Strings_s;
+
+typedef struct {
+ const char *no_preview;
+} Loading_Strings_s;
+
+typedef struct {
+ const char *position_too_big;
+ const char *position_zero;
+ const char *jump_q;
+ const char *cancel;
+ const char *jump;
+ const char *no_theme_extdata;
+ const char *loading_qr;
+ const char *no_wifi;
+ const char *qr_homebrew;
+ const char *camera_broke;
+ const char *too_many_themes;
+ const char *not_enough_themes;
+ const char *uninstall_confirm;
+ const char *delete_confirm;
+} Main_Strings_s;
+
+typedef struct {
+ const char *no_results;
+ const char *check_wifi;
+ const char *new_page_big;
+ const char *new_page_zero;
+ const char *jump_page;
+ const char *cancel;
+ const char *jump;
+ const char *tags;
+ const char *search;
+ const char *parental_fail;
+ const char *zip_not_found;
+ const char *generic_httpc_error;
+ const char *http303_tp;
+ const char *http303;
+ const char *http404;
+ const char *http_err_url;
+ const char *http_errcode_generic;
+ const char *http401;
+ const char *http403;
+ const char *http407;
+ const char *http414;
+ const char *http418;
+ const char *http426;
+ const char *http451;
+ const char *http500;
+ const char *http502;
+ const char *http503;
+ const char *http504;
+ const char *http_unexpected;
+} Remote_Strings_s;
+
+typedef struct {
+ const char *no_splash_found;
+ const char *splash_disabled;
+} Splashes_Strings_s;
+
+typedef struct {
+ const char *no_body_found;
+ const char *mono_warn;
+ const char *illegal_char;
+ const char *name_folder;
+ const char *cancel;
+ const char *done;
+} Themes_Strings_s;
+
+typedef struct {
+ Instructions_s normal_instructions[MODE_AMOUNT];
+ Instructions_s install_instructions;
+ Instructions_s extra_instructions[3];
+ Camera_Strings_s camera;
+ Draw_Strings_s draw;
+ FS_Strings_s fs;
+ Loading_Strings_s loading;
+ Main_Strings_s main;
+ Remote_Strings_s remote;
+ Instructions_s remote_instructions[MODE_AMOUNT];
+ Instructions_s remote_extra_instructions;
+ Splashes_Strings_s splashes;
+ Themes_Strings_s themes;
+} Language_s;
+
+typedef enum {
+ LANGUAGE_EN,
+
+ LANGUAGE_AMOUNT,
+} Language_Name;
+
+Language_s init_strings(CFG_Language lang);
+extern Language_s language;
+
+#endif
diff --git a/source/camera.c b/source/camera.c
index c0e1575..e0b4731 100644
--- a/source/camera.c
+++ b/source/camera.c
@@ -32,6 +32,7 @@
#include "fs.h"
#include "loading.h"
#include "remote.h"
+#include "ui_strings.h"
#include
#include
@@ -200,7 +201,7 @@ static void update_ui(void * arg)
C2D_DrawImageAt((C2D_Image){ &tex, &subt3x }, 0.0f, 0.0f, 0.4f, NULL, 1.0f, 1.0f);
set_screen(bottom);
- draw_text_center(GFX_BOTTOM, 4, 0.5, 0.5, 0.5, colors[COLOR_WHITE], "Press \uE005 To Quit");
+ draw_text_center(GFX_BOTTOM, 4, 0.5, 0.5, 0.5, colors[COLOR_WHITE], language.camera.quit);
end_frame();
}
@@ -212,7 +213,7 @@ static bool start_capture_cam(qr_data * data)
{
if((data->cam_thread = threadCreate(capture_cam_thread, data, 0x10000, 0x1A, 1, false)) == NULL)
{
- throw_error("Capture cam thread creation failed\nPlease report this to the developers", ERROR_LEVEL_ERROR);
+ throw_error(language.camera.thread_error, ERROR_LEVEL_ERROR);
LightEvent_Signal(&data->event_cam_info);
LightEvent_Signal(&data->event_ui_info);
return false;
@@ -397,18 +398,18 @@ bool init_qr(void)
}
else
{
- throw_error("Zip downloaded is neither\na splash nor a theme.", ERROR_LEVEL_WARNING);
+ throw_error(language.camera.zip_not_theme_splash, ERROR_LEVEL_WARNING);
}
}
else
{
- throw_error("File downloaded isn't a zip.", ERROR_LEVEL_WARNING);
+ throw_error(language.camera.file_not_zip, ERROR_LEVEL_WARNING);
}
free(zip_buf);
}
else
{
- throw_error("Download failed.", ERROR_LEVEL_WARNING);
+ throw_error(language.camera.download_failed, ERROR_LEVEL_WARNING);
}
free(filename);
diff --git a/source/conversion.c b/source/conversion.c
index 53610f2..517ec50 100644
--- a/source/conversion.c
+++ b/source/conversion.c
@@ -49,7 +49,7 @@ size_t bin_to_abgr(char ** bufp, size_t size)
return out_size;
}
-size_t png_to_abgr(char ** bufp, size_t size)
+size_t png_to_abgr(char ** bufp, size_t size, u32 *height)
{
size_t out_size = 0;
if(size < 8 || png_sig_cmp((png_bytep)*bufp, 0, 8))
@@ -70,7 +70,7 @@ size_t png_to_abgr(char ** bufp, size_t size)
png_read_info(png, info);
u32 width = png_get_image_width(png, info);
- u32 height = png_get_image_height(png, info);
+ *height = png_get_image_height(png, info);
png_byte color_type = png_get_color_type(png, info);
png_byte bit_depth = png_get_bit_depth(png, info);
@@ -107,10 +107,10 @@ size_t png_to_abgr(char ** bufp, size_t size)
png_read_update_info(png, info);
- row_pointers = malloc(sizeof(png_bytep) * height);
- out_size = sizeof(u32) * (width * height);
+ row_pointers = malloc(sizeof(png_bytep) * *height);
+ out_size = sizeof(u32) * (width * *height);
u32 * out = malloc(out_size);
- for(u32 y = 0; y < height; y++)
+ for(u32 y = 0; y < *height; y++)
{
row_pointers[y] = (png_bytep)(out + (width * y));
}
@@ -126,4 +126,4 @@ size_t png_to_abgr(char ** bufp, size_t size)
*bufp = (char*)out;
return out_size;
-}
\ No newline at end of file
+}
diff --git a/source/draw.c b/source/draw.c
index f2b6513..ce5feb8 100644
--- a/source/draw.c
+++ b/source/draw.c
@@ -27,6 +27,7 @@
#include "draw.h"
#include "unicode.h"
#include "colors.h"
+#include "ui_strings.h"
#include "sprites.h"
@@ -77,56 +78,56 @@ void init_screens(void)
C2D_TextParse(&text[TEXT_VERSION], staticBuf, VERSION);
- C2D_TextParse(&text[TEXT_THEME_MODE], staticBuf, "Theme mode");
- C2D_TextParse(&text[TEXT_SPLASH_MODE], staticBuf, "Splash mode");
+ C2D_TextParse(&text[TEXT_THEME_MODE], staticBuf, language.draw.theme_mode);
+ C2D_TextParse(&text[TEXT_SPLASH_MODE], staticBuf, language.draw.splash_mode);
- C2D_TextParse(&text[TEXT_NO_THEME_FOUND], staticBuf, "No theme found");
- C2D_TextParse(&text[TEXT_NO_SPLASH_FOUND], staticBuf, "No splash found");
+ C2D_TextParse(&text[TEXT_NO_THEME_FOUND], staticBuf, language.draw.no_themes);
+ C2D_TextParse(&text[TEXT_NO_SPLASH_FOUND], staticBuf, language.draw.no_splashes);
- C2D_TextParse(&text[TEXT_DOWNLOAD_FROM_QR], staticBuf, "Press \uE005 to download from QR");
+ C2D_TextParse(&text[TEXT_DOWNLOAD_FROM_QR], staticBuf, language.draw.qr_download);
- C2D_TextParse(&text[TEXT_SWITCH_TO_SPLASHES], staticBuf, "Or \uE004 to switch to splashes");
- C2D_TextParse(&text[TEXT_SWITCH_TO_THEMES], staticBuf, "Or \uE004 to switch to themes");
+ C2D_TextParse(&text[TEXT_SWITCH_TO_SPLASHES], staticBuf, language.draw.switch_splashes);
+ C2D_TextParse(&text[TEXT_SWITCH_TO_THEMES], staticBuf, language.draw.switch_themes);
- C2D_TextParse(&text[TEXT_OR_START_TO_QUIT], staticBuf, "Or to quit");
+ C2D_TextParse(&text[TEXT_OR_START_TO_QUIT], staticBuf, language.draw.quit);
- C2D_TextParse(&text[TEXT_BY_AUTHOR], staticBuf, "By ");
- C2D_TextParse(&text[TEXT_SELECTED], staticBuf, "Selected:");
- C2D_TextParse(&text[TEXT_SELECTED_SHORT], staticBuf, "Sel.:");
+ C2D_TextParse(&text[TEXT_BY_AUTHOR], staticBuf, language.draw.by);
+ C2D_TextParse(&text[TEXT_SELECTED], staticBuf, language.draw.selected);
+ C2D_TextParse(&text[TEXT_SELECTED_SHORT], staticBuf, language.draw.sel);
- C2D_TextParse(&text[TEXT_THEMEPLAZA_THEME_MODE], staticBuf, "ThemePlaza Theme mode");
- C2D_TextParse(&text[TEXT_THEMEPLAZA_SPLASH_MODE], staticBuf, "ThemePlaza Splash mode");
+ C2D_TextParse(&text[TEXT_THEMEPLAZA_THEME_MODE], staticBuf, language.draw.tp_theme_mode);
+ C2D_TextParse(&text[TEXT_THEMEPLAZA_SPLASH_MODE], staticBuf, language.draw.tp_splash_mode);
- C2D_TextParse(&text[TEXT_SEARCH], staticBuf, "Search...");
- C2D_TextParse(&text[TEXT_PAGE], staticBuf, "Page:");
+ C2D_TextParse(&text[TEXT_SEARCH], staticBuf, language.draw.search);
+ C2D_TextParse(&text[TEXT_PAGE], staticBuf, language.draw.page);
- C2D_TextParse(&text[TEXT_ERROR_QUIT], staticBuf, "Press \uE000 to quit.");
- C2D_TextParse(&text[TEXT_ERROR_CONTINUE], staticBuf, "Press \uE000 to continue.");
+ C2D_TextParse(&text[TEXT_ERROR_QUIT], staticBuf, language.draw.err_quit);
+ C2D_TextParse(&text[TEXT_ERROR_CONTINUE], staticBuf, language.draw.warn_continue);
- C2D_TextParse(&text[TEXT_CONFIRM_YES_NO], staticBuf, "\uE000 Yes \uE001 No");
+ C2D_TextParse(&text[TEXT_CONFIRM_YES_NO], staticBuf, language.draw.yes_no);
- C2D_TextParse(&text[TEXT_INSTALL_LOADING_THEMES], staticBuf, "Loading themes, please wait...");
- C2D_TextParse(&text[TEXT_INSTALL_LOADING_SPLASHES], staticBuf, "Loading splashes, please wait...");
- C2D_TextParse(&text[TEXT_INSTALL_LOADING_ICONS], staticBuf, "Loading icons, please wait...");
+ C2D_TextParse(&text[TEXT_INSTALL_LOADING_THEMES], staticBuf, language.draw.load_themes);
+ C2D_TextParse(&text[TEXT_INSTALL_LOADING_SPLASHES], staticBuf, language.draw.load_splash);
+ C2D_TextParse(&text[TEXT_INSTALL_LOADING_ICONS], staticBuf, language.draw.load_icons);
- C2D_TextParse(&text[TEXT_INSTALL_SPLASH], staticBuf, "Installing a splash...");
- C2D_TextParse(&text[TEXT_INSTALL_SPLASH_DELETE], staticBuf, "Deleting installed splash...");
+ C2D_TextParse(&text[TEXT_INSTALL_SPLASH], staticBuf, language.draw.install_splash);
+ C2D_TextParse(&text[TEXT_INSTALL_SPLASH_DELETE], staticBuf, language.draw.delete_splash);
- C2D_TextParse(&text[TEXT_INSTALL_SINGLE], staticBuf, "Installing a single theme...");
- C2D_TextParse(&text[TEXT_INSTALL_SHUFFLE], staticBuf, "Installing shuffle themes...");
- C2D_TextParse(&text[TEXT_INSTALL_BGM], staticBuf, "Installing BGM-only theme...");
- C2D_TextParse(&text[TEXT_INSTALL_NO_BGM], staticBuf, "Installing theme without BGM...");
+ C2D_TextParse(&text[TEXT_INSTALL_SINGLE], staticBuf, language.draw.install_theme);
+ C2D_TextParse(&text[TEXT_INSTALL_SHUFFLE], staticBuf, language.draw.install_shuffle);
+ C2D_TextParse(&text[TEXT_INSTALL_BGM], staticBuf, language.draw.install_bgm);
+ C2D_TextParse(&text[TEXT_INSTALL_NO_BGM], staticBuf, language.draw.install_no_bgm);
- C2D_TextParse(&text[TEXT_INSTALL_DOWNLOAD], staticBuf, "Downloading...");
- C2D_TextParse(&text[TEXT_INSTALL_CHECKING_DOWNLOAD], staticBuf, "Checking downloaded file...");
- C2D_TextParse(&text[TEXT_INSTALL_ENTRY_DELETE], staticBuf, "Deleting from SD...");
+ C2D_TextParse(&text[TEXT_INSTALL_DOWNLOAD], staticBuf, language.draw.downloading);
+ C2D_TextParse(&text[TEXT_INSTALL_CHECKING_DOWNLOAD], staticBuf, language.draw.checking_dl);
+ C2D_TextParse(&text[TEXT_INSTALL_ENTRY_DELETE], staticBuf, language.draw.delete_sd);
- C2D_TextParse(&text[TEXT_INSTALL_LOADING_REMOTE_THEMES], staticBuf, "Downloading theme list, please wait...");
- C2D_TextParse(&text[TEXT_INSTALL_LOADING_REMOTE_SPLASHES], staticBuf, "Downloading splash list, please wait...");
- C2D_TextParse(&text[TEXT_INSTALL_LOADING_REMOTE_PREVIEW], staticBuf, "Downloading preview, please wait...");
- C2D_TextParse(&text[TEXT_INSTALL_LOADING_REMOTE_BGM], staticBuf, "Downloading BGM, please wait...");
- C2D_TextParse(&text[TEXT_INSTALL_DUMPING_THEME], staticBuf, "Dumping theme, please wait...");
- C2D_TextParse(&text[TEXT_INSTALL_DUMPING_ALL_THEMES], staticBuf, "Dumping official themes, please wait...");
+ C2D_TextParse(&text[TEXT_INSTALL_LOADING_REMOTE_THEMES], staticBuf, language.draw.download_themes);
+ C2D_TextParse(&text[TEXT_INSTALL_LOADING_REMOTE_SPLASHES], staticBuf, language.draw.download_splashes);
+ C2D_TextParse(&text[TEXT_INSTALL_LOADING_REMOTE_PREVIEW], staticBuf, language.draw.download_preview);
+ C2D_TextParse(&text[TEXT_INSTALL_LOADING_REMOTE_BGM], staticBuf, language.draw.download_bgm);
+ C2D_TextParse(&text[TEXT_INSTALL_DUMPING_THEME], staticBuf, language.draw.dump_single);
+ C2D_TextParse(&text[TEXT_INSTALL_DUMPING_ALL_THEMES], staticBuf, language.draw.dump_all_official);
for(int i = 0; i < TEXT_AMOUNT; i++)
C2D_TextOptimize(&text[i]);
@@ -318,12 +319,12 @@ void throw_error(const char * error, ErrorLevel level)
}
}
-bool draw_confirm(const char * conf_msg, Entry_List_s * list)
+bool draw_confirm(const char * conf_msg, Entry_List_s * list, DrawMode draw_mode)
{
while(aptMainLoop())
{
Instructions_s instructions = {0};
- draw_interface(list, instructions);
+ draw_interface(list, instructions, draw_mode);
set_screen(top);
draw_text_center(GFX_TOP, BUTTONS_Y_LINE_1, 0.5f, 0.7f, 0.7f, colors[COLOR_YELLOW], conf_msg);
draw_c2d_text_center(GFX_TOP, BUTTONS_Y_LINE_3, 0.5f, 0.6f, 0.6f, colors[COLOR_WHITE], &text[TEXT_CONFIRM_YES_NO]);
@@ -535,7 +536,7 @@ void draw_grid_interface(Entry_List_s * list, Instructions_s instructions)
draw_c2d_text(7, 3, 0.5f, 0.6f, 0.6f, colors[COLOR_WHITE], &text[TEXT_SEARCH]);
- draw_image(sprites_list_idx, 320-96, 0);
+ draw_image(sprites_back_idx, 320-96, 0);
draw_image(sprites_exit_idx, 320-72, 0);
draw_image(sprites_preview_idx, 320-48, 0);
@@ -601,7 +602,7 @@ void draw_grid_interface(Entry_List_s * list, Instructions_s instructions)
draw_c2d_text(176, 219, 0.5, 0.6, 0.6, colors[COLOR_WHITE], &text[TEXT_PAGE]);
}
-void draw_interface(Entry_List_s * list, Instructions_s instructions)
+void draw_interface(Entry_List_s * list, Instructions_s instructions, DrawMode draw_mode)
{
draw_base_interface();
EntryMode current_mode = list->mode;
@@ -613,7 +614,7 @@ void draw_interface(Entry_List_s * list, Instructions_s instructions)
draw_c2d_text_center(GFX_TOP, 4, 0.5f, 0.5f, 0.5f, colors[COLOR_WHITE], mode_string[current_mode]);
- if(list->entries == NULL)
+ if(list->entries == NULL || list->entries_count == 0)
{
C2D_Text * mode_found_string[MODE_AMOUNT] = {
&text[TEXT_NO_THEME_FOUND],
@@ -633,7 +634,7 @@ void draw_interface(Entry_List_s * list, Instructions_s instructions)
C2D_ImageTint yellow_tint;
C2D_PlainImageTint(&yellow_tint, colors[COLOR_YELLOW], 1.0f);
- C2D_SpriteSetPos(&sprite_start, 162, 173);
+ C2D_SpriteSetPos(&sprite_start, language.draw.start_pos, 173);
C2D_SpriteSetScale(&sprite_start, 1.25f, 1.4f);
C2D_DrawSpriteTinted(&sprite_start, &yellow_tint);
C2D_SpriteSetScale(&sprite_start, 1.0f, 1.0f);
@@ -641,7 +642,7 @@ void draw_interface(Entry_List_s * list, Instructions_s instructions)
set_screen(bottom);
draw_image(sprites_sort_idx, 320-144, 0);
- draw_image(sprites_download_idx, 320-120, 0);
+ draw_image(sprites_qr_idx, 320-120, 0);
draw_image(sprites_browse_idx, 320-96, 0);
draw_image(sprites_exit_idx, 320-72, 0);
draw_image(sprites_preview_idx, 320-48, 0);
@@ -667,18 +668,41 @@ void draw_interface(Entry_List_s * list, Instructions_s instructions)
free(shuffle_count_string);
}
- draw_image(sprites_sort_idx, 320-144, 0);
- draw_image(sprites_download_idx, 320-120, 0);
- draw_image(sprites_browse_idx, 320-96, 0);
- draw_image(sprites_exit_idx, 320-72, 0);
- draw_image(sprites_preview_idx, 320-48, 0);
-
- draw_text(320-24+2.5, -3, 0.6, 1.0f, 0.9f, colors[COLOR_WHITE], mode_switch_char[!current_mode]);
+ if (draw_mode == DRAW_MODE_LIST)
+ {
+ draw_image(sprites_install_idx, 320-120, 0);
+ draw_image(sprites_qr_idx, 320-96, 0);
+ draw_image(sprites_exit_idx, 320-72, 0);
+ draw_image(sprites_preview_idx, 320-48, 0);
+ draw_text(320-24+2.5, -3, 0.6, 1.0f, 0.9f, colors[COLOR_WHITE], mode_switch_char[!current_mode]);
+ draw_image(sprites_menu_idx, 320-144, 0);
+ if (current_mode == MODE_THEMES)
+ {
+ draw_image(sprites_shuffle_idx, 320-168, 0);
+ }
+ }
+ else
+ {
+ if (draw_mode == DRAW_MODE_INSTALL)
+ {
+ draw_image(sprites_install_idx, 320-24, 0);
+ draw_image(sprites_shuffle_idx, 320-48, 0);
+ draw_image(sprites_shuffle_no_bgm_idx, 320-72, 0);
+ draw_image(sprites_bgm_only_idx, 320-96, 0);
+ draw_image(sprites_back_idx, 320-120, 0);
+ } else if (draw_mode == DRAW_MODE_EXTRA)
+ {
+ draw_image(sprites_browse_idx, 320-24, 0);
+ draw_image(sprites_dump_idx, 320-48, 0);
+ draw_image(sprites_sort_idx, 320-72, 0);
+ draw_image(sprites_back_idx, 320-96, 0);
+ }
+ }
// Show arrows if there are themes out of bounds
//----------------------------------------------------------------
if(list->scroll > 0)
- draw_image(sprites_arrow_up_idx, 152, 4);
+ draw_image(sprites_arrow_up_idx, 136, 220);
if(list->scroll + list->entries_loaded < list->entries_count)
draw_image(sprites_arrow_down_idx, 152, 220);
@@ -763,4 +787,8 @@ void draw_interface(Entry_List_s * list, Instructions_s instructions)
draw_c2d_text(176, 219, 0.5, 0.6, 0.6, colors[COLOR_WHITE], &text[TEXT_SELECTED]);
else
draw_c2d_text(176, 219, 0.5, 0.6, 0.6, colors[COLOR_WHITE], &text[TEXT_SELECTED_SHORT]);
+ if(draw_mode != DRAW_MODE_LIST)
+ {
+ C2D_DrawRectSolid(0, 24, 1.0f, 320, 240-48, C2D_Color32(0, 0, 0, 128));
+ }
}
diff --git a/source/fs.c b/source/fs.c
index b0b093b..6149d06 100644
--- a/source/fs.c
+++ b/source/fs.c
@@ -29,6 +29,7 @@
#include "fs.h"
#include "draw.h"
#include "unicode.h"
+#include "ui_strings.h"
#include
#include
@@ -372,7 +373,8 @@ static SwkbdCallbackResult fat32filter(void * user, const char ** ppMessage, con
{
(void)textlen;
(void)user;
- *ppMessage = "Input must not contain:\n" ILLEGAL_CHARS;
+
+ *ppMessage = language.fs.illegal_input;
if(strpbrk(text, ILLEGAL_CHARS))
{
DEBUG("illegal filename: %s\n", text);
@@ -434,12 +436,12 @@ renamed:
SwkbdState swkbd;
swkbdInit(&swkbd, SWKBD_TYPE_NORMAL, 3, max_chars / 2);
- swkbdSetHintText(&swkbd, "Choose a new filename or tap Overwrite");
+ swkbdSetHintText(&swkbd, language.fs.new_or_overwrite);
swkbdSetFeatures(&swkbd, SWKBD_PREDICTIVE_INPUT | SWKBD_DARKEN_TOP_SCREEN);
- swkbdSetButton(&swkbd, SWKBD_BUTTON_LEFT, "Cancel", false);
- swkbdSetButton(&swkbd, SWKBD_BUTTON_MIDDLE, "Overwrite", false);
- swkbdSetButton(&swkbd, SWKBD_BUTTON_RIGHT, "Rename", true);
+ swkbdSetButton(&swkbd, SWKBD_BUTTON_LEFT, language.fs.cancel, false);
+ swkbdSetButton(&swkbd, SWKBD_BUTTON_MIDDLE, language.fs.overwrite, false);
+ swkbdSetButton(&swkbd, SWKBD_BUTTON_RIGHT, language.fs.rename, true);
swkbdSetValidation(&swkbd, SWKBD_NOTEMPTY_NOTBLANK, SWKBD_FILTER_CALLBACK, -1);
swkbdSetFilterCallback(&swkbd, &fat32filter, NULL);
@@ -462,18 +464,18 @@ renamed:
return;
case SWKBD_BUTTON_NONE:
DEBUG("SWKBD broke wtf??? :- %x\n", swkbdGetResult(&swkbd));
- return throw_error("???\nTry a USB keyboard", ERROR_LEVEL_WARNING);
+ return throw_error(language.fs.swkbd_fail, ERROR_LEVEL_WARNING);
}
}
else if (res == (long)0xC86044D2)
{
DEBUG("SD card is full\n");
- return throw_error("SD card is full.\nDelete some themes to make space.", ERROR_LEVEL_WARNING);
+ return throw_error(language.fs.sd_full, ERROR_LEVEL_WARNING);
}
else
{
DEBUG("error: %lx\n", res);
- return throw_error("FS Error:\nGet a new SD card.", ERROR_LEVEL_ERROR);
+ return throw_error(language.fs.fs_error, ERROR_LEVEL_ERROR);
}
}
diff --git a/source/loading.c b/source/loading.c
index 6288f24..39c8506 100644
--- a/source/loading.c
+++ b/source/loading.c
@@ -30,6 +30,7 @@
#include "music.h"
#include "draw.h"
#include "conversion.h"
+#include "ui_strings.h"
#include
@@ -306,9 +307,8 @@ void load_icons_thread(void * void_arg)
} while(arg->run_thread);
}
-bool load_preview_from_buffer(char * row_pointers, u32 size, C2D_Image * preview_image, int * preview_offset)
+bool load_preview_from_buffer(char * row_pointers, u32 size, C2D_Image * preview_image, int * preview_offset, int height)
{
- int height = SCREEN_HEIGHT * 2;
int width = (uint32_t)((size / 4) / height);
free_preview(*preview_image);
@@ -355,10 +355,11 @@ bool load_preview(const Entry_List_s * list, C2D_Image * preview_image, int * pr
char * preview_buffer = NULL;
u32 size = load_data("/preview.png", entry, &preview_buffer);
+ u32 height = 480;
if(size)
{
- if (!(size = png_to_abgr(&preview_buffer, size)))
+ if (!(size = png_to_abgr(&preview_buffer, size, &height)))
{
return false;
}
@@ -409,7 +410,7 @@ bool load_preview(const Entry_List_s * list, C2D_Image * preview_image, int * pr
if (!found_splash)
{
free(rgba_buffer);
- throw_error("No preview found.", ERROR_LEVEL_WARNING);
+ throw_error(language.loading.no_preview, ERROR_LEVEL_WARNING);
return false;
}
@@ -417,7 +418,7 @@ bool load_preview(const Entry_List_s * list, C2D_Image * preview_image, int * pr
preview_buffer = rgba_buffer;
}
- bool ret = load_preview_from_buffer(preview_buffer, size, preview_image, preview_offset);
+ bool ret = load_preview_from_buffer(preview_buffer, size, preview_image, preview_offset, height);
free(preview_buffer);
if(ret)
diff --git a/source/main.c b/source/main.c
index 8853d6a..3fbe08d 100644
--- a/source/main.c
+++ b/source/main.c
@@ -32,7 +32,7 @@
#include "camera.h"
#include "music.h"
#include "remote.h"
-#include "instructions.h"
+#include "ui_strings.h"
#include
bool quit = false;
@@ -53,6 +53,8 @@ static Thread_Arg_s install_check_threads_arg[MODE_AMOUNT] = {0};
static Entry_List_s lists[MODE_AMOUNT] = {0};
+Language_s language = {0};
+
int __stacksize__ = 64 * 1024;
Result archive_result;
u32 old_time_limit;
@@ -254,8 +256,8 @@ static void load_lists(Entry_List_s * lists)
DEBUG("total: %i\n", current_list->entries_count);
- load_icons_first(current_list, false);
sort_by_name(current_list);
+ load_icons_first(current_list, false);
void (*install_check_function)(void *) = NULL;
if(i == MODE_THEMES)
@@ -283,12 +285,12 @@ static SwkbdCallbackResult jump_menu_callback(void * entries_count, const char *
int typed_value = atoi(text);
if(typed_value > *(int *)entries_count)
{
- *ppMessage = "The new position has to be\nsmaller or equal to the\nnumber of entries!";
+ *ppMessage = language.main.position_too_big;
return SWKBD_CALLBACK_CONTINUE;
}
else if(typed_value == 0)
{
- *ppMessage = "The new position has to\nbe positive!";
+ *ppMessage = language.main.position_zero;
return SWKBD_CALLBACK_CONTINUE;
}
return SWKBD_CALLBACK_OK;
@@ -309,11 +311,11 @@ static void jump_menu(Entry_List_s * list)
sprintf(numbuf, "%i", list->selected_entry);
swkbdSetInitialText(&swkbd, numbuf);
- sprintf(numbuf, "Where do you want to jump to?\nMay cause icons to reload.");
+ sprintf(numbuf, language.main.jump_q);
swkbdSetHintText(&swkbd, numbuf);
- swkbdSetButton(&swkbd, SWKBD_BUTTON_LEFT, "Cancel", false);
- swkbdSetButton(&swkbd, SWKBD_BUTTON_RIGHT, "Jump", true);
+ swkbdSetButton(&swkbd, SWKBD_BUTTON_LEFT, language.main.cancel, false);
+ swkbdSetButton(&swkbd, SWKBD_BUTTON_RIGHT, language.main.jump, true);
swkbdSetValidation(&swkbd, SWKBD_NOTEMPTY_NOTBLANK, 0, max_chars);
swkbdSetFilterCallback(&swkbd, jump_menu_callback, &list->entries_count);
@@ -375,6 +377,9 @@ int main(void)
{
srand(time(NULL));
init_services();
+ CFG_Language lang;
+ CFGU_GetSystemLanguage(&lang);
+ language = init_strings(lang);
init_screens();
svcCreateMutex(&update_icons_mutex, true);
@@ -400,7 +405,9 @@ int main(void)
int preview_offset = 0;
bool install_mode = false;
+ DrawMode draw_mode = DRAW_MODE_LIST;
bool extra_mode = false;
+ int extra_index = 1;
C2D_Image preview = {0};
while(aptMainLoop())
@@ -421,7 +428,7 @@ int main(void)
#ifndef CITRA_MODE
if(R_FAILED(archive_result) && current_mode == MODE_THEMES)
{
- throw_error("Theme extdata does not exist!\nSet a default theme from the home menu.", ERROR_LEVEL_ERROR);
+ throw_error(language.main.no_theme_extdata, ERROR_LEVEL_ERROR);
quit = true;
continue;
}
@@ -434,22 +441,12 @@ int main(void)
current_list = &lists[current_mode];
- Instructions_s instructions = normal_instructions[current_mode];
+ Instructions_s instructions = language.normal_instructions[current_mode];
if(install_mode)
- instructions = install_instructions;
+ instructions = language.install_instructions;
if(extra_mode)
{
- int index = 1;
- bool key_l = (kDown | kHeld) & KEY_L;
- bool key_r = (kDown | kHeld) & KEY_R;
- if(key_l ^ key_r)
- {
- if(key_l)
- index = 0;
- else if(key_r) // uncomment when we use the right menu. we don't for now
- index = 2;
- }
- instructions = extra_instructions[index];
+ instructions = language.extra_instructions[extra_index];
}
if(preview_mode)
@@ -472,7 +469,7 @@ int main(void)
svcWaitSynchronization(update_icons_mutex, U64_MAX);
}
- draw_interface(current_list, instructions);
+ draw_interface(current_list, instructions, draw_mode);
svcSleepThread(1e7);
released = false;
@@ -502,7 +499,7 @@ int main(void)
{
enable_qr:
draw_base_interface();
- draw_text_center(GFX_TOP, 100, 0.5f, 0.6f, 0.6f, colors[COLOR_WHITE], "Loading QR Scanner...");
+ draw_text_center(GFX_TOP, 100, 0.5f, 0.6f, 0.6f, colors[COLOR_WHITE], language.main.loading_qr);
end_frame();
if(R_SUCCEEDED(camInit()))
{
@@ -518,15 +515,15 @@ int main(void)
}
else
{
- throw_error("Please connect to Wi-Fi before scanning QR codes", ERROR_LEVEL_WARNING);
+ throw_error(language.main.no_wifi, ERROR_LEVEL_WARNING);
}
}
else
{
if(homebrew)
- throw_error("QR scanning doesnt work from the Homebrew\nLauncher, use the ThemePlaza browser instead.", ERROR_LEVEL_WARNING);
+ throw_error(language.main.qr_homebrew, ERROR_LEVEL_WARNING);
else
- throw_error("Your camera seems to have a problem,\nunable to scan QR codes.", ERROR_LEVEL_WARNING);
+ throw_error(language.main.camera_broke, ERROR_LEVEL_WARNING);
}
continue;
@@ -580,92 +577,138 @@ int main(void)
if(install_mode)
{
- if(kUp & KEY_A)
- install_mode = false;
- if(!install_mode)
+ if ((kDown | kHeld) & KEY_TOUCH)
{
- if((kDown | kHeld) & KEY_DLEFT)
+ touchPosition touch = {0};
+ hidTouchRead(&touch);
+ u16 x = touch.px;
+ u16 y = touch.py;
+
+ if (kDown & KEY_TOUCH)
{
- aptSetHomeAllowed(false);
- draw_install(INSTALL_BGM);
- if(R_SUCCEEDED(bgm_install(current_entry)))
+ if (y < 24)
{
- for(int i = 0; i < current_list->entries_count; i++)
+ if (BETWEEN(320-24, x, 320))
{
- Entry_s * theme = ¤t_list->entries[i];
- if(theme == current_entry)
- theme->installed = true;
- else
- theme->installed = false;
+ goto install_theme_single;
+ } else if (BETWEEN(320-48, x, 320-24))
+ {
+ goto install_theme_shuffle;
+ } else if (BETWEEN(320-72, x, 320-48))
+ {
+ goto install_theme_no_bgm;
+ } else if (BETWEEN(320-96, x, 320-72))
+ {
+ goto install_theme_bgm_only;
+ } else if (BETWEEN(320-120, x, 320-96))
+ {
+ goto install_leave;
}
- installed_themes = true;
}
}
- else if((kDown | kHeld) & KEY_DUP)
+ }
+
+ if(kDown & KEY_B)
+ {
+ install_leave:
+ install_mode = false;
+ draw_mode = DRAW_MODE_LIST;
+ }
+ else if(kDown & KEY_DLEFT)
+ {
+ install_theme_bgm_only:
+ install_mode = false;
+ draw_mode = DRAW_MODE_LIST;
+ aptSetHomeAllowed(false);
+ draw_install(INSTALL_BGM);
+ if(R_SUCCEEDED(bgm_install(current_entry)))
+ {
+ for(int i = 0; i < current_list->entries_count; i++)
+ {
+ #define BETWEEN(min, x, max) (min < x && x < max)
+ Entry_s * theme = ¤t_list->entries[i];
+ if(theme == current_entry)
+ theme->installed = true;
+ else
+ theme->installed = false;
+ }
+ installed_themes = true;
+ }
+ }
+ else if(kDown & KEY_DUP)
+ {
+ install_theme_single:
+ install_mode = false;
+ draw_mode = DRAW_MODE_LIST;
+ aptSetHomeAllowed(false);
+ draw_install(INSTALL_SINGLE);
+ if(R_SUCCEEDED(theme_install(current_entry)))
+ {
+ for(int i = 0; i < current_list->entries_count; i++)
+
+ {
+ Entry_s * theme = ¤t_list->entries[i];
+ if(theme == current_entry)
+ theme->installed = true;
+ else
+ theme->installed = false;
+ }
+ installed_themes = true;
+ }
+ }
+ else if(kDown & KEY_DRIGHT)
+ {
+ install_theme_no_bgm:
+ install_mode = false;
+ draw_mode = DRAW_MODE_LIST;
+ aptSetHomeAllowed(false);
+ draw_install(INSTALL_NO_BGM);
+ if(R_SUCCEEDED(no_bgm_install(current_entry)))
+ {
+ for(int i = 0; i < current_list->entries_count; i++)
+ {
+ Entry_s * theme = ¤t_list->entries[i];
+ if(theme == current_entry)
+ theme->installed = true;
+ else
+ theme->installed = false;
+ }
+ installed_themes = true;
+ }
+ }
+ else if(kDown & KEY_DDOWN)
+ {
+ install_theme_shuffle:
+ install_mode = false;
+ draw_mode = DRAW_MODE_LIST;
+ if(current_list->shuffle_count > MAX_SHUFFLE_THEMES)
+ {
+ throw_error(language.main.too_many_themes, ERROR_LEVEL_WARNING);
+ }
+ else if(current_list->shuffle_count < 2)
+ {
+ throw_error(language.main.not_enough_themes, ERROR_LEVEL_WARNING);
+ }
+ else
{
aptSetHomeAllowed(false);
- draw_install(INSTALL_SINGLE);
- if(R_SUCCEEDED(theme_install(current_entry)))
- {
- for(int i = 0; i < current_list->entries_count; i++)
- {
- Entry_s * theme = ¤t_list->entries[i];
- if(theme == current_entry)
- theme->installed = true;
- else
- theme->installed = false;
- }
- installed_themes = true;
- }
- }
- else if((kDown | kHeld) & KEY_DRIGHT)
- {
- aptSetHomeAllowed(false);
- draw_install(INSTALL_NO_BGM);
- if(R_SUCCEEDED(no_bgm_install(current_entry)))
- {
- for(int i = 0; i < current_list->entries_count; i++)
- {
- Entry_s * theme = ¤t_list->entries[i];
- if(theme == current_entry)
- theme->installed = true;
- else
- theme->installed = false;
- }
- installed_themes = true;
- }
- }
- else if((kDown | kHeld) & KEY_DDOWN)
- {
- if(current_list->shuffle_count > MAX_SHUFFLE_THEMES)
- {
- throw_error("You have too many themes selected.", ERROR_LEVEL_WARNING);
- }
- else if(current_list->shuffle_count < 2)
- {
- throw_error("You don't have enough themes selected.", ERROR_LEVEL_WARNING);
- }
+ draw_install(INSTALL_SHUFFLE);
+ Result res = shuffle_install(current_list);
+ if(R_FAILED(res)) DEBUG("shuffle install result: %lx\n", res);
else
{
- aptSetHomeAllowed(false);
- draw_install(INSTALL_SHUFFLE);
- Result res = shuffle_install(current_list);
- if(R_FAILED(res)) DEBUG("shuffle install result: %lx\n", res);
- else
+ for(int i = 0; i < current_list->entries_count; i++)
{
- for(int i = 0; i < current_list->entries_count; i++)
+ Entry_s * theme = ¤t_list->entries[i];
+ if(theme->in_shuffle)
{
- Entry_s * theme = ¤t_list->entries[i];
- if(theme->in_shuffle)
- {
- theme->in_shuffle = false;
- theme->installed = true;
- }
- else theme->installed = false;
+ theme->in_shuffle = false;
+ theme->installed = true;
}
- current_list->shuffle_count = 0;
- installed_themes = true;
+ else theme->installed = false;
}
+ current_list->shuffle_count = 0;
+ installed_themes = true;
}
}
}
@@ -673,71 +716,151 @@ int main(void)
}
else if(extra_mode)
{
- if(kUp & KEY_X)
- extra_mode = false;
- if(!extra_mode)
+ if((kDown | kHeld) & KEY_TOUCH)
{
- bool key_l = (kDown | kHeld) & KEY_L;
- bool key_r = (kDown | kHeld) & KEY_R;
- if(!(key_l ^ key_r))
+ touchPosition touch = {0};
+ hidTouchRead(&touch);
+ u16 x = touch.px;
+ u16 y = touch.py;
+ if (kDown & KEY_TOUCH)
{
- if((kDown | kHeld) & KEY_DLEFT)
+ if (y < 24)
{
- browse_themeplaza:
- if(themeplaza_browser(current_mode))
+ if (BETWEEN(320-24, x, 320))
{
- current_mode = MODE_THEMES;
- load_lists(lists);
+ goto browse_themeplaza;
+ } else if (BETWEEN(320-48, x, 320-24))
+ {
+ goto dump_single;
+ } else if (BETWEEN(320-72, x, 320-48))
+ {
+ switch (current_list->current_sort)
+ {
+ case SORT_NAME:
+ goto sort_author;
+ break;
+ case SORT_AUTHOR:
+ goto sort_path;
+ break;
+ case SORT_PATH:
+ goto sort_name;
+ break;
+ default:
+ break;
+ }
+ } else if (BETWEEN(320-96, x, 320-72))
+ {
+ extra_mode = false;
+ extra_index = 1;
+ draw_mode = DRAW_MODE_LIST;
}
}
- else if((kDown | kHeld) & KEY_DUP)
+ }
+ }
+ else if(extra_index == 1)
+ {
+ if(kDown & KEY_B)
+ {
+ extra_mode = false;
+ draw_mode = DRAW_MODE_LIST;
+ }
+ else if(kDown & KEY_DLEFT)
+ {
+ browse_themeplaza:
+ if(themeplaza_browser(current_mode))
{
- jump:
- jump_menu(current_list);
+ current_mode = MODE_THEMES;
+ load_lists(lists);
+ }
+ extra_mode = false;
+ draw_mode = DRAW_MODE_LIST;
+ extra_index = 1;
+ }
+ else if(kDown & KEY_DUP)
+ {
+ jump:
+ jump_menu(current_list);
+ extra_mode = false;
+ draw_mode = DRAW_MODE_LIST;
+ extra_index = 1;
- }
- else if((kDown | kHeld) & KEY_DDOWN)
- {
- load_icons_first(current_list, false);
- }
}
- else if(key_l)
+ else if(kDown & KEY_DDOWN)
{
- if((kDown | kHeld) & KEY_DLEFT)
- {
- sort_path:
- sort_by_filename(current_list);
- load_icons_first(current_list, false);
- }
- else if(((kDown | kHeld)) & KEY_DUP)
- {
- sort_name:
- sort_by_name(current_list);
- load_icons_first(current_list, false);
- }
- else if(((kDown | kHeld)) & KEY_DDOWN)
- {
- sort_author:
- sort_by_author(current_list);
- load_icons_first(current_list, false);
- }
+ load_icons_first(current_list, false);
+ extra_mode = false;
+ draw_mode = DRAW_MODE_LIST;
+ extra_index = 1;
}
- else if(key_r)
+ else if (kDown & KEY_R)
{
- if(((kDown | kHeld)) & KEY_DUP)
- {
- draw_install(INSTALL_DUMPING_THEME);
- Result res = dump_current_theme();
- if (R_FAILED(res)) DEBUG("Dump theme result: %lx\n", res);
- else load_lists(lists);
- }
- else if(((kDown | kHeld)) & KEY_DDOWN)
- {
- draw_install(INSTALL_DUMPING_ALL_THEMES);
- Result res = dump_all_themes();
- if (R_FAILED(res)) DEBUG("Dump all themes result: %lx\n", res);
- else load_lists(lists);
- }
+ extra_index = 2;
+ }
+ else if(kDown & KEY_L)
+ {
+ extra_index = 0;
+ }
+ }
+ else if(extra_index == 0)
+ {
+ if(kDown & KEY_DLEFT)
+ {
+ sort_path:
+ sort_by_filename(current_list);
+ load_icons_first(current_list, false);
+ extra_mode = false;
+ draw_mode = DRAW_MODE_LIST;
+ extra_index = 1;
+ }
+ else if(kDown & KEY_DUP)
+ {
+ sort_name:
+ sort_by_name(current_list);
+ load_icons_first(current_list, false);
+ extra_mode = false;
+ draw_mode = DRAW_MODE_LIST;
+ extra_index = 1;
+ }
+ else if(kDown & KEY_DDOWN)
+ {
+ sort_author:
+ sort_by_author(current_list);
+ load_icons_first(current_list, false);
+ extra_mode = false;
+ draw_mode = DRAW_MODE_LIST;
+ extra_index = 1;
+ }
+ else if (kDown & KEY_B)
+ {
+ extra_index = 1;
+ }
+ }
+ else if(extra_index == 2)
+ {
+ if(kDown & KEY_DUP)
+ {
+ dump_single:
+ draw_install(INSTALL_DUMPING_THEME);
+ Result res = dump_current_theme();
+ if (R_FAILED(res)) DEBUG("Dump theme result: %lx\n", res);
+ else load_lists(lists);
+ extra_mode = false;
+ draw_mode = DRAW_MODE_LIST;
+ extra_index = 1;
+ }
+ else if(kDown & KEY_DDOWN)
+ {
+ draw_install(INSTALL_DUMPING_ALL_THEMES);
+ Result res = dump_all_themes();
+ if (R_FAILED(res)) DEBUG("Dump all themes result: %lx\n", res);
+ else load_lists(lists);
+ extra_mode = false;
+ draw_mode = DRAW_MODE_LIST;
+ extra_index = 1;
+ }
+ else if(kDown &KEY_B)
+ {
+ extra_index = 1;
}
}
continue;
@@ -751,6 +874,7 @@ int main(void)
{
case MODE_THEMES:
install_mode = true;
+ draw_mode = DRAW_MODE_INSTALL;
break;
case MODE_SPLASHES:
draw_install(INSTALL_SPLASH);
@@ -776,7 +900,7 @@ int main(void)
toggle_shuffle(current_list);
break;
case MODE_SPLASHES:
- if(draw_confirm("Are you sure you would like to delete\nthe installed splash?", current_list))
+ if(draw_confirm(language.main.uninstall_confirm, current_list, draw_mode))
{
draw_install(INSTALL_SPLASH_DELETE);
splash_delete();
@@ -789,10 +913,11 @@ int main(void)
else if(kDown & KEY_X)
{
extra_mode = true;
+ draw_mode = DRAW_MODE_EXTRA;
}
else if(kDown & KEY_SELECT)
{
- if(draw_confirm("Are you sure you would like to delete this?", current_list))
+ if(draw_confirm(language.main.delete_confirm, current_list, draw_mode))
{
draw_install(INSTALL_ENTRY_DELETE);
delete_entry(current_entry, current_entry->is_zip);
@@ -851,43 +976,49 @@ int main(void)
u16 x = touch.px;
u16 y = touch.py;
- u16 arrowStartX = 152;
+ u16 arrowStartX = 136;
u16 arrowEndX = arrowStartX+16;
- #define BETWEEN(min, x, max) (min < x && x < max)
if(kDown & KEY_TOUCH)
{
if(y < 24)
{
- if(current_list->entries != NULL && BETWEEN(arrowStartX, x, arrowEndX) && current_list->scroll > 0)
+ if(BETWEEN(320-168, x, 320-144))
{
- change_selected(current_list, -current_list->entries_per_screen_v);
+ if (current_mode == MODE_THEMES)
+ {
+ toggle_shuffle(current_list);
+ }
}
else if(BETWEEN(320-144, x, 320-120))
{
- switch(current_list->current_sort)
- {
- case SORT_NAME:
- goto sort_author;
- break;
- case SORT_AUTHOR:
- goto sort_path;
- break;
- case SORT_PATH:
- goto sort_name;
- break;
- default:
- break;
- }
+ extra_mode = true;
+ draw_mode = DRAW_MODE_EXTRA;
}
else if(BETWEEN(320-120, x, 320-96))
{
- goto enable_qr;
+ if (current_mode == MODE_THEMES)
+ {
+ install_mode = true;
+ draw_mode = DRAW_MODE_INSTALL;
+ } else if (current_mode == MODE_SPLASHES)
+ {
+ draw_install(INSTALL_SPLASH);
+ splash_install(current_entry);
+ for(int i = 0; i < current_list->entries_count; i++)
+ {
+ Entry_s * splash = ¤t_list->entries[i];
+ if(splash == current_entry)
+ splash->installed = true;
+ else
+ splash->installed = false;
+ }
+ }
}
else if(BETWEEN(320-96, x, 320-72))
{
- goto browse_themeplaza;
+ goto enable_qr;
}
else if(BETWEEN(320-72, x, 320-48))
{
@@ -904,7 +1035,11 @@ int main(void)
}
else if(y >= 216)
{
- if(current_list->entries != NULL && BETWEEN(arrowStartX, x, arrowEndX) && current_list->scroll < current_list->entries_count - current_list->entries_per_screen_v)
+ if(current_list->entries != NULL && BETWEEN(arrowStartX, x, arrowEndX) && current_list->scroll > 0)
+ {
+ change_selected(current_list, -current_list->entries_per_screen_v);
+ }
+ else if(current_list->entries != NULL && BETWEEN(arrowStartX + 16, x, arrowEndX + 16) && current_list->scroll < current_list->entries_count - current_list->entries_per_screen_v)
{
change_selected(current_list, current_list->entries_per_screen_v);
}
diff --git a/source/remote.c b/source/remote.c
index 7964514..5dff767 100644
--- a/source/remote.c
+++ b/source/remote.c
@@ -33,78 +33,12 @@
#include "music.h"
#include "urls.h"
#include "conversion.h"
+#include "ui_strings.h"
// forward declaration of special case used only here
// TODO: replace this travesty with a proper handler
static Result http_get_with_not_found_flag(const char * url, char ** filename, char ** buf, u32 * size, InstallType install_type, const char * acceptable_mime_types, bool not_found_is_error);
-static Instructions_s browser_instructions[MODE_AMOUNT] = {
- {
- .info_line = NULL,
- .instructions = {
- {
- "\uE000 Download theme",
- "\uE001 Go back"
- },
- {
- "\uE002 Hold for more",
- "\uE003 Preview theme"
- },
- {
- "\uE004 Previous page",
- "\uE005 Next page"
- },
- {
- "Exit",
- NULL
- }
- }
- },
- {
- .info_line = NULL,
- .instructions = {
- {
- "\uE000 Download splash",
- "\uE001 Go back"
- },
- {
- "\uE002 Hold for more",
- "\uE003 Preview splash"
- },
- {
- "\uE004 Previous page",
- "\uE005 Next page"
- },
- {
- "Exit",
- NULL
- }
- }
- }
-};
-
-static Instructions_s extra_instructions = {
- .info_line = "Release \uE002 to cancel or hold \uE006 and release \uE002 to do stuff",
- .instructions = {
- {
- "\uE079 Jump to page",
- "\uE07A Search tags"
- },
- {
- "\uE07B Toggle splash/theme",
- "\uE07C Reload without cache"
- },
- {
- NULL,
- NULL
- },
- {
- "Exit",
- NULL
- }
- }
-};
-
static void free_icons(Entry_List_s * list)
{
if (list != NULL)
@@ -237,7 +171,7 @@ static void load_remote_list(Entry_List_s * list, json_int_t page, EntryMode mod
load_remote_entries(list, value, ignore_cache, loading_screen);
else if (json_is_string(value) && !strcmp(key, THEMEPLAZA_JSON_ERROR_MESSAGE)
&& !strcmp(json_string_value(value), THEMEPLAZA_JSON_ERROR_MESSAGE_NOT_FOUND))
- throw_error("No results for this search.", ERROR_LEVEL_WARNING);
+ throw_error(language.remote.no_results, ERROR_LEVEL_WARNING);
}
}
else
@@ -246,7 +180,7 @@ static void load_remote_list(Entry_List_s * list, json_int_t page, EntryMode mod
json_decref(root);
}
else
- throw_error("Couldn't download Theme Plaza data.\nMake sure WiFi is on.", ERROR_LEVEL_WARNING);
+ throw_error(language.remote.check_wifi, ERROR_LEVEL_WARNING);
free(page_json);
}
@@ -288,14 +222,15 @@ static bool load_remote_preview(const Entry_s * entry, C2D_Image * preview_image
char * preview_buf = malloc(preview_size);
u32 preview_buf_size = preview_size;
memcpy(preview_buf, preview_png, preview_size);
+ u32 height = 480;
- if (!(preview_buf_size = png_to_abgr(&preview_buf, preview_buf_size)))
+ if (!(preview_buf_size = png_to_abgr(&preview_buf, preview_buf_size, &height)))
{
free(preview_buf);
return false;
}
- bool ret = load_preview_from_buffer(preview_buf, preview_buf_size, preview_image, preview_offset);
+ bool ret = load_preview_from_buffer(preview_buf, preview_buf_size, preview_image, preview_offset, height);
free(preview_buf);
if (ret && not_cached) // only save the preview if it loaded correctly - isn't corrupted
@@ -380,12 +315,12 @@ jump_menu_callback(void * page_number, const char ** ppMessage, const char * tex
int typed_value = atoi(text);
if (typed_value > *(json_int_t *)page_number)
{
- *ppMessage = "The new page has to be\nsmaller or equal to the\nnumber of pages!";
+ *ppMessage = language.remote.new_page_big;
return SWKBD_CALLBACK_CONTINUE;
}
else if (typed_value == 0)
{
- *ppMessage = "The new position has to\nbe positive!";
+ *ppMessage = language.remote.new_page_zero;
return SWKBD_CALLBACK_CONTINUE;
}
return SWKBD_CALLBACK_OK;
@@ -408,11 +343,11 @@ static void jump_menu(Entry_List_s * list)
JSON_INTEGER_FORMAT, list->tp_current_page);
swkbdSetInitialText(&swkbd, numbuf);
- sprintf(numbuf, "Which page do you want to jump to?");
+ sprintf(numbuf, language.remote.jump_page);
swkbdSetHintText(&swkbd, numbuf);
- swkbdSetButton(&swkbd, SWKBD_BUTTON_LEFT, "Cancel", false);
- swkbdSetButton(&swkbd, SWKBD_BUTTON_RIGHT, "Jump", true);
+ swkbdSetButton(&swkbd, SWKBD_BUTTON_LEFT, language.remote.cancel, false);
+ swkbdSetButton(&swkbd, SWKBD_BUTTON_RIGHT, language.remote.jump, true);
swkbdSetValidation(&swkbd, SWKBD_NOTEMPTY_NOTBLANK, 0, max_chars);
swkbdSetFilterCallback(&swkbd, jump_menu_callback, &list->tp_page_count);
@@ -434,10 +369,10 @@ static void search_menu(Entry_List_s * list)
SwkbdState swkbd;
swkbdInit(&swkbd, SWKBD_TYPE_NORMAL, 2, max_chars);
- swkbdSetHintText(&swkbd, "Which tags do you want to search for?");
+ swkbdSetHintText(&swkbd, language.remote.tags);
- swkbdSetButton(&swkbd, SWKBD_BUTTON_LEFT, "Cancel", false);
- swkbdSetButton(&swkbd, SWKBD_BUTTON_RIGHT, "Search", true);
+ swkbdSetButton(&swkbd, SWKBD_BUTTON_LEFT, language.remote.cancel, false);
+ swkbdSetButton(&swkbd, SWKBD_BUTTON_RIGHT, language.remote.search, true);
swkbdSetValidation(&swkbd, SWKBD_NOTBLANK, 0, max_chars);
SwkbdButton button = swkbdInputText(&swkbd, search, max_chars);
@@ -493,7 +428,7 @@ bool themeplaza_browser(EntryMode mode)
SwkbdResult swkbd_res = swkbdGetResult(&swkbd);
if (swkbd_res != SWKBD_PARENTAL_OK)
{
- throw_error("Parental Control validation failed!\nBrowser Access restricted.", ERROR_LEVEL_WARNING);
+ throw_error(language.remote.parental_fail, ERROR_LEVEL_WARNING);
return downloaded;
}
}
@@ -556,9 +491,9 @@ bool themeplaza_browser(EntryMode mode)
}
else
{
- Instructions_s instructions = browser_instructions[mode];
+ Instructions_s instructions = language.remote_instructions[mode];
if (extra_mode)
- instructions = extra_instructions;
+ instructions = language.remote_extra_instructions;
draw_grid_interface(current_list, instructions);
}
@@ -950,7 +885,6 @@ static ParseResult parse_header(struct header * out, httpcContext * context, con
return SUCCESS;
}
-#define ZIP_NOT_AVAILABLE "ZIP not found at this URL\nIf you believe this is an error, please\ncontact the site administrator"
/*
* call example: written = http_get("url", &filename, &buffer_to_download_to, &filesize, INSTALL_DOWNLOAD, "application/json");
@@ -962,6 +896,7 @@ Result http_get(const char * url, char ** filename, char ** buf, u32 * size, Ins
static Result http_get_with_not_found_flag(const char * url, char ** filename, char ** buf, u32 * size, InstallType install_type, const char * acceptable_mime_types, bool not_found_is_error)
{
+ const char *zip_not_available = language.remote.zip_not_found;
Result ret;
httpcContext context;
char redirect_url[0x824] = {0};
@@ -1005,7 +940,7 @@ redirect: // goto here if we need to redirect
break;
case HTTPC_ERROR:
DEBUG("httpc error %lx\n", _header.result_code);
- snprintf(err_buf, ERROR_BUFFER_SIZE, "Error in HTTPC sysmodule - 0x%08lx.\nIf you are seeing this, please contact an\nAnemone developer on the Theme Plaza Discord.", _header.result_code);
+ snprintf(err_buf, ERROR_BUFFER_SIZE, language.remote.generic_httpc_error, _header.result_code);
throw_error(err_buf, ERROR_LEVEL_ERROR);
quit = true;
httpcCloseContext(&context);
@@ -1013,12 +948,12 @@ redirect: // goto here if we need to redirect
case SEE_OTHER:
if (strstr(url, THEMEPLAZA_BASE_URL))
{
- snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP 303 See Other (Theme Plaza)\nHas this theme been approved?");
+ snprintf(err_buf, ERROR_BUFFER_SIZE, language.remote.http303_tp);
goto error;
}
else
{
- snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP 303 See Other\nDownload the resource directly\nor contact the site administrator.");
+ snprintf(err_buf, ERROR_BUFFER_SIZE, language.remote.http303);
goto error;
}
case REDIRECT:
@@ -1040,7 +975,7 @@ redirect: // goto here if we need to redirect
goto redirect;
case SERVER_IS_MISBEHAVING:
DEBUG("Server is misbehaving (provided resource with incorrect MIME)\n");
- snprintf(err_buf, ERROR_BUFFER_SIZE, ZIP_NOT_AVAILABLE);
+ snprintf(err_buf, ERROR_BUFFER_SIZE, zip_not_available);
goto error;
case HTTP_NOT_FOUND:
if (!not_found_is_error)
@@ -1050,59 +985,59 @@ redirect: // goto here if we need to redirect
const char * http_error = parse == HTTP_NOT_FOUND ? "404 Not Found" : "410 Gone";
DEBUG("HTTP %s; URL: %s\n", http_error, url);
if (strstr(url, THEMEPLAZA_BASE_URL) && parse == HTTP_NOT_FOUND)
- snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP 404 Not Found\nHas this theme been approved?");
+ snprintf(err_buf, ERROR_BUFFER_SIZE, language.remote.http404);
else
- snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP %s\nCheck that the URL is correct.", http_error);
+ snprintf(err_buf, ERROR_BUFFER_SIZE, language.remote.http_err_url, http_error);
goto error;
case HTTP_UNACCEPTABLE:
DEBUG("HTTP 406 Unacceptable; Accept: %s\n", acceptable_mime_types);
- snprintf(err_buf, ERROR_BUFFER_SIZE, ZIP_NOT_AVAILABLE);
+ snprintf(err_buf, ERROR_BUFFER_SIZE, zip_not_available);
goto error;
case HTTP_UNAUTHORIZED:
case HTTP_FORBIDDEN:
case HTTP_PROXY_UNAUTHORIZED:
DEBUG("HTTP %u: device not authenticated\n", parse);
- snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP %s\nContact the site administrator.", parse == HTTP_UNAUTHORIZED
- ? "401 Unauthorized"
+ snprintf(err_buf, ERROR_BUFFER_SIZE, language.remote.http_errcode_generic, parse == HTTP_UNAUTHORIZED
+ ? language.remote.http401
: parse == HTTP_FORBIDDEN
- ? "403 Forbidden"
- : "407 Proxy Authentication Required");
+ ? language.remote.http403
+ : language.remote.http407);
goto error;
case HTTP_URI_TOO_LONG:
DEBUG("HTTP 414; URL is too long, maybe too many redirects?\n");
- snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP 414 URI Too Long\nThe QR code points to a really long URL.\nDownload the file directly.");
+ snprintf(err_buf, ERROR_BUFFER_SIZE, language.remote.http414);
goto error;
case HTTP_IM_A_TEAPOT:
DEBUG("HTTP 418 I'm a teapot\n");
- snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP 418 I'm a teapot\nContact the site administrator.");
+ snprintf(err_buf, ERROR_BUFFER_SIZE, language.remote.http418);
goto error;
case HTTP_UPGRADE_REQUIRED:
DEBUG("HTTP 426; HTTP/2 required\n");
- snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP 426 Upgrade Required\nThe 3DS cannot connect to this server.\nContact the site administrator.");
+ snprintf(err_buf, ERROR_BUFFER_SIZE, language.remote.http426);
goto error;
case HTTP_LEGAL_REASONS:
DEBUG("HTTP 451; URL: %s\n", url);
- snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP 451 Unavailable for Legal Reasons\nSome entity is preventing access\nto the host server for legal reasons.");
+ snprintf(err_buf, ERROR_BUFFER_SIZE, language.remote.http451);
goto error;
case HTTP_INTERNAL_SERVER_ERROR:
DEBUG("HTTP 500; URL: %s\n", url);
- snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP 500 Internal Server Error\nContact the site administrator.");
+ snprintf(err_buf, ERROR_BUFFER_SIZE, language.remote.http500);
goto error;
case HTTP_BAD_GATEWAY:
DEBUG("HTTP 502; URL: %s\n", url);
- snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP 502 Bad Gateway\nContact the site administrator.");
+ snprintf(err_buf, ERROR_BUFFER_SIZE, language.remote.http502);
goto error;
case HTTP_SERVICE_UNAVAILABLE:
DEBUG("HTTP 503; URL: %s\n", url);
- snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP 503 Service Unavailable\nContact the site administrator.");
+ snprintf(err_buf, ERROR_BUFFER_SIZE, language.remote.http503);
goto error;
case HTTP_GATEWAY_TIMEOUT:
DEBUG("HTTP 504; URL: %s\n", url);
- snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP 504 Gateway Timeout\nContact the site administrator.");
+ snprintf(err_buf, ERROR_BUFFER_SIZE, language.remote.http504);
goto error;
default:
DEBUG("HTTP %u; URL: %s\n", parse, url);
- snprintf(err_buf, ERROR_BUFFER_SIZE, "HTTP %u\nIf you believe this is unexpected, please\ncontact the site administrator.", parse);
+ snprintf(err_buf, ERROR_BUFFER_SIZE, language.remote.http_unexpected, parse);
goto error;
}
diff --git a/source/splashes.c b/source/splashes.c
index 477fd7d..c2056d8 100644
--- a/source/splashes.c
+++ b/source/splashes.c
@@ -27,6 +27,7 @@
#include "unicode.h"
#include "fs.h"
#include "draw.h"
+#include "ui_strings.h"
void splash_delete(void)
{
@@ -54,7 +55,7 @@ void splash_install(const Entry_s * splash)
if(size == 0 && bottom_size == 0)
{
- throw_error("No splash.bin or splashbottom.bin found.\nIs this a splash?", ERROR_LEVEL_WARNING);
+ throw_error(language.splashes.no_splash_found, ERROR_LEVEL_WARNING);
}
else
{
@@ -65,7 +66,7 @@ void splash_install(const Entry_s * splash)
if(config_buf[0xC] == 0)
{
free(config_buf);
- throw_error("WARNING: Splashes are disabled in Luma Config", ERROR_LEVEL_WARNING);
+ throw_error(language.splashes.splash_disabled, ERROR_LEVEL_WARNING);
}
}
}
@@ -127,4 +128,4 @@ void splash_check_installed(void * void_arg)
}
}
#endif
-}
\ No newline at end of file
+}
diff --git a/source/themes.c b/source/themes.c
index 9075587..337852e 100644
--- a/source/themes.c
+++ b/source/themes.c
@@ -28,6 +28,7 @@
#include "unicode.h"
#include "fs.h"
#include "draw.h"
+#include "ui_strings.h"
#define BODY_CACHE_SIZE 0x150000
#define BGM_MAX_SIZE 0x337000
@@ -81,7 +82,7 @@ static Result install_theme_internal(const Entry_List_s * themes, int installmod
{
free(body);
DEBUG("body not found\n");
- throw_error("No body_LZ.bin found - is this a theme?", ERROR_LEVEL_WARNING);
+ throw_error(language.themes.no_body_found, ERROR_LEVEL_WARNING);
return MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, RD_NOT_FOUND);
}
@@ -118,9 +119,12 @@ static Result install_theme_internal(const Entry_List_s * themes, int installmod
return MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, RD_TOO_LARGE);
}
- if (music[0x62] == 1)
+ if (music_size > 0)
{
- mono_audio = true;
+ if (music[0x62] == 1)
+ {
+ mono_audio = true;
+ }
}
}
@@ -177,7 +181,7 @@ static Result install_theme_internal(const Entry_List_s * themes, int installmod
{
free(body);
DEBUG("body not found\n");
- throw_error("No body_LZ.bin found - is this a theme?", ERROR_LEVEL_WARNING);
+ throw_error(language.themes.no_body_found, ERROR_LEVEL_WARNING);
return MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, RD_NOT_FOUND);
}
@@ -298,7 +302,7 @@ static Result install_theme_internal(const Entry_List_s * themes, int installmod
//----------------------------------------
if (mono_audio)
{
- throw_error("One or more installed themes use mono audio.\nMono audio causes a number of issues.\nCheck the wiki for more information.", ERROR_LEVEL_WARNING);
+ throw_error(language.themes.mono_warn, ERROR_LEVEL_WARNING);
}
return 0;
}
@@ -342,7 +346,7 @@ dir_name_callback(void * data, const char ** ppMessage, const char * text, size_
(void)data;
if(strpbrk(text, "><\"?;:/\\+,.|[=]"))
{
- *ppMessage = "Illegal character used.";
+ *ppMessage = language.themes.illegal_char;
return SWKBD_CALLBACK_CONTINUE;
}
return SWKBD_CALLBACK_OK;
@@ -356,10 +360,10 @@ Result dump_current_theme(void)
SwkbdState swkbd;
swkbdInit(&swkbd, SWKBD_TYPE_WESTERN, 2, max_chars);
- swkbdSetHintText(&swkbd, "Name of output folder");
+ swkbdSetHintText(&swkbd, language.themes.name_folder);
- swkbdSetButton(&swkbd, SWKBD_BUTTON_LEFT, "Cancel", false);
- swkbdSetButton(&swkbd, SWKBD_BUTTON_RIGHT, "Done", true);
+ swkbdSetButton(&swkbd, SWKBD_BUTTON_LEFT, language.themes.cancel, false);
+ swkbdSetButton(&swkbd, SWKBD_BUTTON_RIGHT, language.themes.done, true);
swkbdSetValidation(&swkbd, SWKBD_NOTEMPTY_NOTBLANK, 0, max_chars);
swkbdSetFilterCallback(&swkbd, dir_name_callback, NULL);
diff --git a/source/ui_strings.c b/source/ui_strings.c
new file mode 100644
index 0000000..1a452f1
--- /dev/null
+++ b/source/ui_strings.c
@@ -0,0 +1,381 @@
+/*
+* This file is part of Anemone3DS
+* Copyright (C) 2016-2024 Contributors in CONTRIBUTORS.md
+*
+* 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 "ui_strings.h"
+#include "fs.h"
+
+const Language_s language_english = {
+ .normal_instructions =
+ {
+ {
+ .info_line = NULL,
+ .instructions = {
+ {
+ "\uE000 Install Theme(s)",
+ "\uE001 Queue shuffle theme"
+ },
+ {
+ "\uE002 More options",
+ "\uE003 Preview theme"
+ },
+ {
+ "\uE004 Switch to splashes",
+ "\uE005 Scan QR code"
+ },
+ {
+ "Exit",
+ "Delete from SD"
+ }
+ }
+ },
+ {
+ .info_line = NULL,
+ .instructions = {
+ {
+ "\uE000 Install splash",
+ "\uE001 Delete installed splash"
+ },
+ {
+ "\uE002 More options",
+ "\uE003 Preview splash"
+ },
+ {
+ "\uE004 Switch to themes",
+ "\uE005 Scan QR code"
+ },
+ {
+ "Exit",
+ "Delete from SD"
+ }
+ }
+ }
+ },
+
+ .install_instructions =
+ {
+ .info_line = "\uE001 Cancel theme install",
+ .instructions = {
+ {
+ "\uE079 Normal install",
+ "\uE07A Shuffle install"
+ },
+ {
+ "\uE07B BGM-only install",
+ "\uE07C No-BGM install"
+ },
+ {
+ NULL,
+ NULL
+ },
+ {
+ "Exit",
+ NULL
+ }
+ }
+ },
+
+ .extra_instructions =
+ {
+ {
+ .info_line = "\uE001 Leave sorting menu",
+ .instructions = {
+ {
+ "\uE079 Sort by name",
+ "\uE07A Sort by author"
+ },
+ {
+ "\uE07B Sort by filename",
+ NULL
+ },
+ {
+ NULL,
+ NULL
+ },
+ {
+ "Exit",
+ NULL
+ }
+ }
+ },
+ {
+ .info_line = "\uE001 Leave extra menu",
+ .instructions = {
+ {
+ "\uE079 Jump in the list",
+ "\uE07A Reload broken icons"
+ },
+ {
+ "\uE07B Browse ThemePlaza",
+ NULL
+ },
+ {
+ "\uE004 Sorting menu",
+ "\uE005 Dumping menu"
+ },
+ {
+ "Exit",
+ NULL
+ }
+ }
+ },
+ {
+ .info_line = "\uE001 Leave dump menu",
+ .instructions = {
+ {
+ "\uE079 Dump Current Theme",
+ "\uE07A Dump All Themes"
+ },
+ {
+ NULL,
+ NULL
+ },
+ {
+ NULL,
+ NULL
+ },
+ {
+ "Exit",
+ NULL
+ }
+ }
+ }
+ },
+ .camera =
+ {
+ .quit = "Press \uE005 To Quit",
+ .thread_error = "Capture cam thread creation failed\nPlease report this to the developers",
+ .zip_not_theme_splash = "Zip downloaded is neither\na splash nor a theme",
+ .file_not_zip = "File downloaded isn't a zip.",
+ .download_failed = "Download failed.",
+ },
+ .draw =
+ {
+ .theme_mode = "Theme mode",
+ .splash_mode = "Splash mode",
+ .no_themes = "No theme found",
+ .no_splashes = "No splash found",
+ .qr_download = "Press \uE005 to download from QR",
+ .switch_splashes = "Or \uE004 to switch to splashes",
+ .switch_themes = "Or \uE004 to switch to themes",
+ .quit = "Or to quit",
+ .start_pos = 162, // Adjust x pos of start glyph to line up with quit string
+ .by = "By ",
+ .selected = "Selected:",
+ .sel = "Sel.:",
+ .tp_theme_mode = "ThemePlaza Theme mode",
+ .tp_splash_mode = "ThemePlaza Splash mode",
+ .search = "Search...",
+ .page = "Page:",
+ .err_quit = "Press \uE000 to quit.",
+ .warn_continue = "Press \uE000 to continue.",
+ .yes_no = "\uE000 Yes \uE001 No",
+ .load_themes = "Loading themes, please wait...",
+ .load_splash = "Loading splashes, please wait...",
+ .load_icons = "Loading icons, please wait...",
+ .install_splash = "Installing a splash...",
+ .delete_splash = "Deleting installed splash...",
+ .install_theme = "Installing a single theme...",
+ .install_shuffle = "Installing shuffle themes...",
+ .install_bgm = "Installing BGM-only theme...",
+ .install_no_bgm = "Installing theme without BGM...",
+ .downloading = "Downloading...",
+ .checking_dl = "Checking downloaded file...",
+ .delete_sd = "Deleting from SD...",
+ .download_themes = "Downloading theme list, please wait...",
+ .download_splashes = "Downloading splash list, please wait...",
+ .download_preview = "Downloading preview, please wait...",
+ .download_bgm = "Downloading BGM, please wait...",
+ .dump_single = "Dumping theme, please wait...",
+ .dump_all_official = "Dumping official themes, please wait...",
+ },
+ .fs =
+ {
+ .illegal_input = "Input must not contain:\n" ILLEGAL_CHARS,
+ .new_or_overwrite = "Choose a new filename or tap Overwrite",
+ .cancel = "Cancel",
+ .overwrite = "Overwrite",
+ .rename = "Rename",
+ .swkbd_fail = "???\nTry a USB keyboard", // Should never be used
+ .sd_full = "SD card is full.\nDelete some themes to make space.",
+ .fs_error = "Error:\nGet a new SD card.",
+ },
+ .loading =
+ {
+ .no_preview = "No preview found.",
+ },
+ .main =
+ {
+ .position_too_big = "The new position has to be\nsmaller or equal to the\nnumber of entries!",
+ .position_zero = "The new position has to\nbe positive!",
+ .jump_q = "Where do you want to jump to?\nMay cause icons to reload.",
+ .cancel = "Cancel",
+ .jump = "Jump",
+ .no_theme_extdata = "Theme extdata does not exist!\nSet a default theme from the home menu.",
+ .loading_qr = "Loading QR Scanner...",
+ .no_wifi = "Please connect to Wi-Fi before scanning QR codes",
+ .qr_homebrew = "QR scanning doesnt work from the Homebrew\nLauncher, use the ThemePlaza browser instead.",
+ .camera_broke = "Your camera seems to have a problem,\nunable to scan QR codes.",
+ .too_many_themes = "You have too many themes selected.",
+ .not_enough_themes = "You don't have enough themes selected.",
+ .uninstall_confirm = "Are you sure you would like to delete\nthe installed splash?",
+ .delete_confirm = "Are you sure you would like to delete this?",
+ },
+ .remote =
+ {
+ .no_results = "No results for this search.",
+ .check_wifi = "Couldn't download Theme Plaza data.\nMake sure WiFi is on.",
+ .new_page_big = "The new page has to be\nsmaller or equal to the\nnumber of pages!",
+ .new_page_zero = "The new position has to\nbe positive!",
+ .jump_page = "Which page do you want to jump to?",
+ .cancel = "Cancel",
+ .jump = "Jump",
+ .tags = "Which tags do you want to search for?",
+ .search = "Search",
+ .parental_fail = "Parental Control validation failed!\nBrowser Access restricted.",
+ .zip_not_found = "ZIP not found at this URL\nIf you believe this is an error, please\ncontact the site administrator",
+ .generic_httpc_error = "Error in HTTPC sysmodule - 0x%08lx.\nIf you are seeing this, please contact an\nAnemone developer on the Theme Plaza Discord.",
+ .http303_tp = "HTTP 303 See Other (Theme Plaza)\nHas this theme been approved?",
+ .http303 = "HTTP 303 See Other\nDownload the resource directly\nor contact the site administrator.",
+ .http404 = "HTTP 404 Not Found\nHas this theme been approved?",
+ .http_err_url = "HTTP %s\nCheck that the URL is correct.",
+ .http_errcode_generic = "HTTP %s\nContact the site administrator.",
+ .http401 = "401 Unauthorized",
+ .http403 = "403 Forbidden",
+ .http407 = "407 Proxy Authentication Required",
+ .http414 = "HTTP 414 URI Too Long\nThe QR code points to a really long URL.\nDownload the file directly.",
+ .http418 = "HTTP 418 I'm a teapot\nContact the site administrator.",
+ .http426 = "HTTP 426 Upgrade Required\nThe 3DS cannot connect to this server.\nContact the site administrator.",
+ .http451 = "HTTP 451 Unavailable for Legal Reasons\nSome entity is preventing access\nto the host server for legal reasons.",
+ .http500 = "HTTP 500 Internal Server Error\nContact the site administrator.",
+ .http502 = "HTTP 502 Bad Gateway\nContact the site administrator.",
+ .http503 = "HTTP 503 Service Unavailable\nContact the site administrator.",
+ .http504 = "HTTP 504 Gateway Timeout\nContact the site administrator.",
+ .http_unexpected = "HTTP %u\nIf you believe this is unexpected, please\ncontact the site administrator.",
+ },
+ .remote_instructions =
+ {
+ {
+ .info_line = NULL,
+ .instructions = {
+ {
+ "\uE000 Download theme",
+ "\uE001 Go back"
+ },
+ {
+ "\uE002 Hold for more",
+ "\uE003 Preview theme"
+ },
+ {
+ "\uE004 Previous page",
+ "\uE005 Next page"
+ },
+ {
+ "Exit",
+ NULL
+ }
+ }
+ },
+ {
+ .info_line = NULL,
+ .instructions = {
+ {
+ "\uE000 Download splash",
+ "\uE001 Go back"
+ },
+ {
+ "\uE002 Hold for more",
+ "\uE003 Preview splash"
+ },
+ {
+ "\uE004 Previous page",
+ "\uE005 Next page"
+ },
+ {
+ "Exit",
+ NULL
+ }
+ }
+ }
+ },
+ .remote_extra_instructions =
+ {
+ .info_line = "Release \uE002 to cancel or hold \uE006 and release \uE002 to do stuff",
+ .instructions = {
+ {
+ "\uE079 Jump to page",
+ "\uE07A Search tags"
+ },
+ {
+ "\uE07B Toggle splash/theme",
+ "\uE07C Reload without cache"
+ },
+ {
+ NULL,
+ NULL
+ },
+ {
+ "Exit",
+ NULL
+ }
+ }
+ },
+ .splashes =
+ {
+ .no_splash_found = "No splash.bin or splashbottom.bin found.\nIs this a splash?",
+ .splash_disabled = "WARNING: Splashes are disabled in Luma Config",
+ },
+ .themes =
+ {
+ .no_body_found = "No body_LZ.bin found - is this a theme?",
+ .mono_warn = "One or more installed themes use mono audio.\nMono audio causes a number of issues.\nCheck the wiki for more information.",
+ .illegal_char = "Illegal character used.",
+ .name_folder = "Name of output folder",
+ .cancel = "Cancel",
+ .done = "Done"
+ }
+};
+
+Language_s init_strings(CFG_Language lang)
+{
+ switch (lang)
+ {
+ case CFG_LANGUAGE_JP:
+ case CFG_LANGUAGE_FR:
+ case CFG_LANGUAGE_DE:
+ case CFG_LANGUAGE_IT:
+ case CFG_LANGUAGE_ES:
+ case CFG_LANGUAGE_ZH:
+ case CFG_LANGUAGE_KO:
+ case CFG_LANGUAGE_NL:
+ case CFG_LANGUAGE_PT:
+ case CFG_LANGUAGE_RU:
+ case CFG_LANGUAGE_TW:
+ case CFG_LANGUAGE_EN:
+ return language_english;
+ default:
+ return language_english;
+ }
+}