From 6ec7388834c9acd330638fcd26845d518fc803dd Mon Sep 17 00:00:00 2001 From: fincs Date: Tue, 26 Mar 2019 23:12:39 +0100 Subject: [PATCH 01/22] Update makefile --- Makefile.nx | 52 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/Makefile.nx b/Makefile.nx index 59f3955..beb7691 100644 --- a/Makefile.nx +++ b/Makefile.nx @@ -15,7 +15,6 @@ include $(DEVKITPRO)/libnx/switch_rules # SOURCES is a list of directories containing source code # DATA is a list of directories containing data files # INCLUDES is a list of directories containing header files -# EXEFS_SRC is the optional input directory containing data copied into exefs, if anything this normally should only contain "main.npdm". # ROMFS is the directory containing data to be added to RomFS, relative to the Makefile (Optional) # # NO_ICON: if set to anything, do not use icon. @@ -29,13 +28,20 @@ include $(DEVKITPRO)/libnx/switch_rules # - .jpg # - icon.jpg # - /default_icon.jpg +# +# CONFIG_JSON is the filename of the NPDM config file (.json), relative to the project folder. +# If not set, it attempts to use one of the following (in this order): +# - .json +# - config.json +# If a JSON file is provided or autodetected, an ExeFS PFS0 (.nsp) is built instead +# of a homebrew executable (.nro). This is intended to be used for sysmodules. +# NACP building is skipped as well. #--------------------------------------------------------------------------------- TARGET := $(notdir $(CURDIR)) BUILD := build SOURCES := common/ nx_main/ nx_main/loaders/ DATA := data INCLUDES := include -EXEFS_SRC := exefs_src ROMFS := romfs DIST_PATH := $(TARGET)_v$(APP_VERSION) @@ -109,7 +115,18 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) -export BUILD_EXEFS_SRC := $(TOPDIR)/$(EXEFS_SRC) +ifeq ($(strip $(CONFIG_JSON)),) + jsons := $(wildcard *.json) + ifneq (,$(findstring $(TARGET).json,$(jsons))) + export APP_JSON := $(TOPDIR)/$(TARGET).json + else + ifneq (,$(findstring config.json,$(jsons))) + export APP_JSON := $(TOPDIR)/config.json + endif + endif +else + export APP_JSON := $(TOPDIR)/$(CONFIG_JSON) +endif ifeq ($(strip $(ICON)),) icons := $(wildcard *.jpg) @@ -152,7 +169,11 @@ $(BUILD): #--------------------------------------------------------------------------------- clean: @echo clean ... - @rm -fr $(BUILD) $(TARGET).pfs0 $(TARGET).nso $(TARGET).nro $(TARGET).nacp $(TARGET).elf +ifeq ($(strip $(APP_JSON)),) + @rm -fr $(BUILD) $(TARGET).nro $(TARGET).nacp $(TARGET).elf +else + @rm -fr $(BUILD) $(TARGET).nsp $(TARGET).nso $(TARGET).npdm $(TARGET).elf +endif #--------------------------------------------------------------------------------- dist-bin: all @@ -169,11 +190,9 @@ DEPENDS := $(OFILES:.o=.d) #--------------------------------------------------------------------------------- # main targets #--------------------------------------------------------------------------------- -all : $(OUTPUT).pfs0 $(OUTPUT).nro +ifeq ($(strip $(APP_JSON)),) -$(OUTPUT).pfs0 : $(OUTPUT).nso - -$(OUTPUT).nso : $(OUTPUT).elf +all : $(OUTPUT).nro ifeq ($(strip $(NO_NACP)),) $(OUTPUT).nro : $(OUTPUT).elf $(OUTPUT).nacp @@ -181,6 +200,16 @@ else $(OUTPUT).nro : $(OUTPUT).elf endif +else + +all : $(OUTPUT).nsp + +$(OUTPUT).nsp : $(OUTPUT).nso $(OUTPUT).npdm + +$(OUTPUT).nso : $(OUTPUT).elf + +endif + $(OUTPUT).elf : $(OFILES) $(OFILES_SRC) : $(HFILES_BIN) @@ -188,12 +217,7 @@ $(OFILES_SRC) : $(HFILES_BIN) #--------------------------------------------------------------------------------- # you need a rule like this for each extension you use as binary data #--------------------------------------------------------------------------------- -%.bin.o %_bin.h: %.bin -#--------------------------------------------------------------------------------- - @echo $(notdir $<) - @$(bin2o) - -%.nxfnt.o : %.nxfnt +%.bin.o %_bin.h : %.bin #--------------------------------------------------------------------------------- @echo $(notdir $<) @$(bin2o) From 85318335fb40977168240c6f83fedcba32544c5d Mon Sep 17 00:00:00 2001 From: yellows8 Date: Mon, 17 Jun 2019 18:56:38 -0400 Subject: [PATCH 02/22] Fixed slowdown due to drawing too many menu entries. Closes #84. --- common/menu.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/common/menu.c b/common/menu.c index 3a2dc90..e6b8b70 100644 --- a/common/menu.c +++ b/common/menu.c @@ -614,6 +614,7 @@ void menuLoop(void) { // Draw menu entries for (me = menu->firstEntry, i = 0; me; me = me->next, i ++) { int entry_start_x = 29 + i * (140 + 30); + int entry_draw_x = entry_start_x + menu->xPos; int screen_width = 1280; if (entry_start_x >= (screen_width - menu->xPos)) @@ -624,7 +625,10 @@ void menuLoop(void) { if (is_active) active_entry = me; - drawEntry(me, entry_start_x + menu->xPos, is_active); + if (entry_draw_x < -(29 + 140 + 30)) + continue; + + drawEntry(me, entry_draw_x, is_active); } int getX = GetTextXCoordinate(interuiregular18, 1180, textGetString(StrId_ThemeMenu), 'r'); From 527ecb6ce308ee8030cf820da0f3155bf01529cc Mon Sep 17 00:00:00 2001 From: yellows8 Date: Mon, 17 Jun 2019 19:27:59 -0400 Subject: [PATCH 03/22] Fixed regression caused by 8531833 where the gfx for the current active menu entry wasn't rendered in some cases. --- common/menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/menu.c b/common/menu.c index e6b8b70..cc00267 100644 --- a/common/menu.c +++ b/common/menu.c @@ -625,7 +625,7 @@ void menuLoop(void) { if (is_active) active_entry = me; - if (entry_draw_x < -(29 + 140 + 30)) + if (!is_active && entry_draw_x < -(29 + 140 + 30)) continue; drawEntry(me, entry_draw_x, is_active); From e91758984c359cc80205b1e08a250a4e84cf7198 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Thu, 20 Jun 2019 17:34:04 -0400 Subject: [PATCH 04/22] Display a netstatus icon. Updated/added icons from #79. Closes #79. --- Makefile.pc | 2 +- assets/airplane_icon.bin | Bin 0 -> 2304 bytes assets/battery_icon.bin | Bin 600 -> 2304 bytes assets/charging_icon.bin | Bin 540 -> 2304 bytes assets/eth_icon.bin | Bin 0 -> 2304 bytes assets/eth_none_icon.bin | Bin 0 -> 2304 bytes assets/wifi1_icon.bin | Bin 0 -> 2304 bytes assets/wifi2_icon.bin | Bin 0 -> 2304 bytes assets/wifi3_icon.bin | Bin 0 -> 2304 bytes assets/wifi_none_icon.bin | Bin 0 -> 2304 bytes common/assets.c | 7 +++++ common/assets.h | 7 +++++ common/common.h | 1 + common/menu.c | 59 ++++++++++++++++++++--------------- resources/airplane_icon.png | Bin 0 -> 3687 bytes resources/battery_icon.png | Bin 188 -> 1753 bytes resources/charging_icon.png | Bin 380 -> 3416 bytes resources/eth_icon.png | Bin 0 -> 405 bytes resources/wifi1_icon.png | Bin 0 -> 2401 bytes resources/wifi2_icon.png | Bin 0 -> 3680 bytes resources/wifi3_icon.png | Bin 0 -> 5134 bytes resources/wifi_none_icon.png | Bin 0 -> 4653 bytes 22 files changed, 49 insertions(+), 27 deletions(-) create mode 100644 assets/airplane_icon.bin create mode 100644 assets/eth_icon.bin create mode 100644 assets/eth_none_icon.bin create mode 100644 assets/wifi1_icon.bin create mode 100644 assets/wifi2_icon.bin create mode 100644 assets/wifi3_icon.bin create mode 100644 assets/wifi_none_icon.bin create mode 100644 resources/airplane_icon.png create mode 100644 resources/eth_icon.png create mode 100644 resources/wifi1_icon.png create mode 100644 resources/wifi2_icon.png create mode 100644 resources/wifi3_icon.png create mode 100644 resources/wifi_none_icon.png diff --git a/Makefile.pc b/Makefile.pc index dd65b1f..20c7cbc 100644 --- a/Makefile.pc +++ b/Makefile.pc @@ -9,7 +9,7 @@ EXTRA_CFLAGS="-D__USE_MINGW_ANSI_STDIO" EXTRA_LDFLAGS="-lws2_32" endif -test : pc_main/main.cpp pc_main/pc_launch.c pc_main/pc_power.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/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 \ diff --git a/assets/airplane_icon.bin b/assets/airplane_icon.bin new file mode 100644 index 0000000000000000000000000000000000000000..6ec4682cba40ffffe15b5d06f1a8541a22800901 GIT binary patch literal 2304 zcmeH|PfEi;6vi`IBwz^`jphJZv=``B50DCzjB7pM!DLKkk_ z_-7#qqQu_^GY|_+ry5sU_>tH5zW3#2I+<2g6;ywKD2hU3Oez$&{melS9Kem`uqcXF z*A?G0s4VB5PRF$Q4ET;}{-ZX%<@N91{GR>R`ea$gmN#4YkHPJqv2vc$2z}uAPK`T%Jclo`9fa_ zFP5_2FRgmiD-U_q>pn5QU3jo`eR?+0Fjt26tx&v4?>cRgBnICBJXr?Ht?Tot>zwDK zwYdhje-wAy_zz$$^zP2U?N_%SXR7(k*rdT@5AOwB!m&m1Lbaw|pPHS&XQ)_*h%5<>@s)XfEI0O9*UjBXxC3?`2*H_FEhuOS;I0MOuyTL1t6 diff --git a/assets/charging_icon.bin b/assets/charging_icon.bin index 634fb1227c5a1cf7160988fe86efbcc4816437ec..b0ccb8a8bc2df797e2694439bc83001e4f39cc79 100644 GIT binary patch literal 2304 zcmbuBJxjwt7=YWvHW5p;QYZ?7P;oA1b|^ThtIjTh;3_yOh={wQKSAtI5c~n6I18Nw z1qBh*LGdF#FI?aVmvXrT9+G==?{m42w=|C9QtUvzUN3VsDwT@wl0PV?-ENn-W?-8! z!a;pq-r*d>eGUiJYSnXbWaW6C7vSB2cUaHr=MoQsz{9x$FUsF_@tAU2trp7C9Na++ z&oFK3>k`8?0T=KG;=h%BaB-z`@QmO)hHvE-e~OAFYOd$xWQ5`zP;r zr7mpUS`A6A$(h7t>>iBUx@C^^mvy~|Wd5=iiBrGd5TBK`wDrp#k<$U$vt<8{c$PiY z-H)^vjeesOqyHb8Rr*L{@hc|eI)uO)%x?6q!n)2tWp|r=;R%d4qf36xb axlA!t$6NSw)sV?$iphTu&QGIA4gCXhLKVXR literal 540 zcmZQzzz#}FOLJRVTBNbdGBA{tm09TO>VC#0-_Xz?prfPn#lgYh2`)8mZf>`La{nVD zB6ea^6B84&4kQo4xw*MD=xVaEvT|5hSitfiHI8pvv@tE(+UL`43Aw{qmk05~!^3xj)BwZh4mNp^n60htGYt)mZ$LkY;8FvUFE1~*!zB+4ANl&u z3SuBd1bmS9`T5C{<$0dF`5%Ao9duonzyOLN6L+oO3jSc465^TsD}7IGZeW5tEN8%_ zhIWLztZ3!ctIo3n1JGey>4`f%p`999_xbdWb@aNkJnk2KGCulexYk|Yq>cTa!yi=x zC+8G-5{TZ)bJTbaU!?VOjPOY{Q1u2r&Zso*gSLRJ{(E{dcm*TKAh~CZ@C9u0_x`os z?`Y^xnhiGJ{nq~Mq;EWd3($_r_dZwAxF78wde!f!-b2t-yzfB0sMpUihFvJXC*mPiQZo1s{8`FQJBDcx)bjPc3of zh7n8rKA(LJ>QSqfwKiW)M6oi}wp^Fw#M~9JCe6iPSl%c06e=hnhZ#XK35ttZJ=B-wM0y7N0vhmX{Fr;Ra~SkJ IrhcmR1Bbx;NdN!< literal 0 HcmV?d00001 diff --git a/assets/wifi1_icon.bin b/assets/wifi1_icon.bin new file mode 100644 index 0000000000000000000000000000000000000000..03f842f85463b12343b6f9b1eb891ea4c6e33d6e GIT binary patch literal 2304 zcmeH{J8r^26h-avugJ(rB-j9@%WQy-6;M;K5z1r%u#!kf6qHD5TnC9dQb1WXIK)(ZlJCGzv8pm-7L!(rz>whK7G8aWr1+TD! zZ$nzKN;M(p!VR!q66YVSQGP1A(lIjmvKTpo&|a6(!!%gt4LufOVT z?%v*Igx|~v!$*H^$MMws%g}xAa{jH}3!-(nKL7v# literal 0 HcmV?d00001 diff --git a/assets/wifi2_icon.bin b/assets/wifi2_icon.bin new file mode 100644 index 0000000000000000000000000000000000000000..7480e6ea2cc209ba29555f6235405a63ce44b0b6 GIT binary patch literal 2304 zcmeH{Jxc>o5JmSh8*qsU7)+gX>0$~?yZnOG3c=1krIuO>i9f;GLJ%x01)J20mLm9B z2o_qc_sDGJZsMjBQXDdwnR{n<@?Mf8agqg#9sI*H;QM~)I8Hx}iNW6;^u`W%y)oT6HkfTPA^`aT!k>?)-fv=uzu_tXc_2u35y&~#HCEbV3siHxP zN1i`ld+Gj7OH zE8>;at8*R6Yb?IRi{L+qcuXxzQ#7aNtjUl2d1Y|FYejvg^>fDM$^I+zp7&|~^VYrr DFW>{~ literal 0 HcmV?d00001 diff --git a/assets/wifi3_icon.bin b/assets/wifi3_icon.bin new file mode 100644 index 0000000000000000000000000000000000000000..a6df67c053f044db5ac8be4e98c1ffc93bf9c53a GIT binary patch literal 2304 zcmds%IcQX26h>#C;4DU*kfcneOJy<;OS=*KSlB2IB7%K74K^;FkSG|i5^F(0P*6}1 z(xg^g3YXw63Km+8=jeS9!kY;%rNv?H+;cQJuA6fZVHaWHFyNC;8S31&YC?_XsT+5jTOH0^k0S7@C{zTEm(nbf$?p4 z3HH1J$C}q;>lm$8D^G0_F2Q?v2di)hCfJKz#bUAKUWl$Q>)eV zo`Z+*9d5ur=ds;-)yIBT)r3|Lz2?HZMf@0CV~=^&5?|(7Cg&Wxa2n1A#^xsMNybr2 zt_OOp!MJPX_b_xzrBcz}$jy?w4A0>!e1YVAjm=rJXI70`J@|hRPI~6%s?}cpabK9u{mq@*t@7!5BDXRtNsa$H$vYs`~dIFel#O#cifycd!kp( zvL1=w*56p$5&F)c9Zh^)JO7)Iysu`mA2H4-nk6`qHt)^jl*?tL|IUoKfMy0Rz!Ufo z7@M21M?Lda`1cGp`wfaKm5SaA;QR7C@4&^t*qpTmdk6Up%Ew-vLVq6)us1dDff$>E zyU^QiPX>+Qn(?Z~TBh+j8cdtBmSs=U#;MoqzHi@>d+{qU?pjOJWXUl{@5Va(ge!sZ zy0t7`X}x%i;pH2;N9-N-{XH;eElraphlk&%4R{KE2jv-TSj*y-*2@|DZCruh@EQCD n8LwDN(`3yt&pr70KG%XJb6I_c^?S$hbpM+>z3;>PcUt=c2bS_z literal 0 HcmV?d00001 diff --git a/assets/wifi_none_icon.bin b/assets/wifi_none_icon.bin new file mode 100644 index 0000000000000000000000000000000000000000..696bf6f0f4016bfa20cf3e06f43fba3d5bc93470 GIT binary patch literal 2304 zcmds%KWkHA6o+qa(gaKz6;rSf0%>lF8;P!|UU5kZ7b z4hrf}Xi=+(gM&`-dEnf^mvGIEP7V+6x#!RC-1pq~zSHS6oBpSaMx!jx^QBs?whU)r zCD2|rW=@s;kH=#*n^~3(;S$_}r|=$*18se`!JMHr)|T}O-3{{9JbT8f&k@s+#s`x7%v3 z!xQ)h_u%|I`?Wsi*|H{T)lh3aw4KK*ID*T(SNl(MO!r^(u~v=HQd8|6_zW*#*zfmC zztJr1!e^}-p{3>yb68^Cg-`Gh28;9v?Lla$wX3$h|F%b&cCojz9&ui}%(wWzy85i0 zN4unlvpfga;5mE@wDlP?$GQGClR`6HlYP9T&VTg_Jb>$gwmxI#%%xrQN_sq_e$%tp zYPE8SbGV7$SS9VG#}@U2X0w^IuEE7%EqtDrE#If8tGaeN9slobcnd!Q?QLUK_0oK1 zaSE+{_zpJ%?R{fue${6*R?u?BkFY(XC$S&vGgehE%}1k$mUq)@@E(*maAYjaulmfl w^KP8LPw-AT4trv(s@|-8-t#n?d*B@?d-`VOF6wJE8g(?Ce^+}^oqt{T3lqI9q5uE@ literal 0 HcmV?d00001 diff --git a/common/assets.c b/common/assets.c index c7c3a06..e3cc541 100644 --- a/common/assets.c +++ b/common/assets.c @@ -20,6 +20,13 @@ assetsDataEntry g_assetsDataList[AssetId_Max] = { GENASSET("hbmenu_logo_light.bin"), GENASSET("theme_icon_dark.bin"), GENASSET("theme_icon_light.bin"), + GENASSET("airplane_icon.bin"), + GENASSET("wifi_none_icon.bin"), + GENASSET("wifi1_icon.bin"), + GENASSET("wifi2_icon.bin"), + GENASSET("wifi3_icon.bin"), + GENASSET("eth_icon.bin"), + GENASSET("eth_none_icon.bin"), }; static void assetsClearEntry(assetsDataEntry *entry) { diff --git a/common/assets.h b/common/assets.h index 797f957..6eb23e2 100644 --- a/common/assets.h +++ b/common/assets.h @@ -10,6 +10,13 @@ typedef enum { AssetId_hbmenu_logo_light, AssetId_theme_icon_dark, AssetId_theme_icon_light, + AssetId_airplane_icon, + AssetId_wifi_none_icon, + AssetId_wifi1_icon, + AssetId_wifi2_icon, + AssetId_wifi3_icon, + AssetId_eth_icon, + AssetId_eth_none_icon, AssetId_Max } AssetId; diff --git a/common/common.h b/common/common.h index 37ad0e4..484bc51 100644 --- a/common/common.h +++ b/common/common.h @@ -64,6 +64,7 @@ typedef union { #include "message-box.h" #include "power.h" #include "netloader.h" +#include "netstatus.h" void menuStartupPath(void); void menuStartup(void); diff --git a/common/menu.c b/common/menu.c index cc00267..b12654d 100644 --- a/common/menu.c +++ b/common/menu.c @@ -414,7 +414,36 @@ void drawWave(int id, float timer, color_t color, int height, float phase, float } } -void drawTime() { +void drawCharge() { + char chargeString[5]; + uint32_t batteryCharge; + bool isCharging; + bool validPower; + + validPower = powerGetDetails(&batteryCharge, &isCharging); + + if (validPower) + { + batteryCharge = (batteryCharge > 100) ? 100 : batteryCharge; + + sprintf(chargeString, "%d%%", batteryCharge); + + int tmpX = GetTextXCoordinate(interuiregular14, 1180 - 10, chargeString, 'r'); + + DrawText(interuiregular14, tmpX - 17, 0 + 47 + 10 + 21 + 4, themeCurrent.textColor, chargeString); + drawIcon(1180 - 16 - 8, 0 + 47 + 10 + 6, 24, 24, assetsGetDataBuffer(AssetId_battery_icon), themeCurrent.textColor); + if (isCharging) + drawIcon(tmpX - 32 - 10, 0 + 47 + 10 + 6, 24, 24, assetsGetDataBuffer(AssetId_charging_icon), themeCurrent.textColor); + } +} + +void drawNetwork(int tmpX) { + AssetId id; + if (netstatusGetDetails(&id)) + drawIcon(tmpX + 5, 0 + 47 + 10 + 3, 24, 24, assetsGetDataBuffer(id), themeCurrent.textColor); +} + +void drawStatus() { char timeString[9]; @@ -431,29 +460,8 @@ void drawTime() { DrawText(interuimedium20, tmpX, 0 + 47 + 10, themeCurrent.textColor, timeString); -} - -void drawCharge() { - char chargeString[5]; - uint32_t batteryCharge; - bool isCharging; - bool validPower; - - validPower = powerGetDetails(&batteryCharge, &isCharging); - - if (validPower) - { - batteryCharge = (batteryCharge > 100) ? 100 : batteryCharge; - - sprintf(chargeString, "%d%%", batteryCharge); - - int tmpX = GetTextXCoordinate(interuiregular14, 1180, chargeString, 'r'); - - DrawText(interuiregular14, tmpX - 15, 0 + 47 + 10 + 21, themeCurrent.textColor, chargeString); - drawIcon(1180 - 11, 0 + 47 + 10 + 6, 10, 15, assetsGetDataBuffer(AssetId_battery_icon), themeCurrent.textColor); - if (isCharging) - drawIcon(tmpX - 32, 0 + 47 + 10 + 6, 9, 15, assetsGetDataBuffer(AssetId_charging_icon), themeCurrent.textColor); - } + drawCharge(); + drawNetwork(tmpX); } void drawButtons(menu_s* menu, bool emptyDir, int *x_image_out) { @@ -553,8 +561,7 @@ void menuLoop(void) { DrawText(interuiregular14, 180 + 256, 46 + 16 + 18, themeCurrent.textColor, tmpstr); #endif - drawTime(); - drawCharge(); + drawStatus(); memset(&netloader_state, 0, sizeof(netloader_state)); netloaderGetState(&netloader_state); diff --git a/resources/airplane_icon.png b/resources/airplane_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..7808f334786d38892dcae794e477b58ac519a3f3 GIT binary patch literal 3687 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 FV1l~?H2VMm literal 0 HcmV?d00001 diff --git a/resources/battery_icon.png b/resources/battery_icon.png index 5c89f729081c6e9519bb40e9b9cb17f8ad138627..a0a53ff874b75ad467051e5f0fae78faeb92fc2a 100644 GIT binary patch literal 1753 zcmV;~1}6E5P) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O1Ywmg^`C{MRaG2?!8^PivfZ&WxX0>MjLv?R=hz(x-LdxN`R;?)3%rlmjnU#5eXTD00Hgw)i@Gf3c*4MPLK+cSFp7V{ zvmRH%6|uw$#v0reT$MPn1=@o>H_kk`A8qA|5WVeI(OO%rJNlwin{0K90$e<-f}Tb$ zf}0A~9J=i_7C!u@!(TiprxC_vZr(8p zgzz{ql>^`7qMN)iH^e$HCLZQA7ic9)s4~uA_SsQPy+#hEbj&R zqdp>svN-W1B0*H5B+0=AA0&jJVb-XuPQ8i-RgIc7M;CpR7^21)Q_RUGhY}_!B&8Hn zN;$)6hUtvi86$Eowz%Splu)$9l1i>fpX#gBP_@RIYHqf<2Kl$plv-@5<<1?c)P0v8 zy7t&p&jYzO-0(w27&_ueBVSoNS-oeC|6uNW*7#&?GUktQ`o$W$RWBxZmJ^wrfideD zjO%0o32i55CbIW-GB-Ih$<88W!5YgXr}1PA4EoMi24A`RV(wesNc=~<*;mZbr0#Dp zN0Yjfxkuifu-5Xiqqu{hslth=aRY@7gR+hILp^@mmgq(-t~+VIRFgV~B2Ap95^b{~ zbt(9wK?+J|5R-*lu`U#wY8RtA1c_A#bPs&`U`22S2)Z%KV5c-c@r-w5EGUlzmz}dK zHSqj~YT8hHJJP7l_X--m%tgJJqh)X39NmVuV~%da+c8Ivt9@rq#xrvSdj;EF$K2Rd z?BF({W=-)iDC|gYO+ph+;&b#q)YNLN*ooA&(QE`prT#pPUbl49;VQzP>m12y znScbAxE3N%%0Qjh=H`3x$gGNev0!<{56_*n(6E{i*8JzO5crqeVar997=P~XGq=mQuAm#MSCL8YUPjhJ&&Uz+XBk#8xR z1QKlLlzVoH6K<8(6oA$Lowc?tO5w^%g(nLOvL6DI!kUS;i&f&bSci+>Tm)I zC^cdD+|6*h)o|VYtba+Q-aueDt3rA?cbq03iO+(($6wl9*cnt)7hQw=c^b16u z0zsc4@fryF42jo3&}T@zZs{{5UIRg&A@Ldr+84*NO8eqiK+wK877(;Ajs*nmi{n=P zTjE$i(7rfUOZ(zjK+wK8UYC(y)l1qJ#{z=(#qm!4AEpHDi(^@&eQ_*rv@ed&%E;T4 zpnY+ymiEQ5fS`SGJS!s`hY8vj#{z=(#qs+?#8V(>UmVX45gUgI+84)9%g7H?g7(F+ zfS`SGEFk{YA>vv_wolr$FOCHS?Th0#hlp=dg7(F6SO)zGW%7T~6%XbSLBJUR000JJ zOGiWi{{a60|De66lK=n!32;bRa{vG#Hvj-3HvuzPpLzfQ00(qQO+^Re1{4w{Dj?OE z%K!iXdr3q=R7l6|kSz{`Koo<&PF8{DKAdMgo>Ooh&VvUz#URM+X25`YO=|jnzNE6v zllojOq?B6QU!W~UtE4ICyjCCBu3AzDEPx9ylDez=#KZcjNKy~Hqxs+$u90uX=z1Rwwbcm=QnDT8ugBo4MA00000NkvXXu0mjfSY$ii literal 188 zcmeAS@N?(olHy`uVBq!ia0vp^AT~b-8<4#FKaLMbu@pObhHwBu4M$1`kk47*5n0T@ zAlMGVjE?b1r9eT+64!{5;QX|b^2DN4hVt@qz0ADq;^f4FRK5J7^x5xhq=1SnJzX3_ zG$tk|I5b@4;o diff --git a/resources/charging_icon.png b/resources/charging_icon.png index 22295906675708e3b4b52cd165ce3203c8c046a9..88c47f2c6a3bd1fc81860526873bdc3cbb2f17ad 100644 GIT binary patch literal 3416 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 literal 0 HcmV?d00001 diff --git a/resources/wifi1_icon.png b/resources/wifi1_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f0fa3b57caf604f0af5b053259720ef2d6a46bc0 GIT binary patch literal 2401 zcmV-n37+ zaB^>EX>4U6ba`-PAZ2)IW&i+q+U-|cmL#hR{dW{+2%-Wy9AB(;W^jjpHbzud)}yQX zaX&k=DvdA^mo1-0SKsD5q=U$1-+8{ zG}Lh9{1>YL2-$5@KK4D|@Z>k~3D^t-`Ix!lfIW^ (^$t$c9KSjVx1c!dV(x&@p_ zhzw;Y1A!=TY!Zr^k`lp=75H>$o^nY82oQ5x6b#tpEC8n_-y82JowbS6H4SP35R9Nv zK!X4RSfw!hM@xkdb|f}(I?zzmdR75&N|!dE3Lc`{!5mIRaaYm z(}pYUvU$taU3c5v;A@tx7@L?{wPyW++KuX4)aV^@U!z7hYK~Yr>+}^hOsl?#Ag2>{ z%z#)b1jN-5fI}z8ELJKdIdYC!YzaZZ38)b}IEx%HAXqjfHhN(9irkmD1unmYTlx`l z!J+$qAQv3E8@Z3TeS+HRC!^#8kVm20G-d;_VNp*Nf8gWaAH$yt_$%nIpud8CT~MA? zZBx&R1aF2~V`;Vxl4UThO3Ocf8dS!X1j<_iNgxk1u-3K+nJZ@HX-Lq+DEer$`Xy}~ zX~?Fxya0jOC+3kDk7B!>mwriLc+&6-f$O6{Qgd-^*YohB1=diYF^CtEh8-Jruf~5g zhVK@<8=-9m-DaGj^tfD$3a&S&+C>A&$o0Xcg1OB)G8xtw?x6b4gC}WSW6J7H>sD@6 z8Kl4CC{?uf<>bFuR-?wAf<$IpbC#`X>adP(1F6hbYM#AnLz?+q-|%Ll?RLFF)$dJ` ztp?+rV;sZ#L5g4D9K^bELo&@;6PlV!T^iilfV${bMrmCeRPAdu*-Wj$8<99?U42Gq z3)rnMh0b={Be?Vzli(P~C^5n;1w{w492NEk=-V-T{s4tb+R|VgX{$`xkQK>%uFz|-v8*y`0Ti|7lStQGYW9jwj-JE3pAdgv+EZ{6kdbDs*A=v{yxog! z{1FEPzknC3xu0WqY{+uF3UN{oQbp!quL018?97HUbhy>F<4q_a;CdX=2RYDimN|^k80} zFmF*CLZyRt;4?IAA>whgwcWb0&4yjeyYs`Ec1(?mEqS-qfRV{r$+S`zOK{7As@4nD z)N$_7q5MXpWSTpQBNS;Jfak)%Lv|msQjtDJK`AL^@8bQH znGgeG6X4|?%R)ph>@dby?hl)XO29vl-iR71)jJ9*YR85~5blV@KgTlRr)bC$qPM43 zlg_*cifP->5ni%UY&xZKu-woXp^nUCqo~?MUpYX`BldaX4@D}wtGVsJWynE*7jD+A z%P>(E=XeyKvpUW7*=~`*1y%C6*c{e{YNhRU7!u}Xxy{SuOxA7vY|uZ(@Z|#9<=X?_ z+J)u*del2a&XRB4($eXj{ewL~pdR{j;c6wMwEW-{j3K$5u~R+)dN#I`m@dQIX1O|agAX{(K+6g)o`mcg z!RaGTp^Cn+^kDAF)y;oZO6WZAO3CiptbbzKk7M|AQ==@iIzY9t8LxBK(cdCZ!A8jX zRbmC+=_HkoURx55v<3*fXFt+};DY&hOdZZWNGDf`W&4y^Fw-f)CK~5- zj@n;W$XVg8zCa@=81e)6VHfUj*emazFaY+co+L3r{#c8gbCs@me2E8Y?(F>#v!Cw7 z(RElbGY-4Qos`RNuFOQ}UpZMt;$$xzfgcy{D4^000SaNLh0L03kO303kO4GgzN`00007bV*G`2jd15 z6BP@xIMh)900CV|L_t(Y$L*FqO9Md=hM$?s?rA)NsTC2l2xw^|h^1g_?_aPLe}UMF z{sMbjdr@q(6a*2hwXlgFw|m*O*~TV!A;c;J1Iv8yGVko{ti%|Zq$m@XDZmt93h)mA ztwuquRx5$(8z#Z_I+-txl@BtiIYcI>P3?oq#LJ*(>JOd{pa&N8u25`>J#uzt%L!gslN2e%p zKVyvfa?ULSTgi1}t$p?0w^j9LXfI-nL$xRh0d`U)KS`f~ouVkDF25E)MCO49pbwlU z?E?=YGGCY9DSWmvO=O6+VuoPolO}2$(tKYYEC8}x;oB<{94!ouF znX2Zs6gOG=s@jb)9ss+^bR{CEA%u^yCizbzjL8Or!5l!AWuM;rL6bb0^ta^~wOtV7 Tjq|+*00000NkvXXu0mjfp7es) literal 0 HcmV?d00001 diff --git a/resources/wifi2_icon.png b/resources/wifi2_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e4456726dfa64685bcdd18aa96a0c128abfee63a GIT binary patch literal 3680 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

