62 Commits

Author SHA1 Message Date
24810a48ad Make sure that the buffer text is copied into is properly null-terminated 2017-09-29 21:56:44 -04:00
Dylan G
5d2119344a Getting ever closer to fixing the SMDH bug 2017-09-30 02:10:33 +01:00
Dylan G
492ea13ef6 Fixing a bad fix of mine '_>' 2017-09-30 02:00:00 +01:00
Helloman892
f99f744000 fixed theme extdata corruption when installing shuffle themes after
scanning a qr code
2017-09-16 17:48:47 +01:00
4fb10029bb Merge branch 'master' of github.com:3dsfug/Anemone3DS 2017-09-11 09:49:03 -04:00
7644974705 Add check for WiFi when scanning with QR code 2017-09-11 09:48:52 -04:00
Dylan G
b7379af2f3 added trello link 2017-09-10 14:57:26 +01:00
26d8c283b3 Add warning about splashes being disabled 2017-09-09 20:19:30 -04:00
4ceac06f0c improve no splashes interface 2017-09-09 20:12:10 -04:00
337693ca13 Improve no themes interface and create folders on boot 2017-09-09 20:10:36 -04:00
8ba1fed5d7 Change QR reader behavior, speed up 2017-09-09 11:33:54 -04:00
Helloman892
d99f1c97a0 fixes splash install
If splash.bin and/or splashbottom.bin didn't already exist, splashes would not install.

