Compare commits
22 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
2c53af56cc | ||
|
7bdfce172c | ||
|
34f7f16cb1 | ||
|
73d7108a62 | ||
|
422039f727 | ||
|
3f73855170 | ||
|
6e654ec2af | ||
|
5c85dd784b | ||
|
8c87b1c46f | ||
|
47fd18cabb | ||
|
c1640f4b54 | ||
|
aef37e10f7 | ||
|
95411fe5e9 | ||
|
65f23b0bde | ||
|
20c1f00972 | ||
|
fcbc56acc4 | ||
|
244d058f1b | ||
|
df09e9ed1b | ||
|
45efcfcb98 | ||
|
16958ac4ba | ||
|
c69f4c56c5 | ||
|
3e451a9c8b |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
.*/
|
||||
*~
|
||||
*.exe
|
||||
*.o
|
||||
|
2
Makefile
2
Makefile
@ -1,4 +1,4 @@
|
||||
export APP_VERSION := 3.3.0
|
||||
export APP_VERSION := 3.5.1
|
||||
|
||||
ifeq ($(RELEASE),)
|
||||
export APP_VERSION := $(APP_VERSION)-$(shell git describe --dirty --always)
|
||||
|
@ -63,7 +63,7 @@ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||
|
||||
LIBS := -lminizip `freetype-config --libs` -lconfig -lturbojpeg -lpng
|
||||
LIBS := -ldeko3d -lphysfs `freetype-config --libs` -lconfig -lturbojpeg -lpng
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
@ -212,6 +212,7 @@ $(OUTPUT).nso : $(OUTPUT).elf
|
||||
|
||||
endif
|
||||
|
||||
menu.o : $(TOPDIR)/Makefile
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
|
||||
$(OFILES_SRC) : $(HFILES_BIN)
|
||||
|
@ -14,7 +14,7 @@ test : pc_main/main.cpp pc_main/pc_launch.c pc_main/pc_power.c pc_main/pc_netsta
|
||||
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/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 -lminizip -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 -lphysfs -lz -lconfig -lturbojpeg -lpng $(EXTRA_LDFLAGS) -I. -iquote $(DEVKITPRO)/libnx/include -Ibuild_pc -g -o $@
|
||||
|
||||
clean:
|
||||
rm -rf build_pc/ test test.*
|
||||
|
@ -13,13 +13,13 @@ The following [pacman packages](https://devkitpro.org/wiki/devkitPro_pacman) are
|
||||
- `switch-freetype`
|
||||
- `switch-libconfig`
|
||||
- `switch-libjpeg-turbo`
|
||||
- `switch-zlib`
|
||||
- `switch-physfs`
|
||||
|
||||
The following libraries are required to build for PC:
|
||||
- `libfreetype`
|
||||
- `libconfig`
|
||||
- `libjpeg-turbo`
|
||||
- `libminizip`
|
||||
- `libphysfs`
|
||||
|
||||
Building for Switch/PC requires `zip`.
|
||||
|
||||
|
177
common/assets.c
177
common/assets.c
@ -1,6 +1,6 @@
|
||||
#include "common.h"
|
||||
|
||||
#include <minizip/unzip.h>
|
||||
#include <physfs.h>
|
||||
#include <png.h>
|
||||
|
||||
#define GENASSET(_p, _mode, _w, _h) {{.path = _p, .imageMode = _mode, .imageSize = {_w, _h}}, {}}
|
||||
@ -46,59 +46,9 @@ static void assetsSetPixelSize(assetsDataEntry *entry) {
|
||||
}
|
||||
}
|
||||
|
||||
static int assetsLoadFile(unzFile zipf, assetsDataEntry *entry) {
|
||||
int ret;
|
||||
int filesize=0;
|
||||
unz_file_info file_info;
|
||||
u8* buffer = NULL;
|
||||
|
||||
assetsSetPixelSize(entry);
|
||||
|
||||
ret = unzLocateFile(zipf, entry->path, 0);
|
||||
|
||||
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 != entry->imageSize[0] * entry->imageSize[1] * entry->pixSize) 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) {
|
||||
int ret=0;
|
||||
bool ret=false;
|
||||
int i, stopi;
|
||||
unzFile zipf;
|
||||
assetsDataEntry *entry = NULL;
|
||||
char tmp_path[PATH_MAX];
|
||||
|
||||
@ -117,40 +67,34 @@ Result assetsInit(void) {
|
||||
snprintf(tmp_path, sizeof(tmp_path)-1, "%s/romfs/assets.zip", menuGetRootBasePath());
|
||||
#endif
|
||||
|
||||
zipf = unzOpen(tmp_path);
|
||||
if(zipf==NULL) {
|
||||
#ifdef __SWITCH__
|
||||
romfsExit();
|
||||
#endif
|
||||
|
||||
return 0x80;
|
||||
}
|
||||
|
||||
for (i=0; i<AssetId_Max; i++) {
|
||||
stopi = i;
|
||||
entry = &g_assetsDataList[i][0];
|
||||
if (entry->path[0]) {
|
||||
ret = assetsLoadFile(zipf, entry);
|
||||
if (ret!=UNZ_OK) break;
|
||||
entry->initialized = true;
|
||||
if (PHYSFS_mount(tmp_path, "", 0)) {
|
||||
ret=true;
|
||||
for (i=0; i<AssetId_Max; i++) {
|
||||
stopi = i;
|
||||
entry = &g_assetsDataList[i][0];
|
||||
if (entry->path[0]) {
|
||||
ret = assetsLoadData(i, NULL, NULL);
|
||||
if (!ret) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret!=UNZ_OK) {
|
||||
for (i=0; i<stopi; i++) {
|
||||
assetsClearEntry(&g_assetsDataList[i][0]);
|
||||
if (!ret) {
|
||||
for (i=0; i<stopi; i++) {
|
||||
assetsClearEntry(&g_assetsDataList[i][0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (ret) g_assetsInitialized = 1;
|
||||
|
||||
PHYSFS_unmount(tmp_path);
|
||||
}
|
||||
|
||||
if (ret==UNZ_OK) g_assetsInitialized = 1;
|
||||
|
||||
unzClose(zipf);
|
||||
|
||||
#ifdef __SWITCH__
|
||||
romfsExit();
|
||||
return ret ? 0 : MAKERESULT(Module_Libnx, LibnxError_IoError);
|
||||
#else
|
||||
return ret ? 0 : 1;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void assetsExit(void) {
|
||||
@ -223,31 +167,67 @@ bool assetsLoadPngFromMemory(u8 *indata, size_t indata_size, u8 *outdata, ImageM
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool assetsLoadFromTheme(AssetId id, const char *path, int *imageSize) {
|
||||
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][1];
|
||||
assetsDataEntry *entry = &g_assetsDataList[id][path ? 1 : 0];
|
||||
if (entry->initialized) return false;
|
||||
|
||||
memset(entry, 0, sizeof(*entry));
|
||||
if (path) memset(entry, 0, sizeof(*entry));
|
||||
|
||||
entry->imageSize[0] = imageSize[0];
|
||||
entry->imageSize[1] = imageSize[1];
|
||||
if (imageSize) {
|
||||
entry->imageSize[0] = imageSize[0];
|
||||
entry->imageSize[1] = imageSize[1];
|
||||
}
|
||||
|
||||
entry->imageMode = g_assetsDataList[id][0].imageMode;
|
||||
if (path) entry->imageMode = g_assetsDataList[id][0].imageMode;
|
||||
assetsSetPixelSize(entry);
|
||||
entry->size = entry->imageSize[0] * entry->imageSize[1] * entry->pixSize;
|
||||
|
||||
strncpy(entry->path, path, sizeof(entry->path)-1);
|
||||
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;
|
||||
struct stat st;
|
||||
|
||||
if (ret && stat(path, &st)==-1) ret = false;
|
||||
|
||||
if (ret) {
|
||||
entry->buffer = (u8*)malloc(entry->size);
|
||||
@ -255,31 +235,18 @@ bool assetsLoadFromTheme(AssetId id, const char *path, int *imageSize) {
|
||||
else ret = false;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
data_buf = (u8*)malloc(st.st_size);
|
||||
if (data_buf) memset(data_buf, 0, st.st_size);
|
||||
else ret = false;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
FILE *f = fopen(entry->path, "rb");
|
||||
if (f==NULL) ret = false;
|
||||
else {
|
||||
ret = fread(data_buf, st.st_size, 1, f) == 1;
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
if (ret) ret = assetsPhysfsReadFile(entry->path, &data_buf, &filesize, false);
|
||||
|
||||
if (ret) {
|
||||
if (strcasecmp(ext, ".bin")==0) {
|
||||
if (st.st_size != entry->size) ret = false;
|
||||
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, st.st_size, entry->buffer, entry->imageMode, entry->imageSize[0], entry->imageSize[1]);
|
||||
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, st.st_size, entry->buffer, entry->imageMode, entry->imageSize[0], entry->imageSize[1]);
|
||||
ret = assetsLoadPngFromMemory(data_buf, filesize, entry->buffer, entry->imageMode, entry->imageSize[0], entry->imageSize[1]);
|
||||
else
|
||||
ret = false; // File extension not recognized.
|
||||
}
|
||||
|
@ -35,7 +35,8 @@ typedef struct {
|
||||
Result assetsInit(void);
|
||||
void assetsExit(void);
|
||||
void assetsClearTheme(void);
|
||||
bool assetsLoadFromTheme(AssetId id, const char *path, int *imageSize);
|
||||
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);
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
typedef uint64_t u64;
|
||||
typedef int8_t s8;
|
||||
|
@ -9,6 +9,10 @@
|
||||
#define FONT_FACES_MAX 2
|
||||
#endif
|
||||
|
||||
#ifdef __SWITCH__
|
||||
static bool s_plinited;
|
||||
#endif
|
||||
|
||||
static FT_Error s_font_libret=1, s_font_facesret[FONT_FACES_MAX];
|
||||
|
||||
static FT_Library s_font_library;
|
||||
@ -364,7 +368,11 @@ bool fontInitialize(void)
|
||||
PlFontData fonts[PlSharedFontType_Total];
|
||||
|
||||
Result rc=0;
|
||||
rc = plGetSharedFont(textGetLanguageCode(), fonts, FONT_FACES_MAX, &s_font_faces_total);
|
||||
rc = plInitialize(PlServiceType_User);
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
s_plinited = true;
|
||||
rc = plGetSharedFont(textGetLanguageCode(), fonts, FONT_FACES_MAX, &s_font_faces_total);
|
||||
}
|
||||
if (R_FAILED(rc)) return false;
|
||||
|
||||
for (i=0; i<s_font_faces_total; i++) {
|
||||
@ -410,6 +418,10 @@ void fontExit()
|
||||
if (s_font_facesret[i]==0) FT_Done_Face(s_font_faces[i]);
|
||||
|
||||
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
|
||||
|
@ -43,13 +43,15 @@ const char* const g_strings[StrId_Max][17] =
|
||||
STR_KO("로딩중…"),
|
||||
STR_RU("загрузка…"),
|
||||
STR_ZH_HANS("加载中…"),
|
||||
STR_ZH_HANT("加載中…"),
|
||||
STR_ZH_HANT("載入中…"),
|
||||
},
|
||||
|
||||
[StrId_AppletMode] =
|
||||
{
|
||||
STR_EN("● Applet Mode ●"),
|
||||
STR_ES("● Modo Applet ●"),
|
||||
STR_FR("● Mode Applet ●"),
|
||||
STR_ZH_HANS("● 小程序模式 ●"),
|
||||
},
|
||||
|
||||
[StrId_Directory] =
|
||||
@ -97,7 +99,7 @@ const char* const g_strings[StrId_Max][17] =
|
||||
STR_KO("알 수 없는 개발자"),
|
||||
STR_RU("неизвестный автор"),
|
||||
STR_ZH_HANS("未知作者"),
|
||||
STR_ZH_HANT("作者不詳"),
|
||||
STR_ZH_HANT("作者未知"),
|
||||
},
|
||||
|
||||
[StrId_IOError] =
|
||||
@ -113,7 +115,7 @@ const char* const g_strings[StrId_Max][17] =
|
||||
STR_KO("입출력 오류"),
|
||||
STR_RU("I/O-ошибка"),
|
||||
STR_ZH_HANS("读写出错"),
|
||||
STR_ZH_HANT("讀寫錯誤"),
|
||||
STR_ZH_HANT("取存錯誤"),
|
||||
},
|
||||
|
||||
[StrId_CouldNotOpenFile] =
|
||||
@ -129,7 +131,14 @@ const char* const g_strings[StrId_Max][17] =
|
||||
STR_KO("파일을 열 수 없습니다:\n%s"),
|
||||
STR_RU("Не могу открыть файл:\n%s"),
|
||||
STR_ZH_HANS("无法打开文件:\n%s"),
|
||||
STR_ZH_HANT("開啓檔案失敗:\n%s"),
|
||||
STR_ZH_HANT("無法開啟檔案:\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] =
|
||||
@ -145,7 +154,7 @@ const char* const g_strings[StrId_Max][17] =
|
||||
STR_KO("애플리케이션을 찾을 수 없습니다"),
|
||||
STR_RU("приложение не найдено"),
|
||||
STR_ZH_HANS("找不到可执行的自制程序"),
|
||||
STR_ZH_HANT("未能找到可執行的自製程式"),
|
||||
STR_ZH_HANT("沒有可執行的自製程式"),
|
||||
},
|
||||
|
||||
[StrId_NoAppsFound_Msg] =
|
||||
@ -206,14 +215,14 @@ const char* const g_strings[StrId_Max][17] =
|
||||
"названием switch и она содержит приложения."
|
||||
),
|
||||
STR_ZH_HANS(
|
||||
"内存卡找不到任何可执行的应用程序。\n"
|
||||
"请在内存卡的根目录建立「switch」子目录,\n"
|
||||
"并存放自制应用软件至该目录。"
|
||||
"找不到任何自制程序(nro)。\n"
|
||||
"在SD卡根目录建立“switch”文件夹,\n"
|
||||
"并将自制程序(nro)放在其中。"
|
||||
),
|
||||
STR_ZH_HANT(
|
||||
"記憶體找不到任何可執行的應用程式。\n"
|
||||
"請在記憶體建立「switch」資料夾,\n"
|
||||
"然後儲存自製軟體到此處。"
|
||||
"記憶卡內沒有可供執行的應用程式。\n"
|
||||
"請在根目錄下建立「switch」資料夾,\n"
|
||||
"並將自製軟體複製到switch資料夾內。"
|
||||
),
|
||||
},
|
||||
|
||||
@ -226,15 +235,19 @@ const char* const g_strings[StrId_Max][17] =
|
||||
STR_IT("L'ultima applicazione ha restituito un errore:"),
|
||||
STR_JP("直前に実行したアプリでエラーが発生しました:"),
|
||||
STR_KO("최근 애플리케이션에서 오류가 발생했습니다:"),
|
||||
STR_ZH_HANT("程式執行時發生錯誤:"),
|
||||
STR_ZH_HANS("程序运行后出现错误:"),
|
||||
STR_ZH_HANT("程式執行後出現錯誤:"),
|
||||
},
|
||||
|
||||
[StrId_AppLaunchError] =
|
||||
{
|
||||
STR_EN("Failed to launch the application:"),
|
||||
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] =
|
||||
@ -265,8 +278,8 @@ const char* const g_strings[StrId_Max][17] =
|
||||
STR_NL("Versie"),
|
||||
STR_KO("버전"),
|
||||
STR_RU("Версия"),
|
||||
STR_ZH_HANS("版"),
|
||||
STR_ZH_HANT("版"),
|
||||
STR_ZH_HANS("版本"),
|
||||
STR_ZH_HANT("版本"),
|
||||
},
|
||||
|
||||
[StrId_Actions_Launch] =
|
||||
@ -274,7 +287,7 @@ const char* const g_strings[StrId_Max][17] =
|
||||
STR_EN("Launch"),
|
||||
STR_ES("Lanzamiento"),
|
||||
STR_DE("Starten"),
|
||||
STR_FR("Lancement"),
|
||||
STR_FR("Lancer"),
|
||||
STR_IT("Avvia"),
|
||||
STR_JP("起動"),
|
||||
STR_PT("Lançamento"),
|
||||
@ -313,8 +326,8 @@ const char* const g_strings[StrId_Max][17] =
|
||||
STR_NL("Terug"),
|
||||
STR_KO("뒤로 가기"),
|
||||
STR_RU("возвращаться"),
|
||||
STR_ZH_HANS("回去"),
|
||||
STR_ZH_HANT("回去"),
|
||||
STR_ZH_HANS("返回"),
|
||||
STR_ZH_HANT("返回"),
|
||||
},
|
||||
|
||||
[StrId_MsgBox_OK] =
|
||||
@ -326,6 +339,7 @@ const char* const g_strings[StrId_Max][17] =
|
||||
STR_ES("Aceptar"),
|
||||
STR_JP("了解"),
|
||||
STR_KO("확인"),
|
||||
STR_ZH_HANS("确认"),
|
||||
STR_ZH_HANT("確認"),
|
||||
},
|
||||
|
||||
@ -338,7 +352,8 @@ const char* const g_strings[StrId_Max][17] =
|
||||
STR_IT("Applica"),
|
||||
STR_JP("適用"),
|
||||
STR_KO("적용"),
|
||||
STR_ZH_HANT("应用"),
|
||||
STR_ZH_HANS("应用"),
|
||||
STR_ZH_HANT("套用"),
|
||||
},
|
||||
|
||||
[StrId_Actions_Star] =
|
||||
@ -346,6 +361,8 @@ const char* const g_strings[StrId_Max][17] =
|
||||
STR_EN("Star"),
|
||||
STR_ES("Agregar a favoritos"),
|
||||
STR_IT("Aggiungi ai preferiti"),
|
||||
STR_FR("Ajouter aux favoris"),
|
||||
STR_ZH_HANS("收藏"),
|
||||
},
|
||||
|
||||
[StrId_Actions_Unstar] =
|
||||
@ -353,18 +370,21 @@ const char* const g_strings[StrId_Max][17] =
|
||||
STR_EN("Unstar"),
|
||||
STR_ES("Borrar de favoritos"),
|
||||
STR_IT("Rimuovi dai preferiti"),
|
||||
STR_FR("Retirer des favoris"),
|
||||
STR_ZH_HANS("取消收藏"),
|
||||
},
|
||||
|
||||
[StrId_ThemeMenu] =
|
||||
{
|
||||
STR_EN("Theme Menu"),
|
||||
STR_FR("Menu Thème"),
|
||||
STR_FR("Menu thèmes"),
|
||||
STR_DE("Theme Menü"),
|
||||
STR_ES("Menú temático"),
|
||||
STR_IT("Tema Menu"),
|
||||
STR_JP("テーマメニュー"),
|
||||
STR_KO("테마 메뉴"),
|
||||
STR_ZH_HANT("主题菜单"),
|
||||
STR_ZH_HANS("主题菜单"),
|
||||
STR_ZH_HANT("主題選單"),
|
||||
},
|
||||
|
||||
[StrId_ThemeNotApplied] =
|
||||
@ -376,7 +396,8 @@ const char* const g_strings[StrId_Max][17] =
|
||||
STR_IT("Il tema non è stato applicato a causa di un errore."),
|
||||
STR_JP("エラーが発生したため、テーマを適用できませんでした。"),
|
||||
STR_KO("오류가 발생 했기 때문에 테마를 적용할 수 없습니다."),
|
||||
STR_ZH_HANT("由于发生错误, 无法应用主题。"),
|
||||
STR_ZH_HANS("由于发生错误, 无法应用主题。"),
|
||||
STR_ZH_HANT("出現錯誤,無法套用主題。"),
|
||||
},
|
||||
|
||||
[StrId_DefaultThemeName] =
|
||||
@ -385,6 +406,9 @@ const char* const g_strings[StrId_Max][17] =
|
||||
STR_FR("Thème par défaut"),
|
||||
STR_DE("Standard Theme"),
|
||||
STR_IT("Tema di default"),
|
||||
STR_ES("Tema por defecto"),
|
||||
STR_ZH_HANS("默认主题"),
|
||||
STR_ZH_HANT("預設主題"),
|
||||
},
|
||||
|
||||
/*[StrId_Reboot] =
|
||||
@ -563,7 +587,7 @@ const char* const g_strings[StrId_Max][17] =
|
||||
STR_DE("Fehler beim Lesen der Titel-Metadaten.\n%08lX%08lX@%d"),
|
||||
STR_FR(
|
||||
"Erreur lors de la lecture des métadonnées\n"
|
||||
"de titre.\n%08lX%08lX@%d"
|
||||
"du titre.\n%08lX%08lX@%d"
|
||||
),
|
||||
STR_IT("Errore nella lettura dei metadata dei titoli.\n%08lX%08lX@%d"),
|
||||
STR_JP("タイトルメタデータを読み取ることができませんでした。\n%08lX%08lX@%d"),
|
||||
@ -572,7 +596,7 @@ const char* const g_strings[StrId_Max][17] =
|
||||
STR_KO("타이틀 메타데이터를 읽는데 실패하였습니다.\n%08lX%08lX@%d"),
|
||||
STR_RU("Ошибка чтения метаданных заголовка\n.%08lX%08lX@%d"),
|
||||
STR_ZH_HANS("读取软件相关信息时发生错误:\n%08lX%08lX@%d"),
|
||||
STR_ZH_HANT("讀取軟體相關數據時發生錯誤:\n%08lX%08lX@%d"),
|
||||
STR_ZH_HANT("讀取軟體相關資訊時發生錯誤:\n%08lX%08lX@%d"),
|
||||
},
|
||||
|
||||
[StrId_NoTitlesFound] =
|
||||
@ -714,7 +738,7 @@ const char* const g_strings[StrId_Max][17] =
|
||||
),
|
||||
STR_ZH_HANT(
|
||||
"您所利用漏洞開啓的「自製軟體啓動器」\n"
|
||||
"無法在當前選中的軟體啓動自製軟件。\n"
|
||||
"無法在當前選中的軟體啓動自製軟體。\n"
|
||||
"請利用其它漏洞來啓動「自製軟體啓動器」。"
|
||||
),
|
||||
},
|
||||
@ -776,7 +800,7 @@ const char* const g_strings[StrId_Max][17] =
|
||||
STR_EN("NetLoader"),
|
||||
STR_ES("Cargador de programas"),
|
||||
STR_DE("Netzwerk-Loader"),
|
||||
STR_FR("Chargeur de programme"),
|
||||
STR_FR("NetLoader"),
|
||||
STR_IT("Caricamento programmi"),
|
||||
STR_JP("ネットローダ"),
|
||||
STR_PT("Carregador de programas"),
|
||||
@ -792,7 +816,7 @@ const char* const g_strings[StrId_Max][17] =
|
||||
STR_EN("The NetLoader is currently unavailable."),
|
||||
STR_ES("El cargador de programas no está disponible."),
|
||||
STR_DE("Der Netzwerk-Loader ist zur Zeit nicht verfügbar."),
|
||||
STR_FR("Le chargeur de programme nxlink est indisponible."),
|
||||
STR_FR("Le programme nxlink est indisponible."),
|
||||
STR_IT("Il caricamento programmi nxlink non è disponibile."),
|
||||
STR_JP("nxlinkネットローダは現在利用できません。"),
|
||||
STR_PT("O carregador de programas está de momento indisponível."),
|
||||
@ -825,10 +849,11 @@ const char* const g_strings[StrId_Max][17] =
|
||||
STR_DE("Offline, warte auf Netzwerk…"),
|
||||
STR_FR("Hors-ligne, en attente d'une connection..."),
|
||||
STR_IT("Disconnesso, in attesa della connessione…"),
|
||||
STR_ES("Desconectado, esperando a la red..."),
|
||||
STR_JP("オフラインです。ネットワーク接続を待っています…"),
|
||||
STR_KO("연결 끊김, 네트워크 기다리는 중…"),
|
||||
STR_ZH_HANS("无法连接网络,等待网络连接…"),
|
||||
STR_ZH_HANT("當前離線,等待網路連線…"),
|
||||
STR_ZH_HANT("目前已離線,等待網路連線…"),
|
||||
},
|
||||
|
||||
[StrId_NetLoaderActive] =
|
||||
@ -935,4 +960,3 @@ const char* const g_strings[StrId_Max][17] =
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -11,6 +11,7 @@ typedef enum
|
||||
StrId_DefaultPublisher,
|
||||
StrId_IOError,
|
||||
StrId_CouldNotOpenFile,
|
||||
StrId_NroNotFound,
|
||||
|
||||
StrId_NoAppsFound_Title,
|
||||
StrId_NoAppsFound_Msg,
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "common.h"
|
||||
#include <physfs.h>
|
||||
|
||||
void menuEntryInit(menuEntry_s* me, MenuEntryType type) {
|
||||
memset(me, 0, sizeof(*me));
|
||||
@ -80,9 +81,13 @@ static bool menuEntryLoadEmbeddedIcon(menuEntry_s* me) {
|
||||
return ok;
|
||||
}
|
||||
|
||||
static bool menuEntryLoadExternalIcon(menuEntry_s* me, const char* path) {
|
||||
static bool menuEntryLoadExternalIcon(menuEntry_s* me, const char* path, bool data_source) {
|
||||
struct stat st;
|
||||
|
||||
if (data_source) {
|
||||
return assetsPhysfsReadFile(path, &me->icon, &me->icon_size, false);
|
||||
}
|
||||
|
||||
if(stat(path, &st)==-1) return false;
|
||||
|
||||
FILE* f = fopen(path, "rb");
|
||||
@ -326,7 +331,7 @@ bool menuEntryLoad(menuEntry_s* me, const char* name, bool shortcut, bool check_
|
||||
char* ext = getExtension(tempbuf);
|
||||
|
||||
strcpy(ext, ".jpg");
|
||||
iconLoaded = menuEntryLoadExternalIcon(me, tempbuf);
|
||||
iconLoaded = menuEntryLoadExternalIcon(me, tempbuf, false);
|
||||
if (iconLoaded) break;
|
||||
|
||||
if (isOldAppFolder)
|
||||
@ -334,7 +339,7 @@ bool menuEntryLoad(menuEntry_s* me, const char* name, bool shortcut, bool check_
|
||||
char* slash = getSlash(tempbuf);
|
||||
|
||||
strcpy(slash, "/icon.jpg");
|
||||
iconLoaded = menuEntryLoadExternalIcon(me, tempbuf);
|
||||
iconLoaded = menuEntryLoadExternalIcon(me, tempbuf, false);
|
||||
if (iconLoaded) break;
|
||||
}*/
|
||||
|
||||
@ -408,18 +413,43 @@ bool menuEntryLoad(menuEntry_s* me, const char* name, bool shortcut, bool check_
|
||||
*version = "1.0.0";
|
||||
|
||||
const char* cfg_path = me->path;
|
||||
#ifdef __SWITCH__
|
||||
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 (config_read_file(&cfg, cfg_path)) {
|
||||
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");
|
||||
if (themeInfo != NULL) {
|
||||
if(config_setting_lookup_string(themeInfo, "name", &name))
|
||||
@ -433,15 +463,17 @@ bool menuEntryLoad(menuEntry_s* me, const char* name, bool shortcut, bool check_
|
||||
strncpy(me->version, version, sizeof(me->version)-1);
|
||||
config_destroy(&cfg);
|
||||
|
||||
#ifdef __SWITCH__
|
||||
if (is_romfs) {
|
||||
if (good_cfg && is_archive) {
|
||||
bool iconLoaded = false;
|
||||
|
||||
iconLoaded = menuEntryLoadExternalIcon(me, "themetmp:/icon.jpg");
|
||||
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
|
||||
}
|
||||
@ -475,7 +507,7 @@ bool menuEntryLoad(menuEntry_s* me, const char* name, bool shortcut, bool check_
|
||||
|
||||
bool iconLoaded = false;
|
||||
|
||||
iconLoaded = menuEntryLoadExternalIcon(me, tempbuf);
|
||||
iconLoaded = menuEntryLoadExternalIcon(me, tempbuf, false);
|
||||
|
||||
if (iconLoaded) menuEntryParseIcon(me);
|
||||
|
||||
@ -560,8 +592,8 @@ void menuEntryFileassocLoad(const char* filepath) {
|
||||
char target_file_extension[PATH_MAX+1];
|
||||
char target_filename[PATH_MAX+1];
|
||||
|
||||
char app_author[ENTRY_AUTHORLENGTH+1];
|
||||
char app_version[ENTRY_VERLENGTH+1];
|
||||
char app_author[ENTRY_AUTHORLENGTH+2];
|
||||
char app_version[ENTRY_VERLENGTH+2];
|
||||
|
||||
uint8_t *app_icon_gfx = NULL;
|
||||
uint8_t *app_icon_gfx_small = NULL;
|
||||
@ -655,8 +687,8 @@ void menuEntryFileassocLoad(const char* filepath) {
|
||||
}
|
||||
me->fileassoc_str[sizeof(me->fileassoc_str)-1] = 0;
|
||||
|
||||
if (target_icon_path[0]) iconLoaded = menuEntryLoadExternalIcon(me, target_icon_path);
|
||||
if (!iconLoaded && main_icon_path[0]) iconLoaded = menuEntryLoadExternalIcon(me, main_icon_path);
|
||||
if (target_icon_path[0]) iconLoaded = menuEntryLoadExternalIcon(me, target_icon_path, false);
|
||||
if (!iconLoaded && main_icon_path[0]) iconLoaded = menuEntryLoadExternalIcon(me, main_icon_path, false);
|
||||
|
||||
if (iconLoaded) {
|
||||
menuEntryParseIcon(me);
|
||||
|
@ -35,6 +35,7 @@ static void _menuAddEntry(menu_s *m, menuEntry_s* me) {
|
||||
m->lastEntry = me;
|
||||
}
|
||||
m->xPos = 0;
|
||||
m->slideSpeed = 0;
|
||||
m->nEntries ++;
|
||||
}
|
||||
|
||||
@ -59,6 +60,7 @@ static void menuAddEntryToFront(menuEntry_s* me) {
|
||||
m->lastEntry = me;
|
||||
}
|
||||
m->xPos = 0;
|
||||
m->slideSpeed = 0;
|
||||
m->nEntries ++;
|
||||
}
|
||||
|
||||
@ -244,8 +246,23 @@ int themeMenuScan(const char* target) {
|
||||
memset(tmp_path, 0, sizeof(tmp_path));
|
||||
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);
|
||||
if (strcasecmp(ext, ".cfg")==0 || strcasecmp(ext, ".romfs")==0)
|
||||
if (entrytype || strcasecmp(ext, ".cfg")==0 || strcasecmp(ext, ".romfs")==0 || strcasecmp(ext, ".zip")==0)
|
||||
me = menuCreateEntry(ENTRY_TYPE_THEME);
|
||||
|
||||
if (!me)
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include "switch/runtime/nxlink.h"
|
||||
#endif
|
||||
|
||||
double menuTimer;
|
||||
|
||||
char rootPathBase[PATH_MAX];
|
||||
char rootPath[PATH_MAX+8];
|
||||
|
||||
@ -591,7 +593,7 @@ u32 drawStatus() {
|
||||
if (statusGet(&netstatusFlag, &id, &temperatureFlag, &temperature)) {
|
||||
if (netstatusFlag) drawNetwork(tmpX, id);
|
||||
if (temperatureFlag) {
|
||||
snprintf(tmpstr, sizeof(tmpstr)-1, "%.1f°C", ((float)temperature) / 1000);
|
||||
snprintf(tmpstr, sizeof(tmpstr)-1, "%d°C", temperature);
|
||||
DrawTextFromLayout(ThemeLayoutId_Temperature, themeCurrent.textColor, tmpstr);
|
||||
}
|
||||
}
|
||||
@ -798,14 +800,35 @@ void menuLoop(void) {
|
||||
int entries_count = layoutobj->posEnd[0];
|
||||
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MenuList];
|
||||
|
||||
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;
|
||||
v += (wanted_x - menu->xPos) / 3;
|
||||
v /= 2;
|
||||
// Gentle Realign only when not manually moving
|
||||
if (menu->slideSpeed == 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;
|
||||
v += (wanted_x - menu->xPos) / 3;
|
||||
v /= 2;
|
||||
}
|
||||
else {
|
||||
menu->xPos = v = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
menu->xPos = v = 0;
|
||||
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;
|
||||
|
@ -33,6 +33,7 @@ struct menu_s_tag
|
||||
int nEntries;
|
||||
int curEntry;
|
||||
int xPos;
|
||||
int slideSpeed;
|
||||
|
||||
char dirname[PATH_MAX+1];
|
||||
};
|
||||
@ -77,7 +78,7 @@ typedef enum
|
||||
IMAGE_MODE_RGBA32
|
||||
} ImageMode;
|
||||
|
||||
double menuTimer;
|
||||
extern double menuTimer;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "theme.h"
|
||||
#include <physfs.h>
|
||||
|
||||
theme_t themeCurrent;
|
||||
ThemePreset themeGlobalPreset;
|
||||
@ -82,9 +83,9 @@ bool assetObjectFromSetting(config_setting_t *asset_setting, AssetId id, ThemeLa
|
||||
return false;
|
||||
|
||||
memset(tmp_path, 0, sizeof(tmp_path));
|
||||
snprintf(tmp_path, sizeof(tmp_path)-1, "theme:/%s", path);
|
||||
snprintf(tmp_path, sizeof(tmp_path)-1, "theme/%s", path);
|
||||
|
||||
return assetsLoadFromTheme(id, tmp_path, imageSize);
|
||||
return assetsLoadData(id, tmp_path, imageSize);
|
||||
}
|
||||
|
||||
void themeStartup(ThemePreset preset) {
|
||||
@ -419,25 +420,48 @@ void themeStartup(ThemePreset preset) {
|
||||
const char *AText, *BText, *XText, *YText, *PText, *MText, *starOnText, *starOffText;
|
||||
bool logoColor_set = 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) {
|
||||
const char* cfg_path = themePath;
|
||||
#ifdef __SWITCH__
|
||||
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) good_cfg = config_read_file(&cfg, cfg_path);
|
||||
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) {
|
||||
@ -583,8 +607,8 @@ void themeStartup(ThemePreset preset) {
|
||||
layoutObjectFromSetting(config_setting_lookup(layout, "menuActiveEntryVersion"), &themeCurrent.layoutObjects[ThemeLayoutId_MenuActiveEntryVersion], false);
|
||||
}
|
||||
|
||||
if (is_romfs) assets = config_lookup(&cfg, "assets");
|
||||
if (is_romfs && assets) {
|
||||
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]);
|
||||
@ -622,6 +646,7 @@ void themeStartup(ThemePreset preset) {
|
||||
|
||||
config_destroy(&cfg);
|
||||
|
||||
if (is_archive) PHYSFS_unmount(theme_archive_path);
|
||||
#ifdef __SWITCH__
|
||||
if (is_romfs) romfsUnmount("theme");
|
||||
#endif
|
||||
|
@ -68,15 +68,26 @@ static void launchFile(const char* path, argData_s* args)
|
||||
|
||||
init_args(argBuf, sizeof(argBuf)-1, args->buf, sizeof(args->buf));
|
||||
|
||||
Result rc = envSetNextLoad(path, argBuf);
|
||||
if(R_FAILED(rc)) {
|
||||
struct stat st;
|
||||
|
||||
if (stat(path, &st) == -1) {
|
||||
memset(msg, 0, sizeof(msg));
|
||||
snprintf(msg, sizeof(msg)-1, "%s\n0x%x", textGetString(StrId_AppLaunchError), rc);
|
||||
snprintf(msg, sizeof(msg)-1, textGetString(StrId_NroNotFound), path);
|
||||
|
||||
menuCreateMsgBox(780, 300, msg);
|
||||
menuScan(".");
|
||||
}
|
||||
else {
|
||||
uiExitLoop();
|
||||
Result rc = envSetNextLoad(path, argBuf);
|
||||
if(R_FAILED(rc)) {
|
||||
memset(msg, 0, sizeof(msg));
|
||||
snprintf(msg, sizeof(msg)-1, "%s\n2%03d-%04d", textGetString(StrId_AppLaunchError), R_MODULE(rc), R_DESCRIPTION(rc));
|
||||
|
||||
menuCreateMsgBox(780, 300, msg);
|
||||
}
|
||||
else {
|
||||
uiExitLoop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,19 +1,22 @@
|
||||
#include <switch.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <physfs.h>
|
||||
|
||||
#include "../common/common.h"
|
||||
#include "nx_graphics.h"
|
||||
#include "nx_touch.h"
|
||||
|
||||
// Define the desired framebuffer resolution (here we set it to 720p).
|
||||
#define FB_WIDTH 1280
|
||||
#define FB_HEIGHT 720
|
||||
|
||||
Framebuffer g_framebufObj;
|
||||
|
||||
uint8_t* g_framebuf;
|
||||
u32 g_framebuf_width;
|
||||
|
||||
PadState g_pad;
|
||||
PadRepeater g_pad_repeater;
|
||||
|
||||
bool menuUpdateErrorScreen(void);
|
||||
|
||||
#ifdef PERF_LOG
|
||||
@ -39,35 +42,44 @@ int main(int argc, char **argv)
|
||||
u64 start_tick=0;
|
||||
#endif
|
||||
|
||||
padConfigureInput(8, HidNpadStyleSet_NpadStandard);
|
||||
padInitializeAny(&g_pad);
|
||||
padRepeaterInitialize(&g_pad_repeater, 20, 10);
|
||||
hidSetNpadHandheldActivationMode(HidNpadHandheldActivationMode_Single);
|
||||
touchInit();
|
||||
|
||||
memset(errormsg, 0, sizeof(errormsg));
|
||||
|
||||
appletLockExit();
|
||||
appletSetScreenShotPermission(AppletScreenShotPermission_Enable);
|
||||
|
||||
ColorSetId theme;
|
||||
ColorSetId theme = ColorSetId_Light;
|
||||
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)) {
|
||||
rc = plInitialize();
|
||||
if (R_FAILED(rc)) snprintf(errormsg, sizeof(errormsg)-1, "Error: plInitialize() failed: 0x%x.", rc);
|
||||
setsysGetColorSetId(&theme);
|
||||
setsysExit();
|
||||
}
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
rc = textInit();
|
||||
if (R_FAILED(rc)) {
|
||||
snprintf(errormsg, sizeof(errormsg)-1, "Error: textInit() failed: 0x%x.", rc);
|
||||
snprintf(errormsg, sizeof(errormsg)-1, "Error: textInit() failed: 2%03d-%04d", R_MODULE(rc), R_DESCRIPTION(rc));
|
||||
}
|
||||
}
|
||||
|
||||
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)) {
|
||||
rc = assetsInit();
|
||||
if (R_FAILED(rc)) {
|
||||
snprintf(errormsg, sizeof(errormsg)-1, "Error: assetsInit() failed: 0x%x.", rc);
|
||||
snprintf(errormsg, sizeof(errormsg)-1, "Error: assetsInit() failed: 2%03d-%04d", R_MODULE(rc), R_DESCRIPTION(rc));
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,7 +90,7 @@ int main(int argc, char **argv)
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
rc = netloaderInit();
|
||||
if (R_FAILED(rc)) {
|
||||
snprintf(errormsg, sizeof(errormsg)-1, "Error: netloaderInit() failed: 0x%x.", rc);
|
||||
snprintf(errormsg, sizeof(errormsg)-1, "Error: netloaderInit() failed: 2%03d-%04d", R_MODULE(rc), R_DESCRIPTION(rc));
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,7 +127,7 @@ int main(int argc, char **argv)
|
||||
|
||||
if (R_FAILED(lastret)) {
|
||||
memset(msg, 0, sizeof(msg));
|
||||
snprintf(msg, sizeof(msg)-1, "%s\n0x%x", textGetString(StrId_LastLoadResult), lastret);
|
||||
snprintf(msg, sizeof(msg)-1, "%s\n2%03d-%04d", textGetString(StrId_LastLoadResult), R_MODULE(lastret), R_DESCRIPTION(lastret));
|
||||
|
||||
menuCreateMsgBox(780, 300, msg);
|
||||
}
|
||||
@ -124,8 +136,7 @@ int main(int argc, char **argv)
|
||||
if (errormsg[0]) error_screen = 1;
|
||||
|
||||
if (!error_screen) {
|
||||
framebufferCreate(&g_framebufObj, nwindowGetDefault(), FB_WIDTH, FB_HEIGHT, PIXEL_FORMAT_RGBA_8888, 2);
|
||||
framebufferMakeLinear(&g_framebufObj);
|
||||
graphicsInit(FB_WIDTH, FB_HEIGHT);
|
||||
}
|
||||
else {
|
||||
consoleInit(NULL);
|
||||
@ -135,16 +146,17 @@ int main(int argc, char **argv)
|
||||
|
||||
while (appletMainLoop())
|
||||
{
|
||||
|
||||
|
||||
//Scan all the inputs. This should be done once for each frame
|
||||
hidScanInput();
|
||||
// Scan the gamepad. This should be done once for each frame
|
||||
padUpdate(&g_pad);
|
||||
padRepeaterUpdate(&g_pad_repeater, padGetButtons(&g_pad) & (
|
||||
HidNpadButton_AnyLeft | HidNpadButton_AnyUp | HidNpadButton_AnyRight | HidNpadButton_AnyDown
|
||||
));
|
||||
|
||||
if (!error_screen) {
|
||||
if (!uiUpdate()) break;
|
||||
g_framebuf = framebufferBegin(&g_framebufObj, &g_framebuf_width);
|
||||
g_framebuf = graphicsFrameBegin(&g_framebuf_width);
|
||||
#ifdef PERF_LOG
|
||||
start_tick = svcGetSystemTick();
|
||||
start_tick = armGetSystemTick();
|
||||
#endif
|
||||
memset(g_framebuf, 237, g_framebuf_width * FB_HEIGHT);
|
||||
menuLoop();
|
||||
@ -154,10 +166,10 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (!error_screen) {
|
||||
framebufferEnd(&g_framebufObj);
|
||||
graphicsFrameEnd();
|
||||
|
||||
#ifdef PERF_LOG
|
||||
g_tickdiff_frame = svcGetSystemTick() - start_tick;
|
||||
g_tickdiff_frame = armGetSystemTick() - start_tick;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
@ -166,7 +178,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (!error_screen) {
|
||||
framebufferClose(&g_framebufObj);
|
||||
graphicsExit();
|
||||
}
|
||||
else {
|
||||
consoleExit(NULL);
|
||||
@ -185,8 +197,7 @@ int main(int argc, char **argv)
|
||||
netloaderExit();
|
||||
powerExit();
|
||||
assetsExit();
|
||||
plExit();
|
||||
setsysExit();
|
||||
PHYSFS_deinit();
|
||||
|
||||
appletUnlockExit();
|
||||
|
||||
@ -194,14 +205,9 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
u64 menuGetKeysDown(void) {
|
||||
u64 down = 0;
|
||||
|
||||
for (u32 controller=0; controller<8; controller++) {
|
||||
if (hidIsControllerConnected(controller)) down |= hidKeysDown(controller);
|
||||
}
|
||||
if (hidIsControllerConnected(CONTROLLER_HANDHELD)) down |= hidKeysDown(CONTROLLER_HANDHELD);
|
||||
|
||||
return down;
|
||||
u64 keys = padGetButtonsDown(&g_pad);
|
||||
keys |= padRepeaterGetButtons(&g_pad_repeater);
|
||||
return keys;
|
||||
}
|
||||
|
||||
//This is implemented here due to the hid code.
|
||||
@ -214,26 +220,26 @@ bool menuUpdate(void) {
|
||||
|
||||
handleTouch(menu);
|
||||
|
||||
if (down & KEY_Y)
|
||||
if (down & HidNpadButton_Y)
|
||||
{
|
||||
launchMenuNetloaderTask();
|
||||
}
|
||||
else if (down & KEY_X)
|
||||
else if (down & HidNpadButton_X)
|
||||
{
|
||||
menuHandleXButton();
|
||||
}
|
||||
else if (down & KEY_A)
|
||||
else if (down & HidNpadButton_A)
|
||||
{
|
||||
menuHandleAButton();
|
||||
}
|
||||
else if (down & KEY_B)
|
||||
else if (down & HidNpadButton_B)
|
||||
{
|
||||
launchMenuBackTask();
|
||||
}
|
||||
else if(down & KEY_MINUS){
|
||||
else if(down & HidNpadButton_Minus){
|
||||
themeMenuStartup();
|
||||
}
|
||||
else if (down & KEY_PLUS)
|
||||
else if (down & HidNpadButton_Plus)
|
||||
{
|
||||
exitflag = 1;
|
||||
}
|
||||
@ -241,10 +247,10 @@ bool menuUpdate(void) {
|
||||
{
|
||||
int move = 0;
|
||||
|
||||
if (down & KEY_LEFT) move--;
|
||||
if (down & KEY_RIGHT) move++;
|
||||
if (down & KEY_DOWN) move-=entries_count;
|
||||
if (down & KEY_UP) move+=entries_count;
|
||||
if (down & HidNpadButton_AnyLeft) move--;
|
||||
if (down & HidNpadButton_AnyRight) move++;
|
||||
if (down & HidNpadButton_AnyDown) move-=entries_count;
|
||||
if (down & HidNpadButton_AnyUp) move+=entries_count;
|
||||
|
||||
int newEntry = menu->curEntry + move;
|
||||
if (newEntry < 0) newEntry = 0;
|
||||
@ -259,7 +265,7 @@ bool menuUpdateErrorScreen(void) {
|
||||
bool exitflag = 0;
|
||||
u64 down = menuGetKeysDown();
|
||||
|
||||
if (down & KEY_PLUS)
|
||||
if (down & HidNpadButton_Plus)
|
||||
{
|
||||
exitflag = 1;
|
||||
}
|
||||
|
141
nx_main/nx_graphics.c
Normal file
141
nx_main/nx_graphics.c
Normal file
@ -0,0 +1,141 @@
|
||||
#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, ©Rect, 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);
|
||||
}
|
9
nx_main/nx_graphics.h
Normal file
9
nx_main/nx_graphics.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <switch.h>
|
||||
|
||||
void graphicsInit(u32 width, u32 height);
|
||||
void graphicsExit(void);
|
||||
|
||||
void* graphicsFrameBegin(u32* out_stride);
|
||||
void graphicsFrameEnd(void);
|
@ -8,7 +8,7 @@ static bool powerCacheIsCharging;
|
||||
static PsmSession powerSession;
|
||||
|
||||
bool powerGetDetails(uint32_t *batteryCharge, bool *isCharging) {
|
||||
ChargerType charger = ChargerType_None;
|
||||
PsmChargerType charger = PsmChargerType_Unconnected;
|
||||
bool hwReadsSucceeded = false;
|
||||
bool use_cache = false;
|
||||
Result rc = 0;
|
||||
@ -31,7 +31,7 @@ bool powerGetDetails(uint32_t *batteryCharge, bool *isCharging) {
|
||||
else {
|
||||
rc = psmGetChargerType(&charger);
|
||||
hwReadsSucceeded &= R_SUCCEEDED(rc);
|
||||
*isCharging = (charger > ChargerType_None);
|
||||
*isCharging = (charger != PsmChargerType_Unconnected);
|
||||
}
|
||||
|
||||
powerCacheCharge = *batteryCharge;
|
||||
|
@ -9,6 +9,6 @@ void thermalstatusExit(void) {
|
||||
}
|
||||
|
||||
bool thermalstatusGetDetails(s32 *temperature) {
|
||||
return R_SUCCEEDED(tsGetTemperatureMilliC(TsLocation_Internal, temperature));
|
||||
return R_SUCCEEDED(tsGetTemperature(TsLocation_Internal, temperature));
|
||||
}
|
||||
|
||||
|
@ -10,11 +10,13 @@
|
||||
|
||||
struct touchInfo_s touchInfo;
|
||||
|
||||
void touchInit() {
|
||||
void touchInit(void) {
|
||||
touchInfo.gestureInProgress = false;
|
||||
touchInfo.isTap = true;
|
||||
touchInfo.initMenuXPos = 0;
|
||||
touchInfo.initMenuIndex = 0;
|
||||
touchInfo.lastSlideSpeed = 0;
|
||||
hidInitializeTouchScreen();
|
||||
}
|
||||
|
||||
void handleTappingOnApp(menu_s* menu, int px) {
|
||||
@ -55,50 +57,50 @@ static inline bool checkInsideTextLayoutObject(ThemeLayoutId id, int x, int y) {
|
||||
|
||||
void handleTouch(menu_s* menu) {
|
||||
ThemeLayoutObject *layoutobj = NULL;
|
||||
touchPosition currentTouch;
|
||||
u32 touches = hidTouchCount();
|
||||
HidTouchScreenState touch = {0};
|
||||
hidGetTouchScreenStates(&touch, 1);
|
||||
|
||||
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MenuListTiles];
|
||||
int entries_count = layoutobj->posEnd[0];
|
||||
layoutobj = &themeCurrent.layoutObjects[ThemeLayoutId_MenuList];
|
||||
|
||||
// On touch start.
|
||||
if (touches == 1 && !touchInfo.gestureInProgress) {
|
||||
hidTouchRead(¤tTouch, 0);
|
||||
|
||||
if (touch.count == 1 && !touchInfo.gestureInProgress) {
|
||||
touchInfo.gestureInProgress = true;
|
||||
touchInfo.firstTouch = currentTouch;
|
||||
touchInfo.prevTouch = currentTouch;
|
||||
touchInfo.firstTouch = touch.touches[0];
|
||||
touchInfo.prevTouch = touch.touches[0];
|
||||
touchInfo.isTap = true;
|
||||
touchInfo.initMenuXPos = menu->xPos;
|
||||
touchInfo.initMenuIndex = menu->curEntry;
|
||||
touchInfo.lastSlideSpeed = 0;
|
||||
menu->slideSpeed = 0;
|
||||
}
|
||||
// On touch moving.
|
||||
else if (touches >= 1 && touchInfo.gestureInProgress) {
|
||||
hidTouchRead(¤tTouch, 0);
|
||||
else if (touch.count >= 1 && touchInfo.gestureInProgress) {
|
||||
touchInfo.lastSlideSpeed = ((int)(touch.touches[0].x - touchInfo.prevTouch.x));
|
||||
|
||||
touchInfo.prevTouch = currentTouch;
|
||||
touchInfo.prevTouch = touch.touches[0];
|
||||
|
||||
if (touchInfo.isTap && (abs(touchInfo.firstTouch.px - currentTouch.px) > TAP_MOVEMENT_GAP || abs(touchInfo.firstTouch.py - currentTouch.py) > TAP_MOVEMENT_GAP)) {
|
||||
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)) {
|
||||
touchInfo.isTap = false;
|
||||
}
|
||||
if (!menuIsMsgBoxOpen() && touchInfo.firstTouch.py > layoutobj->posStart[1] && touchInfo.firstTouch.py < layoutobj->posStart[1]+layoutobj->size[1] && !touchInfo.isTap && menu->nEntries > entries_count) {
|
||||
menu->xPos = touchInfo.initMenuXPos + (currentTouch.px - touchInfo.firstTouch.px);
|
||||
menu->curEntry = touchInfo.initMenuIndex + ((int) (touchInfo.firstTouch.px - currentTouch.px) / layoutobj->posEnd[0]);
|
||||
if (!menuIsMsgBoxOpen() && touchInfo.firstTouch.y > layoutobj->posStart[1] && touchInfo.firstTouch.y < layoutobj->posStart[1]+layoutobj->size[1] && !touchInfo.isTap && menu->nEntries > entries_count) {
|
||||
|
||||
if (menu->curEntry < 0)
|
||||
menu->curEntry = 0;
|
||||
|
||||
if (menu->curEntry >= menu->nEntries - entries_count - 1)
|
||||
menu->curEntry = menu->nEntries - entries_count;
|
||||
if (!touchInfo.isTap) {
|
||||
menu->slideSpeed = touchInfo.lastSlideSpeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
// On touch end.
|
||||
else if (touchInfo.gestureInProgress) {
|
||||
int x1 = touchInfo.firstTouch.px;
|
||||
int y1 = touchInfo.firstTouch.py;
|
||||
int x2 = touchInfo.prevTouch.px;
|
||||
int y2 = touchInfo.prevTouch.py;
|
||||
int x1 = touchInfo.firstTouch.x;
|
||||
int y1 = touchInfo.firstTouch.y;
|
||||
int x2 = touchInfo.prevTouch.x;
|
||||
int y2 = touchInfo.prevTouch.y;
|
||||
|
||||
if (!touchInfo.isTap) {
|
||||
menu->slideSpeed = touchInfo.lastSlideSpeed;
|
||||
}
|
||||
|
||||
bool netloader_active = menuIsNetloaderActive();
|
||||
|
||||
@ -117,7 +119,7 @@ void handleTouch(menu_s* menu) {
|
||||
} else if (touchInfo.isTap && !netloader_active) {
|
||||
// App Icons
|
||||
if (y1 > layoutobj->posStart[1] && y1 < layoutobj->posStart[1]+layoutobj->size[1]) {
|
||||
handleTappingOnApp(menu, touchInfo.prevTouch.px);
|
||||
handleTappingOnApp(menu, touchInfo.prevTouch.x);
|
||||
}
|
||||
// Bottom Buttons
|
||||
else {
|
||||
|
@ -5,11 +5,13 @@
|
||||
|
||||
struct touchInfo_s {
|
||||
bool gestureInProgress;
|
||||
touchPosition firstTouch;
|
||||
touchPosition prevTouch;
|
||||
HidTouchState firstTouch;
|
||||
HidTouchState prevTouch;
|
||||
bool isTap;
|
||||
int initMenuXPos;
|
||||
int initMenuIndex;
|
||||
int lastSlideSpeed;
|
||||
};
|
||||
|
||||
void touchInit(void);
|
||||
void handleTouch(menu_s* menu);
|
@ -1,6 +1,7 @@
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <physfs.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
@ -10,12 +11,13 @@ extern "C" {
|
||||
|
||||
color_t pixels[720][1280];
|
||||
|
||||
int main()
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
sf::RenderWindow window(sf::VideoMode(1280, 720), "Test");
|
||||
window.setFramerateLimit(60);
|
||||
|
||||
menuStartupPath();
|
||||
PHYSFS_init(argv[0]);
|
||||
assetsInit();
|
||||
themeStartup(THEME_PRESET_LIGHT);
|
||||
textInit();
|
||||
@ -62,6 +64,7 @@ int main()
|
||||
netloaderExit();
|
||||
fontExit();
|
||||
assetsExit();
|
||||
PHYSFS_deinit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
BIN
resources/eth_none_icon.png
Normal file
BIN
resources/eth_none_icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 481 B |
Loading…
Reference in New Issue
Block a user