Compare commits

..

No commits in common. "master" and "v3.1.0" have entirely different histories.

35 changed files with 615 additions and 1886 deletions

1
.gitignore vendored
View File

@ -1,4 +1,3 @@
.*/
*~ *~
*.exe *.exe
*.o *.o

View File

@ -1,4 +1,4 @@
export APP_VERSION := 3.5.1 export APP_VERSION := 3.1.0
ifeq ($(RELEASE),) ifeq ($(RELEASE),)
export APP_VERSION := $(APP_VERSION)-$(shell git describe --dirty --always) export APP_VERSION := $(APP_VERSION)-$(shell git describe --dirty --always)

View File

@ -46,8 +46,6 @@ ROMFS := romfs
DIST_PATH := $(TARGET)_v$(APP_VERSION) DIST_PATH := $(TARGET)_v$(APP_VERSION)
APP_AUTHOR := switchbrew
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# options for code generation # options for code generation
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
@ -63,7 +61,7 @@ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
ASFLAGS := -g $(ARCH) ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -ldeko3d -lphysfs `freetype-config --libs` -lconfig -lturbojpeg -lpng LIBS := -lminizip `freetype-config --libs` -lconfig -lturbojpeg
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing # list of directories containing libraries, this must be the top level containing
@ -212,7 +210,6 @@ $(OUTPUT).nso : $(OUTPUT).elf
endif endif
menu.o : $(TOPDIR)/Makefile
$(OUTPUT).elf : $(OFILES) $(OUTPUT).elf : $(OFILES)
$(OFILES_SRC) : $(HFILES_BIN) $(OFILES_SRC) : $(HFILES_BIN)

View File

@ -9,12 +9,12 @@ EXTRA_CFLAGS="-D__USE_MINGW_ANSI_STDIO"
EXTRA_LDFLAGS="-lws2_32" EXTRA_LDFLAGS="-lws2_32"
endif endif
test : pc_main/main.cpp pc_main/pc_launch.c pc_main/pc_power.c pc_main/pc_netstatus.c pc_main/pc_thermalstatus.c \ test : pc_main/main.cpp pc_main/pc_launch.c pc_main/pc_power.c pc_main/pc_netstatus.c \
common/menu.c common/font.c common/language.c common/launch.c common/worker.c common/status.c \ common/menu.c common/font.c common/language.c common/launch.c common/worker.c common/status.c \
common/menu-entry.c common/menu-list.c common/message-box.c common/text.c \ common/menu-entry.c common/menu-list.c common/message-box.c common/text.c \
common/ui.c common/assets.c common/math.c common/theme.c \ common/ui.c common/assets.c common/math.c common/theme.c \
common/netloader.c common/netloader.c
gcc -Wall -O2 -g -DVERSION=\"v$(APP_VERSION)\" $(EXTRA_CFLAGS) `pkg-config freetype2 --cflags` $^ -lsfml-graphics -lsfml-window -lsfml-system -lstdc++ -lpthread `pkg-config freetype2 --libs` -lm -lphysfs -lz -lconfig -lturbojpeg -lpng $(EXTRA_LDFLAGS) -I. -iquote $(DEVKITPRO)/libnx/include -Ibuild_pc -g -o $@ gcc -Wall -O2 -g -DVERSION=\"v$(APP_VERSION)\" $(EXTRA_CFLAGS) `pkg-config freetype2 --cflags` $^ -lsfml-graphics -lsfml-window -lsfml-system -lstdc++ -lpthread `pkg-config freetype2 --libs` -lm -lminizip -lz -lconfig -lturbojpeg $(EXTRA_LDFLAGS) -I. -iquote $(DEVKITPRO)/libnx/include -Ibuild_pc -g -o $@
clean: clean:
rm -rf build_pc/ test test.* rm -rf build_pc/ test test.*

View File

