Major rewrite: less repetition (#101)
* first step of rewriting: at least it compiles™ * fix tabs/spaces * fix dabort on load * fix preview crash * sorting isnt done outside of loading * step one of making remake_file useless * camera/qr code cleanup * fix dabort when folder is empty, and bring back preview optimization * fix button for switching modes and show mode when folder is empty * fix scanning qrs * no more splash discrimination * add debug helpers * fix theme installing turns out that wasnt such a good idea * fix battery icon * mistake * themeplaza compatibility * make use of load_data * don't drink and copy-paste, kids * fix user-agent * remove useless * cleanup includes * not even used * add splash buttons * upgrade buttons drawing * fix controls while preview is up * improve positions
This commit is contained in:
@@ -27,14 +27,16 @@
|
||||
#include "camera.h"
|
||||
|
||||
#include "quirc/quirc.h"
|
||||
#include "draw.h"
|
||||
#include "fs.h"
|
||||
#include "themes.h"
|
||||
#include "pp2d/pp2d/pp2d.h"
|
||||
|
||||
u32 transfer_size;
|
||||
Handle event;
|
||||
struct quirc* context;
|
||||
#include "draw.h"
|
||||
#include "fs.h"
|
||||
#include "loading.h"
|
||||
|
||||
static u32 transfer_size;
|
||||
static Handle event;
|
||||
static struct quirc* context;
|
||||
static u16 * camera_buf = NULL;
|
||||
|
||||
void init_qr(void)
|
||||
{
|
||||
@@ -69,10 +71,14 @@ void exit_qr(void)
|
||||
CAMU_Activate(SELECT_NONE);
|
||||
camExit();
|
||||
quirc_destroy(context);
|
||||
free(camera_buf);
|
||||
camera_buf = NULL;
|
||||
}
|
||||
|
||||
void scan_qr(u16 *buf)
|
||||
bool scan_qr(EntryMode current_mode)
|
||||
{
|
||||
if(camera_buf == NULL) return false;
|
||||
|
||||
int w;
|
||||
int h;
|
||||
|
||||
@@ -82,7 +88,7 @@ void scan_qr(u16 *buf)
|
||||
{
|
||||
for (ssize_t y = 0; y < h; y++)
|
||||
{
|
||||
u16 px = buf[y * 400 + x];
|
||||
u16 px = camera_buf[y * 400 + x];
|
||||
image[y * w + x] = (u8)(((((px >> 11) & 0x1F) << 3) + (((px >> 5) & 0x3F) << 2) + ((px & 0x1F) << 3)) / 3);
|
||||
}
|
||||
}
|
||||
@@ -96,59 +102,49 @@ void scan_qr(u16 *buf)
|
||||
quirc_extract(context, 0, &code);
|
||||
if (!quirc_decode(&code, &data))
|
||||
{
|
||||
qr_mode = false;
|
||||
|
||||
http_get((char*)data.payload, splash_mode ? "/Splashes/" : "/Themes/");
|
||||
http_get((char*)data.payload, main_paths[current_mode]);
|
||||
exit_qr();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void take_picture(void)
|
||||
{
|
||||
u16 *buf = malloc(sizeof(u16) * 400 * 240 * 4);
|
||||
if (buf == NULL) return;
|
||||
CAMU_SetReceiving(&event, buf, PORT_CAM1, 240 * 400 * 2, transfer_size);
|
||||
pp2d_begin_draw(GFX_TOP, GFX_LEFT);
|
||||
free(camera_buf);
|
||||
|
||||
camera_buf = malloc(sizeof(u16) * 400 * 240 * 4);
|
||||
if (camera_buf == NULL) return;
|
||||
|
||||
CAMU_SetReceiving(&event, camera_buf, PORT_CAM1, 240 * 400 * 2, transfer_size);
|
||||
svcWaitSynchronization(event, U64_MAX);
|
||||
svcCloseHandle(event);
|
||||
pp2d_begin_draw(GFX_TOP, GFX_LEFT);
|
||||
|
||||
u32 *rgba8_buf = malloc(240 * 400 * sizeof(u32));
|
||||
if (rgba8_buf == NULL) return;
|
||||
for (int i = 0; i < 240 * 400; i++)
|
||||
{
|
||||
rgba8_buf[i] = RGB565_TO_ABGR8(buf[i]);
|
||||
rgba8_buf[i] = RGB565_TO_ABGR8(camera_buf[i]);
|
||||
}
|
||||
pp2d_free_texture(TEXTURE_QR);
|
||||
pp2d_load_texture_memory(TEXTURE_QR, rgba8_buf, 400, 240);
|
||||
free(rgba8_buf);
|
||||
|
||||
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_Activate(SELECT_NONE);
|
||||
scan_qr(buf);
|
||||
CAMU_Activate(SELECT_OUT1_OUT2);
|
||||
CAMU_StartCapture(PORT_BOTH);
|
||||
}
|
||||
if (kDown & KEY_R)
|
||||
{
|
||||
exit_qr();
|
||||
qr_mode = false;
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
Putting this in camera because I'm too lazy to make a network.c
|
||||
This'll probably get refactored later
|
||||
*/
|
||||
Result http_get(char *url, char *path)
|
||||
Result http_get(char *url, const char *path)
|
||||
{
|
||||
Result ret;
|
||||
httpcContext context;
|
||||
@@ -164,9 +160,10 @@ Result http_get(char *url, char *path)
|
||||
ret = httpcOpenContext(&context, HTTPC_METHOD_GET, url, 1);
|
||||
ret = httpcSetSSLOpt(&context, SSLCOPT_DisableVerify); // should let us do https
|
||||
ret = httpcSetKeepAlive(&context, HTTPC_KEEPALIVE_ENABLED);
|
||||
ret = httpcAddRequestHeaderField(&context, "User-Agent", "Anemone3DS/1.1.0");
|
||||
ret = httpcAddRequestHeaderField(&context, "User-Agent", USER_AGENT);
|
||||
ret = httpcAddRequestHeaderField(&context, "Connection", "Keep-Alive");
|
||||
draw_theme_install(DOWNLOADING);
|
||||
draw_install(INSTALL_DOWNLOAD);
|
||||
|
||||
ret = httpcBeginRequest(&context);
|
||||
if (ret != 0)
|
||||
{
|
||||
@@ -234,9 +231,7 @@ Result http_get(char *url, char *path)
|
||||
free(content_disposition);
|
||||
free(new_url);
|
||||
free(buf);
|
||||
char error[29] = {0};
|
||||
sprintf(error, "Target is not a valid %s", splash_mode ? "splash" : "theme");
|
||||
throw_error(error, WARNING);
|
||||
throw_error("Target is not valid!", ERROR_LEVEL_WARNING);
|
||||
return -1;
|
||||
}
|
||||
for (size_t i = 0; i < strlen(filename); i++)
|
||||
@@ -283,14 +278,13 @@ Result http_get(char *url, char *path)
|
||||
char path_to_file[0x106] = {0};
|
||||
strcpy(path_to_file, path);
|
||||
strcat(path_to_file, filename);
|
||||
char * extension = strrchr(path_to_file, '.');
|
||||
if (extension == NULL || strcmp(extension, ".zip"))
|
||||
strcat(path_to_file, ".zip");
|
||||
|
||||
remake_file(path_to_file, ArchiveSD, size);
|
||||
buf_to_file(size, path_to_file, ArchiveSD, (char*)buf);
|
||||
|
||||
if (splash_mode) get_splashes(&splashes_list, &splash_count);
|
||||
else get_themes(&themes_list, &theme_count);
|
||||
|
||||
exit_qr();
|
||||
|
||||
free(content_disposition);
|
||||
free(new_url);
|
||||
free(buf);
|
||||
|
||||
409
source/draw.c
409
source/draw.c
@@ -25,14 +25,12 @@
|
||||
*/
|
||||
|
||||
#include "draw.h"
|
||||
#include "common.h"
|
||||
#include "unicode.h"
|
||||
|
||||
#include "pp2d/pp2d/pp2d.h"
|
||||
#include "quirc/quirc.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
|
||||
enum Colors {
|
||||
COLOR_BACKGROUND = ABGR8(255, 32, 28, 35), //silver-y black
|
||||
COLOR_ACCENT = RGBA8(55, 122, 168, 255),
|
||||
@@ -46,10 +44,10 @@ enum Colors {
|
||||
void init_screens(void)
|
||||
{
|
||||
pp2d_init();
|
||||
|
||||
|
||||
pp2d_set_screen_color(GFX_TOP, COLOR_BACKGROUND);
|
||||
pp2d_set_screen_color(GFX_BOTTOM, COLOR_BACKGROUND);
|
||||
|
||||
|
||||
pp2d_load_texture_png(TEXTURE_ARROW, "romfs:/arrow.png");
|
||||
pp2d_load_texture_png(TEXTURE_SHUFFLE, "romfs:/shuffle.png");
|
||||
pp2d_load_texture_png(TEXTURE_BATTERY_1, "romfs:/battery1.png");
|
||||
@@ -65,42 +63,41 @@ void exit_screens(void)
|
||||
pp2d_exit();
|
||||
}
|
||||
|
||||
static int theme_vertical_scroll = 0;
|
||||
static int splash_vertical_scroll = 0;
|
||||
|
||||
|
||||
void draw_base_interface(void)
|
||||
static void draw_base_interface(void)
|
||||
{
|
||||
pp2d_begin_draw(GFX_TOP, GFX_LEFT);
|
||||
pp2d_draw_rectangle(0, 0, 400, 23, COLOR_ACCENT);
|
||||
|
||||
time_t t = time(NULL);
|
||||
struct tm tm = *localtime(&t);
|
||||
|
||||
|
||||
pp2d_draw_textf(7, 2, 0.6, 0.6, COLOR_WHITE, "%.2i", tm.tm_hour);
|
||||
pp2d_draw_text(28, 2, 0.6, 0.6, COLOR_WHITE, (tm.tm_sec % 2 == 1) ? ":" : " ");
|
||||
pp2d_draw_text(28, 1, 0.6, 0.6, COLOR_WHITE, (tm.tm_sec % 2 == 1) ? ":" : " ");
|
||||
pp2d_draw_textf(34, 2, 0.6, 0.6, COLOR_WHITE, "%.2i", tm.tm_min);
|
||||
|
||||
u8 battery_charging;
|
||||
u8 battery_charging = 0;
|
||||
PTMU_GetBatteryChargeState(&battery_charging);
|
||||
u8 battery_status;
|
||||
u8 battery_status = 0;
|
||||
PTMU_GetBatteryLevel(&battery_status);
|
||||
pp2d_draw_texture(2 + battery_status, 357, 2);
|
||||
|
||||
if (battery_charging)
|
||||
pp2d_draw_texture(TEXTURE_BATTERY_1 + battery_status - 1, 357, 2);
|
||||
|
||||
if(battery_charging)
|
||||
pp2d_draw_texture(TEXTURE_BATTERY_CHARGE, 357, 2);
|
||||
|
||||
pp2d_draw_on(GFX_BOTTOM, GFX_LEFT);
|
||||
pp2d_draw_rectangle(0, 0, 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, GFX_LEFT);
|
||||
}
|
||||
void throw_error(char* error, int error_type) {
|
||||
|
||||
switch (error_type) {
|
||||
case ERROR:
|
||||
while (aptMainLoop())
|
||||
void throw_error(char* error, ErrorLevel level)
|
||||
{
|
||||
switch(level)
|
||||
{
|
||||
case ERROR_LEVEL_ERROR:
|
||||
while(aptMainLoop())
|
||||
{
|
||||
hidScanInput();
|
||||
u32 kDown = hidKeysDown();
|
||||
@@ -108,254 +105,190 @@ void throw_error(char* error, int error_type) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
if(kDown & KEY_A) exit_function();
|
||||
}
|
||||
break;
|
||||
case ERROR_LEVEL_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;
|
||||
}
|
||||
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_preview(int preview_offset)
|
||||
{
|
||||
pp2d_begin_draw(GFX_TOP, GFX_LEFT);
|
||||
pp2d_draw_texture_part(TEXTURE_PREVIEW, 0, 0, preview_offset, 0, 400, 240);
|
||||
pp2d_draw_on(GFX_BOTTOM, GFX_LEFT);
|
||||
pp2d_draw_texture_part(TEXTURE_PREVIEW, 0, 0, 40 + preview_offset, 240, 320, 240);
|
||||
}
|
||||
|
||||
void draw_install(InstallType type)
|
||||
{
|
||||
draw_base_interface();
|
||||
switch(install_type)
|
||||
switch(type)
|
||||
{
|
||||
case 0:
|
||||
case INSTALL_SINGLE:
|
||||
pp2d_draw_text_center(GFX_TOP, 120, 0.8, 0.8, COLOR_WHITE, "Installing a single theme...");
|
||||
break;
|
||||
case 1:
|
||||
case INSTALL_SHUFFLE:
|
||||
pp2d_draw_text_center(GFX_TOP, 120, 0.8, 0.8, COLOR_WHITE, "Installing a shuffle theme...");
|
||||
break;
|
||||
case 2:
|
||||
case INSTALL_BGM:
|
||||
pp2d_draw_text_center(GFX_TOP, 120, 0.8, 0.8, COLOR_WHITE, "Installing BGM...");
|
||||
break;
|
||||
case 3:
|
||||
case INSTALL_DOWNLOAD:
|
||||
pp2d_draw_text_center(GFX_TOP, 120, 0.8, 0.8, COLOR_WHITE, "Downloading...");
|
||||
break;
|
||||
case INSTALL_SPLASH:
|
||||
pp2d_draw_text_center(GFX_TOP, 120, 0.8, 0.8, COLOR_WHITE, "Installing a splash...");
|
||||
break;
|
||||
case INSTALL_SPLASH_DELETE:
|
||||
pp2d_draw_text_center(GFX_TOP, 120, 0.8, 0.8, COLOR_WHITE, "Uninstalling a splash...");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pp2d_end_draw();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
draw_base_interface();
|
||||
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();
|
||||
return;
|
||||
}
|
||||
|
||||
Theme_s current_theme = themes_list[selected_theme];
|
||||
|
||||
if (preview_mode)
|
||||
{
|
||||
if (current_theme.has_preview)
|
||||
{
|
||||
pp2d_begin_draw(GFX_TOP, GFX_LEFT);
|
||||
pp2d_draw_texture_part(TEXTURE_PREVIEW, 0, 0, current_theme.preview_offset, 0, 400, 240);
|
||||
pp2d_draw_on(GFX_BOTTOM, GFX_LEFT);
|
||||
pp2d_draw_texture_part(TEXTURE_PREVIEW, 0, 0, 40+current_theme.preview_offset, 240, 320, 240);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
draw_base_interface();
|
||||
pp2d_draw_text_center(GFX_TOP, 4, 0.5, 0.5, COLOR_WHITE, "Theme mode");
|
||||
wchar_t title[0x41] = {0};
|
||||
utf16_to_utf32((u32*)title, current_theme.name, 0x40);
|
||||
pp2d_draw_wtext_wrap(20, 30, 0.7, 0.7, COLOR_WHITE, 380, title);
|
||||
wchar_t author[0x41] = {0};
|
||||
utf16_to_utf32((u32*)author, current_theme.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[0x81] = {0};
|
||||
utf16_to_utf32((u32*)description, current_theme.desc, 0x80);
|
||||
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(200, 150, 0.6, 0.6, COLOR_WHITE, L"\uE004 Switch to Splashes");
|
||||
pp2d_draw_wtext(20, 180, 0.6, 0.6, COLOR_WHITE, L"\uE000 Install Theme");
|
||||
pp2d_draw_wtext(200, 180, 0.6, 0.6, COLOR_WHITE, L"\uE001 Queue Shuffle");
|
||||
pp2d_draw_wtext(20, 210, 0.6, 0.6, COLOR_WHITE, L"\uE002 Install BGM");
|
||||
pp2d_draw_wtext(200, 210, 0.6, 0.6, COLOR_WHITE, L"\uE003 Preview Theme");
|
||||
pp2d_draw_wtext(130, 120, 0.6, 0.6, COLOR_WHITE, L"\uE005 Scan QRCode");
|
||||
pp2d_draw_on(GFX_BOTTOM, GFX_LEFT);
|
||||
|
||||
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
|
||||
//----------------------------------------------------------------
|
||||
for (int i = 0; i < theme_count; i++) {
|
||||
if (theme_count <= THEMES_PER_SCREEN)
|
||||
break;
|
||||
|
||||
if (theme_vertical_scroll > selected_theme)
|
||||
theme_vertical_scroll--;
|
||||
|
||||
if ((i < selected_theme) && \
|
||||
((selected_theme - theme_vertical_scroll) >= THEMES_PER_SCREEN) && \
|
||||
(theme_vertical_scroll != ( - THEMES_PER_SCREEN)))
|
||||
theme_vertical_scroll++;
|
||||
}
|
||||
//----------------------------------------------------------------
|
||||
|
||||
// Show arrows if there are themes out of bounds
|
||||
//----------------------------------------------------------------
|
||||
if (theme_vertical_scroll > 0)
|
||||
pp2d_draw_texture(TEXTURE_ARROW, 155, 6);
|
||||
if (theme_vertical_scroll + THEMES_PER_SCREEN < theme_count)
|
||||
pp2d_draw_texture_flip(TEXTURE_ARROW, 155, 224, VERTICAL);
|
||||
|
||||
for (int i = theme_vertical_scroll; i < (THEMES_PER_SCREEN + theme_vertical_scroll); i++)
|
||||
{
|
||||
if (i >= theme_count)
|
||||
break;
|
||||
|
||||
current_theme = themes_list[i];
|
||||
wchar_t name[0x80] = {0};
|
||||
utf16_to_utf32((u32*)name, current_theme.name, 0x80);
|
||||
|
||||
int vertical_offset = 48 * (i-theme_vertical_scroll);
|
||||
u32 font_color = COLOR_WHITE;
|
||||
|
||||
if (i == selected_theme)
|
||||
{
|
||||
font_color = COLOR_BLACK;
|
||||
pp2d_draw_rectangle(0, 24 + vertical_offset, 320, 48, COLOR_CURSOR);
|
||||
}
|
||||
pp2d_draw_wtext(54, 40 + vertical_offset, 0.55, 0.55, font_color, name);
|
||||
if (!current_theme.placeholder_color)
|
||||
pp2d_draw_texture(current_theme.icon_id, 0, 24 + vertical_offset);
|
||||
else
|
||||
pp2d_draw_rectangle(0, 24 + vertical_offset, 48, 48, current_theme.placeholder_color);
|
||||
|
||||
if (current_theme.in_shuffle)
|
||||
pp2d_draw_texture_blend(TEXTURE_SHUFFLE, 280, 32 + vertical_offset, font_color);
|
||||
}
|
||||
}
|
||||
|
||||
pp2d_end_draw();
|
||||
}
|
||||
|
||||
void draw_splash_install(int install_type)
|
||||
void draw_interface(Entry_List_s* list, EntryMode current_mode)
|
||||
{
|
||||
draw_base_interface();
|
||||
switch (install_type)
|
||||
{
|
||||
case SINGLE_INSTALL:
|
||||
pp2d_draw_text_center(GFX_TOP, 110, 0.7, 0.7, COLOR_WHITE, "Installing a splash...");
|
||||
break;
|
||||
case UNINSTALL:
|
||||
pp2d_draw_text_center(GFX_TOP, 110, 0.7, 0.7, COLOR_WHITE, "Uninstalling a splash...");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pp2d_end_draw();
|
||||
}
|
||||
|
||||
void draw_splash_interface(Splash_s *splashes_list, int splash_count, int selected_splash, bool preview_mode)
|
||||
{
|
||||
if (splashes_list == NULL)
|
||||
const char* mode_string[] = {
|
||||
"Theme mode",
|
||||
"Splashes mode",
|
||||
};
|
||||
|
||||
pp2d_draw_text_center(GFX_TOP, 4, 0.5, 0.5, COLOR_WHITE, mode_string[current_mode]);
|
||||
|
||||
if(list->entries == NULL)
|
||||
{
|
||||
draw_base_interface();
|
||||
pp2d_draw_text_center(GFX_TOP, 80, 0.7, 0.7, COLOR_YELLOW, "No splashes found!");
|
||||
const char* mode_found_string[] = {
|
||||
"No themes found",
|
||||
"No splashes found",
|
||||
};
|
||||
pp2d_draw_text_center(GFX_TOP, 80, 0.7, 0.7, COLOR_YELLOW, mode_found_string[current_mode]);
|
||||
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();
|
||||
const char* mode_switch_string[] = {
|
||||
"Or \uE004 to switch to splashes",
|
||||
"Or \uE004 to switch to themes",
|
||||
};
|
||||
pp2d_draw_text_center(GFX_TOP, 140, 0.7, 0.7, COLOR_YELLOW, mode_switch_string[current_mode]);
|
||||
pp2d_draw_text_center(GFX_TOP, 170, 0.7, 0.7, COLOR_YELLOW, "Or \uE045 to quit");
|
||||
return;
|
||||
}
|
||||
Splash_s current_splash = splashes_list[selected_splash];
|
||||
if (preview_mode)
|
||||
|
||||
int selected_entry = list->selected_entry;
|
||||
Entry_s current_entry = list->entries[selected_entry];
|
||||
|
||||
wchar_t title[0x41] = {0};
|
||||
utf16_to_utf32((u32*)title, current_entry.name, 0x40);
|
||||
pp2d_draw_wtext_wrap(20, 30, 0.7, 0.7, COLOR_WHITE, 380, title);
|
||||
|
||||
wchar_t author[0x41] = {0};
|
||||
utf16_to_utf32((u32*)author, current_entry.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[0x81] = {0};
|
||||
utf16_to_utf32((u32*)description, current_entry.desc, 0x80);
|
||||
pp2d_draw_wtext_wrap(20, 65, 0.5, 0.5, COLOR_WHITE, 363, description);
|
||||
|
||||
|
||||
switch(current_mode)
|
||||
{
|
||||
pp2d_begin_draw(GFX_TOP, GFX_LEFT);
|
||||
pp2d_draw_texture_part(TEXTURE_PREVIEW, 0, 0, 0, 0, 400, 240);
|
||||
pp2d_draw_on(GFX_BOTTOM, GFX_LEFT);
|
||||
pp2d_draw_texture_part(TEXTURE_PREVIEW, 0, 0, 40, 240, 320, 240);
|
||||
} else {
|
||||
draw_base_interface();
|
||||
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);
|
||||
case MODE_THEMES:
|
||||
pp2d_draw_text_center(GFX_TOP, BUTTONS_Y_PREVIEW, 0.6, 0.6, COLOR_WHITE, "\uE003 Preview Theme");
|
||||
pp2d_draw_wtext(BUTTONS_X_LEFT, BUTTONS_Y_LINE_1, 0.6, 0.6, COLOR_WHITE, L"\uE004 Switch to Splashes");
|
||||
pp2d_draw_wtext(BUTTONS_X_RIGHT, BUTTONS_Y_LINE_1, 0.6, 0.6, COLOR_WHITE, L"\uE005 Scan QRCode");
|
||||
|
||||
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, 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_wtext(BUTTONS_X_LEFT, BUTTONS_Y_LINE_2, 0.6, 0.6, COLOR_WHITE, L"\uE000 Install Theme");
|
||||
pp2d_draw_wtext(BUTTONS_X_RIGHT, BUTTONS_Y_LINE_2, 0.6, 0.6, COLOR_WHITE, L"\uE001 Queue Shuffle");
|
||||
|
||||
pp2d_draw_on(GFX_BOTTOM, GFX_LEFT);
|
||||
for (int i = 0; i < splash_count; i++) {
|
||||
if (splash_count <= THEMES_PER_SCREEN)
|
||||
break;
|
||||
pp2d_draw_wtext(BUTTONS_X_LEFT, BUTTONS_Y_LINE_3, 0.6, 0.6, COLOR_WHITE, L"\uE002 Install BGM");
|
||||
pp2d_draw_wtext(BUTTONS_X_RIGHT, BUTTONS_Y_LINE_3, 0.6, 0.6, COLOR_WHITE, L"\uE046 Install Shuffle Themes");
|
||||
break;
|
||||
case MODE_SPLASHES:
|
||||
pp2d_draw_text_center(GFX_TOP, BUTTONS_Y_PREVIEW, 0.6, 0.6, COLOR_WHITE, "\uE003 Preview Splash");
|
||||
pp2d_draw_wtext(BUTTONS_X_LEFT, BUTTONS_Y_LINE_1, 0.6, 0.6, COLOR_WHITE, L"\uE004 Switch to Themes");
|
||||
pp2d_draw_wtext(BUTTONS_X_RIGHT, BUTTONS_Y_LINE_1, 0.6, 0.6, COLOR_WHITE, L"\uE005 Scan QRCode");
|
||||
|
||||
if (splash_vertical_scroll > selected_splash)
|
||||
splash_vertical_scroll--;
|
||||
|
||||
if ((i < selected_splash) && \
|
||||
((selected_splash - splash_vertical_scroll) >= THEMES_PER_SCREEN) && \
|
||||
(splash_vertical_scroll != ( - THEMES_PER_SCREEN)))
|
||||
splash_vertical_scroll++;
|
||||
}
|
||||
|
||||
if (splash_vertical_scroll > 0)
|
||||
pp2d_draw_texture(TEXTURE_ARROW, 155, 6);
|
||||
if (splash_vertical_scroll + THEMES_PER_SCREEN < splash_count)
|
||||
pp2d_draw_texture_flip(TEXTURE_ARROW, 155, 224, VERTICAL);
|
||||
|
||||
for (int i = splash_vertical_scroll; i < (THEMES_PER_SCREEN + splash_vertical_scroll); i++)
|
||||
{
|
||||
if (i >= splash_count)
|
||||
break;
|
||||
|
||||
current_splash = splashes_list[i];
|
||||
wchar_t name[0x106] = {0};
|
||||
utf16_to_utf32((u32*)name, current_splash.name, 0x106);
|
||||
|
||||
int vertical_offset = 48 * (i-splash_vertical_scroll);
|
||||
u32 font_color = COLOR_WHITE;
|
||||
|
||||
if (i == selected_splash)
|
||||
{
|
||||
font_color = COLOR_BLACK;
|
||||
pp2d_draw_rectangle(0, 24 + vertical_offset, 320, 48, COLOR_CURSOR);
|
||||
}
|
||||
pp2d_draw_wtext(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_draw_wtext(BUTTONS_X_LEFT, BUTTONS_Y_LINE_2, 0.6, 0.6, COLOR_WHITE, L"\uE000 Install Splash");
|
||||
pp2d_draw_wtext(BUTTONS_X_RIGHT, BUTTONS_Y_LINE_2, 0.6, 0.6, COLOR_WHITE, L"\uE001 Delete installed Splash");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
pp2d_draw_on(GFX_BOTTOM, GFX_LEFT);
|
||||
|
||||
switch(current_mode)
|
||||
{
|
||||
case MODE_THEMES:
|
||||
pp2d_draw_textf(7, 3, 0.6, 0.6, list->shuffle_count <= 10 ? COLOR_WHITE : COLOR_RED, "Selected: %i/10", list->shuffle_count);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Scroll the menu up or down if the selected theme is out of its bounds
|
||||
//----------------------------------------------------------------
|
||||
for(int i = 0; i < list->entries_count; i++) {
|
||||
if(list->entries_count <= ENTRIES_PER_SCREEN) break;
|
||||
|
||||
if(list->scroll > list->selected_entry)
|
||||
list->scroll--;
|
||||
|
||||
if((i < list->selected_entry) && \
|
||||
((list->selected_entry - list->scroll) >= ENTRIES_PER_SCREEN) && \
|
||||
(list->scroll != (i - ENTRIES_PER_SCREEN)))
|
||||
list->scroll++;
|
||||
}
|
||||
//----------------------------------------------------------------
|
||||
|
||||
// Show arrows if there are themes out of bounds
|
||||
//----------------------------------------------------------------
|
||||
if(list->scroll > 0)
|
||||
pp2d_draw_texture(TEXTURE_ARROW, 155, 6);
|
||||
if(list->scroll + ENTRIES_PER_SCREEN < list->entries_count)
|
||||
pp2d_draw_texture_flip(TEXTURE_ARROW, 155, 224, VERTICAL);
|
||||
|
||||
for(int i = list->scroll; i < (ENTRIES_PER_SCREEN + list->scroll); i++)
|
||||
{
|
||||
if(i >= list->entries_count) break;
|
||||
|
||||
current_entry = list->entries[i];
|
||||
|
||||
wchar_t name[0x41] = {0};
|
||||
utf16_to_utf32((u32*)name, current_entry.name, 0x40);
|
||||
|
||||
int vertical_offset = 48 * (i - list->scroll);
|
||||
u32 font_color = COLOR_WHITE;
|
||||
|
||||
if(i == list->selected_entry)
|
||||
{
|
||||
font_color = COLOR_BLACK;
|
||||
pp2d_draw_rectangle(0, 24 + vertical_offset, 320, 48, COLOR_CURSOR);
|
||||
}
|
||||
pp2d_draw_wtext(54, 40 + vertical_offset, 0.55, 0.55, font_color, name);
|
||||
if(!current_entry.placeholder_color)
|
||||
pp2d_draw_texture(current_entry.icon_id, 0, 24 + vertical_offset);
|
||||
else
|
||||
pp2d_draw_rectangle(0, 24 + vertical_offset, 48, 48, current_entry.placeholder_color);
|
||||
|
||||
if(current_entry.in_shuffle)
|
||||
pp2d_draw_texture_blend(TEXTURE_SHUFFLE, 280, 32 + vertical_offset, font_color);
|
||||
}
|
||||
pp2d_end_draw();
|
||||
}
|
||||
|
||||
|
||||
@@ -99,11 +99,11 @@ Result close_archives(void)
|
||||
if(R_FAILED(res = FSUSER_CloseArchive(ArchiveSD))) return res;
|
||||
if(R_FAILED(res = FSUSER_CloseArchive(ArchiveHomeExt))) return res;
|
||||
if(R_FAILED(res = FSUSER_CloseArchive(ArchiveThemeExt))) return res;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u64 file_to_buf(FS_Path path, FS_Archive archive, char** buf)
|
||||
u32 file_to_buf(FS_Path path, FS_Archive archive, char** buf)
|
||||
{
|
||||
Handle file;
|
||||
Result res = 0;
|
||||
@@ -114,7 +114,7 @@ u64 file_to_buf(FS_Path path, FS_Archive archive, char** buf)
|
||||
*buf = calloc(1, size);
|
||||
FSFILE_Read(file, NULL, 0, *buf, size);
|
||||
FSFILE_Close(file);
|
||||
return size;
|
||||
return (u32)size;
|
||||
}
|
||||
|
||||
u32 zip_file_to_buf(char *file_name, u16 *zip_path, char **buf)
|
||||
|
||||
197
source/loading.c
Normal file
197
source/loading.c
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* This file is part of Anemone3DS
|
||||
* Copyright (C) 2016-2017 Alex Taber ("astronautlevel"), Dawid Eckert ("daedreth")
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 "loading.h"
|
||||
#include "pp2d/pp2d/pp2d.h"
|
||||
#include "fs.h"
|
||||
#include "unicode.h"
|
||||
|
||||
u32 load_data(char * filename, Entry_s entry, char ** buf)
|
||||
{
|
||||
if(entry.is_zip)
|
||||
{
|
||||
return zip_file_to_buf(filename+1, entry.path, buf); //the first character will always be '/' because of the other case
|
||||
}
|
||||
else
|
||||
{
|
||||
u16 path[0x106] = {0};
|
||||
strucat(path, entry.path);
|
||||
struacat(path, filename);
|
||||
|
||||
return file_to_buf(fsMakePath(PATH_UTF16, path), ArchiveSD, buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_smdh(Entry_s * entry, const ssize_t textureID, const u16 * fallback_name)
|
||||
{
|
||||
pp2d_free_texture(textureID);
|
||||
|
||||
char *info_buffer = NULL;
|
||||
u64 size = load_data("/info.smdh", *entry, &info_buffer);
|
||||
|
||||
if(!size)
|
||||
{
|
||||
free(info_buffer);
|
||||
memcpy(entry->name, fallback_name, 0x80);
|
||||
utf8_to_utf16(entry->desc, (u8*)"No description", 0x100);
|
||||
utf8_to_utf16(entry->author, (u8*)"Unknown author", 0x80);
|
||||
entry->placeholder_color = RGBA8(rand() % 255, rand() % 255, rand() % 255, 255);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(entry->name, info_buffer + 0x08, 0x80);
|
||||
memcpy(entry->desc, info_buffer + 0x88, 0x100);
|
||||
memcpy(entry->author, info_buffer + 0x188, 0x80);
|
||||
|
||||
u16 *icon_data = malloc(0x1200);
|
||||
memcpy(icon_data, info_buffer + 0x24C0, 0x1200);
|
||||
free(info_buffer);
|
||||
|
||||
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));
|
||||
|
||||
image[dest_pixel] = RGB565_TO_ABGR8(icon_data[source_pixel]);
|
||||
}
|
||||
}
|
||||
|
||||
free(icon_data);
|
||||
pp2d_load_texture_memory(textureID, (u8*)image, (u32)width, (u32)height);
|
||||
free(image);
|
||||
|
||||
entry->icon_id = textureID;
|
||||
}
|
||||
|
||||
static int compare_entries(const void * a, const void * b)
|
||||
{
|
||||
Entry_s *entry_a = (Entry_s *)a;
|
||||
Entry_s *entry_b = (Entry_s *)b;
|
||||
|
||||
return memcmp(entry_a->name, entry_b->name, 0x40*sizeof(u16));
|
||||
}
|
||||
|
||||
static void sort_list(Entry_List_s * list)
|
||||
{
|
||||
qsort(list->entries, list->entries_count, sizeof(Entry_s), compare_entries); //alphabet sort
|
||||
}
|
||||
|
||||
Result load_entries(const char * loading_path, Entry_List_s * list)
|
||||
{
|
||||
Handle dir_handle;
|
||||
Result res = FSUSER_OpenDirectory(&dir_handle, ArchiveSD, fsMakePath(PATH_ASCII, loading_path));
|
||||
if(R_FAILED(res))
|
||||
return res;
|
||||
|
||||
u32 entries_read = 1;
|
||||
|
||||
while(entries_read)
|
||||
{
|
||||
FS_DirectoryEntry dir_entry = {0};
|
||||
res = FSDIR_Read(dir_handle, &entries_read, 1, &dir_entry);
|
||||
if(R_FAILED(res) || entries_read == 0)
|
||||
break;
|
||||
|
||||
if(!(dir_entry.attributes & FS_ATTRIBUTE_DIRECTORY) && strcmp(dir_entry.shortExt, "ZIP"))
|
||||
continue;
|
||||
|
||||
list->entries_count++;
|
||||
list->entries = realloc(list->entries, list->entries_count * sizeof(Entry_s));
|
||||
if(list->entries == NULL)
|
||||
break;
|
||||
|
||||
Entry_s * current_entry = &(list->entries[list->entries_count-1]);
|
||||
memset(current_entry, 0, sizeof(Entry_s));
|
||||
|
||||
struacat(current_entry->path, loading_path);
|
||||
strucat(current_entry->path, dir_entry.name);
|
||||
|
||||
current_entry->is_zip = !strcmp(dir_entry.shortExt, "ZIP");
|
||||
|
||||
ssize_t iconID = TEXTURE_ICON + list->entries_count;
|
||||
parse_smdh(current_entry, iconID, dir_entry.name);
|
||||
}
|
||||
|
||||
FSDIR_Close(dir_handle);
|
||||
|
||||
sort_list(list);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static u16 previous_path[0x106] = {0};
|
||||
|
||||
bool load_preview(Entry_List_s list, int * preview_offset)
|
||||
{
|
||||
if(list.entries == NULL) return false;
|
||||
|
||||
Entry_s entry = list.entries[list.selected_entry];
|
||||
|
||||
if(!memcmp(&previous_path, &entry.path, 0x106*sizeof(u16))) return true;
|
||||
else memcpy(&previous_path, &entry.path, 0x106*sizeof(u16));
|
||||
|
||||
// free the previously loaded preview. wont do anything if there wasnt one
|
||||
pp2d_free_texture(TEXTURE_PREVIEW);
|
||||
|
||||
char *preview_buffer = NULL;
|
||||
u64 size = load_data("/preview.png", entry, &preview_buffer);
|
||||
|
||||
if(!size)
|
||||
{
|
||||
free(preview_buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
u8 * image = NULL;
|
||||
unsigned int width = 0, height = 0;
|
||||
|
||||
if((lodepng_decode32(&image, &width, &height, (u8*)preview_buffer, size)) == 0) // no error
|
||||
{
|
||||
for(u32 i = 0; i < width; i++)
|
||||
{
|
||||
for(u32 j = 0; j < height; j++)
|
||||
{
|
||||
u32* pixel = (u32*)(image + (i + j*width) * 4);
|
||||
*pixel = __builtin_bswap32(*pixel); //swap from RGBA to ABGR, needed for pp2d
|
||||
}
|
||||
}
|
||||
|
||||
pp2d_load_texture_memory(TEXTURE_PREVIEW, image, (u32)width, (u32)height);
|
||||
*preview_offset = (width-400)/2;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
free(image);
|
||||
free(preview_buffer);
|
||||
|
||||
return ret;
|
||||
}
|
||||
444
source/main.c
444
source/main.c
@@ -25,354 +25,278 @@
|
||||
*/
|
||||
|
||||
#include "fs.h"
|
||||
#include "loading.h"
|
||||
#include "themes.h"
|
||||
#include "splashes.h"
|
||||
#include "draw.h"
|
||||
#include "common.h"
|
||||
#include "camera.h"
|
||||
#include "pp2d/pp2d/pp2d.h"
|
||||
#include <time.h>
|
||||
|
||||
static bool homebrew = false;
|
||||
int __stacksize__ = 64 * 1024;
|
||||
Result archive_result;
|
||||
|
||||
int init_services(void)
|
||||
const char * main_paths[MODE_AMOUNT] = {
|
||||
"/Themes/",
|
||||
"/Splashes/",
|
||||
};
|
||||
|
||||
void init_services(void)
|
||||
{
|
||||
consoleDebugInit(debugDevice_SVC);
|
||||
cfguInit();
|
||||
ptmuInit();
|
||||
acInit();
|
||||
httpcInit(0);
|
||||
archive_result = open_archives();
|
||||
homebrew = true;
|
||||
if (!envIsHomebrew())
|
||||
if(envIsHomebrew())
|
||||
{
|
||||
homebrew = false;
|
||||
} else {
|
||||
s64 out;
|
||||
svcGetSystemInfo(&out, 0x10000, 0);
|
||||
if (out)
|
||||
{
|
||||
homebrew = false;
|
||||
}
|
||||
homebrew = !out;
|
||||
}
|
||||
return homebrew;
|
||||
}
|
||||
|
||||
int exit_services(void)
|
||||
void exit_services(void)
|
||||
{
|
||||
close_archives();
|
||||
cfguExit();
|
||||
ptmuExit();
|
||||
httpcExit();
|
||||
acExit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void exit_function(void)
|
||||
{
|
||||
if(homebrew)
|
||||
{
|
||||
APT_HardwareResetAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
srvPublishToSubscriber(0x202, 0);
|
||||
}
|
||||
|
||||
exit_screens();
|
||||
exit_services();
|
||||
}
|
||||
|
||||
void change_selected(Entry_List_s * list, int change_value)
|
||||
{
|
||||
list->selected_entry += change_value;
|
||||
if(change_value < 0 && list->selected_entry < 0)
|
||||
list->selected_entry = list->entries_count - 1;
|
||||
else
|
||||
list->selected_entry %= list->entries_count;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
srand(time(NULL));
|
||||
bool homebrew = init_services();
|
||||
init_services();
|
||||
init_screens();
|
||||
|
||||
themes_list = NULL;
|
||||
theme_count = 0;
|
||||
Result res = get_themes(&themes_list, &theme_count);
|
||||
if (R_FAILED(res))
|
||||
{
|
||||
//don't need to worry about possible textures (icons, previews), that's freed by pp2d itself
|
||||
free(themes_list);
|
||||
themes_list = NULL;
|
||||
}
|
||||
splash_count = 0;
|
||||
splashes_list = NULL;
|
||||
res = get_splashes(&splashes_list, &splash_count);
|
||||
if (R_FAILED(res))
|
||||
{
|
||||
//don't need to worry about possible textures (icons, previews), that's freed by pp2d itself
|
||||
free(splashes_list);
|
||||
splashes_list = NULL;
|
||||
}
|
||||
|
||||
splash_mode = false;
|
||||
int selected_splash = 0;
|
||||
int selected_theme = 0;
|
||||
int previously_selected = 0;
|
||||
shuffle_theme_count = 0;
|
||||
Entry_List_s lists[MODE_AMOUNT] = {0};
|
||||
|
||||
for(int i = 0; i < MODE_AMOUNT; i++)
|
||||
load_entries(main_paths[i], &lists[i]);
|
||||
|
||||
EntryMode current_mode = MODE_THEMES;
|
||||
|
||||
bool preview_mode = false;
|
||||
|
||||
int preview_offset = 0;
|
||||
|
||||
bool qr_mode = false;
|
||||
|
||||
while(aptMainLoop())
|
||||
{
|
||||
hidScanInput();
|
||||
u32 kDown = hidKeysDown();
|
||||
u32 kHeld = hidKeysHeld();
|
||||
|
||||
if (qr_mode)
|
||||
|
||||
Entry_List_s * current_list = &lists[current_mode];
|
||||
|
||||
if(qr_mode) take_picture();
|
||||
else if(preview_mode) draw_preview(preview_offset);
|
||||
else draw_interface(current_list, current_mode);
|
||||
pp2d_end_draw();
|
||||
|
||||
if(kDown & KEY_START) break;
|
||||
|
||||
if(R_FAILED(archive_result) && current_mode == MODE_THEMES)
|
||||
{
|
||||
take_picture();
|
||||
} else if (!splash_mode)
|
||||
{
|
||||
draw_theme_interface(themes_list, theme_count, selected_theme, preview_mode, shuffle_theme_count);
|
||||
} else {
|
||||
draw_splash_interface(splashes_list, splash_count, selected_splash, preview_mode);
|
||||
}
|
||||
|
||||
if (kDown & KEY_START)
|
||||
{
|
||||
if (homebrew)
|
||||
APT_HardwareResetAsync();
|
||||
else {
|
||||
srvPublishToSubscriber(0x202, 0);
|
||||
}
|
||||
}
|
||||
else if (kDown & KEY_L)
|
||||
{
|
||||
splash_mode = !splash_mode;
|
||||
}
|
||||
|
||||
if (R_FAILED(archive_result) && !splash_mode)
|
||||
{
|
||||
throw_error("Theme extdata does not exist\nSet a default theme from the home menu", ERROR);
|
||||
throw_error("Theme extdata does not exist!\nSet a default theme from the home menu.", ERROR_LEVEL_ERROR);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (kDown & KEY_R)
|
||||
|
||||
if(!preview_mode && !qr_mode && kDown & KEY_L) //toggle between splashes and themes
|
||||
{
|
||||
if (preview_mode) {
|
||||
continue;
|
||||
} else {
|
||||
u32 out;
|
||||
ACU_GetWifiStatus(&out);
|
||||
if (out)
|
||||
{
|
||||
qr_mode = !qr_mode;
|
||||
if (qr_mode) init_qr();
|
||||
else exit_qr();
|
||||
continue;
|
||||
} else {
|
||||
throw_error("Please connect to Wi-Fi before scanning QR", WARNING);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
current_mode++;
|
||||
current_mode %= MODE_AMOUNT;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (qr_mode) continue;
|
||||
|
||||
if (themes_list == NULL && !splash_mode)
|
||||
continue;
|
||||
|
||||
if (splashes_list == NULL && splash_mode)
|
||||
continue;
|
||||
|
||||
Theme_s * current_theme = &themes_list[selected_theme];
|
||||
Splash_s *current_splash = &splashes_list[selected_splash];
|
||||
|
||||
if (kDown & KEY_Y)
|
||||
else if(!preview_mode && kDown & KEY_R) //toggle QR mode
|
||||
{
|
||||
if (!preview_mode)
|
||||
u32 out;
|
||||
ACU_GetWifiStatus(&out);
|
||||
if(out)
|
||||
{
|
||||
if (!splash_mode)
|
||||
{
|
||||
if (!current_theme->has_preview)
|
||||
load_theme_preview(current_theme);
|
||||
|
||||
preview_mode = current_theme->has_preview;
|
||||
} else {
|
||||
load_splash_preview(current_splash);
|
||||
preview_mode = true;
|
||||
}
|
||||
qr_mode = !qr_mode;
|
||||
if(qr_mode)
|
||||
init_qr();
|
||||
else
|
||||
exit_qr();
|
||||
}
|
||||
else
|
||||
preview_mode = false;
|
||||
}
|
||||
|
||||
//don't allow anything while the preview is up
|
||||
if (preview_mode)
|
||||
{
|
||||
throw_error("Please connect to Wi-Fi before scanning QR", ERROR_LEVEL_WARNING);
|
||||
}
|
||||
continue;
|
||||
|
||||
}
|
||||
else if(!qr_mode && kDown & KEY_Y) //toggle preview mode
|
||||
{
|
||||
if(!preview_mode)
|
||||
{
|
||||
preview_mode = load_preview(*current_list, &preview_offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
preview_mode = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if(qr_mode && kDown & KEY_L) //scan a QR code while in QR mode
|
||||
{
|
||||
CAMU_StopCapture(PORT_BOTH);
|
||||
CAMU_Activate(SELECT_NONE);
|
||||
qr_mode = !scan_qr(current_mode);
|
||||
CAMU_Activate(SELECT_OUT1_OUT2);
|
||||
CAMU_StartCapture(PORT_BOTH);
|
||||
|
||||
if(!qr_mode)
|
||||
{
|
||||
free(current_list->entries);
|
||||
memset(current_list, 0, sizeof(Entry_List_s));
|
||||
load_entries(main_paths[current_mode], current_list);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if(qr_mode || preview_mode || current_list->entries == NULL)
|
||||
continue;
|
||||
|
||||
int selected_entry = current_list->selected_entry;
|
||||
Entry_s * current_entry = ¤t_list->entries[selected_entry];
|
||||
|
||||
// Actions
|
||||
else if (kDown & KEY_X)
|
||||
if(kDown & KEY_X)
|
||||
{
|
||||
if (splash_mode) {
|
||||
draw_splash_install(UNINSTALL);
|
||||
splash_delete();
|
||||
} else {
|
||||
draw_theme_install(BGM_INSTALL);
|
||||
bgm_install(*current_theme);
|
||||
switch(current_mode)
|
||||
{
|
||||
case MODE_THEMES:
|
||||
draw_install(INSTALL_BGM);
|
||||
bgm_install(*current_entry);
|
||||
break;
|
||||
case MODE_SPLASHES:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (kDown & KEY_A)
|
||||
else if(kDown & KEY_A)
|
||||
{
|
||||
if (splash_mode)
|
||||
switch(current_mode)
|
||||
{
|
||||
draw_splash_install(SINGLE_INSTALL);
|
||||
splash_install(*current_splash);
|
||||
svcSleepThread(5e8);
|
||||
} else {
|
||||
draw_theme_install(SINGLE_INSTALL);
|
||||
single_install(*current_theme);
|
||||
case MODE_THEMES:
|
||||
draw_install(INSTALL_SINGLE);
|
||||
theme_install(*current_entry);
|
||||
break;
|
||||
case MODE_SPLASHES:
|
||||
draw_install(INSTALL_SPLASH);
|
||||
splash_install(*current_entry);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//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)
|
||||
{
|
||||
if (splash_mode)
|
||||
switch(current_mode)
|
||||
{
|
||||
|
||||
} else {
|
||||
if (shuffle_theme_count < 10)
|
||||
{
|
||||
if (current_theme->in_shuffle) shuffle_theme_count--;
|
||||
else shuffle_theme_count++;
|
||||
current_theme->in_shuffle = !(current_theme->in_shuffle);
|
||||
} else {
|
||||
if (current_theme->in_shuffle) {
|
||||
shuffle_theme_count--;
|
||||
current_theme->in_shuffle = false;
|
||||
}
|
||||
}
|
||||
case MODE_THEMES:
|
||||
if(current_entry->in_shuffle) current_list->shuffle_count--;
|
||||
else current_list->shuffle_count++;
|
||||
current_entry->in_shuffle = !current_entry->in_shuffle;
|
||||
break;
|
||||
case MODE_SPLASHES:
|
||||
draw_install(INSTALL_SPLASH_DELETE);
|
||||
splash_delete();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
else if (kDown & KEY_SELECT)
|
||||
else if(kDown & KEY_SELECT)
|
||||
{
|
||||
if (splash_mode)
|
||||
switch(current_mode)
|
||||
{
|
||||
|
||||
} else {
|
||||
if (shuffle_theme_count > 0)
|
||||
{
|
||||
draw_theme_install(SHUFFLE_INSTALL);
|
||||
shuffle_install(themes_list, theme_count);
|
||||
shuffle_theme_count = 0;
|
||||
}
|
||||
else {
|
||||
throw_error("You dont have any Shuffle selected.", WARNING);
|
||||
}
|
||||
case MODE_THEMES:
|
||||
if(current_list->shuffle_count > 0)
|
||||
{
|
||||
draw_install(INSTALL_SHUFFLE);
|
||||
shuffle_install(current_list->entries, current_list->entries_count);
|
||||
current_list->shuffle_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw_error("You dont have any Shuffle selected.", ERROR_LEVEL_WARNING);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Movement in the UI
|
||||
else if (kDown & KEY_DOWN)
|
||||
else if(kDown & KEY_UP)
|
||||
{
|
||||
if (splash_mode)
|
||||
{
|
||||
selected_splash++;
|
||||
if (selected_splash >= splash_count)
|
||||
selected_splash = 0;
|
||||
} else {
|
||||
selected_theme++;
|
||||
if (selected_theme >= theme_count)
|
||||
selected_theme = 0;
|
||||
}
|
||||
change_selected(current_list, -1);
|
||||
}
|
||||
else if (kDown & KEY_UP)
|
||||
else if(kDown & KEY_DOWN)
|
||||
{
|
||||
if (splash_mode)
|
||||
{
|
||||
selected_splash--;
|
||||
if (selected_splash < 0)
|
||||
selected_splash = splash_count - 1;
|
||||
} else {
|
||||
selected_theme--;
|
||||
if (selected_theme < 0)
|
||||
selected_theme = theme_count - 1;
|
||||
}
|
||||
change_selected(current_list, 1);
|
||||
}
|
||||
// Quick moving
|
||||
else if (kDown & KEY_LEFT)
|
||||
else if(kDown & KEY_LEFT)
|
||||
{
|
||||
if (splash_mode)
|
||||
{
|
||||
selected_splash -= 4;
|
||||
if (selected_splash < 0) selected_splash = 0;
|
||||
} else {
|
||||
selected_theme -= 4;
|
||||
if (selected_theme < 0) selected_theme = 0;
|
||||
}
|
||||
change_selected(current_list, -ENTRIES_PER_SCREEN);
|
||||
}
|
||||
else if (kDown & KEY_RIGHT)
|
||||
else if(kDown & KEY_RIGHT)
|
||||
{
|
||||
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;
|
||||
}
|
||||
change_selected(current_list, ENTRIES_PER_SCREEN);
|
||||
}
|
||||
|
||||
// Fast scroll using circle pad
|
||||
else if (kHeld & KEY_CPAD_UP)
|
||||
else if(kHeld & KEY_CPAD_UP)
|
||||
{
|
||||
svcSleepThread(100000000);
|
||||
|
||||
if (splash_mode)
|
||||
{
|
||||
selected_splash--;
|
||||
if (selected_splash < 0)
|
||||
selected_splash = splash_count - 1;
|
||||
} else {
|
||||
selected_theme--;
|
||||
if (selected_theme < 0)
|
||||
selected_theme = theme_count - 1;
|
||||
}
|
||||
change_selected(current_list, -1);
|
||||
}
|
||||
else if (kHeld & KEY_CPAD_DOWN)
|
||||
else if(kHeld & KEY_CPAD_DOWN)
|
||||
{
|
||||
svcSleepThread(100000000);
|
||||
|
||||
if (splash_mode)
|
||||
{
|
||||
selected_splash++;
|
||||
if (selected_splash >= splash_count)
|
||||
selected_splash = 0;
|
||||
} else {
|
||||
selected_theme++;
|
||||
if (selected_theme >= theme_count)
|
||||
selected_theme = 0;
|
||||
}
|
||||
change_selected(current_list, 1);
|
||||
}
|
||||
else if (kDown & KEY_CPAD_LEFT)
|
||||
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;
|
||||
}
|
||||
change_selected(current_list, -ENTRIES_PER_SCREEN);
|
||||
}
|
||||
else if (kDown & KEY_CPAD_RIGHT)
|
||||
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)
|
||||
{
|
||||
current_theme->has_preview = false;
|
||||
previously_selected = selected_theme;
|
||||
change_selected(current_list, ENTRIES_PER_SCREEN);
|
||||
}
|
||||
}
|
||||
exit_screens();
|
||||
exit_services();
|
||||
|
||||
exit_function();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -26,254 +26,34 @@
|
||||
#include "splashes.h"
|
||||
#include "unicode.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;
|
||||
|
||||
if ((lodepng_decode32(&image, &width, &height, (u8*)preview_buffer, size)) == 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 res = 0;
|
||||
Handle dir_handle;
|
||||
|
||||
if (R_FAILED(res = FSUSER_OpenDirectory(&dir_handle, ArchiveSD, fsMakePath(PATH_ASCII, SPLASHES_PATH))))
|
||||
return res;
|
||||
|
||||
if (*splashes_list != NULL)
|
||||
{
|
||||
free(*splashes_list);
|
||||
*splashes_list = NULL;
|
||||
*splash_count = 0;
|
||||
}
|
||||
|
||||
u32 entries_read = 1;
|
||||
while (entries_read)
|
||||
{
|
||||
FS_DirectoryEntry entry = {0};
|
||||
if (R_FAILED(res = FSDIR_Read(dir_handle, &entries_read, 1, &entry)) || entries_read == 0)
|
||||
break;
|
||||
|
||||
if (!(entry.attributes & FS_ATTRIBUTE_DIRECTORY) && strcmp(entry.shortExt, "ZIP"))
|
||||
continue;
|
||||
|
||||
*splash_count += entries_read;
|
||||
*splashes_list= realloc(*splashes_list, (*splash_count) * sizeof(Splash_s));
|
||||
if (splashes_list == NULL)
|
||||
break;
|
||||
|
||||
Splash_s *current_splash = &(*splashes_list)[*splash_count-1];
|
||||
memset(current_splash, 0, sizeof(Splash_s));
|
||||
|
||||
u16 splash_path[0x106]= {0};
|
||||
struacat(splash_path, SPLASHES_PATH);
|
||||
strucat(splash_path, entry.name);
|
||||
|
||||
char pathchar[0x106] = {0};
|
||||
utf16_to_utf8((u8*) pathchar, splash_path, 0x106);
|
||||
|
||||
memcpy(current_splash->path, splash_path, 0x106 * sizeof(u16));
|
||||
current_splash->is_zip = !strcmp(entry.shortExt, "ZIP");
|
||||
|
||||
ssize_t iconID = TEXTURE_PREVIEW + theme_count + *splash_count;
|
||||
parse_smdh(current_splash, iconID, entry.name);
|
||||
}
|
||||
|
||||
FSDIR_Close(dir_handle);
|
||||
|
||||
qsort(*splashes_list, (long)*splash_count, sizeof(Splash_s), splashcmp);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int splashcmp(const void* a, const void* b) //essentially a memcmp alias, so that it can be used properly with qsort
|
||||
{
|
||||
Splash_s *splash_a = (Splash_s *)a;
|
||||
Splash_s *splash_b = (Splash_s *)b;
|
||||
|
||||
return memcmp(splash_a, splash_b, 0x40*sizeof(u16));
|
||||
}
|
||||
|
||||
void splash_delete()
|
||||
void splash_delete(void)
|
||||
{
|
||||
remove("/luma/splash.bin");
|
||||
remove("/luma/splashbottom.bin");
|
||||
}
|
||||
|
||||
void splash_install(Splash_s splash_to_install)
|
||||
void splash_install(Entry_s splash)
|
||||
{
|
||||
char *screen_buf = NULL;
|
||||
u32 size = 0;
|
||||
if (splash_to_install.is_zip)
|
||||
{
|
||||
size = zip_file_to_buf("splash.bin", splash_to_install.path, &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;
|
||||
}
|
||||
|
||||
size = zip_file_to_buf("splashbottom.bin", splash_to_install.path, &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;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
u32 size = load_data("/splash.bin", splash, &screen_buf);
|
||||
remake_file("/luma/splash.bin", ArchiveSD, size);
|
||||
buf_to_file(size, "/luma/splash.bin", ArchiveSD, screen_buf);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
size = load_data("/splashbottom.bin", splash, &screen_buf);
|
||||
remake_file("/luma/splashbottom.bin", ArchiveSD, size);
|
||||
buf_to_file(size, "/luma/splashbottom.bin", ArchiveSD, screen_buf);
|
||||
|
||||
char *config_buf;
|
||||
size = file_to_buf(fsMakePath(PATH_ASCII, "/luma/config.bin"), ArchiveSD, &config_buf);
|
||||
if (size)
|
||||
if(size)
|
||||
{
|
||||
if (config_buf[0xC] == 0)
|
||||
if(config_buf[0xC] == 0)
|
||||
{
|
||||
free(config_buf);
|
||||
throw_error("WARNING: Splashes are disabled in Luma Config", WARNING);
|
||||
throw_error("WARNING: Splashes are disabled in Luma Config", ERROR_LEVEL_WARNING);
|
||||
}
|
||||
}
|
||||
}
|
||||
363
source/themes.c
363
source/themes.c
@@ -27,209 +27,25 @@
|
||||
#include "themes.h"
|
||||
#include "unicode.h"
|
||||
#include "fs.h"
|
||||
#include <time.h>
|
||||
#include "draw.h"
|
||||
|
||||
#include "pp2d/pp2d/pp2d.h"
|
||||
#include "pp2d/pp2d/lodepng.h"
|
||||
#define BGM_MAX_SIZE 3371008
|
||||
|
||||
void load_theme_preview(Theme_s *theme)
|
||||
{
|
||||
//free the previously loaded preview. wont do anything if there wasnt one
|
||||
pp2d_free_texture(TEXTURE_PREVIEW);
|
||||
|
||||
char *preview_buffer = NULL;
|
||||
u64 size = 0;
|
||||
if (!(theme->is_zip))
|
||||
{
|
||||
u16 path_to_preview[0x106] = {0};
|
||||
strucat(path_to_preview, theme->path);
|
||||
struacat(path_to_preview, "/preview.png");
|
||||
size = file_to_buf(fsMakePath(PATH_UTF16, path_to_preview), ArchiveSD, &preview_buffer);
|
||||
} else {
|
||||
size = zip_file_to_buf("preview.png", theme->path, &preview_buffer);
|
||||
}
|
||||
|
||||
if (!size)
|
||||
{
|
||||
free(preview_buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
u8 * image = NULL;
|
||||
unsigned int width = 0, height = 0;
|
||||
|
||||
int result = lodepng_decode32(&image, &width, &height, (u8*)preview_buffer, size);
|
||||
if (result == 0) // no error
|
||||
{
|
||||
for (u32 i = 0; i < width; i++)
|
||||
{
|
||||
for (u32 j = 0; j < height; j++)
|
||||
{
|
||||
u32 p = (i + j*width) * 4;
|
||||
|
||||
u8 r = *(u8*)(image + p);
|
||||
u8 g = *(u8*)(image + p + 1);
|
||||
u8 b = *(u8*)(image + p + 2);
|
||||
u8 a = *(u8*)(image + p + 3);
|
||||
|
||||
*(image + p) = a;
|
||||
*(image + p + 1) = b;
|
||||
*(image + p + 2) = g;
|
||||
*(image + p + 3) = r;
|
||||
}
|
||||
}
|
||||
|
||||
theme->has_preview = true;
|
||||
pp2d_load_texture_memory(TEXTURE_PREVIEW, image, (u32)width, (u32)height);
|
||||
theme->preview_offset = (width-400)/2;
|
||||
}
|
||||
|
||||
free(image);
|
||||
free(preview_buffer);
|
||||
}
|
||||
|
||||
static void parse_smdh(Theme_s *theme, ssize_t textureID, u16 *dir_name)
|
||||
{
|
||||
char *info_buffer = NULL;
|
||||
u64 size = 0;
|
||||
if (!(theme->is_zip))
|
||||
{
|
||||
u16 path_to_smdh[0x106] = {0};
|
||||
strucat(path_to_smdh, theme->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", theme->path, &info_buffer);
|
||||
}
|
||||
|
||||
if (!size)
|
||||
{
|
||||
free(info_buffer);
|
||||
memset(theme->name, 0, 0x80);
|
||||
memset(theme->desc, 0, 0x100);
|
||||
memset(theme->author, 0, 0x80);
|
||||
memcpy(theme->name, dir_name, 0x80);
|
||||
utf8_to_utf16(theme->desc, (u8*)"No description", 0x100);
|
||||
utf8_to_utf16(theme->author, (u8*)"Unknown author", 0x80);
|
||||
theme->placeholder_color = RGBA8(rand() % 255, rand() % 255, rand() % 255, 255);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(theme->name, info_buffer + 0x08, 0x80);
|
||||
memcpy(theme->desc, info_buffer + 0x88, 0x100);
|
||||
memcpy(theme->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);
|
||||
theme->icon_id = textureID;
|
||||
|
||||
free(image);
|
||||
free(icon_data);
|
||||
free(info_buffer);
|
||||
}
|
||||
|
||||
Result get_themes(Theme_s **themes_list, int *theme_count)
|
||||
{
|
||||
shuffle_theme_count = 0;
|
||||
Result res = 0;
|
||||
Handle dir_handle;
|
||||
res = FSUSER_OpenDirectory(&dir_handle, ArchiveSD, fsMakePath(PATH_ASCII, THEMES_PATH));
|
||||
if (R_FAILED(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;
|
||||
|
||||
while (entries_read)
|
||||
{
|
||||
FS_DirectoryEntry entry = {0};
|
||||
res = FSDIR_Read(dir_handle, &entries_read, 1, &entry);
|
||||
if (R_FAILED(res) || entries_read == 0)
|
||||
break;
|
||||
|
||||
if (!(entry.attributes & FS_ATTRIBUTE_DIRECTORY) && strcmp(entry.shortExt, "ZIP"))
|
||||
continue;
|
||||
|
||||
*theme_count += entries_read;
|
||||
*themes_list = realloc(*themes_list, (*theme_count) * sizeof(Theme_s));
|
||||
if (*themes_list == NULL)
|
||||
break;
|
||||
|
||||
Theme_s* current_theme = &(*themes_list)[*theme_count-1];
|
||||
memset(current_theme, 0, sizeof(Theme_s));
|
||||
|
||||
u16 theme_path[0x106] = {0};
|
||||
struacat(theme_path, THEMES_PATH);
|
||||
strucat(theme_path, entry.name);
|
||||
|
||||
char pathchar[0x106] = {0};
|
||||
utf16_to_utf8((u8*)pathchar, theme_path, 0x106);
|
||||
|
||||
memcpy(current_theme->path, theme_path, 0x106 * sizeof(u16));
|
||||
current_theme->is_zip = !strcmp(entry.shortExt, "ZIP");
|
||||
|
||||
ssize_t iconID = TEXTURE_PREVIEW + *theme_count;
|
||||
parse_smdh(current_theme, iconID, entry.name);
|
||||
}
|
||||
|
||||
FSDIR_Close(dir_handle);
|
||||
|
||||
qsort(*themes_list, (long)*theme_count, sizeof(Theme_s), themecmp); //alphabet sort
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int themecmp(const void* a, const void* b) //essentially a memcmp alias, so that it can be used properly with qsort
|
||||
{
|
||||
Theme_s *theme_a = (Theme_s *)a;
|
||||
Theme_s *theme_b = (Theme_s *)b;
|
||||
|
||||
return memcmp(theme_a, theme_b, 0x40*sizeof(u16));
|
||||
}
|
||||
|
||||
void del_theme(u16 *path)
|
||||
void delete_theme(Entry_s theme)
|
||||
{
|
||||
Handle dir_handle;
|
||||
Result res = FSUSER_OpenDirectory(&dir_handle, ArchiveSD, fsMakePath(PATH_UTF16, path));
|
||||
if (R_SUCCEEDED(res))
|
||||
Result res = FSUSER_OpenDirectory(&dir_handle, ArchiveSD, fsMakePath(PATH_UTF16, theme.path));
|
||||
if(R_SUCCEEDED(res))
|
||||
{
|
||||
FSDIR_Close(dir_handle);
|
||||
FSUSER_DeleteDirectoryRecursively(ArchiveSD, fsMakePath(PATH_UTF16, path));
|
||||
FSUSER_DeleteDirectoryRecursively(ArchiveSD, fsMakePath(PATH_UTF16, theme.path));
|
||||
} else
|
||||
{
|
||||
FSUSER_DeleteFile(ArchiveSD, fsMakePath(PATH_UTF16, path));
|
||||
FSUSER_DeleteFile(ArchiveSD, fsMakePath(PATH_UTF16, theme.path));
|
||||
}
|
||||
}
|
||||
|
||||
Result bgm_install(Theme_s bgm_to_install)
|
||||
Result bgm_install(Entry_s bgm_to_install)
|
||||
{
|
||||
char *savedata_buf;
|
||||
char *thememanage_buf;
|
||||
@@ -245,31 +61,23 @@ Result bgm_install(Theme_s bgm_to_install)
|
||||
Result result = buf_to_file(savedata_size, "/SaveData.dat", ArchiveHomeExt, savedata_buf);
|
||||
free(savedata_buf);
|
||||
|
||||
if (!R_SUCCEEDED(result)) return result;
|
||||
if(R_FAILED(result)) return result;
|
||||
|
||||
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);
|
||||
} else {
|
||||
u16 path[0x106] = {0};
|
||||
memcpy(path, bgm_to_install.path, 0x106 * sizeof(u16));
|
||||
struacat(path, "/bgm.bcstm");
|
||||
music_size = file_to_buf(fsMakePath(PATH_UTF16, path), ArchiveSD, &music);
|
||||
}
|
||||
music_size = load_data("/bgm.bcstm", bgm_to_install, &music);
|
||||
|
||||
if (music_size == 0)
|
||||
if(music_size == 0)
|
||||
{
|
||||
music = calloc(1, 3371008);
|
||||
} else if (music_size > 3371008) {
|
||||
music = calloc(1, BGM_MAX_SIZE);
|
||||
} else if(music_size > BGM_MAX_SIZE) {
|
||||
free(music);
|
||||
puts("musicrip");
|
||||
return MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, RD_TOO_LARGE);
|
||||
}
|
||||
|
||||
result = buf_to_file(music_size == 0 ? 3371008 : music_size, "/BgmCache.bin", ArchiveThemeExt, music);
|
||||
result = buf_to_file(music_size == 0 ? BGM_MAX_SIZE : music_size, "/BgmCache.bin", ArchiveThemeExt, music);
|
||||
free(music);
|
||||
|
||||
if (!R_SUCCEEDED(result)) return result;
|
||||
if(R_FAILED(result)) return result;
|
||||
|
||||
file_to_buf(fsMakePath(PATH_ASCII, "/ThemeManage.bin"), ArchiveThemeExt, &thememanage_buf);
|
||||
thememanage_buf[0x00] = 1;
|
||||
@@ -296,23 +104,24 @@ Result bgm_install(Theme_s bgm_to_install)
|
||||
result = buf_to_file(0x800, "/ThemeManage.bin", ArchiveThemeExt, thememanage_buf);
|
||||
free(thememanage_buf);
|
||||
|
||||
if (!R_SUCCEEDED(result)) return result;
|
||||
if(R_FAILED(result)) return result;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Install a single theme
|
||||
Result single_install(Theme_s theme_to_install)
|
||||
Result theme_install(Entry_s theme)
|
||||
{
|
||||
char *body;
|
||||
char *music;
|
||||
char *savedata_buf;
|
||||
char *thememanage_buf;
|
||||
u32 body_size;
|
||||
u32 music_size;
|
||||
u32 savedata_size;
|
||||
char *body = NULL;
|
||||
char *music = NULL;
|
||||
char *savedata_buf = NULL;
|
||||
char *thememanage_buf = NULL;
|
||||
u32 body_size = 0;
|
||||
u32 music_size = 0;
|
||||
u32 savedata_size = 0;
|
||||
|
||||
savedata_size = file_to_buf(fsMakePath(PATH_ASCII, "/SaveData.dat"), ArchiveHomeExt, &savedata_buf);
|
||||
DEBUGPOS("savedata: %p, %lx\n", savedata_buf, savedata_size);
|
||||
savedata_buf[0x141b] = 0;
|
||||
memset(&savedata_buf[0x13b8], 0, 8);
|
||||
savedata_buf[0x13bd] = 3;
|
||||
@@ -320,56 +129,38 @@ Result single_install(Theme_s theme_to_install)
|
||||
Result result = buf_to_file(savedata_size, "/SaveData.dat", ArchiveHomeExt, savedata_buf);
|
||||
free(savedata_buf);
|
||||
|
||||
if (!R_SUCCEEDED(result)) return result;
|
||||
if(R_FAILED(result)) return result;
|
||||
|
||||
// Open body cache file. Test if theme is zipped
|
||||
if (theme_to_install.is_zip)
|
||||
{
|
||||
body_size = zip_file_to_buf("body_LZ.bin", theme_to_install.path, &body);
|
||||
}
|
||||
else
|
||||
{
|
||||
u16 path[0x106] = {0};
|
||||
memcpy(path, theme_to_install.path, 0x106 * sizeof(u16));
|
||||
struacat(path, "/body_lz.bin");
|
||||
body_size = file_to_buf(fsMakePath(PATH_UTF16, path), ArchiveSD, &body);
|
||||
}
|
||||
// Open body cache file.
|
||||
body_size = load_data("/body_LZ.bin", theme, &body);
|
||||
|
||||
if (body_size == 0)
|
||||
if(body_size == 0)
|
||||
{
|
||||
free(body);
|
||||
puts("bodyrip");
|
||||
DEBUGPOS("bodyrip");
|
||||
return MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, RD_NOT_FOUND);
|
||||
}
|
||||
|
||||
result = buf_to_file(body_size, "/BodyCache.bin", ArchiveThemeExt, body); // Write body data to file
|
||||
free(body);
|
||||
|
||||
if (!R_SUCCEEDED(result)) return result;
|
||||
if(R_FAILED(result)) return result;
|
||||
|
||||
if (theme_to_install.is_zip) // Same as above but this time with bgm
|
||||
{
|
||||
music_size = zip_file_to_buf("bgm.bcstm", theme_to_install.path, &music);
|
||||
} else {
|
||||
u16 path[0x106] = {0};
|
||||
memcpy(path, theme_to_install.path, 0x106 * sizeof(u16));
|
||||
struacat(path, "/bgm.bcstm");
|
||||
music_size = file_to_buf(fsMakePath(PATH_UTF16, path), ArchiveSD, &music);
|
||||
}
|
||||
music_size = load_data("/bgm.bcstm", theme, &music);
|
||||
|
||||
if (music_size == 0)
|
||||
if(music_size == 0)
|
||||
{
|
||||
music = calloc(1, 3371008);
|
||||
} else if (music_size > 3371008) {
|
||||
music = calloc(1, BGM_MAX_SIZE);
|
||||
} else if(music_size > BGM_MAX_SIZE) {
|
||||
free(music);
|
||||
puts("musicrip");
|
||||
DEBUGPOS("musicrip");
|
||||
return MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, RD_TOO_LARGE);
|
||||
}
|
||||
|
||||
result = buf_to_file(music_size == 0 ? 3371008 : music_size, "/BgmCache.bin", ArchiveThemeExt, music);
|
||||
result = buf_to_file(music_size == 0 ? BGM_MAX_SIZE : music_size, "/BgmCache.bin", ArchiveThemeExt, music);
|
||||
free(music);
|
||||
|
||||
if (!R_SUCCEEDED(result)) return result;
|
||||
if(R_FAILED(result)) return result;
|
||||
|
||||
file_to_buf(fsMakePath(PATH_ASCII, "/ThemeManage.bin"), ArchiveThemeExt, &thememanage_buf);
|
||||
thememanage_buf[0x00] = 1;
|
||||
@@ -398,18 +189,18 @@ Result single_install(Theme_s theme_to_install)
|
||||
result = buf_to_file(0x800, "/ThemeManage.bin", ArchiveThemeExt, thememanage_buf);
|
||||
free(thememanage_buf);
|
||||
|
||||
if (!R_SUCCEEDED(result)) return result;
|
||||
if(R_FAILED(result)) return result;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result shuffle_install(Theme_s *themes_list, int theme_count)
|
||||
Result shuffle_install(Entry_s* themes_list, int themes_count)
|
||||
{
|
||||
u8 count = 0;
|
||||
Theme_s *shuffle_themes[10] = {0};
|
||||
Entry_s *shuffle_themes[10] = {0};
|
||||
u32 body_sizes[10] = {0};
|
||||
u32 bgm_sizes[10] = {0};
|
||||
for (int i = 0; i < theme_count; i++)
|
||||
for (int i = 0; i < themes_count; i++)
|
||||
{
|
||||
if (count > 10) return MAKERESULT(RL_USAGE, RS_INVALIDARG, RM_COMMON, RD_INVALID_SELECTION);
|
||||
if (themes_list[i].in_shuffle)
|
||||
@@ -435,10 +226,10 @@ Result shuffle_install(Theme_s *themes_list, int theme_count)
|
||||
savedata_buf[0x13bd] = 3;
|
||||
savedata_buf[0x13b8] = 0xff;
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
for(int i = 0; i < 10; i++)
|
||||
{
|
||||
memset(&savedata_buf[0x13c0 + 0x8 * i], 0, 8); // clear any existing theme structure. 8 is the length of the theme structure, so 8 * i is the pos of the current one
|
||||
if (count > i) // if we are still installing themes...
|
||||
if(count > i) // if we are still installing themes...
|
||||
{
|
||||
savedata_buf[0x13c0 + (8 * i)] = i; // index
|
||||
savedata_buf[0x13c0 + (8 * i) + 5] = 3; // persistence (?)
|
||||
@@ -448,61 +239,39 @@ Result shuffle_install(Theme_s *themes_list, int theme_count)
|
||||
Result result = buf_to_file(size, "/SaveData.dat", ArchiveHomeExt, savedata_buf);
|
||||
free(savedata_buf);
|
||||
|
||||
if (!R_SUCCEEDED(result)) return result;
|
||||
if(R_FAILED(result)) return result;
|
||||
|
||||
remake_file("/BodyCache_rd.bin", ArchiveThemeExt, 0x150000 * 10); // Enough space for 10 theme files
|
||||
Handle body_cache_handle;
|
||||
FSUSER_OpenFile(&body_cache_handle, ArchiveThemeExt, fsMakePath(PATH_ASCII, "/BodyCache_rd.bin"), FS_OPEN_WRITE, 0);
|
||||
for (int i = 0; i < 10; i++)
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
if (count > i)
|
||||
{
|
||||
if (shuffle_themes[i]->is_zip)
|
||||
{
|
||||
char *body_buf;
|
||||
u32 body_size = zip_file_to_buf("body_LZ.bin", shuffle_themes[i]->path, &body_buf);
|
||||
body_sizes[i] = body_size;
|
||||
FSFILE_Write(body_cache_handle, NULL, 0x150000 * i, body_buf, body_size, FS_WRITE_FLUSH);
|
||||
free(body_buf);
|
||||
} else {
|
||||
u16 path[0x106] = {0};
|
||||
strucat(path, shuffle_themes[i]->path);
|
||||
struacat(path, "/body_LZ.bin");
|
||||
char *body_buf;
|
||||
u32 body_size = file_to_buf(fsMakePath(PATH_UTF16, path), ArchiveSD, &body_buf);
|
||||
body_sizes[i] = body_size;
|
||||
FSFILE_Write(body_cache_handle, NULL, 0x150000 * i, body_buf, body_size, FS_WRITE_FLUSH);
|
||||
free(body_buf);
|
||||
}
|
||||
}
|
||||
Entry_s * current_theme = shuffle_themes[i];
|
||||
char * body_buf = NULL;
|
||||
u32 body_size = load_data("/body_LZ.bin", *current_theme, &body_buf);
|
||||
|
||||
body_sizes[i] = body_size;
|
||||
FSFILE_Write(body_cache_handle, NULL, 0x150000 * i, body_buf, body_size, FS_WRITE_FLUSH);
|
||||
free(body_buf);
|
||||
}
|
||||
|
||||
FSFILE_Close(body_cache_handle);
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
for(int i = 0; i < 10; i++)
|
||||
{
|
||||
char bgm_cache_path[17] = {0};
|
||||
sprintf(bgm_cache_path, "/BgmCache_%.2i.bin", i);
|
||||
remake_file(bgm_cache_path, ArchiveThemeExt, 3371008);
|
||||
if (count > i)
|
||||
remake_file(bgm_cache_path, ArchiveThemeExt, BGM_MAX_SIZE);
|
||||
if(count > i)
|
||||
{
|
||||
char *music_buf;
|
||||
u32 music_size;
|
||||
Entry_s * current_theme = shuffle_themes[i];
|
||||
char *music_buf = NULL;
|
||||
u32 music_size = music_size = load_data("/bgm.bcstm", *current_theme, &music_buf);
|
||||
|
||||
if (shuffle_themes[i]->is_zip)
|
||||
if(!music_size)
|
||||
{
|
||||
music_size = zip_file_to_buf("bgm.bcstm", shuffle_themes[i]->path, &music_buf);
|
||||
} else {
|
||||
u16 path[0x106] = {0};
|
||||
strucat(path, shuffle_themes[i]->path);
|
||||
struacat(path, "/bgm.bcstm");
|
||||
music_size = file_to_buf(fsMakePath(PATH_UTF16, path), ArchiveSD, &music_buf);
|
||||
}
|
||||
|
||||
if (!music_size)
|
||||
{
|
||||
char *empty = calloc(1, 3371008);
|
||||
buf_to_file(3371008, bgm_cache_path, ArchiveThemeExt, empty);
|
||||
char *empty = calloc(1, BGM_MAX_SIZE);
|
||||
buf_to_file(BGM_MAX_SIZE, bgm_cache_path, ArchiveThemeExt, empty);
|
||||
bgm_sizes[i] = 0;
|
||||
free(empty);
|
||||
continue;
|
||||
@@ -511,8 +280,8 @@ Result shuffle_install(Theme_s *themes_list, int theme_count)
|
||||
buf_to_file(music_size, bgm_cache_path, ArchiveThemeExt, music_buf);
|
||||
free(music_buf);
|
||||
} else {
|
||||
char *empty = calloc(1, 3371008);
|
||||
buf_to_file(3371008, bgm_cache_path, ArchiveThemeExt, empty);
|
||||
char *empty = calloc(1, BGM_MAX_SIZE);
|
||||
buf_to_file(BGM_MAX_SIZE, bgm_cache_path, ArchiveThemeExt, empty);
|
||||
bgm_sizes[i] = 0;
|
||||
free(empty);
|
||||
}
|
||||
@@ -538,7 +307,7 @@ Result shuffle_install(Theme_s *themes_list, int theme_count)
|
||||
*bodysizeloc = (u32) 0;
|
||||
*bgmsizeloc = (u32) 0;
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
for(int i = 0; i < 10; i++)
|
||||
{
|
||||
bodysizeloc = (u32*) (&thememanage_buf[0x338 + (4 * i)]); // body size info for shuffle themes starts at 0x338 and is 4 bytes for each theme
|
||||
bgmsizeloc = (u32*) (&thememanage_buf[0x360 + (4 * i)]); // same thing for bgm but starting at 0x360
|
||||
@@ -549,7 +318,7 @@ Result shuffle_install(Theme_s *themes_list, int theme_count)
|
||||
result = buf_to_file(0x800, "/ThemeManage.bin", ArchiveThemeExt, thememanage_buf);
|
||||
free(thememanage_buf);
|
||||
|
||||
if (!R_SUCCEEDED(result)) return result;
|
||||
if(R_FAILED(result)) return result;
|
||||
|
||||
return MAKERESULT(RL_SUCCESS, RS_SUCCESS, RM_COMMON, RD_SUCCESS);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user