Also added a line break to separate splash_delete(), for consistency.
2017-09-09 13:07:31 +01:00
ZetaDesigns
1a1b3e25b0 Quick fix II - The sequel 2017-09-09 11:54:50 +02:00
c92c20d4e8 Quick fix 2017-09-09 00:26:40 -04:00
ef456c7e9e Splash previews 2017-09-09 00:12:16 -04:00
1103885baf Splash QR codes 2017-09-08 23:34:16 -04:00
5564ffe31b Merge branch 'master' of github.com:3dsfug/Anemone3DS 2017-09-08 23:26:59 -04:00
97ab2307f8 Slightly improve QR code speed 2017-09-08 23:26:49 -04:00
ZetaDesigns
47c64828a4 Merge branch 'master' of https://github.com/astronautlevel2/Anemone3DS 2017-09-08 23:18:41 +02:00
d3aa231c3f Update pp2d 2017-09-08 15:59:32 -04:00
Helloman892
3fb86c80be finally fixed everything
homebrew wasn't actually global, smh
2017-09-08 20:00:21 +01:00
ZetaDesigns
67566330a5 fix indentation and **properly** fix the compile error 2017-09-08 20:52:26 +02:00
68805337bf Merge branch 'master' of github.com:3dsfug/Anemone3DS 2017-09-08 14:04:53 -04:00
Helloman892
416cca88d3 fixing compile error
Upon attempting to build the previous commit, I discovered that Zeta was referring to a var that wasn't declared. Fixed.
2017-09-08 17:57:57 +01:00
2be3bde64d Merge branch 'master' of github.com:3dsfug/Anemone3DS 2017-09-08 07:21:34 -04:00
c46c5ff8cb More CAMU stuff 2017-09-08 07:21:31 -04:00
Helloman892
6b5b391d7b finally got theme deletion working + qr stuff
Theme deletion [SDMC] now works, although no button currently has it assigned. The QR reader now works properly with Unicode filenames.
2017-09-07 22:36:44 +01:00
ZetaDesigns
dc1cbda232 you saw nothing 2017-09-07 22:45:15 +02:00
ZetaDesigns
e63a4066a1 error codes now properly pause 2017-09-07 22:43:32 +02:00
2e71fc5954 Draw SMDH info 2017-09-07 13:55:52 -04:00
778e1a8331 maybe fix splashes 2017-09-07 13:35:56 -04:00
0871f4f30b Break QR code reader trying to make it faster 2017-09-07 13:08:38 -04:00
62f4356a17 Change splashes to support SMDH and zip files 2017-09-07 10:08:52 -04:00
ZetaDesigns
3e2c5994ca fix dabort when no theme data
themes still wont install like this
2017-09-06 18:33:23 +02:00
ZetaDesigns
674fa9d9bf add "downloading" text to qrcode scanning
i know it's not the prettiest idea to put it in draw_theme_install, but it seemed like the most fitting, and i didnt want to create another function for it
2017-09-06 17:49:10 +02:00
Nils P
897dc52424 Merge pull request #64 from saibotu/pr-bgmcrash
Fixed crash when installing themes without bgm
2017-09-06 17:03:51 +02:00
saibotu
379cea8db1 Fixed crash when installing themes without bgm 2017-09-06 15:36:02 +02:00
saibotu
e46783a3c4 Made buf_to_file always return Result 2017-09-06 15:35:31 +02:00
Helloman892
3fd4548d64 Merge pull request #62 from thedax/warning-fix
Fix potential bugs and two warnings relating to them
2017-09-06 10:19:07 +01:00
thedax
34ede05b93 Fix potential bugs and two warnings relating to them
Memset doesn't automatically set the entire size of each element, it's necessary to multiply by sizeof(<typename>) if it's larger than 1 byte, which in this case, u16, is (two bytes).
2017-09-06 05:01:42 -04:00
Helloman892
80b9aa9cdb Merge pull request #60 from Uyuiyu/master
Fix build warning
2017-09-06 09:20:46 +01:00
Uyuiyu
33cce81914 signed 2017-09-06 02:16:03 +02:00
Nils P
424fffd35f Merge pull request #57 from astronautlevel2/zeta-patch
Make Errorcodes great again (well, sorta)
2017-09-05 21:40:17 +02:00
ZetaDesigns
5b067cfac0 fixing some indentation 2017-09-05 21:37:48 +02:00
ZetaDesigns
539e95253c finish up basic errorcode functions 2017-09-05 21:31:50 +02:00
ZetaDesigns
a77b29da92 add errorcodes 2017-09-05 21:15:19 +02:00
Helloman892
dcac5401c1 several text drawing edits
All info.smdh fields now wrap after 300-odd pixels.
2017-09-05 13:10:43 +01:00
Helloman892
1467b1f72b Merge branch 'master' of https://github.com/astronautlevel2/Anemone3DS 2017-09-05 10:57:20 +01:00
Helloman892
9199936215 per PR #52 2017-09-05 10:56:00 +01:00
Helloman892
91fa4fa412 Resolves #22 (#52)
3 commits squashed and merged
2017-09-05 10:55:21 +01:00
Helloman892
1c6ae493d5 Merge pull request #51 from astronautlevel2/hm892
Fast paging [issue #14]
2017-09-05 01:30:33 +01:00
Helloman892
4eb969e84d fast page scrolling 2017-09-05 01:25:48 +01:00
Helloman892
70a40fae44 issue #14 commit for review (#50) 2017-09-04 19:25:52 -04:00
Helloman892
3d17509229 Merge pull request #49 from Helloman892/master
Resolving #35 as best as possible
2017-09-04 22:50:06 +01:00
Helloman892
a38508c30f undoes part of commit d3a8f79 2017-09-04 22:43:42 +01:00
Helloman892
0ddb35d3d7 see #35
percentage bar isn't practical.
counter was quite simple.
2017-09-04 22:41:26 +01:00
Helloman892
e03d150840 Merge pull request #45 from GreatWizard/optimiz_images
Clean battery images and reduce png size
2017-09-04 21:25:57 +01:00
Guillaume Gérard
4607885fe6 Clean battery images and reduce png size 2017-09-04 22:11:52 +02:00
Helloman892
d3a8f79958 beginnings of shuffled theme counter + a couple qr bugfixes 2017-09-04 20:13:09 +01:00
Helloman892
a08c032ccc Update main.c 2017-09-04 19:54:38 +01:00
Helloman892
bdaa8b52cc Update themes.c 2017-09-04 19:53:41 +01:00
Helloman892
8dc7f54f7e attempt to allow 10 themes to be installed 2017-09-04 19:46:55 +01:00
25 changed files with 556 additions and 207 deletions

View File

@@ -49,11 +49,13 @@ ICON_FLAGS := nosavebackups,visible
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft
CFLAGS := -g -Wall -Wextra -mword-relocations \ CFLAGS := -g -Wall -Wextra -O2 -mword-relocations \
-ffunction-sections \ -ffunction-sections \
$(ARCH) $(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS -D_GNU_SOURCE revision := $(shell git describe --tags --match v[0-9]* --abbrev=8 | sed 's/-[0-9]*-g/-/')
CFLAGS += $(INCLUDE) -DARM11 -D_3DS -D_GNU_SOURCE -DVERSION="\"$(revision)\""
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11

View File

@@ -1,11 +1,13 @@
![# Anemone3DS](https://github.com/astronautlevel2/Anemone3DS/blob/master/meta/banner.png) ![# Anemone3DS](https://github.com/astronautlevel2/Anemone3DS/blob/master/meta/banner.png)
A Theme and Splashscreen Manager for the Nintendo3DS, written in C. A Theme and Splashscreen Manager for the Nintendo 3DS, written in C.\
To-do list here: https://trello.com/b/F1YSa1VK
# Dependencies # Dependencies
* zlib, which can be retrieved from the [3ds_portlibs](https://github.com/devkitPro/3ds_portlibs). * zlib, which can be retrieved from the [3ds_portlibs](https://github.com/devkitPro/3ds_portlibs).
* [makerom](https://github.com/profi200/Project_CTR) and [bannertool](https://github.com/Steveice10/buildtools), which can be retrieved from [SteveIce10's](https://github.com/Steveice10) buildtools repo. These must be added to your PATH. * [makerom](https://github.com/profi200/Project_CTR) and [bannertool](https://github.com/Steveice10/buildtools), which can be retrieved from [SteveIce10's](https://github.com/Steveice10) buildtools repo. These must be added to your PATH.
* [pp2d](https://github.com/BernardoGiordano/pp2d), which is included in the repo if you do a git clone --recursive. * [pp2d](https://github.com/BernardoGiordano/pp2d), which is included in the repo if you do a git clone --recursive.
* Git needs to be on your PATH, if building in a non-*nix environment.
# Building # Building
First of all, make sure devkitPRO is properly installed and added to the PATH. First of all, make sure devkitPRO is properly installed and added to the PATH.
After that, open the directory you want to clone the repo into, and type: `git clone https://github.com/astronautlevel2/Anemone3DS/ --recursive`. After that, open the directory you want to clone the repo into, and type: `git clone https://github.com/astronautlevel2/Anemone3DS/ --recursive`.

View File

@@ -29,8 +29,6 @@
#include "common.h" #include "common.h"
struct quirc* context;
u16 *buf;
bool qr_mode; bool qr_mode;
void init_qr(void); void init_qr(void);

View File

@@ -40,9 +40,16 @@
#define SHUFFLE_INSTALL 1 #define SHUFFLE_INSTALL 1
#define BGM_INSTALL 2 #define BGM_INSTALL 2
#define UNINSTALL 3 #define UNINSTALL 3
#define DOWNLOADING 3
#define ERROR 0
#define WARNING 1
static const int THEMES_PER_SCREEN = 4; static const int THEMES_PER_SCREEN = 4;
bool homebrew;
bool splash_mode;
int shuffle_theme_count;
enum TextureID { 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,

View File

@@ -34,11 +34,11 @@
void init_screens(void); void init_screens(void);
void exit_screens(void); void exit_screens(void);
void draw_themext_error(void);
void draw_base_interface(void); void draw_base_interface(void);
void draw_qr(void);
void draw_theme_install(int install_type); void draw_theme_install(int install_type);
void draw_theme_interface(Theme_s * themes_list, int theme_count, int selected_theme, bool preview_mode); void draw_theme_interface(Theme_s * themes_list, int theme_count, int selected_theme, bool preview_mode, int shuffle_theme_count);
void draw_splash_install(int install_type); void draw_splash_install(int install_type);
void draw_splash_interface(Splash_s *splashes_list, int splash_count, int selected_splash, bool preview_mode); void draw_splash_interface(Splash_s *splashes_list, int splash_count, int selected_splash, bool preview_mode);
void throw_error(char* error, int error_type);
#endif #endif

View File

@@ -39,7 +39,7 @@ Result close_archives(void);
u64 file_to_buf(FS_Path path, FS_Archive archive, char** buf); u64 file_to_buf(FS_Path path, FS_Archive archive, char** buf);
u32 zip_file_to_buf(char *file_name, u16 *zip_path, char **buf); u32 zip_file_to_buf(char *file_name, u16 *zip_path, char **buf);
u32 buf_to_file(u32 size, char *path, FS_Archive archive, char *buf); Result buf_to_file(u32 size, char *path, FS_Archive archive, char *buf);
void remake_file(char *path, FS_Archive archive, u32 size); void remake_file(char *path, FS_Archive archive, u32 size);
#endif #endif

View File

@@ -30,12 +30,23 @@
#include "common.h" #include "common.h"
typedef struct{ typedef struct{
u16 name[0x106]; u16 name[0x40];
u16 top_path[0x106]; u16 desc[0x80];
u16 bottom_path[0x106]; u16 author[0x40];
u32 placeholder_color;
ssize_t icon_id;
u16 path[0x106];
bool is_zip;
} Splash_s; } Splash_s;
Splash_s *splashes_list;
int splash_count;
Result get_splashes(Splash_s** splashes_list, int *splash_count); Result get_splashes(Splash_s** splashes_list, int *splash_count);
void splash_install(Splash_s splash_to_install); void splash_install(Splash_s splash_to_install);
void splash_delete(); void splash_delete();
void load_splash_preview(Splash_s *splash);
#endif #endif

View File

@@ -30,9 +30,9 @@
#include "common.h" #include "common.h"
typedef struct { typedef struct {
u16 name[0x40]; u16 name[0x41];
u16 desc[0x80]; u16 desc[0x81];
u16 author[0x40]; u16 author[0x41];
u32 placeholder_color; u32 placeholder_color;
ssize_t icon_id; ssize_t icon_id;
@@ -51,7 +51,7 @@ int theme_count;
void load_theme_preview(Theme_s *theme); 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);
void add_theme(Theme_s **themes_list, int *theme_count, char *path, char *filename); void del_theme(u16 *path);
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);
Result bgm_install(Theme_s bgm_to_install); Result bgm_install(Theme_s bgm_to_install);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 443 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 272 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 272 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 272 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 806 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 449 B

After

Width:  |  Height:  |  Size: 466 B

View File

@@ -30,20 +30,34 @@
#include "draw.h" #include "draw.h"
#include "fs.h" #include "fs.h"
#include "themes.h" #include "themes.h"
#include "pp2d/pp2d/pp2d.h"
u32 transfer_size;
Handle event;
struct quirc* context;
void init_qr(void) void init_qr(void)
{ {
camInit(); camInit();
CAMU_SetSize(SELECT_OUT1_OUT2, SIZE_CTR_TOP_LCD, CONTEXT_A); CAMU_SetSize(SELECT_OUT1_OUT2, SIZE_CTR_TOP_LCD, CONTEXT_A);
CAMU_SetOutputFormat(SELECT_OUT1_OUT2, OUTPUT_RGB_565, CONTEXT_A); CAMU_SetOutputFormat(SELECT_OUT1_OUT2, OUTPUT_RGB_565, CONTEXT_A);
CAMU_SetFrameRate(SELECT_OUT1_OUT2, FRAME_RATE_10);
CAMU_SetNoiseFilter(SELECT_OUT1_OUT2, true); CAMU_SetNoiseFilter(SELECT_OUT1_OUT2, true);
CAMU_SetAutoExposure(SELECT_OUT1_OUT2, true); CAMU_SetAutoExposure(SELECT_OUT1_OUT2, true);
CAMU_SetAutoWhiteBalance(SELECT_OUT1_OUT2, true); CAMU_SetAutoWhiteBalance(SELECT_OUT1_OUT2, true);
CAMU_SetTrimming(PORT_CAM1, false); CAMU_SetTrimming(PORT_CAM1, false);
CAMU_SetTrimming(PORT_CAM2, false);
buf = malloc(sizeof(u16) * 400 * 240 * 2); CAMU_GetMaxBytes(&transfer_size, 400, 240);
CAMU_SetTransferBytes(PORT_BOTH, transfer_size, 400, 240);
CAMU_Activate(SELECT_OUT1_OUT2);
event = 0;
CAMU_ClearBuffer(PORT_BOTH);
CAMU_SynchronizeVsyncTiming(SELECT_OUT1, SELECT_OUT2);
CAMU_StartCapture(PORT_BOTH);
context = quirc_new(); context = quirc_new();
quirc_resize(context, 400, 240); quirc_resize(context, 400, 240);
@@ -51,27 +65,83 @@ void init_qr(void)
void exit_qr(void) void exit_qr(void)
{ {
CAMU_StopCapture(PORT_BOTH);
CAMU_Activate(SELECT_NONE); CAMU_Activate(SELECT_NONE);
camExit(); camExit();
quirc_destroy(context); quirc_destroy(context);
free(buf); }
void scan_qr(u16 *buf)
{
int w;
int h;
u8 *image = (u8*) quirc_begin(context, &w, &h);
for (ssize_t x = 0; x < w; x++)
{
for (ssize_t y = 0; y < h; y++)
{
u16 px = buf[y * 400 + x];
image[y * w + x] = (u8)(((((px >> 11) & 0x1F) << 3) + (((px >> 5) & 0x3F) << 2) + ((px & 0x1F) << 3)) / 3);
}
}
quirc_end(context);
if (quirc_count(context) > 0)
{
struct quirc_code code;
struct quirc_data data;
quirc_extract(context, 0, &code);
if (!quirc_decode(&code, &data))
{
qr_mode = false;
http_get((char*)data.payload, splash_mode ? "/Splashes/" : "/Themes/");
}
}
} }
void take_picture(void) void take_picture(void)
{ {
u32 transfer_size; u16 *buf = malloc(sizeof(u16) * 400 * 240 * 4);
Handle cam_handle = 0; if (buf == NULL) return;
CAMU_GetMaxBytes(&transfer_size, 400, 240); CAMU_SetReceiving(&event, buf, PORT_CAM1, 240 * 400 * 2, transfer_size);
CAMU_SetTransferBytes(PORT_BOTH, transfer_size, 400, 240); svcWaitSynchronization(event, U64_MAX);
CAMU_Activate(SELECT_OUT1_OUT2); svcCloseHandle(event);
CAMU_ClearBuffer(PORT_BOTH); pp2d_begin_draw(GFX_TOP);
CAMU_SynchronizeVsyncTiming(SELECT_OUT1, SELECT_OUT2); u32 *rgba8_buf = malloc(240 * 400 * sizeof(u32));
CAMU_StartCapture(PORT_BOTH); if (rgba8_buf == NULL) return;
CAMU_SetReceiving(&cam_handle, buf, PORT_CAM1, 400 * 240 * 2, transfer_size); for (int i = 0; i < 240 * 400; i++)
svcWaitSynchronization(cam_handle, U64_MAX); {
rgba8_buf[i] = RGB565_TO_ABGR8(buf[i]);
}
pp2d_load_texture_memory(TEXTURE_QR, rgba8_buf, 400, 240);
pp2d_draw_texture(TEXTURE_QR, 0, 0);
pp2d_draw_rectangle(0, 216, 400, 24, RGBA8(55, 122, 168, 255));
pp2d_draw_text_center(GFX_TOP, 220, 0.5, 0.5, RGBA8(255, 255, 255, 255), "Press \uE005 To Quit");
pp2d_draw_rectangle(0, 0, 400, 24, RGBA8(55, 122, 168, 255));
pp2d_draw_text_center(GFX_TOP, 4, 0.5, 0.5, RGBA8(255, 255, 255, 255), "Press \uE004 To Scan");
pp2d_end_draw();
free(rgba8_buf);
pp2d_free_texture(TEXTURE_QR);
hidScanInput();
u32 kDown = hidKeysDown();
if (kDown & KEY_L)
{
CAMU_StopCapture(PORT_BOTH); CAMU_StopCapture(PORT_BOTH);
svcCloseHandle(cam_handle); CAMU_Activate(SELECT_NONE);
CAMU_Activate(PORT_NONE); scan_qr(buf);
CAMU_Activate(SELECT_OUT1_OUT2);
CAMU_StartCapture(PORT_BOTH);
}
if (kDown & KEY_R)
{
exit_qr();
qr_mode = false;
}
free(buf);
} }
/* /*
@@ -96,7 +166,7 @@ Result http_get(char *url, char *path)
ret = httpcSetKeepAlive(&context, HTTPC_KEEPALIVE_ENABLED); ret = httpcSetKeepAlive(&context, HTTPC_KEEPALIVE_ENABLED);
ret = httpcAddRequestHeaderField(&context, "User-Agent", "Anemone3DS/1.1.0"); ret = httpcAddRequestHeaderField(&context, "User-Agent", "Anemone3DS/1.1.0");
ret = httpcAddRequestHeaderField(&context, "Connection", "Keep-Alive"); ret = httpcAddRequestHeaderField(&context, "Connection", "Keep-Alive");
draw_theme_install(DOWNLOADING);
ret = httpcBeginRequest(&context); ret = httpcBeginRequest(&context);
if (ret != 0) if (ret != 0)
{ {
@@ -158,9 +228,9 @@ Result http_get(char *url, char *path)
filename = strtok(NULL, "\""); filename = strtok(NULL, "\"");
char *illegal_characters = "\"?;:/\\+"; char *illegal_characters = "\"?;:/\\+";
for (ssize_t i = 0; i < strlen(filename); i++) for (size_t i = 0; i < strlen(filename); i++)
{ {
for (ssize_t n = 0; n < strlen(illegal_characters); n++) for (size_t n = 0; n < strlen(illegal_characters); n++)
{ {
if (filename[i] == illegal_characters[n]) if (filename[i] == illegal_characters[n])
{ {
@@ -201,7 +271,8 @@ Result http_get(char *url, char *path)
remake_file(path_to_file, ArchiveSD, size); remake_file(path_to_file, ArchiveSD, size);
buf_to_file(size, path_to_file, ArchiveSD, (char*)buf); buf_to_file(size, path_to_file, ArchiveSD, (char*)buf);
add_theme(&themes_list, &theme_count, path_to_file, filename); if (splash_mode) get_splashes(&splashes_list, &splash_count);
else get_themes(&themes_list, &theme_count);
exit_qr(); exit_qr();

View File

@@ -25,18 +25,22 @@
*/ */
#include "draw.h" #include "draw.h"
#include "common.h"
#include "pp2d/pp2d/pp2d.h" #include "pp2d/pp2d/pp2d.h"
#include "quirc/quirc.h" #include "quirc/quirc.h"
#include <time.h> #include <time.h>
enum Colors { enum Colors {
COLOR_BACKGROUND = ABGR8(255, 32, 28, 35), //silver-y black COLOR_BACKGROUND = ABGR8(255, 32, 28, 35), //silver-y black
COLOR_ACCENT = RGBA8(55, 122, 168, 255), COLOR_ACCENT = RGBA8(55, 122, 168, 255),
COLOR_WHITE = RGBA8(255, 255, 255, 255), COLOR_WHITE = RGBA8(255, 255, 255, 255),
COLOR_CURSOR = RGBA8(200, 200, 200, 255), COLOR_CURSOR = RGBA8(200, 200, 200, 255),
COLOR_BLACK = RGBA8(0, 0, 0, 255), COLOR_BLACK = RGBA8(0, 0, 0, 255),
COLOR_RED = RGBA8(200, 0, 0, 255),
COLOR_YELLOW = RGBA8(239, 220, 11, 255),
}; };
void init_screens(void) void init_screens(void)
@@ -64,55 +68,9 @@ void exit_screens(void)
static int theme_vertical_scroll = 0; static int theme_vertical_scroll = 0;
static int splash_vertical_scroll = 0; static int splash_vertical_scroll = 0;
void draw_qr(void) void draw_themext_error(void)
{ {
pp2d_begin_draw(GFX_TOP); throw_error("Theme extdata does not exist\nSet a default theme from the home menu", ERROR);
pp2d_free_texture(TEXTURE_QR);
take_picture();
u32 *rgba8_buf = malloc(240 * 400 * sizeof(u32));
for (int i = 0; i < 240 * 400; i++)
{
rgba8_buf[i] = RGB565_TO_RGBA8(buf[i]);
u8 *byte_pointer = (u8*)&rgba8_buf[i];
u8 r = *(byte_pointer+3);
u8 g = *(byte_pointer+2);
u8 b = *(byte_pointer+1);
u8 a = *(byte_pointer);
rgba8_buf[i] = RGBA8(r, g, b, a);
}
pp2d_load_texture_memory(TEXTURE_QR, rgba8_buf, 400, 240);
pp2d_draw_texture(TEXTURE_QR, 0, 0);
free(rgba8_buf);
pp2d_end_draw();
int w;
int h;
u8 *image = (u8*) quirc_begin(context, &w, &h);
for (ssize_t x = 0; x < w; x++)
{
for (ssize_t y = 0; y < h; y++)
{
u16 px = buf[y * 400 + x];
image[y * w + x] = (u8)(((((px >> 11) & 0x1F) << 3) + (((px >> 5) & 0x3F) << 2) + ((px & 0x1F) << 3)) / 3);
}
}
quirc_end(context);
if (quirc_count(context) > 0)
{
struct quirc_code code;
struct quirc_data data;
quirc_extract(context, 0, &code);
if (!quirc_decode(&code, &data))
{
qr_mode = false;
http_get((char*)data.payload, "/Themes/");
}
}
} }
void draw_base_interface(void) void draw_base_interface(void)
@@ -139,22 +97,60 @@ void draw_base_interface(void)
pp2d_draw_on(GFX_BOTTOM); pp2d_draw_on(GFX_BOTTOM);
pp2d_draw_rectangle(0, 0, 320, 24, COLOR_ACCENT); pp2d_draw_rectangle(0, 0, 320, 24, COLOR_ACCENT);
pp2d_draw_rectangle(0, 216, 320, 24, COLOR_ACCENT); pp2d_draw_rectangle(0, 216, 320, 24, COLOR_ACCENT);
pp2d_draw_text(7, 219, 0.6, 0.6, COLOR_WHITE, VERSION);
pp2d_draw_on(GFX_TOP); pp2d_draw_on(GFX_TOP);
} }
void throw_error(char* error, int error_type) {
switch (error_type) {
case ERROR:
while (aptMainLoop())
{
hidScanInput();
u32 kDown = hidKeysDown();
draw_base_interface();
pp2d_draw_text_center(GFX_TOP, 120, 0.6, 0.6, COLOR_RED, error);
pp2d_draw_wtext_center(GFX_TOP, 150, 0.6, 0.6, COLOR_WHITE, L"Press \uE000 to shut down.");
pp2d_end_draw();
if (kDown & KEY_A) {
if (homebrew)
APT_HardwareResetAsync();
else {
srvPublishToSubscriber(0x202, 0);
}
}
}
case WARNING:
while (aptMainLoop())
{
hidScanInput();
u32 kDown = hidKeysDown();
draw_base_interface();
pp2d_draw_text_center(GFX_TOP, 120, 0.6, 0.6, COLOR_YELLOW, error);
pp2d_draw_wtext_center(GFX_TOP, 150, 0.6, 0.6, COLOR_WHITE, L"Press \uE000 to continue.");
pp2d_end_draw();
if (kDown & KEY_A) break;
}
break;
}
pp2d_end_draw();
}
void draw_theme_install(int install_type) void draw_theme_install(int install_type)
{ {
draw_base_interface(); draw_base_interface();
switch(install_type) switch(install_type)
{ {
case 0: case 0:
pp2d_draw_text(20, 30, 0.7, 0.7, COLOR_WHITE, "Installing a single theme..."); pp2d_draw_text_center(GFX_TOP, 120, 0.8, 0.8, COLOR_WHITE, "Installing a single theme...");
break; break;
case 1: case 1:
pp2d_draw_text(20, 30, 0.7, 0.7, COLOR_WHITE, "Installing a shuffle theme..."); pp2d_draw_text_center(GFX_TOP, 120, 0.8, 0.8, COLOR_WHITE, "Installing a shuffle theme...");
break; break;
case 2: case 2:
pp2d_draw_text(20, 30, 0.7, 0.7, COLOR_WHITE, "Installing BGM..."); pp2d_draw_text_center(GFX_TOP, 120, 0.8, 0.8, COLOR_WHITE, "Installing BGM...");
break;
case 3:
pp2d_draw_text_center(GFX_TOP, 120, 0.8, 0.8, COLOR_WHITE, "Downloading...");
break; break;
default: default:
break; break;
@@ -162,13 +158,15 @@ void draw_theme_install(int install_type)
pp2d_end_draw(); pp2d_end_draw();
} }
void draw_theme_interface(Theme_s * themes_list, int theme_count, int selected_theme, bool preview_mode) void draw_theme_interface(Theme_s * themes_list, int theme_count, int selected_theme, bool preview_mode, int shuffle_theme_count)
{ {
if (themes_list == NULL) if (themes_list == NULL)
{ {
pp2d_begin_draw(GFX_TOP); draw_base_interface();
pp2d_draw_text_center(GFX_TOP, 100, 1, 1, COLOR_WHITE, "NO THEMES FOUND"); pp2d_draw_text_center(GFX_TOP, 80, 0.7, 0.7, COLOR_YELLOW, "No themes found!");
pp2d_draw_text_center(GFX_TOP, 110, 0.7, 0.7, COLOR_YELLOW, "Press \uE005 to download from QR");
pp2d_draw_text_center(GFX_TOP, 140, 0.7, 0.7, COLOR_YELLOW, "Or \uE045 to quit");
pp2d_end_draw(); pp2d_end_draw();
return; return;
} }
@@ -189,16 +187,16 @@ void draw_theme_interface(Theme_s * themes_list, int theme_count, int selected_t
{ {
draw_base_interface(); draw_base_interface();
pp2d_draw_text_center(GFX_TOP, 4, 0.5, 0.5, COLOR_WHITE, "Theme mode"); pp2d_draw_text_center(GFX_TOP, 4, 0.5, 0.5, COLOR_WHITE, "Theme mode");
wchar_t title[0x40] = {0}; wchar_t title[0x41] = {0};
utf16_to_utf32((u32*)title, current_theme.name, 0x40); utf16_to_utf32((u32*)title, current_theme.name, 0x40);
pp2d_draw_wtext(20, 30, 0.7, 0.7, COLOR_WHITE, title); pp2d_draw_wtext_wrap(20, 30, 0.7, 0.7, COLOR_WHITE, 380, title);
wchar_t author[0x40] = {0}; wchar_t author[0x41] = {0};
utf16_to_utf32((u32*)author, current_theme.author, 0x40); utf16_to_utf32((u32*)author, current_theme.author, 0x40);
pp2d_draw_text(20, 50, 0.5, 0.5, COLOR_WHITE, "By: "); pp2d_draw_text(20, 50, 0.5, 0.5, COLOR_WHITE, "By: ");
pp2d_draw_wtext(44, 50, 0.5, 0.5, COLOR_WHITE, author); pp2d_draw_wtext_wrap(44, 50, 0.5, 0.5, COLOR_WHITE, 380, author);
wchar_t description[0x80] = {0}; wchar_t description[0x81] = {0};
utf16_to_utf32((u32*)description, current_theme.desc, 0x80); utf16_to_utf32((u32*)description, current_theme.desc, 0x80);
pp2d_draw_wtext(20, 65, 0.5, 0.5, COLOR_WHITE, description); pp2d_draw_wtext_wrap(20, 65, 0.5, 0.5, COLOR_WHITE, 363, description);
pp2d_draw_wtext(20, 150, 0.6, 0.6, COLOR_WHITE, L"\uE046 Install Shuffle Theme"); pp2d_draw_wtext(20, 150, 0.6, 0.6, COLOR_WHITE, L"\uE046 Install Shuffle Theme");
pp2d_draw_wtext(200, 150, 0.6, 0.6, COLOR_WHITE, L"\uE004 Switch to Splashes"); pp2d_draw_wtext(200, 150, 0.6, 0.6, COLOR_WHITE, L"\uE004 Switch to Splashes");
@@ -209,6 +207,8 @@ void draw_theme_interface(Theme_s * themes_list, int theme_count, int selected_t
pp2d_draw_wtext(130, 120, 0.6, 0.6, COLOR_WHITE, L"\uE005 Scan QRCode"); pp2d_draw_wtext(130, 120, 0.6, 0.6, COLOR_WHITE, L"\uE005 Scan QRCode");
pp2d_draw_on(GFX_BOTTOM); pp2d_draw_on(GFX_BOTTOM);
pp2d_draw_textf(7, 3, 0.6, 0.6, COLOR_WHITE, "Selected: %i/10", shuffle_theme_count);
// Scroll the menu up or down if the selected theme is out of its bounds // Scroll the menu up or down if the selected theme is out of its bounds
//---------------------------------------------------------------- //----------------------------------------------------------------
for (int i = 0; i < theme_count; i++) { for (int i = 0; i < theme_count; i++) {
@@ -269,10 +269,10 @@ void draw_splash_install(int install_type)
switch (install_type) switch (install_type)
{ {
case SINGLE_INSTALL: case SINGLE_INSTALL:
pp2d_draw_textf(20, 30, 0.7, 0.7, COLOR_WHITE, "Installing a splash..."); pp2d_draw_text_center(GFX_TOP, 110, 0.7, 0.7, COLOR_WHITE, "Installing a splash...");
break; break;
case UNINSTALL: case UNINSTALL:
pp2d_draw_textf(20, 30, 0.7, 0.7, COLOR_WHITE, "Uninstalling a splash..."); pp2d_draw_text_center(GFX_TOP, 110, 0.7, 0.7, COLOR_WHITE, "Uninstalling a splash...");
break; break;
default: default:
break; break;
@@ -284,23 +284,39 @@ void draw_splash_interface(Splash_s *splashes_list, int splash_count, int select
{ {
if (splashes_list == NULL) if (splashes_list == NULL)
{ {
pp2d_begin_draw(GFX_TOP); draw_base_interface();
pp2d_draw_text_center(GFX_TOP, 100, 1, 1, COLOR_WHITE, "NO SPLASHES FOUND"); pp2d_draw_text_center(GFX_TOP, 80, 0.7, 0.7, COLOR_YELLOW, "No splashes found!");
pp2d_draw_text_center(GFX_TOP, 110, 0.7, 0.7, COLOR_YELLOW, "Press \uE005 to download from QR");
pp2d_draw_text_center(GFX_TOP, 140, 0.7, 0.7, COLOR_YELLOW, "Or \uE045 to quit");
pp2d_end_draw(); pp2d_end_draw();
return; return;
} }
Splash_s current_splash = splashes_list[selected_splash]; Splash_s current_splash = splashes_list[selected_splash];
if (preview_mode) if (preview_mode)
{ {
// TODO: Splash Previews pp2d_begin_draw(GFX_TOP);
pp2d_draw_texture_part(TEXTURE_PREVIEW, 0, 0, 0, 0, 400, 240);
pp2d_draw_on(GFX_BOTTOM);
pp2d_draw_texture_part(TEXTURE_PREVIEW, 0, 0, 40, 240, 320, 240);
} else { } else {
draw_base_interface(); draw_base_interface();
pp2d_draw_text_center(GFX_TOP, 4, 0.5, 0.5, COLOR_WHITE, "Splash mode"); pp2d_draw_text_center(GFX_TOP, 4, 0.5, 0.5, COLOR_WHITE, "Splash mode");
wchar_t title[0x40] = {0};
utf16_to_utf32((u32*)title, current_splash.name, 0x40);
pp2d_draw_wtext_wrap(20, 30, 0.7, 0.7, COLOR_WHITE, 380, title);
wchar_t author[0x40] = {0};
utf16_to_utf32((u32*)author, current_splash.author, 0x40);
pp2d_draw_text(20, 50, 0.5, 0.5, COLOR_WHITE, "By: ");
pp2d_draw_wtext_wrap(44, 50, 0.5, 0.5, COLOR_WHITE, 380, author);
wchar_t description[0xa6] = {0};
utf16_to_utf32((u32*)description, current_splash.desc, 0xb0);
pp2d_draw_wtext_wrap(20, 65, 0.5, 0.5, COLOR_WHITE, 363, description);
pp2d_draw_wtext_center(GFX_TOP, 180, 0.7, 0.7, COLOR_WHITE, L"\uE000 Install Splash \uE004 Switch to Themes"); pp2d_draw_wtext_center(GFX_TOP, 180, 0.7, 0.7, COLOR_WHITE, L"\uE000 Install Splash \uE004 Switch to Themes");
pp2d_draw_wtext_center(GFX_TOP, 210, 0.7, 0.7, COLOR_WHITE, L"\uE002 Delete current Splash"); pp2d_draw_wtext_center(GFX_TOP, 210, 0.7, 0.7, COLOR_WHITE, L"\uE002 Delete current Splash");
pp2d_draw_wtext_center(GFX_TOP, 150, 0.7, 0.7, COLOR_WHITE, L"\uE003 Preview Splash \uE005 Scan QRCode");
pp2d_draw_wtext(130, 120, 0.6, 0.6, COLOR_WHITE, L"");
pp2d_draw_on(GFX_BOTTOM); pp2d_draw_on(GFX_BOTTOM);
for (int i = 0; i < splash_count; i++) { for (int i = 0; i < splash_count; i++) {
if (splash_count <= THEMES_PER_SCREEN) if (splash_count <= THEMES_PER_SCREEN)
@@ -337,7 +353,12 @@ void draw_splash_interface(Splash_s *splashes_list, int splash_count, int select
font_color = COLOR_BLACK; font_color = COLOR_BLACK;
pp2d_draw_rectangle(0, 24 + vertical_offset, 320, 48, COLOR_CURSOR); 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_draw_wtext(54, 40 + vertical_offset, 0.55, 0.55, font_color, name);
if (!current_splash.placeholder_color)
pp2d_draw_texture(current_splash.icon_id, 0, 24 + vertical_offset);
else
pp2d_draw_rectangle(0, 24 + vertical_offset, 48, 48, current_splash.placeholder_color);
} }
} }
pp2d_end_draw(); pp2d_end_draw();

View File

@@ -38,7 +38,7 @@ int filename_compare(__attribute__((unused)) unzFile file, const char *current_f
Result open_archives(void) Result open_archives(void)
{ {
romfsInit();
u8 regionCode; u8 regionCode;
u32 archive1; u32 archive1;
u32 archive2; u32 archive2;
@@ -68,9 +68,13 @@ Result open_archives(void)
archive2 = 0x00; archive2 = 0x00;
} }
retValue = FSUSER_OpenArchive(&ArchiveSD, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, "")); retValue = FSUSER_OpenArchive(&ArchiveSD, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""));
if(R_FAILED(retValue)) return retValue; if(R_FAILED(retValue)) return retValue;
FSUSER_CreateDirectory(ArchiveSD, fsMakePath(PATH_ASCII, "/Themes"), FS_ATTRIBUTE_DIRECTORY);
FSUSER_CreateDirectory(ArchiveSD, fsMakePath(PATH_ASCII, "/Splashes"), FS_ATTRIBUTE_DIRECTORY);
u32 homeMenuPath[3] = {MEDIATYPE_SD, archive2, 0}; u32 homeMenuPath[3] = {MEDIATYPE_SD, archive2, 0};
home.type = PATH_BINARY; home.type = PATH_BINARY;
home.size = 0xC; home.size = 0xC;
@@ -85,7 +89,11 @@ Result open_archives(void)
retValue = FSUSER_OpenArchive(&ArchiveThemeExt, ARCHIVE_EXTDATA, theme); retValue = FSUSER_OpenArchive(&ArchiveThemeExt, ARCHIVE_EXTDATA, theme);
if(R_FAILED(retValue)) return retValue; if(R_FAILED(retValue)) return retValue;
romfsInit(); Handle test_handle;
retValue = FSUSER_OpenFile(&test_handle, ArchiveThemeExt, fsMakePath(PATH_ASCII, "/ThemeManage.bin"), FS_OPEN_READ, 0);
if(R_FAILED(retValue)) return retValue;
FSFILE_Close(test_handle);
return 0; return 0;
} }
@@ -111,7 +119,7 @@ u64 file_to_buf(FS_Path path, FS_Archive archive, char** buf)
u64 size; u64 size;
FSFILE_GetSize(file, &size); FSFILE_GetSize(file, &size);
*buf = malloc(size); *buf = calloc(1, size);
FSFILE_Read(file, NULL, 0, *buf, size); FSFILE_Read(file, NULL, 0, *buf, size);
FSFILE_Close(file); FSFILE_Close(file);
return size; return size;
@@ -135,7 +143,7 @@ u32 zip_file_to_buf(char *file_name, u16 *zip_path, char **buf)
unz_file_info *file_info = malloc(sizeof(unz_file_info)); unz_file_info *file_info = malloc(sizeof(unz_file_info));
unzGetCurrentFileInfo(zip_handle, file_info, NULL, 0, NULL, 0, NULL, 0); unzGetCurrentFileInfo(zip_handle, file_info, NULL, 0, NULL, 0, NULL, 0);
file_size = file_info->uncompressed_size; file_size = file_info->uncompressed_size;
*buf = malloc(file_size); *buf = calloc(1, file_size);
unzOpenCurrentFile(zip_handle); unzOpenCurrentFile(zip_handle);
unzReadCurrentFile(zip_handle, *buf, file_size); unzReadCurrentFile(zip_handle, *buf, file_size);
unzCloseCurrentFile(zip_handle); unzCloseCurrentFile(zip_handle);
@@ -151,17 +159,16 @@ u32 zip_file_to_buf(char *file_name, u16 *zip_path, char **buf)
} }
} }
u32 buf_to_file(u32 size, char *path, FS_Archive archive, char *buf) Result buf_to_file(u32 size, char *path, FS_Archive archive, char *buf)
{ {
Handle handle; Handle handle;
u32 bytes = 0;
Result res = FSUSER_OpenFile(&handle, archive, fsMakePath(PATH_ASCII, path), FS_OPEN_WRITE, 0); Result res = FSUSER_OpenFile(&handle, archive, fsMakePath(PATH_ASCII, path), FS_OPEN_WRITE, 0);
if (R_FAILED(res)) return res; if (R_FAILED(res)) return res;
res = FSFILE_Write(handle, &bytes, 0, buf, size, FS_WRITE_FLUSH); res = FSFILE_Write(handle, NULL, 0, buf, size, FS_WRITE_FLUSH);
if (R_FAILED(res)) return res; if (R_FAILED(res)) return res;
res = FSFILE_Close(handle); res = FSFILE_Close(handle);
if (R_FAILED(res)) return res; if (R_FAILED(res)) return res;
return bytes; return 0;
} }
void remake_file(char *path, FS_Archive archive, u32 size) void remake_file(char *path, FS_Archive archive, u32 size)

View File

@@ -33,14 +33,16 @@
#include <time.h> #include <time.h>
int __stacksize__ = 64 * 1024; int __stacksize__ = 64 * 1024;
Result archive_result;
int init_services(void) int init_services(void)
{ {
cfguInit(); cfguInit();
ptmuInit(); ptmuInit();
acInit();
httpcInit(0); httpcInit(0);
open_archives(); archive_result = open_archives();
bool homebrew = true; homebrew = true;
if (!envIsHomebrew()) if (!envIsHomebrew())
{ {
homebrew = false; homebrew = false;
@@ -61,6 +63,7 @@ int exit_services(void)
cfguExit(); cfguExit();
ptmuExit(); ptmuExit();
httpcExit(); httpcExit();
acExit();
return 0; return 0;
} }
@@ -79,8 +82,8 @@ int main(void)
free(themes_list); free(themes_list);
themes_list = NULL; themes_list = NULL;
} }
int splash_count = 0; splash_count = 0;
Splash_s *splashes_list = NULL; splashes_list = NULL;
res = get_splashes(&splashes_list, &splash_count); res = get_splashes(&splashes_list, &splash_count);
if (R_FAILED(res)) if (R_FAILED(res))
{ {
@@ -89,11 +92,11 @@ int main(void)
splashes_list = NULL; splashes_list = NULL;
} }
bool splash_mode = false; splash_mode = false;
int selected_splash = 0; int selected_splash = 0;
int selected_theme = 0; int selected_theme = 0;
int previously_selected = 0; int previously_selected = 0;
int shuffle_theme_count = 0; shuffle_theme_count = 0;
bool preview_mode = false; bool preview_mode = false;
while(aptMainLoop()) while(aptMainLoop())
@@ -104,10 +107,10 @@ int main(void)
if (qr_mode) if (qr_mode)
{ {
draw_qr(); take_picture();
} else if (!splash_mode) } else if (!splash_mode)
{ {
draw_theme_interface(themes_list, theme_count, selected_theme, preview_mode); draw_theme_interface(themes_list, theme_count, selected_theme, preview_mode, shuffle_theme_count);
} else { } else {
draw_splash_interface(splashes_list, splash_count, selected_splash, preview_mode); draw_splash_interface(splashes_list, splash_count, selected_splash, preview_mode);
} }
@@ -123,15 +126,31 @@ int main(void)
else if (kDown & KEY_L) else if (kDown & KEY_L)
{ {
splash_mode = !splash_mode; splash_mode = !splash_mode;
} else if (kDown & KEY_R) }
if (R_FAILED(archive_result) && !splash_mode)
{ {
if (splash_mode || preview_mode) { draw_themext_error();
continue;
}
if (kDown & KEY_R)
{
if (preview_mode) {
continue; continue;
} else { } else {
u32 out;
ACU_GetWifiStatus(&out);
if (out)
{
qr_mode = !qr_mode; qr_mode = !qr_mode;
if (qr_mode) init_qr(); if (qr_mode) init_qr();
else exit_qr(); else exit_qr();
continue; continue;
} else {
throw_error("Please connect to Wi-Fi before scanning QR", WARNING);
continue;
}
} }
} }
@@ -149,11 +168,17 @@ int main(void)
if (kDown & KEY_Y) if (kDown & KEY_Y)
{ {
if (!preview_mode) if (!preview_mode)
{
if (!splash_mode)
{ {
if (!current_theme->has_preview) if (!current_theme->has_preview)
load_theme_preview(current_theme); load_theme_preview(current_theme);
preview_mode = current_theme->has_preview; preview_mode = current_theme->has_preview;
} else {
load_splash_preview(current_splash);
preview_mode = true;
}
} }
else else
preview_mode = false; preview_mode = false;
@@ -185,6 +210,13 @@ int main(void)
draw_theme_install(SINGLE_INSTALL); draw_theme_install(SINGLE_INSTALL);
single_install(*current_theme); single_install(*current_theme);
} }
//these are here just so I don't forget how to implement them - HM
//if (current_theme->in_shuffle) {
// shuffle_theme_count--;
// current_theme->in_shuffle = false;
//}
//del_theme(current_theme->path);
//get_themes(&themes_list, &theme_count);
} }
else if (kDown & KEY_B) else if (kDown & KEY_B)
@@ -217,6 +249,7 @@ int main(void)
{ {
draw_theme_install(SHUFFLE_INSTALL); draw_theme_install(SHUFFLE_INSTALL);
shuffle_install(themes_list, theme_count); shuffle_install(themes_list, theme_count);
shuffle_theme_count = 0;
} }
} }
} }
@@ -302,6 +335,32 @@ int main(void)
selected_theme = 0; selected_theme = 0;
} }
} }
else if (kDown & KEY_CPAD_LEFT)
{
svcSleepThread(100000000);
if (splash_mode)
{
selected_splash -= 4;
if (selected_splash < 0) selected_splash = 0;
} else {
selected_theme -= 4;
if (selected_theme < 0) selected_theme = 0;
}
}
else if (kDown & KEY_CPAD_RIGHT)
{
svcSleepThread(100000000);
if (splash_mode)
{
selected_splash += 4;
if (selected_splash >= splash_count) selected_splash = splash_count-1;
} else {
selected_theme += 4;
if (selected_theme >= theme_count) selected_theme = theme_count-1;
}
}
if (!splash_mode && selected_theme != previously_selected) if (!splash_mode && selected_theme != previously_selected)
{ {

View File

@@ -26,6 +26,126 @@
#include "splashes.h" #include "splashes.h"
#include "unicode.h" #include "unicode.h"
#include "fs.h" #include "fs.h"
#include "themes.h"
#include "pp2d/pp2d/pp2d.h"
#include "draw.h"
void load_splash_preview(Splash_s *splash)
{
//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 (!(splash->is_zip))
{
u16 path_to_preview[0x106] = {0};
strucat(path_to_preview, splash->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", splash->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;
}
}
pp2d_load_texture_memory(TEXTURE_PREVIEW, image, (u32)width, (u32)height);
}
free(image);
free(preview_buffer);
}
static void parse_smdh(Splash_s *splash, ssize_t textureID, u16 *splash_name)
{
char *info_buffer = NULL;
u64 size = 0;
if (!(splash->is_zip))
{
u16 path_to_smdh[0x106] = {0};
strucat(path_to_smdh, splash->path);
struacat(path_to_smdh, "/info.smdh");
size = file_to_buf(fsMakePath(PATH_UTF16, path_to_smdh), ArchiveSD, &info_buffer);
} else {
size = zip_file_to_buf("info.smdh", splash->path, &info_buffer);
}
if (!size)
{
free(info_buffer);
memset(splash->name, 0, 0x80);
memset(splash->desc, 0, 0x100);
memset(splash->author, 0, 0x80);
memcpy(splash->name, splash_name, 0x80);
utf8_to_utf16(splash->desc, (u8*)"No description", 0x100);
utf8_to_utf16(splash->author, (u8*)"Unknown author", 0x80);
splash->placeholder_color = RGBA8(rand() % 255, rand() % 255, rand() % 255, 255);
return;
}
memcpy(splash->name, info_buffer + 0x08, 0x80);
memcpy(splash->desc, info_buffer + 0x88, 0x100);
memcpy(splash->author, info_buffer + 0x188, 0x80);
u16 *icon_data = malloc(0x1200);
memcpy(icon_data, info_buffer + 0x24C0, 0x1200);
const u32 width = 48, height = 48;
u32 *image = malloc(width*height*sizeof(u32));
for (u32 x = 0; x < width; x++)
{
for (u32 y = 0; y < height; y++)
{
unsigned int dest_pixel = (x + y*width);
unsigned int source_pixel = (((y >> 3) * (width >> 3) + (x >> 3)) << 6) + ((x & 1) | ((y & 1) << 1) | ((x & 2) << 1) | ((y & 2) << 2) | ((x & 4) << 2) | ((y & 4) << 3));
u8 r = ((icon_data[source_pixel] >> 11) & 0b11111) << 3;
u8 g = ((icon_data[source_pixel] >> 5) & 0b111111) << 2;
u8 b = (icon_data[source_pixel] & 0b11111) << 3;
u8 a = 0xFF;
image[dest_pixel] = (r << 24) | (g << 16) | (b << 8) | a;
}
}
pp2d_load_texture_memory(textureID, (u8*)image, (u32)width, (u32)height);
splash->icon_id = textureID;
free(image);
free(icon_data);
free(info_buffer);
}
Result get_splashes(Splash_s** splashes_list, int *splash_count) Result get_splashes(Splash_s** splashes_list, int *splash_count)
{ {
@@ -35,6 +155,13 @@ Result get_splashes(Splash_s** splashes_list, int *splash_count)
if (R_FAILED(res)) if (R_FAILED(res))
return res; return res;
if (*splashes_list != NULL)
{
free(*splashes_list);
*splashes_list = NULL;
*splash_count = 0;
}
u32 entries_read = 1; u32 entries_read = 1;
while (entries_read) while (entries_read)
{ {
@@ -43,7 +170,7 @@ Result get_splashes(Splash_s** splashes_list, int *splash_count)
if (R_FAILED(res) || entries_read == 0) if (R_FAILED(res) || entries_read == 0)
break; break;
if (!(entry.attributes & FS_ATTRIBUTE_DIRECTORY)) if (!(entry.attributes & FS_ATTRIBUTE_DIRECTORY) && strcmp(entry.shortExt, "ZIP"))
continue; continue;
*splash_count += entries_read; *splash_count += entries_read;
@@ -57,56 +184,87 @@ Result get_splashes(Splash_s** splashes_list, int *splash_count)
u16 splash_path[0x106]= {0}; u16 splash_path[0x106]= {0};
struacat(splash_path, SPLASHES_PATH); struacat(splash_path, SPLASHES_PATH);
strucat(splash_path, entry.name); 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; char pathchar[0x106] = {0};
u32 bytes = file_to_buf(fsMakePath(PATH_UTF16, top_path), ArchiveSD, &temp_buf); utf16_to_utf8((u8*) pathchar, splash_path, 0x106);
if (!bytes)
{ memcpy(current_splash->path, splash_path, 0x106 * sizeof(u16));
memset(top_path, 0, 0x106); current_splash->is_zip = !strcmp(entry.shortExt, "ZIP");
}
free(temp_buf); ssize_t iconID = TEXTURE_PREVIEW + theme_count + *splash_count;
temp_buf = NULL; parse_smdh(current_splash, iconID, entry.name);
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); FSDIR_Close(dir_handle);
return res; return res;
} }
void splash_delete() void splash_delete()
{ {
remove("/luma/splash.bin"); remove("/luma/splash.bin");
remove("/luma/splashbottom.bin"); remove("/luma/splashbottom.bin");
} }
void splash_install(Splash_s splash_to_install) void splash_install(Splash_s splash_to_install)
{ {
char *screen_buf; char *screen_buf = NULL;
u32 size = file_to_buf(fsMakePath(PATH_UTF16, splash_to_install.top_path), ArchiveSD, &screen_buf); u32 size = 0;
if (splash_to_install.is_zip)
{
size = zip_file_to_buf("splash.bin", splash_to_install.path, &screen_buf);
if (size) if (size)
{ {
remake_file("/luma/splash.bin", ArchiveSD, size); remake_file("/luma/splash.bin", ArchiveSD, sizeof(screen_buf));
buf_to_file(size, "/luma/splash.bin", ArchiveSD, screen_buf); buf_to_file(size, "/luma/splash.bin", ArchiveSD, screen_buf);
free(screen_buf); free(screen_buf);
screen_buf = NULL;
size = 0;
} }
size = file_to_buf(fsMakePath(PATH_UTF16, splash_to_install.bottom_path), ArchiveSD, &screen_buf); size = zip_file_to_buf("splashbottom.bin", splash_to_install.path, &screen_buf);
if (size) if (size)
{ {
remake_file("/luma/splashbottom.bin", ArchiveSD, size); remake_file("/luma/splashbottom.bin", ArchiveSD, sizeof(screen_buf));
buf_to_file(size, "/luma/splashbottom.bin", ArchiveSD, screen_buf); buf_to_file(size, "/luma/splashbottom.bin", ArchiveSD, screen_buf);
free(screen_buf); free(screen_buf);
screen_buf = NULL;
size = 0;
}
} else {
u16 path[0x106] = {0};
memcpy(path, splash_to_install.path, 0x106 * sizeof(u16));
struacat(path, "/splash.bin");
size = file_to_buf(fsMakePath(PATH_UTF16, path), ArchiveSD, &screen_buf);
if (size)
{
remake_file("/luma/splash.bin", ArchiveSD, sizeof(screen_buf));
buf_to_file(size, "/luma/splash.bin", ArchiveSD, screen_buf);
free(screen_buf);
screen_buf = NULL;
size = 0;
}
memcpy(path, splash_to_install.path, 0x106 * sizeof(u16));
struacat(path, "/splashbottom.bin");
size = file_to_buf(fsMakePath(PATH_UTF16, path), ArchiveSD, &screen_buf);
if (size)
{
remake_file("/luma/splashbottom.bin", ArchiveSD, sizeof(screen_buf));
buf_to_file(size, "/luma/splashbottom.bin", ArchiveSD, screen_buf);
free(screen_buf);
screen_buf = NULL;
size = 0;
}
}
char *config_buf;
size = file_to_buf(fsMakePath(PATH_ASCII, "/luma/config.bin"), ArchiveSD, &config_buf);
if (size)
{
if (config_buf[0xC] == 0)
{
free(config_buf);
throw_error("WARNING: Splashes are disabled in Luma Config", WARNING);
}
} }
} }

View File

@@ -152,13 +152,22 @@ static void parse_smdh(Theme_s *theme, ssize_t textureID, u16 *dir_name)
Result get_themes(Theme_s **themes_list, int *theme_count) Result get_themes(Theme_s **themes_list, int *theme_count)
{ {
shuffle_theme_count = 0;
Result res = 0; Result res = 0;
Handle dir_handle; Handle dir_handle;
res = FSUSER_OpenDirectory(&dir_handle, ArchiveSD, fsMakePath(PATH_ASCII, THEMES_PATH)); res = FSUSER_OpenDirectory(&dir_handle, ArchiveSD, fsMakePath(PATH_ASCII, THEMES_PATH));
if (R_FAILED(res)) if (R_FAILED(res))
return res; return res;
if (*themes_list != NULL) //used for QR reading and also for theme deletion
{
free(*themes_list);
*themes_list = NULL;
*theme_count = 0;
}
u32 entries_read = 1; u32 entries_read = 1;
while (entries_read) while (entries_read)
{ {
FS_DirectoryEntry entry = {0}; FS_DirectoryEntry entry = {0};
@@ -196,25 +205,18 @@ Result get_themes(Theme_s **themes_list, int *theme_count)
return res; return res;
} }
void add_theme(Theme_s **themes_list, int *theme_count, char *path, char *filename) void del_theme(u16 *path)
{ {
*theme_count += 1; Handle dir_handle;
*themes_list = realloc(*themes_list, (*theme_count) * sizeof(Theme_s)); Result res = FSUSER_OpenDirectory(&dir_handle, ArchiveSD, fsMakePath(PATH_UTF16, path));
if (R_SUCCEEDED(res))
Theme_s *current_theme = &(*themes_list)[*theme_count - 1]; {
memset(current_theme, 0, sizeof(Theme_s)); FSDIR_Close(dir_handle);
FSUSER_DeleteDirectoryRecursively(ArchiveSD, fsMakePath(PATH_UTF16, path));
u16 theme_path[0x106] = {0}; } else
utf8_to_utf16(theme_path, (u8*)path, 0x106); {
FSUSER_DeleteFile(ArchiveSD, fsMakePath(PATH_UTF16, path));
u16 ufilename[0x106] = {0}; }
utf8_to_utf16(ufilename, (u8*)filename, 0x106);
memcpy(current_theme->path, theme_path, 0x106 * sizeof(u16));
current_theme->is_zip = true;
ssize_t iconID = TEXTURE_PREVIEW + *theme_count;
parse_smdh(current_theme, iconID, ufilename);
} }
Result bgm_install(Theme_s bgm_to_install) Result bgm_install(Theme_s bgm_to_install)
@@ -230,9 +232,11 @@ Result bgm_install(Theme_s bgm_to_install)
memset(&savedata_buf[0x13b8], 0, 8); memset(&savedata_buf[0x13b8], 0, 8);
savedata_buf[0x13bd] = 3; savedata_buf[0x13bd] = 3;
savedata_buf[0x13b8] = 0xff; savedata_buf[0x13b8] = 0xff;
u32 size = buf_to_file(savedata_size, "/SaveData.dat", ArchiveHomeExt, savedata_buf); Result result = buf_to_file(savedata_size, "/SaveData.dat", ArchiveHomeExt, savedata_buf);
free(savedata_buf); free(savedata_buf);
if (!R_SUCCEEDED(result)) return result;
if (bgm_to_install.is_zip) // Same as above but this time with bgm if (bgm_to_install.is_zip) // Same as above but this time with bgm
{ {
music_size = zip_file_to_buf("bgm.bcstm", bgm_to_install.path, &music); music_size = zip_file_to_buf("bgm.bcstm", bgm_to_install.path, &music);
@@ -245,7 +249,6 @@ Result bgm_install(Theme_s bgm_to_install)
if (music_size == 0) if (music_size == 0)
{ {
free(music);
music = calloc(1, 3371008); music = calloc(1, 3371008);
} else if (music_size > 3371008) { } else if (music_size > 3371008) {
free(music); free(music);
@@ -253,10 +256,10 @@ Result bgm_install(Theme_s bgm_to_install)
return MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, RD_TOO_LARGE); return MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, RD_TOO_LARGE);
} }
size = buf_to_file(music_size, "/BgmCache.bin", ArchiveThemeExt, music); result = buf_to_file(music_size == 0 ? 3371008 : music_size, "/BgmCache.bin", ArchiveThemeExt, music);
free(music); free(music);
if (size == 0) return MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, RD_NOT_FOUND); if (!R_SUCCEEDED(result)) return result;
file_to_buf(fsMakePath(PATH_ASCII, "/ThemeManage.bin"), ArchiveThemeExt, &thememanage_buf); file_to_buf(fsMakePath(PATH_ASCII, "/ThemeManage.bin"), ArchiveThemeExt, &thememanage_buf);
thememanage_buf[0x00] = 1; thememanage_buf[0x00] = 1;
@@ -280,9 +283,11 @@ Result bgm_install(Theme_s bgm_to_install)
memset(&thememanage_buf[0x340], 0, 4); memset(&thememanage_buf[0x340], 0, 4);
memset(&thememanage_buf[0x360], 0, 4); memset(&thememanage_buf[0x360], 0, 4);
memset(&thememanage_buf[0x368], 0, 4); memset(&thememanage_buf[0x368], 0, 4);
size = buf_to_file(0x800, "/ThemeManage.bin", ArchiveThemeExt, thememanage_buf); result = buf_to_file(0x800, "/ThemeManage.bin", ArchiveThemeExt, thememanage_buf);
free(thememanage_buf); free(thememanage_buf);
if (!R_SUCCEEDED(result)) return result;
return 0; return 0;
} }
@@ -302,9 +307,11 @@ Result single_install(Theme_s theme_to_install)
memset(&savedata_buf[0x13b8], 0, 8); memset(&savedata_buf[0x13b8], 0, 8);
savedata_buf[0x13bd] = 3; savedata_buf[0x13bd] = 3;
savedata_buf[0x13b8] = 0xff; savedata_buf[0x13b8] = 0xff;
u32 size = buf_to_file(savedata_size, "/SaveData.dat", ArchiveHomeExt, savedata_buf); Result result = buf_to_file(savedata_size, "/SaveData.dat", ArchiveHomeExt, savedata_buf);
free(savedata_buf); free(savedata_buf);
if (!R_SUCCEEDED(result)) return result;
// Open body cache file. Test if theme is zipped // Open body cache file. Test if theme is zipped
if (theme_to_install.is_zip) if (theme_to_install.is_zip)
{ {
@@ -325,10 +332,10 @@ Result single_install(Theme_s theme_to_install)
return MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, RD_NOT_FOUND); return MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, RD_NOT_FOUND);
} }
size = buf_to_file(body_size, "/BodyCache.bin", ArchiveThemeExt, body); // Write body data to file result = buf_to_file(body_size, "/BodyCache.bin", ArchiveThemeExt, body); // Write body data to file
free(body); free(body);
if (size == 0) return MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, RD_NOT_FOUND); if (!R_SUCCEEDED(result)) return result;
if (theme_to_install.is_zip) // Same as above but this time with bgm if (theme_to_install.is_zip) // Same as above but this time with bgm
{ {
@@ -342,7 +349,6 @@ Result single_install(Theme_s theme_to_install)
if (music_size == 0) if (music_size == 0)
{ {
free(music);
music = calloc(1, 3371008); music = calloc(1, 3371008);
} else if (music_size > 3371008) { } else if (music_size > 3371008) {
free(music); free(music);
@@ -350,10 +356,10 @@ Result single_install(Theme_s theme_to_install)
return MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, RD_TOO_LARGE); return MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, RD_TOO_LARGE);
} }
size = buf_to_file(music_size, "/BgmCache.bin", ArchiveThemeExt, music); result = buf_to_file(music_size == 0 ? 3371008 : music_size, "/BgmCache.bin", ArchiveThemeExt, music);
free(music); free(music);
if (size == 0) return MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, RD_NOT_FOUND); if (!R_SUCCEEDED(result)) return result;
file_to_buf(fsMakePath(PATH_ASCII, "/ThemeManage.bin"), ArchiveThemeExt, &thememanage_buf); file_to_buf(fsMakePath(PATH_ASCII, "/ThemeManage.bin"), ArchiveThemeExt, &thememanage_buf);
thememanage_buf[0x00] = 1; thememanage_buf[0x00] = 1;
@@ -379,9 +385,11 @@ Result single_install(Theme_s theme_to_install)
memset(&thememanage_buf[0x340], 0, 4); memset(&thememanage_buf[0x340], 0, 4);
memset(&thememanage_buf[0x360], 0, 4); memset(&thememanage_buf[0x360], 0, 4);
memset(&thememanage_buf[0x368], 0, 4); memset(&thememanage_buf[0x368], 0, 4);
size = buf_to_file(0x800, "/ThemeManage.bin", ArchiveThemeExt, thememanage_buf); result = buf_to_file(0x800, "/ThemeManage.bin", ArchiveThemeExt, thememanage_buf);
free(thememanage_buf); free(thememanage_buf);
if (!R_SUCCEEDED(result)) return result;
return 0; return 0;
} }
@@ -393,10 +401,11 @@ Result shuffle_install(Theme_s *themes_list, int theme_count)
u32 bgm_sizes[10] = {0}; u32 bgm_sizes[10] = {0};
for (int i = 0; i < theme_count; i++) for (int i = 0; i < theme_count; i++)
{ {
if (count > 9) return MAKERESULT(RL_USAGE, RS_INVALIDARG, RM_COMMON, RD_INVALID_SELECTION); if (count > 10) return MAKERESULT(RL_USAGE, RS_INVALIDARG, RM_COMMON, RD_INVALID_SELECTION);
if (themes_list[i].in_shuffle) if (themes_list[i].in_shuffle)
{ {
shuffle_themes[count++] = &themes_list[i]; shuffle_themes[count++] = &themes_list[i];
themes_list[i].in_shuffle = false;
} }
} }
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
@@ -426,9 +435,11 @@ Result shuffle_install(Theme_s *themes_list, int theme_count)
} }
} }
buf_to_file(size, "/SaveData.dat", ArchiveHomeExt, savedata_buf); Result result = buf_to_file(size, "/SaveData.dat", ArchiveHomeExt, savedata_buf);
free(savedata_buf); free(savedata_buf);
if (!R_SUCCEEDED(result)) return result;
remake_file("/BodyCache_rd.bin", ArchiveThemeExt, 0x150000 * 10); // Enough space for 10 theme files remake_file("/BodyCache_rd.bin", ArchiveThemeExt, 0x150000 * 10); // Enough space for 10 theme files
Handle body_cache_handle; Handle body_cache_handle;
FSUSER_OpenFile(&body_cache_handle, ArchiveThemeExt, fsMakePath(PATH_ASCII, "/BodyCache_rd.bin"), FS_OPEN_WRITE, 0); FSUSER_OpenFile(&body_cache_handle, ArchiveThemeExt, fsMakePath(PATH_ASCII, "/BodyCache_rd.bin"), FS_OPEN_WRITE, 0);
@@ -525,8 +536,10 @@ Result shuffle_install(Theme_s *themes_list, int theme_count)
*bgmsizeloc = bgm_sizes[i]; *bgmsizeloc = bgm_sizes[i];
} }
buf_to_file(0x800, "/ThemeManage.bin", ArchiveThemeExt, thememanage_buf); result = buf_to_file(0x800, "/ThemeManage.bin", ArchiveThemeExt, thememanage_buf);
free(thememanage_buf); free(thememanage_buf);
if (!R_SUCCEEDED(result)) return result;
return MAKERESULT(RL_SUCCESS, RS_SUCCESS, RM_COMMON, RD_SUCCESS); return MAKERESULT(RL_SUCCESS, RS_SUCCESS, RM_COMMON, RD_SUCCESS);
} }