@ -1,31 +1,17 @@
### Usage #### Usage
See [Homebrew_Applications](https://switchbrew.org/wiki/Homebrew_Applications) for SD layout and applications, etc. See [Switchbrew](https://switchbrew.org/wiki/Homebrew_Menu) for hbmenu docs. See [Homebrew_Applications](https://switchbrew.org/wiki/Homebrew_Applications) for SD layout and applications, etc. See [Switchbrew](https://switchbrew.org/wiki/Homebrew_Menu) for hbmenu docs.
### Download #### Download
The latest release is available from the [releases](https://github.com/switchbrew/nx-hbmenu/releases/latest) page. The latest release is available from the [releases](https://github.com/switchbrew/nx-hbmenu/releases/latest) page.
### Building #### Building
Build for the Nintendo Switch with ```make nx``` and for the PC with ```make pc```. Build with ```make nx``` or just run ```make```.
Running ```make``` builds for both systems.
The following [pacman packages](https://devkitpro.org/wiki/devkitPro_pacman) are required to build for Switch: The following is required to build: libfreetype (switch-freetype), libconfig (switch-libconfig), and libjpeg-turbo (switch-libjpeg-turbo). Where "({name})" is the pacman package. For the pc-build libminizip is required (for the Switch build, the switch-zlib package includes this).
- `switch-dev`
- `switch-freetype`
- `switch-libconfig`
- `switch-libjpeg-turbo`
- `switch-physfs`
The following libraries are required to build for PC: C11-threads are used, hence building for the pc-build may fail if C11-threads are not available.
- `libfreetype`
- `libconfig`
- `libjpeg-turbo`
- `libphysfs`
Building for Switch/PC requires `zip`.
Since C11 threads are used, building for the PC may fail if C11 threads are not available.
#### Credits #### Credits
* This uses code based on 3DS [new-hbmenu](https://github.com/fincs/new-hbmenu). * This uses code based on 3DS [new-hbmenu](https://github.com/fincs/new-hbmenu).
* `libjpeg-turbo` is used for handling JPEG icons. This library doesn't support lossless JPEG (likewise for official sw which uses `libjpeg-turbo`). * libjpeg-turbo is used for handling JPEG icons. This library doesn't support lossless JPEG (likewise for official sw which uses libjpeg-turbo).

View File

@ -1,28 +1,32 @@
#include "common.h" #include "common.h"
#include <physfs.h> #include <minizip/unzip.h>
#include <png.h>
#define GENASSET(_p, _mode, _w, _h) {{.path = _p, .imageMode = _mode, .imageSize = {_w, _h}}, {}} typedef struct {
u8 *buffer;
size_t size;
const char *filename;
} assetsDataEntry;
#define GENASSET(x) {.filename = x}
static bool g_assetsInitialized = 0; static bool g_assetsInitialized = 0;
assetsDataEntry g_assetsDataList[AssetId_Max][2] = { assetsDataEntry g_assetsDataList[AssetId_Max] = {
GENASSET("battery_icon.bin", IMAGE_MODE_RGBA32, 24, 24), GENASSET("battery_icon.bin"),
GENASSET("charging_icon.bin", IMAGE_MODE_RGBA32, 24, 24), GENASSET("charging_icon.bin"),
GENASSET("folder_icon.bin", IMAGE_MODE_RGB24, 256, 256), GENASSET("folder_icon.bin"),
GENASSET("invalid_icon.bin", IMAGE_MODE_RGB24, 256, 256), GENASSET("invalid_icon.bin"),
GENASSET("hbmenu_logo_dark.bin", IMAGE_MODE_RGBA32, 140, 60), GENASSET("hbmenu_logo_dark.bin"),
GENASSET("hbmenu_logo_light.bin", IMAGE_MODE_RGBA32, 140, 60), GENASSET("hbmenu_logo_light.bin"),
GENASSET("theme_icon_dark.bin", IMAGE_MODE_RGB24, 256, 256), GENASSET("theme_icon_dark.bin"),
GENASSET("theme_icon_light.bin", IMAGE_MODE_RGB24, 256, 256), GENASSET("theme_icon_light.bin"),
GENASSET("airplane_icon.bin", IMAGE_MODE_RGBA32, 24, 24), GENASSET("airplane_icon.bin"),
GENASSET("wifi_none_icon.bin", IMAGE_MODE_RGBA32, 24, 24), GENASSET("wifi_none_icon.bin"),
GENASSET("wifi1_icon.bin", IMAGE_MODE_RGBA32, 24, 24), GENASSET("wifi1_icon.bin"),
GENASSET("wifi2_icon.bin", IMAGE_MODE_RGBA32, 24, 24), GENASSET("wifi2_icon.bin"),
GENASSET("wifi3_icon.bin", IMAGE_MODE_RGBA32, 24, 24), GENASSET("wifi3_icon.bin"),
GENASSET("eth_icon.bin", IMAGE_MODE_RGBA32, 24, 24), GENASSET("eth_icon.bin"),
GENASSET("eth_none_icon.bin", IMAGE_MODE_RGBA32, 24, 24), GENASSET("eth_none_icon.bin"),
GENASSET("", IMAGE_MODE_RGB24, 1280, 720),
}; };
static void assetsClearEntry(assetsDataEntry *entry) { static void assetsClearEntry(assetsDataEntry *entry) {
@ -30,27 +34,61 @@ static void assetsClearEntry(assetsDataEntry *entry) {
entry->size = 0; entry->size = 0;
entry->buffer = NULL; entry->buffer = NULL;
memset(entry, 0, sizeof(*entry));
} }
static void assetsSetPixelSize(assetsDataEntry *entry) { static int assetsLoadFile(unzFile zipf, assetsDataEntry *entry) {
switch (entry->imageMode) { int ret;
case IMAGE_MODE_RGB24: int filesize=0;
entry->pixSize = 3; unz_file_info file_info;
break; u8* buffer = NULL;
case IMAGE_MODE_RGBA32: ret = unzLocateFile(zipf, entry->filename, 0);
entry->pixSize = 4;
break; if (ret==UNZ_OK) ret = unzOpenCurrentFile(zipf);
if (ret==UNZ_OK) {
ret = unzGetCurrentFileInfo(zipf, &file_info, NULL, 0, NULL, 0, NULL, 0);
filesize = file_info.uncompressed_size;
if (filesize == 0) ret = -10;
if (ret==UNZ_OK) {
buffer = (u8*)malloc(filesize);
if (buffer) {
memset(buffer, 0, filesize);
} else {
ret = -11;
} }
}
if (ret==UNZ_OK) {
ret = unzReadCurrentFile(zipf, buffer, filesize);
if(ret < filesize) {
ret = -12;
} else {
ret = UNZ_OK;
}
}
if (ret!=UNZ_OK && buffer!=NULL) free(buffer);
unzCloseCurrentFile(zipf);
}
if (ret==UNZ_OK) {
entry->buffer = buffer;
entry->size = filesize;
}
return ret;
} }
Result assetsInit(void) { Result assetsInit(void) {
bool ret=false; int ret=0;
int i, stopi; int i, stopi;
unzFile zipf;
assetsDataEntry *entry = NULL; assetsDataEntry *entry = NULL;
char tmp_path[PATH_MAX]; char tmp_path[PATH_MAX+1];
if (g_assetsInitialized) return 0; if (g_assetsInitialized) return 0;
@ -67,211 +105,65 @@ Result assetsInit(void) {
snprintf(tmp_path, sizeof(tmp_path)-1, "%s/romfs/assets.zip", menuGetRootBasePath()); snprintf(tmp_path, sizeof(tmp_path)-1, "%s/romfs/assets.zip", menuGetRootBasePath());
#endif #endif
if (PHYSFS_mount(tmp_path, "", 0)) { zipf = unzOpen(tmp_path);
ret=true; if(zipf==NULL) {
#ifdef __SWITCH__
romfsExit();
#endif
return 0x80;
}
for (i=0; i<AssetId_Max; i++) { for (i=0; i<AssetId_Max; i++) {
stopi = i; stopi = i;
entry = &g_assetsDataList[i][0]; entry = &g_assetsDataList[i];
if (entry->path[0]) { ret = assetsLoadFile(zipf, entry);
ret = assetsLoadData(i, NULL, NULL); if (ret!=UNZ_OK) break;
if (!ret) break;
}
} }
if (!ret) { if (ret!=UNZ_OK) {
for (i=0; i<stopi; i++) { for (i=0; i<stopi; i++) {
assetsClearEntry(&g_assetsDataList[i][0]); assetsClearEntry(&g_assetsDataList[i]);
} }
} }
if (ret) g_assetsInitialized = 1; if (ret==UNZ_OK) g_assetsInitialized = 1;
PHYSFS_unmount(tmp_path); unzClose(zipf);
}
#ifdef __SWITCH__ #ifdef __SWITCH__
romfsExit(); romfsExit();
return ret ? 0 : MAKERESULT(Module_Libnx, LibnxError_IoError);
#else
return ret ? 0 : 1;
#endif #endif
return ret;
} }
void assetsExit(void) { void assetsExit(void) {
int i;
if (!g_assetsInitialized) return; if (!g_assetsInitialized) return;
g_assetsInitialized = 0; g_assetsInitialized = 0;
for (int i=0; i<AssetId_Max; i++) { for (i=0; i<AssetId_Max; i++) {
assetsClearEntry(&g_assetsDataList[i][0]); assetsClearEntry(&g_assetsDataList[i]);
}
assetsClearTheme();
}
void assetsClearTheme(void) {
for (int i=0; i<AssetId_Max; i++) {
assetsClearEntry(&g_assetsDataList[i][1]);
} }
} }
bool assetsLoadJpgFromMemory(u8 *indata, size_t indata_size, u8 *outdata, ImageMode imageMode, size_t width, size_t height) { void assetsGetData(AssetId id, u8 **buffer, size_t *size) {
int w,h,samp; if (buffer) *buffer = NULL;
if (size) *size = 0;
tjhandle _jpegDecompressor = tjInitDecompress();
if (_jpegDecompressor == NULL) {
return false;
}
if (tjDecompressHeader2(_jpegDecompressor, indata, indata_size, &w, &h, &samp) == -1) {
tjDestroy(_jpegDecompressor);
return false;
}
if (w != width || h != height ) {
tjDestroy(_jpegDecompressor);
return false;
}
if (tjDecompress2(_jpegDecompressor, indata, indata_size, outdata, w, 0, h, imageMode == IMAGE_MODE_RGB24 ? TJPF_RGB : TJPF_RGBA, TJFLAG_ACCURATEDCT) == -1) {
tjDestroy(_jpegDecompressor);
return false;
}
tjDestroy(_jpegDecompressor);
return true;
}
bool assetsLoadPngFromMemory(u8 *indata, size_t indata_size, u8 *outdata, ImageMode imageMode, size_t width, size_t height) {
png_image image;
bool ret=true;
memset(&image, 0, sizeof(image));
image.version = PNG_IMAGE_VERSION;
if (png_image_begin_read_from_memory(&image, indata, indata_size) != 0) {
if (image.width != width || image.height != height)
ret = false;
if (ret) image.format = imageMode == IMAGE_MODE_RGB24 ? PNG_FORMAT_RGB : PNG_FORMAT_RGBA;
if (ret && png_image_finish_read(&image, NULL, outdata, 0, NULL) == 0)
ret = false;
}
else
ret = false;
png_image_free(&image);
return ret;
}
bool assetsPhysfsReadFile(const char *path, u8 **data_buf, size_t *filesize, bool nul_term) {
bool ret=true;
*data_buf = NULL;
if (filesize) *filesize = 0;
PHYSFS_Stat tmpstat={0};
if (!(PHYSFS_stat(path, &tmpstat) && tmpstat.filesize!=-1)) ret = false;
if (ret) {
size_t bufsize = tmpstat.filesize;
if (nul_term) bufsize++;
*data_buf = (u8*)malloc(bufsize);
if (*data_buf) memset(*data_buf, 0, bufsize);
else ret = false;
}
if (ret) {
PHYSFS_File *f = PHYSFS_openRead(path);
if (f==NULL) ret = false;
else {
ret = PHYSFS_readBytes(f, *data_buf, tmpstat.filesize) == tmpstat.filesize;
PHYSFS_close(f);
}
}
if (ret) {
if (filesize) *filesize = tmpstat.filesize;
}
else {
free(*data_buf);
*data_buf = NULL;
}
return ret;
}
bool assetsLoadData(AssetId id, const char *path, int *imageSize) {
if (id < 0 || id >= AssetId_Max) return false;
assetsDataEntry *entry = &g_assetsDataList[id][path ? 1 : 0];
if (entry->initialized) return false;
if (path) memset(entry, 0, sizeof(*entry));
if (imageSize) {
entry->imageSize[0] = imageSize[0];
entry->imageSize[1] = imageSize[1];
}
if (path) entry->imageMode = g_assetsDataList[id][0].imageMode;
assetsSetPixelSize(entry);
entry->size = entry->imageSize[0] * entry->imageSize[1] * entry->pixSize;
if (path) strncpy(entry->path, path, sizeof(entry->path)-1);
const char* ext = getExtension(entry->path);
bool ret=true;
size_t filesize=0;
if (ext==NULL) ret = false;
u8 *data_buf = NULL;
if (ret) {
entry->buffer = (u8*)malloc(entry->size);
if (entry->buffer) memset(entry->buffer, 0, entry->size);
else ret = false;
}
if (ret) ret = assetsPhysfsReadFile(entry->path, &data_buf, &filesize, false);
if (ret) {
if (strcasecmp(ext, ".bin")==0) {
if (filesize != entry->size) ret = false;
if (ret) memcpy(entry->buffer, data_buf, entry->size);
}
else if (strcasecmp(ext, ".jpg")==0 || strcasecmp(ext, ".jpeg")==0)
ret = assetsLoadJpgFromMemory(data_buf, filesize, entry->buffer, entry->imageMode, entry->imageSize[0], entry->imageSize[1]);
else if (strcasecmp(ext, ".png")==0)
ret = assetsLoadPngFromMemory(data_buf, filesize, entry->buffer, entry->imageMode, entry->imageSize[0], entry->imageSize[1]);
else
ret = false; // File extension not recognized.
}
if (ret) entry->initialized = true;
else assetsClearEntry(entry);
free(data_buf);
return ret;
}
void assetsGetData(AssetId id, assetsDataEntry **out) {
if (out) *out = NULL;
if (id < 0 || id >= AssetId_Max) return; if (id < 0 || id >= AssetId_Max) return;
u32 pos = g_assetsDataList[id][1].initialized ? 1 : 0; assetsDataEntry *entry = &g_assetsDataList[id];
assetsDataEntry *entry = &g_assetsDataList[id][pos];
if (entry->initialized) *out = entry; if (buffer) *buffer = entry->buffer;
if (size) *size = entry->size;
} }
u8 *assetsGetDataBuffer(AssetId id) { u8 *assetsGetDataBuffer(AssetId id) {
assetsDataEntry *entry = NULL; u8 *buffer = NULL;
assetsGetData(id, &entry); assetsGetData(id, &buffer, NULL);
return entry ? entry->buffer : NULL; return buffer;
} }

View File

@ -17,28 +17,12 @@ typedef enum {
AssetId_wifi3_icon, AssetId_wifi3_icon,
AssetId_eth_icon, AssetId_eth_icon,
AssetId_eth_none_icon, AssetId_eth_none_icon,
AssetId_background_image,
AssetId_Max, AssetId_Max
} AssetId; } AssetId;
typedef struct {
bool initialized;
u8 *buffer;
size_t size;
ImageMode imageMode;
size_t pixSize;
size_t imageSize[2];
char path[PATH_MAX];
} assetsDataEntry;
Result assetsInit(void); Result assetsInit(void);
void assetsExit(void); void assetsExit(void);
void assetsClearTheme(void); void assetsGetData(AssetId id, u8 **buffer, size_t *size);
bool assetsPhysfsReadFile(const char *path, u8 **data_buf, size_t *filesize, bool nul_term);
bool assetsLoadData(AssetId id, const char *path, int *imageSize);
void assetsGetData(AssetId id, assetsDataEntry **out);
u8 *assetsGetDataBuffer(AssetId id); u8 *assetsGetDataBuffer(AssetId id);
bool assetsLoadJpgFromMemory(u8 *indata, size_t indata_size, u8 *outdata, ImageMode imageMode, size_t width, size_t height);

View File

@ -21,11 +21,8 @@
#include <stdint.h> #include <stdint.h>
typedef uint8_t u8; typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32; typedef uint32_t u32;
typedef uint64_t u64; typedef uint64_t u64;
typedef int8_t s8;
typedef int32_t s32;
typedef u32 Result; typedef u32 Result;
typedef void (*workerThreadFunc)(void *); typedef void (*workerThreadFunc)(void *);
@ -48,49 +45,6 @@ typedef union {
}; };
} color_t; } color_t;
typedef enum
{
ThemeLayoutId_Logo,
ThemeLayoutId_HbmenuVersion,
ThemeLayoutId_LoaderInfo,
ThemeLayoutId_AttentionText,
ThemeLayoutId_LogInfo,
ThemeLayoutId_InfoMsg,
ThemeLayoutId_MenuPath,
ThemeLayoutId_MenuTypeMsg,
ThemeLayoutId_MsgBoxSeparator,
ThemeLayoutId_MsgBoxBottomText,
ThemeLayoutId_BackgroundImage,
ThemeLayoutId_BackWave,
ThemeLayoutId_MiddleWave,
ThemeLayoutId_FrontWave,
ThemeLayoutId_ButtonA,
ThemeLayoutId_ButtonAText,
ThemeLayoutId_ButtonB,
ThemeLayoutId_ButtonBText,
ThemeLayoutId_ButtonY,
ThemeLayoutId_ButtonYText,
ThemeLayoutId_ButtonM,
ThemeLayoutId_ButtonMText,
ThemeLayoutId_ButtonX,
ThemeLayoutId_ButtonXText,
ThemeLayoutId_NetworkIcon,
ThemeLayoutId_BatteryCharge,
ThemeLayoutId_BatteryIcon,
ThemeLayoutId_ChargingIcon,
ThemeLayoutId_Status,
ThemeLayoutId_Temperature,
ThemeLayoutId_MenuList,
ThemeLayoutId_MenuListTiles,
ThemeLayoutId_MenuListIcon,
ThemeLayoutId_MenuListName,
ThemeLayoutId_MenuActiveEntryIcon,
ThemeLayoutId_MenuActiveEntryName,
ThemeLayoutId_MenuActiveEntryAuthor,
ThemeLayoutId_MenuActiveEntryVersion,
ThemeLayoutId_Total,
} ThemeLayoutId;
// when building for pc we need to include these separately // when building for pc we need to include these separately
#ifndef __SWITCH__ #ifndef __SWITCH__
#include "switch/nro.h" #include "switch/nro.h"
@ -111,7 +65,6 @@ typedef enum
#include "power.h" #include "power.h"
#include "netloader.h" #include "netloader.h"
#include "netstatus.h" #include "netstatus.h"
#include "thermalstatus.h"
#include "status.h" #include "status.h"
void menuStartupPath(void); void menuStartupPath(void);
@ -207,8 +160,6 @@ static inline color_t FetchPixelColor(uint32_t x, uint32_t y)
void DrawPixel(uint32_t x, uint32_t y, color_t clr); void DrawPixel(uint32_t x, uint32_t y, color_t clr);
void DrawText(u32 font, uint32_t x, uint32_t y, color_t clr, const char* text); void DrawText(u32 font, uint32_t x, uint32_t y, color_t clr, const char* text);
void DrawTextFromLayout(ThemeLayoutId id, color_t clr, const char* text);
void DrawTextFromLayoutRelative(ThemeLayoutId id, int base_x, int base_y, int *inPos, int *outPos, color_t clr, const char* text, const char align);
void DrawTextTruncate(u32 font, uint32_t x, uint32_t y, color_t clr, const char* text, uint32_t max_width, const char* end_text); void DrawTextTruncate(u32 font, uint32_t x, uint32_t y, color_t clr, const char* text, uint32_t max_width, const char* end_text);
void GetTextDimensions(u32 font, const char* text, uint32_t* width_out, uint32_t* height_out); void GetTextDimensions(u32 font, const char* text, uint32_t* width_out, uint32_t* height_out);
uint32_t GetTextXCoordinate(u32 font, uint32_t rX, const char* text, const char align); uint32_t GetTextXCoordinate(u32 font, uint32_t rX, const char* text, const char align);

View File

@ -9,20 +9,16 @@
#define FONT_FACES_MAX 2 #define FONT_FACES_MAX 2
#endif #endif
#ifdef __SWITCH__
static bool s_plinited;
#endif
static FT_Error s_font_libret=1, s_font_facesret[FONT_FACES_MAX]; static FT_Error s_font_libret=1, s_font_facesret[FONT_FACES_MAX];
static FT_Library s_font_library; static FT_Library s_font_library;
static FT_Face s_font_faces[FONT_FACES_MAX]; static FT_Face s_font_faces[FONT_FACES_MAX];
static FT_Face s_font_lastusedface; static FT_Face s_font_lastusedface;
static s32 s_font_faces_total = 0; static size_t s_font_faces_total = 0;
static bool FontSetType(u32 font) static bool FontSetType(u32 font)
{ {
s32 i=0; u32 i=0;
u32 scale=0; u32 scale=0;
FT_Error ret=0; FT_Error ret=0;
@ -84,12 +80,12 @@ static bool FontSetType(u32 font)
static inline bool FontLoadGlyph(glyph_t* glyph, u32 font, uint32_t codepoint) static inline bool FontLoadGlyph(glyph_t* glyph, u32 font, uint32_t codepoint)
{ {
FT_Face face=0; FT_Face face;
FT_Error ret=0; FT_Error ret=0;
FT_GlyphSlot slot; FT_GlyphSlot slot;
FT_UInt glyph_index; FT_UInt glyph_index;
FT_Bitmap* bitmap; FT_Bitmap* bitmap;
s32 i=0; u32 i=0;
//__builtin_printf("LoadGlyph %u\n", (unsigned int)codepoint); //__builtin_printf("LoadGlyph %u\n", (unsigned int)codepoint);
/*const ffnt_page_t* page = FontGetPage(font, codepoint >> 8); /*const ffnt_page_t* page = FontGetPage(font, codepoint >> 8);
@ -280,38 +276,6 @@ void DrawText(u32 font, uint32_t x, uint32_t y, color_t clr, const char* text)
DrawText_(font, x, y, clr, text, 0, NULL); DrawText_(font, x, y, clr, text, 0, NULL);
} }
void DrawTextFromLayout(ThemeLayoutId id, color_t clr, const char* text)
{
ThemeLayoutObject *obj = &themeCurrent.layoutObjects[id];
if (!obj->visible) return;
DrawText(obj->font, obj->posStart[0], obj->posStart[1], clr, text);
}
void DrawTextFromLayoutRelative(ThemeLayoutId id, int base_x, int base_y, int *inPos, int *outPos, color_t clr, const char* text, const char align)
{
ThemeLayoutObject *obj = &themeCurrent.layoutObjects[id];
base_x = obj->posType ? base_x + inPos[0] : inPos[0];
base_y = obj->posType ? base_y + inPos[1] : inPos[1];
base_x = GetTextXCoordinate(obj->font, base_x, text, align);
if (outPos) {
outPos[0] = base_x;
outPos[1] = base_y;
}
obj->posFinal[0] = base_x;
obj->posFinal[1] = base_y;
if (!obj->visible) return;
GetTextDimensions(obj->font, text, &obj->textSize[0], &obj->textSize[1]);
DrawText(obj->font, base_x, base_y, clr, text);
}
void DrawTextTruncate(u32 font, uint32_t x, uint32_t y, color_t clr, const char* text, uint32_t max_width, const char* end_text) void DrawTextTruncate(u32 font, uint32_t x, uint32_t y, color_t clr, const char* text, uint32_t max_width, const char* end_text)
{ {
DrawText_(font, x, y, clr, text, max_width, end_text); DrawText_(font, x, y, clr, text, max_width, end_text);
@ -356,7 +320,7 @@ void GetTextDimensions(u32 font, const char* text, uint32_t* width_out, uint32_t
bool fontInitialize(void) bool fontInitialize(void)
{ {
FT_Error ret=0; FT_Error ret=0;
s32 i; u32 i;
for (i=0; i<FONT_FACES_MAX; i++) s_font_facesret[i] = 1; for (i=0; i<FONT_FACES_MAX; i++) s_font_facesret[i] = 1;
@ -368,11 +332,7 @@ bool fontInitialize(void)
PlFontData fonts[PlSharedFontType_Total]; PlFontData fonts[PlSharedFontType_Total];
Result rc=0; Result rc=0;
rc = plInitialize(PlServiceType_User);
if (R_SUCCEEDED(rc)) {
s_plinited = true;
rc = plGetSharedFont(textGetLanguageCode(), fonts, FONT_FACES_MAX, &s_font_faces_total); rc = plGetSharedFont(textGetLanguageCode(), fonts, FONT_FACES_MAX, &s_font_faces_total);
}
if (R_FAILED(rc)) return false; if (R_FAILED(rc)) return false;
for (i=0; i<s_font_faces_total; i++) { for (i=0; i<s_font_faces_total; i++) {
@ -412,16 +372,12 @@ bool fontInitialize(void)
void fontExit() void fontExit()
{ {
s32 i=0; u32 i=0;
for (i=0; i<s_font_faces_total; i++) for (i=0; i<s_font_faces_total; i++)
if (s_font_facesret[i]==0) FT_Done_Face(s_font_faces[i]); if (s_font_facesret[i]==0) FT_Done_Face(s_font_faces[i]);
if (s_font_libret==0) FT_Done_FreeType(s_font_library); if (s_font_libret==0) FT_Done_FreeType(s_font_library);
#ifdef __SWITCH__
if (s_plinited) plExit();
#endif
} }
/*Automatically gives you the desired x-coordinate /*Automatically gives you the desired x-coordinate

View File

@ -7,12 +7,12 @@
#define STR_DE(_str) [SetLanguage_DE] = _str #define STR_DE(_str) [SetLanguage_DE] = _str
#define STR_IT(_str) [SetLanguage_IT] = _str #define STR_IT(_str) [SetLanguage_IT] = _str
#define STR_ES(_str) [SetLanguage_ES] = _str, [SetLanguage_ES419] = _str #define STR_ES(_str) [SetLanguage_ES] = _str, [SetLanguage_ES419] = _str
#define STR_ZH_HANS(_str) [SetLanguage_ZHCN] = _str, [SetLanguage_ZHHANS] = _str #define STR_ZH(_str) [SetLanguage_ZHCN] = _str
#define STR_KO(_str) [SetLanguage_KO] = _str #define STR_KO(_str) [SetLanguage_KO] = _str
#define STR_NL(_str) [SetLanguage_NL] = _str #define STR_NL(_str) [SetLanguage_NL] = _str
#define STR_PT(_str) [SetLanguage_PT] = _str #define STR_PT(_str) [SetLanguage_PT] = _str
#define STR_RU(_str) [SetLanguage_RU] = _str #define STR_RU(_str) [SetLanguage_RU] = _str
#define STR_ZH_HANT(_str) [SetLanguage_ZHTW] = _str, [SetLanguage_ZHHANT] = _str #define STR_TW(_str) [SetLanguage_ZHTW] = _str
#else #else
#define STR_JP(_str) [0] = _str #define STR_JP(_str) [0] = _str
#define STR_EN(_str) [1] = _str #define STR_EN(_str) [1] = _str
@ -20,15 +20,15 @@
#define STR_DE(_str) [3] = _str #define STR_DE(_str) [3] = _str
#define STR_IT(_str) [4] = _str #define STR_IT(_str) [4] = _str
#define STR_ES(_str) [5] = _str #define STR_ES(_str) [5] = _str
#define STR_ZH_HANS(_str) [6] = _str #define STR_ZH(_str) [6] = _str
#define STR_KO(_str) [7] = _str #define STR_KO(_str) [7] = _str
#define STR_NL(_str) [8] = _str #define STR_NL(_str) [8] = _str
#define STR_PT(_str) [9] = _str #define STR_PT(_str) [9] = _str
#define STR_RU(_str) [10] = _str #define STR_RU(_str) [10] = _str
#define STR_ZH_HANT(_str) [11] = _str #define STR_TW(_str) [11] = _str
#endif #endif
const char* const g_strings[StrId_Max][17] = const char* const g_strings[StrId_Max][16] =
{ {
[StrId_Loading] = [StrId_Loading] =
{ {
@ -42,16 +42,14 @@ const char* const g_strings[StrId_Max][17] =
STR_NL("Laden…"), STR_NL("Laden…"),
STR_KO("로딩중…"), STR_KO("로딩중…"),
STR_RU("загрузка…"), STR_RU("загрузка…"),
STR_ZH_HANS("加载中…"), STR_ZH("加载中…"),
STR_ZH_HANT("中…"), STR_TW("載中…"),
}, },
[StrId_AppletMode] = [StrId_AppletMode] =
{ {
STR_EN("● Applet Mode ●"), STR_EN("● Applet Mode ●"),
STR_ES("● Modo Applet ●"), STR_ES("● Modo Applet ●"),
STR_FR("● Mode Applet ●"),
STR_ZH_HANS("● 小程序模式 ●"),
}, },
[StrId_Directory] = [StrId_Directory] =
@ -66,8 +64,8 @@ const char* const g_strings[StrId_Max][17] =
STR_NL("Map"), STR_NL("Map"),
STR_KO("디렉토리"), STR_KO("디렉토리"),
STR_RU("каталог"), STR_RU("каталог"),
STR_ZH_HANS("目录"), STR_ZH("目录"),
STR_ZH_HANT("資料夾"), STR_TW("資料夾"),
}, },
/*[StrId_DefaultLongTitle] = /*[StrId_DefaultLongTitle] =
@ -82,8 +80,8 @@ const char* const g_strings[StrId_Max][17] =
STR_NL("Homebrew toepassing"), STR_NL("Homebrew toepassing"),
STR_KO("홈브류 애플리케이션"), STR_KO("홈브류 애플리케이션"),
STR_RU("приложение хомебреw"), STR_RU("приложение хомебреw"),
STR_ZH_HANS("自制应用程序"), STR_ZH("自制应用程序"),
STR_ZH_HANT("自製程式"), STR_TW("自製程式"),
},*/ },*/
[StrId_DefaultPublisher] = [StrId_DefaultPublisher] =
@ -98,8 +96,8 @@ const char* const g_strings[StrId_Max][17] =
STR_NL("Auteur onbekend"), STR_NL("Auteur onbekend"),
STR_KO("알 수 없는 개발자"), STR_KO("알 수 없는 개발자"),
STR_RU("неизвестный автор"), STR_RU("неизвестный автор"),
STR_ZH_HANS("未知作者"), STR_ZH("未知作者"),
STR_ZH_HANT("作者未知"), STR_TW("作者不詳"),
}, },
[StrId_IOError] = [StrId_IOError] =
@ -108,14 +106,14 @@ const char* const g_strings[StrId_Max][17] =
STR_ES("Error de E/S"), STR_ES("Error de E/S"),
STR_DE("I/O-Fehler"), STR_DE("I/O-Fehler"),
STR_FR("Erreur d'E/S"), STR_FR("Erreur d'E/S"),
STR_IT("Errore I/O"), STR_IT("Errore di I/O"),
STR_JP("入出力エラー"), STR_JP("入出力エラー"),
STR_PT("Erro de E/S"), STR_PT("Erro de E/S"),
STR_NL("I/O Fout"), STR_NL("I/O Fout"),
STR_KO("입출력 오류"), STR_KO("입출력 오류"),
STR_RU("I/O-ошибка"), STR_RU("I/O-ошибка"),
STR_ZH_HANS("读写出错"), STR_ZH("读写出错"),
STR_ZH_HANT("取存錯誤"), STR_TW("讀寫錯誤"),
}, },
[StrId_CouldNotOpenFile] = [StrId_CouldNotOpenFile] =
@ -130,15 +128,8 @@ const char* const g_strings[StrId_Max][17] =
STR_NL("Kan bestand niet openen:\n%s"), STR_NL("Kan bestand niet openen:\n%s"),
STR_KO("파일을 열 수 없습니다:\n%s"), STR_KO("파일을 열 수 없습니다:\n%s"),
STR_RU("Не могу открыть файл:\n%s"), STR_RU("Не могу открыть файл:\n%s"),
STR_ZH_HANS("无法打开文件:\n%s"), STR_ZH("无法打开文件:\n%s"),
STR_ZH_HANT("無法開啟檔案:\n%s"), STR_TW("開啓檔案失敗:\n%s"),
},
[StrId_NroNotFound] =
{
STR_EN("Could not find executable: %s"),
STR_FR("Impossible trouver l'exécutable : %s"),
STR_ZH_HANS("找不到可执行文件"),
}, },
[StrId_NoAppsFound_Title] = [StrId_NoAppsFound_Title] =
@ -153,8 +144,8 @@ const char* const g_strings[StrId_Max][17] =
STR_NL("Geen toepassingen gevonden"), STR_NL("Geen toepassingen gevonden"),
STR_KO("애플리케이션을 찾을 수 없습니다"), STR_KO("애플리케이션을 찾을 수 없습니다"),
STR_RU("приложение не найдено"), STR_RU("приложение не найдено"),
STR_ZH_HANS("找不到可执行的自制程序"), STR_ZH("找不到可执行的自制程序"),
STR_ZH_HANT("沒有可執行的自製程式"), STR_TW("未能找到可執行的自製程式"),
}, },
[StrId_NoAppsFound_Msg] = [StrId_NoAppsFound_Msg] =
@ -214,15 +205,15 @@ const char* const g_strings[StrId_Max][17] =
"Убедитесь, что на карте SD есть каталог с\n" "Убедитесь, что на карте SD есть каталог с\n"
"названием switch и она содержит приложения." "названием switch и она содержит приложения."
), ),
STR_ZH_HANS( STR_ZH(
"找不到任何自制程序(nro)\n" "内存卡找不到任何可执行的应用程序\n"
"在SD卡根目录建立“switch”文件夹\n" "请在内存卡的根目录建立「switch」子目录\n"
"将自制程序(nro)放在其中" "存放自制应用软件至该目录"
), ),
STR_ZH_HANT( STR_TW(
"記憶卡內沒有可供執行的應用程式。\n" "記憶體找不到任何可執行的應用程式。\n"
"請在根目錄下建立「switch」資料夾\n" "請在記憶體建立「switch」資料夾\n"
"並將自製軟體複製到switch資料夾內" "然後儲存自製軟體到此處"
), ),
}, },
@ -232,22 +223,16 @@ const char* const g_strings[StrId_Max][17] =
STR_ES("La última aplicación devolvió un error:"), STR_ES("La última aplicación devolvió un error:"),
STR_DE("Die letzte Anwendung erzeugte einen Fehler:"), STR_DE("Die letzte Anwendung erzeugte einen Fehler:"),
STR_FR("La dernière application a retourné une erreur:"), STR_FR("La dernière application a retourné une erreur:"),
STR_IT("L'ultima applicazione ha restituito un errore:"),
STR_JP("直前に実行したアプリでエラーが発生しました:"), STR_JP("直前に実行したアプリでエラーが発生しました:"),
STR_KO("최근 애플리케이션에서 오류가 발생했습니다:"), STR_KO("최근 애플리케이션에서 오류가 발생했습니다:"),
STR_ZH_HANS("程序运行后出现错误:"), STR_TW("程式執行時發生錯誤:"),
STR_ZH_HANT("程式執行後出現錯誤:"),
}, },
[StrId_AppLaunchError] = [StrId_AppLaunchError] =
{ {
STR_EN("Failed to launch the application:"), STR_EN("Failed to launch the application:"),
STR_DE("Konnte die Anwendung nicht starten:"), STR_DE("Konnte die Anwendung nicht starten:"),
STR_FR("Erreur au lancement de l'application:"), STR_FR("Erreur au lancement de l'application"),
STR_IT("Errore nell'avvio dell'applicazione:"),
STR_ES("No se ha podido iniciar la aplicación:"),
STR_ZH_HANS("运行程序时发生错误:"),
STR_ZH_HANT("執行程式時發生錯誤:"),
}, },
[StrId_AppInfo_Author] = [StrId_AppInfo_Author] =
@ -262,8 +247,8 @@ const char* const g_strings[StrId_Max][17] =
STR_NL("Auteur"), STR_NL("Auteur"),
STR_KO("개발자"), STR_KO("개발자"),
STR_RU("автор"), STR_RU("автор"),
STR_ZH_HANS("作者"), STR_ZH("作者"),
STR_ZH_HANT("作者"), STR_TW("作者"),
}, },
[StrId_AppInfo_Version] = [StrId_AppInfo_Version] =
@ -278,8 +263,8 @@ const char* const g_strings[StrId_Max][17] =
STR_NL("Versie"), STR_NL("Versie"),
STR_KO("버전"), STR_KO("버전"),
STR_RU("Версия"), STR_RU("Версия"),
STR_ZH_HANS(""), STR_ZH(""),
STR_ZH_HANT(""), STR_TW(""),
}, },
[StrId_Actions_Launch] = [StrId_Actions_Launch] =
@ -287,15 +272,15 @@ const char* const g_strings[StrId_Max][17] =
STR_EN("Launch"), STR_EN("Launch"),
STR_ES("Lanzamiento"), STR_ES("Lanzamiento"),
STR_DE("Starten"), STR_DE("Starten"),
STR_FR("Lancer"), STR_FR("Lancement"),
STR_IT("Avvia"), STR_IT("Lanciare"),
STR_JP("起動"), STR_JP("起動"),
STR_PT("Lançamento"), STR_PT("Lançamento"),
STR_NL("Lancering"), STR_NL("Lancering"),
STR_KO("실행"), STR_KO("실행"),
STR_RU("запуск"), STR_RU("запуск"),
STR_ZH_HANS("发射"), STR_ZH("发射"),
STR_ZH_HANT("啟動"), STR_TW("啟動"),
}, },
[StrId_Actions_Open] = [StrId_Actions_Open] =
@ -304,14 +289,14 @@ const char* const g_strings[StrId_Max][17] =
STR_ES("Abrir"), STR_ES("Abrir"),
STR_DE("Öffnen"), STR_DE("Öffnen"),
STR_FR("Ouvrir"), STR_FR("Ouvrir"),
STR_IT("Apri"), STR_IT("Aprire"),
STR_JP("開く"), STR_JP("開く"),
STR_PT("Abrir"), STR_PT("Abrir"),
STR_NL("Open"), STR_NL("Open"),
STR_KO("열기"), STR_KO("열기"),
STR_RU("открыто"), STR_RU("открыто"),
STR_ZH_HANS("打开"), STR_ZH("打开"),
STR_ZH_HANT("開啟"), STR_TW("開啟"),
}, },
[StrId_Actions_Back] = [StrId_Actions_Back] =
@ -326,8 +311,8 @@ const char* const g_strings[StrId_Max][17] =
STR_NL("Terug"), STR_NL("Terug"),
STR_KO("뒤로 가기"), STR_KO("뒤로 가기"),
STR_RU("возвращаться"), STR_RU("возвращаться"),
STR_ZH_HANS(""), STR_ZH(""),
STR_ZH_HANT(""), STR_TW(""),
}, },
[StrId_MsgBox_OK] = [StrId_MsgBox_OK] =
@ -335,12 +320,10 @@ const char* const g_strings[StrId_Max][17] =
STR_EN("OK"), STR_EN("OK"),
STR_DE("OK"), STR_DE("OK"),
STR_FR("OK"), STR_FR("OK"),
STR_IT("OK"),
STR_ES("Aceptar"), STR_ES("Aceptar"),
STR_JP("了解"), STR_JP("了解"),
STR_KO("확인"), STR_KO("확인"),
STR_ZH_HANS("确认"), STR_TW("確認"),
STR_ZH_HANT("確認"),
}, },
[StrId_Actions_Apply] = [StrId_Actions_Apply] =
@ -349,55 +332,43 @@ const char* const g_strings[StrId_Max][17] =
STR_FR("Appliquer"), STR_FR("Appliquer"),
STR_DE("Anwenden"), STR_DE("Anwenden"),
STR_ES("Aplicar"), STR_ES("Aplicar"),
STR_IT("Applica"),
STR_JP("適用"), STR_JP("適用"),
STR_KO("적용"), STR_KO("적용"),
STR_ZH_HANS("应用"), STR_TW("应用"),
STR_ZH_HANT("套用"),
}, },
[StrId_Actions_Star] = [StrId_Actions_Star] =
{ {
STR_EN("Star"), STR_EN("Star"),
STR_ES("Agregar a favoritos"), STR_ES("Agregar a favoritos"),
STR_IT("Aggiungi ai preferiti"),
STR_FR("Ajouter aux favoris"),
STR_ZH_HANS("收藏"),
}, },
[StrId_Actions_Unstar] = [StrId_Actions_Unstar] =
{ {
STR_EN("Unstar"), STR_EN("Unstar"),
STR_ES("Borrar de favoritos"), STR_ES("Borrar de favoritos"),
STR_IT("Rimuovi dai preferiti"),
STR_FR("Retirer des favoris"),
STR_ZH_HANS("取消收藏"),
}, },
[StrId_ThemeMenu] = [StrId_ThemeMenu] =
{ {
STR_EN("Theme Menu"), STR_EN("Theme Menu"),
STR_FR("Menu thèmes"), STR_FR("Menu Thème"),
STR_DE("Theme Menü"), STR_DE("Theme Menü"),
STR_ES("Menú temático"), STR_ES("Menú temático"),
STR_IT("Tema Menu"),
STR_JP("テーマメニュー"), STR_JP("テーマメニュー"),
STR_KO("테마 메뉴"), STR_KO("테마 메뉴"),
STR_ZH_HANS("主题菜单"), STR_TW("主题菜单"),
STR_ZH_HANT("主題選單"),
}, },
[StrId_ThemeNotApplied] = [StrId_ThemeNotApplied] =
{ {
STR_EN("Theme cannot be applied because an error occurred."), STR_EN("Theme cannot be applied because an error occurred."),
STR_DE("Das Theme konnte nicht geladen werden, da ein Fehler aufgetreten ist."), STR_EN("Das Theme konnte nicht geladen werden, da ein Fehler aufgetreten ist."),
STR_FR("Le thème ne peut pas être appliqué car une erreur est survenue."), STR_FR("Le thème ne peut pas être appliqué car une erreur est survenue."),
STR_ES("El tema no se pudo aplicar porque se ha producido un error."), STR_ES("El tema no se pudo aplicar porque se ha producido un error."),
STR_IT("Il tema non è stato applicato a causa di un errore."),
STR_JP("エラーが発生したため、テーマを適用できませんでした。"), STR_JP("エラーが発生したため、テーマを適用できませんでした。"),
STR_KO("오류가 발생 했기 때문에 테마를 적용할 수 없습니다."), STR_KO("오류가 발생 했기 때문에 테마를 적용할 수 없습니다."),
STR_ZH_HANS("由于发生错误, 无法应用主题。"), STR_TW("由于发生错误, 无法应用主题。"),
STR_ZH_HANT("出現錯誤,無法套用主題。"),
}, },
[StrId_DefaultThemeName] = [StrId_DefaultThemeName] =
@ -405,10 +376,6 @@ const char* const g_strings[StrId_Max][17] =
STR_EN("Default Theme"), STR_EN("Default Theme"),
STR_FR("Thème par défaut"), STR_FR("Thème par défaut"),
STR_DE("Standard Theme"), STR_DE("Standard Theme"),
STR_IT("Tema di default"),
STR_ES("Tema por defecto"),
STR_ZH_HANS("默认主题"),
STR_ZH_HANT("預設主題"),
}, },
/*[StrId_Reboot] = /*[StrId_Reboot] =
@ -474,13 +441,13 @@ const char* const g_strings[StrId_Max][17] =
" \xEE\x80\x80 Перезагрузите\n" " \xEE\x80\x80 Перезагрузите\n"
" \xEE\x80\x81 Отмена" " \xEE\x80\x81 Отмена"
), ),
STR_ZH_HANS( STR_ZH(
"无法返回至主机的 \xEE\x81\xB3HOME 菜单。\n" "无法返回至主机的 \xEE\x81\xB3HOME 菜单。\n"
"您需要重新启动您的 3DS 设备。\n\n" "您需要重新启动您的 3DS 设备。\n\n"
" \xEE\x80\x80 重启设备\n" " \xEE\x80\x80 重启设备\n"
" \xEE\x80\x81 取消操作" " \xEE\x80\x81 取消操作"
), ),
STR_ZH_HANT( STR_TW(
"無法返回至主機的 \xEE\x81\xB3HOME 選單。\n" "無法返回至主機的 \xEE\x81\xB3HOME 選單。\n"
"您需要重新啓動您的 3DS 設備。\n\n" "您需要重新啓動您的 3DS 設備。\n\n"
" \xEE\x80\x80 重啓設備\n" " \xEE\x80\x80 重啓設備\n"
@ -550,13 +517,13 @@ const char* const g_strings[StrId_Max][17] =
" \xEE\x80\x81 Отмена\n" " \xEE\x80\x81 Отмена\n"
" \xEE\x80\x82 Перезагрузите" " \xEE\x80\x82 Перезагрузите"
), ),
STR_ZH_HANS( STR_ZH(
"您即将返回到主機的 \xEE\x81\xB3HOME 菜单。\n\n" "您即将返回到主機的 \xEE\x81\xB3HOME 菜单。\n\n"
" \xEE\x80\x80 确认返回\n" " \xEE\x80\x80 确认返回\n"
" \xEE\x80\x81 取消操作\n" " \xEE\x80\x81 取消操作\n"
" \xEE\x80\x82 重启设备" " \xEE\x80\x82 重启设备"
), ),
STR_ZH_HANT( STR_TW(
"您即將返回到主機的 \xEE\x81\xB3HOME 選單。\n\n" "您即將返回到主機的 \xEE\x81\xB3HOME 選單。\n\n"
" \xEE\x80\x80 確認返回\n" " \xEE\x80\x80 確認返回\n"
" \xEE\x80\x81 取消操作\n" " \xEE\x80\x81 取消操作\n"
@ -576,8 +543,8 @@ const char* const g_strings[StrId_Max][17] =
STR_NL("Titel selector"), STR_NL("Titel selector"),
STR_KO("타이틀 선택기"), STR_KO("타이틀 선택기"),
STR_RU("Селектор заголовков"), STR_RU("Селектор заголовков"),
STR_ZH_HANS("应用启动器"), STR_ZH("应用启动器"),
STR_ZH_HANT("自製程式啓動器"), STR_TW("自製程式啓動器"),
}, },
[StrId_ErrorReadingTitleMetadata] = [StrId_ErrorReadingTitleMetadata] =
@ -587,7 +554,7 @@ const char* const g_strings[StrId_Max][17] =
STR_DE("Fehler beim Lesen der Titel-Metadaten.\n%08lX%08lX@%d"), STR_DE("Fehler beim Lesen der Titel-Metadaten.\n%08lX%08lX@%d"),
STR_FR( STR_FR(
"Erreur lors de la lecture des métadonnées\n" "Erreur lors de la lecture des métadonnées\n"
"du titre.\n%08lX%08lX@%d" "de titre.\n%08lX%08lX@%d"
), ),
STR_IT("Errore nella lettura dei metadata dei titoli.\n%08lX%08lX@%d"), STR_IT("Errore nella lettura dei metadata dei titoli.\n%08lX%08lX@%d"),
STR_JP("タイトルメタデータを読み取ることができませんでした。\n%08lX%08lX@%d"), STR_JP("タイトルメタデータを読み取ることができませんでした。\n%08lX%08lX@%d"),
@ -595,8 +562,8 @@ const char* const g_strings[StrId_Max][17] =
STR_NL("Fout bij het lezen van titel metadata.\n%08lX%08lX@%d"), STR_NL("Fout bij het lezen van titel metadata.\n%08lX%08lX@%d"),
STR_KO("타이틀 메타데이터를 읽는데 실패하였습니다.\n%08lX%08lX@%d"), STR_KO("타이틀 메타데이터를 읽는데 실패하였습니다.\n%08lX%08lX@%d"),
STR_RU("Ошибка чтения метаданных заголовка\n.%08lX%08lX@%d"), STR_RU("Ошибка чтения метаданных заголовка\n.%08lX%08lX@%d"),
STR_ZH_HANS("读取软件相关信息时发生错误:\n%08lX%08lX@%d"), STR_ZH("读取软件相关信息时发生错误:\n%08lX%08lX@%d"),
STR_ZH_HANT("讀取軟體相關資訊時發生錯誤:\n%08lX%08lX@%d"), STR_TW("讀取軟體相關數據時發生錯誤:\n%08lX%08lX@%d"),
}, },
[StrId_NoTitlesFound] = [StrId_NoTitlesFound] =
@ -611,8 +578,8 @@ const char* const g_strings[StrId_Max][17] =
STR_NL("Geen titels gevonden."), STR_NL("Geen titels gevonden."),
STR_KO("타이틀을 찾을 수 없습니다."), STR_KO("타이틀을 찾을 수 없습니다."),
STR_RU("Заголовки не обнаружены"), STR_RU("Заголовки не обнаружены"),
STR_ZH_HANS("主机内找不到任何软件。"), STR_ZH("主机内找不到任何软件。"),
STR_ZH_HANT("主機内找不到任何軟體。"), STR_TW("主機内找不到任何軟體。"),
}, },
[StrId_SelectTitle] = [StrId_SelectTitle] =
@ -667,12 +634,12 @@ const char* const g_strings[StrId_Max][17] =
" \xEE\x80\x80 Выберите\n" " \xEE\x80\x80 Выберите\n"
" \xEE\x80\x81 Отмена" " \xEE\x80\x81 Отмена"
), ),
STR_ZH_HANS( STR_ZH(
"请选择一个目标软件。\n\n" "请选择一个目标软件。\n\n"
" \xEE\x80\x80 确认\n" " \xEE\x80\x80 确认\n"
" \xEE\x80\x81 取消" " \xEE\x80\x81 取消"
), ),
STR_ZH_HANT( STR_TW(
"請選擇一個目標軟體。\n\n" "請選擇一個目標軟體。\n\n"
" \xEE\x80\x80 確認\n" " \xEE\x80\x80 確認\n"
" \xEE\x80\x81 取消" " \xEE\x80\x81 取消"
@ -731,14 +698,14 @@ const char* const g_strings[StrId_Max][17] =
"приложений под целевыми заголовками.\n" "приложений под целевыми заголовками.\n"
"Пожалуйста, используйте другой эксплойт." "Пожалуйста, используйте другой эксплойт."
), ),
STR_ZH_HANS( STR_ZH(
"您所利用漏洞启动的「自制软件启动器」,\n" "您所利用漏洞启动的「自制软件启动器」,\n"
"无法在当前选中的软件中启动自制软件。\n" "无法在当前选中的软件中启动自制软件。\n"
"请使用其它的漏洞来启动「自制软件启动器」。" "请使用其它的漏洞来启动「自制软件启动器」。"
), ),
STR_ZH_HANT( STR_TW(
"您所利用漏洞開啓的「自製軟體啓動器」\n" "您所利用漏洞開啓的「自製軟體啓動器」\n"
"無法在當前選中的軟體啓動自製軟\n" "無法在當前選中的軟體啓動自製軟\n"
"請利用其它漏洞來啓動「自製軟體啓動器」。" "請利用其它漏洞來啓動「自製軟體啓動器」。"
), ),
}, },
@ -785,11 +752,11 @@ const char* const g_strings[StrId_Max][17] =
"Для приложения требуется зависимость,\n" "Для приложения требуется зависимость,\n"
"которая не установлена." "которая не установлена."
), ),
STR_ZH_HANS( STR_ZH(
"主机找不到该应用程序\n" "主机找不到该应用程序\n"
"所需求的软件。" "所需求的软件。"
), ),
STR_ZH_HANT( STR_TW(
"主機找不到該應用程式\n" "主機找不到該應用程式\n"
"所需求的軟體。" "所需求的軟體。"
), ),
@ -800,15 +767,15 @@ const char* const g_strings[StrId_Max][17] =
STR_EN("NetLoader"), STR_EN("NetLoader"),
STR_ES("Cargador de programas"), STR_ES("Cargador de programas"),
STR_DE("Netzwerk-Loader"), STR_DE("Netzwerk-Loader"),
STR_FR("NetLoader"), STR_FR("Chargeur de programme"),
STR_IT("Caricamento programmi"), STR_IT("Caricamento programmi"),
STR_JP("ネットローダ"), STR_JP("ネットローダ"),
STR_PT("Carregador de programas"), STR_PT("Carregador de programas"),
STR_NL("netwerk lader"), STR_NL("netwerk lader"),
STR_KO("네트워크 로더"), STR_KO("네트워크 로더"),
STR_RU("Загрузчик"), STR_RU("Загрузчик"),
STR_ZH_HANS("网络执行模块"), STR_ZH("网络执行模块"),
STR_ZH_HANT("網路執行模組"), STR_TW("網路執行模組"),
}, },
[StrId_NetLoaderUnavailable] = [StrId_NetLoaderUnavailable] =
@ -816,15 +783,15 @@ const char* const g_strings[StrId_Max][17] =
STR_EN("The NetLoader is currently unavailable."), STR_EN("The NetLoader is currently unavailable."),
STR_ES("El cargador de programas no está disponible."), STR_ES("El cargador de programas no está disponible."),
STR_DE("Der Netzwerk-Loader ist zur Zeit nicht verfügbar."), STR_DE("Der Netzwerk-Loader ist zur Zeit nicht verfügbar."),
STR_FR("Le programme nxlink est indisponible."), STR_FR("Le chargeur de programme nxlink est indisponible."),
STR_IT("Il caricamento programmi nxlink non è disponibile."), STR_IT("Il caricamento programmi nxlink non è disponibile."),
STR_JP("nxlinkネットローダは現在利用できません。"), STR_JP("nxlinkネットローダは現在利用できません。"),
STR_PT("O carregador de programas está de momento indisponível."), STR_PT("O carregador de programas está de momento indisponível."),
STR_NL("De netwerk lader is niet beschikbaar."), STR_NL("De netwerk lader is niet beschikbaar."),
STR_KO("현재 네트워크 로더는 사용이 불가합니다."), STR_KO("현재 네트워크 로더는 사용이 불가합니다."),
STR_RU("Загрузчик в настоящее время недоступен."), STR_RU("Загрузчик в настоящее время недоступен."),
STR_ZH_HANS("无法启动 nxlink 网络执行模块。"), STR_ZH("无法启动 nxlink 网络执行模块。"),
STR_ZH_HANT("無法啓動 nxlink 網路執行模組。"), STR_TW("無法啓動 nxlink 網路執行模組。"),
}, },
[StrId_NetLoaderError] = [StrId_NetLoaderError] =
@ -839,8 +806,8 @@ const char* const g_strings[StrId_Max][17] =
STR_NL("Er is een fout opgetreden\nTechnische details: [%s:%d]"), STR_NL("Er is een fout opgetreden\nTechnische details: [%s:%d]"),
STR_KO("오류가 발생했습니다.\n기술적인 세부사항: [%s:%d]"), STR_KO("오류가 발생했습니다.\n기술적인 세부사항: [%s:%d]"),
STR_RU("Произошла ошибка.\nТехнические подробности: [%s:%d]"), STR_RU("Произошла ошибка.\nТехнические подробности: [%s:%d]"),
STR_ZH_HANS("发生错误。\n详细错误信息:[%s:%d]"), STR_ZH("发生错误。\n详细错误信息:[%s:%d]"),
STR_ZH_HANT("發生錯誤。\n詳細錯誤資訊:[%s:%d]"), STR_TW("發生錯誤。\n詳細錯誤資訊:[%s:%d]"),
}, },
[StrId_NetLoaderOffline] = [StrId_NetLoaderOffline] =
@ -849,11 +816,10 @@ const char* const g_strings[StrId_Max][17] =
STR_DE("Offline, warte auf Netzwerk…"), STR_DE("Offline, warte auf Netzwerk…"),
STR_FR("Hors-ligne, en attente d'une connection..."), STR_FR("Hors-ligne, en attente d'une connection..."),
STR_IT("Disconnesso, in attesa della connessione…"), STR_IT("Disconnesso, in attesa della connessione…"),
STR_ES("Desconectado, esperando a la red..."),
STR_JP("オフラインです。ネットワーク接続を待っています…"), STR_JP("オフラインです。ネットワーク接続を待っています…"),
STR_KO("연결 끊김, 네트워크 기다리는 중…"), STR_KO("연결 끊김, 네트워크 기다리는 중…"),
STR_ZH_HANS("无法连接网络,等待网络连接…"), STR_ZH("无法连接网络,等待网络连接…"),
STR_ZH_HANT("目前已離線,等待網路連線…"), STR_TW("當前離線,等待網路連線…"),
}, },
[StrId_NetLoaderActive] = [StrId_NetLoaderActive] =
@ -898,11 +864,11 @@ const char* const g_strings[StrId_Max][17] =
"Ожидание подключения nxlink…\n" "Ожидание подключения nxlink…\n"
"айпи адрес: %lu.%lu.%lu.%lu, Порт: %d" "айпи адрес: %lu.%lu.%lu.%lu, Порт: %d"
), ),
STR_ZH_HANS( STR_ZH(
"等待 nxlink 连接…\n" "等待 nxlink 连接…\n"
"IP 地址:%lu.%lu.%lu.%lu端口%d" "IP 地址:%lu.%lu.%lu.%lu端口%d"
), ),
STR_ZH_HANT( STR_TW(
"等待 nxlink 連接…\n" "等待 nxlink 連接…\n"
"IP 位址:%lu.%lu.%lu.%lu連接埠%d" "IP 位址:%lu.%lu.%lu.%lu連接埠%d"
), ),
@ -950,13 +916,14 @@ const char* const g_strings[StrId_Max][17] =
"Передача…\n" "Передача…\n"
"%zu из %zu КИБ написано" "%zu из %zu КИБ написано"
), ),
STR_ZH_HANS( STR_ZH(
"正在传输…\n" "正在传输…\n"
"已完成 %zu / %zu KiB" "已完成 %zu / %zu KiB"
), ),
STR_ZH_HANT( STR_TW(
"正在傳輸…\n" "正在傳輸…\n"
"已完成 %zu / %zu KiB" "已完成 %zu / %zu KiB"
), ),
}, },
}; };

View File

@ -11,7 +11,6 @@ typedef enum
StrId_DefaultPublisher, StrId_DefaultPublisher,
StrId_IOError, StrId_IOError,
StrId_CouldNotOpenFile, StrId_CouldNotOpenFile,
StrId_NroNotFound,
StrId_NoAppsFound_Title, StrId_NoAppsFound_Title,
StrId_NoAppsFound_Msg, StrId_NoAppsFound_Msg,
@ -55,5 +54,5 @@ typedef enum
StrId_Max, StrId_Max,
} StrId; } StrId;
extern const char* const g_strings[StrId_Max][17]; extern const char* const g_strings[StrId_Max][16];

View File

@ -1,5 +1,4 @@
#include "common.h" #include "common.h"
#include <physfs.h>
void menuEntryInit(menuEntry_s* me, MenuEntryType type) { void menuEntryInit(menuEntry_s* me, MenuEntryType type) {
memset(me, 0, sizeof(*me)); memset(me, 0, sizeof(*me));
@ -81,13 +80,9 @@ static bool menuEntryLoadEmbeddedIcon(menuEntry_s* me) {
return ok; return ok;
} }
static bool menuEntryLoadExternalIcon(menuEntry_s* me, const char* path, bool data_source) { static bool menuEntryLoadExternalIcon(menuEntry_s* me, const char* path) {
struct stat st; struct stat st;
if (data_source) {
return assetsPhysfsReadFile(path, &me->icon, &me->icon_size, false);
}
if(stat(path, &st)==-1) return false; if(stat(path, &st)==-1) return false;
FILE* f = fopen(path, "rb"); FILE* f = fopen(path, "rb");
@ -111,15 +106,12 @@ static bool menuEntryImportIconGfx(menuEntry_s* me, uint8_t* icon_gfx, uint8_t*
if (icon_gfx == NULL || icon_gfx_small == NULL) return false; if (icon_gfx == NULL || icon_gfx_small == NULL) return false;
ThemeLayoutObject *layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MenuActiveEntryIcon]; tmpsize = 256*256*3;
ThemeLayoutObject *layoutobj2 = &themeCurrent.layoutObjects[ThemeLayoutId_MenuListIcon];
tmpsize = layoutobj->size[0]*layoutobj->size[1]*3;
me->icon_gfx = (uint8_t*)malloc(tmpsize); me->icon_gfx = (uint8_t*)malloc(tmpsize);
if (me->icon_gfx) memcpy(me->icon_gfx, icon_gfx, tmpsize); if (me->icon_gfx) memcpy(me->icon_gfx, icon_gfx, tmpsize);
if (me->icon_gfx) { if (me->icon_gfx) {
tmpsize = layoutobj2->size[0]*layoutobj2->size[1]*3; tmpsize = 140*140*3;
me->icon_gfx_small = (uint8_t*)malloc(tmpsize); me->icon_gfx_small = (uint8_t*)malloc(tmpsize);
if (me->icon_gfx_small) memcpy(me->icon_gfx_small, icon_gfx_small, tmpsize); if (me->icon_gfx_small) memcpy(me->icon_gfx_small, icon_gfx_small, tmpsize);
@ -210,18 +202,18 @@ static bool menuEntryLoadExternalNacp(menuEntry_s* me, const char* path) {
} while (lastc); } while (lastc);
}*/ }*/
bool menuEntryLoad(menuEntry_s* me, const char* name, bool shortcut, bool check_exists) { bool menuEntryLoad(menuEntry_s* me, const char* name, bool shortcut) {
int i=0, tmplen; int i=0, tmplen;
menu_s *menu_fileassoc = menuFileassocGetCurrent(); menu_s *menu_fileassoc = menuFileassocGetCurrent();
menuEntry_s* fileassoc_me = NULL; menuEntry_s* fileassoc_me = NULL;
char *strptr = NULL; char *strptr = NULL;
char tempbuf[PATH_MAX+16]; static char tempbuf[PATH_MAX+1];
//bool isOldAppFolder = false; //bool isOldAppFolder = false;
if (check_exists && !fsobjExists(me->path)) return false; if (!fsobjExists(me->path)) return false;
tempbuf[PATH_MAX] = 0; tempbuf[PATH_MAX] = 0;
strncpy(me->name, name, sizeof(me->name)-1); strcpy(me->name, name);
if (me->type == ENTRY_TYPE_FOLDER) if (me->type == ENTRY_TYPE_FOLDER)
{ {
@ -293,8 +285,9 @@ bool menuEntryLoad(menuEntry_s* me, const char* name, bool shortcut, bool check_
if (me->type == ENTRY_TYPE_FILE) if (me->type == ENTRY_TYPE_FILE)
{ {
strncpy(me->author, textGetString(StrId_DefaultPublisher), sizeof(me->author)-1); //strcpy(me->name, name);//This is already done before both if statements
strncpy(me->version, "1.0.0", sizeof(me->version)-1); strcpy(me->author, textGetString(StrId_DefaultPublisher));
strcpy(me->version, "1.0.0");
//shortcut_s sc; //shortcut_s sc;
@ -331,7 +324,7 @@ bool menuEntryLoad(menuEntry_s* me, const char* name, bool shortcut, bool check_
char* ext = getExtension(tempbuf); char* ext = getExtension(tempbuf);
strcpy(ext, ".jpg"); strcpy(ext, ".jpg");
iconLoaded = menuEntryLoadExternalIcon(me, tempbuf, false); iconLoaded = menuEntryLoadExternalIcon(me, tempbuf);
if (iconLoaded) break; if (iconLoaded) break;
if (isOldAppFolder) if (isOldAppFolder)
@ -339,7 +332,7 @@ bool menuEntryLoad(menuEntry_s* me, const char* name, bool shortcut, bool check_
char* slash = getSlash(tempbuf); char* slash = getSlash(tempbuf);
strcpy(slash, "/icon.jpg"); strcpy(slash, "/icon.jpg");
iconLoaded = menuEntryLoadExternalIcon(me, tempbuf, false); iconLoaded = menuEntryLoadExternalIcon(me, tempbuf);
if (iconLoaded) break; if (iconLoaded) break;
}*/ }*/
@ -412,44 +405,7 @@ bool menuEntryLoad(menuEntry_s* me, const char* name, bool shortcut, bool check_
*author = textGetString(StrId_DefaultPublisher), *author = textGetString(StrId_DefaultPublisher),
*version = "1.0.0"; *version = "1.0.0";
const char* cfg_path = me->path; if (config_read_file(&cfg, me->path)) {
const char* theme_archive_path = NULL;
const char* ext = getExtension(me->path);
bool good_cfg = false;
bool is_archive = false;
#ifdef __SWITCH__
bool is_romfs = false;
if (strcasecmp(ext, ".romfs")==0) {
if (R_FAILED(romfsMountFromFsdev(me->path, 0, "themetmp")))
return false;
is_romfs = true;
cfg_path = "themetmp:/theme.cfg";
theme_archive_path = "themetmp:/";
}
#endif
if (strcasecmp(ext, ".romfs")!=0 && strcasecmp(ext, ".cfg")!=0) {
theme_archive_path = me->path;
}
if (theme_archive_path) {
if (!PHYSFS_mount(theme_archive_path, "themetmp", 0)) cfg_path = NULL;
else {
is_archive = true;
cfg_path = "themetmp/theme.cfg";
}
}
if (cfg_path) {
if (!is_archive) good_cfg = config_read_file(&cfg, cfg_path);
else {
u8 *cfg_buf = NULL;
good_cfg = assetsPhysfsReadFile(cfg_path, &cfg_buf, NULL, true);
if (good_cfg) good_cfg = config_read_string(&cfg, (char*)cfg_buf);
free(cfg_buf);
}
}
if (good_cfg) {
themeInfo = config_lookup(&cfg, "themeInfo"); themeInfo = config_lookup(&cfg, "themeInfo");
if (themeInfo != NULL) { if (themeInfo != NULL) {
if(config_setting_lookup_string(themeInfo, "name", &name)) if(config_setting_lookup_string(themeInfo, "name", &name))
@ -462,20 +418,6 @@ bool menuEntryLoad(menuEntry_s* me, const char* name, bool shortcut, bool check_
strncpy(me->author, author, sizeof(me->author)-1); strncpy(me->author, author, sizeof(me->author)-1);
strncpy(me->version, version, sizeof(me->version)-1); strncpy(me->version, version, sizeof(me->version)-1);
config_destroy(&cfg); config_destroy(&cfg);
if (good_cfg && is_archive) {
bool iconLoaded = false;
iconLoaded = menuEntryLoadExternalIcon(me, "themetmp/icon.jpg", true);
if (iconLoaded) menuEntryParseIcon(me);
}
if (is_archive) PHYSFS_unmount(theme_archive_path);
#ifdef __SWITCH__
if (is_romfs) romfsUnmount("themetmp");
#endif
} }
if (me->type == ENTRY_TYPE_FILE_OTHER) if (me->type == ENTRY_TYPE_FILE_OTHER)
@ -507,7 +449,7 @@ bool menuEntryLoad(menuEntry_s* me, const char* name, bool shortcut, bool check_
bool iconLoaded = false; bool iconLoaded = false;
iconLoaded = menuEntryLoadExternalIcon(me, tempbuf, false); iconLoaded = menuEntryLoadExternalIcon(me, tempbuf);
if (iconLoaded) menuEntryParseIcon(me); if (iconLoaded) menuEntryParseIcon(me);
@ -536,28 +478,9 @@ bool menuEntryLoad(menuEntry_s* me, const char* name, bool shortcut, bool check_
// Initialize the argument data // Initialize the argument data
argData_s* ad = &me->args; argData_s* ad = &me->args;
argData_s* ad_assoc = &fileassoc_me->args;
char *arg_src = (char*)&ad_assoc->buf[1];
bool ftoken_found=0;
ad->dst = (char*)&ad->buf[1]; ad->dst = (char*)&ad->buf[1];
launchAddArg(ad, fileassoc_me->path);
for (u32 argi=0; argi<ad_assoc->buf[0]; argi++, arg_src+= strlen(arg_src)+1) { launchAddArg(ad, me->path);
if (argi) {
strptr = strchr(arg_src, '%');
if (strptr && strptr[0] && strptr[1] && (strptr == arg_src || strptr[-1] != '\\')) {
if (strptr[1] == 'f') {
memset(tempbuf, 0, sizeof(tempbuf));
snprintf(tempbuf, sizeof(tempbuf)-1, "%.*s%s%s", (int)((uintptr_t)strptr-(uintptr_t)arg_src), arg_src, me->path, &strptr[2]);
launchAddArg(ad, tempbuf);
ftoken_found = 1;
continue;
}
}
}
launchAddArg(ad, arg_src);
}
if (!ftoken_found) launchAddArg(ad, me->path);
strncpy(me->path, fileassoc_me->path, sizeof(me->path)); strncpy(me->path, fileassoc_me->path, sizeof(me->path));
me->path[sizeof(me->path)-1] = 0; me->path[sizeof(me->path)-1] = 0;
@ -578,12 +501,12 @@ bool menuEntryLoad(menuEntry_s* me, const char* name, bool shortcut, bool check_
} }
void menuEntryFileassocLoad(const char* filepath) { void menuEntryFileassocLoad(const char* filepath) {
bool success=0, iconLoaded=0; bool success=0, success2=0;
menuEntry_s* me = NULL; menuEntry_s* me = NULL;
config_setting_t *fileassoc = NULL, *targets = NULL, *target = NULL, *app_args = NULL, *target_args = NULL; config_setting_t *fileassoc = NULL, *targets = NULL, *target = NULL;
config_t cfg = {0}; config_t cfg = {0};
int targets_len=0, args_len=0, i; int targets_len=0, i;
const char *strptr = NULL; const char *strptr = NULL;
char app_path[PATH_MAX+8]; char app_path[PATH_MAX+8];
@ -592,8 +515,8 @@ void menuEntryFileassocLoad(const char* filepath) {
char target_file_extension[PATH_MAX+1]; char target_file_extension[PATH_MAX+1];
char target_filename[PATH_MAX+1]; char target_filename[PATH_MAX+1];
char app_author[ENTRY_AUTHORLENGTH+2]; char app_author[ENTRY_AUTHORLENGTH+1];
char app_version[ENTRY_VERLENGTH+2]; char app_version[ENTRY_VERLENGTH+1];
uint8_t *app_icon_gfx = NULL; uint8_t *app_icon_gfx = NULL;
uint8_t *app_icon_gfx_small = NULL; uint8_t *app_icon_gfx_small = NULL;
@ -615,8 +538,7 @@ void menuEntryFileassocLoad(const char* filepath) {
snprintf(app_path, sizeof(app_path)-1, "%s%s", menuGetRootBasePath(), strptr); snprintf(app_path, sizeof(app_path)-1, "%s%s", menuGetRootBasePath(), strptr);
if (config_setting_lookup_string(fileassoc, "icon_path", &strptr)) if (config_setting_lookup_string(fileassoc, "icon_path", &strptr))
snprintf(main_icon_path, sizeof(main_icon_path)-1, "%s%s", menuGetRootBasePath(), strptr); snprintf(main_icon_path, sizeof(main_icon_path)-1, "%s%s", menuGetRootBasePath(), strptr);
app_args = config_setting_lookup(fileassoc, "app_args"); targets = config_setting_get_member(fileassoc, "targets");
targets = config_setting_lookup(fileassoc, "targets");
if (app_path[0] && targets) { if (app_path[0] && targets) {
targets_len = config_setting_length(targets); targets_len = config_setting_length(targets);
@ -632,7 +554,7 @@ void menuEntryFileassocLoad(const char* filepath) {
strptr = getSlash(app_path); strptr = getSlash(app_path);
if(strptr[0] == '/') strptr++; if(strptr[0] == '/') strptr++;
if (menuEntryLoad(me, strptr, 0, true)) { if (menuEntryLoad(me, strptr, 0)) {
strncpy(app_author, me->author, sizeof(app_author)); strncpy(app_author, me->author, sizeof(app_author));
app_author[sizeof(app_author)-1] = 0; app_author[sizeof(app_author)-1] = 0;
strncpy(app_version, me->version, sizeof(app_version)); strncpy(app_version, me->version, sizeof(app_version));
@ -662,13 +584,12 @@ void menuEntryFileassocLoad(const char* filepath) {
strncpy(target_file_extension, strptr, sizeof(target_file_extension)-1); strncpy(target_file_extension, strptr, sizeof(target_file_extension)-1);
if (config_setting_lookup_string(target, "filename", &strptr)) if (config_setting_lookup_string(target, "filename", &strptr))
strncpy(target_filename, strptr, sizeof(target_filename)-1); strncpy(target_filename, strptr, sizeof(target_filename)-1);
target_args = config_setting_lookup(target, "app_args");
//string_is_set for target_file_extension and target_filename must differ: only 1 can be set, not both set or both not set. //string_is_set for target_file_extension and target_filename must differ: only 1 can be set, not both set or both not set.
if ((target_file_extension[0]!=0) == (target_filename[0]!=0)) continue; if ((target_file_extension[0]!=0) == (target_filename[0]!=0)) continue;
me = menuCreateEntry(ENTRY_TYPE_FILEASSOC); me = menuCreateEntry(ENTRY_TYPE_FILEASSOC);
iconLoaded = 0; success2 = 0;
if (me) { if (me) {
strncpy(me->path, app_path, sizeof(me->path)); strncpy(me->path, app_path, sizeof(me->path));
@ -687,32 +608,22 @@ void menuEntryFileassocLoad(const char* filepath) {
} }
me->fileassoc_str[sizeof(me->fileassoc_str)-1] = 0; me->fileassoc_str[sizeof(me->fileassoc_str)-1] = 0;
if (target_icon_path[0]) iconLoaded = menuEntryLoadExternalIcon(me, target_icon_path, false); if (target_icon_path[0]) success2 = menuEntryLoadExternalIcon(me, target_icon_path);
if (!iconLoaded && main_icon_path[0]) iconLoaded = menuEntryLoadExternalIcon(me, main_icon_path, false); if (!success2 && main_icon_path[0]) success2 = menuEntryLoadExternalIcon(me, main_icon_path);
if (iconLoaded) { if (success2) {
menuEntryParseIcon(me); menuEntryParseIcon(me);
} else { } else {
iconLoaded = menuEntryImportIconGfx(me, app_icon_gfx, app_icon_gfx_small); success2 = menuEntryImportIconGfx(me, app_icon_gfx, app_icon_gfx_small);
}
argData_s* ad = &me->args;
ad->dst = (char*)&ad->buf[1];
launchAddArg(ad, me->path);
config_setting_t *config_args = target_args ? target_args : app_args;
if (config_args) {
args_len = config_setting_length(config_args);
for (int argi=0; argi<args_len; argi++) {
strptr = config_setting_get_string_elem(config_args, argi);
if (strptr==NULL) continue;
launchAddArg(ad, strptr);
}
} }
} }
if (me) menuFileassocAddEntry(me); if (me) {
if (success2)
menuFileassocAddEntry(me);
else
menuDeleteEntry(me, 0);
}
} }
} }
} }
@ -731,33 +642,65 @@ void menuEntryFileassocLoad(const char* filepath) {
void menuEntryParseIcon(menuEntry_s* me) { void menuEntryParseIcon(menuEntry_s* me) {
if (me->icon_size==0 || me->icon==NULL) return; if (me->icon_size==0 || me->icon==NULL) return;
ThemeLayoutObject *layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MenuActiveEntryIcon]; int w,h,samp;
ThemeLayoutObject *layoutobj2 = &themeCurrent.layoutObjects[ThemeLayoutId_MenuListIcon]; size_t imagesize = 256*256*3;
me->icon_gfx = (uint8_t*)malloc(imagesize);
size_t imagesize = layoutobj->imageSize[0]*layoutobj->imageSize[1]*3; if (me->icon_gfx == NULL) {
bool ret=true; me->icon_size = 0;
uint8_t *tmp_gfx = (uint8_t*)malloc(imagesize); free(me->icon);
me->icon = NULL;
return;
}
if (tmp_gfx == NULL) ret = false; tjhandle _jpegDecompressor = tjInitDecompress();
if (ret) ret = assetsLoadJpgFromMemory(me->icon, me->icon_size, tmp_gfx, IMAGE_MODE_RGB24, layoutobj->imageSize[0], layoutobj->imageSize[1]); if (_jpegDecompressor == NULL) {
free(me->icon_gfx);
me->icon_gfx = NULL;
if (ret) me->icon_gfx = downscaleImg(tmp_gfx, layoutobj->imageSize[0], layoutobj->imageSize[1], layoutobj->size[0], layoutobj->size[1], IMAGE_MODE_RGB24); me->icon_size = 0;
free(me->icon);
me->icon = NULL;
return;
}
if (ret && me->icon_gfx==NULL) ret = false; if (tjDecompressHeader2(_jpegDecompressor, me->icon, me->icon_size, &w, &h, &samp) == -1) {
free(me->icon_gfx);
me->icon_gfx = NULL;
me->icon_size = 0;
free(me->icon);
me->icon = NULL;
tjDestroy(_jpegDecompressor);
return;
}
if (w != 256 || h != 256 ) return;
if (tjDecompress2(_jpegDecompressor, me->icon, me->icon_size, me->icon_gfx, w, 0, h, TJPF_RGB, TJFLAG_ACCURATEDCT) == -1) {
free(me->icon_gfx);
me->icon_gfx = NULL;
me->icon_size = 0;
free(me->icon);
me->icon = NULL;
tjDestroy(_jpegDecompressor);
return;
}
me->icon_size = 0; me->icon_size = 0;
free(me->icon); free(me->icon);
me->icon = NULL; me->icon = NULL;
if (ret) me->icon_gfx_small = downscaleImg(tmp_gfx, layoutobj->imageSize[0], layoutobj->imageSize[1], layoutobj2->size[0], layoutobj2->size[1], IMAGE_MODE_RGB24); tjDestroy(_jpegDecompressor);
if (!ret || me->icon_gfx_small == NULL) { me->icon_gfx_small = downscaleImg(me->icon_gfx, 256, 256, 140, 140, IMAGE_MODE_RGB24);
if (me->icon_gfx_small == NULL) {
free(me->icon_gfx); free(me->icon_gfx);
me->icon_gfx = NULL; me->icon_gfx = NULL;
} }
free(tmp_gfx);
} }
uint8_t *downscaleImg(const uint8_t *image, int srcWidth, int srcHeight, int destWidth, int destHeight, ImageMode mode) { uint8_t *downscaleImg(const uint8_t *image, int srcWidth, int srcHeight, int destWidth, int destHeight, ImageMode mode) {
@ -777,11 +720,6 @@ uint8_t *downscaleImg(const uint8_t *image, int srcWidth, int srcHeight, int des
return NULL; return NULL;
} }
if (srcWidth == destWidth && srcHeight == destHeight) {
memcpy(out, image, destWidth*destHeight*(mode==IMAGE_MODE_RGBA32 ? 4 : 3));
return out;
}
int tmpx, tmpy; int tmpx, tmpy;
int pos; int pos;
float sourceX, sourceY; float sourceX, sourceY;
@ -888,7 +826,7 @@ void menuEntryParseNacp(menuEntry_s* me) {
if (me->nacp==NULL) return; if (me->nacp==NULL) return;
strncpy(me->version, me->nacp->display_version, sizeof(me->version)-1); strncpy(me->version, me->nacp->version, sizeof(me->version)-1);
#ifdef __SWITCH__ #ifdef __SWITCH__
Result rc=0; Result rc=0;

View File

@ -35,7 +35,6 @@ static void _menuAddEntry(menu_s *m, menuEntry_s* me) {
m->lastEntry = me; m->lastEntry = me;
} }
m->xPos = 0; m->xPos = 0;
m->slideSpeed = 0;
m->nEntries ++; m->nEntries ++;
} }
@ -60,7 +59,6 @@ static void menuAddEntryToFront(menuEntry_s* me) {
m->lastEntry = me; m->lastEntry = me;
} }
m->xPos = 0; m->xPos = 0;
m->slideSpeed = 0;
m->nEntries ++; m->nEntries ++;
} }
@ -178,10 +176,11 @@ int menuScan(const char* target) {
memset(tmp_path, 0, sizeof(tmp_path)); memset(tmp_path, 0, sizeof(tmp_path));
snprintf(tmp_path, sizeof(tmp_path)-1, "%s%s%s", s_menu[!s_curMenu].dirname, dirsep, dp->d_name); snprintf(tmp_path, sizeof(tmp_path)-1, "%s%s%s", s_menu[!s_curMenu].dirname, dirsep, dp->d_name);
#ifdef _DIRENT_HAVE_D_TYPE #ifdef __SWITCH__
if (dp->d_type == DT_UNKNOWN) fsdev_dir_t* dirSt = (fsdev_dir_t*)dir->dirData->dirStruct;
continue; FsDirectoryEntry* entry = &dirSt->entry_data[dirSt->index];
entrytype = dp->d_type != DT_REG;
entrytype = entry->type == ENTRYTYPE_DIR;
#else #else
struct stat tmpstat; struct stat tmpstat;
@ -209,7 +208,7 @@ int menuScan(const char* target) {
strncpy(me->path, tmp_path, sizeof(me->path)-1); strncpy(me->path, tmp_path, sizeof(me->path)-1);
me->path[sizeof(me->path)-1] = 0; me->path[sizeof(me->path)-1] = 0;
if (menuEntryLoad(me, dp->d_name, shortcut, true)) if (menuEntryLoad(me, dp->d_name, shortcut))
menuAddEntry(me); menuAddEntry(me);
else else
menuDeleteEntry(me, 0); menuDeleteEntry(me, 0);
@ -246,23 +245,8 @@ int themeMenuScan(const char* target) {
memset(tmp_path, 0, sizeof(tmp_path)); memset(tmp_path, 0, sizeof(tmp_path));
snprintf(tmp_path, sizeof(tmp_path)-1, "%s/%s", s_menu[!s_curMenu].dirname, dp->d_name); snprintf(tmp_path, sizeof(tmp_path)-1, "%s/%s", s_menu[!s_curMenu].dirname, dp->d_name);
bool entrytype=0;
#ifdef _DIRENT_HAVE_D_TYPE
if (dp->d_type == DT_UNKNOWN)
continue;
entrytype = dp->d_type != DT_REG;
#else
struct stat tmpstat;
if(stat(tmp_path, &tmpstat)==-1)
continue;
entrytype = (tmpstat.st_mode & S_IFMT) != S_IFREG;
#endif
const char* ext = getExtension(dp->d_name); const char* ext = getExtension(dp->d_name);
if (entrytype || strcasecmp(ext, ".cfg")==0 || strcasecmp(ext, ".romfs")==0 || strcasecmp(ext, ".zip")==0) if (strcasecmp(ext, ".cfg")==0)
me = menuCreateEntry(ENTRY_TYPE_THEME); me = menuCreateEntry(ENTRY_TYPE_THEME);
if (!me) if (!me)
@ -270,7 +254,7 @@ int themeMenuScan(const char* target) {
strncpy(me->path, tmp_path, sizeof(me->path)-1); strncpy(me->path, tmp_path, sizeof(me->path)-1);
me->path[sizeof(me->path)-1] = 0; me->path[sizeof(me->path)-1] = 0;
if (menuEntryLoad(me, dp->d_name, shortcut, true)) if (menuEntryLoad(me, dp->d_name, shortcut))
menuAddEntry(me); menuAddEntry(me);
else else
menuDeleteEntry(me, 0); menuDeleteEntry(me, 0);
@ -282,7 +266,7 @@ int themeMenuScan(const char* target) {
menuEntry_s* me = menuCreateEntry(ENTRY_TYPE_THEME); menuEntry_s* me = menuCreateEntry(ENTRY_TYPE_THEME);
if(me) { if(me) {
if(menuEntryLoad(me, textGetString(StrId_DefaultThemeName), false, false))//Create Default theme Menu Entry if(menuEntryLoad(me, textGetString(StrId_DefaultThemeName), false))//Create Default theme Menu Entry
menuAddEntryToFront(me); menuAddEntryToFront(me);
else else
menuDeleteEntry(me, 0); menuDeleteEntry(me, 0);

View File

@ -6,19 +6,10 @@
#include "switch/runtime/nxlink.h" #include "switch/runtime/nxlink.h"
#endif #endif
double menuTimer;
char rootPathBase[PATH_MAX]; char rootPathBase[PATH_MAX];
char rootPath[PATH_MAX+8]; char rootPath[PATH_MAX+8];
uint8_t *folder_icon_large, *folder_icon_small;
uint8_t *invalid_icon_large, *invalid_icon_small;
uint8_t *theme_icon_large, *theme_icon_small;
void computeFrontGradient(color_t baseColor, int height); void computeFrontGradient(color_t baseColor, int height);
void menuLoadFileassoc(void);
char *menuGetRootPath(void) { char *menuGetRootPath(void) {
return rootPath; return rootPath;
} }
@ -122,63 +113,12 @@ void menuHandleXButton(void) {
} }
} }
void menuStartupCommon(void) {
free(folder_icon_large);
free(folder_icon_small);
free(invalid_icon_large);
free(invalid_icon_small);
free(theme_icon_large);
free(theme_icon_small);
ThemeLayoutObject *layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MenuActiveEntryIcon];
ThemeLayoutObject *layoutobj2 = &themeCurrent.layoutObjects[ThemeLayoutId_MenuListIcon];
assetsDataEntry *data = NULL;
assetsGetData(AssetId_folder_icon, &data);
folder_icon_large = downscaleImg(data->buffer, layoutobj->imageSize[0], layoutobj->imageSize[1], layoutobj->size[0], layoutobj->size[1], data->imageMode);
folder_icon_small = downscaleImg(data->buffer, layoutobj->imageSize[0], layoutobj->imageSize[1], layoutobj2->size[0], layoutobj2->size[1], data->imageMode);
assetsGetData(AssetId_invalid_icon, &data);
invalid_icon_large = downscaleImg(data->buffer, layoutobj->imageSize[0], layoutobj->imageSize[1], layoutobj->size[0], layoutobj->size[1], data->imageMode);
invalid_icon_small = downscaleImg(data->buffer, layoutobj->imageSize[0], layoutobj->imageSize[1], layoutobj2->size[0], layoutobj2->size[1], data->imageMode);
if(themeGlobalPreset == THEME_PRESET_DARK)
assetsGetData(AssetId_theme_icon_dark, &data);
else
assetsGetData(AssetId_theme_icon_light, &data);
theme_icon_large = downscaleImg(data->buffer, layoutobj->imageSize[0], layoutobj->imageSize[1], layoutobj->size[0], layoutobj->size[1], data->imageMode);
theme_icon_small = downscaleImg(data->buffer, layoutobj->imageSize[0], layoutobj->imageSize[1], layoutobj2->size[0], layoutobj2->size[1], data->imageMode);
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_FrontWave];
computeFrontGradient(themeCurrent.frontWaveColor, layoutobj->size[1]);
}
void menuThemeSelectCurrentEntry(void) {
menu_s* menu = menuGetCurrent();
char themePath[PATH_MAX] = {0};
GetThemePathFromConfig(themePath, PATH_MAX);
if (themePath[0]==0) menu->curEntry = 0;
else {
int i;
menuEntry_s* me;
for (i = 0, me = menu->firstEntry; me != NULL; i ++, me = me->next) {
if (strcmp(me->path, themePath)==0) {
menu->curEntry = i;
break;
}
}
}
}
void launchApplyThemeTask(menuEntry_s* arg) { void launchApplyThemeTask(menuEntry_s* arg) {
const char* themePath = arg->path; const char* themePath = arg->path;
menu_s* menu = menuGetCurrent();
SetThemePathToConfig(themePath); SetThemePathToConfig(themePath);
themeStartup(themeGlobalPreset); themeStartup(themeGlobalPreset);
menuStartupCommon(); computeFrontGradient(themeCurrent.frontWaveColor, 280);
menuLoadFileassoc();
if (hbmenu_state == HBMENU_THEME_MENU) { // Normally this should never be used outside of theme-menu.
themeMenuScan(menu->dirname);
menuThemeSelectCurrentEntry();
} else menuScan(menu->dirname);
} }
bool menuIsNetloaderActive(void) { bool menuIsNetloaderActive(void) {
@ -225,13 +165,16 @@ static void drawIcon(int x, int y, int width, int height, const uint8_t *image,
} }
} }
uint8_t *folder_icon_small;
uint8_t *invalid_icon_small;
uint8_t *theme_icon_small;
static void drawEntry(menuEntry_s* me, int off_x, int is_active) { static void drawEntry(menuEntry_s* me, int off_x, int is_active) {
ThemeLayoutObject *layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MenuList];
int x, y; int x, y;
int start_y = layoutobj->posStart[1];//*(n % 2); int start_y = 720 - 100 - 145;//*(n % 2);
int end_y = start_y + layoutobj->size[1]; int end_y = start_y + 140 + 32;
int start_x = off_x;//(n / 2); int start_x = off_x;//(n / 2);
int end_x = start_x + layoutobj->size[0]; int end_x = start_x + 140;
int j; int j;
const uint8_t *smallimg = NULL; const uint8_t *smallimg = NULL;
@ -252,7 +195,7 @@ static void drawEntry(menuEntry_s* me, int off_x, int is_active) {
if (is_active) { if (is_active) {
highlight_multiplier = fmax(0.0, fabs(fmod(menuTimer, 1.0) - 0.5) / 0.5); highlight_multiplier = fmax(0.0, fabs(fmod(menuTimer, 1.0) - 0.5) / 0.5);
border_color = MakeColor(themeCurrent.highlightColor.r + (themeCurrent.highlightGradientEdgeColor.r - themeCurrent.highlightColor.r) * highlight_multiplier, themeCurrent.highlightColor.g + (themeCurrent.highlightGradientEdgeColor.g - themeCurrent.highlightColor.g) * highlight_multiplier, themeCurrent.highlightColor.b + (themeCurrent.highlightGradientEdgeColor.b - themeCurrent.highlightColor.b) * highlight_multiplier, 255); border_color = MakeColor(themeCurrent.highlightColor.r + (255 - themeCurrent.highlightColor.r) * highlight_multiplier, themeCurrent.highlightColor.g + (255 - themeCurrent.highlightColor.g) * highlight_multiplier, themeCurrent.highlightColor.b + (255 - themeCurrent.highlightColor.b) * highlight_multiplier, 255);
border_start_x = start_x-6; border_start_x = start_x-6;
border_end_x = end_x+6; border_end_x = end_x+6;
border_start_y = start_y-5; border_start_y = start_y-5;
@ -330,29 +273,29 @@ static void drawEntry(menuEntry_s* me, int off_x, int is_active) {
} }
else if (me->type == ENTRY_TYPE_FOLDER) { else if (me->type == ENTRY_TYPE_FOLDER) {
smallimg = folder_icon_small; smallimg = folder_icon_small;
largeimg = folder_icon_large; largeimg = assetsGetDataBuffer(AssetId_folder_icon);
} }
else if (me->type == ENTRY_TYPE_THEME){ else if (me->type == ENTRY_TYPE_THEME){
smallimg = theme_icon_small; smallimg = theme_icon_small;
largeimg = theme_icon_large; if(themeGlobalPreset == THEME_PRESET_DARK)
largeimg = assetsGetDataBuffer(AssetId_theme_icon_dark);
else largeimg = assetsGetDataBuffer(AssetId_theme_icon_light);
} }
else { else {
smallimg = invalid_icon_small; smallimg = invalid_icon_small;
largeimg = invalid_icon_large; largeimg = assetsGetDataBuffer(AssetId_invalid_icon);
} }
if (smallimg) { if (smallimg) {
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MenuListIcon]; drawImage(start_x, start_y + 32, 140, 140, smallimg, IMAGE_MODE_RGB24);
drawImage(start_x + layoutobj->posStart[0], start_y + layoutobj->posStart[1], layoutobj->size[0], layoutobj->size[1], smallimg, IMAGE_MODE_RGB24);
} }
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MenuActiveEntryIcon]; if (is_active && largeimg) {
if (is_active && largeimg && layoutobj->visible) { drawImage(117, 100+10, 256, 256, largeimg, IMAGE_MODE_RGB24);
drawImage(layoutobj->posStart[0], layoutobj->posStart[1], layoutobj->size[0], layoutobj->size[1], largeimg, IMAGE_MODE_RGB24);
shadow_start_y = layoutobj->posStart[1]+layoutobj->size[1]; shadow_start_y = 100+10+256;
border_start_x = layoutobj->posStart[0]; border_start_x = 117;
border_end_x = layoutobj->posStart[0]+layoutobj->size[0]; border_end_x = 117+256;
for (shadow_y=shadow_start_y; shadow_y <shadow_start_y+shadow_size; shadow_y++) { for (shadow_y=shadow_start_y; shadow_y <shadow_start_y+shadow_size; shadow_y++) {
for (x=border_start_x; x<border_end_x; x++) { for (x=border_start_x; x<border_end_x; x++) {
@ -374,23 +317,21 @@ static void drawEntry(menuEntry_s* me, int off_x, int is_active) {
memset(tmpstr, 0, sizeof(tmpstr)); memset(tmpstr, 0, sizeof(tmpstr));
snprintf(tmpstr, sizeof(tmpstr)-1, "%s%s", strptr, me->name); snprintf(tmpstr, sizeof(tmpstr)-1, "%s%s", strptr, me->name);
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MenuListName]; DrawTextTruncate(interuiregular14, start_x + 4, start_y + 4 + 18, themeCurrent.borderTextColor, tmpstr, 140 - 32, "...");
DrawTextTruncate(layoutobj->font, start_x + layoutobj->posStart[0], start_y + layoutobj->posStart[1], themeCurrent.borderTextColor, tmpstr, layoutobj->size[0], "...");
if (is_active) { if (is_active) {
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MenuActiveEntryName]; start_x = 1280 - 790;
if (layoutobj->visible) DrawTextTruncate(layoutobj->font, layoutobj->posStart[0], layoutobj->posStart[1], themeCurrent.textColor, tmpstr, layoutobj->size[0], "..."); start_y = 135+10;
DrawTextTruncate(interuimedium30, start_x, start_y + 39, themeCurrent.textColor, tmpstr, 1280 - start_x - 120 ,"...");
if (me->type != ENTRY_TYPE_FOLDER) { if (me->type != ENTRY_TYPE_FOLDER) {
memset(tmpstr, 0, sizeof(tmpstr)); memset(tmpstr, 0, sizeof(tmpstr));
snprintf(tmpstr, sizeof(tmpstr)-1, "%s: %s", textGetString(StrId_AppInfo_Author), me->author); snprintf(tmpstr, sizeof(tmpstr)-1, "%s: %s", textGetString(StrId_AppInfo_Author), me->author);
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MenuActiveEntryAuthor]; DrawText(interuiregular14, start_x, start_y + 28 + 30 + 18, themeCurrent.textColor, tmpstr);
if (layoutobj->visible) DrawText(layoutobj->font, layoutobj->posStart[0], layoutobj->posStart[1], themeCurrent.textColor, tmpstr);
memset(tmpstr, 0, sizeof(tmpstr)); memset(tmpstr, 0, sizeof(tmpstr));
snprintf(tmpstr, sizeof(tmpstr)-1, "%s: %s", textGetString(StrId_AppInfo_Version), me->version); snprintf(tmpstr, sizeof(tmpstr)-1, "%s: %s", textGetString(StrId_AppInfo_Version), me->version);
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MenuActiveEntryVersion]; DrawText(interuiregular14, start_x, start_y + 28 + 30 + 18 + 6 + 18, themeCurrent.textColor, tmpstr);
if (layoutobj->visible) DrawText(layoutobj->font, layoutobj->posStart[0], layoutobj->posStart[1], themeCurrent.textColor, tmpstr);
} }
} }
} }
@ -403,8 +344,6 @@ void computeFrontGradient(color_t baseColor, int height) {
float dark_mult, dark_sub = 75; float dark_mult, dark_sub = 75;
color_t color; color_t color;
if (height < 0 || height > 720) return;
for (y=0; y<720; y++) { for (y=0; y<720; y++) {
alpha = y - (720 - height); alpha = y - (720 - height);
@ -453,20 +392,22 @@ void menuStartupPath(void) {
} }
} }
void menuLoadFileassoc(void) { void menuStartup(void) {
char tmp_path[PATH_MAX+28]; char tmp_path[PATH_MAX+28];
memset(tmp_path, 0, sizeof(tmp_path)-1);
snprintf(tmp_path, sizeof(tmp_path)-1, "%s/config/nx-hbmenu/fileassoc", rootPathBase); snprintf(tmp_path, sizeof(tmp_path)-1, "%s/config/nx-hbmenu/fileassoc", rootPathBase);
menuFileassocScan(tmp_path); menuFileassocScan(tmp_path);
}
void menuStartup(void) {
menuLoadFileassoc();
menuScan(rootPath); menuScan(rootPath);
menuStartupCommon(); folder_icon_small = downscaleImg(assetsGetDataBuffer(AssetId_folder_icon), 256, 256, 140, 140, IMAGE_MODE_RGB24);
invalid_icon_small = downscaleImg(assetsGetDataBuffer(AssetId_invalid_icon), 256, 256, 140, 140, IMAGE_MODE_RGB24);
if(themeGlobalPreset == THEME_PRESET_DARK)
theme_icon_small = downscaleImg(assetsGetDataBuffer(AssetId_theme_icon_dark), 256, 256, 140, 140, IMAGE_MODE_RGB24);
else
theme_icon_small = downscaleImg(assetsGetDataBuffer(AssetId_theme_icon_light), 256, 256, 140, 140, IMAGE_MODE_RGB24);
computeFrontGradient(themeCurrent.frontWaveColor, 280);
//menuCreateMsgBox(780, 300, "This is a test");
} }
void themeMenuStartup(void) { void themeMenuStartup(void) {
@ -477,7 +418,6 @@ void themeMenuStartup(void) {
snprintf(tmp_path, sizeof(tmp_path)-1, "%s%s%s%s%s%s%s", rootPathBase, DIRECTORY_SEPARATOR, "config", DIRECTORY_SEPARATOR, "nx-hbmenu" , DIRECTORY_SEPARATOR, "themes"); snprintf(tmp_path, sizeof(tmp_path)-1, "%s%s%s%s%s%s%s", rootPathBase, DIRECTORY_SEPARATOR, "config", DIRECTORY_SEPARATOR, "nx-hbmenu" , DIRECTORY_SEPARATOR, "themes");
themeMenuScan(tmp_path); themeMenuScan(tmp_path);
menuThemeSelectCurrentEntry();
} }
color_t waveBlendAdd(color_t a, color_t b, float alpha) { color_t waveBlendAdd(color_t a, color_t b, float alpha) {
@ -489,7 +429,6 @@ void drawWave(int id, float timer, color_t color, int height, float phase, float
float wave_top_y, alpha, one_minus_alpha; float wave_top_y, alpha, one_minus_alpha;
color_t existing_color, new_color; color_t existing_color, new_color;
if (height < 0 || height > 720) return;
height = 720 - height; height = 720 - height;
for (x=0; x<1280; x++) { for (x=0; x<1280; x++) {
@ -539,39 +478,27 @@ void drawCharge() {
sprintf(chargeString, "%d%%", batteryCharge); sprintf(chargeString, "%d%%", batteryCharge);
ThemeLayoutObject *layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_BatteryCharge]; int tmpX = GetTextXCoordinate(interuiregular14, 1180 - 10, chargeString, 'r');
if (layoutobj->visible) { DrawText(interuiregular14, tmpX - 24 - 8, 0 + 47 + 10 + 21 + 4, themeCurrent.textColor, chargeString);
int tmpX = GetTextXCoordinate(layoutobj->font, layoutobj->posStart[0], chargeString, 'r'); drawIcon(1180 - 8 - 24 - 8, 0 + 47 + 10 + 6, 24, 24, assetsGetDataBuffer(AssetId_battery_icon), themeCurrent.textColor);
DrawText(layoutobj->font, tmpX, layoutobj->posStart[1], themeCurrent.textColor, chargeString); if (isCharging)
} drawIcon(1180 - 20, 0 + 47 + 10 + 6, 24, 24, assetsGetDataBuffer(AssetId_charging_icon), themeCurrent.textColor);
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_BatteryIcon];
assetsDataEntry *data = NULL;
assetsGetData(AssetId_battery_icon, &data);
if (layoutobj->visible) drawIcon(layoutobj->posStart[0], layoutobj->posStart[1], data->imageSize[0], data->imageSize[1], data->buffer, themeCurrent.textColor);
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_ChargingIcon];
assetsGetData(AssetId_charging_icon, &data);
if (isCharging && layoutobj->visible)
drawIcon(layoutobj->posStart[0], layoutobj->posStart[1], data->imageSize[0], data->imageSize[1], data->buffer, themeCurrent.textColor);
} }
} }
void drawNetwork(int tmpX, AssetId id) { void drawNetwork(int tmpX) {
ThemeLayoutObject *layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_NetworkIcon]; bool netstatusFlag=0;
assetsDataEntry *data = NULL; AssetId id;
assetsGetData(id, &data); if (statusGet(&netstatusFlag, &id)) {
if (layoutobj->visible) drawIcon(layoutobj->posType ? tmpX + layoutobj->posStart[0] : layoutobj->posStart[0], layoutobj->posStart[1], data->imageSize[0], data->imageSize[1], data->buffer, themeCurrent.textColor); if (netstatusFlag)
drawIcon(tmpX, 0 + 47 + 10 + 3, 24, 24, assetsGetDataBuffer(id), themeCurrent.textColor);
}
} }
u32 drawStatus() { u32 drawStatus() {
bool netstatusFlag=0;
bool temperatureFlag=0;
s32 temperature=0;
AssetId id;
char tmpstr[32]; char timeString[9];
time_t unixTime = time(NULL); time_t unixTime = time(NULL);
struct tm* timeStruct = localtime((const time_t *)&unixTime); struct tm* timeStruct = localtime((const time_t *)&unixTime);
@ -580,33 +507,26 @@ u32 drawStatus() {
int minutes = timeStruct->tm_min; int minutes = timeStruct->tm_min;
int seconds = timeStruct->tm_sec; int seconds = timeStruct->tm_sec;
snprintf(tmpstr, sizeof(tmpstr)-1, "%02d:%02d:%02d", hours, minutes, seconds); sprintf(timeString, "%02d:%02d:%02d", hours, minutes, seconds);
ThemeLayoutObject *layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_Status]; u32 tmpX = GetTextXCoordinate(interuimedium20, 1180, timeString, 'r');
u32 tmpX = GetTextXCoordinate(layoutobj->font, layoutobj->posStart[0], tmpstr, 'r'); DrawText(interuimedium20, tmpX, 0 + 47 + 10, themeCurrent.textColor, timeString);
if (layoutobj->visible) DrawText(layoutobj->font, tmpX, layoutobj->posStart[1], themeCurrent.textColor, tmpstr);
drawCharge(); drawCharge();
drawNetwork(tmpX);
if (statusGet(&netstatusFlag, &id, &temperatureFlag, &temperature)) {
if (netstatusFlag) drawNetwork(tmpX, id);
if (temperatureFlag) {
snprintf(tmpstr, sizeof(tmpstr)-1, "%d°C", temperature);
DrawTextFromLayout(ThemeLayoutId_Temperature, themeCurrent.textColor, tmpstr);
}
}
return tmpX; return tmpX;
} }
void drawButtons(menu_s* menu, bool emptyDir, int *out_basePos) { void drawButtons(menu_s* menu, bool emptyDir, int *x_image_out) {
ThemeLayoutObject *layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_ButtonA]; int x_image = 1280 - 252 - 30 - 32;
int basePos[2]={0}; int x_text = 1280 - 216 - 30 - 32;
basePos[0] = layoutobj->posStart[0]; if(emptyDir) {
basePos[1] = layoutobj->posStart[1]; x_image = 1280 - 126 - 30 - 32;
x_text = 1280 - 90 - 30 - 32;
}
#ifdef __SWITCH__ #ifdef __SWITCH__
if (strcmp( menu->dirname, "sdmc:/") != 0) if (strcmp( menu->dirname, "sdmc:/") != 0)
@ -614,26 +534,27 @@ void drawButtons(menu_s* menu, bool emptyDir, int *out_basePos) {
if (strcmp( menu->dirname, "/") != 0) if (strcmp( menu->dirname, "/") != 0)
#endif #endif
{ {
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_ButtonBText]; //drawImage(x_image, 720 - 48, 32, 32, themeCurrent.buttonBImage, IMAGE_MODE_RGBA32);
DrawTextFromLayoutRelative(ThemeLayoutId_ButtonBText, basePos[0], basePos[1], !emptyDir ? layoutobj->posStart : layoutobj->posEnd, basePos, themeCurrent.textColor, textGetString(StrId_Actions_Back), 'l'); DrawText(fontscale7, x_image, 720 - 47 + 24, themeCurrent.textColor, themeCurrent.buttonBText);//Display the 'B' button from SharedFont.
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_ButtonB]; DrawText(interuiregular18, x_text, 720 - 47 + 24, themeCurrent.textColor, textGetString(StrId_Actions_Back));
DrawTextFromLayoutRelative(ThemeLayoutId_ButtonB, basePos[0], basePos[1], layoutobj->posStart, basePos, themeCurrent.textColor, themeCurrent.buttonBText, 'l');
} }
if(hbmenu_state == HBMENU_DEFAULT) if(hbmenu_state == HBMENU_DEFAULT)
{ {
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_ButtonYText]; x_text = GetTextXCoordinate(interuiregular18, x_image - 32, textGetString(StrId_NetLoader), 'r');
DrawTextFromLayoutRelative(ThemeLayoutId_ButtonYText, basePos[0], basePos[1], layoutobj->posStart, basePos, themeCurrent.textColor, textGetString(StrId_NetLoader), 'r'); x_image = x_text - 36;
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_ButtonY]; *x_image_out = x_image - 40;
DrawTextFromLayoutRelative(ThemeLayoutId_ButtonY, basePos[0], basePos[1], layoutobj->posStart, basePos, themeCurrent.textColor, themeCurrent.buttonYText, 'l');
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_ButtonMText];
DrawTextFromLayoutRelative(ThemeLayoutId_ButtonMText, basePos[0], basePos[1], layoutobj->posStart, basePos, themeCurrent.textColor, textGetString(StrId_ThemeMenu), 'r');
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_ButtonM];
DrawTextFromLayoutRelative(ThemeLayoutId_ButtonM, basePos[0], basePos[1], layoutobj->posStart, basePos, themeCurrent.textColor, themeCurrent.buttonMText, 'l');
}
out_basePos[0] = basePos[0]; DrawText(fontscale7, x_image, 720 - 47 + 24, themeCurrent.textColor, themeCurrent.buttonYText);
out_basePos[1] = basePos[1]; DrawText(interuiregular18, x_text, 720 - 47 + 24, themeCurrent.textColor, textGetString(StrId_NetLoader));
x_text = GetTextXCoordinate(interuiregular18, x_image - 32, textGetString(StrId_ThemeMenu), 'r');
x_image = x_text - 36;
*x_image_out = x_image - 40;
DrawText(fontscale7, x_image, 720 - 47 + 24, themeCurrent.textColor, themeCurrent.buttonMText);
DrawText(interuiregular18, x_text, 720 - 47 + 24, themeCurrent.textColor, textGetString(StrId_ThemeMenu));
}
} }
void menuUpdateNetloader(netloaderState *netloader_state) { void menuUpdateNetloader(netloaderState *netloader_state) {
@ -668,77 +589,44 @@ void menuLoop(void) {
menuEntry_s* me; menuEntry_s* me;
menu_s* menu = NULL; menu_s* menu = NULL;
int i; int i;
int x, y, endy = 720; int x, y;
int curPos[2]={0}; int menupath_x_endpos = 918 + 40;
netloaderState netloader_state; netloaderState netloader_state;
ThemeLayoutObject *layoutobj = NULL;
for (i=0; i<3; i++) { for (y=0; y<450; y++) {
if (i==2) layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_BackWave];
if (i==1) layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MiddleWave];
if (i==0) layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_FrontWave];
if (layoutobj->visible && layoutobj->size[1] >= 0 && layoutobj->size[1] <= 720-10) {
endy = 720 - layoutobj->size[1] + 10;
break;
}
}
for (y=0; y<endy; y++) {
for (x=0; x<1280; x+=4) {// don't draw bottom pixels as they are covered by the waves for (x=0; x<1280; x+=4) {// don't draw bottom pixels as they are covered by the waves
Draw4PixelsRaw(x, y, themeCurrent.backgroundColor); Draw4PixelsRaw(x, y, themeCurrent.backgroundColor);
} }
} }
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_BackgroundImage]; drawWave(0, menuTimer, themeCurrent.backWaveColor, 295, 0.0, 3.0);
assetsDataEntry *data = NULL; drawWave(1, menuTimer, themeCurrent.middleWaveColor, 290, 2.0, 3.5);
assetsGetData(AssetId_background_image, &data); drawWave(2, menuTimer, themeCurrent.frontWaveColor, 280, 4.0, -2.5);
if (layoutobj->visible && data) drawImage(layoutobj->posStart[0], layoutobj->posStart[1], data->imageSize[0], endy < data->imageSize[1] ? endy : data->imageSize[1], data->buffer, data->imageMode);
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_BackWave];
if (layoutobj->visible) drawWave(0, menuTimer, themeCurrent.backWaveColor, layoutobj->size[1], 0.0, 3.0);
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MiddleWave];
if (layoutobj->visible) drawWave(1, menuTimer, themeCurrent.middleWaveColor, layoutobj->size[1], 2.0, 3.5);
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_FrontWave];
if (layoutobj->visible) drawWave(2, menuTimer, themeCurrent.frontWaveColor, layoutobj->size[1], 4.0, -2.5);
menuTimer += 0.05; menuTimer += 0.05;
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_Logo]; drawImage(40, 20, 140, 60, themeCurrent.hbmenuLogoImage, IMAGE_MODE_RGBA32);
if(themeGlobalPreset == THEME_PRESET_DARK) DrawText(interuiregular14, 184, 46 + 18, themeCurrent.textColor, VERSION);
assetsGetData(AssetId_hbmenu_logo_dark, &data);
else assetsGetData(AssetId_hbmenu_logo_light, &data);
if (layoutobj->visible) {
if (!themeCurrent.logoColor_set)
drawImage(layoutobj->posStart[0], layoutobj->posStart[1], data->imageSize[0], data->imageSize[1], data->buffer, data->imageMode);
else {
drawIcon(layoutobj->posStart[0], layoutobj->posStart[1], data->imageSize[0], data->imageSize[1], data->buffer, themeCurrent.logoColor);
}
}
DrawTextFromLayout(ThemeLayoutId_HbmenuVersion, themeCurrent.textColor, VERSION);
u32 statusXPos = drawStatus(); u32 statusXPos = drawStatus();
#ifdef __SWITCH__ #ifdef __SWITCH__
AppletType at = appletGetAppletType(); AppletType at = appletGetAppletType();
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_AttentionText]; if (at != AppletType_Application && at != AppletType_SystemApplication) {
if (at != AppletType_Application && at != AppletType_SystemApplication && layoutobj->visible) {
const char* appletMode = textGetString(StrId_AppletMode); const char* appletMode = textGetString(StrId_AppletMode);
u32 x_pos = GetTextXCoordinate(layoutobj->font, statusXPos, appletMode, 'r'); u32 x_pos = GetTextXCoordinate(interuimedium30, statusXPos, appletMode, 'r');
DrawText(layoutobj->font, layoutobj->posType ? x_pos + layoutobj->posStart[0] : layoutobj->posStart[0], layoutobj->posStart[1], themeCurrent.attentionTextColor, appletMode); DrawText(interuimedium30, x_pos - 32, 46 + 18, themeCurrent.attentionTextColor, appletMode);
} }
const char* loaderInfo = envGetLoaderInfo(); const char* loaderInfo = envGetLoaderInfo();
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_LoaderInfo]; if (loaderInfo) {
if (loaderInfo && layoutobj->visible) { u32 x_pos = 43;
u32 x_pos = layoutobj->posStart[0];
char* spacePos = strchr(loaderInfo, ' '); char* spacePos = strchr(loaderInfo, ' ');
if (spacePos) { if (spacePos) {
char tempbuf[64] = {0}; char tempbuf[64] = {0};
size_t tempsize = spacePos - loaderInfo + 1; size_t tempsize = spacePos - loaderInfo + 1;
if (tempsize > sizeof(tempbuf)-1) tempsize = sizeof(tempbuf)-1; if (tempsize > sizeof(tempbuf)-1) tempsize = sizeof(tempbuf)-1;
memcpy(tempbuf, loaderInfo, tempsize); memcpy(tempbuf, loaderInfo, tempsize);
x_pos = GetTextXCoordinate(layoutobj->font, layoutobj->posEnd[0], tempbuf, 'r'); x_pos = GetTextXCoordinate(interuiregular14, 184, tempbuf, 'r');
} }
DrawText(layoutobj->font, x_pos, layoutobj->posStart[1], themeCurrent.textColor, loaderInfo); DrawText(interuiregular14, x_pos, 46 + 18 + 20, themeCurrent.textColor, loaderInfo);
} }
#endif #endif
@ -748,7 +636,7 @@ void menuLoop(void) {
char tmpstr[64]; char tmpstr[64];
snprintf(tmpstr, sizeof(tmpstr)-1, "%lu", g_tickdiff_frame); snprintf(tmpstr, sizeof(tmpstr)-1, "%lu", g_tickdiff_frame);
DrawTextFromLayout(ThemeLayoutId_LogInfo, themeCurrent.textColor, tmpstr); DrawText(interuiregular14, 180 + 256, 46 + 16 + 18, themeCurrent.textColor, tmpstr);
#endif #endif
memset(&netloader_state, 0, sizeof(netloader_state)); memset(&netloader_state, 0, sizeof(netloader_state));
@ -765,11 +653,8 @@ void menuLoop(void) {
menuCloseMsgBox(); menuCloseMsgBox();
menuMsgBoxSetNetloaderState(0, NULL, 0, 0); menuMsgBoxSetNetloaderState(0, NULL, 0, 0);
}
if (netloader_state.errormsg[0]) { if (netloader_state.errormsg[0]) menuCreateMsgBox(780,300, netloader_state.errormsg);
menuCloseMsgBox();
menuCreateMsgBox(780,300, netloader_state.errormsg);
} }
if(hbmenu_state == HBMENU_NETLOADER_ACTIVE) { if(hbmenu_state == HBMENU_NETLOADER_ACTIVE) {
@ -789,21 +674,16 @@ void menuLoop(void) {
launchMenuEntryTask(netloader_state.me); launchMenuEntryTask(netloader_state.me);
} }
} else { } else {
DrawTextFromLayout(ThemeLayoutId_InfoMsg, themeCurrent.textColor, textGetString(StrId_NoAppsFound_Msg)); DrawText(interuiregular14, 64, 128 + 18, themeCurrent.textColor, textGetString(StrId_NoAppsFound_Msg));
} }
drawButtons(menu, true, curPos); drawButtons(menu, true, &menupath_x_endpos);
} }
else else
{ {
static int v = 0; static int v = 0;
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MenuListTiles];
int entries_count = layoutobj->posEnd[0];
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MenuList];
// Gentle Realign only when not manually moving if (menu->nEntries > 7) {
if (menu->slideSpeed == 0) { int wanted_x = clamp(-menu->curEntry * (140 + 30), -(menu->nEntries - 7) * (140 + 30), 0);
if (menu->nEntries > entries_count) {
int wanted_x = clamp(-menu->curEntry * layoutobj->posEnd[0], -(menu->nEntries - entries_count) * layoutobj->posEnd[0], 0);
menu->xPos += v; menu->xPos += v;
v += (wanted_x - menu->xPos) / 3; v += (wanted_x - menu->xPos) / 3;
v /= 2; v /= 2;
@ -811,31 +691,12 @@ void menuLoop(void) {
else { else {
menu->xPos = v = 0; menu->xPos = v = 0;
} }
}
else {
menu->xPos += menu->slideSpeed;
if (abs(menu->slideSpeed) > 2) {
// Slow down way faster when outside the normal bounds
if (menu->xPos > 0 || menu->xPos < -(menu->nEntries) * layoutobj->posEnd[0]) {
menu->slideSpeed *= .5f;
}
else {
menu->slideSpeed *= .9f;
}
}
else {
menu->slideSpeed = 0;
}
menu->curEntry = clamp(roundf(-((float) menu->xPos / layoutobj->posEnd[0])), 0, menu->nEntries);
}
menuEntry_s *active_entry = NULL; menuEntry_s *active_entry = NULL;
// Draw menu entries // Draw menu entries
for (me = menu->firstEntry, i = 0; me; me = me->next, i ++) { for (me = menu->firstEntry, i = 0; me; me = me->next, i ++) {
int entry_start_x = layoutobj->posStart[0] + i * layoutobj->posEnd[0]; int entry_start_x = 29 + i * (140 + 30);
int entry_draw_x = entry_start_x + menu->xPos; int entry_draw_x = entry_start_x + menu->xPos;
int screen_width = 1280; int screen_width = 1280;
@ -847,61 +708,54 @@ void menuLoop(void) {
if (is_active) if (is_active)
active_entry = me; active_entry = me;
if (!is_active && entry_draw_x < -(layoutobj->posStart[0] + layoutobj->posEnd[0])) if (!is_active && entry_draw_x < -(29 + 140 + 30))
continue; continue;
drawEntry(me, entry_draw_x, is_active); drawEntry(me, entry_draw_x, is_active);
} }
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MenuTypeMsg]; int getX = GetTextXCoordinate(interuiregular18, 1180, textGetString(StrId_ThemeMenu), 'r');
int getX=0;
if (layoutobj->visible) {
getX = GetTextXCoordinate(layoutobj->font, layoutobj->posStart[0], textGetString(StrId_ThemeMenu), 'r');
if(hbmenu_state == HBMENU_THEME_MENU) { if(hbmenu_state == HBMENU_THEME_MENU) {
DrawText(layoutobj->font, getX, layoutobj->posStart[1], themeCurrent.textColor, textGetString(StrId_ThemeMenu)); DrawText(interuiregular18, getX, 30 + 26 + 32 + 20, themeCurrent.textColor, textGetString(StrId_ThemeMenu));
} else { } else {
//DrawText(interuiregular18, getX, 30 + 26 + 32 + 10, themeCurrent.textColor, textGetString(StrId_ThemeMenu)); //DrawText(interuiregular18, getX, 30 + 26 + 32 + 10, themeCurrent.textColor, textGetString(StrId_ThemeMenu));
//DrawText(fontscale7, getX - 40, 30 + 26 + 32 + 10, themeCurrent.textColor, themeCurrent.buttonMText); //DrawText(fontscale7, getX - 40, 30 + 26 + 32 + 10, themeCurrent.textColor, themeCurrent.buttonMText);
} }
}
if(active_entry != NULL) { if(active_entry != NULL) {
const char *buttonstr = ""; if (active_entry->type == ENTRY_TYPE_THEME) {
DrawText(fontscale7, 1280 - 126 - 30 - 32, 720 - 47 + 24, themeCurrent.textColor, themeCurrent.buttonAText);
if (active_entry->type == ENTRY_TYPE_THEME) DrawText(interuiregular18, 1280 - 90 - 30 - 32, 720 - 47 + 24, themeCurrent.textColor, textGetString(StrId_Actions_Apply));
buttonstr = textGetString(StrId_Actions_Apply); }
else if (active_entry->type != ENTRY_TYPE_FOLDER) else if (active_entry->type != ENTRY_TYPE_FOLDER) {
buttonstr = textGetString(StrId_Actions_Launch); DrawText(fontscale7, 1280 - 126 - 30 - 32, 720 - 47 + 24, themeCurrent.textColor, themeCurrent.buttonAText);//Display the 'A' button from SharedFont.
else DrawText(interuiregular18, 1280 - 90 - 30 - 32, 720 - 47 + 24, themeCurrent.textColor, textGetString(StrId_Actions_Launch));
buttonstr = textGetString(StrId_Actions_Open); }
else {
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_ButtonAText]; DrawText(fontscale7, 1280 - 126 - 30 - 32, 720 - 47 + 24, themeCurrent.textColor, themeCurrent.buttonAText);
DrawTextFromLayoutRelative(ThemeLayoutId_ButtonAText, curPos[0], curPos[1], layoutobj->posStart, curPos, themeCurrent.textColor, buttonstr, 'l'); DrawText(interuiregular18, 1280 - 90 - 30 - 32, 720 - 47 + 24, themeCurrent.textColor, textGetString(StrId_Actions_Open));
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_ButtonA]; }
DrawTextFromLayoutRelative(ThemeLayoutId_ButtonA, curPos[0], curPos[1], layoutobj->posStart, curPos, themeCurrent.textColor, themeCurrent.buttonAText, 'l');
} }
drawButtons(menu, false, curPos); drawButtons(menu, false, &menupath_x_endpos);
if (active_entry && active_entry->type != ENTRY_TYPE_THEME) { if (active_entry && active_entry->type != ENTRY_TYPE_THEME) {
const char *buttonstr = ""; if (active_entry->starred) {
if (active_entry->starred) getX = GetTextXCoordinate(interuiregular18, menupath_x_endpos + 8, textGetString(StrId_Actions_Unstar), 'r');
buttonstr = textGetString(StrId_Actions_Unstar); DrawText(fontscale7, getX - 36, 720 - 47 + 24, themeCurrent.textColor, themeCurrent.buttonXText);
else DrawText(interuiregular18, getX, 720 - 47 + 24, themeCurrent.textColor, textGetString(StrId_Actions_Unstar));
buttonstr = textGetString(StrId_Actions_Star); } else {
getX = GetTextXCoordinate(interuiregular18, menupath_x_endpos + 8, textGetString(StrId_Actions_Star), 'r');
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_ButtonXText]; DrawText(fontscale7, getX - 36, 720 - 47 + 24, themeCurrent.textColor, themeCurrent.buttonXText);
DrawTextFromLayoutRelative(ThemeLayoutId_ButtonXText, curPos[0], curPos[1], layoutobj->posStart, curPos, themeCurrent.textColor, buttonstr, 'r'); DrawText(interuiregular18, getX, 720 - 47 + 24, themeCurrent.textColor, textGetString(StrId_Actions_Star));
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_ButtonX]; }
DrawTextFromLayoutRelative(ThemeLayoutId_ButtonX, curPos[0], curPos[1], layoutobj->posStart, curPos, themeCurrent.textColor, themeCurrent.buttonXText, 'l'); menupath_x_endpos = getX - 36 - 40;
} }
} }
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MenuPath]; DrawTextTruncate(interuiregular18, 40, 720 - 47 + 24, themeCurrent.textColor, menu->dirname, menupath_x_endpos - 40, "...");
if (layoutobj->visible) DrawTextTruncate(layoutobj->font, layoutobj->posStart[0], layoutobj->posStart[1], themeCurrent.textColor, menu->dirname, layoutobj->size[0], "...");
menuDrawMsgBox(); menuDrawMsgBox();
} }