emVJrPd_6ZV40 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 wbfw={h4 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 Date: Sat, 22 Jun 2019 17:47:31 -0400 Subject: [PATCH 05/22] Added netstatus files which were missing from e917589. Closes #86. --- common/netstatus.h | 5 +++++ nx_main/nx_netstatus.c | 36 ++++++++++++++++++++++++++++++++++++ pc_main/pc_netstatus.c | 6 ++++++ 3 files changed, 47 insertions(+) create mode 100644 common/netstatus.h create mode 100644 nx_main/nx_netstatus.c create mode 100644 pc_main/pc_netstatus.c diff --git a/common/netstatus.h b/common/netstatus.h new file mode 100644 index 0000000..ceebc2b --- /dev/null +++ b/common/netstatus.h @@ -0,0 +1,5 @@ +#pragma once +#include "common.h" + +bool netstatusGetDetails(AssetId *id); + diff --git a/nx_main/nx_netstatus.c b/nx_main/nx_netstatus.c new file mode 100644 index 0000000..378e30f --- /dev/null +++ b/nx_main/nx_netstatus.c @@ -0,0 +1,36 @@ +#include "../common/common.h" + +bool netstatusGetDetails(AssetId *id) { + Result rc=0; + NifmInternetConnectionType contype; + u32 wifiStrength=0; + NifmInternetConnectionStatus connectionStatus; + + rc = nifmGetInternetConnectionStatus(&contype, &wifiStrength, &connectionStatus); + if (R_FAILED(rc)) { + *id = AssetId_airplane_icon; + return true; + } + + if (contype == NifmInternetConnectionType_Ethernet) { + if (connectionStatus != NifmInternetConnectionStatus_Connected) + *id = AssetId_eth_none_icon; + else + *id = AssetId_eth_icon; + return true; + } + + if (wifiStrength==0) { + *id = AssetId_wifi_none_icon; + return true; + } + + if (wifiStrength==3) + *id = AssetId_wifi3_icon; + if (wifiStrength==2) + *id = AssetId_wifi2_icon; + else + *id = AssetId_wifi1_icon; + + return true; +} diff --git a/pc_main/pc_netstatus.c b/pc_main/pc_netstatus.c new file mode 100644 index 0000000..dc4e1ab --- /dev/null +++ b/pc_main/pc_netstatus.c @@ -0,0 +1,6 @@ +#include "../common/common.h" + +bool netstatusGetDetails(AssetId *id) { + *id = AssetId_wifi3_icon; + return true; +} From 7c029c18b0e6b8c6fb0da2800a2568e4aa27e4e3 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Mon, 24 Jun 2019 11:43:15 -0400 Subject: [PATCH 06/22] Moved status gfx around (charging icon moved to the right of the battery icon). Previously there was gfx overlap when the battery charge was 100%. --- common/menu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/common/menu.c b/common/menu.c index b12654d..c0dad04 100644 --- a/common/menu.c +++ b/common/menu.c @@ -430,17 +430,17 @@ void drawCharge() { int tmpX = GetTextXCoordinate(interuiregular14, 1180 - 10, chargeString, 'r'); - DrawText(interuiregular14, tmpX - 17, 0 + 47 + 10 + 21 + 4, themeCurrent.textColor, chargeString); - drawIcon(1180 - 16 - 8, 0 + 47 + 10 + 6, 24, 24, assetsGetDataBuffer(AssetId_battery_icon), themeCurrent.textColor); + DrawText(interuiregular14, tmpX - 24 - 8, 0 + 47 + 10 + 21 + 4, themeCurrent.textColor, chargeString); + drawIcon(1180 - 8 - 24 - 8, 0 + 47 + 10 + 6, 24, 24, assetsGetDataBuffer(AssetId_battery_icon), themeCurrent.textColor); if (isCharging) - drawIcon(tmpX - 32 - 10, 0 + 47 + 10 + 6, 24, 24, assetsGetDataBuffer(AssetId_charging_icon), themeCurrent.textColor); + drawIcon(1180 - 20, 0 + 47 + 10 + 6, 24, 24, assetsGetDataBuffer(AssetId_charging_icon), themeCurrent.textColor); } } void drawNetwork(int tmpX) { AssetId id; if (netstatusGetDetails(&id)) - drawIcon(tmpX + 5, 0 + 47 + 10 + 3, 24, 24, assetsGetDataBuffer(id), themeCurrent.textColor); + drawIcon(tmpX, 0 + 47 + 10 + 3, 24, 24, assetsGetDataBuffer(id), themeCurrent.textColor); } void drawStatus() { From 9e257d760610d170d41c252c58f654558967e4c2 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Mon, 24 Jun 2019 15:41:35 -0400 Subject: [PATCH 07/22] Use netstatusGetDetails from a dedicated thread, since nifmGetInternetConnectionStatus can block for a few seconds. --- Makefile.pc | 2 +- common/common.h | 1 + common/menu.c | 7 ++- common/status.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++ common/status.h | 7 +++ nx_main/main.c | 6 +++ pc_main/main.cpp | 2 + 7 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 common/status.c create mode 100644 common/status.h diff --git a/Makefile.pc b/Makefile.pc index 20c7cbc..e15c645 100644 --- a/Makefile.pc +++ b/Makefile.pc @@ -10,7 +10,7 @@ EXTRA_LDFLAGS="-lws2_32" endif 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/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/ui.c common/assets.c common/math.c common/theme.c \ common/netloader.c diff --git a/common/common.h b/common/common.h index 484bc51..b59f77f 100644 --- a/common/common.h +++ b/common/common.h @@ -65,6 +65,7 @@ typedef union { #include "power.h" #include "netloader.h" #include "netstatus.h" +#include "status.h" void menuStartupPath(void); void menuStartup(void); diff --git a/common/menu.c b/common/menu.c index c0dad04..3643763 100644 --- a/common/menu.c +++ b/common/menu.c @@ -438,9 +438,12 @@ void drawCharge() { } void drawNetwork(int tmpX) { + bool netstatusFlag=0; AssetId id; - if (netstatusGetDetails(&id)) - drawIcon(tmpX, 0 + 47 + 10 + 3, 24, 24, assetsGetDataBuffer(id), themeCurrent.textColor); + if (statusGet(&netstatusFlag, &id)) { + if (netstatusFlag) + drawIcon(tmpX, 0 + 47 + 10 + 3, 24, 24, assetsGetDataBuffer(id), themeCurrent.textColor); + } } void drawStatus() { diff --git a/common/status.c b/common/status.c new file mode 100644 index 0000000..3181603 --- /dev/null +++ b/common/status.c @@ -0,0 +1,109 @@ +#include "status.h" + +static bool s_statusInitialized = 0; +static thrd_t s_statusThread; +static cnd_t s_statusCdn; +static mtx_t s_statusMtx; +static mtx_t s_statusAccessMtx; +static bool s_statusExit; + +static bool s_statusReady; +static bool s_statusNetFlag; +static AssetId s_statusNetAssetId; + +// This uses netstatusGetDetails from a dedicated thread, since nifmGetInternetConnectionStatus can block for a few seconds. + +static int statusThreadProc(void* unused) +{ + mtx_lock(&s_statusMtx); + + struct timespec timeout = {0}; + + clock_gettime(CLOCK_MONOTONIC, &timeout); + timeout.tv_sec++; + + for (;;) + { + cnd_timedwait(&s_statusCdn, &s_statusMtx, &timeout); + + if (s_statusExit) + break; + + mtx_lock(&s_statusAccessMtx); + + s_statusNetFlag = netstatusGetDetails(&s_statusNetAssetId); + + s_statusReady = 1; + + mtx_unlock(&s_statusAccessMtx); + + clock_gettime(CLOCK_MONOTONIC, &timeout); + timeout.tv_sec++; + } + + mtx_unlock(&s_statusMtx); + + return 0; +} + +bool statusGet(bool *netstatusFlag, AssetId *netstatusAssetId) { + if (!s_statusReady) return 0; + + mtx_lock(&s_statusAccessMtx); + + *netstatusFlag = s_statusNetFlag; + *netstatusAssetId = s_statusNetAssetId; + + mtx_unlock(&s_statusAccessMtx); + + return 1; +} + +bool statusInit(void) +{ + if (s_statusInitialized) return 1; + + if (cnd_init(&s_statusCdn) != thrd_success) return 0; + if (mtx_init(&s_statusMtx, mtx_plain) != thrd_success) { + cnd_destroy(&s_statusCdn); + return 0; + } + + if (mtx_init(&s_statusAccessMtx, mtx_plain) != thrd_success) { + mtx_destroy(&s_statusMtx); + cnd_destroy(&s_statusCdn); + return 0; + } + + if (thrd_create(&s_statusThread, statusThreadProc, 0) != thrd_success) { + mtx_destroy(&s_statusAccessMtx); + mtx_destroy(&s_statusMtx); + cnd_destroy(&s_statusCdn); + return 0; + } + + s_statusInitialized = 1; + return 1; +} + +void statusExit(void) +{ + int res=0; + + if (!s_statusInitialized) return; + s_statusInitialized = 0; + + mtx_lock(&s_statusMtx); + s_statusExit = true; + cnd_signal(&s_statusCdn); + mtx_unlock(&s_statusMtx); + + thrd_join(s_statusThread, &res); + + s_statusReady = 0; + + mtx_destroy(&s_statusAccessMtx); + mtx_destroy(&s_statusMtx); + cnd_destroy(&s_statusCdn); +} + diff --git a/common/status.h b/common/status.h new file mode 100644 index 0000000..7e52eba --- /dev/null +++ b/common/status.h @@ -0,0 +1,7 @@ +#pragma once +#include "common.h" + +bool statusInit(void); +void statusExit(void); +bool statusGet(bool *netstatusFlag, AssetId *netstatusAssetId); + diff --git a/nx_main/main.c b/nx_main/main.c index cb2caf7..b968e7e 100644 --- a/nx_main/main.c +++ b/nx_main/main.c @@ -87,6 +87,11 @@ int main(int argc, char **argv) snprintf(errormsg, sizeof(errormsg)-1, "Error: workerInit() failed."); } + if (R_SUCCEEDED(rc) && !statusInit()) { + rc = 1; + snprintf(errormsg, sizeof(errormsg)-1, "Error: statusInit() failed."); + } + if (R_SUCCEEDED(rc)) menuStartup(); if (R_SUCCEEDED(rc)) { @@ -175,6 +180,7 @@ int main(int argc, char **argv) fontExit(); launchExit(); netloaderSignalExit(); + statusExit(); workerExit(); netloaderExit(); powerExit(); diff --git a/pc_main/main.cpp b/pc_main/main.cpp index 0ddaa2f..f038dc7 100644 --- a/pc_main/main.cpp +++ b/pc_main/main.cpp @@ -22,6 +22,7 @@ int main() fontInitialize(); netloaderInit(); workerInit(); + statusInit(); menuStartup(); while (window.isOpen()) @@ -56,6 +57,7 @@ int main() } netloaderSignalExit(); + statusExit(); workerExit(); netloaderExit(); fontExit(); From f0ef77b2f26511dd36ad47153f5fb9884968d5d8 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Mon, 24 Jun 2019 17:05:24 -0400 Subject: [PATCH 08/22] Added support for loading {filename}.nacp similar to {filename}.jpg, when processing files for fileassoc. --- common/menu-entry.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/common/menu-entry.c b/common/menu-entry.c index ab34d3a..ed90336 100644 --- a/common/menu-entry.c +++ b/common/menu-entry.c @@ -168,6 +168,26 @@ static bool menuEntryLoadEmbeddedNacp(menuEntry_s* me) { return ok; } +static bool menuEntryLoadExternalNacp(menuEntry_s* me, const char* path) { + struct stat st; + + if(stat(path, &st)==-1) return false; + + FILE* f = fopen(path, "rb"); + if (!f) return false; + + me->nacp = (NacpStruct*)malloc(sizeof(NacpStruct)); + if (me->nacp == NULL) { + fclose(f); + return false; + } + memset(me->nacp, 0, sizeof(NacpStruct)); + + bool ok = fread(me->nacp, sizeof(NacpStruct), 1, f) == 1; + fclose(f); + return ok; +} + /*static void fixSpaceNewLine(char* buf) { char *outp = buf, *inp = buf; char lastc = 0; @@ -438,11 +458,23 @@ bool menuEntryLoad(menuEntry_s* me, const char* name, bool shortcut) { if (!iconLoaded && fileassoc_me->icon_gfx && fileassoc_me->icon_gfx_small) iconLoaded = menuEntryImportIconGfx(me, fileassoc_me->icon_gfx, fileassoc_me->icon_gfx_small); - strncpy(me->author, fileassoc_me->author, sizeof(me->author)); - me->author[sizeof(me->author)-1] = 0; + //Attempt to load the nacp from {me->path filepath with extension .nacp}, then on failure use the config from fileassoc_me. + memset(tempbuf, 0, sizeof(tempbuf)); + strncpy(tempbuf, me->path, sizeof(tempbuf)); + tempbuf[sizeof(tempbuf)-1] = 0; + strptr = getExtension(tempbuf); + strncpy(strptr, ".nacp", sizeof(tempbuf)-1 - ((ptrdiff_t)strptr - (ptrdiff_t)tempbuf)); - strncpy(me->version, fileassoc_me->version, sizeof(me->version)); - me->version[sizeof(me->version)-1] = 0; + bool nacpLoaded = menuEntryLoadExternalNacp(me, tempbuf); + + if (nacpLoaded) menuEntryParseNacp(me); + else { + strncpy(me->author, fileassoc_me->author, sizeof(me->author)); + me->author[sizeof(me->author)-1] = 0; + + strncpy(me->version, fileassoc_me->version, sizeof(me->version)); + me->version[sizeof(me->version)-1] = 0; + } // Initialize the argument data argData_s* ad = &me->args; From 753a97ef7b979e39fdcdedd2b1e0ccfcc9d77318 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Tue, 25 Jun 2019 16:21:30 -0400 Subject: [PATCH 09/22] Don't lock the mutex before calling netstatusGetDetails, lock it afterwards and use tmp fields. --- common/status.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/common/status.c b/common/status.c index 3181603..b0f0d9e 100644 --- a/common/status.c +++ b/common/status.c @@ -18,6 +18,8 @@ static int statusThreadProc(void* unused) mtx_lock(&s_statusMtx); struct timespec timeout = {0}; + bool tmpflag; + AssetId tmpid; clock_gettime(CLOCK_MONOTONIC, &timeout); timeout.tv_sec++; @@ -29,9 +31,12 @@ static int statusThreadProc(void* unused) if (s_statusExit) break; + tmpflag = netstatusGetDetails(&tmpid); + mtx_lock(&s_statusAccessMtx); - s_statusNetFlag = netstatusGetDetails(&s_statusNetAssetId); + s_statusNetFlag = tmpflag; + s_statusNetAssetId = tmpid; s_statusReady = 1; From dcad6f2afae1d50a3b6c14a70af9d547c9876d9a Mon Sep 17 00:00:00 2001 From: Dave Murphy Date: Sun, 30 Jun 2019 23:30:41 +0100 Subject: [PATCH 10/22] fix assets.zip dependency. Closes #88 --- Makefile | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 437c14c..ac900fe 100644 --- a/Makefile +++ b/Makefile @@ -8,18 +8,20 @@ endif all: nx pc -romfs : assets +romfs: @mkdir -p romfs + +romfs/assets.zip : romfs assets @rm -f romfs/assets.zip @zip -rj romfs/assets.zip assets -dist-bin: romfs +dist-bin: romfs/assets.zip $(MAKE) -f Makefile.nx dist-bin -nx: romfs +nx: romfs/assets.zip $(MAKE) -f Makefile.nx -pc: romfs +pc: romfs/assets.zip $(MAKE) -f Makefile.pc clean: From d6c780256ffef2a0a20193a3e54cb3d3ee46a50d Mon Sep 17 00:00:00 2001 From: hippydave Date: Tue, 9 Jul 2019 18:33:21 +0100 Subject: [PATCH 11/22] Add starred favourites at start of list (#91) * Add starred favourites at start of list --- common/font.c | 4 +++ common/font.h | 1 + common/language.c | 14 +++++++++- common/language.h | 2 ++ common/menu-entry.c | 7 +++++ common/menu-list.c | 28 +++++++++++++++++-- common/menu.c | 67 +++++++++++++++++++++++++++++++++++++++++++-- common/menu.h | 6 ++++ common/theme.c | 21 +++++++++++--- common/theme.h | 3 ++ nx_main/main.c | 4 +++ nx_main/nx_touch.c | 15 ++++++++++ pc_main/main.cpp | 6 ++++ 13 files changed, 168 insertions(+), 10 deletions(-) diff --git a/common/font.c b/common/font.c index 43fd442..803cad9 100644 --- a/common/font.c +++ b/common/font.c @@ -43,6 +43,10 @@ static bool FontSetType(u32 font) case interuimedium30: scale = 8; break; + + case largestar: + scale = 18; + break; default: return false; diff --git a/common/font.h b/common/font.h index 45ed8fe..fb9d300 100644 --- a/common/font.h +++ b/common/font.h @@ -43,3 +43,4 @@ extern const ffnt_header_t interuiregular18_nxfnt;*/ #define interuiregular14 0//&interuiregular14_nxfnt #define interuiregular18 1//&interuiregular18_nxfnt #define fontscale7 4 +#define largestar 5 diff --git a/common/language.c b/common/language.c index e634e02..9aaeb51 100644 --- a/common/language.c +++ b/common/language.c @@ -1,4 +1,4 @@ -#include "language.h" +#include "language.h" #ifdef __SWITCH__ #define STR_JP(_str) [SetLanguage_JA] = _str @@ -331,6 +331,18 @@ const char* const g_strings[StrId_Max][16] = STR_TW("应用"), }, + [StrId_Actions_Star] = + { + STR_EN("Star"), + STR_ES("Agregar a favoritos"), + }, + + [StrId_Actions_Unstar] = + { + STR_EN("Unstar"), + STR_ES("Borrar de favoritos"), + }, + [StrId_ThemeMenu] = { STR_EN("Theme Menu"), diff --git a/common/language.h b/common/language.h index d76839c..1604f3d 100644 --- a/common/language.h +++ b/common/language.h @@ -23,6 +23,8 @@ typedef enum StrId_Actions_Open, StrId_Actions_Back, StrId_Actions_Apply, + StrId_Actions_Star, + StrId_Actions_Unstar, StrId_MsgBox_OK, diff --git a/common/menu-entry.c b/common/menu-entry.c index ed90336..250c3da 100644 --- a/common/menu-entry.c +++ b/common/menu-entry.c @@ -490,6 +490,13 @@ bool menuEntryLoad(menuEntry_s* me, const char* name, bool shortcut) { return false; } + //check for .filename.star in same path + strptr = getSlash(me->path); + if (strptr[0] == '/') strptr++; + int strptrLen = strlen(strptr); + snprintf(me->starpath, sizeof(me->starpath)-1, "%.*s.%.*s.star", (int)(strlen(me->path) - strptrLen), me->path, (int)strptrLen, strptr); + me->starred = fileExists(me->starpath); + return true; } diff --git a/common/menu-list.c b/common/menu-list.c index d693f54..61227bc 100644 --- a/common/menu-list.c +++ b/common/menu-list.c @@ -96,20 +96,34 @@ static void menuSort(void) { menu_s* m = &s_menu[!s_curMenu]; int nEntries = m->nEntries; if (nEntries==0) return; + int nEntriesStar = 0, nEntriesNoStar = 0; menuEntry_s** list = (menuEntry_s**)calloc(nEntries, sizeof(menuEntry_s*)); if(list == NULL) return; + menuEntry_s** listStar = (menuEntry_s**)calloc(nEntries, sizeof(menuEntry_s*)); + if(listStar == NULL) { + free(list); + return; + } menuEntry_s* p = m->firstEntry; for(i = 0; i < nEntries; ++i) { - list[i] = p; + if (p->starred) + listStar[nEntriesStar++] = p; + else + list[nEntriesNoStar++] = p; p = p->next; } - qsort(list, nEntries, sizeof(menuEntry_s*), menuEntryCmp); + qsort(listStar, nEntriesStar, sizeof(menuEntry_s*), menuEntryCmp); + qsort(list, nEntriesNoStar, sizeof(menuEntry_s*), menuEntryCmp); menuEntry_s** pp = &m->firstEntry; - for(i = 0; i < nEntries; ++i) { + for(i = 0; i < nEntriesStar; ++i) { + *pp = listStar[i]; + pp = &(*pp)->next; + } + for(i = 0; i < nEntriesNoStar; ++i) { *pp = list[i]; pp = &(*pp)->next; } @@ -117,6 +131,14 @@ static void menuSort(void) { *pp = NULL; free(list); + free(listStar); +} + +void menuReorder (void) { + s_curMenu = !s_curMenu; + menuSort(); + s_curMenu = !s_curMenu; + menuClear(); } int menuScan(const char* target) { diff --git a/common/menu.c b/common/menu.c index 3643763..cf29df6 100644 --- a/common/menu.c +++ b/common/menu.c @@ -29,6 +29,35 @@ void launchMenuEntryTask(menuEntry_s* arg) { launchMenuEntry(me); } +void toggleStarState(menuEntry_s* arg) { + menuEntry_s* me = arg; + if (me->starred) { + if (fileExists(me->starpath)) + remove(me->starpath); + } else { + if (!fileExists(me->starpath)) { + FILE* f = fopen(me->starpath, "w"); + if (f) fclose(f); + } + } + me->starred = fileExists(me->starpath); + //todo: error handling/message? + + menuReorder(); + menu_s* menu = menuGetCurrent(); + menuEntry_s* meSearch = menu->firstEntry; + menu->curEntry = -1; + int i = 0; + while (menu->curEntry < 0) { + if (me == meSearch) + menu->curEntry = i; + else { + meSearch = meSearch->next; + i++; + } + } +} + static enum { HBMENU_DEFAULT, @@ -73,6 +102,18 @@ void menuHandleAButton(void) { } } +void menuHandleXButton(void) { + menu_s* menu = menuGetCurrent(); + + if (menu->nEntries > 0 && hbmenu_state == HBMENU_DEFAULT) { + int i; + menuEntry_s* me; + for (i = 0, me = menu->firstEntry; i != menu->curEntry; i ++, me = me->next); + toggleStarState(me); + } +} + + void launchApplyThemeTask(menuEntry_s* arg) { const char* themePath = arg->path; SetThemePathToConfig(themePath); @@ -246,6 +287,8 @@ static void drawEntry(menuEntry_s* me, int off_x, int is_active) { if (smallimg) { drawImage(start_x, start_y + 32, 140, 140, smallimg, IMAGE_MODE_RGB24); + if (me->starred) + DrawText(interuimedium30, start_x + 105 + 16, start_y + 16, themeCurrent.borderTextColor, themeCurrent.labelStarOnText); } if (is_active && largeimg) { @@ -283,6 +326,12 @@ static void drawEntry(menuEntry_s* me, int off_x, int is_active) { snprintf(tmpstr, sizeof(tmpstr)-1, "%s: %s", textGetString(StrId_AppInfo_Version), me->version); DrawText(interuiregular14, start_x, start_y + 28 + 30 + 18 + 6 + 18, themeCurrent.textColor, tmpstr); } + + if (me->starred) + DrawText(largestar, start_x - 68, 160, themeCurrent.textColor, themeCurrent.labelStarOnText); + else + if (me->type != ENTRY_TYPE_THEME) + DrawText(largestar, start_x - 68, 160, themeCurrent.textColor, themeCurrent.labelStarOffText); } } @@ -483,8 +532,8 @@ void drawButtons(menu_s* menu, bool emptyDir, int *x_image_out) { #endif { //drawImage(x_image, 720 - 48, 32, 32, themeCurrent.buttonBImage, IMAGE_MODE_RGBA32); - DrawText(fontscale7, x_image, 720 - 47 + 26, themeCurrent.textColor, themeCurrent.buttonBText);//Display the 'B' button from SharedFont. - DrawText(interuimedium20, x_text, 720 - 47 + 26, themeCurrent.textColor, textGetString(StrId_Actions_Back)); + DrawText(fontscale7, x_image, 720 - 47 + 24, themeCurrent.textColor, themeCurrent.buttonBText);//Display the 'B' button from SharedFont. + DrawText(interuimedium20, x_text, 720 - 47 + 24, themeCurrent.textColor, textGetString(StrId_Actions_Back)); } if(hbmenu_state == HBMENU_DEFAULT) @@ -666,6 +715,20 @@ void menuLoop(void) { } drawButtons(menu, false, &menupath_x_endpos); + + if (active_entry && active_entry->type != ENTRY_TYPE_THEME) { + if (active_entry->starred) { + getX = GetTextXCoordinate(interuiregular18, menupath_x_endpos + 8, textGetString(StrId_Actions_Unstar), 'r'); + DrawText(fontscale7, getX - 36, 720 - 47 + 24, themeCurrent.textColor, themeCurrent.buttonXText); + DrawText(interuiregular18, getX, 720 - 47 + 24, themeCurrent.textColor, textGetString(StrId_Actions_Unstar)); + } else { + getX = GetTextXCoordinate(interuiregular18, menupath_x_endpos + 8, textGetString(StrId_Actions_Star), 'r'); + DrawText(fontscale7, getX - 36, 720 - 47 + 24, themeCurrent.textColor, themeCurrent.buttonXText); + DrawText(interuiregular18, getX, 720 - 47 + 24, themeCurrent.textColor, textGetString(StrId_Actions_Star)); + } + menupath_x_endpos = getX - 36 - 40; + } + } DrawTextTruncate(interuiregular18, 40, 720 - 47 + 24, themeCurrent.textColor, menu->dirname, menupath_x_endpos - 40, "..."); diff --git a/common/menu.h b/common/menu.h index bd7894f..ff54a4f 100644 --- a/common/menu.h +++ b/common/menu.h @@ -51,6 +51,7 @@ struct menuEntry_s_tag MenuEntryType type; char path[PATH_MAX+8]; + char starpath[PATH_MAX+8]; argData_s args; bool fileassoc_type;//0=file_extension, 1 = filename @@ -64,6 +65,8 @@ struct menuEntry_s_tag size_t icon_size; uint8_t *icon_gfx; uint8_t *icon_gfx_small; + + bool starred; NacpStruct *nacp; }; @@ -97,11 +100,13 @@ void menuDeleteEntry(menuEntry_s* me, bool skip_icongfx); menu_s* menuGetCurrent(void); menu_s* menuFileassocGetCurrent(void); +void menuReorder (void); int menuScan(const char* target); int themeMenuScan(const char* target); int menuFileassocScan(const char* target); void launchMenuEntryTask(menuEntry_s* arg); +void toggleStarState(menuEntry_s* arg); void launchApplyThemeTask(menuEntry_s* arg); void launchMenuBackTask(); void launchMenuNetloaderTask(); @@ -109,6 +114,7 @@ char *menuGetRootPath(void); char *menuGetRootBasePath(void); void menuHandleAButton(void); +void menuHandleXButton(void); bool menuIsNetloaderActive(void); diff --git a/common/theme.c b/common/theme.c index c18853b..bdc13af 100644 --- a/common/theme.c +++ b/common/theme.c @@ -26,10 +26,13 @@ void themeStartup(ThemePreset preset) { .enableWaveBlending = 0, .buttonAText = "\uE0E0", .buttonBText = "\uE0E1", + .buttonXText = "\uE0E2", .buttonYText = "\uE0E3", .buttonPText = "\uE0EF", .buttonMText = "\uE0F0", - .hbmenuLogoImage = assetsGetDataBuffer(AssetId_hbmenu_logo_light) + .labelStarOnText = "\u2605", + .labelStarOffText = "\u2606", + .hbmenuLogoImage = assetsGetDataBuffer(AssetId_hbmenu_logo_light), }; theme_t themeDark = (theme_t) { @@ -46,10 +49,13 @@ void themeStartup(ThemePreset preset) { .enableWaveBlending = 0, .buttonAText = "\uE0A0", .buttonBText = "\uE0A1", + .buttonXText = "\uE0A2", .buttonYText = "\uE0A3", .buttonPText = "\uE0B3", .buttonMText = "\uE0B4", - .hbmenuLogoImage = assetsGetDataBuffer(AssetId_hbmenu_logo_dark) + .labelStarOnText = "\u2605", + .labelStarOffText = "\u2606", + .hbmenuLogoImage = assetsGetDataBuffer(AssetId_hbmenu_logo_dark), }; char themePath[PATH_MAX] = {0}; @@ -61,7 +67,7 @@ void themeStartup(ThemePreset preset) { config_setting_t *theme = NULL; color_t text, frontWave, middleWave, backWave, background, highlight, separator, borderColor, borderTextColor, progressBarColor; int waveBlending; - const char *AText, *BText, *YText, *PText, *MText; + const char *AText, *BText, *XText, *YText, *PText, *MText, *starOnText, *starOffText; bool good_cfg = false; if(themePath[0]!=0) @@ -110,13 +116,19 @@ void themeStartup(ThemePreset preset) { AText = themeDefault->buttonAText; if (!config_setting_lookup_string(theme, "buttonBText", &BText)) BText = themeDefault->buttonBText; + if (!config_setting_lookup_string(theme, "buttonXText", &XText)) + XText = themeDefault->buttonXText; if (!config_setting_lookup_string(theme, "buttonYText", &YText)) YText = themeDefault->buttonYText; if (!config_setting_lookup_string(theme, "buttonPText", &PText)) PText = themeDefault->buttonPText; if (!config_setting_lookup_string(theme, "buttonMText", &MText)) MText = themeDefault->buttonMText; - themeCurrent = (theme_t) { + if (!config_setting_lookup_string(theme, "labelStarOnText", &starOnText)) + starOnText = themeDefault->labelStarOnText; + if (!config_setting_lookup_string(theme, "labelStarOffText", &starOffText)) + starOffText = themeDefault->labelStarOffText; + themeCurrent = (theme_t) { .textColor = text, .frontWaveColor = frontWave, .middleWaveColor = middleWave, @@ -132,6 +144,7 @@ void themeStartup(ThemePreset preset) { }; strncpy(themeCurrent.buttonAText, AText, sizeof(themeCurrent.buttonAText)-1); strncpy(themeCurrent.buttonBText, BText, sizeof(themeCurrent.buttonBText)-1); + strncpy(themeCurrent.buttonXText, XText, sizeof(themeCurrent.buttonXText)-1); strncpy(themeCurrent.buttonYText, YText, sizeof(themeCurrent.buttonYText)-1); strncpy(themeCurrent.buttonPText, PText, sizeof(themeCurrent.buttonPText)-1); strncpy(themeCurrent.buttonMText, MText, sizeof(themeCurrent.buttonMText)-1); diff --git a/common/theme.h b/common/theme.h index 65ef7d4..9ccecd6 100644 --- a/common/theme.h +++ b/common/theme.h @@ -18,9 +18,12 @@ typedef struct bool enableWaveBlending; char buttonAText[32]; char buttonBText[32]; + char buttonXText[32]; char buttonYText[32]; char buttonPText[32]; char buttonMText[32]; + char labelStarOnText[32]; + char labelStarOffText[32]; const uint8_t *hbmenuLogoImage; } theme_t; diff --git a/nx_main/main.c b/nx_main/main.c index b968e7e..4b2a2c4 100644 --- a/nx_main/main.c +++ b/nx_main/main.c @@ -204,6 +204,10 @@ bool menuUpdate(void) { { launchMenuNetloaderTask(); } + else if (down & KEY_X) + { + menuHandleXButton(); + } else if (down & KEY_A) { menuHandleAButton(); diff --git a/nx_main/nx_touch.c b/nx_main/nx_touch.c index 1584033..593997b 100644 --- a/nx_main/nx_touch.c +++ b/nx_main/nx_touch.c @@ -13,6 +13,11 @@ #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))) @@ -127,6 +132,16 @@ void handleTouch(menu_s* menu) { } } } + // Star + else { + int i; + menuEntry_s* me; + for (i = 0, me = menu->firstEntry; i != menu->curEntry; i ++, me = me->next); + 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(); + } + } } // Vertical Swipe else if (abs(x1 - x2) < VERTICAL_SWIPE_HORIZONTAL_PLAY && distance(x1, y1, x2, y2) > VERTICAL_SWIPE_MINIMUM_DISTANCE) { diff --git a/pc_main/main.cpp b/pc_main/main.cpp index f038dc7..e8adbe0 100644 --- a/pc_main/main.cpp +++ b/pc_main/main.cpp @@ -74,6 +74,8 @@ extern "C" bool menuUpdate(void) { int new_esc_state = sf::Keyboard::isKeyPressed(sf::Keyboard::Escape); static int return_state = 0; int new_return_state = sf::Keyboard::isKeyPressed(sf::Keyboard::Return); + static int x_state = 0; + int new_x_state = sf::Keyboard::isKeyPressed(sf::Keyboard::X); static int y_state = 0; int new_y_state = sf::Keyboard::isKeyPressed(sf::Keyboard::Y); static int t_state = 0; @@ -82,7 +84,11 @@ extern "C" bool menuUpdate(void) { if(!new_y_state && y_state) { launchMenuNetloaderTask(); + } + if(!new_x_state && x_state) + { + menuHandleXButton(); } if (!new_esc_state && esc_state) From 48a4819e67a9794f22a85cf885fa332e05ffe2fe Mon Sep 17 00:00:00 2001 From: friedkeenan Date: Tue, 9 Jul 2019 14:30:53 -0500 Subject: [PATCH 12/22] Fix stars with custom themes --- common/theme.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/theme.c b/common/theme.c index bdc13af..5cf65a0 100644 --- a/common/theme.c +++ b/common/theme.c @@ -148,6 +148,8 @@ void themeStartup(ThemePreset preset) { strncpy(themeCurrent.buttonYText, YText, sizeof(themeCurrent.buttonYText)-1); strncpy(themeCurrent.buttonPText, PText, sizeof(themeCurrent.buttonPText)-1); strncpy(themeCurrent.buttonMText, MText, sizeof(themeCurrent.buttonMText)-1); + strncpy(themeCurrent.labelStarOffText, starOffText, sizeof(themeCurrent.labelStarOffText)-1); + strncpy(themeCurrent.labelStarOnText, starOnText, sizeof(themeCurrent.labelStarOnText)-1); } else { themeCurrent = *themeDefault; } From a123712db8412003f01499687db6e11b29ef9d5e Mon Sep 17 00:00:00 2001 From: octopuserectus Date: Wed, 10 Jul 2019 19:45:18 +0000 Subject: [PATCH 13/22] Fix inconsistensies in button label placement Also fixes text overlap with the new icons in "Theme Menu" --- common/menu.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/common/menu.c b/common/menu.c index cf29df6..5558f23 100644 --- a/common/menu.c +++ b/common/menu.c @@ -542,15 +542,15 @@ void drawButtons(menu_s* menu, bool emptyDir, int *x_image_out) { x_image = x_text - 36; *x_image_out = x_image - 40; - DrawText(fontscale7, x_image, 720 - 47 + 26, themeCurrent.textColor, themeCurrent.buttonYText); - DrawText(interuiregular18, x_text, 720 - 47 + 26, themeCurrent.textColor, textGetString(StrId_NetLoader)); + DrawText(fontscale7, x_image, 720 - 47 + 24, themeCurrent.textColor, themeCurrent.buttonYText); + 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 + 26, themeCurrent.textColor, themeCurrent.buttonMText); - DrawText(interuiregular18, x_text, 720 - 47 + 26, themeCurrent.textColor, textGetString(StrId_ThemeMenu)); + DrawText(fontscale7, x_image, 720 - 47 + 24, themeCurrent.textColor, themeCurrent.buttonMText); + DrawText(interuiregular18, x_text, 720 - 47 + 24, themeCurrent.textColor, textGetString(StrId_ThemeMenu)); } } @@ -693,7 +693,7 @@ void menuLoop(void) { int getX = GetTextXCoordinate(interuiregular18, 1180, textGetString(StrId_ThemeMenu), 'r'); if(hbmenu_state == HBMENU_THEME_MENU) { - DrawText(interuiregular18, getX, 30 + 26 + 32 + 10, themeCurrent.textColor, textGetString(StrId_ThemeMenu)); + DrawText(interuiregular18, getX, 30 + 26 + 32 + 20, themeCurrent.textColor, textGetString(StrId_ThemeMenu)); } else { //DrawText(interuiregular18, getX, 30 + 26 + 32 + 10, themeCurrent.textColor, textGetString(StrId_ThemeMenu)); //DrawText(fontscale7, getX - 40, 30 + 26 + 32 + 10, themeCurrent.textColor, themeCurrent.buttonMText); From 3ceb44fd78f2a77117e73d77cae5f1ee9a2a1983 Mon Sep 17 00:00:00 2001 From: octopuserectus Date: Wed, 10 Jul 2019 20:17:04 +0000 Subject: [PATCH 14/22] Change font size for back button label --- common/menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/menu.c b/common/menu.c index 5558f23..dc1840e 100644 --- a/common/menu.c +++ b/common/menu.c @@ -533,7 +533,7 @@ void drawButtons(menu_s* menu, bool emptyDir, int *x_image_out) { { //drawImage(x_image, 720 - 48, 32, 32, themeCurrent.buttonBImage, IMAGE_MODE_RGBA32); DrawText(fontscale7, x_image, 720 - 47 + 24, themeCurrent.textColor, themeCurrent.buttonBText);//Display the 'B' button from SharedFont. - DrawText(interuimedium20, x_text, 720 - 47 + 24, themeCurrent.textColor, textGetString(StrId_Actions_Back)); + DrawText(interuiregular18, x_text, 720 - 47 + 24, themeCurrent.textColor, textGetString(StrId_Actions_Back)); } if(hbmenu_state == HBMENU_DEFAULT) From f2e085b6be411a25d3bda9b283767de5e1e9660d Mon Sep 17 00:00:00 2001 From: yellows8 Date: Sat, 13 Jul 2019 11:20:37 -0400 Subject: [PATCH 15/22] Use enum from latest libnx for appletSetScreenShotPermission. --- nx_main/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nx_main/main.c b/nx_main/main.c index 4b2a2c4..25f0950 100644 --- a/nx_main/main.c +++ b/nx_main/main.c @@ -42,7 +42,7 @@ int main(int argc, char **argv) memset(errormsg, 0, sizeof(errormsg)); appletLockExit(); - appletSetScreenShotPermission(1); + appletSetScreenShotPermission(AppletScreenShotPermission_Enable); ColorSetId theme; rc = setsysInitialize(); From 78da39d0a20a0a595f3433fd918ddc111c4bb1e7 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Sat, 13 Jul 2019 18:03:17 -0400 Subject: [PATCH 16/22] Draw the star icons as part of the text, instead of seperately. Removed unstar icon usage. --- common/menu.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/common/menu.c b/common/menu.c index dc1840e..1254cea 100644 --- a/common/menu.c +++ b/common/menu.c @@ -179,6 +179,7 @@ static void drawEntry(menuEntry_s* me, int off_x, int is_active) { const uint8_t *smallimg = NULL; const uint8_t *largeimg = NULL; + char *strptr = NULL; char tmpstr[1024]; int border_start_x, border_end_x; @@ -287,8 +288,6 @@ static void drawEntry(menuEntry_s* me, int off_x, int is_active) { if (smallimg) { drawImage(start_x, start_y + 32, 140, 140, smallimg, IMAGE_MODE_RGB24); - if (me->starred) - DrawText(interuimedium30, start_x + 105 + 16, start_y + 16, themeCurrent.borderTextColor, themeCurrent.labelStarOnText); } if (is_active && largeimg) { @@ -310,13 +309,21 @@ static void drawEntry(menuEntry_s* me, int off_x, int is_active) { } } - DrawTextTruncate(interuiregular14, start_x + 4, start_y + 4 + 18, themeCurrent.borderTextColor, me->name, 140 - 32, "..."); + if (me->type != ENTRY_TYPE_THEME) + strptr = me->starred ? themeCurrent.labelStarOnText : ""; + else + strptr = ""; + + memset(tmpstr, 0, sizeof(tmpstr)); + snprintf(tmpstr, sizeof(tmpstr)-1, "%s%s", strptr, me->name); + + DrawTextTruncate(interuiregular14, start_x + 4, start_y + 4 + 18, themeCurrent.borderTextColor, tmpstr, 140 - 32, "..."); if (is_active) { start_x = 1280 - 790; start_y = 135; - DrawTextTruncate(interuimedium30, start_x, start_y + 39, themeCurrent.textColor, me->name, 1280 - start_x - 120 ,"..."); + DrawTextTruncate(interuimedium30, start_x, start_y + 39, themeCurrent.textColor, tmpstr, 1280 - start_x - 120 ,"..."); if (me->type != ENTRY_TYPE_FOLDER) { memset(tmpstr, 0, sizeof(tmpstr)); @@ -326,12 +333,6 @@ static void drawEntry(menuEntry_s* me, int off_x, int is_active) { snprintf(tmpstr, sizeof(tmpstr)-1, "%s: %s", textGetString(StrId_AppInfo_Version), me->version); DrawText(interuiregular14, start_x, start_y + 28 + 30 + 18 + 6 + 18, themeCurrent.textColor, tmpstr); } - - if (me->starred) - DrawText(largestar, start_x - 68, 160, themeCurrent.textColor, themeCurrent.labelStarOnText); - else - if (me->type != ENTRY_TYPE_THEME) - DrawText(largestar, start_x - 68, 160, themeCurrent.textColor, themeCurrent.labelStarOffText); } } From ce35f40f31c4b621f0cf241051593e1112f1bab9 Mon Sep 17 00:00:00 2001 From: fincs Date: Mon, 29 Jul 2019 17:36:59 +0200 Subject: [PATCH 17/22] Display "Applet Mode" indicator when running under an applet --- common/language.c | 12 +++++++++--- common/language.h | 1 + common/menu.c | 16 +++++++++++----- common/theme.c | 23 ++++++++++++++--------- common/theme.h | 1 + 5 files changed, 36 insertions(+), 17 deletions(-) diff --git a/common/language.c b/common/language.c index 9aaeb51..9d4de14 100644 --- a/common/language.c +++ b/common/language.c @@ -46,6 +46,12 @@ const char* const g_strings[StrId_Max][16] = STR_TW("加載中…"), }, + [StrId_AppletMode] = + { + STR_EN("● Applet Mode ●"), + STR_ES("● Modo Applet ●"), + }, + [StrId_Directory] = { STR_EN("Directory"), @@ -292,7 +298,7 @@ const char* const g_strings[StrId_Max][16] = STR_ZH("打开"), STR_TW("開啟"), }, - + [StrId_Actions_Back] = { STR_EN("Back"), @@ -336,13 +342,13 @@ const char* const g_strings[StrId_Max][16] = STR_EN("Star"), STR_ES("Agregar a favoritos"), }, - + [StrId_Actions_Unstar] = { STR_EN("Unstar"), STR_ES("Borrar de favoritos"), }, - + [StrId_ThemeMenu] = { STR_EN("Theme Menu"), diff --git a/common/language.h b/common/language.h index 1604f3d..95bbcd8 100644 --- a/common/language.h +++ b/common/language.h @@ -6,6 +6,7 @@ typedef enum { StrId_Loading = 0, + StrId_AppletMode, StrId_Directory, StrId_DefaultPublisher, StrId_IOError, diff --git a/common/menu.c b/common/menu.c index 1254cea..199ada3 100644 --- a/common/menu.c +++ b/common/menu.c @@ -104,7 +104,7 @@ void menuHandleAButton(void) { void menuHandleXButton(void) { menu_s* menu = menuGetCurrent(); - + if (menu->nEntries > 0 && hbmenu_state == HBMENU_DEFAULT) { int i; menuEntry_s* me; @@ -118,7 +118,7 @@ void launchApplyThemeTask(menuEntry_s* arg) { const char* themePath = arg->path; SetThemePathToConfig(themePath); themeStartup(themeGlobalPreset); - computeFrontGradient(themeCurrent.frontWaveColor, 280); + computeFrontGradient(themeCurrent.frontWaveColor, 280); } bool menuIsNetloaderActive(void) { @@ -471,13 +471,13 @@ void drawCharge() { bool validPower; validPower = powerGetDetails(&batteryCharge, &isCharging); - + if (validPower) { batteryCharge = (batteryCharge > 100) ? 100 : batteryCharge; sprintf(chargeString, "%d%%", batteryCharge); - + int tmpX = GetTextXCoordinate(interuiregular14, 1180 - 10, chargeString, 'r'); DrawText(interuiregular14, tmpX - 24 - 8, 0 + 47 + 10 + 21 + 4, themeCurrent.textColor, chargeString); @@ -604,6 +604,12 @@ void menuLoop(void) { drawImage(40, 20, 140, 60, themeCurrent.hbmenuLogoImage, IMAGE_MODE_RGBA32); DrawText(interuiregular14, 180, 46 + 18, themeCurrent.textColor, VERSION); + #ifdef __SWITCH__ + AppletType at = appletGetAppletType(); + if (at != AppletType_Application && at != AppletType_SystemApplication) { + DrawText(interuimedium30, 640-32, 46 + 18, themeCurrent.attentionTextColor, textGetString(StrId_AppletMode)); + } + #endif #ifdef PERF_LOG_DRAW//Seperate from the PERF_LOG define since this might affect perf. extern u64 g_tickdiff_frame; @@ -699,7 +705,7 @@ void menuLoop(void) { //DrawText(interuiregular18, getX, 30 + 26 + 32 + 10, themeCurrent.textColor, textGetString(StrId_ThemeMenu)); //DrawText(fontscale7, getX - 40, 30 + 26 + 32 + 10, themeCurrent.textColor, themeCurrent.buttonMText); } - + if(active_entry != NULL) { if (active_entry->type == ENTRY_TYPE_THEME) { DrawText(fontscale7, 1280 - 126 - 30 - 32, 720 - 47 + 24, themeCurrent.textColor, themeCurrent.buttonAText); diff --git a/common/theme.c b/common/theme.c index 5cf65a0..a67069f 100644 --- a/common/theme.c +++ b/common/theme.c @@ -12,8 +12,9 @@ bool colorFromSetting(config_setting_t *rgba, color_t *col) { void themeStartup(ThemePreset preset) { themeGlobalPreset = preset; - theme_t themeLight = (theme_t) { + theme_t themeLight = (theme_t) { .textColor = MakeColor(0, 0, 0, 255), + .attentionTextColor = MakeColor(255, 0, 0, 255), .frontWaveColor = MakeColor(100, 212, 250, 255), .middleWaveColor = MakeColor(100, 153, 255, 255), .backWaveColor = MakeColor(154, 171, 255, 255), @@ -34,9 +35,10 @@ void themeStartup(ThemePreset preset) { .labelStarOffText = "\u2606", .hbmenuLogoImage = assetsGetDataBuffer(AssetId_hbmenu_logo_light), }; - - theme_t themeDark = (theme_t) { + + theme_t themeDark = (theme_t) { .textColor = MakeColor(255, 255, 255, 255), + .attentionTextColor = MakeColor(255, 0, 0, 255), .frontWaveColor = MakeColor(96, 204, 204, 255), .middleWaveColor = MakeColor(66, 154, 159, 255), .backWaveColor = MakeColor(73, 103, 169, 255), @@ -65,7 +67,7 @@ void themeStartup(ThemePreset preset) { config_t cfg = {0}; config_init(&cfg); config_setting_t *theme = NULL; - color_t text, frontWave, middleWave, backWave, background, highlight, separator, borderColor, borderTextColor, progressBarColor; + color_t text, attentionText, frontWave, middleWave, backWave, background, highlight, separator, borderColor, borderTextColor, progressBarColor; int waveBlending; const char *AText, *BText, *XText, *YText, *PText, *MText, *starOnText, *starOffText; bool good_cfg = false; @@ -92,6 +94,8 @@ void themeStartup(ThemePreset preset) { if (theme != NULL) { if (!colorFromSetting(config_setting_lookup(theme, "textColor"), &text)) text = themeDefault->textColor; + if (!colorFromSetting(config_setting_lookup(theme, "attentionTextColor"), &attentionText)) + attentionText = themeDefault->attentionTextColor; if (!colorFromSetting(config_setting_lookup(theme, "frontWaveColor"), &frontWave)) frontWave = themeDefault->frontWaveColor; if (!colorFromSetting(config_setting_lookup(theme, "middleWaveColor"), &middleWave)) @@ -130,6 +134,7 @@ void themeStartup(ThemePreset preset) { starOffText = themeDefault->labelStarOffText; themeCurrent = (theme_t) { .textColor = text, + .attentionTextColor = attentionText, .frontWaveColor = frontWave, .middleWaveColor = middleWave, .backWaveColor = backWave, @@ -169,7 +174,7 @@ void GetThemePathFromConfig(char* themePath, size_t size) { snprintf(tmp_path, sizeof(tmp_path)-1, "%s/config/nx-hbmenu/settings.cfg", menuGetRootBasePath()); snprintf(tmp_path_theme, sizeof(tmp_path_theme)-1, "%s/config/nx-hbmenu/themes/", menuGetRootBasePath()); bool good_cfg = config_read_file(&cfg, tmp_path); - + if(good_cfg) { settings = config_lookup(&cfg, "settings"); if(settings != NULL) { @@ -187,7 +192,7 @@ void SetThemePathToConfig(const char* themePath) { char settingPath[PATH_MAX] = {0}; config_setting_t *root = NULL, - *group = NULL, + *group = NULL, *settings = NULL; themePath = getSlash(themePath); @@ -199,7 +204,7 @@ void SetThemePathToConfig(const char* themePath) { snprintf(settingPath, sizeof(settingPath)-1, "%s/config/nx-hbmenu/settings.cfg", menuGetRootBasePath()); bool good_cfg = config_read_file(&cfg, settingPath); - + if(good_cfg) { group = config_lookup(&cfg, "settings"); if(group != NULL) @@ -210,9 +215,9 @@ void SetThemePathToConfig(const char* themePath) { root = config_root_setting(&cfg); if(root != NULL) group = config_setting_add(root, "settings", CONFIG_TYPE_GROUP); - if(group != NULL) + if(group != NULL) settings = config_setting_add(group, "themePath", CONFIG_TYPE_STRING); - if(settings != NULL) + if(settings != NULL) config_setting_set_string(settings, themePath); } diff --git a/common/theme.h b/common/theme.h index 9ccecd6..2cc48b0 100644 --- a/common/theme.h +++ b/common/theme.h @@ -6,6 +6,7 @@ typedef struct { color_t textColor; + color_t attentionTextColor; color_t frontWaveColor; color_t middleWaveColor; color_t backWaveColor; From 6c84575ef790992101606921339d14c37dce5973 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Mon, 5 Aug 2019 12:00:45 -0400 Subject: [PATCH 18/22] Fixed buffer overflow when the netloader chunksize is too large, during NRO transfer (this will not occur with an unmodified nxlink). --- common/netloader.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/common/netloader.c b/common/netloader.c index dd3ad6a..9624870 100644 --- a/common/netloader.c +++ b/common/netloader.c @@ -304,6 +304,12 @@ static int decompress(int sock, FILE *fh, size_t filesize) { return Z_DATA_ERROR; } + if (chunksize > sizeof(in)) { + (void)inflateEnd(&strm); + netloader_error("Invalid chunk size.",0); + return Z_DATA_ERROR; + } + strm.avail_in = recvall(sock,in,chunksize,0); if (strm.avail_in == 0) { From d9effc31436e5a0249d52c781d2c6f50e5f0a207 Mon Sep 17 00:00:00 2001 From: fincs Date: Mon, 5 Aug 2019 22:45:01 +0200 Subject: [PATCH 19/22] Display hbmenu and hbloader version, side by side. Align "Applet Mode" text to the right. --- common/font.c | 12 ++++++------ common/menu.c | 29 +++++++++++++++++++++++------ 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/common/font.c b/common/font.c index 803cad9..2acdf7d 100644 --- a/common/font.c +++ b/common/font.c @@ -43,7 +43,7 @@ static bool FontSetType(u32 font) case interuimedium30: scale = 8; break; - + case largestar: scale = 18; break; @@ -313,8 +313,8 @@ void GetTextDimensions(u32 font, const char* text, uint32_t* width_out, uint32_t width = x; } - *width_out = width; - *height_out = height; + if(width_out) *width_out = width; + if(height_out) *height_out = height; } bool fontInitialize(void) @@ -380,11 +380,11 @@ void fontExit() if (s_font_libret==0) FT_Done_FreeType(s_font_library); } -/*Automatically gives you the desired x-coordinate +/*Automatically gives you the desired x-coordinate *based on the string length and desired alignment *rY=reference point... where to align around *align='t','b','c' translates to (top,bottom,center) - *'t' aligned, top of text aligns with rY, + *'t' aligned, top of text aligns with rY, *you get the rest.... */ uint32_t GetTextYCoordinate(u32 font, uint32_t rY, const char* text, const char align) { @@ -405,7 +405,7 @@ uint32_t GetTextYCoordinate(u32 font, uint32_t rY, const char* text, const char } } -/*Automatically gives you the desired x-coordinate +/*Automatically gives you the desired x-coordinate *based on the string length and desired alignment *rX=reference point... where to align around *text=string you want to display diff --git a/common/menu.c b/common/menu.c index 199ada3..9674ec0 100644 --- a/common/menu.c +++ b/common/menu.c @@ -496,7 +496,7 @@ void drawNetwork(int tmpX) { } } -void drawStatus() { +u32 drawStatus() { char timeString[9]; @@ -509,12 +509,14 @@ void drawStatus() { sprintf(timeString, "%02d:%02d:%02d", hours, minutes, seconds); - int tmpX = GetTextXCoordinate(interuimedium20, 1180, timeString, 'r'); + u32 tmpX = GetTextXCoordinate(interuimedium20, 1180, timeString, 'r'); DrawText(interuimedium20, tmpX, 0 + 47 + 10, themeCurrent.textColor, timeString); drawCharge(); drawNetwork(tmpX); + + return tmpX; } void drawButtons(menu_s* menu, bool emptyDir, int *x_image_out) { @@ -603,11 +605,28 @@ void menuLoop(void) { menuTimer += 0.05; drawImage(40, 20, 140, 60, themeCurrent.hbmenuLogoImage, IMAGE_MODE_RGBA32); - DrawText(interuiregular14, 180, 46 + 18, themeCurrent.textColor, VERSION); + DrawText(interuiregular14, 184, 46 + 18, themeCurrent.textColor, VERSION); + u32 statusXPos = drawStatus(); + #ifdef __SWITCH__ AppletType at = appletGetAppletType(); if (at != AppletType_Application && at != AppletType_SystemApplication) { - DrawText(interuimedium30, 640-32, 46 + 18, themeCurrent.attentionTextColor, textGetString(StrId_AppletMode)); + const char* appletMode = textGetString(StrId_AppletMode); + u32 x_pos = GetTextXCoordinate(interuimedium30, statusXPos, appletMode, 'r'); + DrawText(interuimedium30, x_pos - 32, 46 + 18, themeCurrent.attentionTextColor, appletMode); + } + const char* loaderInfo = envGetLoaderInfo(); + if (loaderInfo) { + u32 x_pos = 43; + char* spacePos = strchr(loaderInfo, ' '); + if (spacePos) { + char tempbuf[64] = {0}; + size_t tempsize = spacePos - loaderInfo + 1; + if (tempsize > sizeof(tempbuf)-1) tempsize = sizeof(tempbuf)-1; + memcpy(tempbuf, loaderInfo, tempsize); + x_pos = GetTextXCoordinate(interuiregular14, 184, tempbuf, 'r'); + } + DrawText(interuiregular14, x_pos, 46 + 18 + 20, themeCurrent.textColor, loaderInfo); } #endif @@ -620,8 +639,6 @@ void menuLoop(void) { DrawText(interuiregular14, 180 + 256, 46 + 16 + 18, themeCurrent.textColor, tmpstr); #endif - drawStatus(); - memset(&netloader_state, 0, sizeof(netloader_state)); netloaderGetState(&netloader_state); From ea4db4ff02295650d89fa65afceb855e0bd2bc8d Mon Sep 17 00:00:00 2001 From: yellows8 Date: Mon, 5 Aug 2019 16:49:59 -0400 Subject: [PATCH 20/22] Moved the gfx for the current active entry down by 10 pixels. --- common/menu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/menu.c b/common/menu.c index 9674ec0..b0f7d96 100644 --- a/common/menu.c +++ b/common/menu.c @@ -291,9 +291,9 @@ static void drawEntry(menuEntry_s* me, int off_x, int is_active) { } if (is_active && largeimg) { - drawImage(117, 100, 256, 256, largeimg, IMAGE_MODE_RGB24); + drawImage(117, 100+10, 256, 256, largeimg, IMAGE_MODE_RGB24); - shadow_start_y = 100+256; + shadow_start_y = 100+10+256; border_start_x = 117; border_end_x = 117+256; @@ -321,7 +321,7 @@ static void drawEntry(menuEntry_s* me, int off_x, int is_active) { if (is_active) { start_x = 1280 - 790; - start_y = 135; + start_y = 135+10; DrawTextTruncate(interuimedium30, start_x, start_y + 39, themeCurrent.textColor, tmpstr, 1280 - start_x - 120 ,"..."); From fa3d93d6491c9e7df4107eda9e155e91b3fc923e Mon Sep 17 00:00:00 2001 From: yellows8 Date: Thu, 8 Aug 2019 17:55:56 -0400 Subject: [PATCH 21/22] Enabled using setvbuf with adjustments, improves netloader perf. Fixed issue with large-chunksize, chunksize is now uint32_t and initialized to 0. Minor other change. --- common/netloader.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/common/netloader.c b/common/netloader.c index 9624870..471b03d 100644 --- a/common/netloader.c +++ b/common/netloader.c @@ -274,7 +274,7 @@ static int decompress(int sock, FILE *fh, size_t filesize) { int ret; unsigned have; z_stream strm; - size_t chunksize; + uint32_t chunksize=0; /* allocate inflate state */ strm.zalloc = Z_NULL; @@ -306,7 +306,7 @@ static int decompress(int sock, FILE *fh, size_t filesize) { if (chunksize > sizeof(in)) { (void)inflateEnd(&strm); - netloader_error("Invalid chunk size.",0); + netloader_error("Invalid chunk size",chunksize); return Z_DATA_ERROR; } @@ -442,11 +442,18 @@ int loadnro(menuEntry_s *me, int sock, struct in_addr remote) { send(sock,(char *)&response,sizeof(response),0); + char *writebuffer = NULL; if (response == 0 ) { + writebuffer = malloc(FILE_BUFFER_SIZE); + if (writebuffer==NULL) { + netloader_error("Failed to allocate memory",ENOMEM); + response = -1; + } + else + setvbuf(file,writebuffer,_IOFBF, FILE_BUFFER_SIZE); + } - //char *writebuffer=malloc(FILE_BUFFER_SIZE); - //setvbuf(file,writebuffer,_IOFBF, FILE_BUFFER_SIZE); - + if (response == 0 ) { //printf("transferring %s\n%d bytes.\n", filename, filelen); if (decompress(sock,file,filelen)==Z_OK) { @@ -493,9 +500,9 @@ int loadnro(menuEntry_s *me, int sock, struct in_addr remote) { response = -1; } - //free(writebuffer); fflush(file); fclose(file); + free(writebuffer); if (response == -1) unlink(me->path); } From d7c37c68619501fc90180dfd1f5ca57c36b96a0f Mon Sep 17 00:00:00 2001 From: yellows8 Date: Thu, 8 Aug 2019 20:49:30 -0400 Subject: [PATCH 22/22] Release v3.1.0 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ac900fe..5a8662d 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -export APP_VERSION := 3.0.1 +export APP_VERSION := 3.1.0 ifeq ($(RELEASE),) export APP_VERSION := $(APP_VERSION)-$(shell git describe --dirty --always)