View File

@ -33,7 +33,6 @@ struct menu_s_tag
int nEntries; int nEntries;
int curEntry; int curEntry;
int xPos; int xPos;
int slideSpeed;
char dirname[PATH_MAX+1]; char dirname[PATH_MAX+1];
}; };
@ -78,7 +77,7 @@ typedef enum
IMAGE_MODE_RGBA32 IMAGE_MODE_RGBA32
} ImageMode; } ImageMode;
extern double menuTimer; double menuTimer;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -87,7 +86,7 @@ extern "C" {
void menuEntryInit(menuEntry_s* me, MenuEntryType type); void menuEntryInit(menuEntry_s* me, MenuEntryType type);
void menuEntryFree(menuEntry_s* me, bool skip_icongfx); void menuEntryFree(menuEntry_s* me, bool skip_icongfx);
bool fileExists(const char* path); bool fileExists(const char* path);
bool menuEntryLoad(menuEntry_s* me, const char* name, bool shortcut, bool check_exists); bool menuEntryLoad(menuEntry_s* me, const char* name, bool shortcut);
void menuEntryParseIcon(menuEntry_s* me); void menuEntryParseIcon(menuEntry_s* me);
uint8_t *downscaleImg(const uint8_t *image, int srcWidth, int srcHeight, int destWidth, int destHeight, ImageMode mode); uint8_t *downscaleImg(const uint8_t *image, int srcWidth, int srcHeight, int destWidth, int destHeight, ImageMode mode);
void menuEntryParseNacp(menuEntry_s* me); void menuEntryParseNacp(menuEntry_s* me);

View File

@ -16,7 +16,6 @@ void drawMsgBoxBgToBuff(color_t *buff, int width, int height) {
float rad, alpha; float rad, alpha;
color_t base_color = themeCurrent.backgroundColor; color_t base_color = themeCurrent.backgroundColor;
color_t color; color_t color;
ThemeLayoutObject *layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MsgBoxSeparator];
for (y=0; y<height; y++) { for (y=0; y<height; y++) {
for (x=0; x<width; x++) { for (x=0; x<width; x++) {
@ -63,7 +62,7 @@ void drawMsgBoxBgToBuff(color_t *buff, int width, int height) {
else else
color = base_color; color = base_color;
if (y == height + layoutobj->posStart[1]) { if (y == height - 80) {
color = themeCurrent.separatorColor; color = themeCurrent.separatorColor;
} }
@ -77,7 +76,6 @@ void menuDrawMsgBox() {
if (!menuIsMsgBoxOpen()) if (!menuIsMsgBoxOpen())
return; return;
ThemeLayoutObject *layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MsgBoxSeparator];
int off; int off;
int x, y; int x, y;
int start_x = 1280 / 2 - currMsgBox.width / 2; int start_x = 1280 / 2 - currMsgBox.width / 2;
@ -87,7 +85,7 @@ void menuDrawMsgBox() {
color_t curr_color; color_t curr_color;
color_t border_color; color_t border_color;
int sep_start_y = currMsgBox.height + layoutobj->posStart[1]; int sep_start_y = currMsgBox.height - 80;
int border_thickness = 6; int border_thickness = 6;
int shadow_start_y, shadow_y; int shadow_start_y, shadow_y;
@ -123,7 +121,7 @@ void menuDrawMsgBox() {
curr_color = border_color; curr_color = border_color;
} }
} }
else if (msgboxNetloaderProgressEnabled && y > sep_start_y && x < progress_width) { else if (msgboxNetloaderProgressEnabled && y > currMsgBox.height - 80 && x < progress_width) {
curr_color = themeCurrent.progressBarColor; curr_color = themeCurrent.progressBarColor;
} }
@ -137,11 +135,10 @@ void menuDrawMsgBox() {
x = GetTextXCoordinate(interuiregular18, start_x + (currMsgBox.width / 2), textptr, 'c'); x = GetTextXCoordinate(interuiregular18, start_x + (currMsgBox.width / 2), textptr, 'c');
if (text_width < currMsgBox.width && text_height < sep_start_y) { if (text_width < currMsgBox.width && text_height < sep_start_y) {
DrawText(interuiregular18, x, start_y + (sep_start_y - text_height) / 2, themeCurrent.textColor, textptr); DrawText(interuiregular18, x, start_y + (currMsgBox.height - text_height - 80) / 2, themeCurrent.textColor, textptr);
} }
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MsgBoxBottomText]; y = start_y + 245 + 26;
y = start_y + currMsgBox.height + layoutobj->posStart[1];
if (!msgboxNetloaderEnabled) { if (!msgboxNetloaderEnabled) {
x = GetTextXCoordinate(interuimedium20, start_x + (currMsgBox.width / 2), textGetString(StrId_MsgBox_OK), 'c'); x = GetTextXCoordinate(interuimedium20, start_x + (currMsgBox.width / 2), textGetString(StrId_MsgBox_OK), 'c');

View File

@ -368,7 +368,7 @@ static int decompress(int sock, FILE *fh, size_t filesize) {
int loadnro(menuEntry_s *me, int sock, struct in_addr remote) { int loadnro(menuEntry_s *me, int sock, struct in_addr remote) {
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
int len, namelen, filelen; int len, namelen, filelen;
char filepath[PATH_MAX+1]; char filename[PATH_MAX+1];
len = recvall(sock, &namelen, 4, 0); len = recvall(sock, &namelen, 4, 0);
if (len != 4) { if (len != 4) {
@ -376,19 +376,19 @@ int loadnro(menuEntry_s *me, int sock, struct in_addr remote) {
return -1; return -1;
} }
if (namelen >= sizeof(filepath)-1) { if (namelen >= sizeof(filename)-1) {
netloader_error("File-path length is too large",errno); netloader_error("Filename length is too large",errno);
return -1; return -1;
} }
len = recvall(sock, filepath, namelen, 0); len = recvall(sock, filename, namelen, 0);
if (len != namelen) { if (len != namelen) {
netloader_error("Error getting file-path", errno); netloader_error("Error getting filename", errno);
return -1; return -1;
} }
filepath[namelen] = 0; filename[namelen] = 0;
len = recvall(sock, &filelen, 4, 0); len = recvall(sock, &filelen, 4, 0);
@ -403,34 +403,21 @@ int loadnro(menuEntry_s *me, int sock, struct in_addr remote) {
int response = 0; int response = 0;
sanitisePath(filepath); sanitisePath(filename);
snprintf(me->path, sizeof(me->path)-1, "%s%s%s", menuGetRootPath(), DIRECTORY_SEPARATOR, filepath); snprintf(me->path, sizeof(me->path)-1, "%s%s%s", menuGetRootPath(), DIRECTORY_SEPARATOR, filename);
me->path[PATH_MAX] = 0;
// make sure it's terminated // make sure it's terminated
me->path[sizeof(me->path)-1] = 0; me->path[PATH_MAX] = 0;
strncpy(filepath, me->path, sizeof(filepath)-1); // menuEntryLoad() below will overwrite me->path, so copy me->path to filepath and use that instead.
filepath[sizeof(filepath)-1] = 0;
argData_s* ad = &me->args; argData_s* ad = &me->args;
ad->dst = (char*)&ad->buf[1]; ad->dst = (char*)&ad->buf[1];
ad->nxlink_host = remote; ad->nxlink_host = remote;
const char* ext = getExtension(me->path);
if (ext && strcasecmp(ext, ".nro")==0)
launchAddArg(ad, me->path); launchAddArg(ad, me->path);
else {
me->type = ENTRY_TYPE_FILE_OTHER; // Handle fileassoc when extension isn't .nro.
if (!menuEntryLoad(me, "", false, false)) {
response = -3;
errno = EINVAL;
netloader_error("File-extension/filename not recognized",0);
}
menuEntryFree(me, false); // We don't need any of the buffers which may have been allocated.
}
#ifndef _WIN32 #ifndef _WIN32
if (response == 0) { int fd = open(me->path,O_CREAT|O_WRONLY, ACCESSPERMS);
int fd = open(filepath,O_CREAT|O_WRONLY, ACCESSPERMS);
if (fd < 0) { if (fd < 0) {
response = -1; response = -1;
@ -442,18 +429,16 @@ int loadnro(menuEntry_s *me, int sock, struct in_addr remote) {
} }
close(fd); close(fd);
} }
}
#endif #endif
FILE *file = NULL; FILE *file = NULL;
if (response == 0) { if (response == 0) file = fopen(me->path,"wb");
file = fopen(filepath,"wb");
if(file == NULL) { if(NULL == file) {
perror("file"); perror("file");
response = -1; response = -1;
} }
}
send(sock,(char *)&response,sizeof(response),0); send(sock,(char *)&response,sizeof(response),0);
@ -464,14 +449,12 @@ int loadnro(menuEntry_s *me, int sock, struct in_addr remote) {
netloader_error("Failed to allocate memory",ENOMEM); netloader_error("Failed to allocate memory",ENOMEM);
response = -1; response = -1;
} }
else { else
memset(writebuffer, 0, FILE_BUFFER_SIZE);
setvbuf(file,writebuffer,_IOFBF, FILE_BUFFER_SIZE); setvbuf(file,writebuffer,_IOFBF, FILE_BUFFER_SIZE);
} }
}
if (response == 0 ) { if (response == 0 ) {
//printf("transferring %s\n%d bytes.\n", filepath, filelen); //printf("transferring %s\n%d bytes.\n", filename, filelen);
if (decompress(sock,file,filelen)==Z_OK) { if (decompress(sock,file,filelen)==Z_OK) {
int netloaded_cmdlen = 0; int netloaded_cmdlen = 0;
@ -494,7 +477,7 @@ int loadnro(menuEntry_s *me, int sock, struct in_addr remote) {
} }
if (response == 0 ) { if (response == 0 ) {
if ((me->args.dst+netloaded_cmdlen) >= (char*)(me->args.buf + sizeof(me->args.buf))) netloaded_cmdlen = (uintptr_t)me->args.buf + sizeof(me->args.buf)-1 - (uintptr_t)me->args.dst; if (netloaded_cmdlen > sizeof(me->args.buf)-1) netloaded_cmdlen = sizeof(me->args.buf)-1;
len = recvall(sock,me->args.dst, netloaded_cmdlen,0); len = recvall(sock,me->args.dst, netloaded_cmdlen,0);
@ -516,15 +499,14 @@ int loadnro(menuEntry_s *me, int sock, struct in_addr remote) {
} else { } else {
response = -1; response = -1;
} }
}
if (file) {
fflush(file); fflush(file);
fclose(file); fclose(file);
}
if (response == -1) unlink(filepath);
free(writebuffer); free(writebuffer);
if (response == -1) unlink(me->path);
}
return response; return response;
} }
@ -567,15 +549,7 @@ int netloader_activate(void) {
return -1; return -1;
} }
uint32_t tmpval=1; int rc = bind(netloader_listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
int rc = setsockopt(netloader_listenfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&tmpval, sizeof(tmpval));
if(rc != 0)
{
netloader_socket_error("setsockopt");
return -1;
}
rc = bind(netloader_listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
if(rc != 0) if(rc != 0)
{ {
netloader_socket_error("bind"); netloader_socket_error("bind");
@ -727,10 +701,6 @@ Result netloaderInit(void) {
#ifdef __SWITCH__ #ifdef __SWITCH__
rc = socketInitializeDefault(); rc = socketInitializeDefault();
if (R_SUCCEEDED(rc)) {
rc = nifmInitialize(NifmServiceType_User);
if (R_FAILED(rc)) socketExit();
}
#endif #endif
#ifdef __WIN32__ #ifdef __WIN32__
@ -757,7 +727,6 @@ void netloaderExit(void) {
mtx_destroy(&netloader_mtx); mtx_destroy(&netloader_mtx);
#ifdef __SWITCH__ #ifdef __SWITCH__
nifmExit();
socketExit(); socketExit();
#endif #endif

View File

@ -10,8 +10,6 @@ static bool s_statusExit;
static bool s_statusReady; static bool s_statusReady;
static bool s_statusNetFlag; static bool s_statusNetFlag;
static AssetId s_statusNetAssetId; static AssetId s_statusNetAssetId;
static bool s_statusTemperatureFlag;
static s32 s_statusTemperature;
// This uses netstatusGetDetails from a dedicated thread, since nifmGetInternetConnectionStatus can block for a few seconds. // This uses netstatusGetDetails from a dedicated thread, since nifmGetInternetConnectionStatus can block for a few seconds.
@ -20,13 +18,8 @@ static int statusThreadProc(void* unused)
mtx_lock(&s_statusMtx); mtx_lock(&s_statusMtx);
struct timespec timeout = {0}; struct timespec timeout = {0};
bool tmpflag=0; bool tmpflag;
bool thermalflag=0;
bool thermal_initialized=0;
AssetId tmpid; AssetId tmpid;
s32 temperature;
thermal_initialized = thermalstatusInit();
clock_gettime(CLOCK_MONOTONIC, &timeout); clock_gettime(CLOCK_MONOTONIC, &timeout);
timeout.tv_sec++; timeout.tv_sec++;
@ -39,16 +32,12 @@ static int statusThreadProc(void* unused)
break; break;
tmpflag = netstatusGetDetails(&tmpid); tmpflag = netstatusGetDetails(&tmpid);
if (thermal_initialized) thermalflag = thermalstatusGetDetails(&temperature);
mtx_lock(&s_statusAccessMtx); mtx_lock(&s_statusAccessMtx);
s_statusNetFlag = tmpflag; s_statusNetFlag = tmpflag;
s_statusNetAssetId = tmpid; s_statusNetAssetId = tmpid;
s_statusTemperatureFlag = thermalflag;
s_statusTemperature = temperature;
s_statusReady = 1; s_statusReady = 1;
mtx_unlock(&s_statusAccessMtx); mtx_unlock(&s_statusAccessMtx);
@ -59,12 +48,10 @@ static int statusThreadProc(void* unused)
mtx_unlock(&s_statusMtx); mtx_unlock(&s_statusMtx);
if (thermal_initialized) thermalstatusExit();
return 0; return 0;
} }
bool statusGet(bool *netstatusFlag, AssetId *netstatusAssetId, bool *temperatureFlag, s32 *temperature) { bool statusGet(bool *netstatusFlag, AssetId *netstatusAssetId) {
if (!s_statusReady) return 0; if (!s_statusReady) return 0;
mtx_lock(&s_statusAccessMtx); mtx_lock(&s_statusAccessMtx);
@ -72,9 +59,6 @@ bool statusGet(bool *netstatusFlag, AssetId *netstatusAssetId, bool *temperature
*netstatusFlag = s_statusNetFlag; *netstatusFlag = s_statusNetFlag;
*netstatusAssetId = s_statusNetAssetId; *netstatusAssetId = s_statusNetAssetId;
*temperatureFlag = s_statusTemperatureFlag;
*temperature = s_statusTemperature;
mtx_unlock(&s_statusAccessMtx); mtx_unlock(&s_statusAccessMtx);
return 1; return 1;

View File

@ -3,5 +3,5 @@
bool statusInit(void); bool statusInit(void);
void statusExit(void); void statusExit(void);
bool statusGet(bool *netstatusFlag, AssetId *netstatusAssetId, bool *temperatureFlag, s32 *temperature); bool statusGet(bool *netstatusFlag, AssetId *netstatusAssetId);

View File

@ -10,14 +10,14 @@ static int s_textLang = 1;
Result textInit(void) { Result textInit(void) {
#ifdef __SWITCH__ #ifdef __SWITCH__
SetLanguage Language=SetLanguage_ENUS; s32 Language=0;
s_textLang = Language; s_textLang = SetLanguage_ENUS;
Result rc = setInitialize(); Result rc = setInitialize();
if (R_SUCCEEDED(rc)) rc = setGetSystemLanguage(&s_textLanguageCode); if (R_SUCCEEDED(rc)) rc = setGetSystemLanguage(&s_textLanguageCode);
if (R_SUCCEEDED(rc)) rc = setMakeLanguage(s_textLanguageCode, &Language); if (R_SUCCEEDED(rc)) rc = setMakeLanguage(s_textLanguageCode, &Language);
//if (R_SUCCEEDED(rc) && Language < 17) s_textLang = Language;//TODO: Re-enable this once language.c supports all used languages. //if (R_SUCCEEDED(rc) && Language < 16) s_textLang = Language;//TODO: Re-enable this once language.c supports all used languages.
setExit(); setExit();
if (R_FAILED(rc)) return rc; if (R_FAILED(rc)) return rc;
#else #else

View File

@ -1,5 +1,4 @@
#include "theme.h" #include "theme.h"
#include <physfs.h>
theme_t themeCurrent; theme_t themeCurrent;
ThemePreset themeGlobalPreset; ThemePreset themeGlobalPreset;
@ -11,83 +10,6 @@ bool colorFromSetting(config_setting_t *rgba, color_t *col) {
return true; return true;
} }
bool intElemFromSetting(config_setting_t *setting, int *out, size_t count) {
if (!setting || config_setting_length(setting) < count)
return false;
for (size_t i=0; i<count; i++) {
out[i] = config_setting_get_int_elem(setting, i);
}
return true;
}
bool layoutObjectFromSetting(config_setting_t *layout_setting, ThemeLayoutObject *obj, bool ignore_cfg_visible) {
int tmp=0;
ThemeLayoutObject tmpobj={0};
if (!layout_setting)
return false;
memcpy(tmpobj.posStart, obj->posStart, sizeof(obj->posStart));
memcpy(tmpobj.posEnd, obj->posEnd, sizeof(obj->posEnd));
memcpy(tmpobj.size, obj->size, sizeof(obj->size));
if (config_setting_lookup_bool(layout_setting, "visible", &tmp)==CONFIG_TRUE)
tmpobj.visible = tmp;
else
tmpobj.visible = obj->visible;
if (config_setting_lookup_bool(layout_setting, "posType", &tmp)==CONFIG_TRUE)
tmpobj.posType = tmp;
else
tmpobj.posType = obj->posType;
intElemFromSetting(config_setting_lookup(layout_setting, "posStart"), tmpobj.posStart, 2);
intElemFromSetting(config_setting_lookup(layout_setting, "posEnd"), tmpobj.posEnd, 2);
intElemFromSetting(config_setting_lookup(layout_setting, "size"), tmpobj.size, 2);
if (!tmpobj.posType && (tmpobj.posStart[0] < 0 || tmpobj.posStart[1] < 0 || tmpobj.posEnd[0] < 0 || tmpobj.posEnd[1] < 0))
return false;
if (tmpobj.size[0] < 0 || tmpobj.size[1] < 0)
return false;
obj->posStart[0] = tmpobj.posStart[0];
obj->posStart[1] = tmpobj.posStart[1];
obj->posEnd[0] = tmpobj.posEnd[0];
obj->posEnd[1] = tmpobj.posEnd[1];
if (!ignore_cfg_visible) obj->visible = tmpobj.visible;
obj->posType = tmpobj.posType;
obj->size[0] = tmpobj.size[0];
obj->size[1] = tmpobj.size[1];
return true;
}
bool assetObjectFromSetting(config_setting_t *asset_setting, AssetId id, ThemeLayoutObject *layoutobj) {
int imageSize[2]={0};
const char *path = NULL;
char tmp_path[PATH_MAX];
if (!asset_setting)
return false;
if (config_setting_lookup_string(asset_setting, "path", &path)==CONFIG_FALSE)
return false;
if (!intElemFromSetting(config_setting_lookup(asset_setting, "imageSize"), imageSize, 2))
return false;
if (imageSize[0] <= 0 || imageSize[1] <= 0 || imageSize[0] > 1280 || imageSize[1] > 720)
return false;
if (layoutobj && (imageSize[0] != layoutobj->imageSize[0] || imageSize[1] != layoutobj->imageSize[1]))
return false;
memset(tmp_path, 0, sizeof(tmp_path));
snprintf(tmp_path, sizeof(tmp_path)-1, "theme/%s", path);
return assetsLoadData(id, tmp_path, imageSize);
}
void themeStartup(ThemePreset preset) { void themeStartup(ThemePreset preset) {
themeGlobalPreset = preset; themeGlobalPreset = preset;
theme_t themeLight = (theme_t) { theme_t themeLight = (theme_t) {
@ -98,7 +20,6 @@ void themeStartup(ThemePreset preset) {
.backWaveColor = MakeColor(154, 171, 255, 255), .backWaveColor = MakeColor(154, 171, 255, 255),
.backgroundColor = MakeColor(233, 236, 241, 255), .backgroundColor = MakeColor(233, 236, 241, 255),
.highlightColor = MakeColor(91, 237, 224, 255), .highlightColor = MakeColor(91, 237, 224, 255),
.highlightGradientEdgeColor = MakeColor(91,176,224,255),
.separatorColor = MakeColor(219, 218, 219, 255), .separatorColor = MakeColor(219, 218, 219, 255),
.borderColor = MakeColor(255,255,255,255), .borderColor = MakeColor(255,255,255,255),
.borderTextColor = MakeColor(64,64,64,255), .borderTextColor = MakeColor(64,64,64,255),
@ -112,6 +33,7 @@ void themeStartup(ThemePreset preset) {
.buttonMText = "\uE0F0", .buttonMText = "\uE0F0",
.labelStarOnText = "\u2605", .labelStarOnText = "\u2605",
.labelStarOffText = "\u2606", .labelStarOffText = "\u2606",
.hbmenuLogoImage = assetsGetDataBuffer(AssetId_hbmenu_logo_light),
}; };
theme_t themeDark = (theme_t) { theme_t themeDark = (theme_t) {
@ -122,7 +44,6 @@ void themeStartup(ThemePreset preset) {
.backWaveColor = MakeColor(73, 103, 169, 255), .backWaveColor = MakeColor(73, 103, 169, 255),
.backgroundColor = MakeColor(45, 45, 50, 255), .backgroundColor = MakeColor(45, 45, 50, 255),
.highlightColor = MakeColor(91, 237, 224, 255), .highlightColor = MakeColor(91, 237, 224, 255),
.highlightGradientEdgeColor = MakeColor(91,176,224,255),
.separatorColor = MakeColor(219, 218, 219, 255), .separatorColor = MakeColor(219, 218, 219, 255),
.borderColor = MakeColor(255,255,255,255), .borderColor = MakeColor(255,255,255,255),
.borderTextColor = MakeColor(64,64,64,255), .borderTextColor = MakeColor(64,64,64,255),
@ -136,276 +57,7 @@ void themeStartup(ThemePreset preset) {
.buttonMText = "\uE0B4", .buttonMText = "\uE0B4",
.labelStarOnText = "\u2605", .labelStarOnText = "\u2605",
.labelStarOffText = "\u2606", .labelStarOffText = "\u2606",
}; .hbmenuLogoImage = assetsGetDataBuffer(AssetId_hbmenu_logo_dark),
theme_t themeCommon = {
.layoutObjects = {
[ThemeLayoutId_Logo] = {
.visible = true,
.posType = false,
.posStart = {40, 20},
},
[ThemeLayoutId_HbmenuVersion] = {
.visible = true,
.posType = false,
.posStart = {184, 46 + 18},
.font = interuiregular14,
},
[ThemeLayoutId_LoaderInfo] = {
.visible = true,
.posType = true,
.posStart = {43, 46 + 18 + 20},
.posEnd = {184},
.font = interuiregular14,
},
[ThemeLayoutId_AttentionText] = {
.visible = true,
.posType = true,
.posStart = {-32, 46 + 18},
.font = interuimedium30,
},
[ThemeLayoutId_LogInfo] = {
.visible = true,
.posType = false,
.posStart = {180 + 256, 46 + 16 + 18},
.font = interuiregular14,
},
[ThemeLayoutId_InfoMsg] = {
.visible = true,
.posType = false,
.posStart = {64, 128 + 18},
.font = interuiregular14,
},
[ThemeLayoutId_MenuPath] = {
.visible = true,
.posType = false,
.posStart = {40, 720 - 47 + 24},
.size = {380},
.font = interuiregular18,
},
[ThemeLayoutId_MenuTypeMsg] = {
.visible = true,
.posType = false,
.posStart = {1180, 30 + 26 + 32 + 20},
.font = interuiregular18,
},
[ThemeLayoutId_MsgBoxSeparator] = {
.visible = true,
.posType = true,
.posStart = {0, -80},
},
[ThemeLayoutId_MsgBoxBottomText] = {
.visible = true,
.posType = true,
.posStart = {0, -29},
},
// ThemeLayoutId_BackgroundImage is not set with the defaults.
[ThemeLayoutId_BackWave] = {
.visible = true,
.posType = true,
.size = {0, 295},
},
[ThemeLayoutId_MiddleWave] = {
.visible = true,
.posType = true,
.size = {0, 290},
},
[ThemeLayoutId_FrontWave] = {
.visible = true,
.posType = true,
.size = {0, 280},
},
[ThemeLayoutId_ButtonA] = {
.visible = true,
.posType = false,
.posStart = {1280 - 126 - 30 - 32, 720 - 47 + 24},
.touchSize = {36, 25},
.font = fontscale7,
},
[ThemeLayoutId_ButtonAText] = {
.visible = true,
.posType = false,
.posStart = {1280 - 90 - 30 - 32, 720 - 47 + 24},
.touchSize = {0, 25},
.font = interuiregular18,
},
[ThemeLayoutId_ButtonB] = {
.visible = true,
.posType = true,
.posStart = {-36, 0},
.posEnd = {0},
.touchSize = {36, 25},
.font = fontscale7,
},
[ThemeLayoutId_ButtonBText] = {
.visible = true,
.posType = true,
.posStart = {-90, 0},
.touchSize = {0, 32},
.font = interuiregular18,
},
[ThemeLayoutId_ButtonY] = {
.visible = true,
.posType = true,
.posStart = {-36, 0},
.font = fontscale7,
},
[ThemeLayoutId_ButtonYText] = {
.visible = true,
.posType = true,
.posStart = {-32, 0},
.font = interuiregular18,
},
[ThemeLayoutId_ButtonM] = {
.visible = true,
.posType = true,
.posStart = {-36, 0},
.font = fontscale7,
},
[ThemeLayoutId_ButtonMText] = {
.visible = true,
.posType = true,
.posStart = {-32, 0},
.font = interuiregular18,
},
[ThemeLayoutId_ButtonX] = {
.visible = true,
.posType = true,
.posStart = {-36, 0},
.touchSize = {36, 25},
.font = fontscale7,
},
[ThemeLayoutId_ButtonXText] = {
.visible = true,
.posType = true,
.posStart = {-40 + 8, 0},
.touchSize = {0, 25},
.font = interuiregular18,
},
[ThemeLayoutId_NetworkIcon] = {
.visible = true,
.posType = true,
.posStart = {0, 0 + 47 + 10 + 3},
},
[ThemeLayoutId_BatteryCharge] = {
.visible = true,
.posType = false,
.posStart = {1180 - 10 - 24 - 8, 0 + 47 + 10 + 21 + 4},
.font = interuiregular14,
},
[ThemeLayoutId_BatteryIcon] = {
.visible = true,
.posType = false,
.posStart = {1180 - 8 - 24 - 8, 0 + 47 + 10 + 6},
},
[ThemeLayoutId_ChargingIcon] = {
.visible = true,
.posType = false,
.posStart = {1180 - 20, 0 + 47 + 10 + 6},
},
[ThemeLayoutId_Status] = {
.visible = true,
.posType = false,
.posStart = {1180, 0 + 47 + 10},
.font = interuimedium20,
},
[ThemeLayoutId_Temperature] = {
.visible = true,
.posType = false,
.posStart = {1180 + 4, 0 + 47 + 10 + + 21 + 6},
.font = interuiregular14,
},
[ThemeLayoutId_MenuList] = {
.visible = true,
.posType = false,
.posStart = {29, 720 - 100 - 145},
.posEnd = {140 + 30, 0},
.size = {140, 140 + 32},
},
[ThemeLayoutId_MenuListTiles] = {
.visible = true,
.posType = true,
.posEnd = {7, 0},
.size = {0, 0},
},
[ThemeLayoutId_MenuListIcon] = {
.visible = true,
.posType = true,
.posStart = {0, 32},
.size = {140, 140},
.imageSize = {256, 256},
},
[ThemeLayoutId_MenuListName] = {
.visible = true,
.posType = true,
.posStart = {4, 4 + 18},
.size = {140 - 32, 0},
.font = interuiregular14,
},
[ThemeLayoutId_MenuActiveEntryIcon] = {
.visible = true,
.posType = false,
.posStart = {117, 100+10},
.size = {256, 256},
.imageSize = {256, 256},
},
[ThemeLayoutId_MenuActiveEntryName] = {
.visible = true,
.posType = false,
.posStart = {1280 - 790, 135+10 + 39},
.size = {790 - 120, 0},
.font = interuimedium30,
},
[ThemeLayoutId_MenuActiveEntryAuthor] = {
.visible = true,
.posType = false,
.posStart = {1280 - 790, 135+10 + 28 + 30 + 18},
.font = interuiregular14,
},
[ThemeLayoutId_MenuActiveEntryVersion] = {
.visible = true,
.posType = false,
.posStart = {1280 - 790, 135+10 + 28 + 30 + 18 + 6 + 18},
.font = interuiregular14,
},
},
}; };
char themePath[PATH_MAX] = {0}; char themePath[PATH_MAX] = {0};
@ -414,55 +66,14 @@ void themeStartup(ThemePreset preset) {
theme_t *themeDefault; theme_t *themeDefault;
config_t cfg = {0}; config_t cfg = {0};
config_init(&cfg); config_init(&cfg);
config_setting_t *theme = NULL, *layout = NULL, *assets = NULL; config_setting_t *theme = NULL;
color_t text, logoColor={0}, attentionText, frontWave, middleWave, backWave, background, highlight, highlightGradientEdgeColor, separator, borderColor, borderTextColor, progressBarColor; color_t text, attentionText, frontWave, middleWave, backWave, background, highlight, separator, borderColor, borderTextColor, progressBarColor;
int waveBlending; int waveBlending;
const char *AText, *BText, *XText, *YText, *PText, *MText, *starOnText, *starOffText; const char *AText, *BText, *XText, *YText, *PText, *MText, *starOnText, *starOffText;
bool logoColor_set = false;
bool good_cfg = false; bool good_cfg = false;
#ifdef __SWITCH__
bool is_romfs = false;
#endif
bool is_archive = false;
const char* theme_archive_path = NULL;
assetsClearTheme(); if(themePath[0]!=0)
good_cfg = config_read_file(&cfg, themePath);
if(themePath[0]!=0) {
const char* cfg_path = themePath;
const char* ext = getExtension(themePath);
#ifdef __SWITCH__
if (strcasecmp(ext, ".romfs")==0) {
if (R_FAILED(romfsMountFromFsdev(themePath, 0, "theme")))
cfg_path = NULL;
else {
is_romfs = true;
cfg_path = "theme:/theme.cfg";
theme_archive_path = "theme:/";
}
}
#endif
if (strcasecmp(ext, ".romfs")!=0 && strcasecmp(ext, ".cfg")!=0) {
theme_archive_path = themePath;
}
if (theme_archive_path) {
if (!PHYSFS_mount(theme_archive_path, "theme", 0)) cfg_path = NULL;
else {
is_archive = true;
cfg_path = "theme/theme.cfg";
}
}
if (cfg_path) {
if (!is_archive) good_cfg = config_read_file(&cfg, cfg_path);
else {
u8 *cfg_buf = NULL;
good_cfg = assetsPhysfsReadFile(cfg_path, &cfg_buf, NULL, true);
if (good_cfg) good_cfg = config_read_string(&cfg, (char*)cfg_buf);
free(cfg_buf);
}
}
}
switch (preset) { switch (preset) {
case THEME_PRESET_LIGHT: case THEME_PRESET_LIGHT:
@ -483,8 +94,6 @@ void themeStartup(ThemePreset preset) {
if (theme != NULL) { if (theme != NULL) {
if (!colorFromSetting(config_setting_lookup(theme, "textColor"), &text)) if (!colorFromSetting(config_setting_lookup(theme, "textColor"), &text))
text = themeDefault->textColor; text = themeDefault->textColor;
if (colorFromSetting(config_setting_lookup(theme, "logoColor"), &logoColor))
logoColor_set = true;
if (!colorFromSetting(config_setting_lookup(theme, "attentionTextColor"), &attentionText)) if (!colorFromSetting(config_setting_lookup(theme, "attentionTextColor"), &attentionText))
attentionText = themeDefault->attentionTextColor; attentionText = themeDefault->attentionTextColor;
if (!colorFromSetting(config_setting_lookup(theme, "frontWaveColor"), &frontWave)) if (!colorFromSetting(config_setting_lookup(theme, "frontWaveColor"), &frontWave))
@ -497,8 +106,6 @@ void themeStartup(ThemePreset preset) {
background = themeDefault->backgroundColor; background = themeDefault->backgroundColor;
if (!colorFromSetting(config_setting_lookup(theme, "highlightColor"), &highlight)) if (!colorFromSetting(config_setting_lookup(theme, "highlightColor"), &highlight))
highlight = themeDefault->highlightColor; highlight = themeDefault->highlightColor;
if (!colorFromSetting(config_setting_lookup(theme, "highlightGradientEdgeColor"), &highlightGradientEdgeColor))
highlightGradientEdgeColor = themeDefault->highlightGradientEdgeColor;
if (!colorFromSetting(config_setting_lookup(theme, "separatorColor"), &separator)) if (!colorFromSetting(config_setting_lookup(theme, "separatorColor"), &separator))
separator = themeDefault->separatorColor; separator = themeDefault->separatorColor;
if (!colorFromSetting(config_setting_lookup(theme, "borderColor"), &borderColor)) if (!colorFromSetting(config_setting_lookup(theme, "borderColor"), &borderColor))
@ -527,129 +134,34 @@ void themeStartup(ThemePreset preset) {
starOffText = themeDefault->labelStarOffText; starOffText = themeDefault->labelStarOffText;
themeCurrent = (theme_t) { themeCurrent = (theme_t) {
.textColor = text, .textColor = text,
.logoColor = logoColor,
.attentionTextColor = attentionText, .attentionTextColor = attentionText,
.frontWaveColor = frontWave, .frontWaveColor = frontWave,
.middleWaveColor = middleWave, .middleWaveColor = middleWave,
.backWaveColor = backWave, .backWaveColor = backWave,
.backgroundColor = background, .backgroundColor = background,
.highlightColor = highlight, .highlightColor = highlight,
.highlightGradientEdgeColor = highlightGradientEdgeColor,
.separatorColor = separator, .separatorColor = separator,
.borderColor = borderColor, .borderColor = borderColor,
.borderTextColor = borderTextColor, .borderTextColor = borderTextColor,
.progressBarColor = progressBarColor, .progressBarColor = progressBarColor,
.logoColor_set = logoColor_set,
.enableWaveBlending = waveBlending, .enableWaveBlending = waveBlending,
.hbmenuLogoImage = themeDefault->hbmenuLogoImage
}; };
strncpy(themeCurrent.buttonAText, AText, sizeof(themeCurrent.buttonAText)); strncpy(themeCurrent.buttonAText, AText, sizeof(themeCurrent.buttonAText)-1);
themeCurrent.buttonAText[sizeof(themeCurrent.buttonAText)-1] = 0; strncpy(themeCurrent.buttonBText, BText, sizeof(themeCurrent.buttonBText)-1);
strncpy(themeCurrent.buttonBText, BText, sizeof(themeCurrent.buttonBText)); strncpy(themeCurrent.buttonXText, XText, sizeof(themeCurrent.buttonXText)-1);
themeCurrent.buttonBText[sizeof(themeCurrent.buttonBText)-1] = 0; strncpy(themeCurrent.buttonYText, YText, sizeof(themeCurrent.buttonYText)-1);
strncpy(themeCurrent.buttonXText, XText, sizeof(themeCurrent.buttonXText)); strncpy(themeCurrent.buttonPText, PText, sizeof(themeCurrent.buttonPText)-1);
themeCurrent.buttonXText[sizeof(themeCurrent.buttonXText)-1] = 0; strncpy(themeCurrent.buttonMText, MText, sizeof(themeCurrent.buttonMText)-1);
strncpy(themeCurrent.buttonYText, YText, sizeof(themeCurrent.buttonYText)); strncpy(themeCurrent.labelStarOffText, starOffText, sizeof(themeCurrent.labelStarOffText)-1);
themeCurrent.buttonYText[sizeof(themeCurrent.buttonYText)-1] = 0; strncpy(themeCurrent.labelStarOnText, starOnText, sizeof(themeCurrent.labelStarOnText)-1);
strncpy(themeCurrent.buttonPText, PText, sizeof(themeCurrent.buttonPText));
themeCurrent.buttonPText[sizeof(themeCurrent.buttonPText)-1] = 0;
strncpy(themeCurrent.buttonMText, MText, sizeof(themeCurrent.buttonMText));
themeCurrent.buttonMText[sizeof(themeCurrent.buttonMText)-1] = 0;
strncpy(themeCurrent.labelStarOnText, starOnText, sizeof(themeCurrent.labelStarOnText));
themeCurrent.labelStarOnText[sizeof(themeCurrent.labelStarOnText)-1] = 0;
strncpy(themeCurrent.labelStarOffText, starOffText, sizeof(themeCurrent.labelStarOffText));
themeCurrent.labelStarOffText[sizeof(themeCurrent.labelStarOffText)-1] = 0;
} else { } else {
themeCurrent = *themeDefault; themeCurrent = *themeDefault;
} }
memcpy(themeCurrent.layoutObjects, themeCommon.layoutObjects, sizeof(themeCommon.layoutObjects));
layout = config_lookup(&cfg, "layout");
if (layout != NULL) {
layoutObjectFromSetting(config_setting_lookup(layout, "logo"), &themeCurrent.layoutObjects[ThemeLayoutId_Logo], true);
layoutObjectFromSetting(config_setting_lookup(layout, "hbmenuVersion"), &themeCurrent.layoutObjects[ThemeLayoutId_HbmenuVersion], true);
layoutObjectFromSetting(config_setting_lookup(layout, "loaderInfo"), &themeCurrent.layoutObjects[ThemeLayoutId_LoaderInfo], true);
layoutObjectFromSetting(config_setting_lookup(layout, "attentionText"), &themeCurrent.layoutObjects[ThemeLayoutId_AttentionText], true);
layoutObjectFromSetting(config_setting_lookup(layout, "logInfo"), &themeCurrent.layoutObjects[ThemeLayoutId_LogInfo], true);
layoutObjectFromSetting(config_setting_lookup(layout, "infoMsg"), &themeCurrent.layoutObjects[ThemeLayoutId_InfoMsg], true);
layoutObjectFromSetting(config_setting_lookup(layout, "menuPath"), &themeCurrent.layoutObjects[ThemeLayoutId_MenuPath], false);
layoutObjectFromSetting(config_setting_lookup(layout, "menuTypeMsg"), &themeCurrent.layoutObjects[ThemeLayoutId_MenuTypeMsg], false);
layoutObjectFromSetting(config_setting_lookup(layout, "msgBoxSeparator"), &themeCurrent.layoutObjects[ThemeLayoutId_MsgBoxSeparator], false);
layoutObjectFromSetting(config_setting_lookup(layout, "msgBoxBottomText"), &themeCurrent.layoutObjects[ThemeLayoutId_MsgBoxBottomText], false);
layoutObjectFromSetting(config_setting_lookup(layout, "backgroundImage"), &themeCurrent.layoutObjects[ThemeLayoutId_BackgroundImage], false);
layoutObjectFromSetting(config_setting_lookup(layout, "backWave"), &themeCurrent.layoutObjects[ThemeLayoutId_BackWave], false);
layoutObjectFromSetting(config_setting_lookup(layout, "middleWave"), &themeCurrent.layoutObjects[ThemeLayoutId_MiddleWave], false);
layoutObjectFromSetting(config_setting_lookup(layout, "frontWave"), &themeCurrent.layoutObjects[ThemeLayoutId_FrontWave], false);
layoutObjectFromSetting(config_setting_lookup(layout, "buttonA"), &themeCurrent.layoutObjects[ThemeLayoutId_ButtonA], false);
layoutObjectFromSetting(config_setting_lookup(layout, "buttonAText"), &themeCurrent.layoutObjects[ThemeLayoutId_ButtonAText], false);
layoutObjectFromSetting(config_setting_lookup(layout, "buttonB"), &themeCurrent.layoutObjects[ThemeLayoutId_ButtonB], false);
layoutObjectFromSetting(config_setting_lookup(layout, "buttonBText"), &themeCurrent.layoutObjects[ThemeLayoutId_ButtonBText], false);
layoutObjectFromSetting(config_setting_lookup(layout, "buttonY"), &themeCurrent.layoutObjects[ThemeLayoutId_ButtonY], false);
layoutObjectFromSetting(config_setting_lookup(layout, "buttonYText"), &themeCurrent.layoutObjects[ThemeLayoutId_ButtonYText], false);
layoutObjectFromSetting(config_setting_lookup(layout, "buttonM"), &themeCurrent.layoutObjects[ThemeLayoutId_ButtonM], false);
layoutObjectFromSetting(config_setting_lookup(layout, "buttonMText"), &themeCurrent.layoutObjects[ThemeLayoutId_ButtonMText], false);
layoutObjectFromSetting(config_setting_lookup(layout, "buttonX"), &themeCurrent.layoutObjects[ThemeLayoutId_ButtonX], false);
layoutObjectFromSetting(config_setting_lookup(layout, "buttonXText"), &themeCurrent.layoutObjects[ThemeLayoutId_ButtonXText], false);
layoutObjectFromSetting(config_setting_lookup(layout, "networkIcon"), &themeCurrent.layoutObjects[ThemeLayoutId_NetworkIcon], false);
layoutObjectFromSetting(config_setting_lookup(layout, "batteryCharge"), &themeCurrent.layoutObjects[ThemeLayoutId_BatteryCharge], false);
layoutObjectFromSetting(config_setting_lookup(layout, "batteryIcon"), &themeCurrent.layoutObjects[ThemeLayoutId_BatteryIcon], false);
layoutObjectFromSetting(config_setting_lookup(layout, "chargingIcon"), &themeCurrent.layoutObjects[ThemeLayoutId_ChargingIcon], false);
layoutObjectFromSetting(config_setting_lookup(layout, "status"), &themeCurrent.layoutObjects[ThemeLayoutId_Status], false);
layoutObjectFromSetting(config_setting_lookup(layout, "temperature"), &themeCurrent.layoutObjects[ThemeLayoutId_Temperature], false);
layoutObjectFromSetting(config_setting_lookup(layout, "menuList"), &themeCurrent.layoutObjects[ThemeLayoutId_MenuList], false);
layoutObjectFromSetting(config_setting_lookup(layout, "menuListTiles"), &themeCurrent.layoutObjects[ThemeLayoutId_MenuListTiles], false);
layoutObjectFromSetting(config_setting_lookup(layout, "menuListIcon"), &themeCurrent.layoutObjects[ThemeLayoutId_MenuListIcon], false);
layoutObjectFromSetting(config_setting_lookup(layout, "menuListName"), &themeCurrent.layoutObjects[ThemeLayoutId_MenuListName], false);
layoutObjectFromSetting(config_setting_lookup(layout, "menuActiveEntryIcon"), &themeCurrent.layoutObjects[ThemeLayoutId_MenuActiveEntryIcon], false);
layoutObjectFromSetting(config_setting_lookup(layout, "menuActiveEntryName"), &themeCurrent.layoutObjects[ThemeLayoutId_MenuActiveEntryName], false);
layoutObjectFromSetting(config_setting_lookup(layout, "menuActiveEntryAuthor"), &themeCurrent.layoutObjects[ThemeLayoutId_MenuActiveEntryAuthor], false);
layoutObjectFromSetting(config_setting_lookup(layout, "menuActiveEntryVersion"), &themeCurrent.layoutObjects[ThemeLayoutId_MenuActiveEntryVersion], false);
}
if (is_archive) assets = config_lookup(&cfg, "assets");
if (is_archive && assets) {
assetObjectFromSetting(config_setting_lookup(assets, "battery_icon"), AssetId_battery_icon, NULL);
assetObjectFromSetting(config_setting_lookup(assets, "charging_icon"), AssetId_charging_icon, NULL);
assetObjectFromSetting(config_setting_lookup(assets, "folder_icon"), AssetId_folder_icon, &themeCurrent.layoutObjects[ThemeLayoutId_MenuActiveEntryIcon]);
assetObjectFromSetting(config_setting_lookup(assets, "invalid_icon"), AssetId_invalid_icon, &themeCurrent.layoutObjects[ThemeLayoutId_MenuActiveEntryIcon]);
assetObjectFromSetting(config_setting_lookup(assets, "theme_icon_dark"), AssetId_theme_icon_dark, &themeCurrent.layoutObjects[ThemeLayoutId_MenuActiveEntryIcon]);
assetObjectFromSetting(config_setting_lookup(assets, "theme_icon_light"), AssetId_theme_icon_light, &themeCurrent.layoutObjects[ThemeLayoutId_MenuActiveEntryIcon]);
assetObjectFromSetting(config_setting_lookup(assets, "airplane_icon"), AssetId_airplane_icon, NULL);
assetObjectFromSetting(config_setting_lookup(assets, "wifi_none_icon"), AssetId_wifi_none_icon, NULL);
assetObjectFromSetting(config_setting_lookup(assets, "wifi1_icon"), AssetId_wifi1_icon, NULL);
assetObjectFromSetting(config_setting_lookup(assets, "wifi2_icon"), AssetId_wifi2_icon, NULL);
assetObjectFromSetting(config_setting_lookup(assets, "wifi3_icon"), AssetId_wifi3_icon, NULL);
assetObjectFromSetting(config_setting_lookup(assets, "eth_icon"), AssetId_eth_icon, NULL);
assetObjectFromSetting(config_setting_lookup(assets, "eth_none_icon"), AssetId_eth_none_icon, NULL);
assetObjectFromSetting(config_setting_lookup(assets, "background_image"), AssetId_background_image, NULL);
}
} else { } else {
themeCurrent = *themeDefault; themeCurrent = *themeDefault;
memcpy(themeCurrent.layoutObjects, themeCommon.layoutObjects, sizeof(themeCommon.layoutObjects));
} }
ThemeLayoutObject *layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MenuListTiles];
if (layoutobj->posEnd[0] < 1) layoutobj->posEnd[0] = 1;
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MenuListIcon];
if (layoutobj->size[0] <= 0 || layoutobj->size[1] <= 0 || layoutobj->size[0] > layoutobj->imageSize[0] || layoutobj->size[1] > layoutobj->imageSize[1]) {
layoutobj->size[0] = layoutobj->imageSize[0];
layoutobj->size[1] = layoutobj->imageSize[1];
}
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MenuActiveEntryIcon];
if (layoutobj->size[0] <= 0 || layoutobj->size[1] <= 0 || layoutobj->size[0] > layoutobj->imageSize[0] || layoutobj->size[1] > layoutobj->imageSize[1]) {
layoutobj->size[0] = layoutobj->imageSize[0];
layoutobj->size[1] = layoutobj->imageSize[1];
}
config_destroy(&cfg); config_destroy(&cfg);
if (is_archive) PHYSFS_unmount(theme_archive_path);
#ifdef __SWITCH__
if (is_romfs) romfsUnmount("theme");
#endif
} }
void GetThemePathFromConfig(char* themePath, size_t size) { void GetThemePathFromConfig(char* themePath, size_t size) {

View File

@ -3,42 +3,19 @@
#include "common.h" #include "common.h"
#include <libconfig.h> #include <libconfig.h>
typedef enum
{
THEME_PRESET_LIGHT,
THEME_PRESET_DARK,
} ThemePreset;
typedef struct
{
bool visible;
bool posType; // false = absolute, true = relative
int posStart[2];
int posEnd[2];
int size[2]; // width/height
int imageSize[2]; // width/height for the actual image data
int touchSize[2];
int posFinal[2];
uint32_t textSize[2];
u32 font;
} ThemeLayoutObject;
typedef struct typedef struct
{ {
color_t textColor; color_t textColor;
color_t logoColor;
color_t attentionTextColor; color_t attentionTextColor;
color_t frontWaveColor; color_t frontWaveColor;
color_t middleWaveColor; color_t middleWaveColor;
color_t backWaveColor; color_t backWaveColor;
color_t backgroundColor; color_t backgroundColor;
color_t highlightColor; color_t highlightColor;
color_t highlightGradientEdgeColor;
color_t separatorColor; color_t separatorColor;
color_t borderColor; color_t borderColor;
color_t borderTextColor; color_t borderTextColor;
color_t progressBarColor; color_t progressBarColor;
bool logoColor_set;
bool enableWaveBlending; bool enableWaveBlending;
char buttonAText[32]; char buttonAText[32];
char buttonBText[32]; char buttonBText[32];
@ -48,10 +25,15 @@ typedef struct
char buttonMText[32]; char buttonMText[32];
char labelStarOnText[32]; char labelStarOnText[32];
char labelStarOffText[32]; char labelStarOffText[32];
const uint8_t *hbmenuLogoImage;
ThemeLayoutObject layoutObjects[ThemeLayoutId_Total];
} theme_t; } theme_t;
typedef enum
{
THEME_PRESET_LIGHT,
THEME_PRESET_DARK,
} ThemePreset;
bool colorFromSetting(config_setting_t *rgba, color_t *col); bool colorFromSetting(config_setting_t *rgba, color_t *col);
void themeStartup(ThemePreset preset); void themeStartup(ThemePreset preset);
void GetThemePathFromConfig(char* themePath, size_t size); void GetThemePathFromConfig(char* themePath, size_t size);

View File

@ -1,7 +0,0 @@
#pragma once
#include "common.h"
bool thermalstatusInit(void);
void thermalstatusExit(void);
bool thermalstatusGetDetails(s32 *temperature);

View File

@ -68,27 +68,16 @@ static void launchFile(const char* path, argData_s* args)
init_args(argBuf, sizeof(argBuf)-1, args->buf, sizeof(args->buf)); init_args(argBuf, sizeof(argBuf)-1, args->buf, sizeof(args->buf));
struct stat st;
if (stat(path, &st) == -1) {
memset(msg, 0, sizeof(msg));
snprintf(msg, sizeof(msg)-1, textGetString(StrId_NroNotFound), path);
menuCreateMsgBox(780, 300, msg);
menuScan(".");
}
else {
Result rc = envSetNextLoad(path, argBuf); Result rc = envSetNextLoad(path, argBuf);
if(R_FAILED(rc)) { if(R_FAILED(rc)) {
memset(msg, 0, sizeof(msg)); memset(msg, 0, sizeof(msg));
snprintf(msg, sizeof(msg)-1, "%s\n2%03d-%04d", textGetString(StrId_AppLaunchError), R_MODULE(rc), R_DESCRIPTION(rc)); snprintf(msg, sizeof(msg)-1, "%s\n0x%x", textGetString(StrId_AppLaunchError), rc);
menuCreateMsgBox(780, 300, msg); menuCreateMsgBox(780, 300, msg);
} }
else { else {
uiExitLoop(); uiExitLoop();
} }
}
} }
const loaderFuncs_s loader_builtin = const loaderFuncs_s loader_builtin =

View File

@ -1,22 +1,19 @@
#include <switch.h> #include <switch.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <physfs.h>
#include "../common/common.h" #include "../common/common.h"
#include "nx_graphics.h"
#include "nx_touch.h" #include "nx_touch.h"
// Define the desired framebuffer resolution (here we set it to 720p). // Define the desired framebuffer resolution (here we set it to 720p).
#define FB_WIDTH 1280 #define FB_WIDTH 1280
#define FB_HEIGHT 720 #define FB_HEIGHT 720
Framebuffer g_framebufObj;
uint8_t* g_framebuf; uint8_t* g_framebuf;
u32 g_framebuf_width; u32 g_framebuf_width;
PadState g_pad;
PadRepeater g_pad_repeater;
bool menuUpdateErrorScreen(void); bool menuUpdateErrorScreen(void);
#ifdef PERF_LOG #ifdef PERF_LOG
@ -42,44 +39,35 @@ int main(int argc, char **argv)
u64 start_tick=0; u64 start_tick=0;
#endif #endif
padConfigureInput(8, HidNpadStyleSet_NpadStandard);
padInitializeAny(&g_pad);
padRepeaterInitialize(&g_pad_repeater, 20, 10);
hidSetNpadHandheldActivationMode(HidNpadHandheldActivationMode_Single);
touchInit();
memset(errormsg, 0, sizeof(errormsg)); memset(errormsg, 0, sizeof(errormsg));
appletLockExit(); appletLockExit();
appletSetScreenShotPermission(AppletScreenShotPermission_Enable); appletSetScreenShotPermission(AppletScreenShotPermission_Enable);
ColorSetId theme = ColorSetId_Light; ColorSetId theme;
rc = setsysInitialize(); rc = setsysInitialize();
if (R_FAILED(rc)) snprintf(errormsg, sizeof(errormsg)-1, "Error: setsysInitialize() failed: 0x%x.", rc);
if (R_SUCCEEDED(rc)) setsysGetColorSetId(&theme);
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
setsysGetColorSetId(&theme); rc = plInitialize();
setsysExit(); if (R_FAILED(rc)) snprintf(errormsg, sizeof(errormsg)-1, "Error: plInitialize() failed: 0x%x.", rc);
} }
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
rc = textInit(); rc = textInit();
if (R_FAILED(rc)) { if (R_FAILED(rc)) {
snprintf(errormsg, sizeof(errormsg)-1, "Error: textInit() failed: 2%03d-%04d", R_MODULE(rc), R_DESCRIPTION(rc)); snprintf(errormsg, sizeof(errormsg)-1, "Error: textInit() failed: 0x%x.", rc);
} }
} }
if (R_SUCCEEDED(rc)) menuStartupPath(); if (R_SUCCEEDED(rc)) menuStartupPath();
if (R_SUCCEEDED(rc)) {
if (!PHYSFS_init(argv[0])) {
rc = 1;
snprintf(errormsg, sizeof(errormsg)-1, "Error: PHYSFS_init() failed: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
}
}
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
rc = assetsInit(); rc = assetsInit();
if (R_FAILED(rc)) { if (R_FAILED(rc)) {
snprintf(errormsg, sizeof(errormsg)-1, "Error: assetsInit() failed: 2%03d-%04d", R_MODULE(rc), R_DESCRIPTION(rc)); snprintf(errormsg, sizeof(errormsg)-1, "Error: assetsInit() failed: 0x%x.", rc);
} }
} }
@ -90,7 +78,7 @@ int main(int argc, char **argv)
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
rc = netloaderInit(); rc = netloaderInit();
if (R_FAILED(rc)) { if (R_FAILED(rc)) {
snprintf(errormsg, sizeof(errormsg)-1, "Error: netloaderInit() failed: 2%03d-%04d", R_MODULE(rc), R_DESCRIPTION(rc)); snprintf(errormsg, sizeof(errormsg)-1, "Error: netloaderInit() failed: 0x%x.", rc);
} }
} }
@ -127,7 +115,7 @@ int main(int argc, char **argv)
if (R_FAILED(lastret)) { if (R_FAILED(lastret)) {
memset(msg, 0, sizeof(msg)); memset(msg, 0, sizeof(msg));
snprintf(msg, sizeof(msg)-1, "%s\n2%03d-%04d", textGetString(StrId_LastLoadResult), R_MODULE(lastret), R_DESCRIPTION(lastret)); snprintf(msg, sizeof(msg)-1, "%s\n0x%x", textGetString(StrId_LastLoadResult), lastret);
menuCreateMsgBox(780, 300, msg); menuCreateMsgBox(780, 300, msg);
} }
@ -136,7 +124,8 @@ int main(int argc, char **argv)
if (errormsg[0]) error_screen = 1; if (errormsg[0]) error_screen = 1;
if (!error_screen) { if (!error_screen) {
graphicsInit(FB_WIDTH, FB_HEIGHT); framebufferCreate(&g_framebufObj, nwindowGetDefault(), FB_WIDTH, FB_HEIGHT, PIXEL_FORMAT_RGBA_8888, 2);
framebufferMakeLinear(&g_framebufObj);
} }
else { else {
consoleInit(NULL); consoleInit(NULL);
@ -146,17 +135,16 @@ int main(int argc, char **argv)
while (appletMainLoop()) while (appletMainLoop())
{ {
// Scan the gamepad. This should be done once for each frame
padUpdate(&g_pad);
padRepeaterUpdate(&g_pad_repeater, padGetButtons(&g_pad) & ( //Scan all the inputs. This should be done once for each frame
HidNpadButton_AnyLeft | HidNpadButton_AnyUp | HidNpadButton_AnyRight | HidNpadButton_AnyDown hidScanInput();
));
if (!error_screen) { if (!error_screen) {
if (!uiUpdate()) break; if (!uiUpdate()) break;
g_framebuf = graphicsFrameBegin(&g_framebuf_width); g_framebuf = framebufferBegin(&g_framebufObj, &g_framebuf_width);
#ifdef PERF_LOG #ifdef PERF_LOG
start_tick = armGetSystemTick(); start_tick = svcGetSystemTick();
#endif #endif
memset(g_framebuf, 237, g_framebuf_width * FB_HEIGHT); memset(g_framebuf, 237, g_framebuf_width * FB_HEIGHT);
menuLoop(); menuLoop();
@ -166,10 +154,10 @@ int main(int argc, char **argv)
} }
if (!error_screen) { if (!error_screen) {
graphicsFrameEnd(); framebufferEnd(&g_framebufObj);
#ifdef PERF_LOG #ifdef PERF_LOG
g_tickdiff_frame = armGetSystemTick() - start_tick; g_tickdiff_frame = svcGetSystemTick() - start_tick;
#endif #endif
} }
else { else {
@ -178,7 +166,7 @@ int main(int argc, char **argv)
} }
if (!error_screen) { if (!error_screen) {
graphicsExit(); framebufferClose(&g_framebufObj);
} }
else { else {
consoleExit(NULL); consoleExit(NULL);
@ -197,49 +185,41 @@ int main(int argc, char **argv)
netloaderExit(); netloaderExit();
powerExit(); powerExit();
assetsExit(); assetsExit();
PHYSFS_deinit(); plExit();
setsysExit();
appletUnlockExit(); appletUnlockExit();
return 0; return 0;
} }
u64 menuGetKeysDown(void) {
u64 keys = padGetButtonsDown(&g_pad);
keys |= padRepeaterGetButtons(&g_pad_repeater);
return keys;
}
//This is implemented here due to the hid code. //This is implemented here due to the hid code.
bool menuUpdate(void) { bool menuUpdate(void) {
bool exitflag = 0; bool exitflag = 0;
menu_s* menu = menuGetCurrent(); menu_s* menu = menuGetCurrent();
u64 down = menuGetKeysDown(); u32 down = hidKeysDown(CONTROLLER_P1_AUTO);
ThemeLayoutObject *layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MenuListTiles];
int entries_count = layoutobj->posEnd[0];
handleTouch(menu); handleTouch(menu);
if (down & HidNpadButton_Y) if (down & KEY_Y)
{ {
launchMenuNetloaderTask(); launchMenuNetloaderTask();
} }
else if (down & HidNpadButton_X) else if (down & KEY_X)
{ {
menuHandleXButton(); menuHandleXButton();
} }
else if (down & HidNpadButton_A) else if (down & KEY_A)
{ {
menuHandleAButton(); menuHandleAButton();
} }
else if (down & HidNpadButton_B) else if (down & KEY_B)
{ {
launchMenuBackTask(); launchMenuBackTask();
} }
else if(down & HidNpadButton_Minus){ else if(down & KEY_MINUS){
themeMenuStartup(); themeMenuStartup();
} }
else if (down & HidNpadButton_Plus) else if (down & KEY_PLUS)
{ {
exitflag = 1; exitflag = 1;
} }
@ -247,10 +227,10 @@ bool menuUpdate(void) {
{ {
int move = 0; int move = 0;
if (down & HidNpadButton_AnyLeft) move--; if (down & KEY_LEFT) move--;
if (down & HidNpadButton_AnyRight) move++; if (down & KEY_RIGHT) move++;
if (down & HidNpadButton_AnyDown) move-=entries_count; if (down & KEY_DOWN) move-=7;
if (down & HidNpadButton_AnyUp) move+=entries_count; if (down & KEY_UP) move+=7;
int newEntry = menu->curEntry + move; int newEntry = menu->curEntry + move;
if (newEntry < 0) newEntry = 0; if (newEntry < 0) newEntry = 0;
@ -263,9 +243,9 @@ bool menuUpdate(void) {
bool menuUpdateErrorScreen(void) { bool menuUpdateErrorScreen(void) {
bool exitflag = 0; bool exitflag = 0;
u64 down = menuGetKeysDown(); u32 down = hidKeysDown(CONTROLLER_P1_AUTO);
if (down & HidNpadButton_Plus) if (down & KEY_PLUS)
{ {
exitflag = 1; exitflag = 1;
} }

View File

@ -72,7 +72,7 @@ static void audio_playback_thread(void* arg)
playing = 1; playing = 1;
} }
if (R_SUCCEEDED(audoutWaitPlayFinish(&released_buffer, &released_count, UINT64_MAX))) if (R_SUCCEEDED(audoutWaitPlayFinish(&released_buffer, &released_count, U64_MAX)))
playing = 0; playing = 0;
} }
} }

View File

@ -1,141 +0,0 @@
#include <switch.h>
#include <deko3d.h>
#include "nx_graphics.h"
#define FB_NUM 2
#define CMDMEMSIZE 0x1000
static u32 s_fbWidth, s_fbHeight;
static DkDevice s_device;
static DkMemBlock s_fbMemBlock, s_workMemBlock, s_cmdMemBlock;
static DkSwapchain s_swapchain;
static DkCmdBuf s_cmdBuf;
static DkCmdList s_cmdLists[FB_NUM];
static DkFence s_fence;
static DkQueue s_queue;
void graphicsInit(u32 width, u32 height)
{
DkImageLayoutMaker imgLayoutMaker;
DkMemBlockMaker memBlockMaker;
// Create the device, which is the root object
DkDeviceMaker deviceMaker;
dkDeviceMakerDefaults(&deviceMaker);
s_device = dkDeviceCreate(&deviceMaker);
// Calculate layout for the framebuffers
DkImageLayout fbLayout;
dkImageLayoutMakerDefaults(&imgLayoutMaker, s_device);
imgLayoutMaker.flags = DkImageFlags_UsagePresent;
imgLayoutMaker.format = DkImageFormat_RGBA8_Unorm;
imgLayoutMaker.dimensions[0] = s_fbWidth = width;
imgLayoutMaker.dimensions[1] = s_fbHeight = height;
dkImageLayoutInitialize(&fbLayout, &imgLayoutMaker);
// Retrieve necessary size and alignment for the framebuffers
uint32_t fbSize = dkImageLayoutGetSize(&fbLayout);
uint32_t fbAlign = dkImageLayoutGetAlignment(&fbLayout);
fbSize = (fbSize + fbAlign - 1) &~ (fbAlign - 1);
// Create a memory block that will host the framebuffers
dkMemBlockMakerDefaults(&memBlockMaker, s_device, FB_NUM*fbSize);
memBlockMaker.flags = DkMemBlockFlags_GpuCached | DkMemBlockFlags_Image;
s_fbMemBlock = dkMemBlockCreate(&memBlockMaker);
// Initialize the framebuffers with the layout and backing memory we've just created
DkImage fbImages[FB_NUM];
DkImage const* swapchainImages[FB_NUM];
for (unsigned i = 0; i < FB_NUM; i ++)
{
swapchainImages[i] = &fbImages[i];
dkImageInitialize(&fbImages[i], &fbLayout, s_fbMemBlock, i*fbSize);
}
// Create a swapchain out of the framebuffers we've just initialized
DkSwapchainMaker swapchainMaker;
dkSwapchainMakerDefaults(&swapchainMaker, s_device, nwindowGetDefault(), swapchainImages, FB_NUM);
s_swapchain = dkSwapchainCreate(&swapchainMaker);
// Create a memory block for the linear framebuffer
dkMemBlockMakerDefaults(&memBlockMaker, s_device, width*height*4);
memBlockMaker.flags = DkMemBlockFlags_CpuCached | DkMemBlockFlags_GpuUncached;
s_workMemBlock = dkMemBlockCreate(&memBlockMaker);
// Create a memory block for the command lists
dkMemBlockMakerDefaults(&memBlockMaker, s_device, CMDMEMSIZE);
memBlockMaker.flags = DkMemBlockFlags_CpuUncached | DkMemBlockFlags_GpuCached;
s_cmdMemBlock = dkMemBlockCreate(&memBlockMaker);
// Create a command buffer
DkCmdBufMaker cmdBufMaker;
dkCmdBufMakerDefaults(&cmdBufMaker, s_device);
s_cmdBuf = dkCmdBufCreate(&cmdBufMaker);
dkCmdBufAddMemory(s_cmdBuf, s_cmdMemBlock, 0, CMDMEMSIZE);
// Define source for linear framebuffer copies
const DkCopyBuf linearSrc = {
.addr = dkMemBlockGetGpuAddr(s_workMemBlock),
.rowLength = 0,
.imageHeight = 0,
};
// Define rectangle for the copies
const DkImageRect copyRect = {
.x = 0, .y = 0, .z = 0,
.width = width, .height = height, .depth = 1,
};
// Record command lists for the copies
for (unsigned i = 0; i < FB_NUM; i ++) {
DkImageView tiledDst;
dkImageViewDefaults(&tiledDst, &fbImages[i]);
dkCmdBufCopyBufferToImage(s_cmdBuf, &linearSrc, &tiledDst, &copyRect, 0);
dkCmdBufSignalFence(s_cmdBuf, &s_fence, false);
s_cmdLists[i] = dkCmdBufFinishList(s_cmdBuf);
}
// Create a queue, to which we will submit our command lists
DkQueueMaker queueMaker;
dkQueueMakerDefaults(&queueMaker, s_device);
queueMaker.flags = 0; // we will only use this queue for transferring
s_queue = dkQueueCreate(&queueMaker);
}
void graphicsExit(void)
{
// Make sure the queue is idle before destroying anything
dkQueueWaitIdle(s_queue);
// Destroy all the resources we've created
dkQueueDestroy(s_queue);
dkCmdBufDestroy(s_cmdBuf);
dkMemBlockDestroy(s_cmdMemBlock);
dkMemBlockDestroy(s_workMemBlock);
dkSwapchainDestroy(s_swapchain);
dkMemBlockDestroy(s_fbMemBlock);
dkDeviceDestroy(s_device);
}
void* graphicsFrameBegin(u32* out_stride)
{
// Ensure the GPU is not reading from the framebuffer
dkFenceWait(&s_fence, -1);
// Return information
if (out_stride) *out_stride = s_fbWidth*4;
return dkMemBlockGetCpuAddr(s_workMemBlock);
}
void graphicsFrameEnd(void)
{
// Flush the linear framebuffer
dkMemBlockFlushCpuCache(s_workMemBlock, 0, s_fbWidth*s_fbHeight*4);
// Present a frame
int slot = dkQueueAcquireImage(s_queue, s_swapchain);
dkQueueSubmitCommands(s_queue, s_cmdLists[slot]);
dkQueuePresentImage(s_queue, s_swapchain, slot);
}

View File

@ -1,9 +0,0 @@
#pragma once
#include <switch.h>
void graphicsInit(u32 width, u32 height);
void graphicsExit(void);
void* graphicsFrameBegin(u32* out_stride);
void graphicsFrameEnd(void);

View File

@ -8,7 +8,7 @@ static bool powerCacheIsCharging;
static PsmSession powerSession; static PsmSession powerSession;
bool powerGetDetails(uint32_t *batteryCharge, bool *isCharging) { bool powerGetDetails(uint32_t *batteryCharge, bool *isCharging) {
PsmChargerType charger = PsmChargerType_Unconnected; ChargerType charger = ChargerType_None;
bool hwReadsSucceeded = false; bool hwReadsSucceeded = false;
bool use_cache = false; bool use_cache = false;
Result rc = 0; Result rc = 0;
@ -31,7 +31,7 @@ bool powerGetDetails(uint32_t *batteryCharge, bool *isCharging) {
else { else {
rc = psmGetChargerType(&charger); rc = psmGetChargerType(&charger);
hwReadsSucceeded &= R_SUCCEEDED(rc); hwReadsSucceeded &= R_SUCCEEDED(rc);
*isCharging = (charger != PsmChargerType_Unconnected); *isCharging = (charger > ChargerType_None);
} }
powerCacheCharge = *batteryCharge; powerCacheCharge = *batteryCharge;

View File

@ -1,14 +0,0 @@
#include "../common/common.h"
bool thermalstatusInit(void) {
return R_SUCCEEDED(tsInitialize());
}
void thermalstatusExit(void) {
tsExit();
}
bool thermalstatusGetDetails(s32 *temperature) {
return R_SUCCEEDED(tsGetTemperature(TsLocation_Internal, temperature));
}

View File

@ -5,33 +5,43 @@
#define VERTICAL_SWIPE_MINIMUM_DISTANCE 300 #define VERTICAL_SWIPE_MINIMUM_DISTANCE 300
#define HORIZONTAL_SWIPE_VERTICAL_PLAY 250 #define HORIZONTAL_SWIPE_VERTICAL_PLAY 250
#define HORIZONTAL_SWIPE_MINIMUM_DISTANCE 300 #define HORIZONTAL_SWIPE_MINIMUM_DISTANCE 300
#define LISTING_START_Y 475
#define LISTING_END_Y 647
#define BUTTON_START_Y 672
#define BUTTON_END_Y 704
#define BACK_BUTTON_START_X 966
#define BACK_BUTTON_END_X 1048
#define LAUNCH_BUTTON_START_X 1092
#define LAUNCH_BUTTON_END_X 1200
#define STAR_BUTTON_START_X 426
#define STAR_BUTTON_END_X 490
#define STAR_BUTTON_START_Y 100
#define STAR_BUTTON_END_Y 161
#define distance(x1, y1, x2, y2) (int) sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1))) #define distance(x1, y1, x2, y2) (int) sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)))
struct touchInfo_s touchInfo; struct touchInfo_s touchInfo;
void touchInit(void) { void touchInit() {
touchInfo.gestureInProgress = false; touchInfo.gestureInProgress = false;
touchInfo.isTap = true; touchInfo.isTap = true;
touchInfo.initMenuXPos = 0; touchInfo.initMenuXPos = 0;
touchInfo.initMenuIndex = 0; touchInfo.initMenuIndex = 0;
touchInfo.lastSlideSpeed = 0;
hidInitializeTouchScreen();
} }
void handleTappingOnApp(menu_s* menu, int px) { void handleTappingOnApp(menu_s* menu, int px) {
int i = 0; int i = 0;
menuEntry_s *me = NULL; menuEntry_s *me = NULL;
ThemeLayoutObject *layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MenuList];
for (me = menu->firstEntry, i = 0; me; me = me->next, i ++) { for (me = menu->firstEntry, i = 0; me; me = me->next, i ++) {
int entry_start_x = layoutobj->posStart[0] + i * layoutobj->posEnd[0]; int entry_start_x = 29 + i * (140 + 30);
int screen_width = 1280; int screen_width = 1280;
if (entry_start_x >= (screen_width - menu->xPos)) if (entry_start_x >= (screen_width - menu->xPos))
break; break;
if (px >= (entry_start_x + menu->xPos) && px <= (entry_start_x + menu->xPos) + layoutobj->size[0]) { if (px >= (entry_start_x + menu->xPos) && px <= (entry_start_x + menu->xPos) + 140 ) {
launchMenuEntryTask(me); launchMenuEntryTask(me);
break; break;
} }
@ -48,100 +58,91 @@ void handleTappingOnOpenLaunch(menu_s* menu) {
} }
} }
static inline bool checkInsideTextLayoutObject(ThemeLayoutId id, int x, int y) {
ThemeLayoutObject *layoutobj = &themeCurrent.layoutObjects[id];
if (!layoutobj->visible) return false;
return x > layoutobj->posFinal[0] && x < layoutobj->posFinal[0]+(layoutobj->touchSize[0] ? layoutobj->touchSize[0] : layoutobj->textSize[0]) && y > layoutobj->posFinal[1]-layoutobj->touchSize[1] && y < layoutobj->posFinal[1];
}
void handleTouch(menu_s* menu) { void handleTouch(menu_s* menu) {
ThemeLayoutObject *layoutobj = NULL; touchPosition currentTouch;
HidTouchScreenState touch = {0}; u32 touches = hidTouchCount();
hidGetTouchScreenStates(&touch, 1);
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MenuListTiles];
int entries_count = layoutobj->posEnd[0];
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MenuList];
// On touch start. // On touch start.
if (touch.count == 1 && !touchInfo.gestureInProgress) { if (touches == 1 && !touchInfo.gestureInProgress) {
hidTouchRead(&currentTouch, 0);
touchInfo.gestureInProgress = true; touchInfo.gestureInProgress = true;
touchInfo.firstTouch = touch.touches[0]; touchInfo.firstTouch = currentTouch;
touchInfo.prevTouch = touch.touches[0]; touchInfo.prevTouch = currentTouch;
touchInfo.isTap = true; touchInfo.isTap = true;
touchInfo.initMenuXPos = menu->xPos; touchInfo.initMenuXPos = menu->xPos;
touchInfo.initMenuIndex = menu->curEntry; touchInfo.initMenuIndex = menu->curEntry;
touchInfo.lastSlideSpeed = 0;
menu->slideSpeed = 0;
} }
// On touch moving. // On touch moving.
else if (touch.count >= 1 && touchInfo.gestureInProgress) { else if (touches >= 1 && touchInfo.gestureInProgress) {
touchInfo.lastSlideSpeed = ((int)(touch.touches[0].x - touchInfo.prevTouch.x)); hidTouchRead(&currentTouch, 0);
touchInfo.prevTouch = touch.touches[0]; touchInfo.prevTouch = currentTouch;
if (touchInfo.isTap && (abs(touchInfo.firstTouch.x - touch.touches[0].x) > TAP_MOVEMENT_GAP || abs(touchInfo.firstTouch.y - touch.touches[0].y) > TAP_MOVEMENT_GAP)) { if (touchInfo.isTap && (abs(touchInfo.firstTouch.px - currentTouch.px) > TAP_MOVEMENT_GAP || abs(touchInfo.firstTouch.py - currentTouch.py) > TAP_MOVEMENT_GAP)) {
touchInfo.isTap = false; touchInfo.isTap = false;
} }
if (!menuIsMsgBoxOpen() && touchInfo.firstTouch.y > layoutobj->posStart[1] && touchInfo.firstTouch.y < layoutobj->posStart[1]+layoutobj->size[1] && !touchInfo.isTap && menu->nEntries > entries_count) { if (!menuIsMsgBoxOpen() && touchInfo.firstTouch.py > LISTING_START_Y && touchInfo.firstTouch.py < LISTING_END_Y && !touchInfo.isTap && menu->nEntries > 7) {
menu->xPos = touchInfo.initMenuXPos + (currentTouch.px - touchInfo.firstTouch.px);
menu->curEntry = touchInfo.initMenuIndex + ((int) (touchInfo.firstTouch.px - currentTouch.px) / 170);
if (!touchInfo.isTap) { if (menu->curEntry < 0)
menu->slideSpeed = touchInfo.lastSlideSpeed; menu->curEntry = 0;
}
if (menu->curEntry >= menu->nEntries - 6)
menu->curEntry = menu->nEntries - 7;
} }
} }
// On touch end. // On touch end.
else if (touchInfo.gestureInProgress) { else if (touchInfo.gestureInProgress) {
int x1 = touchInfo.firstTouch.x; int x1 = touchInfo.firstTouch.px;
int y1 = touchInfo.firstTouch.y; int y1 = touchInfo.firstTouch.py;
int x2 = touchInfo.prevTouch.x; int x2 = touchInfo.prevTouch.px;
int y2 = touchInfo.prevTouch.y; int y2 = touchInfo.prevTouch.py;
if (!touchInfo.isTap) {
menu->slideSpeed = touchInfo.lastSlideSpeed;
}
bool netloader_active = menuIsNetloaderActive(); bool netloader_active = menuIsNetloaderActive();
if (menuIsMsgBoxOpen() && !netloader_active) { if (menuIsMsgBoxOpen() && !netloader_active) {
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MsgBoxSeparator];
MessageBox currMsgBox = menuGetCurrentMsgBox(); MessageBox currMsgBox = menuGetCurrentMsgBox();
int start_x = 1280 / 2 - currMsgBox.width / 2; int start_x = 1280 / 2 - currMsgBox.width / 2;
int start_y = (720 / 2 - currMsgBox.height / 2) + currMsgBox.height; int start_y = (720 / 2 - currMsgBox.height / 2) + (currMsgBox.height - 80);
int end_x = start_x + currMsgBox.width; int end_x = start_x + currMsgBox.width;
int end_y = start_y; int end_y = start_y + 80;
start_y+= layoutobj->posStart[1];
if (x1 > start_x && x1 < end_x && y1 > start_y && y1 < end_y && touchInfo.isTap) { if (x1 > start_x && x1 < end_x && y1 > start_y && y1 < end_y && touchInfo.isTap) {
menuCloseMsgBox(); menuCloseMsgBox();
} }
} else if (touchInfo.isTap && !netloader_active) { } else if (touchInfo.isTap && !netloader_active) {
// App Icons // App Icons
if (y1 > layoutobj->posStart[1] && y1 < layoutobj->posStart[1]+layoutobj->size[1]) { if (y1 > LISTING_START_Y && y1 < LISTING_END_Y) {
handleTappingOnApp(menu, touchInfo.prevTouch.x); handleTappingOnApp(menu, touchInfo.prevTouch.px);
} }
// Bottom Buttons // Bottom Buttons
else { else if (y1 > BUTTON_START_Y && y1 < BUTTON_END_Y) {
// Back Button // Back Button for non-empty directory
if (checkInsideTextLayoutObject(ThemeLayoutId_ButtonB, x1, y1) || checkInsideTextLayoutObject(ThemeLayoutId_ButtonBText, x1, y1)) { if (menu->nEntries != 0 && x1 > BACK_BUTTON_START_X && x1 < BACK_BUTTON_END_X) {
launchMenuBackTask(); launchMenuBackTask();
} }
// Open/Launch Button // Open/Launch Button / Back Button for empty directories
else if (menu->nEntries != 0 && (checkInsideTextLayoutObject(ThemeLayoutId_ButtonA, x1, y1) || checkInsideTextLayoutObject(ThemeLayoutId_ButtonAText, x1, y1))) { else if (x1 > LAUNCH_BUTTON_START_X && x1 < LAUNCH_BUTTON_END_X) {
if (menu->nEntries == 0) {
launchMenuBackTask();
} else {
handleTappingOnOpenLaunch(menu); handleTappingOnOpenLaunch(menu);
} }
// Star Button }
else if (menu->nEntries != 0) { }
// Star
else {
int i; int i;
menuEntry_s* me; menuEntry_s* me;
for (i = 0, me = menu->firstEntry; i != menu->curEntry; i ++, me = me->next); for (i = 0, me = menu->firstEntry; i != menu->curEntry; i ++, me = me->next);
if (me->type != ENTRY_TYPE_THEME && (checkInsideTextLayoutObject(ThemeLayoutId_ButtonX, x1, y1) || checkInsideTextLayoutObject(ThemeLayoutId_ButtonXText, x1, y1))) { if (me->type != ENTRY_TYPE_THEME && x1 > STAR_BUTTON_START_X && x1 < STAR_BUTTON_END_X
&& y1 > STAR_BUTTON_START_Y && y1 < STAR_BUTTON_END_Y) {
menuHandleXButton(); menuHandleXButton();
} }
} }
} }
}
// Vertical Swipe // Vertical Swipe
else if (abs(x1 - x2) < VERTICAL_SWIPE_HORIZONTAL_PLAY && distance(x1, y1, x2, y2) > VERTICAL_SWIPE_MINIMUM_DISTANCE) { else if (abs(x1 - x2) < VERTICAL_SWIPE_HORIZONTAL_PLAY && distance(x1, y1, x2, y2) > VERTICAL_SWIPE_MINIMUM_DISTANCE) {
// Swipe up to go back // Swipe up to go back
@ -154,7 +155,7 @@ void handleTouch(menu_s* menu) {
} }
} }
// Horizontal Swipe // Horizontal Swipe
else if (y1 < layoutobj->posStart[1] && y2 < layoutobj->posStart[1]) { else if (y1 < LISTING_START_Y && y2 < LISTING_START_Y) {
if (abs(y1 - y2) < HORIZONTAL_SWIPE_VERTICAL_PLAY && distance(x1, y1, x2, y2) > HORIZONTAL_SWIPE_MINIMUM_DISTANCE) { if (abs(y1 - y2) < HORIZONTAL_SWIPE_VERTICAL_PLAY && distance(x1, y1, x2, y2) > HORIZONTAL_SWIPE_MINIMUM_DISTANCE) {
// Swipe left to go into theme-menu // Swipe left to go into theme-menu
if (x1 - x2 > 0) { if (x1 - x2 > 0) {

View File

@ -5,13 +5,11 @@
struct touchInfo_s { struct touchInfo_s {
bool gestureInProgress; bool gestureInProgress;
HidTouchState firstTouch; touchPosition firstTouch;
HidTouchState prevTouch; touchPosition prevTouch;
bool isTap; bool isTap;
int initMenuXPos; int initMenuXPos;
int initMenuIndex; int initMenuIndex;
int lastSlideSpeed;
}; };
void touchInit(void);
void handleTouch(menu_s* menu); void handleTouch(menu_s* menu);

View File

@ -1,7 +1,6 @@
#include <SFML/Graphics.hpp> #include <SFML/Graphics.hpp>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include <physfs.h>
extern "C" { extern "C" {
@ -11,13 +10,12 @@ extern "C" {
color_t pixels[720][1280]; color_t pixels[720][1280];
int main(int argc, char **argv) int main()
{ {
sf::RenderWindow window(sf::VideoMode(1280, 720), "Test"); sf::RenderWindow window(sf::VideoMode(1280, 720), "Test");
window.setFramerateLimit(60); window.setFramerateLimit(60);
menuStartupPath(); menuStartupPath();
PHYSFS_init(argv[0]);
assetsInit(); assetsInit();
themeStartup(THEME_PRESET_LIGHT); themeStartup(THEME_PRESET_LIGHT);
textInit(); textInit();
@ -64,7 +62,6 @@ int main(int argc, char **argv)
netloaderExit(); netloaderExit();
fontExit(); fontExit();
assetsExit(); assetsExit();
PHYSFS_deinit();
return 0; return 0;
} }

View File

@ -1,15 +0,0 @@
#include "../common/common.h"
bool thermalstatusInit(void) {
return false;
}
void thermalstatusExit(void) {
}
bool thermalstatusGetDetails(s32 *temperature) {
*temperature = 0;
return false;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 481 B