diff --git a/.travis.yml b/.travis.yml index a91ab47..4e349aa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,24 +2,39 @@ language: c sudo: true -#Cache devkitARM and doxygen -cache: - directories: - - /home/travis/devkitPro - before_install: - cd include/dr_libs/ - git clone https://github.com/mackron/dr_libs.git - cd ../.. - - export DEVKITPRO=/opt/devkitpro - - export DEVKITARM=/opt/devkitpro/devkitARM - - export CTRULIB=${DEVKITPRO}/libctru - - export PORTLIBS=${DEVKITPRO}/portlibs/armv6k - - sh resources/.travis-deps.sh + - wget https://github.com/devkitPro/pacman/releases/download/v1.0.0/devkitpro-pacman.deb + - sudo dpkg -i devkitpro-pacman.deb + +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - libstdc++-4.9-dev + +install: + - sudo dkp-pacman -Syu 3ds-dev --noconfirm --needed + - sudo dkp-pacman -Syu 3ds-curl --noconfirm --force + - sudo dkp-pacman -S 3ds-libogg --noconfirm + - sudo dkp-pacman -S 3ds-libvorbisidec --noconfirm + - sudo dkp-pacman -S 3ds-mpg123 --noconfirm + - source /etc/profile.d/devkit-env.sh + - export CC=arm-none-eabi-gcc + - export CXX=arm-none-eabi-g++ + - git clone --recursive https://github.com/Steveice10/bannertool && cd bannertool/ + - make && sudo cp output/linux-x86_64/bannertool /opt/devkitpro/devkitARM/bin/bannertool + - cd ../ && rm -rf bannertool/ + - git clone https://github.com/profi200/Project_CTR.git && cd Project_CTR/makerom + - make && sudo cp makerom /opt/devkitpro/devkitARM/bin/makerom + - cd ../.. && rm -rf Project_CTR script: - cd $TRAVIS_BUILD_DIR - - sh resources/.build.sh + - sh .travis/build.sh deploy: provider: pages diff --git a/.travis/build.sh b/.travis/build.sh new file mode 100644 index 0000000..9a16e15 --- /dev/null +++ b/.travis/build.sh @@ -0,0 +1,7 @@ +#!/bin/bash -ex + +source /etc/profile.d/devkit-env.sh +cd /3DShell +make clean && make +rm .gitignore .gitmodules .travis.yml 3DShell.elf 3DShell.smdh devkitpro-pacman.deb LICENSE Makefile README.md +rm -rf .travis build include res romfs source \ No newline at end of file diff --git a/Makefile b/Makefile index 5c71026..124faf8 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,10 @@ include $(DEVKITARM)/3ds_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 +# GRAPHICS is a list of directories containing graphics files +# GFXBUILD is the directory where converted graphics files will be placed +# If set to $(BUILD), it will statically link in the converted +# files as if they were data files. # # NO_SMDH: if set to anything, no SMDH file is generated. # ROMFS is the directory which contains the RomFS, relative to the Makefile (Optional) @@ -27,69 +31,60 @@ include $(DEVKITARM)/3ds_rules # - icon.png # - /default_icon.png #--------------------------------------------------------------------------------- - -# CIA -APP_TITLE := 3DShell -APP_PRODUCT_CODE := CTR-3D-SHEL -APP_ROMFS := romfs -APP_CATEGORY := Application -APP_UNIQUE_ID := 0x16200 -APP_USE_ON_SD := true -APP_ENCRYPTED := false -APP_MEMORY_TYPE := Application -APP_SYSTEM_MODE := 64MB -APP_SYSTEM_MODE_EXT := Legacy -APP_CPU_SPEED := 268MHz -APP_ENABLE_L2_CACHE := true -VERSION_MAJOR := 3 -VERSION_MINOR := 0 -VERSION_MICRO := 0 -APP_RSF_FILE := resources/cia.rsf - -APP_DESCRIPTION := Multi purpose file manager GUI -APP_AUTHOR := Joel16 - -TARGET := $(subst $e ,_,$(notdir $(APP_TITLE))) -OUTDIR := out -BUILD := build -SOURCES := source source/audio source/ftp source/menus source/minizip source/misc source/pp2d +TARGET := $(notdir $(CURDIR)) +BUILD := build +SOURCES := source source/audio source/ftp source/graphics source/menus source/minizip DATA := data -INCLUDES := include include/audio include/dr_libs include/ftp include/menus include/minizip include/misc include/pp2d - -ICON := resources/ic_launcher_filemanager.png -BANNER := resources/banner.png -BANNER_AUDIO := resources/banner.wav -LOGO := resources/logo.lz11 -ICON_FLAGS := nosavebackups,visible +INCLUDES := include include/audio include/dr_libs include/ftp include/graphics include/menus include/minizip +GRAPHICS := res/drawable +ROMFS := romfs +GFXBUILD := $(ROMFS)/res/drawable + +APP_TITLE := 3DShell +APP_DESCRIPTION := Multi-purpose file manager +APP_AUTHOR := Joel16 +VERSION_MAJOR := 4 +VERSION_MINOR := 0 +VERSION_MICRO := 0 +GITVERSION := $(shell git log -1 --pretty='%h') +ICON := res/ic_launcher_filemanager.png -GITVERSION := $(shell git log -1 --pretty='%h') +# CIA +BANNER_AUDIO := res/banner.wav +BANNER_IMAGE := res/banner.png +RSF_PATH := res/app.rsf +LOGO := res/logo.lz11 +UNIQUE_ID := 0x16200 +PRODUCT_CODE := CTR-3D-SHEL +ICON_FLAGS := nosavebackups,visible #--------------------------------------------------------------------------------- # options for code generation #--------------------------------------------------------------------------------- -ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft +ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft -CFLAGS := -g -Werror -O2 -mword-relocations \ - -fomit-frame-pointer -ffunction-sections \ - -DVERSION_MAJOR=$(VERSION_MAJOR) -DVERSION_MINOR=$(VERSION_MINOR) -DVERSION_MICRO=$(VERSION_MICRO) \ +CFLAGS := -g -Werror -O2 -mword-relocations \ + -fomit-frame-pointer -ffunction-sections \ + -DVERSION_MAJOR=$(VERSION_MAJOR) -DVERSION_MINOR=$(VERSION_MINOR) -DVERSION_MICRO=$(VERSION_MICRO) \ -DAPP_TITLE="\"$(APP_TITLE)\"" \ -DGITVERSION="\"${GITVERSION}\"" \ $(ARCH) -CFLAGS += $(INCLUDE) -DARM11 -D_3DS +CFLAGS += $(INCLUDE) -DARM11 -D_3DS -CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 -ASFLAGS := -g $(ARCH) -LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) -LIBS := -lcurl -lmbedtls -lmbedx509 -lmbedcrypto -lmpg123 -lvorbisidec -logg -lcitro3d -lctru -lm -lz +LIBS := -lcurl -lmbedtls -lmbedx509 -lmbedcrypto -lmpg123 -lvorbisidec -logg \ + -lcitro2d -lcitro3d -lctru -lm -lz #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing # include and lib #--------------------------------------------------------------------------------- -LIBDIRS := $(CTRULIB) $(PORTLIBS) +LIBDIRS := $(PORTLIBS) $(CTRULIB) #--------------------------------------------------------------------------------- # no real need to edit anything past this point unless you need to add additional @@ -98,44 +93,69 @@ LIBDIRS := $(CTRULIB) $(PORTLIBS) ifneq ($(BUILD),$(notdir $(CURDIR))) #--------------------------------------------------------------------------------- -export OUTPUT := $(CURDIR)/$(OUTDIR)/$(TARGET) -export TOPDIR := $(CURDIR) +export OUTPUT := $(CURDIR)/$(TARGET) +export TOPDIR := $(CURDIR) -export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ - $(foreach dir,$(DATA),$(CURDIR)/$(dir)) +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) export DEPSDIR := $(CURDIR)/$(BUILD) -CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) -CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) -SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -PICAFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.v.pica))) -SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist))) -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +PICAFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.v.pica))) +SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist))) +GFXFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.t3s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) #--------------------------------------------------------------------------------- # use CXX for linking C++ projects, CC for standard C #--------------------------------------------------------------------------------- ifeq ($(strip $(CPPFILES)),) #--------------------------------------------------------------------------------- - export LD := $(CC) + export LD := $(CC) #--------------------------------------------------------------------------------- else #--------------------------------------------------------------------------------- - export LD := $(CXX) + export LD := $(CXX) #--------------------------------------------------------------------------------- endif #--------------------------------------------------------------------------------- -export OFILES := $(addsuffix .o,$(BINFILES)) \ +#--------------------------------------------------------------------------------- +ifeq ($(GFXBUILD),$(BUILD)) +#--------------------------------------------------------------------------------- +export T3XFILES := $(GFXFILES:.t3s=.t3x) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- +export ROMFS_T3XFILES := $(patsubst %.t3s, $(GFXBUILD)/%.t3x, $(GFXFILES)) +export T3XHFILES := $(patsubst %.t3s, $(BUILD)/%.h, $(GFXFILES)) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES_SOURCES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) + +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) \ $(PICAFILES:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.shbin.o) \ - $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) + $(addsuffix .o,$(T3XFILES)) + +export OFILES := $(OFILES_BIN) $(OFILES_SOURCES) -export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ +export HFILES := $(PICAFILES:.v.pica=_shbin.h) $(SHLISTFILES:.shlist=_shbin.h) \ + $(addsuffix .h,$(subst .,_,$(BINFILES))) \ + $(GFXFILES:.t3s=.h) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ -I$(CURDIR)/$(BUILD) -export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +export _3DSXDEPS := $(if $(NO_SMDH),,$(OUTPUT).smdh) ifeq ($(strip $(ICON)),) icons := $(wildcard *.png) @@ -151,106 +171,98 @@ else endif ifeq ($(strip $(NO_SMDH)),) - export _3DSXFLAGS += --smdh=$(OUTPUT).smdh + export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh endif -ifneq ("$(wildcard $(APP_ROMFS))","") - _3DSXFLAGS += --romfs=$(APP_ROMFS) +ifneq ($(ROMFS),) + export _3DSXFLAGS += --romfs=$(CURDIR)/$(ROMFS) endif -ifeq ($(strip $(VERSION_MAJOR)),) - VERSION_MAJOR := 0 -endif +.PHONY: all clean -ifeq ($(strip $(VERSION_MINOR)),) - VERSION_MINOR := 0 +#--------------------------------------------------------------------------------- +MAKEROM ?= makerom +MAKEROM_ARGS := -elf "$(OUTPUT).elf" -rsf "$(RSF_PATH)" -banner "$(BUILD)/banner.bnr" -icon "$(BUILD)/icon.icn" -DAPP_TITLE="$(APP_TITLE)" -DAPP_PRODUCT_CODE="$(PRODUCT_CODE)" -DAPP_UNIQUE_ID="$(UNIQUE_ID)" +MAKEROM_ARGS += -major $(VERSION_MAJOR) -minor $(VERSION_MINOR) -micro $(VERSION_MICRO) + +ifneq ($(strip $(LOGO)),) + MAKEROM_ARGS += -logo "$(LOGO)" +endif +ifneq ($(strip $(ROMFS)),) + MAKEROM_ARGS += -DAPP_ROMFS="$(ROMFS)" endif -ifeq ($(strip $(VERSION_MICRO)),) - VERSION_MICRO := 0 +BANNERTOOL ?= bannertool + +ifeq ($(suffix $(BANNER_IMAGE)),.cgfx) + BANNER_IMAGE_ARG := -ci +else + BANNER_IMAGE_ARG := -i endif -.PHONY: $(BUILD) clean all +ifeq ($(suffix $(BANNER_AUDIO)),.cwav) + BANNER_AUDIO_ARG := -ca +else + BANNER_AUDIO_ARG := -a +endif #--------------------------------------------------------------------------------- -all: 3dsx cia +all: $(BUILD) $(GFXBUILD) $(DEPSDIR) $(ROMFS_T3XFILES) $(T3XHFILES) + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + @$(BANNERTOOL) makebanner $(BANNER_IMAGE_ARG) "$(BANNER_IMAGE)" $(BANNER_AUDIO_ARG) "$(BANNER_AUDIO)" -o "$(BUILD)/banner.bnr" + @$(BANNERTOOL) makesmdh -s "$(APP_TITLE)" -l "$(APP_DESCRIPTION)" -p "$(APP_AUTHOR)" -i "$(APP_ICON)" -f "$(ICON_FLAGS)" -o "$(BUILD)/icon.icn" + $(MAKEROM) -f cia -o "$(OUTPUT).cia" -target t -exefslogo $(MAKEROM_ARGS) @echo "${VERSION_MAJOR}${VERSION_MINOR}${VERSION_MICRO}" > UPDATE_MILESTONE.txt # For maintainer builds @echo "${GITVERSION}" > UPDATE_NIGHTLY.txt # For maintainer builds -3dsx: $(BUILD) $(OUTPUT).3dsx +$(BUILD): + @mkdir -p $@ -cia : $(BUILD) $(OUTPUT).cia +ifneq ($(GFXBUILD),$(BUILD)) +$(GFXBUILD): + @mkdir -p $@ +endif -citra: export CITRA_MODE = 1 -citra: 3dsx -#--------------------------------------------------------------------------------- -$(BUILD): - @mkdir -p $(OUTDIR) - @[ -d "$@" ] || mkdir -p "$@" - @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile +ifneq ($(DEPSDIR),$(BUILD)) +$(DEPSDIR): + @mkdir -p $@ +endif #--------------------------------------------------------------------------------- clean: @echo clean ... - @rm -fr $(BUILD) $(OUTDIR) + @rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf $(GFXBUILD) #--------------------------------------------------------------------------------- -ifeq ($(strip $(NO_SMDH)),) -$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh -else -$(OUTPUT).3dsx : $(OUTPUT).elf -endif - +$(GFXBUILD)/%.t3x $(BUILD)/%.h : %.t3s #--------------------------------------------------------------------------------- -MAKEROM ?= makerom -MAKEROM_ARGS := -rsf "$(APP_RSF_FILE)" -target t -exefslogo -icon "$(BUILD)/icon.icn" -banner "$(BUILD)/banner.bnr" -major $(VERSION_MAJOR) -minor $(VERSION_MINOR) -micro $(VERSION_MICRO) -DAPP_TITLE="$(APP_TITLE)" -DAPP_PRODUCT_CODE="$(APP_PRODUCT_CODE)" -DAPP_UNIQUE_ID="$(APP_UNIQUE_ID)" -DAPP_SYSTEM_MODE="$(APP_SYSTEM_MODE)" -DAPP_SYSTEM_MODE_EXT="$(APP_SYSTEM_MODE_EXT)" -DAPP_CATEGORY="$(APP_CATEGORY)" -DAPP_USE_ON_SD="$(APP_USE_ON_SD)" -DAPP_MEMORY_TYPE="$(APP_MEMORY_TYPE)" -DAPP_CPU_SPEED="$(APP_CPU_SPEED)" -DAPP_ENABLE_L2_CACHE="$(APP_ENABLE_L2_CACHE)" -DAPP_VERSION_MAJOR=$(VERSION_MAJOR) - -ifneq ("$(wildcard $(LOGO))","") - MAKEROM_ARGS += -logo "$(LOGO)" -endif - -ifneq ("$(wildcard $(APP_ROMFS))","") - MAKEROM_ARGS += -DAPP_ROMFS="$(APP_ROMFS)" -endif - -$(OUTPUT).cia: $(OUTPUT).elf $(BUILD)/banner.bnr $(BUILD)/icon.icn - $(MAKEROM) -f cia -o $@ -elf $< -DAPP_ENCRYPTED=false $(MAKEROM_ARGS) - -BANNERTOOL ?= bannertool - -ifeq ($(suffix $(BANNER)),.cgfx) - BANNER_ARG := -ci -else - BANNER_ARG := -i -endif - -ifeq ($(suffix $(BANNER_AUDIO)),.cwav) - BANNER_AUDIO_ARG := -ca -else - BANNER_AUDIO_ARG := -a -endif - -$(BUILD)/banner.bnr : $(BANNER) $(BANNER_AUDIO) - $(BANNERTOOL) makebanner $(BANNER_ARG) "$(BANNER)" $(BANNER_AUDIO_ARG) "$(BANNER_AUDIO)" -o "$@" - -$(BUILD)/icon.icn : $(APP_ICON) - $(BANNERTOOL) makesmdh -s "$(APP_TITLE)" -l "$(APP_DESCRIPTION)" -p "$(APP_AUTHOR)" -i "$(APP_ICON)" -f "$(ICON_FLAGS)" -o "$@" + @echo $(notdir $<) + @tex3ds -i $< -H $(BUILD)/$*.h -d $(DEPSDIR)/$*.d -o $(GFXBUILD)/$*.t3x #--------------------------------------------------------------------------------- else -DEPENDS := $(OFILES:.o=.d) - #--------------------------------------------------------------------------------- # main targets #--------------------------------------------------------------------------------- +$(OUTPUT).3dsx : $(OUTPUT).elf $(_3DSXDEPS) -$(OUTPUT).elf : $(OFILES) +$(OFILES_SOURCES) : $(HFILES) + +$(OUTPUT).elf : $(OFILES) #--------------------------------------------------------------------------------- # you need a rule like this for each extension you use as binary data #--------------------------------------------------------------------------------- -%.bin.o : %.bin +%.bin.o %_bin.h : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +#--------------------------------------------------------------------------------- +.PRECIOUS : %.t3x +#--------------------------------------------------------------------------------- +%.t3x.o %_t3x.h : %.t3x #--------------------------------------------------------------------------------- @echo $(notdir $<) @$(bin2o) @@ -259,27 +271,35 @@ $(OUTPUT).elf : $(OFILES) # rules for assembling GPU shaders #--------------------------------------------------------------------------------- define shader-as - $(eval CURBIN := $(patsubst %.shbin.o,%.shbin,$(notdir $@))) - picasso -o $(CURBIN) $1 - bin2s $(CURBIN) | $(AS) -o $@ + $(eval CURBIN := $*.shbin) + $(eval DEPSFILE := $(DEPSDIR)/$*.shbin.d) + echo "$(CURBIN).o: $< $1" > $(DEPSFILE) echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(CURBIN) | tr . _)`.h echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(CURBIN) | tr . _)`.h echo "extern const u32" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(CURBIN) | tr . _)`.h + picasso -o $(CURBIN) $1 + bin2s $(CURBIN) | $(AS) -o $*.shbin.o endef -%.shbin.o : %.v.pica %.g.pica +%.shbin.o %_shbin.h : %.v.pica %.g.pica @echo $(notdir $^) @$(call shader-as,$^) -%.shbin.o : %.v.pica +%.shbin.o %_shbin.h : %.v.pica @echo $(notdir $<) @$(call shader-as,$<) -%.shbin.o : %.shlist +%.shbin.o %_shbin.h : %.shlist + @echo $(notdir $<) + @$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)$(file))) + +#--------------------------------------------------------------------------------- +%.t3x %.h : %.t3s +#--------------------------------------------------------------------------------- @echo $(notdir $<) - @$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file))) + @tex3ds -i $< -H $*.h -d $*.d -o $*.t3x --include $(DEPENDS) +-include $(DEPSDIR)/*.d #--------------------------------------------------------------------------------------- endif diff --git a/include/C2D_helper.h b/include/C2D_helper.h new file mode 100644 index 0000000..f45614c --- /dev/null +++ b/include/C2D_helper.h @@ -0,0 +1,37 @@ +#ifndef _3D_SHELL_C2D_HELPER_H +#define _3D_SHELL_C2D_HELPER_H + +#include + +#define WHITE C2D_Color32(255, 255, 255, 255) +#define BLACK_BG C2D_Color32(48, 48, 48, 255) +#define STATUS_BAR_LIGHT C2D_Color32(37, 79, 174, 255) +#define STATUS_BAR_DARK C2D_Color32(38, 50, 56, 255) +#define MENU_BAR_LIGHT C2D_Color32(51, 103, 214, 255) +#define MENU_BAR_DARK C2D_Color32(55, 71, 79, 255) +#define BLACK C2D_Color32(0, 0, 0, 255) +#define SELECTOR_COLOUR_LIGHT C2D_Color32(241, 241, 241, 255) +#define SELECTOR_COLOUR_DARK C2D_Color32(76, 76, 76, 255) +#define TITLE_COLOUR C2D_Color32(30, 136, 229, 255) +#define TITLE_COLOUR_DARK C2D_Color32(0, 150, 136, 255) +#define TEXT_MIN_COLOUR_LIGHT C2D_Color32(32, 32, 32, 255) +#define TEXT_MIN_COLOUR_DARK C2D_Color32(185, 185, 185, 255) +#define BAR_COLOUR C2D_Color32(200, 200, 200, 255) +#define PROGRESS_COLOUR C2D_Color32(48, 174, 222, 255) + +C3D_RenderTarget *RENDER_TOP, *RENDER_BOTTOM; +C2D_TextBuf staticBuf, dynamicBuf, sizeBuf; + +typedef u32 Colour; + +void Draw_EndFrame(void); +void Draw_Text(float x, float y, float size, Colour colour, const char *text); +void Draw_Textf(float x, float y, float size, Colour colour, const char* text, ...); +void Draw_GetTextSize(float size, float *width, float *height, const char *text); +float Draw_GetTextWidth(float size, const char *text); +float Draw_GetTextHeight(float size, const char *text); +bool Draw_Rect(float x, float y, float w, float h, Colour colour); +bool Draw_Image(C2D_Image image, float x, float y); +bool Draw_ImageScale(C2D_Image image, float x, float y, float scaleX, float scaleY); + +#endif \ No newline at end of file diff --git a/include/audio/audio.h b/include/audio/audio.h index 0fde76a..8df2929 100644 --- a/include/audio/audio.h +++ b/include/audio/audio.h @@ -1,16 +1,41 @@ #ifndef AUDIO_H #define AUDIO_H -#include "menu_music.h" +#include <3ds.h> + +extern volatile bool stop; enum channel_e { - BGM = 0, + BGM, SFX }; -bool Audio_IsPlaying(enum channel_e); +enum file_types +{ + FILE_TYPE_ERROR, + FILE_TYPE_BCSTM, + FILE_TYPE_WAV, + FILE_TYPE_FLAC, + FILE_TYPE_VORBIS, + FILE_TYPE_MP3 +}; + +struct decoder_fn +{ + int (* init)(const char *file); + u32 (* rate)(void); + u8 (* channels)(void); + size_t buffSize; + u64 (* decode)(void*); + void (* exit)(void); +}; + bool Audio_IsPaused(enum channel_e); bool Audio_TogglePlayback(enum channel_e); +void Audio_StopPlayback(void); +bool Audio_IsPlaying(void); +enum file_types Audio_GetMusicFileType(const char *file); +void Audio_PlayFile(void *path); #endif diff --git a/include/audio/flac.h b/include/audio/flac.h index 2b23dab..765bd2b 100644 --- a/include/audio/flac.h +++ b/include/audio/flac.h @@ -1,53 +1,53 @@ /* Obtained from ctrmus source with permission. */ -#include "menu_music.h" +#include "audio.h" /** - * Set decoder parameters for flac. + *Set decoder parameters for flac. * - * \param decoder Structure to store parameters. + *\param decoder Structure to store parameters. */ -void setFlac(struct decoder_fn * decoder); +void setFlac(struct decoder_fn *decoder); /** - * Initialise Flac decoder. + *Initialise Flac decoder. * - * \param file Location of flac file to play. - * \return 0 on success, else failure. + *\param file Location of flac file to play. + *\return 0 on success, else failure. */ -int initFlac(const char * file); +int initFlac(const char *file); /** - * Get sampling rate of Flac file. + *Get sampling rate of Flac file. * - * \return Sampling rate. + *\return Sampling rate. */ u32 rateFlac(void); /** - * Get number of channels of Flac file. + *Get number of channels of Flac file. * - * \return Number of channels for opened file. + *\return Number of channels for opened file. */ u8 channelFlac(void); /** - * Decode part of open Flac file. + *Decode part of open Flac file. * - * \param buffer Decoded output. - * \return Samples read for each channel. + *\param buffer Decoded output. + *\return Samples read for each channel. */ -u64 decodeFlac(void * buffer); +u64 decodeFlac(void *buffer); /** - * Free Flac decoder. + *Free Flac decoder. */ void exitFlac(void); /** - * Checks if the input file is Flac + *Checks if the input file is Flac * - * \param in Input file. - * \return 0 if Flac file, else not or failure. + *\param in Input file. + *\return 0 if Flac file, else not or failure. */ -int isFlac(const char * in); \ No newline at end of file +int isFlac(const char *in); \ No newline at end of file diff --git a/include/audio/mp3.h b/include/audio/mp3.h index 881096c..f8cb828 100644 --- a/include/audio/mp3.h +++ b/include/audio/mp3.h @@ -2,7 +2,7 @@ #include -#include "menu_music.h" +#include "audio.h" typedef struct { @@ -16,46 +16,46 @@ typedef struct ID3_Tag ID3; -char * id3_pic; +char *id3_pic; /** - * Set decoder parameters for MP3. + *Set decoder parameters for MP3. * - * \param decoder Structure to store parameters. + *\param decoder Structure to store parameters. */ -void setMp3(struct decoder_fn * decoder); +void setMp3(struct decoder_fn *decoder); /** - * Initialise MP3 decoder. + *Initialise MP3 decoder. * - * \param file Location of MP3 file to play. - * \return 0 on success, else failure. + *\param file Location of MP3 file to play. + *\return 0 on success, else failure. */ -int initMp3(const char * file); +int initMp3(const char *file); /** - * Get sampling rate of MP3 file. + *Get sampling rate of MP3 file. * - * \return Sampling rate. + *\return Sampling rate. */ u32 rateMp3(void); /** - * Get number of channels of MP3 file. + *Get number of channels of MP3 file. * - * \return Number of channels for opened file. + *\return Number of channels for opened file. */ u8 channelMp3(void); /** - * Decode part of open MP3 file. + *Decode part of open MP3 file. * - * \param buffer Decoded output. - * \return Samples read for each channel. + *\param buffer Decoded output. + *\return Samples read for each channel. */ -u64 decodeMp3(void * buffer); +u64 decodeMp3(void *buffer); /** - * Free MP3 decoder. + *Free MP3 decoder. */ void exitMp3(void); \ No newline at end of file diff --git a/include/audio/vorbis.h b/include/audio/vorbis.h index 3b20901..ccc3c7d 100644 --- a/include/audio/vorbis.h +++ b/include/audio/vorbis.h @@ -3,22 +3,22 @@ #include #include -#include "menu_music.h" +#include "audio.h" -void setVorbis(struct decoder_fn * decoder); +void setVorbis(struct decoder_fn *decoder); -int initVorbis(const char * file); +int initVorbis(const char *file); u32 rateVorbis(void); u8 channelVorbis(void); -u64 decodeVorbis(void * buffer); +u64 decodeVorbis(void *buffer); void exitVorbis(void); -int playVorbis(const char * in); +int playVorbis(const char *in); -u64 fillVorbisBuffer(char * bufferOut); +u64 fillVorbisBuffer(char *bufferOut); -int isVorbis(const char * in); \ No newline at end of file +int isVorbis(const char *in); \ No newline at end of file diff --git a/include/audio/wav.h b/include/audio/wav.h index 74bcad0..bbac5a9 100644 --- a/include/audio/wav.h +++ b/include/audio/wav.h @@ -1,51 +1,51 @@ -#include "menu_music.h" +#include "audio.h" /** - * Set decoder parameters for WAV. + *Set decoder parameters for WAV. * - * \param decoder Structure to store parameters. + *\param decoder Structure to store parameters. */ -void setWav(struct decoder_fn * decoder); +void setWav(struct decoder_fn *decoder); /** - * Initialise WAV playback. + *Initialise WAV playback. * - * \param file Location of WAV file to play. - * \return 0 on success, else failure. + *\param file Location of WAV file to play. + *\return 0 on success, else failure. */ -int initWav(const char * file); +int initWav(const char *file); /** - * Get sampling rate of Wav file. + *Get sampling rate of Wav file. * - * \return Sampling rate. + *\return Sampling rate. */ u32 rateWav(void); /** - * Get number of channels of Wav file. + *Get number of channels of Wav file. * - * \return Number of channels for opened file. + *\return Number of channels for opened file. */ u8 channelWav(void); /** - * Decode part of open Wav file. + *Decode part of open Wav file. * - * \param buffer Output. - * \return Samples read for each channel. + *\param buffer Output. + *\return Samples read for each channel. */ -u64 decodeWav(void * buffer); +u64 decodeWav(void *buffer); /** - * Free Wav file. + *Free Wav file. */ void exitWav(void); /** - * Checks if the input file is Wav + *Checks if the input file is Wav * - * \param in Input file. - * \return 0 if Wav file, else not or failure. + *\param in Input file. + *\return 0 if Wav file, else not or failure. */ -int isWav(const char * in); \ No newline at end of file +int isWav(const char *in); \ No newline at end of file diff --git a/include/cia.h b/include/cia.h index c6d51d1..735161d 100644 --- a/include/cia.h +++ b/include/cia.h @@ -1,8 +1,8 @@ -#ifndef CIA_H -#define CIA_H +#ifndef _3D_SHELL_CIA_H +#define _3D_SHELL_CIA_H #include <3ds.h> -Result CIA_InstallTitle(const char * path, FS_MediaType media, bool update); +Result CIA_InstallTitle(const char *path, FS_MediaType media, bool update); #endif \ No newline at end of file diff --git a/include/common.h b/include/common.h index d7ad133..1d8c568 100644 --- a/include/common.h +++ b/include/common.h @@ -1,37 +1,37 @@ -#ifndef COMMON_H -#define COMMON_H +#ifndef NX_SHELL_COMMON_H +#define NX_SHELL_COMMON_H -#include <3ds.h> +#include + +#define wait(msec) svcSleepThread(10000000 * (s64)msec) #define ROOT_PATH "/" #define START_PATH ROOT_PATH #define MAX_FILES 1024 #define FILES_PER_PAGE 5 -#define wait(msec) svcSleepThread(10000000 * (s64)msec) - -int MENU_DEFAULT_STATE; - -#define MENU_STATE_HOME 0 -#define MENU_STATE_OPTIONS 1 -#define MENU_STATE_SETTINGS 2 -#define MENU_STATE_FTP 3 -#define MENU_STATE_SORT 4 -#define MENU_STATE_THEMES 5 -#define MENU_STATE_DIALOG 6 -#define MENU_STATE_PROPERTIES 7 -#define MENU_STATE_UPDATE 8 -#define MENU_STATE_UPDATE_2 9 - +#define MENU_STATE_HOME 0 +#define MENU_STATE_FILEOPTIONS 1 +#define MENU_STATE_MENUBAR 2 +#define MENU_STATE_SETTINGS 3 +#define MENU_STATE_FTP 4 +#define MENU_STATE_SORT 5 +#define MENU_STATE_THEMES 6 +#define MENU_STATE_DELETE 7 +#define MENU_STATE_PROPERTIES 8 +#define MENU_STATE_UPDATE 9 +#define MENU_STATE_UPDATE_2 10 +#define MENU_STATE_ABOUT 11 + +#define BROWSE_STATE_SD 0 +#define BROWSE_STATE_NAND 1 + +jmp_buf exitJmp; + +int MENU_STATE; int BROWSE_STATE; -#define STATE_SD 0 -#define STATE_NAND 1 - char cwd[512]; -char fileName[255]; - -bool recycleBin, galleryDisplay, isHiddenEnabled; -int sortBy; +char fileName[256]; #endif \ No newline at end of file diff --git a/include/config.h b/include/config.h new file mode 100644 index 0000000..2b38190 --- /dev/null +++ b/include/config.h @@ -0,0 +1,13 @@ +#ifndef _3D_SHELL_CONFIG_H +#define _3D_SHELL_CONFIG_H + +#include <3ds.h> + +bool config_dark_theme, config_hidden_files; +int config_sort_by; + +Result Config_Save(bool config_dark_theme, bool config_hidden_files, int config_sort_by); +Result Config_Load(void); +Result Config_GetLastDirectory(void); + +#endif \ No newline at end of file diff --git a/include/dir_list.h b/include/dir_list.h deleted file mode 100644 index f49ed52..0000000 --- a/include/dir_list.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef DIRLIST_H -#define DIRLIST_H - -#include <3ds.h> - -typedef struct File -{ - struct File * next; // Next item - int isDir; // Folder flag - int isReadOnly; // Read-only flag - int isHidden; // Hidden file flag - u8 name[256]; // File name - char ext[4]; // File extension - u64 size; // File size -} File; - -extern File * files; - -extern int position; -extern int fileCount; -bool multi_select[255]; -char multi_select_dir[255]; - -Result Dirlist_PopulateFiles(bool clear); -void Dirlist_DisplayFiles(void); -File * Dirlist_GetFileIndex(int index); -void Dirlist_OpenFile(void); -int Dirlist_Navigate(int dir); - -#endif \ No newline at end of file diff --git a/include/dirbrowse.h b/include/dirbrowse.h new file mode 100644 index 0000000..c018203 --- /dev/null +++ b/include/dirbrowse.h @@ -0,0 +1,36 @@ +#ifndef _3D_SHELL_DIRBROWSE_H +#define _3D_SHELL_DIRBROWSE_H + +#include <3ds.h> + +typedef struct File +{ + struct File *next; // Next item + int isDir; // Folder flag + int isReadOnly; // Read-only flag + int isHidden; // Hidden file flag + u8 name[256]; // File name + char ext[4]; // File extension + u64 size; // File size +} File; + +extern File *files; + +extern int initialPosition; +extern int position; +extern int fileCount; + +int multi_select_index; // Multi-select index. +bool multi_select[256]; // Array of indices selected. +int multi_select_indices[256]; // Array to hold the indices. +char multi_select_dir[256]; // Holds the current dir where multi-select happens. +char multi_select_paths[51][256]; // Holds the file paths of those in the clipboard. + +void Dirbrowse_RecursiveFree(File *node); +Result Dirbrowse_PopulateFiles(bool clear); +void Dirbrowse_DisplayFiles(void); +File *Dirbrowse_GetFileIndex(int index); +void Dirbrowse_OpenFile(void); +int Dirbrowse_Navigate(int dir); + +#endif \ No newline at end of file diff --git a/include/fs.h b/include/fs.h index 2c99e3d..9b45715 100644 --- a/include/fs.h +++ b/include/fs.h @@ -1,28 +1,29 @@ -#ifndef FS_H -#define FS_H +#ifndef _3D_SHELL_FS_H +#define _3D_SHELL_FS_H #include <3ds.h> FS_Archive archive; -Result FS_OpenArchive(FS_Archive * archive, FS_ArchiveID id); +Result FS_OpenArchive(FS_Archive *archive, FS_ArchiveID id); Result FS_CloseArchive(FS_Archive archive); -Result FS_MakeDir(FS_Archive archive, const char * path); -Result FS_RecursiveMakeDir(FS_Archive archive, const char * dir); -bool FS_FileExists(FS_Archive archive, const char * path); -bool FS_DirExists(FS_Archive archive, const char * path); -char* FS_GetFileModifiedTime(char * path); -u64 FS_GetFileSize(FS_Archive archive, const char * path); +Result FS_MakeDir(FS_Archive archive, const char *path); +Result FS_RecursiveMakeDir(FS_Archive archive, const char *dir); +bool FS_FileExists(FS_Archive archive, const char *path); +bool FS_DirExists(FS_Archive archive, const char *path); +char* FS_GetFileModifiedTime(char *path); +Result FS_GetFileSize(FS_Archive archive, const char *path, u64 *size); u64 FS_GetFreeStorage(FS_SystemMediaType mediaType); u64 FS_GetTotalStorage(FS_SystemMediaType mediaType); u64 FS_GetUsedStorage(FS_SystemMediaType mediaType); -Result FS_Remove(FS_Archive archive, const char * filename); -Result FS_Rmdir(FS_Archive archive, const char * path); -Result FS_RmdirRecursive(FS_Archive archive, const char * path); -Result FS_RenameFile(FS_Archive archive, const char * old_filename, const char * new_filename); -Result FS_RenameDir(FS_Archive archive, const char * old_filename, const char * new_filename); -Result FS_Open(Handle * handle, FS_Archive archive, const char * path, u32 flags); -Result FS_Read(FS_Archive archive, const char * path, u64 size, char * buf); -Result FS_Write(FS_Archive archive, const char * path, const char * buf); +Result FS_Remove(FS_Archive archive, const char *filename); +Result FS_Rmdir(FS_Archive archive, const char *path); +Result FS_RmdirRecursive(FS_Archive archive, const char *path); +Result FS_RenameFile(FS_Archive archive, const char *old_filename, const char *new_filename); +Result FS_RenameDir(FS_Archive archive, const char *old_filename, const char *new_filename); +Result FS_Open(Handle *handle, FS_Archive archive, const char *path, u32 flags); +Result FS_Read(FS_Archive archive, const char *path, u64 size, char *buf); +Result FS_Write(FS_Archive archive, const char *path, const char *buf); +char *FS_GetFileTimestamp(FS_Archive archive, char *path); #endif \ No newline at end of file diff --git a/include/graphics/loadbmp.h b/include/graphics/loadbmp.h new file mode 100644 index 0000000..c35318a --- /dev/null +++ b/include/graphics/loadbmp.h @@ -0,0 +1,278 @@ + +// Author: Christian Vallentin +// Website: http://vallentinsource.com +// Repository: https://github.com/MrVallentin/LoadBMP +// +// Date Created: January 03, 2014 +// Last Modified: August 13, 2016 +// +// Version: 1.1.0 + +// Copyright (c) 2014-2016 Christian Vallentin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. + +// Include loadbmp.h as following +// to create the implementation file. +// +// #define LOADBMP_IMPLEMENTATION +// #include "loadbmp.h" + +#ifndef LOADBMP_H +#define LOADBMP_H + +#ifdef __cplusplus +extern "C" { +#endif + + +// Errors +#define LOADBMP_NO_ERROR 0 + +#define LOADBMP_OUT_OF_MEMORY 1 + +#define LOADBMP_FILE_NOT_FOUND 2 +#define LOADBMP_FILE_OPERATION 3 + +#define LOADBMP_INVALID_FILE_FORMAT 4 + +#define LOADBMP_INVALID_SIGNATURE 5 +#define LOADBMP_INVALID_BITS_PER_PIXEL 6 + + +// Components +#define LOADBMP_RGB 3 +#define LOADBMP_RGBA 4 + + +#ifdef LOADBMP_IMPLEMENTATION +# define LOADBMP_API +#else +# define LOADBMP_API extern +#endif + + +// LoadBMP uses raw buffers and support RGB and RGBA formats. +// The order is RGBRGBRGB... or RGBARGBARGBA..., from top left +// to bottom right, without any padding. + + +LOADBMP_API unsigned int loadbmp_decode_file( + const char *filename, unsigned char **imageData, unsigned int *width, unsigned int *height, unsigned int components); + +LOADBMP_API unsigned int loadbmp_encode_file( + const char *filename, const unsigned char *imageData, unsigned int width, unsigned int height, unsigned int components); + + +#ifdef LOADBMP_IMPLEMENTATION + +// Disable Microsoft Visual C++ compiler security warnings for fopen, strcpy, etc being unsafe +#if defined(_MSC_VER) && (_MSC_VER >= 1310) +# pragma warning(disable: 4996) +#endif + +#include /* malloc(), free() */ +#include /* memset(), memcpy() */ +#include /* fopen(), fwrite(), fread(), fclose() */ + + +LOADBMP_API unsigned int loadbmp_decode_file( + const char *filename, unsigned char **imageData, unsigned int *width, unsigned int *height, unsigned int components) +{ + FILE *f = fopen(filename, "rb"); + + if (!f) + return LOADBMP_FILE_NOT_FOUND; + + unsigned char bmp_file_header[14]; + unsigned char bmp_info_header[40]; + unsigned char bmp_pad[3]; + + unsigned int w, h; + unsigned char *data = NULL; + + unsigned int x, y, i, padding; + + memset(bmp_file_header, 0, sizeof(bmp_file_header)); + memset(bmp_info_header, 0, sizeof(bmp_info_header)); + + if (fread(bmp_file_header, sizeof(bmp_file_header), 1, f) == 0) + { + fclose(f); + return LOADBMP_INVALID_FILE_FORMAT; + } + + if (fread(bmp_info_header, sizeof(bmp_info_header), 1, f) == 0) + { + fclose(f); + return LOADBMP_INVALID_FILE_FORMAT; + } + + if ((bmp_file_header[0] != 'B') || (bmp_file_header[1] != 'M')) + { + fclose(f); + return LOADBMP_INVALID_SIGNATURE; + } + + if ((bmp_info_header[14] != 24) && (bmp_info_header[14] != 32)) + { + fclose(f); + return LOADBMP_INVALID_BITS_PER_PIXEL; + } + + w = (bmp_info_header[4] + (bmp_info_header[5] << 8) + (bmp_info_header[6] << 16) + (bmp_info_header[7] << 24)); + h = (bmp_info_header[8] + (bmp_info_header[9] << 8) + (bmp_info_header[10] << 16) + (bmp_info_header[11] << 24)); + + if ((w > 0) && (h > 0)) + { + data = (unsigned char*)malloc(w * h * components); + + if (!data) + { + fclose(f); + return LOADBMP_OUT_OF_MEMORY; + } + + for (y = (h - 1); y != -1; y--) + { + for (x = 0; x < w; x++) + { + i = (x + y * w) * components; + + if (fread(data + i, 3, 1, f) == 0) + { + free(data); + + fclose(f); + return LOADBMP_INVALID_FILE_FORMAT; + } + + data[i] ^= data[i + 2] ^= data[i] ^= data[i + 2]; // BGR -> RGB + + if (components == LOADBMP_RGBA) + data[i + 3] = 255; + } + + padding = ((4 - (w * 3) % 4) % 4); + + if (fread(bmp_pad, 1, padding, f) != padding) + { + free(data); + + fclose(f); + return LOADBMP_INVALID_FILE_FORMAT; + } + } + } + + (*width) = w; + (*height) = h; + (*imageData) = data; + + fclose(f); + + return LOADBMP_NO_ERROR; +} + + +LOADBMP_API unsigned int loadbmp_encode_file( + const char *filename, const unsigned char *imageData, unsigned int width, unsigned int height, unsigned int components) +{ + FILE *f = fopen(filename, "wb"); + + if (!f) + return LOADBMP_FILE_OPERATION; + + unsigned char bmp_file_header[14] = { 'B', 'M', 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0 }; + unsigned char bmp_info_header[40] = { 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 24, 0 }; + const unsigned char bmp_pad[3] = { 0, 0, 0 }; + + const unsigned int size = 54 + width * height * 3; // 3 as the BMP format uses 3 channels (red, green, blue and NO alpha) + + unsigned int x, y, i, padding; + + unsigned char pixel[3]; + + bmp_file_header[2] = (unsigned char)(size); + bmp_file_header[3] = (unsigned char)(size >> 8); + bmp_file_header[4] = (unsigned char)(size >> 16); + bmp_file_header[5] = (unsigned char)(size >> 24); + + bmp_info_header[4] = (unsigned char)(width); + bmp_info_header[5] = (unsigned char)(width >> 8); + bmp_info_header[6] = (unsigned char)(width >> 16); + bmp_info_header[7] = (unsigned char)(width >> 24); + + bmp_info_header[8] = (unsigned char)(height); + bmp_info_header[9] = (unsigned char)(height >> 8); + bmp_info_header[10] = (unsigned char)(height >> 16); + bmp_info_header[11] = (unsigned char)(height >> 24); + + if (fwrite(bmp_file_header, 14, 1, f) == 0) + { + fclose(f); + return LOADBMP_FILE_OPERATION; + } + + if (fwrite(bmp_info_header, 40, 1, f) == 0) + { + fclose(f); + return LOADBMP_FILE_OPERATION; + } + + for (y = (height - 1); y != -1; y--) + { + for (x = 0; x < width; x++) + { + i = (x + y * width) * components; + + memcpy(pixel, imageData + i, sizeof(pixel)); + + pixel[0] ^= pixel[2] ^= pixel[0] ^= pixel[2]; // RGB -> BGR + + if (fwrite(pixel, sizeof(pixel), 1, f) == 0) + { + fclose(f); + return LOADBMP_FILE_OPERATION; + } + } + + padding = ((4 - (width * 3) % 4) % 4); + + if (fwrite(bmp_pad, 1, padding, f) != padding) + { + fclose(f); + return LOADBMP_FILE_OPERATION; + } + } + + fclose(f); + + return LOADBMP_NO_ERROR; +} + + +#endif + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/include/pp2d/lodepng.h b/include/graphics/lodepng.h similarity index 99% rename from include/pp2d/lodepng.h rename to include/graphics/lodepng.h index cf6667c..6c56c1d 100644 --- a/include/pp2d/lodepng.h +++ b/include/graphics/lodepng.h @@ -1,5 +1,5 @@ /* -LodePNG version 20180114 +LodePNG version 20180611 Copyright (c) 2005-2018 Lode Vandevenne @@ -410,7 +410,7 @@ typedef struct LodePNGInfo /*header (IHDR), palette (PLTE) and transparency (tRNS) chunks*/ unsigned compression_method;/*compression method of the original file. Always 0.*/ unsigned filter_method; /*filter method of the original file*/ - unsigned interlace_method; /*interlace method of the original file*/ + unsigned interlace_method; /*interlace method of the original file: 0=none, 1=Adam7*/ LodePNGColorMode color; /*color type and bits, palette and transparency of the PNG file*/ #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS @@ -1614,6 +1614,7 @@ yyyymmdd. Some changes aren't backwards compatible. Those are indicated with a (!) symbol. +*) 11 jun 2018: less restrictive check for pixel size integer overflow *) 14 jan 2018: allow optionally ignoring a few more recoverable errors *) 17 sep 2017: fix memory leak for some encoder input error cases *) 27 nov 2016: grey+alpha auto color model detection bugfix @@ -1765,5 +1766,5 @@ Domain: gmail dot com. Account: lode dot vandevenne. -Copyright (c) 2005-2017 Lode Vandevenne +Copyright (c) 2005-2018 Lode Vandevenne */ diff --git a/include/pp2d/stb_image.h b/include/graphics/stb_image.h similarity index 100% rename from include/pp2d/stb_image.h rename to include/graphics/stb_image.h diff --git a/include/keyboard.h b/include/keyboard.h new file mode 100644 index 0000000..f67ab26 --- /dev/null +++ b/include/keyboard.h @@ -0,0 +1,6 @@ +#ifndef _3D_SHELL_KEYBOARD_H +#define _3D_SHELL_KEYBOARD_H + +char *OSK_Get(int maxTextLength, const char *initialText, const char *hintText); + +#endif \ No newline at end of file diff --git a/include/language.h b/include/language.h deleted file mode 100644 index 19fc025..0000000 --- a/include/language.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef LANGUAGE_H -#define LANGUAGE_H - -#include <3ds.h> - -CFG_Language language; - -const char lang_welcome[12][3][100]; -const char lang_months[12][12][50]; -const char lang_days[12][7][50]; -const char lang_files[12][11][50]; -const char lang_options[12][9][100]; -const char lang_properties[12][7][100]; -const char lang_deletion[12][5][100]; -const char lang_settings[12][9][100]; -const char lang_themes[12][1][100]; -const char lang_ftp[12][5][100]; -const char lang_update[12][4][100]; - -#endif \ No newline at end of file diff --git a/include/menus/menu_update.h b/include/menu_update.h similarity index 66% rename from include/menus/menu_update.h rename to include/menu_update.h index 6358b25..368faba 100644 --- a/include/menus/menu_update.h +++ b/include/menu_update.h @@ -1,10 +1,7 @@ -#ifndef MENU_UPDATE_H -#define MENU_UPDATE_H +#ifndef _3D_SHELL_MENU_UPDATE_H +#define _3D_SHELL_MENU_UPDATE_H #include <3ds.h> -#include - -jmp_buf exitJmp; void Menu_DisplayUpdate(void); void Menu_DisplayUpdate2(void); diff --git a/include/menus/menu_delete.h b/include/menus/menu_delete.h deleted file mode 100644 index 70d756b..0000000 --- a/include/menus/menu_delete.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef MENU_DELETE_H -#define MENU_DELETE_H - -#include <3ds.h> - -void Menu_DisplayDeleteDialog(void); -void Menu_ControlDeleteDialog(u32 input); - -#endif \ No newline at end of file diff --git a/include/menus/menu_file_options.h b/include/menus/menu_file_options.h deleted file mode 100644 index 9b50525..0000000 --- a/include/menus/menu_file_options.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef MENU_FILE_OPTIONS_H -#define MENU_FILE_OPTIONS_H - -#include <3ds.h> - -void Menu_DisplayFileOptions(void); -void Menu_ControlFileOptions(u32 input); - -#endif \ No newline at end of file diff --git a/include/menus/menu_fileoptions.h b/include/menus/menu_fileoptions.h new file mode 100644 index 0000000..74229fa --- /dev/null +++ b/include/menus/menu_fileoptions.h @@ -0,0 +1,14 @@ +#ifndef _3D_SHELL_MENU_FILEOPTIONS_H +#define _3D_SHELL_MENU_FILEOPTIONS_H + +#include <3ds.h> + +void FileOptions_ResetClipboard(void); +void Menu_DisplayDeleteDialog(void); +void Menu_ControlDeleteDialog(u32 input); +void Menu_DisplayProperties(void); +void Menu_ControlProperties(u32 input); +void Menu_DisplayFileOptions(void); +void Menu_ControlFileOptions(u32 input); + +#endif \ No newline at end of file diff --git a/include/menus/menu_ftp.h b/include/menus/menu_ftp.h index da4a9ff..dbb70a5 100644 --- a/include/menus/menu_ftp.h +++ b/include/menus/menu_ftp.h @@ -1,5 +1,5 @@ -#ifndef MENU_FTP_H -#define MENU_FTP_H +#ifndef _3D_SHELL_MENU_FTP_H +#define _3D_SHELL_MENU_FTP_H void Menu_DisplayFTP(void); diff --git a/include/menus/menu_gallery.h b/include/menus/menu_gallery.h index bb3e078..b326e3e 100644 --- a/include/menus/menu_gallery.h +++ b/include/menus/menu_gallery.h @@ -1,6 +1,6 @@ -#ifndef MENU_GALLERY_H -#define MENU_GALLERY_H +#ifndef _3D_SHELL_MENU_GALLERY_H +#define _3D_SHELL_MENU_GALLERY_H -void Gallery_DisplayImage(char * path); +void Gallery_DisplayImage(char *path); #endif \ No newline at end of file diff --git a/include/menus/menu_home.h b/include/menus/menu_home.h deleted file mode 100644 index 478a0d9..0000000 --- a/include/menus/menu_home.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef MENU_HOME_H -#define MENU_HOME_H - -void Menu_Home(void); - -#endif \ No newline at end of file diff --git a/include/menus/menu_main.h b/include/menus/menu_main.h index 075a9e2..4afa478 100644 --- a/include/menus/menu_main.h +++ b/include/menus/menu_main.h @@ -1,7 +1,8 @@ -#ifndef MENU_MAIN_H -#define MENU_MAIN_H +#ifndef _3D_SHELL_MENU_MAIN_H +#define _3D_SHELL_MENU_MAIN_H -void Menu_Draw_MenuBar(void); +void Menu_DrawMenuBar(void); +void Menu_ControlMenuBar(u32 input); void Menu_Main(void); #endif \ No newline at end of file diff --git a/include/menus/menu_music.h b/include/menus/menu_music.h index 360ec89..ff7b0e7 100644 --- a/include/menus/menu_music.h +++ b/include/menus/menu_music.h @@ -1,44 +1,6 @@ -#ifndef MENU_MUSIC_H -#define MENU_MUSIC_H +#ifndef _3D_SHELL_MENU_MUSIC_H +#define _3D_SHELL_MENU_MUSIC_H -#include <3ds.h> - -enum file_types -{ - FILE_TYPE_ERROR = 0, - FILE_TYPE_BCSTM, - FILE_TYPE_WAV, - FILE_TYPE_FLAC, - FILE_TYPE_VORBIS, - FILE_TYPE_MP3 -}; - -struct decoder_fn -{ - int (* init)(const char* file); - u32 (* rate)(void); - u8 (* channels)(void); - size_t buffSize; - u64 (* decode)(void*); - void (* exit)(void); -}; - -// Returns true if playing. -bool Music_IsPlaying(void); - -/** - * Obtains file type. - * - * \param file File location. - * \return file_types enum or 0 on error and errno set. - */ -enum file_types Music_GetMusicFileType(const char *file); - -/** - * Play an audio file. - * - * \param path File path. - */ -void Music_Player(char * path); +void Menu_PlayMusic(char *path); #endif diff --git a/include/menus/menu_properties.h b/include/menus/menu_properties.h deleted file mode 100644 index c53a2e1..0000000 --- a/include/menus/menu_properties.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef MENU_PROPERTIES_H -#define MENU_PROPERTIES_H - -#include <3ds.h> - -void Menu_DisplayProperties(void); -void Menu_ControlProperties(u32 input); - -#endif \ No newline at end of file diff --git a/include/menus/menu_settings.h b/include/menus/menu_settings.h index 82e04b1..700351b 100644 --- a/include/menus/menu_settings.h +++ b/include/menus/menu_settings.h @@ -1,8 +1,12 @@ -#ifndef MENU_SETTINGS_H -#define MENU_SETTINGS_H +#ifndef _3D_SHELL_MENU_SETTINGS_H +#define _3D_SHELL_MENU_SETTINGS_H #include <3ds.h> +void Menu_DisplayAbout(void); +void Menu_ControlAbout(u32 input); +void Menu_DisplaySortSettings(void); +void Menu_ControlSortSettings(u32 input); void Menu_DisplaySettings(void); void Menu_ControlSettings(u32 input); diff --git a/include/menus/menu_sort.h b/include/menus/menu_sort.h deleted file mode 100644 index 298a3a3..0000000 --- a/include/menus/menu_sort.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef MENU_SORT_H -#define MENU_SORT_H - -#include <3ds.h> - -void Menu_DisplaySort(void); -void Menu_ControlSort(u32 input); - -#endif \ No newline at end of file diff --git a/include/menus/menu_textviewer.h b/include/menus/menu_textviewer.h deleted file mode 100644 index c092518..0000000 --- a/include/menus/menu_textviewer.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef MENU_TEXTVIEWER_H -#define MENU_TEXTVIEWER_H - -void TextViewer_DisplayText(char * path); - -#endif \ No newline at end of file diff --git a/include/misc/battery.h b/include/misc/battery.h deleted file mode 100644 index f7a67aa..0000000 --- a/include/misc/battery.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef BATTERY_H -#define BATTERY_H - -char * Battery_GetBatteryPercentString(void); -void Battery_DrawIcons(int x, int y); - -#endif diff --git a/include/misc/clock.h b/include/misc/clock.h deleted file mode 100644 index 7abd6f9..0000000 --- a/include/misc/clock.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef CLOCK_H -#define CLOCK_H - -#include <3ds.h> - -char * Clock_GetCurrentTime(bool _12hour); -char * Clock_GetDayOfWeek(bool brief); -char * Clock_GetMonthOfYear(int style); - -#endif \ No newline at end of file diff --git a/include/misc/keyboard.h b/include/misc/keyboard.h deleted file mode 100644 index 52a77d0..0000000 --- a/include/misc/keyboard.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef KEYBOARD_H -#define KEYBOARD_H - -char * keyboard_3ds_get(int maxTextLength, const char* initialText, const char* hintText); - -#endif \ No newline at end of file diff --git a/include/misc/status_bar.h b/include/misc/status_bar.h deleted file mode 100644 index a7a5941..0000000 --- a/include/misc/status_bar.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef STATUS_BAR_H -#define STATUS_BAR_H - -void StatusBar_DisplayBar(void); - -#endif \ No newline at end of file diff --git a/include/misc/touch.h b/include/misc/touch.h deleted file mode 100644 index ae49915..0000000 --- a/include/misc/touch.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef TOUCH_H -#define TOUCH_H - -#define touchInRect(x1, y1, x2, y2) ((touchGetX() >= (x1) && touchGetX() <= (x2)) && (touchGetY() >= (y1) && touchGetY() <= (y2))) - -u16 touchGetX(void); -u16 touchGetY(void); - -#endif \ No newline at end of file diff --git a/include/misc/wifi.h b/include/misc/wifi.h deleted file mode 100644 index a0c6e33..0000000 --- a/include/misc/wifi.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef COMMON_H -#define COMMON_H - -void WiFi_DrawIcons(int x, int y); - -#endif \ No newline at end of file diff --git a/include/net.h b/include/net.h index 5a1ee60..bb277fb 100644 --- a/include/net.h +++ b/include/net.h @@ -1,5 +1,5 @@ -#ifndef NET_H -#define NET_H +#ifndef _3D_SHELL_NET_H +#define _3D_SHELL_NET_H #include <3ds.h> diff --git a/include/pp2d/LICENSE b/include/pp2d/LICENSE deleted file mode 100644 index 51ef706..0000000 --- a/include/pp2d/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2017 Bernardo Giordano - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/include/pp2d/README.md b/include/pp2d/README.md deleted file mode 100644 index c1682cc..0000000 --- a/include/pp2d/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# [pp2d](https://discord.gg/bGKEyfY) - -Plug & Play 2D (unofficial) wrapper for Citro3D. - -## License - -pp2d is licensed under the MIT License. - -## Changes - -* depth parameter (Ryuzaki-MrL) -* standalone pp2d_free_texture (LiquidFenrir) -* 3d support (Robz8) -* load png from memory (ErmanSayin) -* BMP support (blujay) diff --git a/include/pp2d/libnsbmp.h b/include/pp2d/libnsbmp.h deleted file mode 100644 index 7e90b4a..0000000 --- a/include/pp2d/libnsbmp.h +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright 2006 Richard Wilson - * Copyright 2008 Sean Fox - * - * This file is part of NetSurf's libnsbmp, http://www.netsurf-browser.org/ - * Licenced under the MIT License, - * http://www.opensource.org/licenses/mit-license.php - */ - -/** - * \file - * Bitmap file decoding interface. - */ - -#ifndef libnsbmp_h_ -#define libnsbmp_h_ - -#include -#include -#include - -/* bmp flags */ -#define BMP_NEW 0 -/** image is opaque (as opposed to having an alpha mask) */ -#define BMP_OPAQUE (1 << 0) -/** memory should be wiped */ -#define BMP_CLEAR_MEMORY (1 << 1) - -/** - * error return values - */ -typedef enum { - BMP_OK = 0, - BMP_INSUFFICIENT_MEMORY = 1, - BMP_INSUFFICIENT_DATA = 2, - BMP_DATA_ERROR = 3 -} bmp_result; - -/** - * encoding types - */ -typedef enum { - BMP_ENCODING_RGB = 0, - BMP_ENCODING_RLE8 = 1, - BMP_ENCODING_RLE4 = 2, - BMP_ENCODING_BITFIELDS = 3 -} bmp_encoding; - -/* API for Bitmap callbacks */ -typedef void* (*bmp_bitmap_cb_create)(int width, int height, unsigned int state); -typedef void (*bmp_bitmap_cb_destroy)(void *bitmap); -typedef unsigned char* (*bmp_bitmap_cb_get_buffer)(void *bitmap); -typedef size_t (*bmp_bitmap_cb_get_bpp)(void *bitmap); - -/** - * The Bitmap callbacks function table - */ -typedef struct bmp_bitmap_callback_vt_s { - /** Callback to allocate bitmap storage. */ - bmp_bitmap_cb_create bitmap_create; - /** Called to free bitmap storage. */ - bmp_bitmap_cb_destroy bitmap_destroy; - /** Return a pointer to the pixel data in a bitmap. */ - bmp_bitmap_cb_get_buffer bitmap_get_buffer; - /** Find the width of a pixel row in bytes. */ - bmp_bitmap_cb_get_bpp bitmap_get_bpp; -} bmp_bitmap_callback_vt; - -/** - * bitmap image - */ -typedef struct bmp_image { - /** callbacks for bitmap functions */ - bmp_bitmap_callback_vt bitmap_callbacks; - /** pointer to BMP data */ - uint8_t *bmp_data; - /** width of BMP (valid after _analyse) */ - uint32_t width; - /** heigth of BMP (valid after _analyse) */ - uint32_t height; - /** whether the image has been decoded */ - bool decoded; - /** decoded image */ - void *bitmap; - - /* Internal members are listed below */ - /** total number of bytes of BMP data available */ - uint32_t buffer_size; - /** pixel encoding type */ - bmp_encoding encoding; - /** offset of bitmap data */ - uint32_t bitmap_offset; - /** bits per pixel */ - uint16_t bpp; - /** number of colours */ - uint32_t colours; - /** colour table */ - uint32_t *colour_table; - /** whether to use bmp's limited transparency */ - bool limited_trans; - /** colour to display for "transparent" pixels when using limited - * transparency - */ - uint32_t trans_colour; - /** scanlines are top to bottom */ - bool reversed; - /** image is part of an ICO, mask follows */ - bool ico; - /** true if the bitmap does not contain an alpha channel */ - bool opaque; - /** four bitwise mask */ - uint32_t mask[4]; - /** four bitwise shifts */ - int32_t shift[4]; - /** colour representing "transparency" in the bitmap */ - uint32_t transparent_index; -} bmp_image; - -typedef struct ico_image { - bmp_image bmp; - struct ico_image *next; -} ico_image; - -/** - * icon image collection - */ -typedef struct ico_collection { - /** callbacks for bitmap functions */ - bmp_bitmap_callback_vt bitmap_callbacks; - /** width of largest BMP */ - uint16_t width; - /** heigth of largest BMP */ - uint16_t height; - - /* Internal members are listed below */ - /** pointer to ICO data */ - uint8_t *ico_data; - /** total number of bytes of ICO data available */ - uint32_t buffer_size; - /** root of linked list of images */ - ico_image *first; -} ico_collection; - -/** - * Initialises bitmap ready for analysing the bitmap. - * - * \param bmp The Bitmap to initialise - * \param callbacks The callbacks the library will call on operations. - * \return BMP_OK on success or appropriate error code. - */ -bmp_result bmp_create(bmp_image *bmp, bmp_bitmap_callback_vt *callbacks); - -/** - * Initialises icon ready for analysing the icon - * - * \param bmp The Bitmap to initialise - * \param callbacks The callbacks the library will call on operations. - * \return BMP_OK on success or appropriate error code. - */ -bmp_result ico_collection_create(ico_collection *ico, - bmp_bitmap_callback_vt *callbacks); - -/** - * Analyse a BMP prior to decoding. - * - * This will scan the data provided and perform checks to ensure the data is a - * valid BMP and prepare the bitmap image structure ready for decode. - * - * This function must be called and resturn BMP_OK before bmp_decode() as it - * prepares the bmp internal state for the decode process. - * - * \param bmp the BMP image to analyse. - * \param size The size of data in cdata. - * \param data The bitmap source data. - * \return BMP_OK on success or error code on faliure. - */ -bmp_result bmp_analyse(bmp_image *bmp, size_t size, uint8_t *data); - -/** - * Analyse an ICO prior to decoding. - * - * This function will scan the data provided and perform checks to ensure the - * data is a valid ICO. - * - * This function must be called before ico_find(). - * - * \param ico the ICO image to analyse - * \param size The size of data in cdata. - * \param data The bitmap source data. - * \return BMP_OK on success - */ -bmp_result ico_analyse(ico_collection *ico, size_t size, uint8_t *data); - -/** - * Decode a BMP - * - * This function decodes the BMP data such that bmp->bitmap is a valid - * image. The state of bmp->decoded is set to TRUE on exit such that it - * can easily be identified which BMPs are in a fully decoded state. - * - * \param bmp the BMP image to decode - * \return BMP_OK on success - */ -bmp_result bmp_decode(bmp_image *bmp); - -/** - * Decode a BMP using "limited transparency" - * - * Bitmaps do not have native transparency support. However, there is a - * "trick" that is used in some instances in which the first pixel of the - * bitmap becomes the "transparency index". The decoding application can - * replace this index with whatever background colour it chooses to - * create the illusion of transparency. - * - * When to use transparency is at the discretion of the decoding - * application. - * - * \param bmp the BMP image to decode - * \param colour the colour to use as "transparent" - * \return BMP_OK on success - */ -bmp_result bmp_decode_trans(bmp_image *bmp, uint32_t transparent_colour); - -/** - * Finds the closest BMP within an ICO collection - * - * This function finds the BMP with dimensions as close to a specified set - * as possible from the images in the collection. - * - * \param ico the ICO collection to examine - * \param width the preferred width (0 to use ICO header width) - * \param height the preferred height (0 to use ICO header height) - */ -bmp_image *ico_find(ico_collection *ico, uint16_t width, uint16_t height); - -/** - * Finalise a BMP prior to destruction. - * - * \param bmp the BMP image to finalise. - */ -void bmp_finalise(bmp_image *bmp); - -/** - * Finalise an ICO prior to destruction. - * - * \param ico the ICO image to finalise, - */ -void ico_finalise(ico_collection *ico); - -#endif diff --git a/include/pp2d/pp2d.h b/include/pp2d/pp2d.h deleted file mode 100644 index d3e5806..0000000 --- a/include/pp2d/pp2d.h +++ /dev/null @@ -1,493 +0,0 @@ -/* MIT License - * - * Copyright (c) 2017 Bernardo Giordano - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * https://discord.gg/bGKEyfY - */ - -/** - * Plug & Play 2D - * @file pp2d.c - * @author Bernardo Giordano - * @date 17 January 2018 - * @brief pp2d implementation - */ - -#ifndef PP2D_H -#define PP2D_H - -#include "lodepng.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#include <3ds.h> -#include -#include -#include -#include -#include -#include -#include "vshader_shbin.h" - -#define TOP_WIDTH 400 -#define BOTTOM_WIDTH 320 -#define SCREEN_HEIGHT 240 - -/** - * @brief Used to transfer the final rendered display to the framebuffer - */ -#define DISPLAY_TRANSFER_FLAGS \ - (GX_TRANSFER_FLIP_VERT(0) | GX_TRANSFER_OUT_TILED(0) | GX_TRANSFER_RAW_COPY(0) | \ - GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | \ - GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO)) - -/** - * @brief Creates a 8 byte RGBA color - * @param r red component of the color - * @param g green component of the color - * @param b blue component of the color - * @param a alpha component of the color - */ -#define RGBA8(r, g, b, a) ((((r)&0xFF)<<0) | (((g)&0xFF)<<8) | (((b)&0xFF)<<16) | (((a)&0xFF)<<24)) - -/** - * @brief Creates a 8 byte ABGR color - * @param a alpha component of the color - * @param b blue component of the color - * @param g green component of the color - * @param r red component of the color - */ -#define ABGR8(a, b, g, r) ((((a)&0xFF)<<0) | (((b)&0xFF)<<8) | (((g)&0xFF)<<16) | (((r)&0xFF)<<24)) - -/** - * @brief Converts a RGB565 color to RGBA8 color (adds maximum alpha) - * @param rgb 565 to be converted - * @param a alpha - */ -#define RGB565_TO_RGBA8(rgb, a) \ - (RGBA8(((rgb>>11)&0x1F)*0xFF/0x1F, ((rgb>>5)&0x3F)*0xFF/0x3F, (rgb&0x1F)*0xFF/0x1F, a&0xFF)) - -/** - * @brief Converts a RGB565 color to ABGR8 color (adds maximum alpha) - * @param rgb 565 to be converted - * @param a alpha - */ -#define RGB565_TO_ABGR8(rgb, a) \ - (RGBA8(a&0xFF, (rgb&0x1F)*0xFF/0x1F, ((rgb>>5)&0x3F)*0xFF/0x3F, ((rgb>>11)&0x1F)*0xFF/0x1F)) - -#define BACKGROUND_COLOR ABGR8(255, 0, 0, 0) -#define PP2D_NEUTRAL RGBA8(255, 255, 255, 255) - -#define DEFAULT_DEPTH 0.5f - -#define MAX_TEXTURES 1024 - -#define TEXT_VTX_ARRAY_COUNT (4*1024) - -typedef enum { - NONE, - HORIZONTAL, - VERTICAL, - BOTH -} flipType; - -typedef struct { - float position[3]; - float texcoord[2]; -} textVertex_s; - -/** - * @brief Starts a new frame on the specified screen - * @param target GFX_TOP or GFX_BOTTOM - */ -void pp2d_begin_draw(gfxScreen_t target, gfx3dSide_t side); - -/** - * @brief Changes target screen to the specified target - * @param target GFX_TOP or GFX_BOTTOM - */ -void pp2d_draw_on(gfxScreen_t target, gfx3dSide_t side); - -/** - * @brief Draw a rectangle - * @param x of the top left corner - * @param y of the top left corner - * @param width on the rectangle - * @param height of the rectangle - * @param color RGBA8 to fill the rectangle - */ -void pp2d_draw_rectangle(int x, int y, int width, int height, u32 color); - -/** - * @brief Prints a char pointer - * @param x position to start drawing - * @param y position to start drawing - * @param scaleX multiplier for the text width - * @param scaleY multiplier for the text height - * @param color RGBA8 the text will be drawn - * @param text to be printed on the screen - */ -void pp2d_draw_text(float x, float y, float scaleX, float scaleY, u32 color, const char* text); - -/** - * @brief Prints a char pointer in the middle of the target screen - * @param target screen to draw the text to - * @param y position to start drawing - * @param scaleX multiplier for the text width - * @param scaleY multiplier for the text height - * @param color RGBA8 the text will be drawn - * @param text to be printed on the screen - */ -void pp2d_draw_text_center(gfxScreen_t target, float y, float scaleX, float scaleY, u32 color, const char* text); - -/** - * @brief Prints a char pointer in the middle of the target screen - * @param x position to start drawing - * @param y position to start drawing - * @param scaleX multiplier for the text width - * @param scaleY multiplier for the text height - * @param color RGBA8 the text will be drawn - * @param wrapX wrap width - * @param text to be printed on the screen - */ -void pp2d_draw_text_wrap(float x, float y, float scaleX, float scaleY, u32 color, float wrapX, const char* text); - -/** - * @brief Prints a char pointer with arguments - * @param x position to start drawing - * @param y position to start drawing - * @param scaleX multiplier for the text width - * @param scaleY multiplier for the text height - * @param color RGBA8 the text will be drawn - * @param text to be printed on the screen - * @param ... arguments - */ -void pp2d_draw_textf(float x, float y, float scaleX, float scaleY, u32 color, const char* text, ...); - -/** - * @brief Prints a texture - * @param id of the texture - * @param x position on the screen to draw the texture - * @param y position on the screen to draw the texture - */ -void pp2d_draw_texture(size_t id, int x, int y); - -/** - * @brief Prints a texture with color modulation - * @param id of the texture - * @param x position on the screen to draw the texture - * @param y position on the screen to draw the texture - * @param color RGBA8 to modulate the texture with - */ -void pp2d_draw_texture_blend(size_t id, int x, int y, u32 color); - -/** - * @brief Prints a flipped texture - * @param id of the texture - * @param x position on the screen to draw the texture - * @param y position on the screen to draw the texture - * @param fliptype HORIZONTAL, VERTICAL or BOTH - */ - -void pp2d_draw_texture_flip(size_t id, int x, int y, flipType fliptype); - -/** - * @brief Prints a rotated texture - * @param id of the texture - * @param x position on the screen to draw the texture - * @param y position on the screen to draw the texture - * @param angle in degrees to rotate the texture - */ -void pp2d_draw_texture_rotate(size_t id, int x, int y, float angle); - -/** - * @brief Prints a texture with a scale factor - * @param id of the texture - * @param x position on the screen to draw the texture - * @param y position on the screen to draw the texture - * @param scaleX width scale factor - * @param scaleY height scale factor - */ -void pp2d_draw_texture_scale(size_t id, int x, int y, float scaleX, float scaleY); - -/** - * @brief Prints a portion of a texture - * @param id of the texture - * @param x position on the screen to draw the texture - * @param y position on the screen to draw the texture - * @param xbegin position to start drawing - * @param ybegin position to start drawing - * @param width to draw from the xbegin position - * @param height to draw from the ybegin position - */ -void pp2d_draw_texture_part(size_t id, int x, int y, int xbegin, int ybegin, int width, int height); - -/** - * @brief Prints a wchar_t pointer - * @param x position to start drawing - * @param y position to start drawing - * @param scaleX multiplier for the text width - * @param scaleY multiplier for the text height - * @param color RGBA8 the text will be drawn - * @param text to be printed on the screen - */ -void pp2d_draw_wtext(float x, float y, float scaleX, float scaleY, u32 color, const wchar_t* text); - -/** - * @brief Prints a wchar_t pointer in the middle of the target screen - * @param target screen to draw the text to - * @param y position to start drawing - * @param scaleX multiplier for the text width - * @param scaleY multiplier for the text height - * @param color RGBA8 the text will be drawn - * @param text to be printed on the screen - */ -void pp2d_draw_wtext_center(gfxScreen_t target, float y, float scaleX, float scaleY, u32 color, const wchar_t* text); - -/** - * @brief Prints a wchar_t pointer - * @param x position to start drawing - * @param y position to start drawing - * @param scaleX multiplier for the text width - * @param scaleY multiplier for the text height - * @param color RGBA8 the text will be drawn - * @param wrapX wrap width - * @param text to be printed on the screen - */ -void pp2d_draw_wtext_wrap(float x, float y, float scaleX, float scaleY, u32 color, float wrapX, const wchar_t* text); - -/** - * @brief Prints a wchar_t pointer with arguments - * @param x position to start drawing - * @param y position to start drawing - * @param scaleX multiplier for the text width - * @param scaleY multiplier for the text height - * @param color RGBA8 the text will be drawn - * @param text to be printed on the screen - * @param ... arguments - */ -void pp2d_draw_wtextf(float x, float y, float scaleX, float scaleY, u32 color, const wchar_t* text, ...); - -/// Ends a frame -void pp2d_end_draw(void); - -/// Frees the pp2d environment -void pp2d_exit(void); - -/** - * @brief Inits the pp2d environment - * @return 0 if everything went correctly, otherwise returns Result code - * @note This will trigger gfxInitDefault by default - */ -Result pp2d_init(void); - -/** - * @brief Calculates a char pointer height - * @param text char pointer to calculate the height of - * @param scaleX multiplier for the text width - * @param scaleY multiplier for the text height - * @return height the text will have if rendered in the supplied conditions - */ -float pp2d_get_text_height(const char* text, float scaleX, float scaleY); - -/** - * @brief Calculates a char pointer height - * @param text char pointer to calculate the height of - * @param scaleX multiplier for the text width - * @param scaleY multiplier for the text height - * @param wrapX wrap width - * @return height the text will have if rendered in the supplied conditions - */ -float pp2d_get_text_height_wrap(const char* text, float scaleX, float scaleY, int wrapX); - -/** - * @brief Calculates width and height for a char pointer - * @param width pointer to the width to return - * @param height pointer to the height to return - * @param scaleX multiplier for the text width - * @param scaleY multiplier for the text height - * @param text to calculate dimensions of - */ -void pp2d_get_text_size(float* width, float* height, float scaleX, float scaleY, const char* text); - -/** - * @brief Calculates a char pointer width - * @param text char pointer to calculate the width of - * @param scaleX multiplier for the text width - * @param scaleY multiplier for the text height - * @return width the text will have if rendered in the supplied conditions - */ -float pp2d_get_text_width(const char* text, float scaleX, float scaleY); - -/** - * @brief Calculates a wchar_t pointer height - * @param text wchar_t pointer to calculate the height of - * @param scaleX multiplier for the text width - * @param scaleY multiplier for the text height - * @return height the text will have if rendered in the supplied conditions - */ -float pp2d_get_wtext_height(const wchar_t* text, float scaleX, float scaleY); - -/** - * @brief Calculates a wchar_t pointer width - * @param text wchar_t pointer to calculate the width of - * @param scaleX multiplier for the text width - * @param scaleY multiplier for the text height - * @return width the text will have if rendered in the supplied conditions - */ -float pp2d_get_wtext_width(const wchar_t* text, float scaleX, float scaleY); - -/** - * @brief Gets the width of a texture - * @param id of the texture - */ -float pp2d_get_texture_width(size_t id); - -/** - * @brief Gets the height of a texture - * @param id of the texture - */ -float pp2d_get_texture_height(size_t id); - -/** - * @brief Frees a texture - * @param id of the texture to free - */ -void pp2d_free_texture(size_t id); - -/** - * @brief Loads a texture from a a buffer in memory - * @param id of the texture - * @param buf buffer where the texture is stored - * @param width of the texture - * @param height of the texture - */ -void pp2d_load_texture_memory(size_t id, void* buf, u32 size, u32 width, u32 height, GPU_TEXCOLOR format); - -/** - * @brief Loads a texture from a BMP file - * @param id of the texture - * @param path where the BMP file is located - */ -void pp2d_load_texture_bmp(size_t id, const char* path); - -/** - * @brief Loads a texture from a JPEG file - * @param id of the texture - * @param path where the JPEG file is located - */ -void pp2d_load_texture_jpg(size_t id, const char* path); - -/** - * @brief Loads a texture from a PSD, GIF, HDR, PIC and TGA file - * @param id of the texture - * @param path where the image file is located - */ -void pp2d_load_texture_other(size_t id, const char* path); - -/** - * @brief Loads a texture from a png file - * @param id of the texture - * @param path where the png file is located - */ -void pp2d_load_texture_png(size_t id, const char* path); - -/** - * @brief Enables 3D service - * @param enable integer - */ -void pp2d_set_3D(int enable); - -/** - * @brief Sets a background color for the specified screen - * @param target GFX_TOP or GFX_BOTTOM - * @param color ABGR8 which will be the background one - */ -void pp2d_set_screen_color(gfxScreen_t target, u32 color); - -/** - * @brief Sets filters to load texture with - * @param magFilter GPU_NEAREST or GPU_LINEAR - * @param minFilter GPU_NEAREST or GPU_LINEAR - */ -void pp2d_set_texture_filter(GPU_TEXTURE_FILTER_PARAM magFilter, GPU_TEXTURE_FILTER_PARAM minFilter); - -/** - * @brief Inits a texture to be drawn - * @param id of the texture - * @param x to draw the texture at - * @param y to draw the texture at - */ -void pp2d_texture_select(size_t id, int x, int y); - -/** - * @brief Inits a portion of a texture to be drawn - * @param id of the texture - * @param x position on the screen to draw the texture - * @param y position on the screen to draw the texture - * @param xbegin position to start drawing - * @param ybegin position to start drawing - * @param width to draw from the xbegin position - * @param height to draw from the ybegin position - */ -void pp2d_texture_select_part(size_t id, int x, int y, int xbegin, int ybegin, int width, int height); - -/** - * @brief Modulates a texture with a color - * @param color to modulate the texture - */ -void pp2d_texture_blend(u32 color); - -/** - * @brief Scales a texture - * @param scaleX width scale factor - * @param scaleY height scale factor - */ -void pp2d_texture_scale(float scaleX, float scaleY); - -/** - * @brief Flips a texture - * @param fliptype HORIZONTAL, VERTICAL or BOTH - */ -void pp2d_texture_flip(flipType fliptype); - -/** - * @brief Rotates a texture - * @param angle in degrees to rotate the texture - */ -void pp2d_texture_rotate(float angle); - -/** - * @brief Sets the depth of a texture - * @param depth factor of the texture - */ -void pp2d_texture_depth(float depth); - -/// Renders a texture -void pp2d_texture_draw(void); - -#ifdef __cplusplus -} -#endif - -#endif /*PP2D_H*/ diff --git a/include/progress_bar.h b/include/progress_bar.h index 04547c0..5c28245 100644 --- a/include/progress_bar.h +++ b/include/progress_bar.h @@ -1,6 +1,6 @@ -#ifndef PROGRESS_BAR_H -#define PROGRESS_BAR_H +#ifndef _3D_SHELL_PROGRESS_BAR_H +#define _3D_SHELL_PROGRESS_BAR_H -void ProgressBar_DisplayProgress(char * msg, char * src, u32 offset, u32 size); +void ProgressBar_DisplayProgress(char *msg, char *src, u32 offset, u32 size); #endif \ No newline at end of file diff --git a/include/misc/screenshot.h b/include/screenshot.h similarity index 100% rename from include/misc/screenshot.h rename to include/screenshot.h diff --git a/include/status_bar.h b/include/status_bar.h new file mode 100644 index 0000000..ef37eb1 --- /dev/null +++ b/include/status_bar.h @@ -0,0 +1,6 @@ +#ifndef _3D_SHELL_STATUS_BAR_H +#define _3D_SHELL_STATUS_BAR_H + +void StatusBar_DisplayTime(void); + +#endif \ No newline at end of file diff --git a/include/textures.h b/include/textures.h index 4315b91..ecf1a9a 100644 --- a/include/textures.h +++ b/include/textures.h @@ -1,80 +1,21 @@ -#ifndef TEXTURES_H -#define TEXTURES_H - -#define TEXTURE_BACKGROUND 0 -#define TEXTURE_SELECTOR 1 - -#define TEXTURE_ICON_APP 2 -#define TEXTURE_ICON_ARCHIVE 3 -#define TEXTURE_ICON_AUDIO 4 -#define TEXTURE_ICON_FILE 5 -#define TEXTURE_ICON_FOLDER 6 -#define TEXTURE_ICON_IMG 7 -#define TEXTURE_ICON_SYSTEM 8 -#define TEXTURE_ICON_TEXT 9 - -#define TEXTURE_ICON_CHECK 10 -#define TEXTURE_ICON_UNCHECK 11 - -#define TEXTURE_DIALOG 12 -#define TEXTURE_OPTIONS 13 -#define TEXTURE_PROPERTIES 14 - -#define TEXTURE_HOME_ICON 15 -#define TEXTURE_OPTIONS_ICON 16 -#define TEXTURE_SETTINGS_ICON 17 -#define TEXTURE_FTP_ICON 18 -#define TEXTURE_UPDATE_ICON 19 - -#define TEXTURE_HOME_ICON_SELECTED 20 -#define TEXTURE_OPTIONS_ICON_SELECTED 21 -#define TEXTURE_SETTINGS_ICON_SELECTED 22 -#define TEXTURE_FTP_ICON_SELECTED 23 -#define TEXTURE_UPDATE_ICON_SELECTED 24 - -#define TEXTURE_SD_ICON 25 -#define TEXTURE_NAND_ICON 26 - -#define TEXTURE_SD_ICON_SELECTED 27 -#define TEXTURE_NAND_ICON_SELECTED 28 - -#define TEXTURE_TOGGLE_ON 29 -#define TEXTURE_TOGGLE_OFF 30 -#define TEXTURE_RADIO_ON 31 -#define TEXTURE_RADIO_OFF 32 - -#define TEXTURE_THEMES_LAUNCHER 33 - -#define TEXTURE_SEARCH_ICON 34 - -#define TEXTURE_BATTERY_0 35 -#define TEXTURE_BATTERY_15 36 -#define TEXTURE_BATTERY_28 37 -#define TEXTURE_BATTERY_43 38 -#define TEXTURE_BATTERY_57 39 -#define TEXTURE_BATTERY_71 40 -#define TEXTURE_BATTERY_85 41 -#define TEXTURE_BATTERY_100 42 -#define TEXTURE_BATTERY_CHARGE 43 - -#define TEXTURE_WIFI_NULL 44 -#define TEXTURE_WIFI_0 45 -#define TEXTURE_WIFI_1 46 -#define TEXTURE_WIFI_2 47 -#define TEXTURE_WIFI_3 48 - -#define TEXTURE_GALLERY_BAR 49 -#define TEXTURE_GALLERY_IMAGE 50 - -#define TEXTURE_MUSIC_TOP_BG 51 -#define TEXTURE_MUSIC_BOTTOM_BG 52 -#define TEXTURE_MUSIC_PLAY 53 -#define TEXTURE_MUSIC_PAUSE 54 -#define TEXTURE_MUSIC_COVER 55 -#define TEXTURE_MUSIC_STATUS 56 - -#define TEXTURE_TEXTVIEWER_BG 57 - -void Load_Textures(void); +#ifndef _3D_SHELL_TEXTURES_H +#define _3D_SHELL_TEXTURES_H + +#include + +C2D_Image icon_app, icon_archive, icon_audio, icon_dir, icon_file, icon_image, icon_text, icon_dir_dark, \ + icon_doc, icon_check, icon_uncheck, icon_check_dark, icon_uncheck_dark, icon_radio_off, icon_radio_on, \ + icon_radio_dark_off, icon_radio_dark_on, icon_toggle_on, icon_toggle_dark_on, icon_toggle_off, \ + dialog, options_dialog, properties_dialog, dialog_dark, options_dialog_dark, properties_dialog_dark, \ + icon_home, icon_home_dark, icon_home_overlay, icon_options, icon_options_dark, icon_options_overlay, \ + icon_settings, icon_settings_dark, icon_settings_overlay, icon_ftp, icon_ftp_dark, icon_ftp_overlay, \ + icon_sd, icon_sd_dark, icon_sd_overlay, icon_secure, icon_secure_dark, icon_secure_overlay, icon_search, \ + icon_updates, icon_updates_dark, icon_updates_overlay, \ + default_artwork, default_artwork_blur, ic_music_bg_bottom, btn_play, btn_pause, btn_rewind, btn_forward, \ + btn_repeat, btn_shuffle, btn_repeat_overlay, btn_shuffle_overlay, \ + icon_nav_drawer, icon_actions, icon_back; + +void Textures_Load(void); +void Textures_Free(void); #endif \ No newline at end of file diff --git a/include/theme.h b/include/theme.h deleted file mode 100644 index db7da6b..0000000 --- a/include/theme.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef THEME_H -#define THEME_H - -#include <3ds.h> - -char temp_arr[250], theme_dir[250], colour_dir[250]; - -char background_path[250], dialog_path[250], options_path[250], properties_path[250], selector_path[250]; -char app_path[250], archive_path[250], audio_path[250], img_path[250], file_path[250], folder_path[250], system_path[250], text_path[250]; -char check_path[250], uncheck_path[250]; - -char bottomScreen_path[250], bottomScreen_bar_path[250], bottomScreen_text_path[250], options_select_path[250], options_text_path[250], - options_title_text_path[250], settings_colour_path[250], settings_text_path[250], settings_text_min_path[250], settings_title_text_path[250], - storage_path[250], topScreen_path[250], topScreen_bar_path[250], topScreen_min_path[250]; - -struct colour -{ - int r; - int g; - int b; -}; - -Result Theme_SaveConfig(char * themePath, char * coloursPath); -void Theme_Load(void); -void Theme_Reload(void); - -#endif \ No newline at end of file diff --git a/include/touch.h b/include/touch.h new file mode 100644 index 0000000..2892b67 --- /dev/null +++ b/include/touch.h @@ -0,0 +1,11 @@ +#ifndef _3D_SHELL_TOUCH_H +#define _3D_SHELL_TOUCH_H + +#include <3ds.h> + +#define TouchInRect(x1, y1, x2, y2) ((Touch_GetX() >= (x1) && Touch_GetX() <= (x2)) && (Touch_GetY() >= (y1) && Touch_GetY() <= (y2))) + +u16 Touch_GetX(void); +u16 Touch_GetY(void); + +#endif \ No newline at end of file diff --git a/include/utils.h b/include/utils.h index c313cb1..32a0ac3 100644 --- a/include/utils.h +++ b/include/utils.h @@ -1,18 +1,13 @@ -#ifndef UTILS_H -#define UTILS_H +#ifndef _3D_SHELL_UTILS_H +#define _3D_SHELL_UTILS_H -#include <3ds.h> - -void Utils_MakeDirectories(void); -Result Utils_SaveConfig(int sortBy, bool recycleBin, bool galleryDisplay, bool hidden); -Result Utils_LoadConfig(void); -Result Utils_GetLastDirectory(void); -char * Utils_Basename(const char * filename); -void Utils_GetSizeString(char * string, uint64_t size); -CFG_Region Utils_GetRegion(void); -CFG_Language Utils_GetLanguage(void); -const char * Utils_GetUsername(void); bool Utils_IsN3DS(void); -void u16_to_u8(char * buf, const u16 * input, size_t bufsize); +void Utils_U16_To_U8(char *buf, const u16 *input, size_t bufsize); +char *Utils_Basename(const char *filename); +void Utils_GetSizeString(char *string, u64 size); +void Utils_SetMax(int *set, int value, int max); +void Utils_SetMin(int *set, int value, int min); +int Utils_Alphasort(const void *p1, const void *p2); +void Utils_AppendArr(char subject[], const char insert[], int pos); #endif \ No newline at end of file diff --git a/res/app.rsf b/res/app.rsf new file mode 100644 index 0000000..47112b1 --- /dev/null +++ b/res/app.rsf @@ -0,0 +1,195 @@ +BasicInfo: + Title : $(APP_TITLE) + CompanyCode : "00" + ProductCode : $(APP_PRODUCT_CODE) + ContentType : Application + Logo : Homebrew # Nintendo / Licensed / Distributed / iQue / iQueForSystem + +TitleInfo: + UniqueId : $(APP_UNIQUE_ID) + + Category : Application + +CardInfo: + MediaSize : 128MB # 128MB / 256MB / 512MB / 1GB / 2GB / 4GB + MediaType : Card1 # Card1 / Card2 + CardDevice : NorFlash # NorFlash(Pick this if you use savedata) / None + + +Option: + UseOnSD : true # true if App is to be installed to SD + FreeProductCode : true # Removes limitations on ProductCode + MediaFootPadding : false # If true CCI files are created with padding + EnableCrypt : false # Enables encryption for NCCH and CIA + EnableCompress : true # Compresses exefs code + +AccessControlInfo: + #UseExtSaveData : true + #ExtSaveDataId: 0xff3ff + #UseExtendedSaveDataAccessControl: true + #AccessibleSaveDataIds: [0x101, 0x202, 0x303, 0x404, 0x505, 0x606] + +SystemControlInfo: + SaveDataSize: 128KB + RemasterVersion: 7 + StackSize: 0x40000 + +RomFs: + RootPath : $(APP_ROMFS) + +# DO NOT EDIT BELOW HERE OR PROGRAMS WILL NOT LAUNCH (most likely) + +AccessControlInfo: + FileSystemAccess: + - Debug + - DirectSdmc + - DirectSdmcWrite + + IdealProcessor : 0 + AffinityMask : 1 + + Priority : 16 + + MaxCpu : 0x9E # Default + DisableDebug : false + EnableForceDebug : false + CanWriteSharedPage : false + CanUsePrivilegedPriority : false + CanUseNonAlphabetAndNumber : false + PermitMainFunctionArgument : false + CanShareDeviceMemory : false + RunnableOnSleep : false + SpecialMemoryArrange : false + CoreVersion : 2 + DescVersion : 2 + + ReleaseKernelMajor : "02" + ReleaseKernelMinor : "33" + MemoryType : Application + HandleTableSize: 512 + IORegisterMapping: + - 1ff50000-1ff57fff + - 1ff70000-1ff77fff + MemoryMapping: + - 1f000000-1f5fffff:r + SystemCallAccess: + ArbitrateAddress: 34 + Break: 60 + CancelTimer: 28 + ClearEvent: 25 + ClearTimer: 29 + CloseHandle: 35 + ConnectToPort: 45 + ControlMemory: 1 + CreateAddressArbiter: 33 + CreateEvent: 23 + CreateMemoryBlock: 30 + CreateMutex: 19 + CreateSemaphore: 21 + CreateThread: 8 + CreateTimer: 26 + DuplicateHandle: 39 + ExitProcess: 3 + ExitThread: 9 + GetCurrentProcessorNumber: 17 + GetHandleInfo: 41 + GetProcessId: 53 + GetProcessIdOfThread: 54 + GetProcessIdealProcessor: 6 + GetProcessInfo: 43 + GetResourceLimit: 56 + GetResourceLimitCurrentValues: 58 + GetResourceLimitLimitValues: 57 + GetSystemInfo: 42 + GetSystemTick: 40 + GetThreadContext: 59 + GetThreadId: 55 + GetThreadIdealProcessor: 15 + GetThreadInfo: 44 + GetThreadPriority: 11 + MapMemoryBlock: 31 + OutputDebugString: 61 + QueryMemory: 2 + ReleaseMutex: 20 + ReleaseSemaphore: 22 + SendSyncRequest1: 46 + SendSyncRequest2: 47 + SendSyncRequest3: 48 + SendSyncRequest4: 49 + SendSyncRequest: 50 + SetThreadPriority: 12 + SetTimer: 27 + SignalEvent: 24 + SleepThread: 10 + UnmapMemoryBlock: 32 + WaitSynchronization1: 36 + WaitSynchronizationN: 37 + InterruptNumbers: + ServiceAccessControl: + - APT:U + - $hioFIO + - $hostio0 + - $hostio1 + - ac:u + - boss:U + - cam:u + - cecd:u + - cfg:u + - dlp:FKCL + - dlp:SRVR + - dsp::DSP + - frd:u + - fs:USER + - gsp::Gpu + - hid:USER + - http:C + - mic:u + - ndm:u + - news:s + - nwm::UDS + - ptm:u + - pxi:dev + - soc:U + - gsp::Lcd + - y2r:u + - ldr:ro + - ir:USER + - ir:u + - csnd:SND + - am:u + - ns:s + - ptm:sysm + - mcu::HWC + +SystemControlInfo: + Dependency: + ac: 0x0004013000002402L + am: 0x0004013000001502L + boss: 0x0004013000003402L + camera: 0x0004013000001602L + cecd: 0x0004013000002602L + cfg: 0x0004013000001702L + codec: 0x0004013000001802L + csnd: 0x0004013000002702L + dlp: 0x0004013000002802L + dsp: 0x0004013000001a02L + friends: 0x0004013000003202L + gpio: 0x0004013000001b02L + gsp: 0x0004013000001c02L + hid: 0x0004013000001d02L + http: 0x0004013000002902L + i2c: 0x0004013000001e02L + ir: 0x0004013000003302L + mcu: 0x0004013000001f02L + mic: 0x0004013000002002L + ndm: 0x0004013000002b02L + news: 0x0004013000003502L + nim: 0x0004013000002c02L + nwm: 0x0004013000002d02L + pdn: 0x0004013000002102L + ps: 0x0004013000003102L + ptm: 0x0004013000002202L + ro: 0x0004013000003702L + socket: 0x0004013000002e02L + spi: 0x0004013000002302L + ssl: 0x0004013000002f02L diff --git a/resources/banner.png b/res/banner.png similarity index 100% rename from resources/banner.png rename to res/banner.png diff --git a/resources/banner.wav b/res/banner.wav similarity index 100% rename from resources/banner.wav rename to res/banner.wav diff --git a/res/drawable/btn_material_light_check_off_normal.png b/res/drawable/btn_material_light_check_off_normal.png new file mode 100644 index 0000000..a7161a0 Binary files /dev/null and b/res/drawable/btn_material_light_check_off_normal.png differ diff --git a/res/drawable/btn_material_light_check_off_normal_dark.png b/res/drawable/btn_material_light_check_off_normal_dark.png new file mode 100644 index 0000000..aa346fe Binary files /dev/null and b/res/drawable/btn_material_light_check_off_normal_dark.png differ diff --git a/res/drawable/btn_material_light_check_on_normal.png b/res/drawable/btn_material_light_check_on_normal.png new file mode 100644 index 0000000..b44bf84 Binary files /dev/null and b/res/drawable/btn_material_light_check_on_normal.png differ diff --git a/res/drawable/btn_material_light_check_on_normal_dark.png b/res/drawable/btn_material_light_check_on_normal_dark.png new file mode 100644 index 0000000..478b01d Binary files /dev/null and b/res/drawable/btn_material_light_check_on_normal_dark.png differ diff --git a/res/drawable/btn_material_light_radio_off_normal.png b/res/drawable/btn_material_light_radio_off_normal.png new file mode 100644 index 0000000..2bc4cac Binary files /dev/null and b/res/drawable/btn_material_light_radio_off_normal.png differ diff --git a/res/drawable/btn_material_light_radio_off_normal_dark.png b/res/drawable/btn_material_light_radio_off_normal_dark.png new file mode 100644 index 0000000..3a0a28c Binary files /dev/null and b/res/drawable/btn_material_light_radio_off_normal_dark.png differ diff --git a/res/drawable/btn_material_light_radio_on_normal.png b/res/drawable/btn_material_light_radio_on_normal.png new file mode 100644 index 0000000..a2893d5 Binary files /dev/null and b/res/drawable/btn_material_light_radio_on_normal.png differ diff --git a/res/drawable/btn_material_light_radio_on_normal_dark.png b/res/drawable/btn_material_light_radio_on_normal_dark.png new file mode 100644 index 0000000..741ec5d Binary files /dev/null and b/res/drawable/btn_material_light_radio_on_normal_dark.png differ diff --git a/romfs/res/drawable/ic_material_light_update.png b/res/drawable/btn_material_light_toggle_off_normal.png similarity index 89% rename from romfs/res/drawable/ic_material_light_update.png rename to res/drawable/btn_material_light_toggle_off_normal.png index fef83bf..e59e6cf 100644 Binary files a/romfs/res/drawable/ic_material_light_update.png and b/res/drawable/btn_material_light_toggle_off_normal.png differ diff --git a/res/drawable/btn_material_light_toggle_on_normal.png b/res/drawable/btn_material_light_toggle_on_normal.png new file mode 100644 index 0000000..f2f9554 Binary files /dev/null and b/res/drawable/btn_material_light_toggle_on_normal.png differ diff --git a/romfs/res/drawable/ic_overlay_update.png b/res/drawable/btn_material_light_toggle_on_normal_dark.png similarity index 88% rename from romfs/res/drawable/ic_overlay_update.png rename to res/drawable/btn_material_light_toggle_on_normal_dark.png index 9da8c26..7cb1f8d 100644 Binary files a/romfs/res/drawable/ic_overlay_update.png and b/res/drawable/btn_material_light_toggle_on_normal_dark.png differ diff --git a/res/drawable/btn_playback_forward.png b/res/drawable/btn_playback_forward.png new file mode 100644 index 0000000..ccdc365 Binary files /dev/null and b/res/drawable/btn_playback_forward.png differ diff --git a/res/drawable/btn_playback_pause.png b/res/drawable/btn_playback_pause.png new file mode 100644 index 0000000..6309fa8 Binary files /dev/null and b/res/drawable/btn_playback_pause.png differ diff --git a/res/drawable/btn_playback_play.png b/res/drawable/btn_playback_play.png new file mode 100644 index 0000000..a904e0b Binary files /dev/null and b/res/drawable/btn_playback_play.png differ diff --git a/res/drawable/btn_playback_repeat.png b/res/drawable/btn_playback_repeat.png new file mode 100644 index 0000000..dad8f22 Binary files /dev/null and b/res/drawable/btn_playback_repeat.png differ diff --git a/res/drawable/btn_playback_repeat_overlay.png b/res/drawable/btn_playback_repeat_overlay.png new file mode 100644 index 0000000..8caf9de Binary files /dev/null and b/res/drawable/btn_playback_repeat_overlay.png differ diff --git a/res/drawable/btn_playback_rewind.png b/res/drawable/btn_playback_rewind.png new file mode 100644 index 0000000..9aeaf2e Binary files /dev/null and b/res/drawable/btn_playback_rewind.png differ diff --git a/res/drawable/btn_playback_shuffle.png b/res/drawable/btn_playback_shuffle.png new file mode 100644 index 0000000..b0053eb Binary files /dev/null and b/res/drawable/btn_playback_shuffle.png differ diff --git a/res/drawable/btn_playback_shuffle_overlay.png b/res/drawable/btn_playback_shuffle_overlay.png new file mode 100644 index 0000000..73068a5 Binary files /dev/null and b/res/drawable/btn_playback_shuffle_overlay.png differ diff --git a/res/drawable/default_artwork_blur.png b/res/drawable/default_artwork_blur.png new file mode 100644 index 0000000..4f280e6 Binary files /dev/null and b/res/drawable/default_artwork_blur.png differ diff --git a/res/drawable/ic_album_lg.png b/res/drawable/ic_album_lg.png new file mode 100644 index 0000000..dfce572 Binary files /dev/null and b/res/drawable/ic_album_lg.png differ diff --git a/res/drawable/ic_arrow_back_normal.png b/res/drawable/ic_arrow_back_normal.png new file mode 100644 index 0000000..740122d Binary files /dev/null and b/res/drawable/ic_arrow_back_normal.png differ diff --git a/res/drawable/ic_fso_default.png b/res/drawable/ic_fso_default.png new file mode 100644 index 0000000..ccdc580 Binary files /dev/null and b/res/drawable/ic_fso_default.png differ diff --git a/res/drawable/ic_fso_folder.png b/res/drawable/ic_fso_folder.png new file mode 100644 index 0000000..ae7554e Binary files /dev/null and b/res/drawable/ic_fso_folder.png differ diff --git a/res/drawable/ic_fso_folder_dark.png b/res/drawable/ic_fso_folder_dark.png new file mode 100644 index 0000000..b9c6c49 Binary files /dev/null and b/res/drawable/ic_fso_folder_dark.png differ diff --git a/res/drawable/ic_fso_type_audio.png b/res/drawable/ic_fso_type_audio.png new file mode 100644 index 0000000..a9f09c9 Binary files /dev/null and b/res/drawable/ic_fso_type_audio.png differ diff --git a/res/drawable/ic_fso_type_compress.png b/res/drawable/ic_fso_type_compress.png new file mode 100644 index 0000000..547013b Binary files /dev/null and b/res/drawable/ic_fso_type_compress.png differ diff --git a/res/drawable/ic_fso_type_document.png b/res/drawable/ic_fso_type_document.png new file mode 100644 index 0000000..eace17c Binary files /dev/null and b/res/drawable/ic_fso_type_document.png differ diff --git a/res/drawable/ic_fso_type_executable.png b/res/drawable/ic_fso_type_executable.png new file mode 100644 index 0000000..44d61c9 Binary files /dev/null and b/res/drawable/ic_fso_type_executable.png differ diff --git a/res/drawable/ic_fso_type_image.png b/res/drawable/ic_fso_type_image.png new file mode 100644 index 0000000..231f628 Binary files /dev/null and b/res/drawable/ic_fso_type_image.png differ diff --git a/res/drawable/ic_fso_type_text.png b/res/drawable/ic_fso_type_text.png new file mode 100644 index 0000000..afa2d6b Binary files /dev/null and b/res/drawable/ic_fso_type_text.png differ diff --git a/res/drawable/ic_material_dialog.png b/res/drawable/ic_material_dialog.png new file mode 100644 index 0000000..afb9ae3 Binary files /dev/null and b/res/drawable/ic_material_dialog.png differ diff --git a/res/drawable/ic_material_dialog_dark.png b/res/drawable/ic_material_dialog_dark.png new file mode 100644 index 0000000..45c3f20 Binary files /dev/null and b/res/drawable/ic_material_dialog_dark.png differ diff --git a/res/drawable/ic_material_light_contextual_action.png b/res/drawable/ic_material_light_contextual_action.png new file mode 100644 index 0000000..81757d4 Binary files /dev/null and b/res/drawable/ic_material_light_contextual_action.png differ diff --git a/res/drawable/ic_material_light_filesystem.png b/res/drawable/ic_material_light_filesystem.png new file mode 100644 index 0000000..1040449 Binary files /dev/null and b/res/drawable/ic_material_light_filesystem.png differ diff --git a/res/drawable/ic_material_light_filesystem_dark.png b/res/drawable/ic_material_light_filesystem_dark.png new file mode 100644 index 0000000..5c8cded Binary files /dev/null and b/res/drawable/ic_material_light_filesystem_dark.png differ diff --git a/res/drawable/ic_material_light_filesystem_overlay.png b/res/drawable/ic_material_light_filesystem_overlay.png new file mode 100644 index 0000000..acbc0f1 Binary files /dev/null and b/res/drawable/ic_material_light_filesystem_overlay.png differ diff --git a/res/drawable/ic_material_light_home.png b/res/drawable/ic_material_light_home.png new file mode 100644 index 0000000..ff20f1e Binary files /dev/null and b/res/drawable/ic_material_light_home.png differ diff --git a/res/drawable/ic_material_light_home_dark.png b/res/drawable/ic_material_light_home_dark.png new file mode 100644 index 0000000..c8e572a Binary files /dev/null and b/res/drawable/ic_material_light_home_dark.png differ diff --git a/res/drawable/ic_material_light_home_overlay.png b/res/drawable/ic_material_light_home_overlay.png new file mode 100644 index 0000000..6d44947 Binary files /dev/null and b/res/drawable/ic_material_light_home_overlay.png differ diff --git a/res/drawable/ic_material_light_navigation_drawer.png b/res/drawable/ic_material_light_navigation_drawer.png new file mode 100644 index 0000000..3b00c4f Binary files /dev/null and b/res/drawable/ic_material_light_navigation_drawer.png differ diff --git a/res/drawable/ic_material_light_remote.png b/res/drawable/ic_material_light_remote.png new file mode 100644 index 0000000..1cf885e Binary files /dev/null and b/res/drawable/ic_material_light_remote.png differ diff --git a/res/drawable/ic_material_light_remote_dark.png b/res/drawable/ic_material_light_remote_dark.png new file mode 100644 index 0000000..fa71938 Binary files /dev/null and b/res/drawable/ic_material_light_remote_dark.png differ diff --git a/res/drawable/ic_material_light_remote_overlay.png b/res/drawable/ic_material_light_remote_overlay.png new file mode 100644 index 0000000..e89f6b6 Binary files /dev/null and b/res/drawable/ic_material_light_remote_overlay.png differ diff --git a/res/drawable/ic_material_light_sdcard.png b/res/drawable/ic_material_light_sdcard.png new file mode 100644 index 0000000..6e308d8 Binary files /dev/null and b/res/drawable/ic_material_light_sdcard.png differ diff --git a/res/drawable/ic_material_light_sdcard_dark.png b/res/drawable/ic_material_light_sdcard_dark.png new file mode 100644 index 0000000..f15c9da Binary files /dev/null and b/res/drawable/ic_material_light_sdcard_dark.png differ diff --git a/res/drawable/ic_material_light_sdcard_overlay.png b/res/drawable/ic_material_light_sdcard_overlay.png new file mode 100644 index 0000000..c441b89 Binary files /dev/null and b/res/drawable/ic_material_light_sdcard_overlay.png differ diff --git a/romfs/res/drawable/ic_material_light_search.png b/res/drawable/ic_material_light_search.png similarity index 87% rename from romfs/res/drawable/ic_material_light_search.png rename to res/drawable/ic_material_light_search.png index 2cd7cdc..8dad3e2 100644 Binary files a/romfs/res/drawable/ic_material_light_search.png and b/res/drawable/ic_material_light_search.png differ diff --git a/res/drawable/ic_material_light_secure.png b/res/drawable/ic_material_light_secure.png new file mode 100644 index 0000000..c11e3e1 Binary files /dev/null and b/res/drawable/ic_material_light_secure.png differ diff --git a/res/drawable/ic_material_light_secure_dark.png b/res/drawable/ic_material_light_secure_dark.png new file mode 100644 index 0000000..c0a57c3 Binary files /dev/null and b/res/drawable/ic_material_light_secure_dark.png differ diff --git a/res/drawable/ic_material_light_secure_overlay.png b/res/drawable/ic_material_light_secure_overlay.png new file mode 100644 index 0000000..6c949e8 Binary files /dev/null and b/res/drawable/ic_material_light_secure_overlay.png differ diff --git a/res/drawable/ic_material_light_settings.png b/res/drawable/ic_material_light_settings.png new file mode 100644 index 0000000..14b7348 Binary files /dev/null and b/res/drawable/ic_material_light_settings.png differ diff --git a/res/drawable/ic_material_light_settings_dark.png b/res/drawable/ic_material_light_settings_dark.png new file mode 100644 index 0000000..e39dfea Binary files /dev/null and b/res/drawable/ic_material_light_settings_dark.png differ diff --git a/res/drawable/ic_material_light_settings_overlay.png b/res/drawable/ic_material_light_settings_overlay.png new file mode 100644 index 0000000..d71b1f9 Binary files /dev/null and b/res/drawable/ic_material_light_settings_overlay.png differ diff --git a/res/drawable/ic_material_light_tab.png b/res/drawable/ic_material_light_tab.png new file mode 100644 index 0000000..9eed359 Binary files /dev/null and b/res/drawable/ic_material_light_tab.png differ diff --git a/res/drawable/ic_material_light_tab_dark.png b/res/drawable/ic_material_light_tab_dark.png new file mode 100644 index 0000000..45336f8 Binary files /dev/null and b/res/drawable/ic_material_light_tab_dark.png differ diff --git a/res/drawable/ic_material_light_tab_overlay.png b/res/drawable/ic_material_light_tab_overlay.png new file mode 100644 index 0000000..969f532 Binary files /dev/null and b/res/drawable/ic_material_light_tab_overlay.png differ diff --git a/res/drawable/ic_material_options_dialog.png b/res/drawable/ic_material_options_dialog.png new file mode 100644 index 0000000..7d77d09 Binary files /dev/null and b/res/drawable/ic_material_options_dialog.png differ diff --git a/res/drawable/ic_material_options_dialog_dark.png b/res/drawable/ic_material_options_dialog_dark.png new file mode 100644 index 0000000..bd8c2bd Binary files /dev/null and b/res/drawable/ic_material_options_dialog_dark.png differ diff --git a/res/drawable/ic_material_properties_dialog.png b/res/drawable/ic_material_properties_dialog.png new file mode 100644 index 0000000..65c8dc5 Binary files /dev/null and b/res/drawable/ic_material_properties_dialog.png differ diff --git a/res/drawable/ic_material_properties_dialog_dark.png b/res/drawable/ic_material_properties_dialog_dark.png new file mode 100644 index 0000000..3a35418 Binary files /dev/null and b/res/drawable/ic_material_properties_dialog_dark.png differ diff --git a/res/drawable/ic_music_bg_bottom.png b/res/drawable/ic_music_bg_bottom.png new file mode 100644 index 0000000..8da7894 Binary files /dev/null and b/res/drawable/ic_music_bg_bottom.png differ diff --git a/res/drawable/sprites.t3s b/res/drawable/sprites.t3s new file mode 100644 index 0000000..7b97727 --- /dev/null +++ b/res/drawable/sprites.t3s @@ -0,0 +1,63 @@ +--atlas -f rgba -z auto +btn_material_light_check_off_normal_dark.png +btn_material_light_check_off_normal.png +btn_material_light_check_on_normal_dark.png +btn_material_light_check_on_normal.png +btn_material_light_radio_off_normal_dark.png +btn_material_light_radio_off_normal.png +btn_material_light_radio_on_normal_dark.png +btn_material_light_radio_on_normal.png +btn_material_light_toggle_off_normal.png +btn_material_light_toggle_on_normal_dark.png +btn_material_light_toggle_on_normal.png +ic_material_light_filesystem.png +ic_material_light_filesystem_dark.png +ic_material_light_filesystem_overlay.png +ic_material_light_home.png +ic_material_light_home_dark.png +ic_material_light_home_overlay.png +ic_material_light_remote.png +ic_material_light_remote_dark.png +ic_material_light_remote_overlay.png +ic_material_light_sdcard.png +ic_material_light_sdcard_dark.png +ic_material_light_sdcard_overlay.png +ic_material_light_search.png +ic_material_light_secure.png +ic_material_light_secure_dark.png +ic_material_light_secure_overlay.png +ic_material_light_settings.png +ic_material_light_settings_dark.png +ic_material_light_settings_overlay.png +ic_material_light_tab.png +ic_material_light_tab_dark.png +ic_material_light_tab_overlay.png +default_artwork_blur.png +ic_album_lg.png +ic_music_bg_bottom.png +btn_playback_forward.png +btn_playback_pause.png +btn_playback_play.png +btn_playback_repeat_overlay.png +btn_playback_repeat.png +btn_playback_rewind.png +btn_playback_shuffle_overlay.png +btn_playback_shuffle.png +ic_arrow_back_normal.png +ic_fso_default.png +ic_fso_folder_dark.png +ic_fso_folder.png +ic_fso_type_audio.png +ic_fso_type_compress.png +ic_fso_type_document.png +ic_fso_type_executable.png +ic_fso_type_image.png +ic_fso_type_text.png +ic_material_dialog_dark.png +ic_material_dialog.png +ic_material_light_contextual_action.png +ic_material_light_navigation_drawer.png +ic_material_options_dialog_dark.png +ic_material_options_dialog.png +ic_material_properties_dialog_dark.png +ic_material_properties_dialog.png \ No newline at end of file diff --git a/resources/ic_launcher_filemanager.png b/res/ic_launcher_filemanager.png similarity index 100% rename from resources/ic_launcher_filemanager.png rename to res/ic_launcher_filemanager.png diff --git a/resources/logo.lz11 b/res/logo.lz11 similarity index 100% rename from resources/logo.lz11 rename to res/logo.lz11 diff --git a/resources/.build.sh b/resources/.build.sh deleted file mode 100644 index 75f407e..0000000 --- a/resources/.build.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh -set -e -set -x - -make clean && make -mv out/3DShell.cia . -mv out/3DShell.3dsx . -rm .gitignore .gitmodules .travis.yml LICENSE Makefile README.md -rm -rf build include out romfs resources source \ No newline at end of file diff --git a/resources/.travis-deps.sh b/resources/.travis-deps.sh deleted file mode 100644 index 0b61659..0000000 --- a/resources/.travis-deps.sh +++ /dev/null @@ -1,76 +0,0 @@ -#!/bin/sh -set -e -set -x - -# Build and install devkitARM + ctrulib -mkdir -p $DEVKITPRO -cd $DEVKITPRO -wget -N https://raw.githubusercontent.com/devkitPro/installer/master/perl/devkitARMupdate.pl -chmod +x ./devkitARMupdate.pl -./devkitARMupdate.pl - -# Get latest ctrulib and overwrite bundled one -git clone https://github.com/smealum/ctrulib.git -cd ctrulib/libctru -make && make install -cd ../../ -rm -rf ctrulib - -# Get latest version of Citro3D -git clone --recursive https://github.com/fincs/citro3d.git -cd citro3d -make && make install -cd ../ -rm -rf citro3d - -# Install latest version of picasso -git clone https://github.com/fincs/picasso.git -cd picasso -./autogen.sh -./configure -make -cp picasso ${DEVKITPRO}/devkitARM/bin/picasso -cd ../ -rm -rf picasso - -export CC=arm-none-eabi-gcc -export CXX=arm-none-eabi-g++ - -# Build and install bannertool -git clone --recursive https://github.com/Steveice10/bannertool -cd bannertool/ -make -cp output/linux-x86_64/bannertool ${DEVKITPRO}/devkitARM/bin/bannertool -cd ../ -rm -rf bannertool/ - -# Build and install makerom -git clone https://github.com/profi200/Project_CTR.git -cd Project_CTR/makerom -make -cp makerom ${DEVKITPRO}/devkitARM/bin/makerom -cd ../.. -rm -rf Project_CTR - -# Build and install portlibs using pacman -mkdir ${DEVKITPRO}/portlibs && mkdir ${PORTLIBS}/ -wget https://github.com/devkitPro/pacman/releases/download/v1.0.0/devkitpro-pacman.deb -sudo dpkg -i devkitpro-pacman.deb - -# Remove mbedtls if it's included - causes issues. -sudo rm -rf ${DEVKITPRO}/portlibs/3ds/include/mbedtls/ -sudo rm ${DEVKITPRO}/portlibs/3ds/lib/libmbedcrypto.a -sudo rm ${DEVKITPRO}/portlibs/3ds/lib/libmbedtls.a -sudo rm ${DEVKITPRO}/portlibs/3ds/lib/libmbedx509.a - -# Install required libs -sudo dkp-pacman -S 3ds-zlib --noconfirm -sudo dkp-pacman -S 3ds-curl --noconfirm -sudo dkp-pacman -S 3ds-mpg123 --noconfirm -sudo dkp-pacman -S 3ds-libogg --noconfirm -sudo dkp-pacman -S 3ds-libvorbisidec --noconfirm - -# Remove unnecessary files -rm *.bz2 -rm devkitARMupdate.pl -rm devkitpro-pacman.deb \ No newline at end of file diff --git a/resources/cia.rsf b/resources/cia.rsf deleted file mode 100644 index 24a764f..0000000 --- a/resources/cia.rsf +++ /dev/null @@ -1,286 +0,0 @@ -BasicInfo: - Title : $(APP_TITLE) - ProductCode : $(APP_PRODUCT_CODE) - Logo : Homebrew - -RomFs: - RootPath: $(APP_ROMFS) - -TitleInfo: - Category : $(APP_CATEGORY) - UniqueId : $(APP_UNIQUE_ID) - -Option: - UseOnSD : $(APP_USE_ON_SD) # true if App is to be installed to SD - FreeProductCode : true # Removes limitations on ProductCode - MediaFootPadding : false # If true CCI files are created with padding - EnableCrypt : $(APP_ENCRYPTED) # Enables encryption for NCCH and CIA - EnableCompress : true # Compresses where applicable (currently only exefs:/.code) - -AccessControlInfo: - CoreVersion : 2 - - # Exheader Format Version - DescVersion : 2 - - # Minimum Required Kernel Version (below is for 4.5.0) - ReleaseKernelMajor : "02" - ReleaseKernelMinor : "33" - - # ExtData - UseExtSaveData : false # enables ExtData - #ExtSaveDataId : 0x300 # only set this when the ID is different to the UniqueId - - # FS:USER Archive Access Permissions - # Uncomment as required - FileSystemAccess: - - CategorySystemApplication - - CategoryHardwareCheck - - CategoryFileSystemTool - - Debug - - TwlCardBackup - - TwlNandData - - Boss - - DirectSdmc - - Core - - CtrNandRo - - CtrNandRw - - CtrNandRoWrite - - CategorySystemSettings - - CardBoard - - ExportImportIvs - - DirectSdmcWrite - - SwitchCleanup - - SaveDataMove - - Shop - - Shell - - CategoryHomeMenu - - SeedDB - IoAccessControl: - - FsMountNand - - FsMountNandRoWrite - - FsMountTwln - - FsMountWnand - - FsMountCardSpi - - UseSdif3 - - CreateSeed - - UseCardSpi - - # Process Settings - MemoryType : $(APP_MEMORY_TYPE) # Application/System/Base - SystemMode : $(APP_SYSTEM_MODE) # 64MB(Default)/96MB/80MB/72MB/32MB - IdealProcessor : 0 - AffinityMask : 1 - Priority : 16 - MaxCpu : 0x9E # Default - HandleTableSize : 0x200 - DisableDebug : false - EnableForceDebug : false - CanWriteSharedPage : true - CanUsePrivilegedPriority : false - CanUseNonAlphabetAndNumber : true - PermitMainFunctionArgument : true - CanShareDeviceMemory : true - RunnableOnSleep : false - SpecialMemoryArrange : true - - # New3DS Exclusive Process Settings - SystemModeExt : $(APP_SYSTEM_MODE_EXT) # Legacy(Default)/124MB/178MB Legacy:Use Old3DS SystemMode - CpuSpeed : $(APP_CPU_SPEED) # 268MHz(Default)/804MHz - EnableL2Cache : $(APP_ENABLE_L2_CACHE) # false(default)/true - CanAccessCore2 : true - - # Virtual Address Mappings - IORegisterMapping: - - 1ff00000-1ff7ffff # DSP memory - MemoryMapping: - - 1f000000-1f5fffff:r # VRAM - - # Accessible SVCs, : - SystemCallAccess: - ControlMemory: 1 - QueryMemory: 2 - ExitProcess: 3 - GetProcessAffinityMask: 4 - SetProcessAffinityMask: 5 - GetProcessIdealProcessor: 6 - SetProcessIdealProcessor: 7 - CreateThread: 8 - ExitThread: 9 - SleepThread: 10 - GetThreadPriority: 11 - SetThreadPriority: 12 - GetThreadAffinityMask: 13 - SetThreadAffinityMask: 14 - GetThreadIdealProcessor: 15 - SetThreadIdealProcessor: 16 - GetCurrentProcessorNumber: 17 - Run: 18 - CreateMutex: 19 - ReleaseMutex: 20 - CreateSemaphore: 21 - ReleaseSemaphore: 22 - CreateEvent: 23 - SignalEvent: 24 - ClearEvent: 25 - CreateTimer: 26 - SetTimer: 27 - CancelTimer: 28 - ClearTimer: 29 - CreateMemoryBlock: 30 - MapMemoryBlock: 31 - UnmapMemoryBlock: 32 - CreateAddressArbiter: 33 - ArbitrateAddress: 34 - CloseHandle: 35 - WaitSynchronization1: 36 - WaitSynchronizationN: 37 - SignalAndWait: 38 - DuplicateHandle: 39 - GetSystemTick: 40 - GetHandleInfo: 41 - GetSystemInfo: 42 - GetProcessInfo: 43 - GetThreadInfo: 44 - ConnectToPort: 45 - SendSyncRequest1: 46 - SendSyncRequest2: 47 - SendSyncRequest3: 48 - SendSyncRequest4: 49 - SendSyncRequest: 50 - OpenProcess: 51 - OpenThread: 52 - GetProcessId: 53 - GetProcessIdOfThread: 54 - GetThreadId: 55 - GetResourceLimit: 56 - GetResourceLimitLimitValues: 57 - GetResourceLimitCurrentValues: 58 - GetThreadContext: 59 - Break: 60 - OutputDebugString: 61 - ControlPerformanceCounter: 62 - CreatePort: 71 - CreateSessionToPort: 72 - CreateSession: 73 - AcceptSession: 74 - ReplyAndReceive1: 75 - ReplyAndReceive2: 76 - ReplyAndReceive3: 77 - ReplyAndReceive4: 78 - ReplyAndReceive: 79 - BindInterrupt: 80 - UnbindInterrupt: 81 - InvalidateProcessDataCache: 82 - StoreProcessDataCache: 83 - FlushProcessDataCache: 84 - StartInterProcessDma: 85 - StopDma: 86 - GetDmaState: 87 - RestartDma: 88 - DebugActiveProcess: 96 - BreakDebugProcess: 97 - TerminateDebugProcess: 98 - GetProcessDebugEvent: 99 - ContinueDebugEvent: 100 - GetProcessList: 101 - GetThreadList: 102 - GetDebugThreadContext: 103 - SetDebugThreadContext: 104 - QueryDebugProcessMemory: 105 - ReadProcessMemory: 106 - WriteProcessMemory: 107 - SetHardwareBreakPoint: 108 - GetDebugThreadParam: 109 - ControlProcessMemory: 112 - MapProcessMemory: 113 - UnmapProcessMemory: 114 - CreateCodeSet: 115 - CreateProcess: 117 - TerminateProcess: 118 - SetProcessResourceLimits: 119 - CreateResourceLimit: 120 - SetResourceLimitValues: 121 - AddCodeSegment: 122 - Backdoor: 123 - KernelSetState: 124 - QueryProcessMemory: 125 - - # Service List - # Maximum 34 services (32 if firmware is prior to 9.6.0) - ServiceAccessControl: - - APT:U - - ac:u - - am:net - - boss:U - - cam:u - - cecd:u - - cfg:nor - - cfg:u - - csnd:SND - - dsp::DSP - - frd:u - - fs:USER - - gsp::Gpu - - gsp::Lcd - - hid:USER - - http:C - - ir:rst - - ir:u - - ir:USER - - mic:u - - mcu::HWC - - ndm:u - - news:s - - nwm::EXT - - nwm::UDS - - ptm:sysm - - ptm:u - - pxi:dev - - soc:U - - ssl:C - - y2r:u - - -SystemControlInfo: - SaveDataSize: 0KB # Change if the app uses savedata - RemasterVersion: $(APP_VERSION_MAJOR) - StackSize: 0x40000 - - # Modules that run services listed above should be included below - # Maximum 48 dependencies - # : - Dependency: - ac: 0x0004013000002402 - #act: 0x0004013000003802 - am: 0x0004013000001502 - boss: 0x0004013000003402 - camera: 0x0004013000001602 - cecd: 0x0004013000002602 - cfg: 0x0004013000001702 - codec: 0x0004013000001802 - csnd: 0x0004013000002702 - dlp: 0x0004013000002802 - dsp: 0x0004013000001a02 - friends: 0x0004013000003202 - gpio: 0x0004013000001b02 - gsp: 0x0004013000001c02 - hid: 0x0004013000001d02 - http: 0x0004013000002902 - i2c: 0x0004013000001e02 - ir: 0x0004013000003302 - mcu: 0x0004013000001f02 - mic: 0x0004013000002002 - ndm: 0x0004013000002b02 - news: 0x0004013000003502 - #nfc: 0x0004013000004002 - nim: 0x0004013000002c02 - nwm: 0x0004013000002d02 - pdn: 0x0004013000002102 - ps: 0x0004013000003102 - ptm: 0x0004013000002202 - #qtm: 0x0004013020004202 - ro: 0x0004013000003702 - socket: 0x0004013000002e02 - spi: 0x0004013000002302 - ssl: 0x0004013000002f02 \ No newline at end of file diff --git a/romfs/res/drawable/battery/0.png b/romfs/res/drawable/battery/0.png deleted file mode 100644 index d9ac8fe..0000000 Binary files a/romfs/res/drawable/battery/0.png and /dev/null differ diff --git a/romfs/res/drawable/battery/100.png b/romfs/res/drawable/battery/100.png deleted file mode 100644 index 3b69de1..0000000 Binary files a/romfs/res/drawable/battery/100.png and /dev/null differ diff --git a/romfs/res/drawable/battery/15.png b/romfs/res/drawable/battery/15.png deleted file mode 100644 index da4ba88..0000000 Binary files a/romfs/res/drawable/battery/15.png and /dev/null differ diff --git a/romfs/res/drawable/battery/28.png b/romfs/res/drawable/battery/28.png deleted file mode 100644 index 70bf5c1..0000000 Binary files a/romfs/res/drawable/battery/28.png and /dev/null differ diff --git a/romfs/res/drawable/battery/43.png b/romfs/res/drawable/battery/43.png deleted file mode 100644 index d72ec85..0000000 Binary files a/romfs/res/drawable/battery/43.png and /dev/null differ diff --git a/romfs/res/drawable/battery/57.png b/romfs/res/drawable/battery/57.png deleted file mode 100644 index 7aad741..0000000 Binary files a/romfs/res/drawable/battery/57.png and /dev/null differ diff --git a/romfs/res/drawable/battery/71.png b/romfs/res/drawable/battery/71.png deleted file mode 100644 index 8313cb0..0000000 Binary files a/romfs/res/drawable/battery/71.png and /dev/null differ diff --git a/romfs/res/drawable/battery/85.png b/romfs/res/drawable/battery/85.png deleted file mode 100644 index 9000c76..0000000 Binary files a/romfs/res/drawable/battery/85.png and /dev/null differ diff --git a/romfs/res/drawable/battery/charge.png b/romfs/res/drawable/battery/charge.png deleted file mode 100644 index c66b381..0000000 Binary files a/romfs/res/drawable/battery/charge.png and /dev/null differ diff --git a/romfs/res/drawable/btn_material_check_off.png b/romfs/res/drawable/btn_material_check_off.png deleted file mode 100644 index 9c456dc..0000000 Binary files a/romfs/res/drawable/btn_material_check_off.png and /dev/null differ diff --git a/romfs/res/drawable/btn_material_check_on.png b/romfs/res/drawable/btn_material_check_on.png deleted file mode 100644 index 7e839cc..0000000 Binary files a/romfs/res/drawable/btn_material_check_on.png and /dev/null differ diff --git a/romfs/res/drawable/btn_material_radio_off.png b/romfs/res/drawable/btn_material_radio_off.png deleted file mode 100644 index 280dc20..0000000 Binary files a/romfs/res/drawable/btn_material_radio_off.png and /dev/null differ diff --git a/romfs/res/drawable/btn_material_radio_on.png b/romfs/res/drawable/btn_material_radio_on.png deleted file mode 100644 index b078cda..0000000 Binary files a/romfs/res/drawable/btn_material_radio_on.png and /dev/null differ diff --git a/romfs/res/drawable/btn_material_toggle_off.png b/romfs/res/drawable/btn_material_toggle_off.png deleted file mode 100644 index ceb7963..0000000 Binary files a/romfs/res/drawable/btn_material_toggle_off.png and /dev/null differ diff --git a/romfs/res/drawable/btn_material_toggle_on.png b/romfs/res/drawable/btn_material_toggle_on.png deleted file mode 100644 index 09b1976..0000000 Binary files a/romfs/res/drawable/btn_material_toggle_on.png and /dev/null differ diff --git a/romfs/res/drawable/gallery/ic_gallery_bar.png b/romfs/res/drawable/gallery/ic_gallery_bar.png deleted file mode 100644 index f75f86a..0000000 Binary files a/romfs/res/drawable/gallery/ic_gallery_bar.png and /dev/null differ diff --git a/romfs/res/drawable/ic_background.png b/romfs/res/drawable/ic_background.png deleted file mode 100644 index 90abac2..0000000 Binary files a/romfs/res/drawable/ic_background.png and /dev/null differ diff --git a/romfs/res/drawable/ic_dialog.png b/romfs/res/drawable/ic_dialog.png deleted file mode 100644 index 6401cff..0000000 Binary files a/romfs/res/drawable/ic_dialog.png and /dev/null differ diff --git a/romfs/res/drawable/ic_fso_type_app.png b/romfs/res/drawable/ic_fso_type_app.png deleted file mode 100644 index 3b98863..0000000 Binary files a/romfs/res/drawable/ic_fso_type_app.png and /dev/null differ diff --git a/romfs/res/drawable/ic_fso_type_archive.png b/romfs/res/drawable/ic_fso_type_archive.png deleted file mode 100644 index 489162c..0000000 Binary files a/romfs/res/drawable/ic_fso_type_archive.png and /dev/null differ diff --git a/romfs/res/drawable/ic_fso_type_audio.png b/romfs/res/drawable/ic_fso_type_audio.png deleted file mode 100644 index 17da186..0000000 Binary files a/romfs/res/drawable/ic_fso_type_audio.png and /dev/null differ diff --git a/romfs/res/drawable/ic_fso_type_file.png b/romfs/res/drawable/ic_fso_type_file.png deleted file mode 100644 index 2d52878..0000000 Binary files a/romfs/res/drawable/ic_fso_type_file.png and /dev/null differ diff --git a/romfs/res/drawable/ic_fso_type_folder.png b/romfs/res/drawable/ic_fso_type_folder.png deleted file mode 100644 index b61da27..0000000 Binary files a/romfs/res/drawable/ic_fso_type_folder.png and /dev/null differ diff --git a/romfs/res/drawable/ic_fso_type_img.png b/romfs/res/drawable/ic_fso_type_img.png deleted file mode 100644 index d4ee283..0000000 Binary files a/romfs/res/drawable/ic_fso_type_img.png and /dev/null differ diff --git a/romfs/res/drawable/ic_fso_type_system.png b/romfs/res/drawable/ic_fso_type_system.png deleted file mode 100644 index 4dbe7c3..0000000 Binary files a/romfs/res/drawable/ic_fso_type_system.png and /dev/null differ diff --git a/romfs/res/drawable/ic_fso_type_text.png b/romfs/res/drawable/ic_fso_type_text.png deleted file mode 100644 index f582731..0000000 Binary files a/romfs/res/drawable/ic_fso_type_text.png and /dev/null differ diff --git a/romfs/res/drawable/ic_launcher_themes.png b/romfs/res/drawable/ic_launcher_themes.png deleted file mode 100644 index e622520..0000000 Binary files a/romfs/res/drawable/ic_launcher_themes.png and /dev/null differ diff --git a/romfs/res/drawable/ic_material_light_ftp.png b/romfs/res/drawable/ic_material_light_ftp.png deleted file mode 100644 index ba04379..0000000 Binary files a/romfs/res/drawable/ic_material_light_ftp.png and /dev/null differ diff --git a/romfs/res/drawable/ic_material_light_home.png b/romfs/res/drawable/ic_material_light_home.png deleted file mode 100644 index 71cbfa9..0000000 Binary files a/romfs/res/drawable/ic_material_light_home.png and /dev/null differ diff --git a/romfs/res/drawable/ic_material_light_nand.png b/romfs/res/drawable/ic_material_light_nand.png deleted file mode 100644 index ab25ab8..0000000 Binary files a/romfs/res/drawable/ic_material_light_nand.png and /dev/null differ diff --git a/romfs/res/drawable/ic_material_light_options.png b/romfs/res/drawable/ic_material_light_options.png deleted file mode 100644 index 0fee767..0000000 Binary files a/romfs/res/drawable/ic_material_light_options.png and /dev/null differ diff --git a/romfs/res/drawable/ic_material_light_sd.png b/romfs/res/drawable/ic_material_light_sd.png deleted file mode 100644 index 935ec6b..0000000 Binary files a/romfs/res/drawable/ic_material_light_sd.png and /dev/null differ diff --git a/romfs/res/drawable/ic_material_light_settings.png b/romfs/res/drawable/ic_material_light_settings.png deleted file mode 100644 index 0103127..0000000 Binary files a/romfs/res/drawable/ic_material_light_settings.png and /dev/null differ diff --git a/romfs/res/drawable/ic_options.png b/romfs/res/drawable/ic_options.png deleted file mode 100644 index c7b75de..0000000 Binary files a/romfs/res/drawable/ic_options.png and /dev/null differ diff --git a/romfs/res/drawable/ic_overlay_ftp.png b/romfs/res/drawable/ic_overlay_ftp.png deleted file mode 100644 index 1aa7560..0000000 Binary files a/romfs/res/drawable/ic_overlay_ftp.png and /dev/null differ diff --git a/romfs/res/drawable/ic_overlay_home.png b/romfs/res/drawable/ic_overlay_home.png deleted file mode 100644 index 898c82f..0000000 Binary files a/romfs/res/drawable/ic_overlay_home.png and /dev/null differ diff --git a/romfs/res/drawable/ic_overlay_nand.png b/romfs/res/drawable/ic_overlay_nand.png deleted file mode 100644 index 25bb1f2..0000000 Binary files a/romfs/res/drawable/ic_overlay_nand.png and /dev/null differ diff --git a/romfs/res/drawable/ic_overlay_options.png b/romfs/res/drawable/ic_overlay_options.png deleted file mode 100644 index 318660c..0000000 Binary files a/romfs/res/drawable/ic_overlay_options.png and /dev/null differ diff --git a/romfs/res/drawable/ic_overlay_sd.png b/romfs/res/drawable/ic_overlay_sd.png deleted file mode 100644 index f70a39b..0000000 Binary files a/romfs/res/drawable/ic_overlay_sd.png and /dev/null differ diff --git a/romfs/res/drawable/ic_overlay_settings.png b/romfs/res/drawable/ic_overlay_settings.png deleted file mode 100644 index 4e63ab5..0000000 Binary files a/romfs/res/drawable/ic_overlay_settings.png and /dev/null differ diff --git a/romfs/res/drawable/ic_properties.png b/romfs/res/drawable/ic_properties.png deleted file mode 100644 index 4c89dc6..0000000 Binary files a/romfs/res/drawable/ic_properties.png and /dev/null differ diff --git a/romfs/res/drawable/ic_selector.png b/romfs/res/drawable/ic_selector.png deleted file mode 100644 index 7abea70..0000000 Binary files a/romfs/res/drawable/ic_selector.png and /dev/null differ diff --git a/romfs/res/drawable/music/ic_music_bg_bottom.png b/romfs/res/drawable/music/ic_music_bg_bottom.png deleted file mode 100644 index ca2d3dc..0000000 Binary files a/romfs/res/drawable/music/ic_music_bg_bottom.png and /dev/null differ diff --git a/romfs/res/drawable/music/ic_music_bg_top.png b/romfs/res/drawable/music/ic_music_bg_top.png deleted file mode 100644 index bccc299..0000000 Binary files a/romfs/res/drawable/music/ic_music_bg_top.png and /dev/null differ diff --git a/romfs/res/drawable/music/ic_music_forward.png b/romfs/res/drawable/music/ic_music_forward.png deleted file mode 100644 index 1901df6..0000000 Binary files a/romfs/res/drawable/music/ic_music_forward.png and /dev/null differ diff --git a/romfs/res/drawable/music/ic_music_pause.png b/romfs/res/drawable/music/ic_music_pause.png deleted file mode 100644 index 0859f87..0000000 Binary files a/romfs/res/drawable/music/ic_music_pause.png and /dev/null differ diff --git a/romfs/res/drawable/music/ic_music_play.png b/romfs/res/drawable/music/ic_music_play.png deleted file mode 100644 index 958847e..0000000 Binary files a/romfs/res/drawable/music/ic_music_play.png and /dev/null differ diff --git a/romfs/res/drawable/music/ic_music_repeat.png b/romfs/res/drawable/music/ic_music_repeat.png deleted file mode 100644 index 98814ee..0000000 Binary files a/romfs/res/drawable/music/ic_music_repeat.png and /dev/null differ diff --git a/romfs/res/drawable/music/ic_music_rewind.png b/romfs/res/drawable/music/ic_music_rewind.png deleted file mode 100644 index f44d839..0000000 Binary files a/romfs/res/drawable/music/ic_music_rewind.png and /dev/null differ diff --git a/romfs/res/drawable/music/ic_music_shuffle.png b/romfs/res/drawable/music/ic_music_shuffle.png deleted file mode 100644 index ad041c7..0000000 Binary files a/romfs/res/drawable/music/ic_music_shuffle.png and /dev/null differ diff --git a/romfs/res/drawable/music/ic_music_status.png b/romfs/res/drawable/music/ic_music_status.png deleted file mode 100644 index eee3526..0000000 Binary files a/romfs/res/drawable/music/ic_music_status.png and /dev/null differ diff --git a/romfs/res/drawable/textviewer/textview.png b/romfs/res/drawable/textviewer/textview.png deleted file mode 100644 index 0c36b69..0000000 Binary files a/romfs/res/drawable/textviewer/textview.png and /dev/null differ diff --git a/romfs/res/drawable/wifi/stat_sys_wifi_signal_0.png b/romfs/res/drawable/wifi/stat_sys_wifi_signal_0.png deleted file mode 100644 index eccc570..0000000 Binary files a/romfs/res/drawable/wifi/stat_sys_wifi_signal_0.png and /dev/null differ diff --git a/romfs/res/drawable/wifi/stat_sys_wifi_signal_1.png b/romfs/res/drawable/wifi/stat_sys_wifi_signal_1.png deleted file mode 100644 index 049a388..0000000 Binary files a/romfs/res/drawable/wifi/stat_sys_wifi_signal_1.png and /dev/null differ diff --git a/romfs/res/drawable/wifi/stat_sys_wifi_signal_2.png b/romfs/res/drawable/wifi/stat_sys_wifi_signal_2.png deleted file mode 100644 index eacaf83..0000000 Binary files a/romfs/res/drawable/wifi/stat_sys_wifi_signal_2.png and /dev/null differ diff --git a/romfs/res/drawable/wifi/stat_sys_wifi_signal_3.png b/romfs/res/drawable/wifi/stat_sys_wifi_signal_3.png deleted file mode 100644 index eec7952..0000000 Binary files a/romfs/res/drawable/wifi/stat_sys_wifi_signal_3.png and /dev/null differ diff --git a/romfs/res/drawable/wifi/stat_sys_wifi_signal_null.png b/romfs/res/drawable/wifi/stat_sys_wifi_signal_null.png deleted file mode 100644 index f12b0a6..0000000 Binary files a/romfs/res/drawable/wifi/stat_sys_wifi_signal_null.png and /dev/null differ diff --git a/source/C2D_helper.c b/source/C2D_helper.c new file mode 100644 index 0000000..a0e2c4d --- /dev/null +++ b/source/C2D_helper.c @@ -0,0 +1,65 @@ +#include + +#include "common.h" +#include "C2D_helper.h" + +void Draw_EndFrame(void) +{ + C2D_TextBufClear(dynamicBuf); + C2D_TextBufClear(sizeBuf); + C3D_FrameEnd(0); +} + +void Draw_Text(float x, float y, float size, Colour colour, const char *text) +{ + C2D_Text c2d_text; + C2D_TextParse(&c2d_text, dynamicBuf, text); + C2D_TextOptimize(&c2d_text); + C2D_DrawText(&c2d_text, C2D_WithColor, x, y, 0.5f, size, size, colour); +} + +void Draw_Textf(float x, float y, float size, Colour colour, const char* text, ...) +{ + char buffer[256]; + va_list args; + va_start(args, text); + vsnprintf(buffer, 256, text, args); + Draw_Text(x, y, size, colour, buffer); + va_end(args); +} + +void Draw_GetTextSize(float size, float *width, float *height, const char *text) +{ + C2D_Text c2d_text; + C2D_TextParse(&c2d_text, sizeBuf, text); + C2D_TextGetDimensions(&c2d_text, size, size, width, height); +} + +float Draw_GetTextWidth(float size, const char *text) +{ + float width = 0; + Draw_GetTextSize(size, &width, NULL, text); + return width; +} + +float Draw_GetTextHeight(float size, const char *text) +{ + float height = 0; + Draw_GetTextSize(size, NULL, &height, text); + return height; +} + +bool Draw_Rect(float x, float y, float w, float h, Colour colour) +{ + return C2D_DrawRectSolid(x, y, 0.5f, w, h, colour); +} + +bool Draw_Image(C2D_Image image, float x, float y) +{ + return C2D_DrawImageAt(image, x, y, 0.5f, NULL, 1.0f, 1.0f); +} + +bool Draw_ImageScale(C2D_Image image, float x, float y, float scaleX, float scaleY) +{ + return C2D_DrawImageAt(image, x, y, 0.5f, NULL, scaleX, scaleY); +} \ No newline at end of file diff --git a/source/audio/audio.c b/source/audio/audio.c index c7fbf78..830f18c 100644 --- a/source/audio/audio.c +++ b/source/audio/audio.c @@ -3,11 +3,19 @@ #include #include "audio.h" +#include "flac.h" +#include "mp3.h" +#include "vorbis.h" +#include "wav.h" -bool Audio_IsPlaying(enum channel_e channel) +#include "fs.h" + +volatile bool stop = true; + +/*bool Audio_IsPlaying(enum channel_e channel) { return ndspChnIsPlaying(channel); -} +}*/ bool Audio_IsPaused(enum channel_e channel) { @@ -18,4 +26,197 @@ bool Audio_TogglePlayback(enum channel_e channel) { ndspChnSetPaused(channel, !(ndspChnIsPaused(channel))); return !(ndspChnIsPaused(channel)); +} + +void Audio_StopPlayback(void) +{ + stop = true; +} + +bool Audio_IsPlaying(void) +{ + return !stop; +} + +enum file_types Audio_GetMusicFileType(const char *file) +{ + Handle handle; + + u32 fileSig = 0, bytesRead = 0; + u64 offset = 0; + + enum file_types file_type = FILE_TYPE_ERROR; + + /* Failure opening file */ + if (R_FAILED(FS_Open(&handle, archive, file, FS_OPEN_READ))) + { + FSFILE_Close(handle); + return -1; + } + + if (R_FAILED(FSFILE_Read(handle, &bytesRead, offset, &fileSig, 4))) + { + FSFILE_Close(handle); + return -2; + } + + offset += bytesRead; + + switch(fileSig) + { + // "RIFF" + case 0x46464952: + if (isWav(file) == 0) + file_type = FILE_TYPE_WAV; + break; + + // "fLaC" + case 0x43614c66: + file_type = FILE_TYPE_FLAC; + break; + + // "OggS" + case 0x5367674F: + if (isFlac(file) == 0) + file_type = FILE_TYPE_FLAC; + else if (isVorbis(file) == 0) + file_type = FILE_TYPE_VORBIS; + + break; + + // MP3 file with an ID3v2 container + default: + if ((fileSig << 16) == 0xFBFF0000 || (fileSig << 16) == 0xFAFF0000 || (fileSig << 8) == 0x33444900) + { + file_type = FILE_TYPE_MP3; + break; + } + } + + FSFILE_Close(handle); + return file_type; +} + +void Audio_PlayFile(void *path) +{ + struct decoder_fn decoder; + const char *file = path; + s16 *buffer1 = NULL; + s16 *buffer2 = NULL; + ndspWaveBuf waveBuf[2]; + bool lastbuf = false; + Result ret = -1; + + /* Reset previous stop command */ + stop = false; + + switch(Audio_GetMusicFileType(file)) + { + case FILE_TYPE_WAV: + setWav(&decoder); + break; + + case FILE_TYPE_FLAC: + setFlac(&decoder); + break; + + case FILE_TYPE_MP3: + setMp3(&decoder); + break; + + case FILE_TYPE_VORBIS: + setVorbis(&decoder); + break; + + default: + goto out; + } + + if ((ret = (*decoder.init)(file)) != 0) + goto out; + + if ((*decoder.channels)() > 2 || (*decoder.channels)() < 1) + goto out; + + buffer1 = linearAlloc(decoder.buffSize *sizeof(s16)); + buffer2 = linearAlloc(decoder.buffSize *sizeof(s16)); + + ndspChnReset(SFX); + ndspChnWaveBufClear(SFX); + ndspSetOutputMode(NDSP_OUTPUT_STEREO); + ndspChnSetInterp(SFX, NDSP_INTERP_POLYPHASE); + ndspChnSetRate(SFX, (*decoder.rate)()); + ndspChnSetFormat(SFX, (*decoder.channels)() == 2 ? NDSP_FORMAT_STEREO_PCM16 : NDSP_FORMAT_MONO_PCM16); + + memset(waveBuf, 0, sizeof(waveBuf)); + waveBuf[0].nsamples = (*decoder.decode)(&buffer1[0]) / (*decoder.channels)(); + waveBuf[0].data_vaddr = &buffer1[0]; + ndspChnWaveBufAdd(SFX, &waveBuf[0]); + + waveBuf[1].nsamples = (*decoder.decode)(&buffer2[0]) / (*decoder.channels)(); + waveBuf[1].data_vaddr = &buffer2[0]; + ndspChnWaveBufAdd(SFX, &waveBuf[1]); + + /** + *There may be a chance that the music has not started by the time we get + *to the while loop. So we ensure that music has started here. + */ + while(ndspChnIsPlaying(SFX) == false); + + while(stop == false) + { + svcSleepThread(100 *1000); + + /* When the last buffer has finished playing, break. */ + if ((lastbuf == true) && (waveBuf[0].status == NDSP_WBUF_DONE) && (waveBuf[1].status == NDSP_WBUF_DONE)) + break; + + if ((ndspChnIsPaused(SFX) == true) || (lastbuf == true)) + continue; + + if (waveBuf[0].status == NDSP_WBUF_DONE) + { + size_t read = (*decoder.decode)(&buffer1[0]); + + if (read <= 0) + { + lastbuf = true; + continue; + } + else if (read < decoder.buffSize) + waveBuf[0].nsamples = read / (*decoder.channels)(); + + ndspChnWaveBufAdd(SFX, &waveBuf[0]); + } + + if (waveBuf[1].status == NDSP_WBUF_DONE) + { + size_t read = (*decoder.decode)(&buffer2[0]); + + if (read <= 0) + { + lastbuf = true; + continue; + } + else if (read < decoder.buffSize) + waveBuf[1].nsamples = read / (*decoder.channels)(); + + ndspChnWaveBufAdd(SFX, &waveBuf[1]); + } + + if (R_FAILED(DSP_FlushDataCache(buffer1, decoder.buffSize *sizeof(s16)))) + return; + if (R_FAILED(DSP_FlushDataCache(buffer2, decoder.buffSize *sizeof(s16)))) + return; + } + + (*decoder.exit)(); + +out: + Audio_StopPlayback(); + linearFree(buffer1); + linearFree(buffer2); + + threadExit(0); + return; } \ No newline at end of file diff --git a/source/audio/flac.c b/source/audio/flac.c index 195d5c0..8bcf1ed 100644 --- a/source/audio/flac.c +++ b/source/audio/flac.c @@ -5,16 +5,16 @@ #include "flac.h" -static drflac * pFlac; +static drflac *pFlac; static const drflac_uint64 buffSize = 16 * 1024; static drflac_uint64 samplesRead; /** - * Set decoder parameters for flac. + *Set decoder parameters for flac. * - * \param decoder Structure to store parameters. + *\param decoder Structure to store parameters. */ -void setFlac(struct decoder_fn * decoder) +void setFlac(struct decoder_fn *decoder) { decoder->init = &initFlac; decoder->rate = &rateFlac; @@ -25,12 +25,12 @@ void setFlac(struct decoder_fn * decoder) } /** - * Initialise Flac decoder. + *Initialise Flac decoder. * - * \param file Location of flac file to play. - * \return 0 on success, else failure. + *\param file Location of flac file to play. + *\return 0 on success, else failure. */ -int initFlac(const char * file) +int initFlac(const char *file) { pFlac = drflac_open_file(file); @@ -38,9 +38,9 @@ int initFlac(const char * file) } /** - * Get sampling rate of Flac file. + *Get sampling rate of Flac file. * - * \return Sampling rate. + *\return Sampling rate. */ u32 rateFlac(void) { @@ -48,9 +48,9 @@ u32 rateFlac(void) } /** - * Get number of channels of Flac file. + *Get number of channels of Flac file. * - * \return Number of channels for opened file. + *\return Number of channels for opened file. */ u8 channelFlac(void) { @@ -58,19 +58,19 @@ u8 channelFlac(void) } /** - * Decode part of open Flac file. + *Decode part of open Flac file. * - * \param buffer Decoded output. - * \return Samples read for each channel. + *\param buffer Decoded output. + *\return Samples read for each channel. */ -u64 decodeFlac(void * buffer) +u64 decodeFlac(void *buffer) { samplesRead = drflac_read_s16(pFlac, buffSize, buffer); return samplesRead; } /** - * Free Flac decoder. + *Free Flac decoder. */ void exitFlac(void) { @@ -78,15 +78,15 @@ void exitFlac(void) } /** - * Checks if the input file is Flac + *Checks if the input file is Flac * - * \param in Input file. - * \return 0 if Flac file, else not or failure. + *\param in Input file. + *\return 0 if Flac file, else not or failure. */ -int isFlac(const char * in) +int isFlac(const char *in) { int err = -1; - drflac * pFlac = drflac_open_file(in); + drflac *pFlac = drflac_open_file(in); if (pFlac != NULL) err = 0; diff --git a/source/audio/mp3.c b/source/audio/mp3.c index 4a44636..32825d3 100644 --- a/source/audio/mp3.c +++ b/source/audio/mp3.c @@ -26,8 +26,8 @@ typedef intmax_t ssize_p; typedef long ssize_p; #endif -static size_t * buffSize; -static mpg123_handle * mh = NULL; +static size_t *buffSize; +static mpg123_handle *mh = NULL; static u32 rate; static u8 channels; @@ -69,18 +69,18 @@ struct genre genreList[] = }; /** - * Set decoder parameters for MP3. + *Set decoder parameters for MP3. * - * \param decoder Structure to store parameters. + *\param decoder Structure to store parameters. */ -void setMp3(struct decoder_fn * decoder) +void setMp3(struct decoder_fn *decoder) { decoder->init = &initMp3; decoder->rate = &rateMp3; decoder->channels = &channelMp3; /* - * buffSize changes depending on input file. So we set buffSize later when - * decoder is initialised. + *buffSize changes depending on input file. So we set buffSize later when + *decoder is initialised. */ buffSize = &(decoder->buffSize); decoder->decode = &decodeMp3; @@ -88,7 +88,7 @@ void setMp3(struct decoder_fn * decoder) } /* Helper for v1 printing, get these strings their zero byte. */ -void safe_print(char * tag, char * name, char * data, size_t size) +void safe_print(char *tag, char *name, char *data, size_t size) { char safe[31]; if (size > 30) @@ -99,24 +99,24 @@ void safe_print(char * tag, char * name, char * data, size_t size) } /* Print out ID3v1 info. */ -void print_v1(ID3_Tag * ID3tag, mpg123_id3v1 *v1) +void print_v1(ID3_Tag *ID3tag, mpg123_id3v1 *v1) { - safe_print(ID3tag->title, "Title", v1->title, sizeof(v1->title)); - safe_print(ID3tag->artist, "Artist", v1->artist, sizeof(v1->artist)); - safe_print(ID3tag->album, "Album", v1->album, sizeof(v1->album)); - safe_print(ID3tag->year, "Year", v1->year, sizeof(v1->year)); - safe_print(ID3tag->comment, "Comment", v1->comment, sizeof(v1->comment)); - safe_print(ID3tag->genre, "Genre", genreList[v1->genre].text, sizeof(genreList[v1->genre].text)); + safe_print(ID3tag->title, "", v1->title, sizeof(v1->title)); + safe_print(ID3tag->artist, "", v1->artist, sizeof(v1->artist)); + safe_print(ID3tag->album, "", v1->album, sizeof(v1->album)); + safe_print(ID3tag->year, "", v1->year, sizeof(v1->year)); + safe_print(ID3tag->comment, "", v1->comment, sizeof(v1->comment)); + safe_print(ID3tag->genre, "", genreList[v1->genre].text, sizeof(genreList[v1->genre].text)); } /* Split up a number of lines separated by \n, \r, both or just zero byte and print out each line with specified prefix. */ -void print_lines(char * data, const char * prefix, mpg123_string * inlines) +void print_lines(char *data, const char *prefix, mpg123_string *inlines) { size_t i; int hadcr = 0, hadlf = 0; - char * lines = NULL; - char * line = NULL; + char *lines = NULL; + char *line = NULL; size_t len = 0; if (inlines != NULL && inlines->fill) @@ -161,18 +161,18 @@ void print_lines(char * data, const char * prefix, mpg123_string * inlines) } /* Print out the named ID3v2 fields. */ -void print_v2(ID3_Tag * ID3tag, mpg123_id3v2 * v2) +void print_v2(ID3_Tag *ID3tag, mpg123_id3v2 *v2) { - print_lines(ID3tag->title, "Title: ", v2->title); + print_lines(ID3tag->title, "", v2->title); print_lines(ID3tag->artist, "", v2->artist); - print_lines(ID3tag->album, "Album: ", v2->album); - print_lines(ID3tag->year, "Year: ", v2->year); - print_lines(ID3tag->comment, "Comment: ", v2->comment); - print_lines(ID3tag->genre, "Genre: ", v2->genre); + print_lines(ID3tag->album, "", v2->album); + print_lines(ID3tag->year, "", v2->year); + print_lines(ID3tag->comment, "", v2->comment); + print_lines(ID3tag->genre, "", v2->genre); } /* Easy conversion to string via lookup. */ -const char * pic_types[] = +const char *pic_types[] = { "other" ,"icon" @@ -197,7 +197,7 @@ const char * pic_types[] = ,"publisher logo" }; -static const char * pic_type(int id) +static const char *pic_type(int id) { return (id >= 0 && id < (sizeof(pic_types)/sizeof(char*))) ? pic_types[id] : "invalid type"; } @@ -254,12 +254,12 @@ void print_raw_v2(mpg123_id3v2 *v2) } } -const char * unknown_end = "picture"; +const char *unknown_end = "picture"; -static char * mime2end(mpg123_string * mime) +static char *mime2end(mpg123_string *mime) { size_t len; - char * end; + char *end; if(strncasecmp("image/",mime->p,6)) { len = strlen(unknown_end)+1; @@ -292,10 +292,10 @@ static char * mime2end(mpg123_string * mime) /* Construct a sane file name without introducing spaces, then open. Example: /some/where/some.mp3.front_cover.jpeg If multiple ones are there: some.mp3.front_cover2.jpeg */ -int open_picfile(const char * prefix, mpg123_picture * pic) +int open_picfile(const char *prefix, mpg123_picture *pic) { - char * end, * typestr, * pfn; - const char * pictype; + char *end, *typestr, *pfn; + const char *pictype; size_t i, len; int fd; unsigned long count = 1; @@ -364,7 +364,7 @@ static void store_pictures(const char* prefix, mpg123_id3v2 *v2) fd = open_picfile(prefix, pic); if(fd >= 0) { /* stream I/O for not having to care about interruptions */ - FILE * picfile = fdopen(fd, "w"); + FILE *picfile = fdopen(fd, "w"); if(picfile) { if(fwrite(pic->data, pic->size, 1, picfile) != 1) @@ -381,12 +381,12 @@ static void store_pictures(const char* prefix, mpg123_id3v2 *v2) } /** - * Initialise MP3 decoder. + *Initialise MP3 decoder. * - * \param file Location of MP3 file to play. - * \return 0 on success, else failure. + *\param file Location of MP3 file to play. + *\return 0 on success, else failure. */ -int initMp3(const char * file) +int initMp3(const char *file) { int err = 0; int encoding = 0; @@ -402,8 +402,8 @@ int initMp3(const char * file) mpg123_param(mh, MPG123_ADD_FLAGS, MPG123_PICTURE, 0.); - mpg123_id3v1 * v1; - mpg123_id3v2 * v2; + mpg123_id3v1 *v1; + mpg123_id3v2 *v2; int meta; if (mpg123_open(mh, file) != MPG123_OK || mpg123_getformat(mh, (long *) &rate, (int *) &channels, &encoding) != MPG123_OK) @@ -430,15 +430,15 @@ int initMp3(const char * file) } /* - * Ensure that this output format will not change (it might, when we allow - * it). + *Ensure that this output format will not change (it might, when we allow + *it). */ mpg123_format_none(mh); mpg123_format(mh, rate, channels, encoding); /* - * Buffer could be almost any size here, mpg123_outblock() is just some - * recommendation. The size should be a multiple of the PCM frame size. + *Buffer could be almost any size here, mpg123_outblock() is just some + *recommendation. The size should be a multiple of the PCM frame size. */ *buffSize = (mpg123_outblock(mh) * 16); @@ -446,9 +446,9 @@ int initMp3(const char * file) } /** - * Get sampling rate of MP3 file. + *Get sampling rate of MP3 file. * - * \return Sampling rate. + *\return Sampling rate. */ u32 rateMp3(void) { @@ -456,9 +456,9 @@ u32 rateMp3(void) } /** - * Get number of channels of MP3 file. + *Get number of channels of MP3 file. * - * \return Number of channels for opened file. + *\return Number of channels for opened file. */ u8 channelMp3(void) { @@ -466,12 +466,12 @@ u8 channelMp3(void) } /** - * Decode part of open MP3 file. + *Decode part of open MP3 file. * - * \param buffer Decoded output. - * \return Samples read for each channel. + *\param buffer Decoded output. + *\return Samples read for each channel. */ -u64 decodeMp3(void * buffer) +u64 decodeMp3(void *buffer) { size_t done = 0; mpg123_read(mh, buffer, *buffSize, &done); @@ -479,7 +479,7 @@ u64 decodeMp3(void * buffer) } /** - * Free MP3 decoder. + *Free MP3 decoder. */ void exitMp3(void) { diff --git a/source/audio/vorbis.c b/source/audio/vorbis.c index f4a9354..ebc43d1 100644 --- a/source/audio/vorbis.c +++ b/source/audio/vorbis.c @@ -7,16 +7,16 @@ #include "vorbis.h" static OggVorbis_File vorbisFile; -static vorbis_info * vi; -static FILE * f; +static vorbis_info *vi; +static FILE *f; static const size_t buffSize = (8 * 4096); /** - * Set decoder parameters for Vorbis. + *Set decoder parameters for Vorbis. * - * \param decoder Structure to store parameters. + *\param decoder Structure to store parameters. */ -void setVorbis(struct decoder_fn * decoder) +void setVorbis(struct decoder_fn *decoder) { decoder->init = &initVorbis; decoder->rate = &rateVorbis; @@ -27,12 +27,12 @@ void setVorbis(struct decoder_fn * decoder) } /** - * Initialise Vorbis decoder. + *Initialise Vorbis decoder. * - * \param file Location of vorbis file to play. - * \return 0 on success, else failure. + *\param file Location of vorbis file to play. + *\return 0 on success, else failure. */ -int initVorbis(const char * file) +int initVorbis(const char *file) { int err = -1; @@ -52,9 +52,9 @@ int initVorbis(const char * file) } /** - * Get sampling rate of Vorbis file. + *Get sampling rate of Vorbis file. * - * \return Sampling rate. + *\return Sampling rate. */ u32 rateVorbis(void) { @@ -62,9 +62,9 @@ u32 rateVorbis(void) } /** - * Get number of channels of Vorbis file. + *Get number of channels of Vorbis file. * - * \return Number of channels for opened file. + *\return Number of channels for opened file. */ u8 channelVorbis(void) { @@ -72,19 +72,19 @@ u8 channelVorbis(void) } /** - * Decode part of open Vorbis file. + *Decode part of open Vorbis file. * - * \param buffer Decoded output. - * \return Samples read for each channel. 0 for end of file, negative + *\param buffer Decoded output. + *\return Samples read for each channel. 0 for end of file, negative * for error. */ -u64 decodeVorbis(void * buffer) +u64 decodeVorbis(void *buffer) { return fillVorbisBuffer(buffer); } /** - * Free Vorbis decoder. + *Free Vorbis decoder. */ void exitVorbis(void) { @@ -93,13 +93,13 @@ void exitVorbis(void) } /** - * Decode Vorbis file to fill buffer. + *Decode Vorbis file to fill buffer. * - * \param opusFile File to decode. - * \param bufferOut Pointer to buffer. - * \return Samples read per channel. + *\param opusFile File to decode. + *\param bufferOut Pointer to buffer. + *\return Samples read per channel. */ -u64 fillVorbisBuffer(char * bufferOut) +u64 fillVorbisBuffer(char *bufferOut) { u64 samplesRead = 0; int samplesToRead = buffSize; @@ -124,14 +124,14 @@ u64 fillVorbisBuffer(char * bufferOut) } /** - * Checks if the input file is Vorbis. + *Checks if the input file is Vorbis. * - * \param in Input file. - * \return 0 if Vorbis file, else not or failure. + *\param in Input file. + *\return 0 if Vorbis file, else not or failure. */ -int isVorbis(const char * in) +int isVorbis(const char *in) { - FILE * ft = fopen(in, "r"); + FILE *ft = fopen(in, "r"); OggVorbis_File testvf; if (ft == NULL) diff --git a/source/audio/wav.c b/source/audio/wav.c index 1247908..f676b78 100644 --- a/source/audio/wav.c +++ b/source/audio/wav.c @@ -11,11 +11,11 @@ static drwav* pWav; static drwav_uint64 samplesRead; /** - * Set decoder parameters for WAV. + *Set decoder parameters for WAV. * - * \param decoder Structure to store parameters. + *\param decoder Structure to store parameters. */ -void setWav(struct decoder_fn * decoder) +void setWav(struct decoder_fn *decoder) { decoder->init = &initWav; decoder->rate = &rateWav; @@ -26,10 +26,10 @@ void setWav(struct decoder_fn * decoder) } /** - * Initialise WAV playback. + *Initialise WAV playback. * - * \param file Location of WAV file to play. - * \return 0 on success, else failure. + *\param file Location of WAV file to play. + *\return 0 on success, else failure. */ int initWav(const char* filename) { @@ -39,9 +39,9 @@ int initWav(const char* filename) } /** - * Get sampling rate of Wav file. + *Get sampling rate of Wav file. * - * \return Sampling rate. + *\return Sampling rate. */ u32 rateWav(void) { @@ -49,9 +49,9 @@ u32 rateWav(void) } /** - * Get number of channels of Wav file. + *Get number of channels of Wav file. * - * \return Number of channels for opened file. + *\return Number of channels for opened file. */ u8 channelWav(void) { @@ -59,19 +59,19 @@ u8 channelWav(void) } /** - * Read part of open Wav file. + *Read part of open Wav file. * - * \param buffer Output. - * \return Samples read for each channel. + *\param buffer Output. + *\return Samples read for each channel. */ -u64 decodeWav(void * buffer) +u64 decodeWav(void *buffer) { samplesRead = drwav_read_s16(pWav, buffSize, buffer); return samplesRead; } /** - * Free Wav file. + *Free Wav file. */ void exitWav(void) { @@ -79,15 +79,15 @@ void exitWav(void) } /** - * Checks if the input file is Wav + *Checks if the input file is Wav * - * \param in Input file. - * \return 0 if Wav file, else not or failure. + *\param in Input file. + *\return 0 if Wav file, else not or failure. */ -int isWav(const char * in) +int isWav(const char *in) { int err = -1; - drwav * testWav = drwav_open_file(in); + drwav *testWav = drwav_open_file(in); if (testWav != NULL) err = 0; diff --git a/source/cia.c b/source/cia.c index 683a05c..87ff194 100644 --- a/source/cia.c +++ b/source/cia.c @@ -13,7 +13,7 @@ static Result CIA_RemoveTitle(u64 titleID, FS_MediaType media) return ret; u32 read = 0; - u64 * titleIDs = malloc(count * sizeof(u64)); + u64 *titleIDs = malloc(count *sizeof(u64)); ret = AM_GetTitleList(&read, media, count, titleIDs); if (R_FAILED(ret)) @@ -53,7 +53,7 @@ static void CIA_LaunchTitle(u64 titleId, FS_MediaType mediaType) APT_DoApplicationJump(param, sizeof(param), hmac); } -Result CIA_InstallTitle(const char * path, FS_MediaType media, bool update) +Result CIA_InstallTitle(const char *path, FS_MediaType media, bool update) { u32 bytesRead = 0, bytesWritten = 0; u64 fileSize = 0, offset = 0; @@ -62,7 +62,7 @@ Result CIA_InstallTitle(const char * path, FS_MediaType media, bool update) Result ret = 0; - char * filename = Utils_Basename(path); + char *filename = Utils_Basename(path); if (R_FAILED(ret = FSUSER_OpenFileDirectly(&fileHandle, ARCHIVE_SDMC, fsMakePath(PATH_ASCII, ""), fsMakePath(PATH_ASCII, path), FS_OPEN_READ, 0))) return ret; @@ -82,14 +82,14 @@ Result CIA_InstallTitle(const char * path, FS_MediaType media, bool update) if (R_FAILED(ret = AM_StartCiaInstall(media, &ciaHandle))) return ret; - u8 * cia_buffer = malloc((512 * 1024)); + u8 *cia_buffer = malloc((512 *1024)); while (offset < fileSize) { u64 bytesRemaining = fileSize - offset; ProgressBar_DisplayProgress("Installing", filename, bytesRead, fileSize); - ret = FSFILE_Read(fileHandle, &bytesRead, offset, cia_buffer, (512 * 1024)); // (512 * 1024) - chunk size + ret = FSFILE_Read(fileHandle, &bytesRead, offset, cia_buffer, (512 *1024)); // (512 *1024) - chunk size ret = FSFILE_Write(ciaHandle, &bytesWritten, offset, cia_buffer, bytesRead, 0); if (bytesRead != bytesWritten) diff --git a/source/config.c b/source/config.c new file mode 100644 index 0000000..5f52c50 --- /dev/null +++ b/source/config.c @@ -0,0 +1,105 @@ +#include +#include +#include + +#include "common.h" +#include "config.h" +#include "fs.h" + +const char *config_file = + "config_dark_theme = %d\n" + "config_hidden_files = %d\n" + "config_sort_by = %d"; + +Result Config_Save(bool config_dark_theme, bool config_hidden_files, int config_sort_by) +{ + Result ret = 0; + + char *buf = (char *)malloc(256); + snprintf(buf, 256, config_file, config_dark_theme, config_hidden_files, config_sort_by); + + if (R_FAILED(ret = FS_Write(archive, "/3ds/3DShell/config.cfg", buf))) + { + free(buf); + return ret; + } + + free(buf); + return 0; +} + +Result Config_Load(void) +{ + Handle handle; + Result ret = 0; + + if (!FS_FileExists(archive, "/3ds/3DShell/config.cfg")) + { + // set these to the following by default: + config_dark_theme = false; + config_hidden_files = true; + config_sort_by = 0; + return Config_Save(config_dark_theme, config_hidden_files, config_sort_by); + } + + u64 size64 = 0; + u32 size = 0; + + FS_GetFileSize(archive, "/3ds/3DShell/config.cfg", &size64); + size = (u32)size64; + char *buf = (char *)malloc(size + 1); + + if (R_FAILED(ret = FS_Read(archive, "/3ds/3DShell/config.cfg", size, buf))) + { + free(buf); + return ret; + } + + buf[size] = '\0'; + + sscanf(buf, config_file, &config_dark_theme, &config_hidden_files, &config_sort_by); + + free(buf); + return 0; +} + +Result Config_GetLastDirectory(void) +{ + Handle handle; + Result ret = 0; + + if (!FS_FileExists(archive, "/3ds/3DShell/lastdir.txt")) + { + FS_Write(archive, "/3ds/3DShell/lastdir.txt", START_PATH); + strcpy(cwd, START_PATH); // Set Start Path to "sdmc:/" if lastDir.txt hasn't been created. + } + else + { + u64 size64 = 0; + u32 size = 0; + + FS_GetFileSize(archive, "/3ds/3DShell/lastdir.txt", &size64); + size = (u32)size64; + char *buf = (char *)malloc(size + 1); + + if (R_FAILED(ret = FS_Read(archive, "/3ds/3DShell/lastdir.txt", size, buf))) + { + free(buf); + return ret; + } + + buf[size] = '\0'; + + char tempPath[256]; + sscanf(buf, "%[^\n]s", tempPath); + + if (FS_DirExists(archive, tempPath)) // Incase a directory previously visited had been deleted, set start path to sdmc:/ to avoid errors. + strcpy(cwd, tempPath); + else + strcpy(cwd, START_PATH); + + free(buf); + } + + return 0; +} \ No newline at end of file diff --git a/source/dir_list.c b/source/dir_list.c deleted file mode 100644 index b999d72..0000000 --- a/source/dir_list.c +++ /dev/null @@ -1,378 +0,0 @@ -#include -#include - -#include "archive.h" -#include "cia.h" -#include "common.h" -#include "dir_list.h" -#include "fs.h" -#include "language.h" -#include "menu_gallery.h" -#include "menu_music.h" -#include "menu_textviewer.h" -#include "pp2d.h" -#include "textures.h" -#include "theme.h" -#include "utils.h" - -int position = 0; // menu position -int fileCount = 0; // file count -File * files = NULL; // file list - -struct colour TopScreen_colour; -struct colour TopScreen_min_colour; - -static void recursiveFree(File * node) -{ - if (node == NULL) // End of list - return; - - recursiveFree(node->next); // Nest further - free(node); // Free memory -} - -// Sort directories alphabetically. Folder first, then files. -static int cmpstringp(const void *p1, const void *p2) -{ - FS_DirectoryEntry* entryA = (FS_DirectoryEntry*) p1; - FS_DirectoryEntry* entryB = (FS_DirectoryEntry*) p2; - - if ((entryA->attributes & FS_ATTRIBUTE_DIRECTORY) && !(entryB->attributes & FS_ATTRIBUTE_DIRECTORY)) - return -1; - else if (!(entryA->attributes & FS_ATTRIBUTE_DIRECTORY) && (entryB->attributes & FS_ATTRIBUTE_DIRECTORY)) - return 1; - else - { - if (sortBy == 0) - return 0; - else if (sortBy == 1) // Sort alphabetically (ascending - A to Z) - { - char entryNameA[0x200] = {'\0'}, entryNameB[0x200] = {'\0'}; - u16_to_u8((u8 *) entryNameA, entryA->name, sizeof(entryNameA) - 1); - u16_to_u8((u8 *) entryNameB, entryB->name, sizeof(entryNameB) - 1); - return strcasecmp(entryNameA, entryNameB); - } - else if (sortBy == 2) // Sort alphabetically (descending - Z to A) - { - char entryNameA[0x200] = {'\0'}, entryNameB[0x200] = {'\0'}; - u16_to_u8((u8 *) entryNameA, entryA->name, sizeof(entryNameA) - 1); - u16_to_u8((u8 *) entryNameB, entryB->name, sizeof(entryNameB) - 1); - return strcasecmp(entryNameB, entryNameA); - } - else if (sortBy == 3) // Sort by file size (largest first) - { - u64 sizeA = entryA->fileSize; - u64 sizeB = entryB->fileSize; - return sizeA > sizeB ? -1 : sizeA < sizeB ? 1 : 0; - } - else if (sortBy == 4) // Sort by file size (smallest first) - { - u64 sizeA = entryA->fileSize; - u64 sizeB = entryB->fileSize; - return sizeB > sizeA ? -1 : sizeB < sizeA ? 1 : 0; - } - } - - return 0; -} - -Result Dirlist_PopulateFiles(bool clear) -{ - recursiveFree(files); - files = NULL; - fileCount = 0; - - Handle dirHandle; - Result ret = 0; - - if (R_SUCCEEDED(ret = FSUSER_OpenDirectory(&dirHandle, archive, fsMakePath(PATH_ASCII, cwd)))) - { - /* Add fake ".." entry except on root */ - if (strcmp(cwd, ROOT_PATH)) - { - files = (File *)malloc(sizeof(File)); // New list - memset(files, 0, sizeof(File)); // Clear memory - - strcpy(files->name, ".."); // Copy file Name - files->isDir = 1; // Set folder flag - fileCount++; - } - - u32 entryCount = 0; - FS_DirectoryEntry* entries = (FS_DirectoryEntry*) calloc(MAX_FILES, sizeof(FS_DirectoryEntry)); - - if (R_SUCCEEDED(ret = FSDIR_Read(dirHandle, &entryCount, MAX_FILES, entries))) - { - qsort(entries, entryCount, sizeof(FS_DirectoryEntry), cmpstringp); - u8 name[255] = {'\0'}; - - for (u32 i = 0; i < entryCount; i++) - { - u16_to_u8(&name[0], entries[i].name, 254); - - if (name[0] == '\0') // Ingore null filenames - continue; - - if ((!isHiddenEnabled) && (strncmp(name, ".", 1) == RL_SUCCESS)) // Ignore "." in all Directories - continue; - - if (strcmp(cwd, ROOT_PATH) == RL_SUCCESS && strncmp(name, "..", 2) == RL_SUCCESS) // Ignore ".." in Root Directory - continue; - - File * item = (File *)malloc(sizeof(File)); // Allocate memory - memset(item, 0, sizeof(File)); // Clear memory - - strcpy(item->name, name); // Copy file name - strcpy(item->ext, entries[i].shortExt); // Copy file extension - item->size = entries[i].fileSize; // Copy file size - - item->isDir = entries[i].attributes & FS_ATTRIBUTE_DIRECTORY; // Set folder flag - item->isReadOnly = entries[i].attributes & FS_ATTRIBUTE_READ_ONLY; // Set read-Only flag - item->isHidden = entries[i].attributes & FS_ATTRIBUTE_HIDDEN; // Set hidden file flag - - if ((!isHiddenEnabled) && (item->isHidden)) - continue; - - if (files == NULL) // New list - files = item; - - // Existing list - else - { - File * list = files; - - while(list->next != NULL) // Append to list - list = list->next; - - list->next = item; // Link item - } - - fileCount++; // Increment file count - } - } - else - { - free(entries); - return ret; - } - - free(entries); - - if (R_FAILED(ret = FSDIR_Close(dirHandle))) // Close directory - return ret; - } - else - return ret; - - // Attempt to keep index - if (!clear) - { - if (position >= fileCount) - position = fileCount - 1; // Fix position - } - else - position = 0; // Reset position - - return 0; -} - -void Dirlist_DisplayFiles(void) -{ - pp2d_draw_textf(84, 28, 0.45f, 0.45f, RGBA8(255, 255, 255, 255), "%.33s", cwd); // Display current path - - u64 totalStorage = FS_GetTotalStorage(BROWSE_STATE? SYSTEM_MEDIATYPE_CTR_NAND : SYSTEM_MEDIATYPE_SD); - u64 usedStorage = FS_GetUsedStorage(BROWSE_STATE? SYSTEM_MEDIATYPE_CTR_NAND : SYSTEM_MEDIATYPE_SD); - double fill = (((double)usedStorage / (double)totalStorage) * 209.0); - - pp2d_draw_rectangle(82, 47, fill, 2, RGBA8(48, 174, 222, 255)); // Draw storage bar - - int i = 0; - int printed = 0; // Print counter - - File * file = files; // Draw file list - - //scroll_x = 395; - - for(; file != NULL; file = file->next) - { - if (printed == FILES_PER_PAGE) // Limit the files per page - break; - - if (position < FILES_PER_PAGE || i > (position - FILES_PER_PAGE)) - { - if (i == position) - pp2d_draw_texture(TEXTURE_SELECTOR, 0, 53 + (38 * printed)); // Draw selector - - if (strcmp(multi_select_dir, cwd) == 0) - multi_select[i] == true? pp2d_draw_texture(TEXTURE_ICON_CHECK, 8, 66 + (38 * printed)) : pp2d_draw_texture(TEXTURE_ICON_UNCHECK, 8, 66 + (38 * printed)); - else - pp2d_draw_texture(TEXTURE_ICON_UNCHECK, 8, 66 + (38 * printed)); - - char path[500]; - strcpy(path, cwd); - strcpy(path + strlen(path), file->name); - - if (file->isDir) - pp2d_draw_texture(TEXTURE_ICON_FOLDER, 30, 58 + (38 * printed)); - else if ((strncasecmp(file->ext, "3ds", 3) == RL_SUCCESS) || (strncasecmp(file->ext, "cia", 3) == RL_SUCCESS)) - pp2d_draw_texture(TEXTURE_ICON_APP, 30, 58 + (38 * printed)); - else if ((strncasecmp(file->ext, "mp3", 3) == RL_SUCCESS) || (strncasecmp(file->ext, "ogg", 3) == RL_SUCCESS) || - (strncasecmp(file->ext, "wav", 3) == RL_SUCCESS) || (strncasecmp(file->ext, "fla", 3) == RL_SUCCESS) || - (strncasecmp(file->ext, "bcs", 3) == RL_SUCCESS)) - pp2d_draw_texture(TEXTURE_ICON_AUDIO, 30, 58 + (38 * printed)); - else if ((strncasecmp(file->ext, "jpg", 3) == RL_SUCCESS) || (strncasecmp(file->ext, "png", 3) == RL_SUCCESS) || - (strncasecmp(file->ext, "gif", 3) == RL_SUCCESS) || (strncasecmp(file->ext, "bmp", 3) == RL_SUCCESS) || - (strncasecmp(file->ext, "tga", 3) == RL_SUCCESS)) - pp2d_draw_texture(TEXTURE_ICON_IMG, 30, 58 + (38 * printed)); - else if ((strncasecmp(file->ext, "bin", 3) == RL_SUCCESS) || (strncasecmp(file->ext, "fir", 3) == RL_SUCCESS)) - pp2d_draw_texture(TEXTURE_ICON_SYSTEM, 30, 58 + (38 * printed)); - else if (strncasecmp(file->ext, "txt", 3) == RL_SUCCESS) - pp2d_draw_texture(TEXTURE_ICON_TEXT, 30, 58 + (38 * printed)); - else if (strncasecmp(file->ext, "zip", 3) == RL_SUCCESS) - pp2d_draw_texture(TEXTURE_ICON_ARCHIVE, 30, 58 + (38 * printed)); - else - pp2d_draw_texture(TEXTURE_ICON_FILE, 30, 58 + (38 * printed)); - - char buf[64], size[16]; - - strncpy(buf, file->name, sizeof(buf)); - buf[sizeof(buf) - 1] = '\0'; - - pp2d_draw_textf(70, 58 + (38 * printed), 0.45f, 0.45f, RGBA8(TopScreen_colour.r ,TopScreen_colour.g, TopScreen_colour.b, 255), "%.45s", buf); // Display file name - - if ((file->isDir) && (strncmp(file->name, "..", 2) != RL_SUCCESS)) - { - if (file->isReadOnly) - pp2d_draw_textf(70, 76 + (38 * printed), 0.42f, 0.42f, RGBA8(TopScreen_min_colour.r, TopScreen_min_colour.g, TopScreen_min_colour.b, 255), "%s dr-xr-xr-x", FS_GetFileModifiedTime(path)); - else - pp2d_draw_textf(70, 76 + (38 * printed), 0.42f, 0.42f, RGBA8(TopScreen_min_colour.r, TopScreen_min_colour.g, TopScreen_min_colour.b, 255), "%s drwxrwxrwx", FS_GetFileModifiedTime(path)); - - } - else if (strncmp(file->name, "..", 2) == RL_SUCCESS) - pp2d_draw_text(70, 76 + (38 * printed), 0.45f, 0.45f, RGBA8(TopScreen_min_colour.r, TopScreen_min_colour.g, TopScreen_min_colour.b, 255), lang_files[language][0]); - else - { - Utils_GetSizeString(size, file->size); - - if (file->isReadOnly) - pp2d_draw_textf(70, 76 + (38 * printed), 0.42f, 0.42f, RGBA8(TopScreen_min_colour.r, TopScreen_min_colour.g, TopScreen_min_colour.b, 255), "%s -r--r--r--", FS_GetFileModifiedTime(path)); - else - pp2d_draw_textf(70, 76 + (38 * printed), 0.42f, 0.42f, RGBA8(TopScreen_min_colour.r, TopScreen_min_colour.g, TopScreen_min_colour.b, 255), "%s -rw-rw-rw-", FS_GetFileModifiedTime(path)); - - pp2d_draw_textf(395 - pp2d_get_text_width(size, 0.42f, 0.42f), 76 + (38 * printed), 0.42f, 0.42f, RGBA8(TopScreen_colour.r, TopScreen_colour.g, TopScreen_colour.b, 255), "%s", size); - } - - printed++; // Increase printed counter - } - - i++; // Increase counter - } -} - -static Result Dirlist_SaveLastDirectory(void) -{ - return FS_Write(archive, "/3ds/3DShell/lastdir.txt", cwd); -} - -// Get file index -File * Dirlist_GetFileIndex(int index) -{ - int i = 0; - - File * file = files; // Find file Item - - for(; file != NULL && i != index; file = file->next) - i++; - - return file; // Return file -} - -/** - * Executes an operation on the file depending on the filetype. - */ -void Dirlist_OpenFile(void) -{ - char path[512]; - File * file = Dirlist_GetFileIndex(position); - - if (file == NULL) - return; - - strcpy(fileName, file->name); - strcpy(path, cwd); - strcpy(path + strlen(path), file->name); - - if (file->isDir) - { - // Attempt to navigate to target - if (R_SUCCEEDED(Dirlist_Navigate(0))) - { - if (BROWSE_STATE != STATE_NAND) - Dirlist_SaveLastDirectory(); - - Dirlist_PopulateFiles(true); - Dirlist_DisplayFiles(); - } - } - else if ((strncasecmp(file->ext, "png", 3) == RL_SUCCESS) || (strncasecmp(file->ext, "jpg", 3) == RL_SUCCESS) || - (strncasecmp(file->ext, "gif", 3) == RL_SUCCESS) || (strncasecmp(file->ext, "bmp", 3) == RL_SUCCESS) || - (strncasecmp(file->ext, "tga", 3) == RL_SUCCESS)) - Gallery_DisplayImage(path); - else if (Music_GetMusicFileType(path) != RL_SUCCESS) - Music_Player(path); - else if (strncasecmp(file->ext, "txt", 3) == RL_SUCCESS) - TextViewer_DisplayText(path); - else if (strncasecmp(file->ext, "zip", 3) == RL_SUCCESS) - { - Archive_ExtractZip(path, cwd); - Dirlist_PopulateFiles(true); - Dirlist_DisplayFiles(); - } - /*else if (strncasecmp(file->ext, "txt", 3) == RL_SUCCESS) - menu_displayText(path);*/ -} - -// Navigate to Folder -int Dirlist_Navigate(int dir) -{ - File * file = Dirlist_GetFileIndex(position); // Get index - - if ((file == NULL) || (!file->isDir)) // Not a folder - return -1; - - // Special case ".." - if ((dir == -1) || (strncmp(file->name, "..", 2) == 0)) - { - char * slash = NULL; - - // Find last '/' in working directory - int i = strlen(cwd) - 2; for(; i >= 0; i--) - { - // Slash discovered - if (cwd[i] == '/') - { - slash = cwd + i + 1; // Save pointer - break; // Stop search - } - } - - slash[0] = 0; // Terminate working directory - - if (BROWSE_STATE != STATE_NAND) - Dirlist_SaveLastDirectory(); - } - - // Normal folder - else - { - // Append folder to working directory - strcpy(cwd + strlen(cwd), file->name); - cwd[strlen(cwd) + 1] = 0; - cwd[strlen(cwd)] = '/'; - - if (BROWSE_STATE != STATE_NAND) - Dirlist_SaveLastDirectory(); - } - - return 0; // Return success -} \ No newline at end of file diff --git a/source/dirbrowse.c b/source/dirbrowse.c new file mode 100644 index 0000000..1a64749 --- /dev/null +++ b/source/dirbrowse.c @@ -0,0 +1,354 @@ +#include + +#include "archive.h" +#include "C2D_helper.h" +#include "common.h" +#include "config.h" +#include "dirbrowse.h" +#include "fs.h" +#include "menu_gallery.h" +#include "menu_music.h" +//#include "menu_book_reader.h" +#include "textures.h" +#include "utils.h" + +int initialPosition = 0; +int position = 0; // menu position +int fileCount = 0; // file count +File *files = NULL; // file list + +void Dirbrowse_RecursiveFree(File *node) +{ + if (node == NULL) // End of list + return; + + Dirbrowse_RecursiveFree(node->next); // Nest further + free(node); // Free memory +} + +// Sort directories alphabetically. Folder first, then files. +static int cmpstringp(const void *p1, const void *p2) +{ + FS_DirectoryEntry* entryA = (FS_DirectoryEntry*) p1; + FS_DirectoryEntry* entryB = (FS_DirectoryEntry*) p2; + + if ((entryA->attributes & FS_ATTRIBUTE_DIRECTORY) && !(entryB->attributes & FS_ATTRIBUTE_DIRECTORY)) + return -1; + else if (!(entryA->attributes & FS_ATTRIBUTE_DIRECTORY) && (entryB->attributes & FS_ATTRIBUTE_DIRECTORY)) + return 1; + else + { + if (config_sort_by == 0) // Sort alphabetically (ascending - A to Z) + { + char entryNameA[256] = {'\0'}, entryNameB[256] = {'\0'}; + Utils_U16_To_U8((u8 *) entryNameA, entryA->name, sizeof(entryNameA) - 1); + Utils_U16_To_U8((u8 *) entryNameB, entryB->name, sizeof(entryNameB) - 1); + return strcasecmp(entryNameA, entryNameB); + } + else if (config_sort_by == 1) // Sort alphabetically (descending - Z to A) + { + char entryNameA[256] = {'\0'}, entryNameB[256] = {'\0'}; + Utils_U16_To_U8((u8 *) entryNameA, entryA->name, sizeof(entryNameA) - 1); + Utils_U16_To_U8((u8 *) entryNameB, entryB->name, sizeof(entryNameB) - 1); + return strcasecmp(entryNameB, entryNameA); + } + else if (config_sort_by == 2) // Sort by file size (largest first) + { + u64 sizeA = entryA->fileSize; + u64 sizeB = entryB->fileSize; + return sizeA > sizeB ? -1 : sizeA < sizeB ? 1 : 0; + } + else if (config_sort_by == 3) // Sort by file size (smallest first) + { + u64 sizeA = entryA->fileSize; + u64 sizeB = entryB->fileSize; + return sizeB > sizeA ? -1 : sizeB < sizeA ? 1 : 0; + } + } + + return 0; +} + +Result Dirbrowse_PopulateFiles(bool clear) +{ + Dirbrowse_RecursiveFree(files); + files = NULL; + fileCount = 0; + + Handle dir; + Result ret = 0; + + if (R_SUCCEEDED(ret = FSUSER_OpenDirectory(&dir, archive, fsMakePath(PATH_ASCII, cwd)))) + { + /* Add fake ".." entry except on root */ + if (strcmp(cwd, ROOT_PATH)) + { + files = (File *)malloc(sizeof(File)); // New list + memset(files, 0, sizeof(File)); // Clear memory + strcpy(files->name, ".."); // Copy file Name + files->isDir = 1; // Set folder flag + fileCount++; + } + + u32 entryCount = 0; + FS_DirectoryEntry* entries = (FS_DirectoryEntry*) calloc(MAX_FILES, sizeof(FS_DirectoryEntry)); + + if (R_SUCCEEDED(ret = FSDIR_Read(dir, &entryCount, MAX_FILES, entries))) + { + qsort(entries, entryCount, sizeof(FS_DirectoryEntry), cmpstringp); + u8 name[256] = {'\0'}; + + for (u32 i = 0; i < entryCount; i++) + { + Utils_U16_To_U8(&name[0], entries[i].name, 255); + + if (name[0] == '\0') // Ignore "." in all Directories + continue; + + if ((!config_hidden_files) && (strncmp(name, ".", 1) == RL_SUCCESS)) // Ignore "." in all Directories + continue; + + if (strcmp(cwd, ROOT_PATH) == 0 && strncmp(name, "..", 2) == 0) // Ignore ".." in Root Directory + continue; + + File *item = (File *)malloc(sizeof(File)); + memset(item, 0, sizeof(File)); + + strcpy(item->name, name); // Copy file name + strcpy(item->ext, entries[i].shortExt); // Copy file extension + item->size = entries[i].fileSize; // Copy file size + + item->isDir = entries[i].attributes & FS_ATTRIBUTE_DIRECTORY; // Set folder flag + item->isReadOnly = entries[i].attributes & FS_ATTRIBUTE_READ_ONLY; // Set read-Only flag + item->isHidden = entries[i].attributes & FS_ATTRIBUTE_HIDDEN; // Set hidden file flag + + if ((!config_hidden_files) && (item->isHidden)) + continue; + + if (files == NULL) // New list + files = item; + + // Existing list + else + { + File *list = files; + + while(list->next != NULL) // Append to list + list = list->next; + + list->next = item; // Link item + } + + fileCount++; // Increment file count + } + } + else + { + free(entries); + return ret; + } + + free(entries); + + if (R_FAILED(ret = FSDIR_Close(dir))) // Close directory + return ret; + } + else + return ret; + + // Attempt to keep index + if (!clear) + { + if (position >= fileCount) + position = fileCount - 1; // Fix position + } + else + position = 0; // Reset position + + return 0; +} + +void Dirbrowse_DisplayFiles(void) +{ + //Draw_Image(icon_nav_drawer, 20, 58); + //Draw_Image(icon_actions, (380 - 64), 58); + float title_height = 0; + Draw_GetTextSize(0.48f, NULL, &title_height, cwd); + Draw_Text(70, 18 + ((34 - title_height) / 2), 0.48f, WHITE, cwd); + + int i = 0, printed = 0; + File *file = files; // Draw file list + + for(; file != NULL; file = file->next) + { + if (printed == FILES_PER_PAGE) // Limit the files per page + break; + + if (position < FILES_PER_PAGE || i > (position - FILES_PER_PAGE)) + { + if (i == position) + Draw_Rect(0, 52 + (38 * printed), 400, 38, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); + + if (strcmp(multi_select_dir, cwd) == 0) + { + multi_select[i] == true? Draw_Image(config_dark_theme? icon_check_dark : icon_check, 5, 61 + (38 * printed)) : + Draw_Image(config_dark_theme? icon_uncheck_dark : icon_uncheck, 5, 61 + (38 * printed)); + } + else + Draw_Image(config_dark_theme? icon_uncheck_dark : icon_uncheck, 5, 61 + (38 * printed)); + + char path[512]; + strcpy(path, cwd); + strcpy(path + strlen(path), file->name); + + if (file->isDir) + Draw_Image(config_dark_theme? icon_dir_dark : icon_dir, 30, 56 + (38 * printed)); + else if ((strncasecmp(file->ext, "3ds", 3) == 0) || (strncasecmp(file->ext, "cia", 3) == 0) || (strncasecmp(file->ext, "bin", 3) == 0)) + Draw_Image(icon_app, 30, 56 + (38 * printed)); + else if ((strncasecmp(file->ext, "zip", 3) == 0) || (strncasecmp(file->ext, "tar", 3) == 0) + || (strncasecmp(file->ext, "lz4", 3) == 0)) + Draw_Image(icon_archive, 30, 56 + (38 * printed)); + else if ((strncasecmp(file->ext, "mp3", 3) == 0) || (strncasecmp(file->ext, "ogg", 3) == 0) + || (strncasecmp(file->ext, "wav", 3) == 0) || (strncasecmp(file->ext, "fla", 3) == 0)) + Draw_Image(icon_audio, 30, 56 + (38 * printed)); + else if ((strncasecmp(file->ext, "png", 3) == 0) || (strncasecmp(file->ext, "jpg", 3) == 0) + || (strncasecmp(file->ext, "bmp", 3) == 0)) + Draw_Image(icon_image, 30, 56 + (38 * printed)); + else if ((strncasecmp(file->ext, "txt", 3) == 0) || (strncasecmp(file->ext, "lua", 3) == 0) + || (strncasecmp(file->ext, "cfg", 3) == 0)) + Draw_Image(icon_text, 30, 56 + (38 * printed)); + else if ((strncasecmp(file->ext, "pdf", 3) == 0) || (strncasecmp(file->ext, "cbz", 3) == 0) + || (strncasecmp(file->ext, "fb2", 3) == 0) || (strncasecmp(file->ext, "epub", 4) == 0)) + Draw_Image(icon_doc, 30, 56 + (38 * printed)); + else + Draw_Image(icon_file, 30, 56 + (38 * printed)); + + char buf[64], size[16]; + strncpy(buf, file->name, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + + /*if (!file->isDir) + { + Utils_GetSizeString(size, file->size); + float width = 0; + Draw_GetTextSize(0.48f, &width, NULL, size); + Draw_Text(390 - width, 180 + (73 * printed), 0.48f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, size); + }*/ + + float height = 0; + Draw_GetTextSize(0.48f, NULL, &height, buf); + + if (strncmp(file->name, "..", 2) == 0) + Draw_Text(70, 52 + ((38 - height)/2) + (38 * printed), 0.48f, config_dark_theme? WHITE : BLACK, "Parent folder"); + else + Draw_Text(70, 52 + ((38 - height)/2) + (38 * printed), 0.48f, config_dark_theme? WHITE : BLACK, buf); + + printed++; // Increase printed counter + } + + i++; // Increase counter + } +} + +static Result Dirbrowse_SaveLastDirectory(void) +{ + Result ret = 0; + + if (R_FAILED(ret = FS_Write(archive, "/3ds/3DShell/lastdir.txt", cwd))) + return ret; + + return 0; +} + +// Get file index +File *Dirbrowse_GetFileIndex(int index) +{ + int i = 0; + File *file = files; // Find file Item + + for(; file != NULL && i != index; file = file->next) + i++; + + return file; // Return file +} + +/** + * Executes an operation on the file depending on the filetype. + */ +void Dirbrowse_OpenFile(void) +{ + char path[512]; + File *file = Dirbrowse_GetFileIndex(position); + + if (file == NULL) + return; + + strcpy(fileName, file->name); + strcpy(path, cwd); + strcpy(path + strlen(path), file->name); + + if (file->isDir) + { + // Attempt to navigate to target + if (R_SUCCEEDED(Dirbrowse_Navigate(0))) + { + Dirbrowse_SaveLastDirectory(); + Dirbrowse_PopulateFiles(true); + } + } + else if ((strncasecmp(file->ext, "png", 3) == 0) || (strncasecmp(file->ext, "jpg", 3) == 0) || + (strncasecmp(file->ext, "bmp", 3) == 0)) + Gallery_DisplayImage(path); + else if (strncasecmp(file->ext, "zip", 3) == 0) + { + Archive_ExtractZip(path, cwd); + Dirbrowse_PopulateFiles(true); + } + else if ((strncasecmp(file->ext, "mp3", 3) == 0) || (strncasecmp(file->ext, "ogg", 3) == 0) + || (strncasecmp(file->ext, "wav", 3) == 0) || (strncasecmp(file->ext, "fla", 3) == 0)) + Menu_PlayMusic(path); + /*else if ((strncasecmp(file->ext, "pdf", 3) == 0) || (strncasecmp(file->ext, "cbz", 3) == 0) + || (strncasecmp(file->ext, "fb2", 3) == 0) || (strncasecmp(file->ext, "epub", 4) == 0)) + Menu_OpenBook(path);*/ +} + +// Navigate to Folder +int Dirbrowse_Navigate(int dir) +{ + File *file = Dirbrowse_GetFileIndex(position); // Get index + + if ((file == NULL) || (!file->isDir)) // Not a folder + return -1; + + // Special case ".." + if ((dir == -1) || (strncmp(file->name, "..", 2) == 0)) + { + char *slash = NULL; + + // Find last '/' in working directory + int i = strlen(cwd) - 2; for(; i >= 0; i--) + { + // Slash discovered + if (cwd[i] == '/') + { + slash = cwd + i + 1; // Save pointer + break; // Stop search + } + } + + slash[0] = 0; // Terminate working directory + } + + // Normal folder + else + { + // Append folder to working directory + strcpy(cwd + strlen(cwd), file->name); + cwd[strlen(cwd) + 1] = 0; + cwd[strlen(cwd)] = '/'; + } + + Dirbrowse_SaveLastDirectory(); + + return 0; // Return success +} \ No newline at end of file diff --git a/source/fs.c b/source/fs.c index af1d1e8..b41ff07 100644 --- a/source/fs.c +++ b/source/fs.c @@ -5,7 +5,7 @@ #include "fs.h" #include "utils.h" -Result FS_OpenArchive(FS_Archive * archive, FS_ArchiveID archiveID) +Result FS_OpenArchive(FS_Archive *archive, FS_ArchiveID archiveID) { Result ret = 0; @@ -25,7 +25,7 @@ Result FS_CloseArchive(FS_Archive archive) return 0; } -Result FS_MakeDir(FS_Archive archive, const char * path) +Result FS_MakeDir(FS_Archive archive, const char *path) { Result ret = 0; @@ -35,7 +35,7 @@ Result FS_MakeDir(FS_Archive archive, const char * path) return 0; } -Result FS_RecursiveMakeDir(FS_Archive archive, const char * dir) +Result FS_RecursiveMakeDir(FS_Archive archive, const char *dir) { Result ret = 0; char buf[256]; @@ -65,7 +65,7 @@ Result FS_RecursiveMakeDir(FS_Archive archive, const char * dir) return ret; } -bool FS_FileExists(FS_Archive archive, const char * path) +bool FS_FileExists(FS_Archive archive, const char *path) { Handle handle; @@ -78,7 +78,7 @@ bool FS_FileExists(FS_Archive archive, const char * path) return true; } -bool FS_DirExists(FS_Archive archive, const char * path) +bool FS_DirExists(FS_Archive archive, const char *path) { Handle handle; @@ -91,7 +91,7 @@ bool FS_DirExists(FS_Archive archive, const char * path) return true; } -char * FS_GetFileModifiedTime(char * path) +/*char *FS_GetFileModifiedTime(char *path) { static char timeStr[20]; u64 mtime = 0; @@ -125,24 +125,21 @@ char * FS_GetFileModifiedTime(char * path) } return timeStr; -} +}*/ -u64 FS_GetFileSize(FS_Archive archive, const char * path) +Result FS_GetFileSize(FS_Archive archive, const char *path, u64 *size) { Handle handle; Result ret = 0; - u64 st_size = 0; if (R_FAILED(ret = FSUSER_OpenFile(&handle, archive, fsMakePath(PATH_ASCII, path), FS_OPEN_READ, 0))) return ret; - if (R_FAILED(ret = FSFILE_GetSize(handle, &st_size))) + if (R_FAILED(ret = FSFILE_GetSize(handle, size))) return ret; if (R_FAILED(ret = FSFILE_Close(handle))) return ret; - - return st_size; } u64 FS_GetFreeStorage(FS_SystemMediaType mediaType) @@ -150,7 +147,7 @@ u64 FS_GetFreeStorage(FS_SystemMediaType mediaType) FS_ArchiveResource resource = {0}; if (R_SUCCEEDED(FSUSER_GetArchiveResource(&resource, mediaType))) - return (((u64) resource.freeClusters * (u64) resource.clusterSize)); + return (((u64) resource.freeClusters *(u64) resource.clusterSize)); return 0; } @@ -160,7 +157,7 @@ u64 FS_GetTotalStorage(FS_SystemMediaType mediaType) FS_ArchiveResource resource = {0}; if (R_SUCCEEDED(FSUSER_GetArchiveResource(&resource, mediaType))) - return (((u64) resource.totalClusters * (u64) resource.clusterSize)); + return (((u64) resource.totalClusters *(u64) resource.clusterSize)); return 0; } @@ -170,12 +167,12 @@ u64 FS_GetUsedStorage(FS_SystemMediaType mediaType) FS_ArchiveResource resource = {0}; if (R_SUCCEEDED(FSUSER_GetArchiveResource(&resource, mediaType))) - return ((((u64) resource.totalClusters * (u64) resource.clusterSize)) - (((u64) resource.freeClusters * (u64) resource.clusterSize))); + return ((((u64) resource.totalClusters *(u64) resource.clusterSize)) - (((u64) resource.freeClusters *(u64) resource.clusterSize))); return 0; } -Result FS_Remove(FS_Archive archive, const char * filename) +Result FS_Remove(FS_Archive archive, const char *filename) { Result ret = 0; @@ -185,7 +182,7 @@ Result FS_Remove(FS_Archive archive, const char * filename) return 0; } -Result FS_Rmdir(FS_Archive archive, const char * path) +Result FS_Rmdir(FS_Archive archive, const char *path) { Result ret = 0; @@ -195,7 +192,7 @@ Result FS_Rmdir(FS_Archive archive, const char * path) return 0; } -Result FS_RmdirRecursive(FS_Archive archive, const char * path) +Result FS_RmdirRecursive(FS_Archive archive, const char *path) { Result ret = 0; @@ -205,7 +202,7 @@ Result FS_RmdirRecursive(FS_Archive archive, const char * path) return 0; } -Result FS_RenameFile(FS_Archive archive, const char * old_filename, const char * new_filename) +Result FS_RenameFile(FS_Archive archive, const char *old_filename, const char *new_filename) { Result ret = 0; @@ -215,7 +212,7 @@ Result FS_RenameFile(FS_Archive archive, const char * old_filename, const char * return 0; } -Result FS_RenameDir(FS_Archive archive, const char * old_filename, const char * new_filename) +Result FS_RenameDir(FS_Archive archive, const char *old_filename, const char *new_filename) { Result ret = 0; @@ -225,7 +222,7 @@ Result FS_RenameDir(FS_Archive archive, const char * old_filename, const char * return 0; } -Result FS_Open(Handle * handle, FS_Archive archive, const char * path, u32 flags) +Result FS_Open(Handle *handle, FS_Archive archive, const char *path, u32 flags) { Result ret = 0; @@ -235,7 +232,7 @@ Result FS_Open(Handle * handle, FS_Archive archive, const char * path, u32 flags return 0; } -Result FS_Read(FS_Archive archive, const char * path, u64 size, char * buf) +Result FS_Read(FS_Archive archive, const char *path, u64 size, char *buf) { Handle handle; Result ret = 0; @@ -254,7 +251,7 @@ Result FS_Read(FS_Archive archive, const char * path, u64 size, char * buf) return 0; } -Result FS_Write(FS_Archive archive, const char * path, const char * buf) +Result FS_Write(FS_Archive archive, const char *path, const char *buf) { Handle handle; Result ret = 0; @@ -282,4 +279,43 @@ Result FS_Write(FS_Archive archive, const char * path, const char * buf) return ret; return 0; -} \ No newline at end of file +} + +/*static Result FS_GetFileTimestampRaw(FS_Archive archive, const char *path, u64 *mtime) +{ + Result ret = 0; + u16 path_utf16[256] = {0}; + + utf8_to_utf16(path_utf16, path, 256); + + if (R_FAILED(ret = FSUSER_ControlArchive(archive, ARCHIVE_ACTION_GET_TIMESTAMP, path_utf16, sizeof(path_utf16), mtime, sizeof(*mtime)))) + return ret; + + *mtime /= 1000; + *mtime += 946684800; + + return 0; +}*/ + +char *FS_GetFileTimestamp(FS_Archive archive, char *path) +{ + static char timeStr[20]; + u64 mtime = 0; + + if (R_SUCCEEDED(sdmc_getmtime(path, &mtime))) + { + time_t mt = mtime; + struct tm *timeStruct = gmtime(&mt); + + int hours = timeStruct->tm_hour; + int minutes = timeStruct->tm_min; + + int day = timeStruct->tm_mday; + int month = timeStruct->tm_mon + 1; // January being 0 + int year = timeStruct->tm_year + 1900; + + snprintf(timeStr, sizeof(timeStr), "%d/%d/%d %2i:%02i", year, month, day, hours, minutes); + } + + return timeStr; +} diff --git a/source/pp2d/lodepng.c b/source/graphics/lodepng.c similarity index 97% rename from source/pp2d/lodepng.c rename to source/graphics/lodepng.c index 98a8376..6568bba 100644 --- a/source/pp2d/lodepng.c +++ b/source/graphics/lodepng.c @@ -1,5 +1,5 @@ /* -LodePNG version 20180114 +LodePNG version 20180611 Copyright (c) 2005-2018 Lode Vandevenne @@ -39,7 +39,7 @@ Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for #pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/ #endif /*_MSC_VER */ -const char* LODEPNG_VERSION_STRING = "20180114"; +const char* LODEPNG_VERSION_STRING = "20180611"; /* This source file is built up in the following large parts. The code sections @@ -62,11 +62,17 @@ from here.*/ #ifdef LODEPNG_COMPILE_ALLOCATORS static void* lodepng_malloc(size_t size) { +#ifdef LODEPNG_MAX_ALLOC + if(size > LODEPNG_MAX_ALLOC) return 0; +#endif return malloc(size); } static void* lodepng_realloc(void* ptr, size_t new_size) { +#ifdef LODEPNG_MAX_ALLOC + if(new_size > LODEPNG_MAX_ALLOC) return 0; +#endif return realloc(ptr, new_size); } @@ -86,6 +92,8 @@ void lodepng_free(void* ptr); /* ////////////////////////////////////////////////////////////////////////// */ /* ////////////////////////////////////////////////////////////////////////// */ +#define LODEPNG_MAX(a, b) (((a) > (b)) ? (a) : (b)) + /* Often in case of an error a value is assigned to a variable and then it breaks out of a loop (to go to the cleanup phase of a function). This macro does that. @@ -1455,11 +1463,11 @@ static void updateHashChain(Hash* hash, size_t wpos, unsigned hashval, unsigned { hash->val[wpos] = (int)hashval; if(hash->head[hashval] != -1) hash->chain[wpos] = hash->head[hashval]; - hash->head[hashval] = (unsigned)wpos; + hash->head[hashval] = (int)wpos; hash->zeros[wpos] = numzeros; if(hash->headz[numzeros] != -1) hash->chainz[wpos] = hash->headz[numzeros]; - hash->headz[numzeros] = (unsigned)wpos; + hash->headz[numzeros] = (int)wpos; } /* @@ -2090,13 +2098,13 @@ static unsigned deflate(unsigned char** out, size_t* outsize, static unsigned update_adler32(unsigned adler, const unsigned char* data, unsigned len) { - unsigned s1 = adler & 0xffff; - unsigned s2 = (adler >> 16) & 0xffff; + unsigned s1 = adler & 0xffff; + unsigned s2 = (adler >> 16) & 0xffff; while(len > 0) { - /*at least 5550 sums can be done before the sums overflow, saving a lot of module divisions*/ - unsigned amount = len > 5550 ? 5550 : len; + /*at least 5552 sums can be done before the sums overflow, saving a lot of module divisions*/ + unsigned amount = len > 5552 ? 5552 : len; len -= amount; while(amount > 0) { @@ -2621,15 +2629,10 @@ static int lodepng_color_mode_equal(const LodePNGColorMode* a, const LodePNGColo if(a->key_g != b->key_g) return 0; if(a->key_b != b->key_b) return 0; } - /*if one of the palette sizes is 0, then we consider it to be the same as the - other: it means that e.g. the palette was not given by the user and should be - considered the same as the palette inside the PNG.*/ - if(1/*a->palettesize != 0 && b->palettesize != 0*/) { - if(a->palettesize != b->palettesize) return 0; - for(i = 0; i != a->palettesize * 4; ++i) - { - if(a->palette[i] != b->palette[i]) return 0; - } + if(a->palettesize != b->palettesize) return 0; + for(i = 0; i != a->palettesize * 4; ++i) + { + if(a->palette[i] != b->palette[i]) return 0; } return 1; } @@ -2705,32 +2708,75 @@ unsigned lodepng_can_have_alpha(const LodePNGColorMode* info) || lodepng_has_palette_alpha(info); } -size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color) +size_t lodepng_get_raw_size_lct(unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) { - /*will not overflow for any color type if roughly w * h < 268435455*/ - size_t bpp = lodepng_get_bpp(color); - size_t n = w * h; + size_t bpp = lodepng_get_bpp_lct(colortype, bitdepth); + size_t n = (size_t)w * (size_t)h; return ((n / 8) * bpp) + ((n & 7) * bpp + 7) / 8; } -size_t lodepng_get_raw_size_lct(unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) +size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color) { - /*will not overflow for any color type if roughly w * h < 268435455*/ - size_t bpp = lodepng_get_bpp_lct(colortype, bitdepth); - size_t n = w * h; - return ((n / 8) * bpp) + ((n & 7) * bpp + 7) / 8; + return lodepng_get_raw_size_lct(w, h, color->colortype, color->bitdepth); } #ifdef LODEPNG_COMPILE_PNG #ifdef LODEPNG_COMPILE_DECODER -/*in an idat chunk, each scanline is a multiple of 8 bits, unlike the lodepng output buffer*/ + +/*in an idat chunk, each scanline is a multiple of 8 bits, unlike the lodepng output buffer, +and in addition has one extra byte per line: the filter byte. So this gives a larger +result than lodepng_get_raw_size. */ static size_t lodepng_get_raw_size_idat(unsigned w, unsigned h, const LodePNGColorMode* color) { - /*will not overflow for any color type if roughly w * h < 268435455*/ size_t bpp = lodepng_get_bpp(color); - size_t line = ((w / 8) * bpp) + ((w & 7) * bpp + 7) / 8; - return h * line; + /* + 1 for the filter byte, and possibly plus padding bits per line */ + size_t line = ((size_t)(w / 8) * bpp) + 1 + ((w & 7) * bpp + 7) / 8; + return (size_t)h * line; +} + +/* Safely check if multiplying two integers will overflow (no undefined +behavior, compiler removing the code, etc...) and output result. */ +static int lodepng_mulofl(size_t a, size_t b, size_t* result) +{ + *result = a * b; /* Unsigned multiplication is well defined and safe in C90 */ + return (a != 0 && *result / a != b); +} + +/* Safely check if adding two integers will overflow (no undefined +behavior, compiler removing the code, etc...) and output result. */ +static int lodepng_addofl(size_t a, size_t b, size_t* result) +{ + *result = a + b; /* Unsigned addition is well defined and safe in C90 */ + return *result < a; +} + +/*Safely checks whether size_t overflow can be caused due to amount of pixels. +This check is overcautious rather than precise. If this check indicates no overflow, +you can safely compute in a size_t (but not an unsigned): +-(size_t)w * (size_t)h * 8 +-amount of bytes in IDAT (including filter, padding and Adam7 bytes) +-amount of bytes in raw color model +Returns 1 if overflow possible, 0 if not. +*/ +static int lodepng_pixel_overflow(unsigned w, unsigned h, + const LodePNGColorMode* pngcolor, const LodePNGColorMode* rawcolor) +{ + size_t bpp = LODEPNG_MAX(lodepng_get_bpp(pngcolor), lodepng_get_bpp(rawcolor)); + size_t numpixels, total; + size_t line; /* bytes per line in worst case */ + + if(lodepng_mulofl((size_t)w, (size_t)h, &numpixels)) return 1; + if(lodepng_mulofl(numpixels, 8, &total)) return 1; /* bit pointer with 8-bit color, or 8 bytes per channel color */ + + /* Bytes per scanline with the expression "(w / 8) * bpp) + ((w & 7) * bpp + 7) / 8" */ + if(lodepng_mulofl((size_t)(w / 8), bpp, &line)) return 1; + if(lodepng_addofl(line, ((w & 7) * bpp + 7) / 8, &line)) return 1; + + if(lodepng_addofl(line, 5, &line)) return 1; /* 5 bytes overhead per line: 1 filterbyte, 4 for Adam7 worst case */ + if(lodepng_mulofl(line, h, &total)) return 1; /* Total bytes in worst case */ + + return 0; /* no overflow */ } #endif /*LODEPNG_COMPILE_DECODER*/ #endif /*LODEPNG_COMPILE_PNG*/ @@ -3462,7 +3508,7 @@ unsigned lodepng_convert(unsigned char* out, const unsigned char* in, { size_t i; ColorTree tree; - size_t numpixels = w * h; + size_t numpixels = (size_t)w * (size_t)h; unsigned error = 0; if(lodepng_color_mode_equal(mode_out, mode_in)) @@ -3476,7 +3522,7 @@ unsigned lodepng_convert(unsigned char* out, const unsigned char* in, { size_t palettesize = mode_out->palettesize; const unsigned char* palette = mode_out->palette; - size_t palsize = 1u << mode_out->bitdepth; + size_t palsize = (size_t)1u << mode_out->bitdepth; /*if the user specified output palette but did not give the values, assume they want the values of the input color type (assuming that one is palette). Note that we never create a new palette ourselves.*/ @@ -3484,6 +3530,15 @@ unsigned lodepng_convert(unsigned char* out, const unsigned char* in, { palettesize = mode_in->palettesize; palette = mode_in->palette; + /*if the input was also palette with same bitdepth, then the color types are also + equal, so copy literally. This to preserve the exact indices that were in the PNG + even in case there are duplicate colors in the palette.*/ + if (mode_in->colortype == LCT_PALETTE && mode_in->bitdepth == mode_out->bitdepth) + { + size_t numbytes = lodepng_get_raw_size(w, h, mode_in); + for(i = 0; i != numbytes; ++i) out[i] = in[i]; + return 0; + } } if(palettesize < palsize) palsize = palettesize; color_tree_init(&tree); @@ -3573,7 +3628,7 @@ unsigned lodepng_get_color_profile(LodePNGColorProfile* profile, unsigned error = 0; size_t i; ColorTree tree; - size_t numpixels = w * h; + size_t numpixels = (size_t)w * (size_t)h; unsigned colored_done = lodepng_is_greyscale_type(mode) ? 1 : 0; unsigned alpha_done = lodepng_can_have_alpha(mode) ? 0 : 1; @@ -3768,14 +3823,16 @@ unsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out, { LodePNGColorProfile prof; unsigned error = 0; - unsigned i, n, palettebits, palette_ok; + unsigned palettebits, palette_ok; + size_t i, n; + size_t numpixels = (size_t)w * (size_t)h; lodepng_color_profile_init(&prof); error = lodepng_get_color_profile(&prof, image, w, h, mode_in); if(error) return error; mode_out->key_defined = 0; - if(prof.key && w * h <= 16) + if(prof.key && numpixels <= 16) { prof.alpha = 1; /*too few pixels to justify tRNS chunk overhead*/ prof.key = 0; @@ -3784,7 +3841,7 @@ unsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out, n = prof.numcolors; palettebits = n <= 2 ? 1 : (n <= 4 ? 2 : (n <= 16 ? 4 : 8)); palette_ok = n <= 256 && prof.bits <= 8; - if(w * h < n * 2) palette_ok = 0; /*don't add palette overhead if image has only a few pixels*/ + if(numpixels < n * 2) palette_ok = 0; /*don't add palette overhead if image has only a few pixels*/ if(!prof.colored && prof.bits <= palettebits) palette_ok = 0; /*grey is less overhead*/ if(palette_ok) @@ -4531,7 +4588,6 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h, ucvector idat; /*the data from idat chunks*/ ucvector scanlines; size_t predict; - size_t numpixels; size_t outsize = 0; /*for unknown chunk order*/ @@ -4546,13 +4602,10 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h, state->error = lodepng_inspect(w, h, state, in, insize); /*reads header and resets other parameters in state->info_png*/ if(state->error) return; - numpixels = *w * *h; - - /*multiplication overflow*/ - if(*h != 0 && numpixels / *h != *w) CERROR_RETURN(state->error, 92); - /*multiplication overflow possible further below. Allows up to 2^31-1 pixel - bytes with 16-bit RGBA, the rest is room for filter bytes.*/ - if(numpixels > 268435455) CERROR_RETURN(state->error, 92); + if(lodepng_pixel_overflow(*w, *h, &state->info_png.color, &state->info_raw)) + { + CERROR_RETURN(state->error, 92); /*overflow possible due to amount of pixels*/ + } ucvector_init(&idat); chunk = &in[33]; /*first byte of the first chunk after the header*/ @@ -4591,7 +4644,9 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h, if(lodepng_chunk_type_equals(chunk, "IDAT")) { size_t oldsize = idat.size; - if(!ucvector_resize(&idat, oldsize + chunkLength)) CERROR_BREAK(state->error, 83 /*alloc fail*/); + size_t newsize; + if(lodepng_addofl(oldsize, chunkLength, &newsize)) CERROR_BREAK(state->error, 95); + if(!ucvector_resize(&idat, newsize)) CERROR_BREAK(state->error, 83 /*alloc fail*/); for(i = 0; i != chunkLength; ++i) idat.data[oldsize + i] = data[i]; #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS critical_pos = 3; @@ -4694,21 +4749,20 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h, If the decompressed size does not match the prediction, the image must be corrupt.*/ if(state->info_png.interlace_method == 0) { - /*The extra *h is added because this are the filter bytes every scanline starts with*/ - predict = lodepng_get_raw_size_idat(*w, *h, &state->info_png.color) + *h; + predict = lodepng_get_raw_size_idat(*w, *h, &state->info_png.color); } else { /*Adam-7 interlaced: predicted size is the sum of the 7 sub-images sizes*/ const LodePNGColorMode* color = &state->info_png.color; predict = 0; - predict += lodepng_get_raw_size_idat((*w + 7) >> 3, (*h + 7) >> 3, color) + ((*h + 7) >> 3); - if(*w > 4) predict += lodepng_get_raw_size_idat((*w + 3) >> 3, (*h + 7) >> 3, color) + ((*h + 7) >> 3); - predict += lodepng_get_raw_size_idat((*w + 3) >> 2, (*h + 3) >> 3, color) + ((*h + 3) >> 3); - if(*w > 2) predict += lodepng_get_raw_size_idat((*w + 1) >> 2, (*h + 3) >> 2, color) + ((*h + 3) >> 2); - predict += lodepng_get_raw_size_idat((*w + 1) >> 1, (*h + 1) >> 2, color) + ((*h + 1) >> 2); - if(*w > 1) predict += lodepng_get_raw_size_idat((*w + 0) >> 1, (*h + 1) >> 1, color) + ((*h + 1) >> 1); - predict += lodepng_get_raw_size_idat((*w + 0), (*h + 0) >> 1, color) + ((*h + 0) >> 1); + predict += lodepng_get_raw_size_idat((*w + 7) >> 3, (*h + 7) >> 3, color); + if(*w > 4) predict += lodepng_get_raw_size_idat((*w + 3) >> 3, (*h + 7) >> 3, color); + predict += lodepng_get_raw_size_idat((*w + 3) >> 2, (*h + 3) >> 3, color); + if(*w > 2) predict += lodepng_get_raw_size_idat((*w + 1) >> 2, (*h + 3) >> 2, color); + predict += lodepng_get_raw_size_idat((*w + 1) >> 1, (*h + 1) >> 2, color); + if(*w > 1) predict += lodepng_get_raw_size_idat((*w + 0) >> 1, (*h + 1) >> 1, color); + predict += lodepng_get_raw_size_idat((*w + 0), (*h + 0) >> 1, color); } if(!state->error && !ucvector_reserve(&scanlines, predict)) state->error = 83; /*alloc fail*/ if(!state->error) @@ -5697,7 +5751,7 @@ unsigned lodepng_encode(unsigned char** out, size_t* outsize, if(!lodepng_color_mode_equal(&state->info_raw, &info.color)) { unsigned char* converted; - size_t size = (w * h * (size_t)lodepng_get_bpp(&info.color) + 7) / 8; + size_t size = ((size_t)w * (size_t)h * (size_t)lodepng_get_bpp(&info.color) + 7) / 8; converted = (unsigned char*)lodepng_malloc(size); if(!converted && size) state->error = 83; /*alloc fail*/ @@ -6010,9 +6064,10 @@ const char* lodepng_error_text(unsigned code) /*the windowsize in the LodePNGCompressSettings. Requiring POT(==> & instead of %) makes encoding 12% faster.*/ case 90: return "windowsize must be a power of two"; case 91: return "invalid decompressed idat size"; - case 92: return "too many pixels, not supported"; + case 92: return "integer overflow due to too many pixels"; case 93: return "zero width or height is invalid"; case 94: return "header chunk must have a size of 13 bytes"; + case 95: return "integer overflow with combined idat chunk size"; } return "unknown error code"; } diff --git a/source/misc/keyboard.c b/source/keyboard.c similarity index 91% rename from source/misc/keyboard.c rename to source/keyboard.c index 20f493c..712c792 100644 --- a/source/misc/keyboard.c +++ b/source/keyboard.c @@ -4,13 +4,13 @@ #include "keyboard.h" -char * keyboard_3ds_get(int maxTextLength, const char* initialText, const char* hintText) +char *OSK_Get(int maxTextLength, const char *initialText, const char *hintText) { static SwkbdState swkbd; static SwkbdStatusData swkbdStatus; static SwkbdLearningData swkbdLearning; - char * str = malloc(maxTextLength); + char *str = malloc(maxTextLength); memset(str, 0, maxTextLength); swkbdInit(&swkbd, SWKBD_TYPE_NORMAL, 2, maxTextLength); diff --git a/source/language.c b/source/language.c deleted file mode 100644 index e8e93e2..0000000 --- a/source/language.c +++ /dev/null @@ -1,194 +0,0 @@ -#include "language.h" - -/* - The languages are in the order based on CFG_Language: - - 0. Japanese - 1. English - 2. French - 3. German - 4. Italian - 5. Spanish - 6. Simplified Chinese - 7. Korean - 8. Dutch - 9. Portugese - 10. Russian - 11. Traditional Chinese -*/ - -const char lang_welcome[][3][100] = -{ - {"こんにちは", "ご機嫌よう", "今日は"}, - {"Hello there", "How are you today?", "Today is"}, - {"Allo", "Comment allez-vous aujourd'hui?", "Aujourd'hui, c'est"}, - {"Hallo", "Wie geht es dir heute?", "Heute ist"}, - {"Ciao", "Come stai?", "Oggi è"}, - {"Hola", "¿Cómo estás?", "Hoy es"}, - {"你好!", "今天过得怎么样?", "今天是"}, - {"안녕하세요!", "오늘 하루는 어떠세요?", "오늘은 "}, - {"Hallo", "Hoe gaat het?", "Vandaag is het"}, - {"Olá!", "Como está hoje?", "Hoje é"}, - {"Привет", "Как поживаешь?", "Сегодня"}, - {"嗨", "今天好嗎?", "今天是"} -}; - -const char lang_months[][12][50] = -{ - {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}, - {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}, - {"Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"}, - {"Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"}, - {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}, - {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}, - {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}, - {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}, - {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}, - {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}, - {"Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"}, - {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"} -}; - -const char lang_days[][7][50] = -{ - {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}, - {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}, - {"Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"}, - {"Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"}, - {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}, - {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}, - {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}, - {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}, - {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}, - {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}, - {"Воскресенье", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота"}, - {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"} -}; - -const char lang_files[][11][50] = -{ - {"Parent folder", "Folder", "APP", "Payload", "archive/zip", "archive/rar", "image/png", "image/jpeg", "audio/mpeg", "TEXT", "FILE"}, - {"Parent folder", "Folder", "APP", "Payload", "archive/zip", "archive/rar", "image/png", "image/jpeg", "audio/mpeg", "TEXT", "FILE"}, - {"Parent folder", "Folder", "APP", "Payload", "archive/zip", "archive/rar", "image/png", "image/jpeg", "audio/mpeg", "TEXT", "FILE"}, - {"Parent folder", "Folder", "APP", "Payload", "archive/zip", "archive/rar", "image/png", "image/jpeg", "audio/mpeg", "TEXT", "FILE"}, - {"Parent folder", "Folder", "APP", "Payload", "archive/zip", "archive/rar", "image/png", "image/jpeg", "audio/mpeg", "TEXT", "FILE"}, - {"Parent folder", "Folder", "APP", "Payload", "archive/zip", "archive/rar", "image/png", "image/jpeg", "audio/mpeg", "TEXT", "FILE"}, - {"Parent folder", "Folder", "APP", "Payload", "archive/zip", "archive/rar", "image/png", "image/jpeg", "audio/mpeg", "TEXT", "FILE"}, - {"Parent folder", "Folder", "APP", "Payload", "archive/zip", "archive/rar", "image/png", "image/jpeg", "audio/mpeg", "TEXT", "FILE"}, - {"Parent folder", "Folder", "APP", "Payload", "archive/zip", "archive/rar", "image/png", "image/jpeg", "audio/mpeg", "TEXT", "FILE"}, - {"Parent folder", "Folder", "APP", "Payload", "archive/zip", "archive/rar", "image/png", "image/jpeg", "audio/mpeg", "TEXT", "FILE"}, - {"Parent folder", "Folder", "APP", "Payload", "archive/zip", "archive/rar", "image/png", "image/jpeg", "audio/mpeg", "TEXT", "FILE"}, - {"Parent folder", "Folder", "APP", "Payload", "archive/zip", "archive/rar", "image/png", "image/jpeg", "audio/mpeg", "TEXT", "FILE"} -}; - -const char lang_options[][9][100] = -{ - {"アクション", "プロパティ", "名前を変更", "フォルダを作る", "コピー", "削除", "切り取る", "Paste", "キャンセル"}, - {"Actions", "Properties", "Rename", "New folder", "Copy", "Delete", "Cut", "Paste", "CANCEL"}, - {"Actions", "Propriétés", "Renommer", "Nouveau dossier", "Copier", "Supprimer", "Couper", "Paste", "ANNULER"}, - {"Aktionen", "Eigenschaften", "Umbenennen", "Neuer Ordner", "Kopieren", "Löschen", "Ausschneiden", "Paste", "ABBRECHEN"}, - {"Azioni", "Proprietà", "Rinomina", "Nuova cartella", "Copia", "Elimina", "Taglia", "Paste", "ANNULLA"}, - {"Acciones", "Propiedades", "Renombrar", "Nueva carpeta", "Copiar", "Eliminar", "Cortar", "Paste", "CANCELAR"}, - {"操作", "属性", "重命名", "新建文件夹", "复制", "删除", "剪切", "Paste", "取消"}, - {"작업", "속성", "이름 바꾸기", "새 폴더", "복사", "삭제", "잘라내기", "Paste", "취소"}, - {"Actie's", "Instellingen", "Naam wijzigen", "Nieuwe map", "Kopiëren", "Verwijderen", "Knippen", "Paste", "ANNULEREN"}, - {"Ações", "Propriedades", "Renomear", "Nova pasta", "Copiar", "Eliminar", "Recortar", "Paste", "CANCELAR"}, - {"Действия", "Свойства", "Переименовать", "Новая папка", "Копировать", "Удалить", "Вырезать", "Paste", "Отменить"}, - {"動作", "屬性", "重新命名", "新資料夾", "複製", "刪除", "剪下", "Paste", "取消"} -}; - -const char lang_properties[][7][100] = -{ - {"プロパティ", "詳細", "名前", "親ディレクトリ", "タイプ", "Size", "OK"}, - {"Properties", "INFO", "Name", "Parent", "Type", "Size", "OK"}, - {"Propriétés", "INFO", "Nom", "Parent", "Type", "Size", "OK"}, - {"Eigenschaften", "INFO", "Name", "Übergeordnet", "Typ", "Size", "OK"}, - {"Proprietà", "INFO", "Nome", "Cartella", "Tipo", "Size", "OK"}, - {"Propiedades", "Información", "Nombre", "Padre", "Tipo", "Size", "Confirmar"}, - {"属性", "信息", "名称", "父目录", "类型", "Size", "OK"}, - {"속성", "정보", "이름", "부모", "타입", "Size", "확인"}, - {"Instellingen", "INFO", "Naam", "Omhoog", "Soort", "Size", "Oke"}, - {"Propriedades", "INFO", "Nome", "Local", "Tipo", "Size", "OK"}, - {"Свойства", "ИНФО", "Название", "Вверх", "Тип", "Size", "OK"}, - {"屬性", "資訊", "名字", "根目錄", "型態", "Size", "OK"} -}; - -const char lang_deletion[][5][100] = -{ - {"削除を確認", "削除されたファイルは引き戻せません", "削除しますか", "いいえ", "はい"}, - {"Confirm deletion", "This action cannot be undone.", "Do you want to continue", "NO", "YES"}, - {"Confirmer la supprimation", "Cette action est irréversible.", "Voulez-vous continuer", "NON", "OUI"}, - {"Löschen bestätigen", "Diese Aktion kann nicht rückgängig gemacht werden.", "Fortsetzen?", "NEIN", "JA"}, - {"Conferma eliminazione", "Questa azione non può essere ripristinata.", "Vuoi continuare", "NO", "SI"}, - {"Confirmar borrado", "Esta acción no puede ser revertida", "¿Desea continuar?", "NO", "SÍ"}, - {"确认删除", "该操作结果不可逆", "是否确认继续?", "取消", "确认"}, - {"삭제 확인", "삭제한 파일은 되돌릴 수 없습니다.", "계속 할까요?", "아니요", "예"}, - {"Bevestig Verwijdering", "Deze actie kan niet ongedaan worden gemaakt.", "Weet u het zeker?", "NEE(N)", "JA"}, - {"Eliminar arquivo", "Esta ação não pode ser anulada.", "Deseja continuar?", "NÃO", "SIM"}, - {"Подтвердите удаление", "Вы не сможете восстановить удаленные файлы.", "Хотите продолжить", "НЕТ", "ДА"}, - {"確認刪除", "這個動作無法復原", "你希望繼續嗎", "否", "是"} -}; - -const char lang_settings[][9][100] = -{ - {"一般的", "システムファイル防御", "大切なファイルの削除を防止します", "カスタムテーマ", "現在のテーマ:", "Recycle Bin", "Enable 3D-Shell's recyle bin."}, - {"General", "Display filename in Gallery", "Toggles filename display in Gallery.", "Custom themes", "Current:", "Recycle Bin", "Enable 3D-Shell's recyle bin.", "Show hidden files", "Displays hidden files in file browser."}, - {"Général", "Protection de fichier système", "Empêche la supprimation des fichiers systèmes.", "Thèmes personnalisés", "Actuel:", "Recycle Bin", "Enable 3D-Shell's recyle bin."}, - {"Allgemein", "Systemdateien-Schutz", "Verhindert das Löschen von Systemdateien.", "Eigene Themen", "Aktuell:", "Recycle Bin", "Enable 3D-Shell's recyle bin."}, - {"Generale", "Protezione file di sistema", "Previene l'eliminazione di file di sistema.", "Temi custom", "Attuale:", "Recycle Bin", "Enable 3D-Shell's recyle bin."}, - {"General", "Protección de archivos del sistema", "Previene la eliminación de archivos del sistema", "Temas personalizados", "Actual:", "Recycle Bin", "Enable 3D-Shell's recyle bin."}, - {"通用", "系统文件保护", "防止系统文件被删除。", "自定义主题", "当前:", "Recycle Bin", "Enable 3D-Shell's recyle bin."}, - {"일반", "시스템 파일 보호", "시스템 파일의 삭제를 방지합니다.", "커스텀 테마", "현재:", "Recycle Bin", "Enable 3D-Shell's recyle bin."}, - {"Algemeen", "System file protection", "Voorkomt het verwijderen van systeembestanden.", "Aangepaste Thema's", "Momenteel:", "Recycle Bin", "Enable 3D-Shell's recyle bin."}, - {"Geral", "Proteção de arquivos do sistema", "Prevenir eliminação de arquivos do sistema", "Customização", "Tema atual:", "Recycle Bin", "Enable 3D-Shell's recyle bin."}, - {"Общее", "Защита файловой системы", "Предотвращать удаление системных файлов.", "Темы", "Текущая:", "Recycle Bin", "Enable 3D-Shell's recyle bin."}, - {"一般", "系統資料保護", "保護系統資料不被刪除", "自製主題", "當前:", "Recycle Bin", "Enable 3D-Shell's recyle bin."} -}; - -const char lang_themes[][1][100] = -{ - {"テーマを選択してください"}, - {"Select a theme"}, - {"Choisissez un thème"}, - {"Thema auswählen"}, - {"Seleziona un tema"}, - {"Selecciona un tema"}, - {"选择一个主题"}, - {"테마 선택"}, - {"Selecteer een thema"}, - {"Selecione um tema"}, - {"Выберите тему"}, - {"請選擇一個主題"} -}; - -const char lang_ftp[][5][100] = -{ - {"FTP起動しました", "この状態ではブラウザが使えません", "FTPアイコンをタッチすると、FTP接続が終了します", "Failed to initialize FTP.", "WiFi not enabled."}, - {"FTP initialized", "File browser cannot be accesed at this time.", "Tap the FTP icon to disable the FTP connection.", "Failed to initialize FTP.", "WiFi not enabled."}, - {"FTP initialisé", "Le navigateur de fichiers ne peut pas être accédé en ce moment.", "Appuyer sur l'icône FTP pour désactiver la connection de FTP.", "Failed to initialize FTP.", "WiFi not enabled."}, - {"FTP gestartet", "Auf den Dateibrowser kann zur Zeit nicht zugegriffen werden.", "Wähle das FTP-Icon aus, um die FTP-Verbindung zu deaktivieren.", "Failed to initialize FTP.", "WiFi not enabled."}, - {"Avviato FTP", "Non è possibile accedere al momento al browser di file.", "Tocca l'icona FTP per disattivare la connessione FTP.", "Failed to initialize FTP.", "WiFi not enabled."}, - {"FTP inicializado", "El explorador de archivos no puede ser utilizado actualmente.", "Toca el ícono de FTP para desactivar la conexión FTP.", "Failed to initialize FTP.", "WiFi not enabled."}, - {"FTP 初始化完毕", "文件浏览器当前不可用。", "点击FTP图标以禁用FTP连接。", "Failed to initialize FTP.", "WiFi not enabled."}, - {"FTP 초기화 완료", "현재는 파일 브라우저를 이용할 수 없습니다.", "FTP 아이콘을 탭해 FTP를 비활성화", "Failed to initialize FTP.", "WiFi not enabled."}, - {"FTP gestart", "Bestandsbeheer kan niet worden geopend op dit moment.", "Klik op de FTP icoon om de FTP service uit te zetten.", "Failed to initialize FTP.", "WiFi not enabled."}, - {"FPT inicializado", "O explorador de arquivos não poderá ser utilizado.", "Toque no ícone FTP para terminar a conexão.", "Failed to initialize FTP.", "WiFi not enabled."}, - {"FTP запущен", "В настоящий момент файловый браузер недоступен.", "Нажмите на иконку FTP для прерывания FTP соединения.", "Failed to initialize FTP.", "WiFi not enabled."}, - {"FTP初始化中", "目前無法取得檔案管理員的資料", "請點選FTP的按鈕來結束與FTP的連線", "Failed to initialize FTP.", "WiFi not enabled."} -}; - -const char lang_update[][4][100] = -{ - {"Checking for updates...", "Install failed", "Install success", "Exiting.."}, - {"Checking for updates...", "Install failed", "Install success", "Exiting.."}, - {"Vérification des mises à jour...", "Installation échouée", "Installation réussie", "Fermeture..."}, - {"Suche nach Updates...", "Installation fehlgeschlagen", "Installation erfolgreich", "Beenden..."}, - {"Checking for updates...", "Install failed", "Install success", "Exiting.."}, - {"Checking for updates...", "Install failed", "Install success", "Exiting.."}, - {"Checking for updates...", "Install failed", "Install success", "Exiting.."}, - {"Checking for updates...", "Install failed", "Install success", "Exiting.."}, - {"Checking for updates...", "Install failed", "Install success", "Exiting.."}, - {"Checking for updates...", "Install failed", "Install success", "Exiting.."}, - {"Проверка обновлений...", "Установка не удалась", "Успешная установка", "Выходим..."}, - {"Checking for updates...", "Install failed", "Install success", "Exiting.."} -}; \ No newline at end of file diff --git a/source/main.c b/source/main.c index df8da7c..e442c31 100644 --- a/source/main.c +++ b/source/main.c @@ -1,61 +1,74 @@ +#include #include <3ds.h> #include "common.h" +#include "config.h" #include "fs.h" -#include "language.h" -#include "menus/menu_main.h" -#include "menu_update.h" -#include "pp2d/pp2d.h" +#include "menu_main.h" +#include "C2D_helper.h" #include "textures.h" #include "utils.h" +static u32 cpu_time_limit = 0; + +static void Term_Services(void) +{ + Textures_Free(); + + if (Utils_IsN3DS()) + osSetSpeedupEnable(false); + + FS_CloseArchive(archive); + + C2D_TextBufDelete(sizeBuf); + C2D_TextBufDelete(dynamicBuf); + C2D_TextBufDelete(staticBuf); + + if (cpu_time_limit != UINT32_MAX) + APT_SetAppCpuTimeLimit(cpu_time_limit); + + C2D_Fini(); + C3D_Fini(); + gfxExit(); + romfsExit(); + ndspExit(); + amExit(); + acExit(); +} + static void Init_Services(void) { acInit(); amInit(); AM_QueryAvailableExternalTitleDatabase(NULL); - cfguInit(); - mcuHwcInit(); ndspInit(); ndspSetOutputMode(NDSP_OUTPUT_STEREO); - ptmuInit(); - pp2d_init(); romfsInit(); - - FS_OpenArchive(&archive, ARCHIVE_SDMC); + gfxInitDefault(); + C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); + C2D_Init(C2D_DEFAULT_MAX_OBJECTS); + C2D_Prepare(); if (Utils_IsN3DS()) osSetSpeedupEnable(true); + APT_GetAppCpuTimeLimit(&cpu_time_limit); APT_SetAppCpuTimeLimit(30); - Utils_MakeDirectories(); - Utils_LoadConfig(); - Utils_GetLastDirectory(); - - Load_Textures(); - - language = 1; //Utils_GetLanguage(); + staticBuf = C2D_TextBufNew(4096); + dynamicBuf = C2D_TextBufNew(4096); + sizeBuf = C2D_TextBufNew(4096); - BROWSE_STATE = STATE_SD; - MENU_DEFAULT_STATE = MENU_STATE_HOME; -} + RENDER_TOP = C2D_CreateScreenTarget(GFX_TOP, GFX_LEFT); + RENDER_BOTTOM = C2D_CreateScreenTarget(GFX_BOTTOM, GFX_LEFT); -static void Term_Services(void) -{ - if (Utils_IsN3DS()) - osSetSpeedupEnable(false); + FS_OpenArchive(&archive, ARCHIVE_SDMC); - FS_CloseArchive(archive); + FS_RecursiveMakeDir(archive, "/3ds/3DShell/"); - romfsExit(); - pp2d_exit(); - ptmuExit(); - ndspExit(); - mcuHwcExit(); - cfguExit(); - amExit(); - acExit(); + Textures_Load(); + Config_Load(); + Config_GetLastDirectory(); } int main(int argc, char *argv[]) @@ -68,6 +81,10 @@ int main(int argc, char *argv[]) return 0; } + MENU_STATE = MENU_STATE_HOME; + BROWSE_STATE = BROWSE_STATE_SD; Menu_Main(); Term_Services(); + + return 0; } diff --git a/source/menus/menu_delete.c b/source/menus/menu_delete.c deleted file mode 100644 index 42e4052..0000000 --- a/source/menus/menu_delete.c +++ /dev/null @@ -1,96 +0,0 @@ -#include "common.h" -#include "dir_list.h" -#include "fs.h" -#include "language.h" -#include "menu_delete.h" -#include "pp2d.h" -#include "textures.h" -#include "theme.h" -#include "touch.h" -#include "utils.h" - -struct colour BottomScreen_colour; -struct colour Options_title_text_colour; -struct colour Settings_title_text_colour; - -static Result FileOptions_Delete(void) -{ - File * file = Dirlist_GetFileIndex(position); - - if (file == NULL) - return -1; - - if (strncmp(file->name, "..", 2) == 0) - return -2; - - /*if ((recycleBin) && !(strstr(cwd, "/3ds/3DShell/bin/") != NULL)) - { - isMovingToBin = true; - char * buf = (char *)malloc(1024); - copy(COPY_DELETE_ON_FINISH); - strcpy(buf, cwd); - memset(cwd, 0, sizeof(cwd)); - sprintf(cwd, "/3ds/3DShell/bin/"); - paste(); - strcpy(cwd, buf); - free(buf); - return 0; - }*/ - - char path[1024]; // File path - - // Puzzle path - strcpy(path, cwd); - strcpy(path + strlen(path), file->name); - - Result ret = 0; - - if (file->isDir) // Delete folder - { - if (R_FAILED(ret = FS_RmdirRecursive(archive, path))) - return ret; - } - else // Delete file - { - if (R_FAILED(ret = FS_Remove(archive, path))) - return ret; - } - - return 0; -} - -void Menu_DisplayDeleteDialog(void) -{ - pp2d_draw_rectangle(0, 0, 320, 240, RGBA8(BottomScreen_colour.r, BottomScreen_colour.g, BottomScreen_colour.b, 255)); - - pp2d_draw_texture(TEXTURE_DIALOG, 20, 55); - - pp2d_draw_text(27, 72, 0.45f, 0.45f, RGBA8(Settings_title_text_colour.r, Settings_title_text_colour.g, Settings_title_text_colour.b, 255), lang_deletion[language][0]); - - pp2d_draw_text(206, 159, 0.45f, 0.45f, RGBA8(Settings_title_text_colour.r, Settings_title_text_colour.g, Settings_title_text_colour.b, 255), lang_deletion[language][3]); - pp2d_draw_text(255, 159, 0.45f, 0.45f, RGBA8(Settings_title_text_colour.r, Settings_title_text_colour.g, Settings_title_text_colour.b, 255), lang_deletion[language][4]); - - pp2d_draw_text(((320 - pp2d_get_text_width(lang_deletion[language][1], 0.45f, 0.45f)) / 2), 100, 0.45f, 0.45f, RGBA8(Options_title_text_colour.r, Options_title_text_colour.g, Options_title_text_colour.b, 255), lang_deletion[language][1]); - pp2d_draw_text(((320 - pp2d_get_text_width(lang_deletion[language][2], 0.45f, 0.45f)) / 2), 115, 0.45f, 0.45f, RGBA8(Options_title_text_colour.r, Options_title_text_colour.g, Options_title_text_colour.b, 255), lang_deletion[language][2]); -} - -void Menu_ControlDeleteDialog(u32 input) -{ - if ((input & KEY_A) || (touchInRect(240, 142, 320, 185))) - { - if (R_SUCCEEDED(FileOptions_Delete())) - { - Dirlist_PopulateFiles(true); - Dirlist_DisplayFiles(); - } - - wait(1); - MENU_DEFAULT_STATE = MENU_STATE_OPTIONS; - } - - else if ((input & KEY_B) || (touchInRect(136, 142, 239, 185))) - { - wait(1); - MENU_DEFAULT_STATE = MENU_STATE_OPTIONS; - } -} \ No newline at end of file diff --git a/source/menus/menu_file_options.c b/source/menus/menu_file_options.c deleted file mode 100644 index 3faa514..0000000 --- a/source/menus/menu_file_options.c +++ /dev/null @@ -1,448 +0,0 @@ -#include -#include - -#include "common.h" -#include "dir_list.h" -#include "fs.h" -#include "keyboard.h" -#include "language.h" -#include "menu_properties.h" -#include "menu_settings.h" -#include "pp2d.h" -#include "progress_bar.h" -#include "textures.h" -#include "theme.h" -#include "touch.h" -#include "utils.h" - -/* -* Copy Flags -*/ -#define COPY_FOLDER_RECURSIVE 2 -#define COPY_DELETE_ON_FINISH 1 -#define COPY_KEEP_ON_FINISH 0 -#define NOTHING_TO_COPY -1 - -struct colour Options_select_colour; -struct colour Options_text_colour; -struct colour Settings_title_text_colour; - -static int selectionX, selectionY; -static bool copy_enable, cut_enable; - -#define CAN_COPY (((copy_enable == false) && (cut_enable != true))) -#define CAN_CUT (((cut_enable == false) && (copy_enable != true))) - - -/* -* Copy Mode -* -1 : Nothing -* 0 : Copy -* 1 : Move -*/ -static int copymode = NOTHING_TO_COPY; -/* -* Copy Move Origin -*/ -static char copysource[1024]; -static char selected_file[255][255]; // 255 slots, of length 255 - -static Result FileOptions_CreateFolder(void) -{ - char * buf = (char *)malloc(256); - strcpy(buf, keyboard_3ds_get(256, "", "Enter name")); - - if (strncmp(buf, "", 1) == 0) - return -1; - - char path[500]; - strcpy(path, cwd); - strcat(path, buf); - free(buf); - - FS_RecursiveMakeDir(archive, path); - - Dirlist_PopulateFiles(true); - return 0; -} - -static Result FileOptions_RenameFile(void) -{ - Result ret = 0; - File * file = Dirlist_GetFileIndex(position); - - if (file == NULL) - return -1; - - if (strncmp(file->name, "..", 2) == 0) - return -2; - - char oldPath[500], newPath[500]; - - char * buf = (char *)malloc(256); - - strcpy(oldPath, cwd); - strcpy(newPath, cwd); - strcat(oldPath, file->name); - - strcpy(buf, keyboard_3ds_get(255, file->name, "Enter name")); - strcat(newPath, buf); - free(buf); - - if (file->isDir) - { - if (R_FAILED(ret = FS_RenameDir(archive, oldPath, newPath))) - return ret; - } - else - { - if (R_FAILED(ret = FS_RenameFile(archive, oldPath, newPath))) - return ret; - } - - Dirlist_PopulateFiles(true); - return 0; -} - -// Copy file from src to dst -int FileOptions_CopyFile(char * src, char * dst, bool displayAnim) -{ - int chunksize = (512 * 1024); // Chunk size - char * buffer = (char *)malloc(chunksize); // Reading buffer - - u64 totalwrite = 0; // Accumulated writing - u64 totalread = 0; // Accumulated reading - - int result = 0; // Result - - int in = open(src, O_RDONLY, 0777); // Open file for reading - u64 size = FS_GetFileSize(archive, src); - - // Opened file for reading - if (in >= 0) - { - if (FS_FileExists(archive, dst)) - FS_Remove(archive, dst); // Delete output file (if existing) - - int out = open(dst, O_WRONLY | O_CREAT | O_TRUNC, 0777); // Open output file for writing - - if (out >= 0) // Opened file for writing - { - u64 b_read = 0; // Read byte count - - // Copy loop (512KB at a time) - while((b_read = read(in, buffer, chunksize)) > 0) - { - totalread += b_read; // Accumulate read data - totalwrite += write(out, buffer, b_read); // Write data - - if (displayAnim) - ProgressBar_DisplayProgress(copymode == 1? "Moving" : "Copying", Utils_Basename(src), totalread, size); - } - - close(out); // Close output file - - if (totalread != totalwrite) // Insufficient copy - result = -3; - } - - else // Output open error - result = -2; - - close(in); // Close input file - } - - // Input open error - else - result = -1; - - free(buffer); // Free memory - return result; // Return result -} - -// Recursively copy file from src to dst -static Result FileOptions_CopyDir(char * src, char * dst) -{ - Handle dirHandle; - Result ret = 0; // Open working Directory - - // Opened directory - if (R_SUCCEEDED(ret = FSUSER_OpenDirectory(&dirHandle, archive, fsMakePath(PATH_ASCII, src)))) - { - FS_MakeDir(archive, dst); // Create output directory (is allowed to fail, we can merge folders after all) - - u32 entryCount = 0; - FS_DirectoryEntry* entries = (FS_DirectoryEntry*) calloc(MAX_FILES, sizeof(FS_DirectoryEntry)); - - if (R_SUCCEEDED(ret = FSDIR_Read(dirHandle, &entryCount, MAX_FILES, entries))) - { - u8 name[255] = {'\0'}; - for (u32 i = 0; i < entryCount; i++) - { - u16_to_u8(&name[0], entries[i].name, 254); - - if (strlen(name) > 0) - { - // Calculate buffer size - int insize = strlen(src) + strlen(name) + 2; - int outsize = strlen(dst) + strlen(name) + 2; - - // Allocate buffer - char * inbuffer = (char *)malloc(insize); - char * outbuffer = (char *)malloc(outsize); - - // Puzzle input path - strcpy(inbuffer, src); - inbuffer[strlen(inbuffer) + 1] = 0; - inbuffer[strlen(inbuffer)] = '/'; - strcpy(inbuffer + strlen(inbuffer), name); - - // Puzzle output path - strcpy(outbuffer, dst); - outbuffer[strlen(outbuffer) + 1] = 0; - outbuffer[strlen(outbuffer)] = '/'; - strcpy(outbuffer + strlen(outbuffer), name); - - if (entries[i].attributes & FS_ATTRIBUTE_DIRECTORY) // Another folder - FileOptions_CopyDir(inbuffer, outbuffer); // Copy folder (via recursion) - - else - { - if (R_FAILED(ret = ret = FileOptions_CopyFile(inbuffer, outbuffer, false))) // Copy file - return ret; - } - - // Free buffer - free(inbuffer); - free(outbuffer); - } - - ProgressBar_DisplayProgress(copymode == 1? "Moving" : "Copying", Utils_Basename(name), i, entryCount); - } - } - else - return ret; - - free(entries); - - if (R_FAILED(ret = FSDIR_Close(dirHandle))) // Close directory - return ret; - } - else - return ret; - - return 0; -} - -static void FileOptions_Copy(int flag) -{ - File * file = Dirlist_GetFileIndex(position); - - if (file == NULL) - return; - - // Copy file source - strcpy(copysource, cwd); - strcpy(copysource + strlen(copysource), file->name); - - if ((file->isDir) && (strncmp(file->name, "..", 2) != 0)) // If directory, add recursive folder flag - flag |= COPY_FOLDER_RECURSIVE; - - copymode = flag; // Set copy flags -} - -// Paste file or folder -static Result FileOptions_Paste(void) -{ - if (copymode == NOTHING_TO_COPY) // No copy source - return -1; - - // Source and target folder are identical - char * lastslash = NULL; - int i = 0; - - for(; i < strlen(copysource); i++) - if (copysource[i] == '/') - lastslash = copysource + i; - - char backup = lastslash[1]; - lastslash[1] = 0; - int identical = strcmp(copysource, cwd) == 0; - lastslash[1] = backup; - - if (identical) - return -2; - - char * filename = lastslash + 1; // Source filename - - int requiredlength = strlen(cwd) + strlen(filename) + 1; // Required target path buffer size - char * copytarget = (char *)malloc(requiredlength); // Allocate target path buffer - - // Puzzle target path - strcpy(copytarget, cwd); - strcpy(copytarget + strlen(copytarget), filename); - - Result ret = -3; // Return result - - // Recursive folder copy - if ((copymode & COPY_FOLDER_RECURSIVE) == COPY_FOLDER_RECURSIVE) - { - // Check files in current folder - File * node = files; for(; node != NULL; node = node->next) - { - if ((strcmp(filename, node->name) == 0) && (!node->isDir)) // Found a file matching the name (folder = ok, file = not) - return -4; // Error out - } - - ret = FileOptions_CopyDir(copysource, copytarget); // Copy folder recursively - - if ((R_SUCCEEDED(ret)) && (copymode & COPY_DELETE_ON_FINISH) == COPY_DELETE_ON_FINISH) - FS_RmdirRecursive(archive, copysource); // Delete dir - } - - // Simple file copy - else - { - ret = FileOptions_CopyFile(copysource, copytarget, true); // Copy file - - if ((R_SUCCEEDED(ret)) && (copymode & COPY_DELETE_ON_FINISH) == COPY_DELETE_ON_FINISH) - FS_Remove(archive, copysource); // Delete file - } - - // Paste success - if (R_SUCCEEDED(ret)) - { - memset(copysource, 0, sizeof(copysource)); // Erase cache data - copymode = NOTHING_TO_COPY; - } - - free(copytarget); // Free target path buffer - return ret; // Return result -} - -void Menu_DisplayFileOptions(void) -{ - pp2d_draw_texture(TEXTURE_OPTIONS, 37, 20); - - pp2d_draw_rectangle(37 + (selectionX * 123), 56 + (selectionY * 37), 123, 37, RGBA8(Options_select_colour.r, Options_select_colour.g, Options_select_colour.b, 255)); - - pp2d_draw_text(42, 36, 0.45f, 0.45f, RGBA8(Settings_title_text_colour.r, Settings_title_text_colour.g, Settings_title_text_colour.b, 255), lang_options[language][0]); - pp2d_draw_text(232, 196, 0.45f, 0.45f, RGBA8(Settings_title_text_colour.r, Settings_title_text_colour.g, Settings_title_text_colour.b, 255), lang_options[language][8]); - - pp2d_draw_text(47, 72, 0.45f, 0.45f, RGBA8(Options_text_colour.r, Options_text_colour.g, Options_text_colour.b, 255), lang_options[language][1]); - pp2d_draw_text(47, 109, 0.45f, 0.45f, RGBA8(Options_text_colour.r, Options_text_colour.g, Options_text_colour.b, 255), lang_options[language][3]); - pp2d_draw_text(47, 146, 0.45f, 0.45f, RGBA8(Options_text_colour.r, Options_text_colour.g, Options_text_colour.b, 255), lang_options[language][5]); - - pp2d_draw_text(170, 72, 0.45f, 0.45f, RGBA8(Options_text_colour.r, Options_text_colour.g, Options_text_colour.b, 255), lang_options[language][2]); - - if (copy_enable) - { - pp2d_draw_text(170, 109, 0.45f, 0.45f, RGBA8(Options_text_colour.r, Options_text_colour.g, Options_text_colour.b, 255), lang_options[language][7]); - pp2d_draw_text(170, 146, 0.45f, 0.45f, RGBA8(Options_text_colour.r, Options_text_colour.g, Options_text_colour.b, 255), lang_options[language][6]); - } - else if (cut_enable) - { - pp2d_draw_text(170, 146, 0.45f, 0.45f, RGBA8(Options_text_colour.r, Options_text_colour.g, Options_text_colour.b, 255), lang_options[language][7]); - pp2d_draw_text(170, 109, 0.45f, 0.45f, RGBA8(Options_text_colour.r, Options_text_colour.g, Options_text_colour.b, 255), lang_options[language][4]); - } - else - { - pp2d_draw_text(170, 109, 0.45f, 0.45f, RGBA8(Options_text_colour.r, Options_text_colour.g, Options_text_colour.b, 255), lang_options[language][4]); - pp2d_draw_text(170, 146, 0.45f, 0.45f, RGBA8(Options_text_colour.r, Options_text_colour.g, Options_text_colour.b, 255), lang_options[language][6]); - } -} - -void Menu_ControlFileOptions(u32 input) -{ - if ((input & KEY_TOUCH) && (touchInRect(37, 179, 282, 217))) // Cancel - { - wait(1); - copy_enable = false; - cut_enable = false; - MENU_DEFAULT_STATE = MENU_STATE_HOME; - } - - else if ((input & KEY_TOUCH) && (touchInRect(37, 56, 160, 93))) - { - selectionX = 0; - selectionY = 0; - wait(1); - - MENU_DEFAULT_STATE = MENU_STATE_PROPERTIES; - } - - else if ((input & KEY_TOUCH) && (touchInRect(37, 94, 160, 130))) - { - selectionX = 0; - selectionY = 1; - wait(1); - - FileOptions_CreateFolder(); - } - - else if ((input & KEY_TOUCH) && (touchInRect(161, 56, 284, 93))) - { - selectionX = 1; - selectionY = 0; - wait(1); - - FileOptions_RenameFile(); - } - - else if ((input & KEY_TOUCH) && (touchInRect(37, 131, 160, 167))) - { - //selectionX = 0; - //selectionY = 2; - wait(1); - - MENU_DEFAULT_STATE = MENU_STATE_DIALOG; - } - - if ((CAN_COPY) && (input & KEY_TOUCH) && (touchInRect(161, 94, 284, 130))) - { - selectionX = 1; - selectionY = 1; - wait(1); - - FileOptions_Copy(COPY_KEEP_ON_FINISH); - copy_enable = true; - } - - else if ((copy_enable) && (input & KEY_TOUCH) && (touchInRect(161, 94, 284, 130))) - { - selectionX = 0; - selectionY = 0; - wait(1); - - if (FileOptions_Paste() == 0) - { - copy_enable = false; - Dirlist_PopulateFiles(true); - Dirlist_DisplayFiles(); - } - } - - if ((CAN_CUT) && (input & KEY_TOUCH) && (touchInRect(161, 131, 284, 167))) - { - selectionX = 1; - selectionY = 2; - wait(1); - - FileOptions_Copy(COPY_DELETE_ON_FINISH); - cut_enable = true; - } - - else if ((cut_enable) && (input & KEY_TOUCH) && (touchInRect(161, 131, 284, 167))) - { - selectionX = 0; - selectionY = 0; - wait(1); - - if (FileOptions_Paste() == 0) - { - cut_enable = false; - Dirlist_PopulateFiles(true); - Dirlist_DisplayFiles(); - } - } -} \ No newline at end of file diff --git a/source/menus/menu_fileoptions.c b/source/menus/menu_fileoptions.c new file mode 100644 index 0000000..56a3573 --- /dev/null +++ b/source/menus/menu_fileoptions.c @@ -0,0 +1,735 @@ +#include +#include +#include +#include + +#include "C2D_helper.h" +#include "common.h" +#include "config.h" +#include "dirbrowse.h" +#include "fs.h" +#include "keyboard.h" +#include "progress_bar.h" +#include "menu_fileoptions.h" +#include "textures.h" +#include "touch.h" +#include "utils.h" + +/* +* Copy Flags +*/ +#define COPY_FOLDER_RECURSIVE 2 +#define COPY_DELETE_ON_FINISH 1 +#define COPY_KEEP_ON_FINISH 0 +#define NOTHING_TO_COPY -1 + +/* +* Copy Mode +* -1 : Nothing +* 0 : Copy +* 1 : Move +*/ +static int copymode = NOTHING_TO_COPY; +/* +* Copy Move Origin +*/ +static char copysource[1024]; + +static int delete_dialog_selection = 0, row = 0, column = 0; +static bool copy_status = false, cut_status = false; + +static float delete_confirm_width = 0, delete_confirm_height = 0; +static float delete_cancel_width = 0, delete_cancel_height = 0; + +static float properties_ok_width = 0, properties_ok_height = 0; +static float options_cancel_width = 0, options_cancel_height = 0; + +void FileOptions_ResetClipboard(void) +{ + multi_select_index = 0; + memset(multi_select, 0, sizeof(multi_select)); + memset(multi_select_indices, 0, sizeof(multi_select_indices)); + memset(multi_select_dir, 0, sizeof(multi_select_dir)); + memset(multi_select_paths, 0, sizeof(multi_select_paths)); +} + +static Result FileOptions_CreateFolder(void) +{ + char *buf = (char *)malloc(256); + strcpy(buf, OSK_Get(256, "", "Enter name")); + + if (strncmp(buf, "", 1) == 0) + return -1; + + char path[512]; + strcpy(path, cwd); + strcat(path, buf); + free(buf); + + FS_RecursiveMakeDir(archive, path); + + Dirbrowse_PopulateFiles(true); + return 0; +} + +static Result FileOptions_Rename(void) +{ + Result ret = 0; + File *file = Dirbrowse_GetFileIndex(position); + + if (file == NULL) + return -1; + + if (strncmp(file->name, "..", 2) == 0) + return -2; + + char oldPath[512], newPath[512]; + + char *buf = (char *)malloc(256); + + strcpy(oldPath, cwd); + strcpy(newPath, cwd); + strcat(oldPath, file->name); + + strcpy(buf, OSK_Get(256, file->name, "Enter name")); + strcat(newPath, buf); + free(buf); + + if (file->isDir) + { + if (R_FAILED(ret = FS_RenameDir(archive, oldPath, newPath))) + return ret; + } + else + { + if (R_FAILED(ret = FS_RenameFile(archive, oldPath, newPath))) + return ret; + } + + Dirbrowse_PopulateFiles(true); + return 0; +} + +static int FileOptions_DeleteFile(void) +{ + File *file = Dirbrowse_GetFileIndex(position); + + if (file == NULL) + return -1; + + if (strncmp(file->name, "..", 2) == 0) + return -2; + + char path[512]; + strcpy(path, cwd); + strcpy(path + strlen(path), file->name); + + Result ret = 0; + + if (file->isDir) // Delete folder + { + if (R_FAILED(ret = FS_RmdirRecursive(archive, path))) + return ret; + } + else // Delete file + { + if (R_FAILED(ret = FS_Remove(archive, path))) + return ret; + } + + return 0; +} + +// Copy file from src to dst +static int FileOptions_CopyFile(char *src, char *dst, bool displayAnim) +{ + int chunksize = (512 * 1024); // Chunk size + char *buffer = (char *)malloc(chunksize); // Reading buffer + + u64 totalwrite = 0; // Accumulated writing + u64 totalread = 0; // Accumulated reading + + int result = 0; // Result + + int in = open(src, O_RDONLY, 0777); // Open file for reading + u64 size = 0; + FS_GetFileSize(archive, src, &size); + + // Opened file for reading + if (in >= 0) + { + if (FS_FileExists(archive, dst)) + FS_Remove(archive, dst); // Delete output file (if existing) + + int out = open(dst, O_WRONLY | O_CREAT | O_TRUNC, 0777); // Open output file for writing + + if (out >= 0) // Opened file for writing + { + u64 b_read = 0; // Read byte count + + // Copy loop (512KB at a time) + while((b_read = read(in, buffer, chunksize)) > 0) + { + totalread += b_read; // Accumulate read data + totalwrite += write(out, buffer, b_read); // Write data + + if (displayAnim) + ProgressBar_DisplayProgress(copymode == 1? "Moving" : "Copying", Utils_Basename(src), totalread, size); + } + + close(out); // Close output file + + if (totalread != totalwrite) // Insufficient copy + result = -3; + } + + else // Output open error + result = -2; + + close(in); // Close input file + } + + // Input open error + else + result = -1; + + free(buffer); // Free memory + return result; // Return result +} + +// Recursively copy file from src to dst +static Result FileOptions_CopyDir(char *src, char *dst) +{ + Handle dirHandle; + Result ret = 0; // Open working Directory + + // Opened directory + if (R_SUCCEEDED(ret = FSUSER_OpenDirectory(&dirHandle, archive, fsMakePath(PATH_ASCII, src)))) + { + FS_MakeDir(archive, dst); // Create output directory (is allowed to fail, we can merge folders after all) + + u32 entryCount = 0; + FS_DirectoryEntry *entries = (FS_DirectoryEntry*) calloc(MAX_FILES, sizeof(FS_DirectoryEntry)); + + if (R_SUCCEEDED(ret = FSDIR_Read(dirHandle, &entryCount, MAX_FILES, entries))) + { + u8 name[255] = {'\0'}; + for (u32 i = 0; i < entryCount; i++) + { + Utils_U16_To_U8(&name[0], entries[i].name, 254); + + if (strlen(name) > 0) + { + // Calculate buffer size + int insize = strlen(src) + strlen(name) + 2; + int outsize = strlen(dst) + strlen(name) + 2; + + // Allocate buffer + char *inbuffer = (char *)malloc(insize); + char *outbuffer = (char *)malloc(outsize); + + // Puzzle input path + strcpy(inbuffer, src); + inbuffer[strlen(inbuffer) + 1] = 0; + inbuffer[strlen(inbuffer)] = '/'; + strcpy(inbuffer + strlen(inbuffer), name); + + // Puzzle output path + strcpy(outbuffer, dst); + outbuffer[strlen(outbuffer) + 1] = 0; + outbuffer[strlen(outbuffer)] = '/'; + strcpy(outbuffer + strlen(outbuffer), name); + + if (entries[i].attributes & FS_ATTRIBUTE_DIRECTORY) // Another folder + FileOptions_CopyDir(inbuffer, outbuffer); // Copy folder (via recursion) + + else + { + if (R_FAILED(ret = ret = FileOptions_CopyFile(inbuffer, outbuffer, false))) // Copy file + return ret; + } + + // Free buffer + free(inbuffer); + free(outbuffer); + } + + ProgressBar_DisplayProgress(copymode == 1? "Moving" : "Copying", Utils_Basename(name), i, entryCount); + } + } + else + return ret; + + free(entries); + + if (R_FAILED(ret = FSDIR_Close(dirHandle))) // Close directory + return ret; + } + else + return ret; + + return 0; +} + +static void FileOptions_Copy(int flag) +{ + File *file = Dirbrowse_GetFileIndex(position); + + if (file == NULL) + return; + + // Copy file source + strcpy(copysource, cwd); + strcpy(copysource + strlen(copysource), file->name); + + if ((file->isDir) && (strncmp(file->name, "..", 2) != 0)) // If directory, add recursive folder flag + flag |= COPY_FOLDER_RECURSIVE; + + copymode = flag; // Set copy flags +} + +// Paste file or folder +static Result FileOptions_Paste(void) +{ + if (copymode == NOTHING_TO_COPY) // No copy source + return -1; + + // Source and target folder are identical + char *lastslash = NULL; + int i = 0; + + for(; i < strlen(copysource); i++) + if (copysource[i] == '/') + lastslash = copysource + i; + + char backup = lastslash[1]; + lastslash[1] = 0; + int identical = strcmp(copysource, cwd) == 0; + lastslash[1] = backup; + + if (identical) + return -2; + + char *filename = lastslash + 1; // Source filename + + int requiredlength = strlen(cwd) + strlen(filename) + 1; // Required target path buffer size + char *copytarget = (char *)malloc(requiredlength); // Allocate target path buffer + + // Puzzle target path + strcpy(copytarget, cwd); + strcpy(copytarget + strlen(copytarget), filename); + + Result ret = -3; // Return result + + // Recursive folder copy + if ((copymode & COPY_FOLDER_RECURSIVE) == COPY_FOLDER_RECURSIVE) + { + // Check files in current folder + File *node = files; for(; node != NULL; node = node->next) + { + if ((strcmp(filename, node->name) == 0) && (!node->isDir)) // Found a file matching the name (folder = ok, file = not) + return -4; // Error out + } + + ret = FileOptions_CopyDir(copysource, copytarget); // Copy folder recursively + + if ((R_SUCCEEDED(ret)) && (copymode & COPY_DELETE_ON_FINISH) == COPY_DELETE_ON_FINISH) + { + // Needs to add a forward "/" + if (!(strcmp(&(copysource[(strlen(copysource)-1)]), "/") == 0)) + strcat(copysource, "/"); + + FS_RmdirRecursive(archive, copysource); // Delete dir + } + } + + // Simple file copy + else + { + ret = FileOptions_CopyFile(copysource, copytarget, true); // Copy file + + if ((R_SUCCEEDED(ret)) && (copymode & COPY_DELETE_ON_FINISH) == COPY_DELETE_ON_FINISH) + FS_Remove(archive, copysource); // Delete file + } + + // Paste success + if (R_SUCCEEDED(ret)) + { + memset(copysource, 0, sizeof(copysource)); // Erase cache data + copymode = NOTHING_TO_COPY; + } + + free(copytarget); // Free target path buffer + return ret; // Return result +} + +static void HandleDelete(void) +{ + if ((multi_select_index > 0) && (strlen(multi_select_dir) != 0)) + { + for (int i = 0; i < multi_select_index; i++) + { + if (strlen(multi_select_paths[i]) != 0) + { + if (strncmp(multi_select_paths[i], "..", 2) != 0) + { + if (FS_DirExists(archive, multi_select_paths[i])) + FS_RmdirRecursive(archive, multi_select_paths[i]); + else if (FS_FileExists(archive, multi_select_paths[i])) + FS_Remove(archive, multi_select_paths[i]); + } + } + } + + FileOptions_ResetClipboard(); + } + else if (FileOptions_DeleteFile() != 0) + return; + + Dirbrowse_PopulateFiles(true); + MENU_STATE = MENU_STATE_HOME; +} + +void Menu_ControlDeleteDialog(u32 input) +{ + if (input & KEY_RIGHT) + delete_dialog_selection++; + else if (input & KEY_LEFT) + delete_dialog_selection--; + + Utils_SetMax(&delete_dialog_selection, 0, 1); + Utils_SetMin(&delete_dialog_selection, 1, 0); + + if (input & KEY_B) + { + delete_dialog_selection = 0; + MENU_STATE = MENU_STATE_FILEOPTIONS; + } + + if (input & KEY_A) + { + if (delete_dialog_selection == 1) + HandleDelete(); + else + MENU_STATE = MENU_STATE_FILEOPTIONS; + + delete_dialog_selection = 0; + } + + if (TouchInRect((288 - delete_cancel_width) - 5, (159 - delete_cancel_height) - 5, ((288 - delete_cancel_width) - 5) + delete_cancel_width + 10, ((159 - delete_cancel_height) - 5) + delete_cancel_height + 10)) + { + delete_dialog_selection = 0; + + if (input & KEY_TOUCH) + { + MENU_STATE = MENU_STATE_FILEOPTIONS; + delete_dialog_selection = 0; + } + } + else if (TouchInRect((248 - (delete_confirm_width)) - 5, (159 - delete_confirm_height) - 5, ((248 - (delete_confirm_width)) - 5) + delete_confirm_width + 10, ((159 - delete_confirm_height) - 5) + delete_confirm_height + 10)) + { + delete_dialog_selection = 1; + + if (input & KEY_TOUCH) + { + HandleDelete(); + delete_dialog_selection = 0; + } + } +} + +void Menu_DisplayDeleteDialog(void) +{ + float text_width = 0; + Draw_GetTextSize(0.45f, &text_width, NULL, "Do you want to continue?"); + + Draw_GetTextSize(0.45f, &delete_confirm_width, &delete_confirm_height, "YES"); + Draw_GetTextSize(0.45f, &delete_cancel_width, &delete_cancel_height, "NO"); + + Draw_Image(config_dark_theme? dialog_dark : dialog, ((320 - (dialog.subtex->width)) / 2), ((240 - (dialog.subtex->height)) / 2)); + + Draw_Text(((320 - (dialog.subtex->width)) / 2) + 6, ((240 - (dialog.subtex->height)) / 2) + 6, 0.45f, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR, "Confirm deletion"); + + Draw_Text(((320 - (text_width)) / 2), ((240 - (dialog.subtex->height)) / 2) + 40, 0.45f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Do you wish to continue?"); + + if (delete_dialog_selection == 0) + Draw_Rect((288 - delete_cancel_width) - 5, (159 - delete_cancel_height) - 5, delete_cancel_width + 10, delete_cancel_height + 10, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); + else if (delete_dialog_selection == 1) + Draw_Rect((248 - (delete_confirm_width)) - 5, (159 - delete_confirm_height) - 5, delete_confirm_width + 10, delete_confirm_height + 10, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); + + Draw_Text(248 - (delete_confirm_width), (159 - delete_confirm_height), 0.45f, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR, "YES"); + Draw_Text(288 - delete_cancel_width, (159 - delete_cancel_height), 0.45f, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR, "NO"); +} + +void Menu_ControlProperties(u32 input) +{ + if ((input & KEY_A) || (input & KEY_B)) + MENU_STATE = MENU_STATE_FILEOPTIONS; + + if (TouchInRect((253 - properties_ok_width) - 5, (218 - properties_ok_height) - 5, ((253 - properties_ok_width) - 5) + properties_ok_width + 10, ((218 - properties_ok_height) - 5) + properties_ok_height + 10)) + if (input & KEY_TOUCH) + MENU_STATE = MENU_STATE_FILEOPTIONS; +} + +void Menu_DisplayProperties(void) +{ + // Find File + File *file = Dirbrowse_GetFileIndex(position); + + char path[1024]; + strcpy(path, cwd); + strcpy(path + strlen(path), file->name); + + Draw_Image(config_dark_theme? properties_dialog_dark : properties_dialog, 54, 30); + Draw_Text(61, 37, 0.45f, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR, "Properties"); + + char utils_size[16]; + u64 size = 0; + + if (!file->isDir) + { + FS_GetFileSize(archive, path, &size); + Utils_GetSizeString(utils_size, size); + } + + Draw_Textf(66, 60, 0.45f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Name: %.22s", file->name); + Draw_Textf(66, 76, 0.45f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Parent: %.20s", cwd); + + if (!file->isDir) + { + Draw_Textf(66, 92, 0.45f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Size: %s", utils_size); + Draw_Textf(66, 108, 0.45f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Modified time: %s", FS_GetFileTimestamp(archive, path)); + } + else + Draw_Textf(66, 92, 0.45f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Modified time: %s", FS_GetFileTimestamp(archive, path)); + + Draw_GetTextSize(0.45f, &properties_ok_width, &properties_ok_height, "OK"); + Draw_Rect((253 - properties_ok_width) - 5, (218 - properties_ok_height) - 5, properties_ok_width + 10, properties_ok_height + 10, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); + Draw_Text(253 - properties_ok_width, 218 - properties_ok_height, 0.45f, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR, "OK"); +} + +static void HandleCopy() +{ + if ((!copy_status) && (!cut_status)) + { + copy_status = true; + FileOptions_Copy(COPY_KEEP_ON_FINISH); + MENU_STATE = MENU_STATE_HOME; + } + else if (copy_status) + { + if ((multi_select_index > 0) && (strlen(multi_select_dir) != 0)) + { + char dest[512]; + + for (int i = 0; i < multi_select_index; i++) + { + if (strlen(multi_select_paths[i]) != 0) + { + if (strncmp(multi_select_paths[i], "..", 2) != 0) + { + snprintf(dest, 512, "%s%s", cwd, Utils_Basename(multi_select_paths[i])); + + if (FS_DirExists(archive, multi_select_paths[i])) + FileOptions_CopyDir(multi_select_paths[i], dest); + else if (FS_FileExists(archive, multi_select_paths[i])) + FileOptions_CopyFile(multi_select_paths[i], dest, true); + } + } + } + + FileOptions_ResetClipboard(); + copymode = NOTHING_TO_COPY; + + } + else if (FileOptions_Paste() != 0) + return; + + copy_status = false; + Dirbrowse_PopulateFiles(true); + MENU_STATE = MENU_STATE_HOME; + } +} + +static void HandleCut() +{ + if ((!cut_status) && (!copy_status)) + { + cut_status = true; + FileOptions_Copy(COPY_DELETE_ON_FINISH); + MENU_STATE = MENU_STATE_HOME; + } + else if (cut_status) + { + char dest[512]; + + if ((multi_select_index > 0) && (strlen(multi_select_dir) != 0)) + { + for (int i = 0; i < multi_select_index; i++) + { + if (strlen(multi_select_paths[i]) != 0) + { + snprintf(dest, 512, "%s%s", cwd, Utils_Basename(multi_select_paths[i])); + + if (FS_DirExists(archive, multi_select_paths[i])) + FS_RenameDir(archive, multi_select_paths[i], dest); + else if (FS_FileExists(archive, multi_select_paths[i])) + FS_RenameFile(archive, multi_select_paths[i], dest); + } + } + + FileOptions_ResetClipboard(); + } + else + { + snprintf(dest, 512, "%s%s", cwd, Utils_Basename(copysource)); + + if (FS_DirExists(archive, copysource)) + FS_RenameDir(archive, copysource, dest); + else if (FS_FileExists(archive, copysource)) + FS_RenameFile(archive, copysource, dest); + } + + cut_status = false; + copymode = NOTHING_TO_COPY; + Dirbrowse_PopulateFiles(true); + MENU_STATE = MENU_STATE_HOME; + } +} + +void Menu_ControlFileOptions(u32 input) +{ + if (input & KEY_RIGHT) + row++; + else if (input & KEY_LEFT) + row--; + + if (input & KEY_DDOWN) + column++; + else if (input & KEY_DUP) + column--; + + Utils_SetMax(&row, 0, 1); + Utils_SetMin(&row, 1, 0); + + Utils_SetMax(&column, 0, 2); + Utils_SetMin(&column, 2, 0); + + if (input & KEY_A) + { + if (row == 0 && column == 0) + MENU_STATE = MENU_STATE_PROPERTIES; + else if (row == 1 && column == 0) + FileOptions_CreateFolder(); + else if (row == 0 && column == 1) + FileOptions_Rename(); + else if (row == 1 && column == 1) + HandleCopy(); + else if (row == 0 && column == 2) + HandleCut(); + else if (row == 1 && column == 2) + MENU_STATE = MENU_STATE_DELETE; + } + + if (input & KEY_B) + { + copy_status = false; + cut_status = false; + row = 0; + column = 0; + MENU_STATE = MENU_STATE_HOME; + } + + if (input & KEY_X) + MENU_STATE = MENU_STATE_HOME; + + if (TouchInRect(56, 69, 159, 104)) + { + row = 0; + column = 0; + + if (input & KEY_TOUCH) + MENU_STATE = MENU_STATE_PROPERTIES; + } + else if (TouchInRect(160, 69, 263, 104)) + { + row = 1; + column = 0; + + if (input & KEY_TOUCH) + FileOptions_CreateFolder(); + } + else if (TouchInRect(56, 105, 159, 141)) + { + row = 0; + column = 1; + + if (input & KEY_TOUCH) + FileOptions_Rename(); + } + else if (TouchInRect(160, 105, 263, 141)) + { + row = 1; + column = 1; + + if (input & KEY_TOUCH) + HandleCopy(); + } + else if (TouchInRect(56, 142, 159, 178)) + { + row = 0; + column = 2; + + if (input & KEY_TOUCH) + HandleCut(); + } + else if (TouchInRect(160, 142, 263, 178)) + { + row = 1; + column = 2; + + if (input & KEY_TOUCH) + MENU_STATE = MENU_STATE_DELETE; + } + else if (TouchInRect(258 - options_cancel_width, 223 - options_cancel_height, (258 - options_cancel_width) + options_cancel_width, (223 - options_cancel_height) + options_cancel_height)) + { + if (input & KEY_TOUCH) + { + copy_status = false; + cut_status = false; + row = 0; + column = 0; + MENU_STATE = MENU_STATE_HOME; + } + } +} + +void Menu_DisplayFileOptions(void) +{ + Draw_Image(config_dark_theme? options_dialog_dark : options_dialog, 54, 30); + Draw_Text(61, 37, 0.45f, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR, "Actions"); + + Draw_GetTextSize(0.45f, &options_cancel_width, &options_cancel_height, "CANCEL"); + Draw_Text(258 - options_cancel_width, 223 - options_cancel_height, 0.45f, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR, "CANCEL"); + + if (row == 0 && column == 0) + Draw_Rect(56, 69, 103, 36, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); + else if (row == 1 && column == 0) + Draw_Rect(160, 69, 103, 36, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); + else if (row == 0 && column == 1) + Draw_Rect(56, 105, 103, 36, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); + else if (row == 1 && column == 1) + Draw_Rect(160, 105, 103, 36, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); + else if (row == 0 && column == 2) + Draw_Rect(56, 142, 103, 36, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); + else if (row == 1 && column == 2) + Draw_Rect(160, 142, 103, 36, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); + + Draw_Text(66, 80, 0.45f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Properties"); + Draw_Text(66, 116, 0.45f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Rename"); + Draw_Text(66, 152, 0.45f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, cut_status? "Paste" : "Move"); + + Draw_Text(170, 80, 0.45f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "New folder"); + Draw_Text(170, 116, 0.45f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, copy_status? "Paste" : "Copy"); + Draw_Text(170, 152, 0.45f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Delete"); +} diff --git a/source/menus/menu_ftp.c b/source/menus/menu_ftp.c index 9cb2c43..616fcd3 100644 --- a/source/menus/menu_ftp.c +++ b/source/menus/menu_ftp.c @@ -1,100 +1,95 @@ #include #include +#include "C2D_helper.h" #include "common.h" -#include "dir_list.h" +#include "config.h" +#include "dirbrowse.h" #include "fs.h" #include "ftp.h" -#include "language.h" #include "menu_ftp.h" #include "menu_main.h" -#include "pp2d.h" #include "status_bar.h" #include "textures.h" -#include "theme.h" +#include "touch.h" #include "utils.h" -struct colour Storage_colour; -struct colour BottomScreen_colour; -struct colour BottomScreen_bar_colour; -struct colour BottomScreen_text_colour; - void Menu_DisplayFTP(void) { ftp_init(); touchPosition touch; - + char buf[25]; u32 wifiStatus = 0; int pBar = 0, xlim = 270; - while(MENU_DEFAULT_STATE == MENU_STATE_FTP) + while(MENU_STATE == MENU_STATE_FTP) { ftp_loop(); + + C3D_FrameBegin(C3D_FRAME_SYNCDRAW); + C2D_TargetClear(RENDER_BOTTOM, config_dark_theme? BLACK_BG : WHITE); + C2D_SceneBegin(RENDER_BOTTOM); + Draw_Rect(0, 0, 320, 20, config_dark_theme? STATUS_BAR_DARK : STATUS_BAR_LIGHT); // Status bar + Draw_Rect(0, 20, 320, 220, config_dark_theme? MENU_BAR_DARK : MENU_BAR_LIGHT); // Menu bar ACU_GetWifiStatus(&wifiStatus); - - pp2d_begin_draw(GFX_BOTTOM, GFX_LEFT); - - pp2d_draw_rectangle(0, 0, 320, 240, RGBA8(BottomScreen_colour.r, BottomScreen_colour.g, BottomScreen_colour.b, 255)); - pp2d_draw_rectangle(0, 0, 320, 20, RGBA8(BottomScreen_bar_colour.r, BottomScreen_bar_colour.g, BottomScreen_bar_colour.b, 255)); - Menu_Draw_MenuBar(); - - if (!(wifiStatus)) - { - pp2d_draw_text(((320 - pp2d_get_text_width(lang_ftp[language][3], 0.45f, 0.45f)) / 2), 40, 0.45f, 0.45f, RGBA8(BottomScreen_text_colour.r, BottomScreen_text_colour.g , BottomScreen_text_colour.b, 255), lang_ftp[language][3]); - sprintf(buf, lang_ftp[language][4]); - } - else - { - pp2d_draw_text(((320 - pp2d_get_text_width(lang_ftp[language][0], 0.45f, 0.45f)) / 2), 40, 0.45f, 0.45f, RGBA8(BottomScreen_text_colour.r, BottomScreen_text_colour.g , BottomScreen_text_colour.b, 255), lang_ftp[language][0]); - - u32 ip = gethostid(); - sprintf(buf, "IP: %lu.%lu.%lu.%lu:5000", ip & 0xFF, (ip>>8)&0xFF, (ip>>16)&0xFF, (ip>>24)&0xFF); + Menu_DrawMenuBar(); + + if (wifiStatus == 0) + { + Draw_Text(((320 - Draw_GetTextWidth(0.48f, "Failed to initialize FTP.")) / 2), 40, 0.48f, WHITE, "Failed to initialize FTP."); + sprintf(buf, "WiFi not enabled."); + } + else + { + Draw_Text(((320 - Draw_GetTextWidth(0.48f, "FTP initialized")) / 2), 40, 0.48f, WHITE, "FTP initialized"); + + u32 ip = gethostid(); + sprintf(buf, "IP: %lu.%lu.%lu.%lu:5000", ip & 0xFF, (ip>>8)&0xFF, (ip>>16)&0xFF, (ip>>24)&0xFF); - pp2d_draw_text(((320 - pp2d_get_text_width(buf, 0.45f, 0.45f)) / 2), 60, 0.45f, 0.45f, RGBA8(BottomScreen_text_colour.r, BottomScreen_text_colour.g , BottomScreen_text_colour.b, 255), buf); + Draw_Text(((320 - Draw_GetTextWidth(0.48f, buf)) / 2), 60, 0.48f, WHITE, buf); - if (strlen(ftp_accepted_connection) != 0) - pp2d_draw_text(((320 - pp2d_get_text_width(ftp_accepted_connection, 0.45f, 0.45f)) / 2), 80, 0.45f, 0.45f, RGBA8(BottomScreen_text_colour.r, BottomScreen_text_colour.g , BottomScreen_text_colour.b, 255), ftp_accepted_connection); + if (strlen(ftp_accepted_connection) != 0) + Draw_Text(((320 - Draw_GetTextWidth(0.48f, ftp_accepted_connection)) / 2), 80, 0.48f, WHITE, ftp_accepted_connection); - pp2d_draw_text(((320 - pp2d_get_text_width(lang_ftp[language][1], 0.45f, 0.45f)) / 2), 100, 0.45f, 0.45f, RGBA8(BottomScreen_text_colour.r, BottomScreen_text_colour.g , BottomScreen_text_colour.b, 255), lang_ftp[language][1]); + Draw_Text(((320 - Draw_GetTextWidth(0.48f, "File browser cannot be accesed at this time.")) / 2), 100, 0.48f, WHITE, "File browser cannot be accesed at this time."); - if (strlen(ftp_file_transfer) != 0) - pp2d_draw_text(((320 - pp2d_get_text_width(ftp_file_transfer, 0.45f, 0.45f)) / 2), 150, 0.45f, 0.45f, RGBA8(BottomScreen_text_colour.r, BottomScreen_text_colour.g , BottomScreen_text_colour.b, 255), ftp_file_transfer); + if (strlen(ftp_file_transfer) != 0) + Draw_Text(((320 - Draw_GetTextWidth(0.45f, ftp_file_transfer)) / 2), 150, 0.45f, WHITE, ftp_file_transfer); - if (isTransfering) - { - pp2d_draw_rectangle(50, 140, 220, 3, RGBA8(BottomScreen_bar_colour.r, BottomScreen_bar_colour.g, BottomScreen_bar_colour.b, 255)); - pp2d_draw_rectangle(pBar, 140, 40, 3, RGBA8(BottomScreen_text_colour.r, BottomScreen_text_colour.g , BottomScreen_text_colour.b, 255)); + if (isTransfering) + { + Draw_Rect(50, 140, 220, 3, config_dark_theme? STATUS_BAR_DARK : STATUS_BAR_LIGHT); + Draw_Rect(pBar, 140, 40, 3, WHITE); - // Boundary stuff - pp2d_draw_rectangle(0, 140, 50, 3, RGBA8(BottomScreen_colour.r, BottomScreen_colour.g, BottomScreen_colour.b, 255)); - pp2d_draw_rectangle(270, 140, 50, 3, RGBA8(BottomScreen_colour.r, BottomScreen_colour.g, BottomScreen_colour.b, 255)); - pBar += 4; - - if (pBar >= xlim) - pBar = 34; - } + // Boundary stuff + Draw_Rect(0, 140, 50, 3, config_dark_theme? MENU_BAR_DARK : MENU_BAR_LIGHT); + Draw_Rect(270, 140, 50, 3, config_dark_theme? MENU_BAR_DARK : MENU_BAR_LIGHT); + pBar += 4; + + if (pBar >= xlim) + pBar = 34; } + } - pp2d_draw_text(((320 - pp2d_get_text_width(lang_ftp[language][2], 0.45f, 0.45f)) / 2), 120, 0.45f, 0.45f, RGBA8(BottomScreen_text_colour.r, BottomScreen_text_colour.g , BottomScreen_text_colour.b, 255), lang_ftp[language][2]); + Draw_Text(((320 - Draw_GetTextWidth(0.48f, "Tap the FTP icon to disable the FTP connection.")) / 2), 120, 0.48f, WHITE, "Tap the FTP icon to disable the FTP connection."); - pp2d_end_draw(); + Draw_EndFrame(); hidScanInput(); u32 kDown = hidKeysDown(); - if (kDown & KEY_SELECT) + if (((kDown & KEY_TOUCH) && (TouchInRect(73, 0, 97, 20))) || (kDown & KEY_SELECT)) break; } memset(ftp_accepted_connection, 0, 20); // Empty accepted connection address memset(ftp_file_transfer, 0, 50); // Empty transfer status ftp_exit(); - MENU_DEFAULT_STATE = MENU_STATE_HOME; - Dirlist_PopulateFiles(true); - Dirlist_DisplayFiles(); + MENU_STATE = MENU_STATE_HOME; + Dirbrowse_PopulateFiles(true); } \ No newline at end of file diff --git a/source/menus/menu_gallery.c b/source/menus/menu_gallery.c index 6a3417a..1af82f3 100644 --- a/source/menus/menu_gallery.c +++ b/source/menus/menu_gallery.c @@ -1,142 +1,371 @@ -#include -#include +#include +#include <3ds.h> +#include "C2D_helper.h" #include "common.h" -#include "dir_list.h" +#include "config.h" +#include "fs.h" #include "menu_gallery.h" -#include "pp2d.h" -#include "screenshot.h" -#include "textures.h" + +#define LOADBMP_IMPLEMENTATION +#include "loadbmp.h" +#undef LOADBMP_IMPLEMENTATION +#include "lodepng.h" +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" +#undef STB_IMAGE_IMPLEMENTATION + +#include "touch.h" #include "utils.h" +#define EXTENSION_SIZE 4 + #define DIMENSION_DEFAULT 0 #define DIMENSION_NINTENDO_SCREENSHOT 1 #define DIMENSION_NINTENDO_PICTURE 2 #define DIMENSION_3DSHELL_SCREENSHOT 3 #define DIMENSION_OTHER 4 -#define GALLERY_BAR_Y_BOUNDARY -35 -#define GALLERY_NAME_Y_BOUNDARY -11 +static char album[512][512]; +static int count = 0, selection = 0, dimensions = 0; +C2D_Image image; -void Gallery_DisplayImage(char * path) +// Thanks to LiquidFenrir +static u32 Gallery_GetNextPowerOf2(u32 v) // from pp2d { - File * file = Dirlist_GetFileIndex(position); + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v++; + return v >= 64 ? v : 64; +} - if (strncasecmp(file->ext, "png", 3) == 0) - pp2d_load_texture_png(TEXTURE_GALLERY_IMAGE, path); - else if (strncasecmp(file->ext, "bmp", 3) == 0) - pp2d_load_texture_bmp(TEXTURE_GALLERY_IMAGE, path); - else if (strncasecmp(file->ext, "jpg", 3) == 0) - pp2d_load_texture_jpg(TEXTURE_GALLERY_IMAGE, path); - else if ((strncasecmp(file->ext, "gif", 3) == 0) || (strncasecmp(file->ext, "tga", 3) == 0)) - pp2d_load_texture_other(TEXTURE_GALLERY_IMAGE, path); +// Thanks to LiquidFenrir +static C2D_Image Gallery_LoadImage(const char *path) +{ + u32* outBuf = NULL; + u32 size = 0; + int width = 0, height = 0; + GPU_TEXCOLOR format; - int galleryBarY = 0, nameY = 11; + char extension[EXTENSION_SIZE + 1] = {0}; + strncpy(extension, &path[strlen(path)-EXTENSION_SIZE], EXTENSION_SIZE); - u64 start = osGetTime(); + if (!strncasecmp(extension, ".png", EXTENSION_SIZE)) + { + unsigned char *texture; + lodepng_decode32_file(&texture, &width, &height, path); - float width = pp2d_get_texture_width(TEXTURE_GALLERY_IMAGE); - float height = pp2d_get_texture_height(TEXTURE_GALLERY_IMAGE); + for (u32 i = 0; i < width; i++) + { + for (u32 j = 0; j < height; j++) + { + u32 p = (i + j* width) * 4; - int dimensions = 0; + u8 r = *(u8*)(texture + p); + u8 g = *(u8*)(texture + p + 1); + u8 b = *(u8*)(texture + p + 2); + u8 a = *(u8*)(texture + p + 3); - while (aptMainLoop()) - { - hidScanInput(); + *(texture + p) = a; + *(texture + p + 1) = b; + *(texture + p + 2) = g; + *(texture + p + 3) = r; + } + } - u32 kDown = hidKeysDown(); - u32 kHeld = hidKeysHeld(); + size = (u32)(width * height * 4); + outBuf = (u32 *)malloc(size); + memcpy(outBuf, texture, size); + format = GPU_RGBA8; + } + else if (!strncasecmp(extension, ".jpg", EXTENSION_SIZE) || !strncasecmp(extension, ".jpeg", EXTENSION_SIZE)) + { + int channel = 0; + stbi_uc *texture = stbi_load(path, &width, &height, &channel, STBI_rgb); - pp2d_begin_draw(GFX_BOTTOM, GFX_LEFT); + for (u32 x = 0; x < width; x++) + { + for (u32 y = 0; y < height; y++) + { - pp2d_draw_rectangle(0, 0, 320, 240, RGBA8(33, 39, 43, 255)); + u32 pos = (y * width + x) * channel; - switch (dimensions) - { - case DIMENSION_NINTENDO_SCREENSHOT: - pp2d_draw_texture_part(TEXTURE_GALLERY_IMAGE, 0, 0, 56, 272, 320, 240); - break; + u8 c1 = texture[pos + 0]; + u8 c2 = texture[pos + 1]; + u8 c3 = texture[pos + 2]; - case DIMENSION_3DSHELL_SCREENSHOT: - pp2d_draw_texture_part(TEXTURE_GALLERY_IMAGE, 0, 0, 40, 240, 320, 240); - break; - } - - pp2d_end_draw(); + texture[pos + 0] = c3; + texture[pos + 1] = c2; + texture[pos + 2] = c1; + } + } - pp2d_begin_draw(GFX_TOP, GFX_LEFT); + size = (u32)(width * height * channel); + outBuf = (u32 *)malloc(size); + memcpy(outBuf, texture, size); + stbi_image_free(texture); + format = GPU_RGB8; + } + else if (!strncasecmp(extension, ".bmp", EXTENSION_SIZE)) + { + u8* texture = NULL; + loadbmp_decode_file(path, &texture, &width, &height, LOADBMP_RGBA); + + for (u32 i = 0; i < width; i++) + { + for (u32 j = 0; j < height; j++) + { + u32 p = (i + j*width) * 4; - pp2d_draw_rectangle(0, 0, 400, 240, RGBA8(33, 39, 43, 255)); + u8 r = *(u8*)(texture + p); + u8 g = *(u8*)(texture + p + 1); + u8 b = *(u8*)(texture + p + 2); + u8 a = *(u8*)(texture + p + 3); - if ((width <= 400.0) && (height <= 240.0)) - DIMENSION_DEFAULT; - else if ((width == 432) && (height == 528)) // Nintnedo's screenshot (both screens) dimensions. - dimensions = DIMENSION_NINTENDO_SCREENSHOT; - else if ((width == 640) && (height == 480)) // Nintnedo's CAM dimensions. - dimensions = DIMENSION_NINTENDO_PICTURE; - else if ((width == 400) && (height == 480)) - dimensions = DIMENSION_3DSHELL_SCREENSHOT; - else if ((width > 400.0) && (height > 240.0)) - dimensions = DIMENSION_OTHER; + *(texture + p) = a; + *(texture + p + 1) = b; + *(texture + p + 2) = g; + *(texture + p + 3) = r; + } + } + + size = (u32)(width * height * 4); + outBuf = (u32 *)malloc(size); + memcpy(outBuf, texture, size); + format = GPU_RGBA8; + } - switch (dimensions) - { - case DIMENSION_DEFAULT: - pp2d_draw_texture(TEXTURE_GALLERY_IMAGE, ((400.0 - width) / 2.0), ((240.0 - height) / 2.0)); - break; + if (outBuf) + { - case DIMENSION_NINTENDO_SCREENSHOT: - pp2d_draw_texture_part(TEXTURE_GALLERY_IMAGE, 0, 0, 16, 16, 400, 240); - break; + C3D_Tex *tex = malloc(sizeof(C3D_Tex)); + Tex3DS_SubTexture *subtex = malloc(sizeof(Tex3DS_SubTexture)); - case DIMENSION_NINTENDO_PICTURE: - pp2d_draw_texture_scale(TEXTURE_GALLERY_IMAGE, 40, 0, 0.5, 0.5); - break; + u32 w_pow2 = Gallery_GetNextPowerOf2((u32)width); + u32 h_pow2 = Gallery_GetNextPowerOf2((u32)height); - case DIMENSION_3DSHELL_SCREENSHOT: - pp2d_draw_texture_part(TEXTURE_GALLERY_IMAGE, 0, 0, 0, 0, 400, 240); - break; + subtex->width = width; + subtex->height = height; + subtex->left = 0.0f; + subtex->top = 1.0f; + subtex->right = width/(float)w_pow2; + subtex->bottom = 1.0 - (height/(float)h_pow2); - case DIMENSION_OTHER: - pp2d_draw_texture_scale(TEXTURE_GALLERY_IMAGE, 0, 0, 400.0/width, 240.0/height); - break; - } + C3D_TexInit(tex, (u16)w_pow2, (u16)h_pow2, format); + C3D_TexSetFilter(tex, GPU_LINEAR, GPU_LINEAR); - if (galleryDisplay) - { - if (osGetTime() - start >= (1500)) - { - nameY -= 4; - galleryBarY -= 4; - } + memset(tex->data, 0, tex->size); + + u32 pixelSize = size / width / height; + + for (u32 x = 0; x < width; x++) + { + for (u32 y = 0; y < height; y++) + { + u32 dstPos = ((((y >> 3) * (w_pow2 >> 3) + (x >> 3)) << 6) + ((x & 1) | ((y & 1) << 1) | ((x & 2) << 1) | ((y & 2) << 2) | ((x & 4) << 2) | ((y & 4) << 3))) * pixelSize; + u32 srcPos = (y * width + x) * pixelSize; + + memcpy(&((u8 *)tex->data)[dstPos], &((u8 *) outBuf)[srcPos], pixelSize); + } + } + + C3D_TexFlush(tex); + + free(outBuf); + tex->border = 0xFFFFFFFF; + C3D_TexSetWrap(tex, GPU_CLAMP_TO_BORDER, GPU_CLAMP_TO_BORDER); - if (galleryBarY == -35) - galleryBarY = GALLERY_BAR_Y_BOUNDARY; - if (nameY == -11) - nameY = GALLERY_NAME_Y_BOUNDARY; + if ((subtex->width <= 400) && (subtex->height <= 240)) + DIMENSION_DEFAULT; + else if ((subtex->width == 432) && (subtex->height == 528)) // Nintnedo's screenshot (both screens) dimensions. + dimensions = DIMENSION_NINTENDO_SCREENSHOT; + else if ((subtex->width == 640) && (subtex->height == 480)) // Nintnedo's CAM dimensions. + dimensions = DIMENSION_NINTENDO_PICTURE; + else if ((subtex->width == 400) && ((subtex->height == 480) || (subtex->height == 482))) + dimensions = DIMENSION_3DSHELL_SCREENSHOT; + else if ((subtex->width > 400) && (subtex->height > 240)) + dimensions = DIMENSION_OTHER; - pp2d_draw_texture(TEXTURE_GALLERY_BAR, 0, galleryBarY); - pp2d_draw_textf(30, nameY, 0.45f, 0.45f, RGBA8(255, 255, 255, 255), "%.60s", fileName); + C2D_Image img; + img.tex = tex; + img.subtex = subtex; - if (kDown & KEY_TOUCH) + return img; + } +} + +// Thanks to LiquidFenrir +static void Gallery_FreeImage(C2D_Image *image) +{ + dimensions = 0; + C3D_TexDelete(image->tex); + free(image->tex); + free((Tex3DS_SubTexture *)image->subtex); + //free(image); +} + +static bool Gallery_DrawImage(C2D_Image image, float x, float y, float start, float end) +{ + C2D_DrawParams params = + { + { x, y, 1.0f*image.subtex->width, 1.0f*image.subtex->height }, + { start, end }, + 0.5f, 0.0f + }; + + return C2D_DrawImage(image, ¶ms, NULL); +} + +static Result Gallery_GetImageList(void) +{ + Handle dir; + Result ret = 0; + + if (R_SUCCEEDED(ret = FSUSER_OpenDirectory(&dir, archive, fsMakePath(PATH_ASCII, cwd)))) + { + u32 entryCount = 0; + FS_DirectoryEntry* entries = (FS_DirectoryEntry*) calloc(MAX_FILES, sizeof(FS_DirectoryEntry)); + + if (R_SUCCEEDED(ret = FSDIR_Read(dir, &entryCount, MAX_FILES, entries))) + { + qsort(entries, entryCount, sizeof(FS_DirectoryEntry), Utils_Alphasort); + u8 name[256] = {'\0'}; + + for (u32 i = 0; i < entryCount; i++) + { + Utils_U16_To_U8(&name[0], entries[i].name, 255); + int length = strlen(name); + + if ((strncasecmp(entries[i].shortExt, "png", 3) == 0) || (strncasecmp(entries[i].shortExt, "jpg", 3) == 0) + || (strncasecmp(entries[i].shortExt, "bmp", 3) == 0)) { - galleryBarY = 0; - nameY = 11; - start = osGetTime(); + strcpy(album[count], cwd); + strcpy(album[count] + strlen(album[count]), name); + count++; } } + } + else + { + free(entries); + return ret; + } + + free(entries); + + if (R_FAILED(ret = FSDIR_Close(dir))) // Close directory + return ret; + } + else + return ret; +} + +static int Gallery_GetCurrentIndex(char *path) +{ + for(int i = 0; i < count; ++i) + { + if (!strcmp(album[i], path)) + return i; + } +} + +static void Gallery_LoadTexture(char *path) +{ + Gallery_GetImageList(); + selection = Gallery_GetCurrentIndex(path); + + image = Gallery_LoadImage(path); +} + +static void Gallery_HandleNext(bool forward) +{ + if (forward) + selection++; + else + selection--; + + Utils_SetMax(&selection, 0, (count - 1)); + Utils_SetMin(&selection, (count - 1), 0); + + Gallery_FreeImage(&image); - pp2d_end_draw(); + wait(1); + Gallery_LoadTexture(album[selection]); +} + +void Gallery_DisplayImage(char *path) +{ + Gallery_LoadTexture(path); + + while(aptMainLoop()) + { + C3D_FrameBegin(C3D_FRAME_SYNCDRAW); + C2D_TargetClear(RENDER_TOP, C2D_Color32(33, 39, 43, 255)); + C2D_TargetClear(RENDER_BOTTOM, C2D_Color32(33, 39, 43, 255)); + C2D_SceneBegin(RENDER_TOP); + + switch (dimensions) + { + case DIMENSION_DEFAULT: + Draw_Image(image, ((400.0f - image.subtex->width) / 2.0f), ((240.0f - image.subtex->height) / 2.0f)); + break; + + case DIMENSION_NINTENDO_SCREENSHOT: + Gallery_DrawImage(image, 0, 0, 16, 16); + break; + + case DIMENSION_NINTENDO_PICTURE: + Draw_ImageScale(image, 40, 0, 0.5, 0.5); + break; + + case DIMENSION_3DSHELL_SCREENSHOT: + Gallery_DrawImage(image, 0, 0, 0, 0); + break; + case DIMENSION_OTHER: + Draw_ImageScale(image, 0, 0, 400.0f / image.subtex->width, 240.0f / image.subtex->height); + break; + } + + C2D_SceneBegin(RENDER_BOTTOM); + + switch (dimensions) + { + case DIMENSION_NINTENDO_SCREENSHOT: + Gallery_DrawImage(image, 0, 0, 56, 272); + break; + + case DIMENSION_3DSHELL_SCREENSHOT: + Gallery_DrawImage(image, 0, 0, 40, 240); + break; + } + + Draw_EndFrame(); + + hidScanInput(); + u32 kDown = hidKeysDown(); + + if ((kDown & KEY_LEFT) || (kDown & KEY_L)) + { + wait(1); + Gallery_HandleNext(false); + } + else if ((kDown & KEY_RIGHT) || (kDown & KEY_R)) + { + wait(1); + Gallery_HandleNext(true); + } + if (kDown & KEY_B) - { - wait(10); break; - } - - if (((kHeld & KEY_L) && (kDown & KEY_R)) || ((kHeld & KEY_R) && (kDown & KEY_L))) - Screenshot_Capture(); } - pp2d_free_texture(TEXTURE_GALLERY_IMAGE); // delete image + Gallery_FreeImage(&image); + memset(album, 0, sizeof(album[0][0]) * 512 * 512); + count = 0; + MENU_STATE = MENU_STATE_HOME; } diff --git a/source/menus/menu_home.c b/source/menus/menu_home.c deleted file mode 100644 index 659d37a..0000000 --- a/source/menus/menu_home.c +++ /dev/null @@ -1,6 +0,0 @@ -#include <3ds.h> - -#include "../dir_list.h" -#include "menu_home.h" -#include "../pp2d/pp2d.h" -#include "textures.h" \ No newline at end of file diff --git a/source/menus/menu_main.c b/source/menus/menu_main.c index 8f4fb1f..9a54895 100644 --- a/source/menus/menu_main.c +++ b/source/menus/menu_main.c @@ -1,353 +1,280 @@ +#include #include <3ds.h> +#include "C2D_helper.h" #include "common.h" -#include "dir_list.h" +#include "config.h" +#include "dirbrowse.h" #include "fs.h" #include "keyboard.h" -#include "menu_delete.h" -#include "menu_file_options.h" #include "menu_ftp.h" +#include "menu_fileoptions.h" #include "menu_main.h" -#include "menu_properties.h" -#include "menu_settings.h" -#include "menu_sort.h" #include "menu_update.h" -#include "pp2d.h" -#include "screenshot.h" +#include "menu_settings.h" #include "status_bar.h" +#include "screenshot.h" #include "textures.h" -#include "theme.h" #include "touch.h" +#include "utils.h" -struct colour BottomScreen_colour; -struct colour BottomScreen_bar_colour; -struct colour BottomScreen_text_colour; +static char multi_select_dir_old[256]; -void Menu_Draw_MenuBar(void) +static void Menu_HandleMultiSelect(void) { - float options_x = pp2d_get_texture_width(TEXTURE_HOME_ICON) + 5; - float settings_x = pp2d_get_texture_width(TEXTURE_HOME_ICON) + pp2d_get_texture_width(TEXTURE_OPTIONS_ICON) + 15; - float ftp_x = pp2d_get_texture_width(TEXTURE_HOME_ICON) + pp2d_get_texture_width(TEXTURE_OPTIONS_ICON) + - pp2d_get_texture_width(TEXTURE_SETTINGS_ICON) + 25; - float update_x = pp2d_get_texture_width(TEXTURE_HOME_ICON) + pp2d_get_texture_width(TEXTURE_OPTIONS_ICON) + - pp2d_get_texture_width(TEXTURE_SETTINGS_ICON) + pp2d_get_texture_width(TEXTURE_FTP_ICON) + 35; - - if (MENU_DEFAULT_STATE == MENU_STATE_HOME) - pp2d_draw_texture(TEXTURE_HOME_ICON_SELECTED, 0, -2); + // multi_select_dir can only hold one dir + strcpy(multi_select_dir_old, cwd); + if (strcmp(multi_select_dir_old, multi_select_dir) != 0) + FileOptions_ResetClipboard(); + + char path[256]; + File *file = Dirbrowse_GetFileIndex(position); + strcpy(path, cwd); + strcpy(path + strlen(path), file->name); + strcpy(multi_select_dir, cwd); + + if (!multi_select[position]) + { + multi_select[position] = true; + multi_select_indices[position] = multi_select_index; // Store the index in the position + Utils_AppendArr(multi_select_paths[multi_select_index], path, multi_select_index); + multi_select_index += 1; + } else - pp2d_draw_texture(TEXTURE_HOME_ICON, 0, -2); + { + multi_select[position] = false; + strcpy(multi_select_paths[multi_select_indices[position]], ""); + multi_select_indices[position] = -1; + } - if ((MENU_DEFAULT_STATE == MENU_STATE_OPTIONS) || (MENU_DEFAULT_STATE == MENU_STATE_PROPERTIES)) - pp2d_draw_texture(TEXTURE_OPTIONS_ICON_SELECTED, options_x, 0); - else - pp2d_draw_texture(TEXTURE_OPTIONS_ICON, options_x, 0); + Utils_SetMax(&multi_select_index, 0, 50); + Utils_SetMin(&multi_select_index, 50, 0); +} - if ((MENU_DEFAULT_STATE == MENU_STATE_SETTINGS) || (MENU_DEFAULT_STATE == MENU_STATE_SORT) || (MENU_DEFAULT_STATE == MENU_STATE_THEMES)) - pp2d_draw_texture(TEXTURE_SETTINGS_ICON_SELECTED, settings_x, 1); - else - pp2d_draw_texture(TEXTURE_SETTINGS_ICON, settings_x, 1); +static void Menu_ControlHome(u32 input) +{ + if (fileCount > 0) + { + if (input & KEY_DUP) + position--; + else if (input & KEY_DDOWN) + position++; - if (MENU_DEFAULT_STATE == MENU_STATE_FTP) - pp2d_draw_texture(TEXTURE_FTP_ICON_SELECTED, ftp_x, 0); - else - pp2d_draw_texture(TEXTURE_FTP_ICON, ftp_x, 0); + if (hidKeysHeld() & KEY_CPAD_UP) + { + wait(5); + position--; + } + else if (hidKeysHeld() & KEY_CPAD_DOWN) + { + wait(5); + position++; + } - if ((MENU_DEFAULT_STATE == MENU_STATE_UPDATE) || (MENU_DEFAULT_STATE == MENU_STATE_UPDATE_2)) - pp2d_draw_texture(TEXTURE_UPDATE_ICON_SELECTED, update_x, 0); - else - pp2d_draw_texture(TEXTURE_UPDATE_ICON, update_x, 0); + Utils_SetMax(&position, 0, (fileCount - 1)); + Utils_SetMin(&position, (fileCount - 1), 0); - if (BROWSE_STATE == STATE_SD) - pp2d_draw_texture(TEXTURE_SD_ICON_SELECTED, (320 - pp2d_get_texture_width(TEXTURE_SD_ICON_SELECTED)) - 55, 0); - else - pp2d_draw_texture(TEXTURE_SD_ICON, (320 - pp2d_get_texture_width(TEXTURE_SD_ICON)) - 55, 0); + if (input & KEY_LEFT) + position = 0; + else if (input & KEY_RIGHT) + position = fileCount - 1; - if (BROWSE_STATE == STATE_NAND) - pp2d_draw_texture(TEXTURE_NAND_ICON_SELECTED, (320 - pp2d_get_texture_width(TEXTURE_NAND_ICON_SELECTED)) - 30, 0); - else - pp2d_draw_texture(TEXTURE_NAND_ICON, (320 - pp2d_get_texture_width(TEXTURE_NAND_ICON)) - 30, 0); + // Open options + if (input & KEY_X) + { + if (MENU_STATE == MENU_STATE_FILEOPTIONS) + MENU_STATE = MENU_STATE_HOME; + else + MENU_STATE = MENU_STATE_FILEOPTIONS; + } + + if (input & KEY_Y) + Menu_HandleMultiSelect(); - pp2d_draw_texture(TEXTURE_SEARCH_ICON, (320 - pp2d_get_texture_width(TEXTURE_SEARCH_ICON)), -2); + if (input & KEY_A) + { + wait(5); + Dirbrowse_OpenFile(); + } + else if ((strcmp(cwd, ROOT_PATH) != 0) && (input & KEY_B)) + { + wait(5); + Dirbrowse_Navigate(-1); + Dirbrowse_PopulateFiles(true); + } + } } -static void Menu_Main_Controls(void) +void Menu_DrawMenuBar(void) { - u32 kDown = hidKeysDown(); - u32 kHeld = hidKeysHeld(); + Draw_Image(MENU_STATE == MENU_STATE_HOME? icon_home_overlay : (config_dark_theme? icon_home_dark : icon_home), 0, -2); + Draw_Image((MENU_STATE == MENU_STATE_FILEOPTIONS) || (MENU_STATE == MENU_STATE_PROPERTIES) || (MENU_STATE == MENU_STATE_DELETE)? + icon_options_overlay : (config_dark_theme? icon_options_dark : icon_options), 25, 0); + Draw_Image((MENU_STATE == MENU_STATE_SETTINGS) || (MENU_STATE == MENU_STATE_SORT) || (MENU_STATE == MENU_STATE_ABOUT)? + icon_settings_overlay : (config_dark_theme? icon_settings_dark : icon_settings), 50, 0); + Draw_Image(MENU_STATE == MENU_STATE_FTP? icon_ftp_overlay : (config_dark_theme? icon_ftp_dark : icon_ftp), 75, 0); + Draw_Image((MENU_STATE == MENU_STATE_UPDATE) || (MENU_STATE == MENU_STATE_UPDATE_2)? icon_updates_overlay : + (config_dark_theme? icon_updates_dark : icon_updates), 100, 1); + Draw_Image(BROWSE_STATE == BROWSE_STATE_SD? icon_sd_overlay : (config_dark_theme? icon_sd_dark : icon_sd), 250, 0); + Draw_Image(BROWSE_STATE == BROWSE_STATE_NAND? icon_secure_overlay : (config_dark_theme? icon_secure_dark : icon_secure), 275, 0); + Draw_Image(icon_search, 300, 0); +} - if (((kHeld & KEY_L) && (kDown & KEY_R)) || ((kHeld & KEY_R) && (kDown & KEY_L))) - Screenshot_Capture(); +void Menu_ControlMenuBar(u32 input) +{ + if ((input & KEY_TOUCH) && (TouchInRect(0, 0, 22, 20))) + { + wait(1); + MENU_STATE = MENU_STATE_HOME; + } + else if ((input & KEY_TOUCH) && (TouchInRect(23, 0, 47, 20))) + { + wait(1); + MENU_STATE = MENU_STATE_FILEOPTIONS; + } + else if ((input & KEY_TOUCH) && (TouchInRect(48, 0, 72, 20))) + { + wait(1); + MENU_STATE = MENU_STATE_SETTINGS; + } + else if (((input & KEY_TOUCH) && (TouchInRect(73, 0, 97, 20))) || (input & KEY_SELECT)) + { + wait(1); + MENU_STATE = MENU_STATE_FTP; + Menu_DisplayFTP(); + } + else if ((input & KEY_TOUCH) && (TouchInRect(98, 0, 122, 20))) + { + wait(1); + MENU_STATE = MENU_STATE_UPDATE; + } +} - if ((kDown & KEY_TOUCH) && (touchInRect((320 - pp2d_get_texture_width(TEXTURE_SD_ICON)) - 55, 0, - ((320 - pp2d_get_texture_width(TEXTURE_SD_ICON)) - 55) + 20, 20))) // SD +static void Menu_ControlBrowseOptions(u32 input) +{ + if ((input & KEY_TOUCH) && (TouchInRect(247, 0, 272, 20))) // SD { wait(1); FS_Write(archive, "/3ds/3DShell/lastdir.txt", START_PATH); strcpy(cwd, START_PATH); - BROWSE_STATE = STATE_SD; + BROWSE_STATE = BROWSE_STATE_SD; FS_CloseArchive(archive); FS_OpenArchive(&archive, ARCHIVE_SDMC); - Dirlist_PopulateFiles(true); - Dirlist_DisplayFiles(); + Dirbrowse_PopulateFiles(true); } - else if ((kDown & KEY_TOUCH) && (touchInRect((320 - pp2d_get_texture_width(TEXTURE_NAND_ICON)) - 30, 0, - ((320 - pp2d_get_texture_width(TEXTURE_NAND_ICON)) - 30) + 20, 20))) // CTR NAND + else if ((input & KEY_TOUCH) && (TouchInRect(273, 0, 292, 20))) // CTR NAND { wait(1); strcpy(cwd, START_PATH); - BROWSE_STATE = STATE_NAND; + BROWSE_STATE = BROWSE_STATE_NAND; FS_CloseArchive(archive); FS_OpenArchive(&archive, ARCHIVE_NAND_CTR_FS); - Dirlist_PopulateFiles(true); - Dirlist_DisplayFiles(); + Dirbrowse_PopulateFiles(true); } - if ((kDown & KEY_TOUCH) && (touchInRect((320 - pp2d_get_texture_width(TEXTURE_SEARCH_ICON)), 0, 320, 20))) + if ((input & KEY_TOUCH) && (TouchInRect(293, 0, 320, 20))) { char *path = (char *)malloc(256); - strcpy(path, keyboard_3ds_get(256, "/", "Enter path")); + strcpy(path, OSK_Get(256, "/", "Enter path")); if (FS_DirExists(archive, path)) { strcpy(cwd, path); - Dirlist_PopulateFiles(true); - Dirlist_DisplayFiles(); + Dirbrowse_PopulateFiles(true); } - else - Dirlist_DisplayFiles(); free(path); } +} - if ((kDown & KEY_TOUCH) && (touchInRect(0, 0, 22, 20))) - { - wait(1); - MENU_DEFAULT_STATE = MENU_STATE_HOME; - } - else if ((kDown & KEY_TOUCH) && (touchInRect(23, 0, 48, 20))) - { - wait(1); - MENU_DEFAULT_STATE = MENU_STATE_OPTIONS; - } - else if ((kDown & KEY_TOUCH) && (touchInRect(49, 0, 74, 20))) - { - wait(1); - MENU_DEFAULT_STATE = MENU_STATE_SETTINGS; - } - else if (((kDown & KEY_TOUCH) && (touchInRect(75, 0, 100, 20))) || (kDown & KEY_SELECT)) - { - wait(1); - MENU_DEFAULT_STATE = MENU_STATE_FTP; - Menu_DisplayFTP(); - } - else if ((kDown & KEY_TOUCH) && (touchInRect(101, 0, 126, 20))) - { - wait(1); - MENU_DEFAULT_STATE = MENU_STATE_UPDATE; - } +void Menu_Main(void) +{ + Dirbrowse_PopulateFiles(false); + memset(multi_select, 0, sizeof(multi_select)); // Reset all multi selected items - if (MENU_DEFAULT_STATE == MENU_STATE_OPTIONS) - Menu_ControlFileOptions(kDown); - else if (MENU_DEFAULT_STATE == MENU_STATE_PROPERTIES) - Menu_ControlProperties(kDown); - else if (MENU_DEFAULT_STATE == MENU_STATE_SETTINGS) - Menu_ControlSettings(kDown); - else if (MENU_DEFAULT_STATE == MENU_STATE_SORT) - Menu_ControlSort(kDown); - else if (MENU_DEFAULT_STATE == MENU_STATE_DIALOG) - Menu_ControlDeleteDialog(kDown); - else if (MENU_DEFAULT_STATE == MENU_STATE_UPDATE) - Menu_ControlUpdate(kDown); - else if (MENU_DEFAULT_STATE == MENU_STATE_UPDATE_2) - Menu_ControlUpdate2(kDown); - else if (MENU_DEFAULT_STATE == MENU_STATE_THEMES) + while(aptMainLoop()) { - if (kDown & KEY_A) - { - File * file = Dirlist_GetFileIndex(position); + C3D_FrameBegin(C3D_FRAME_SYNCDRAW); + C2D_TargetClear(RENDER_TOP, config_dark_theme? BLACK_BG : WHITE); + C2D_TargetClear(RENDER_BOTTOM, config_dark_theme? BLACK_BG : WHITE); + C2D_SceneBegin(RENDER_TOP); - strcpy(fileName, file->name); + Draw_Rect(0, 0, 400, 18, config_dark_theme? STATUS_BAR_DARK : STATUS_BAR_LIGHT); // Status bar + Draw_Rect(0, 18, 400, 34, config_dark_theme? MENU_BAR_DARK : MENU_BAR_LIGHT); // Menu bar - if ((strncmp(fileName, "default", 7) == 0)) - { - strcpy(theme_dir, "romfs:/res/drawable"); - strcpy(colour_dir, "/3ds/3DShell/themes/default"); + StatusBar_DisplayTime(); + Dirbrowse_DisplayFiles(); - Theme_SaveConfig(theme_dir, colour_dir); + C2D_SceneBegin(RENDER_BOTTOM); + Draw_Rect(0, 0, 320, 20, config_dark_theme? STATUS_BAR_DARK : MENU_BAR_LIGHT); // Status bar + Draw_Rect(0, 20, 320, 220, config_dark_theme? MENU_BAR_DARK : STATUS_BAR_LIGHT); // Menu bar - wait(1); + Menu_DrawMenuBar(); - Theme_Load(); - Theme_Reload(); - } - else if ((strncmp(fileName, "..", 2) != 0) && (file->isDir)) - { - strcpy(theme_dir, cwd); - strcpy(colour_dir, cwd); - - strcat(theme_dir, fileName); - strcat(colour_dir, fileName); + hidScanInput(); + u32 kDown = hidKeysDown(); + u32 kHeld = hidKeysHeld(); - Theme_SaveConfig(theme_dir, colour_dir); - - wait(1); + Menu_ControlMenuBar(kDown); + + if (((kHeld & KEY_L) && (kDown & KEY_R)) || ((kHeld & KEY_R) && (kDown & KEY_L))) + Screenshot_Capture(); - Theme_Load(); - Theme_Reload(); - } + if (MENU_STATE == MENU_STATE_HOME) + { + Menu_ControlHome(kDown); + Menu_ControlBrowseOptions(kDown); } - if (kDown & KEY_B) + else if (MENU_STATE == MENU_STATE_FILEOPTIONS) { - char buf[250]; - - FILE * read = fopen("/3ds/3DShell/lastdir.txt", "r"); - fscanf(read, "%s", buf); - fclose(read); - - if (FS_DirExists(archive, buf)) // Incase a directory previously visited had been deleted, set start path to sdmc:/ to avoid errors. - strcpy(cwd, buf); - else - strcpy(cwd, START_PATH); - - wait(1); - - MENU_DEFAULT_STATE = MENU_STATE_SETTINGS; + Menu_DisplayFileOptions(); + Menu_ControlFileOptions(kDown); } - } - - if (fileCount > 0) - { - // Position Decrement - if (kDown & KEY_DUP) + else if (MENU_STATE == MENU_STATE_PROPERTIES) { - // Decrease Position - if (position > 0) - position--; - - // Rewind Pointer - else - position = fileCount - 1; + Menu_DisplayProperties(); + Menu_ControlProperties(kDown); } - - // Position Increment - else if (kDown & KEY_DDOWN) + else if (MENU_STATE == MENU_STATE_DELETE) { - // Increase Position - if (position < (fileCount - 1)) - position++; - - // Rewind Pointer - else - position = 0; + Menu_DisplayDeleteDialog(); + Menu_ControlDeleteDialog(kDown); } - - if (kHeld & KEY_CPAD_UP) + else if (MENU_STATE == MENU_STATE_SETTINGS) { - wait(5); - - //scroll_x = 395; - //scroll_time = osGetTime(); - - if (position > 0) - position--; - - else position = fileCount - 1; + Menu_DisplaySettings(); + Menu_ControlSettings(kDown); } - - else if (kHeld & KEY_CPAD_DOWN) + else if (MENU_STATE == MENU_STATE_SORT) { - wait(5); - - //scroll_x = 395; - //scroll_time = osGetTime(); - - if (position < (fileCount - 1)) - position++; - - else position = 0; + Menu_DisplaySortSettings(); + Menu_ControlSortSettings(kDown); } - - else if (kDown & KEY_A) + else if (MENU_STATE == MENU_STATE_ABOUT) { - if (MENU_DEFAULT_STATE != MENU_STATE_THEMES) - { - wait(1); - Dirlist_OpenFile(); // Open file/dir - } + Menu_DisplayAbout(); + Menu_ControlAbout(kDown); } - - else if (kDown & KEY_Y) + else if (MENU_STATE == MENU_STATE_UPDATE) { - snprintf(multi_select_dir, 255, cwd); - - if (!multi_select[position]) - multi_select[position] = true; - else - multi_select[position] = false; + Menu_DisplayUpdate(); + Menu_ControlUpdate(kDown); } - - else if ((strcmp(cwd, ROOT_PATH) != 0) && (kDown & KEY_B)) + else if (MENU_STATE == MENU_STATE_UPDATE_2) { - if (MENU_DEFAULT_STATE != MENU_STATE_THEMES) - { - wait(1); - Dirlist_Navigate(-1); - Dirlist_PopulateFiles(true); - Dirlist_DisplayFiles(); - } + Menu_DisplayUpdate2(); + Menu_ControlUpdate2(kDown); } - } -} - -void Menu_Main(void) -{ - Dirlist_PopulateFiles(true); - - memset(multi_select, 0, sizeof(multi_select)); // Reset all multi selected items - while (aptMainLoop()) - { - pp2d_begin_draw(GFX_TOP, GFX_LEFT); - pp2d_draw_texture(TEXTURE_BACKGROUND, 0, 0); - StatusBar_DisplayBar(); - Dirlist_DisplayFiles(); - pp2d_end_draw(); - - pp2d_begin_draw(GFX_BOTTOM, GFX_LEFT); - pp2d_draw_rectangle(0, 0, 320, 240, RGBA8(BottomScreen_colour.r, BottomScreen_colour.g, BottomScreen_colour.b, 255)); - pp2d_draw_rectangle(0, 0, 320, 20, RGBA8(BottomScreen_bar_colour.r, BottomScreen_bar_colour.g, BottomScreen_bar_colour.b, 255)); - - if (MENU_DEFAULT_STATE == MENU_STATE_HOME) - pp2d_draw_textf(2, 225, 0.45f, 0.45f, RGBA8(BottomScreen_text_colour.r, BottomScreen_text_colour.g , BottomScreen_text_colour.b, 255), "3DShell %d.%d.%d - %s", VERSION_MAJOR, VERSION_MINOR, VERSION_MICRO, GITVERSION); - else if (MENU_DEFAULT_STATE == MENU_STATE_OPTIONS) - Menu_DisplayFileOptions(); - else if (MENU_DEFAULT_STATE == MENU_STATE_PROPERTIES) - Menu_DisplayProperties(); - else if (MENU_DEFAULT_STATE == MENU_STATE_SETTINGS) - Menu_DisplaySettings(); - else if (MENU_DEFAULT_STATE == MENU_STATE_SORT) - Menu_DisplaySort(); - else if (MENU_DEFAULT_STATE == MENU_STATE_DIALOG) - Menu_DisplayDeleteDialog(); - else if (MENU_DEFAULT_STATE == MENU_STATE_UPDATE) - Menu_DisplayUpdate(); - else if (MENU_DEFAULT_STATE == MENU_STATE_UPDATE_2) - Menu_DisplayUpdate2(); - - Menu_Draw_MenuBar(); - pp2d_end_draw(); + Draw_EndFrame(); - hidScanInput(); - Menu_Main_Controls(); - - u32 kDown = hidKeysDown(); if (kDown & KEY_START) - break; + longjmp(exitJmp, 1); } } \ No newline at end of file diff --git a/source/menus/menu_music.c b/source/menus/menu_music.c index ba2157d..685e8e0 100644 --- a/source/menus/menu_music.c +++ b/source/menus/menu_music.c @@ -1,308 +1,261 @@ -#include -#include +#include + +#include <3ds.h> #include "audio.h" -#include "flac.h" #include "mp3.h" -#include "vorbis.h" -#include "wav.h" +#include "C2D_helper.h" #include "common.h" -#include "dir_list.h" +#include "config.h" +#include "dirbrowse.h" #include "fs.h" #include "menu_music.h" -#include "pp2d.h" #include "screenshot.h" #include "status_bar.h" #include "textures.h" #include "touch.h" #include "utils.h" -static volatile bool stop = true; +#define MUSIC_GENRE_COLOUR C2D_Color32(97, 97, 97, 255) +#define MUSIC_STATUS_BG_COLOUR C2D_Color32(43, 53, 61, 255) +#define MUSIC_SEPARATOR_COLOUR C2D_Color32(34, 41, 48, 255) -/** - * Stops current playback. Playback thread should exit as a result. - */ -static void Music_StopPlayback(void) +typedef enum { - stop = true; -} + MUSIC_STATE_NONE, // 0 + MUSIC_STATE_REPEAT, // 1 + MUSIC_STATE_SHUFFLE // 2 +} Music_State; -/** - * Returns whether music is playing or paused. - */ -bool Music_IsPlaying(void) -{ - return !stop; -} +static Thread thread = NULL; +static bool isMP3 = false; +static char playlist[512][512], title[128]; +static int count = 0, selection = 0, state = 0; -/** - * Obtains audio file type. Lifted from ctrmus with permission. - * - * \param file File location. - * \return file_types enum or 0 on unsupported file or error. - */ -enum file_types Music_GetMusicFileType(const char * file) +static Result Menu_GetMusicList(void) { - Handle handle; - - u32 fileSig = 0, bytesRead = 0; - u64 offset = 0; - - enum file_types file_type = FILE_TYPE_ERROR; - - /* Failure opening file */ - if (R_FAILED(FS_Open(&handle, archive, file, FS_OPEN_READ))) - { - FSFILE_Close(handle); - return -1; - } + Handle dir; + Result ret = 0; - if (R_FAILED(FSFILE_Read(handle, &bytesRead, offset, &fileSig, 4))) + if (R_SUCCEEDED(ret = FSUSER_OpenDirectory(&dir, archive, fsMakePath(PATH_ASCII, cwd)))) { - FSFILE_Close(handle); - return -2; - } - - offset += bytesRead; - - switch(fileSig) - { - // "RIFF" - case 0x46464952: - if (isWav(file) == 0) - file_type = FILE_TYPE_WAV; - break; - - // "fLaC" - case 0x43614c66: - file_type = FILE_TYPE_FLAC; - break; - - // "OggS" - case 0x5367674F: - if (isFlac(file) == 0) - file_type = FILE_TYPE_FLAC; - else if (isVorbis(file) == 0) - file_type = FILE_TYPE_VORBIS; + u32 entryCount = 0; + FS_DirectoryEntry* entries = (FS_DirectoryEntry*) calloc(MAX_FILES, sizeof(FS_DirectoryEntry)); + + if (R_SUCCEEDED(ret = FSDIR_Read(dir, &entryCount, MAX_FILES, entries))) + { + qsort(entries, entryCount, sizeof(FS_DirectoryEntry), Utils_Alphasort); + u8 name[256] = {'\0'}; - break; - - // MP3 file with an ID3v2 container - default: - if ((fileSig << 16) == 0xFBFF0000 || (fileSig << 16) == 0xFAFF0000 || (fileSig << 8) == 0x33444900) + for (u32 i = 0; i < entryCount; i++) { - file_type = FILE_TYPE_MP3; - break; + Utils_U16_To_U8(&name[0], entries[i].name, 255); + int length = strlen(name); + + if ((strncasecmp(entries[i].shortExt, "mp3", 3) == 0) || (strncasecmp(entries[i].shortExt, "ogg", 3) == 0) + || (strncasecmp(entries[i].shortExt, "fla", 3) == 0) || (strncasecmp(entries[i].shortExt, "wav", 3) == 0)) + { + strcpy(playlist[count], cwd); + strcpy(playlist[count] + strlen(playlist[count]), name); + count++; + } } + } + else + { + free(entries); + return ret; + } + + free(entries); + + if (R_FAILED(ret = FSDIR_Close(dir))) // Close directory + return ret; } + else + return ret; +} - FSFILE_Close(handle); - return file_type; +static int Music_GetCurrentIndex(char *path) +{ + for(int i = 0; i < count; ++i) + { + if (!strcmp(playlist[i], path)) + return i; + } } -/** - * Should only be called from a new thread only, and have only one playback - * thread at time. This function has not been written for more than one - * playback thread in mind. - * - * \param pathIn File location. - */ -static void Music_PlayFile(void * pathIn) +static void Music_Play(char *path) { - struct decoder_fn decoder; - const char * file = pathIn; - s16 * buffer1 = NULL; - s16 * buffer2 = NULL; - ndspWaveBuf waveBuf[2]; - bool lastbuf = false; - Result ret = -1; + Menu_GetMusicList(); /* Reset previous stop command */ stop = false; - switch(Music_GetMusicFileType(file)) - { - case FILE_TYPE_WAV: - setWav(&decoder); - break; + s32 prio = 0; + svcGetThreadPriority(&prio, CUR_THREAD_HANDLE); + thread = threadCreate(Audio_PlayFile, path, 32 *1024, prio - 1, -2, false); - case FILE_TYPE_FLAC: - setFlac(&decoder); - break; + selection = Music_GetCurrentIndex(path); + strncpy(title, strlen(ID3.title) == 0? strupr(Utils_Basename(path)) : strupr(ID3.title), strlen(ID3.title) == 0? strlen(Utils_Basename(path)) + 1 : strlen(ID3.title) + 1); - case FILE_TYPE_MP3: - setMp3(&decoder); - break; + isMP3 = (strncasecmp(&path[strlen(path)-3], "mp3", 3) == 0); +} - case FILE_TYPE_VORBIS: - setVorbis(&decoder); - break; - default: - goto out; +static void Music_HandleNext(bool forward, int state) +{ + if (state == MUSIC_STATE_NONE) + { + if (forward) + selection++; + else + selection--; } + else if (state == MUSIC_STATE_SHUFFLE) + { + int old_selection = selection; + time_t t; + srand((unsigned) time(&t)); + selection = rand() % (count - 1); - if ((ret = (*decoder.init)(file)) != 0) - goto out; + if (selection == old_selection) + selection++; + } - if ((*decoder.channels)() > 2 || (*decoder.channels)() < 1) - goto out; + Utils_SetMax(&selection, 0, (count - 1)); + Utils_SetMin(&selection, (count - 1), 0); - buffer1 = linearAlloc(decoder.buffSize * sizeof(s16)); - buffer2 = linearAlloc(decoder.buffSize * sizeof(s16)); + wait(1); + Audio_StopPlayback(); + memset(title, 0, sizeof(title)); - ndspChnReset(SFX); - ndspChnWaveBufClear(SFX); - ndspSetOutputMode(NDSP_OUTPUT_STEREO); - ndspChnSetInterp(SFX, NDSP_INTERP_POLYPHASE); - ndspChnSetRate(SFX, (*decoder.rate)()); - ndspChnSetFormat(SFX, (*decoder.channels)() == 2 ? NDSP_FORMAT_STEREO_PCM16 : NDSP_FORMAT_MONO_PCM16); + memset(ID3.artist, 0, 30); + memset(ID3.title, 0, 30); + memset(ID3.album, 0, 30); + memset(ID3.year, 0, 4); + memset(ID3.genre, 0, 30); - memset(waveBuf, 0, sizeof(waveBuf)); - waveBuf[0].nsamples = (*decoder.decode)(&buffer1[0]) / (*decoder.channels)(); - waveBuf[0].data_vaddr = &buffer1[0]; - ndspChnWaveBufAdd(SFX, &waveBuf[0]); + threadJoin(thread, U64_MAX); + threadFree(thread); - waveBuf[1].nsamples = (*decoder.decode)(&buffer2[0]) / (*decoder.channels)(); - waveBuf[1].data_vaddr = &buffer2[0]; - ndspChnWaveBufAdd(SFX, &waveBuf[1]); - - /** - * There may be a chance that the music has not started by the time we get - * to the while loop. So we ensure that music has started here. - */ - while(ndspChnIsPlaying(SFX) == false); + Music_Play(playlist[selection]); +} - while(stop == false) +void Menu_PlayMusic(char *path) +{ + aptSetSleepAllowed(false); + Music_Play(path); + + while (aptMainLoop()) { - svcSleepThread(100 * 1000); - - /* When the last buffer has finished playing, break. */ - if ((lastbuf == true) && (waveBuf[0].status == NDSP_WBUF_DONE) && (waveBuf[1].status == NDSP_WBUF_DONE)) - break; + C3D_FrameBegin(C3D_FRAME_SYNCDRAW); + C2D_TargetClear(RENDER_TOP, config_dark_theme? BLACK_BG : WHITE); + C2D_TargetClear(RENDER_BOTTOM, config_dark_theme? BLACK_BG : WHITE); + C2D_SceneBegin(RENDER_TOP); - if ((ndspChnIsPaused(SFX) == true) || (lastbuf == true)) - continue; + Draw_Image(default_artwork_blur, 0, 0); + Draw_Rect(0, 0, 400, 18, MUSIC_GENRE_COLOUR); // Status bar + Draw_Rect(0, 55, 400, 2, MUSIC_SEPARATOR_COLOUR); // Separating line - if (waveBuf[0].status == NDSP_WBUF_DONE) - { - size_t read = (*decoder.decode)(&buffer1[0]); - - if (read <= 0) - { - lastbuf = true; - continue; - } - else if (read < decoder.buffSize) - waveBuf[0].nsamples = read / (*decoder.channels)(); + StatusBar_DisplayTime(); - ndspChnWaveBufAdd(SFX, &waveBuf[0]); - } - - if (waveBuf[1].status == NDSP_WBUF_DONE) - { - size_t read = (*decoder.decode)(&buffer2[0]); + Draw_Rect(178, 57, 222, 175, C2D_Color32(45, 48, 50, 255)); + Draw_Rect(183, 62, 212, 165, C2D_Color32(46, 49, 51, 255)); - if (read <= 0) - { - lastbuf = true; - continue; - } - else if (read < decoder.buffSize) - waveBuf[1].nsamples = read / (*decoder.channels)(); + if (isMP3) // Only print out ID3 tag info for MP3 + { + Draw_Text(5, 22, 0.5f, WHITE, strupr(title)); + Draw_Text(5, 38, 0.45f, WHITE, strupr(ID3.artist)); - ndspChnWaveBufAdd(SFX, &waveBuf[1]); + Draw_Textf(184, 64, 0.5f, WHITE, "%.30s", ID3.album); + Draw_Textf(184, 84, 0.5f, WHITE, "%.30s", ID3.year); + Draw_Textf(184, 104, 0.5f, WHITE, "%.30s", ID3.genre); } + else + Draw_Text(5, ((37 - Draw_GetTextHeight(0.5f, title)) / 2) + 18, 0.5f, WHITE, title); - if (R_FAILED(DSP_FlushDataCache(buffer1, decoder.buffSize * sizeof(s16)))) - return; - if (R_FAILED(DSP_FlushDataCache(buffer2, decoder.buffSize * sizeof(s16)))) - return; - } + Draw_Rect(0, 57, 175, 175, MUSIC_GENRE_COLOUR); + Draw_Image(default_artwork, 0, 57); - (*decoder.exit)(); + C2D_SceneBegin(RENDER_BOTTOM); -out: - Music_StopPlayback(); - linearFree(buffer1); - linearFree(buffer2); + Draw_Image(ic_music_bg_bottom, 0, 0); - threadExit(0); - return; -} + if (!(Audio_IsPaused(SFX))) + Draw_Image(btn_pause, ((320 - btn_pause.subtex->width) / 2) - 2, ((240 - btn_pause.subtex->height) / 2)); + else + Draw_Image(btn_play, ((320 - btn_play.subtex->width) / 2), ((240 - btn_play.subtex->height) / 2)); -/** - * Play an audio file. - * - * \param path File path. - */ -void Music_Player(char * path) -{ - s32 prio; - static Thread thread = NULL; + Draw_Image(btn_rewind, ((320 - btn_rewind.subtex->width) / 2) - 80, ((240 - btn_rewind.subtex->height) / 2)); + Draw_Image(btn_forward, ((320 - btn_forward.subtex->width) / 2) + 80, ((240 - btn_forward.subtex->height) / 2)); - /* Reset previous stop command */ - stop = false; + Draw_Image(state == MUSIC_STATE_SHUFFLE? btn_shuffle_overlay : btn_shuffle, ((320 - btn_shuffle.subtex->width) / 2) - 65, ((240 - btn_shuffle.subtex->height) / 2) + 35); + Draw_Image(state == MUSIC_STATE_REPEAT? btn_repeat_overlay : btn_repeat, ((320 - btn_repeat.subtex->width) / 2) + 65, ((240 - btn_repeat.subtex->height) / 2) + 35); + + Draw_EndFrame(); - svcGetThreadPriority(&prio, CUR_THREAD_HANDLE); - thread = threadCreate(Music_PlayFile, path, 32 * 1024, prio - 1, -2, false); - - File * file = Dirlist_GetFileIndex(position); - bool isMP3 = (strncasecmp(file->ext, "mp3", 3) == 0); - - while (Music_IsPlaying()) - { hidScanInput(); u32 kDown = hidKeysDown(); u32 kHeld = hidKeysHeld(); - if ((kDown & KEY_A) || ((touchInRect(114, 76, 204, 164)) && (kDown & KEY_TOUCH))) + if ((kDown & KEY_A) || ((TouchInRect(114, 76, 204, 164)) && (kDown & KEY_TOUCH))) Audio_TogglePlayback(SFX); - pp2d_begin_draw(GFX_BOTTOM, GFX_LEFT); - - pp2d_draw_texture(TEXTURE_MUSIC_BOTTOM_BG, 0, 0); - - if (!(Audio_IsPaused(SFX))) - pp2d_draw_texture(TEXTURE_MUSIC_PAUSE, ((320.0 - pp2d_get_texture_width(TEXTURE_MUSIC_PAUSE)) / 2.0) - 2, - ((240.0 - pp2d_get_texture_height(TEXTURE_MUSIC_PAUSE)) / 2.0)); + if ((kDown & KEY_Y) || ((TouchInRect(((320 - btn_repeat.subtex->width) / 2) + 65, ((240 - btn_shuffle.subtex->height) / 2) + 35, + (((320 - btn_repeat.subtex->width) / 2) + 65) + 30, (((240 - btn_shuffle.subtex->height) / 2) + 35) + 30)) && (kDown & KEY_TOUCH))) + { + if (state == MUSIC_STATE_REPEAT) + state = MUSIC_STATE_NONE; else - pp2d_draw_texture(TEXTURE_MUSIC_PLAY, ((320.0 - pp2d_get_texture_width(TEXTURE_MUSIC_PLAY)) / 2.0), - ((240.0 - pp2d_get_texture_height(TEXTURE_MUSIC_PLAY)) / 2.0)); - - pp2d_end_draw(); - - pp2d_begin_draw(GFX_TOP, GFX_LEFT); - - pp2d_draw_texture(TEXTURE_MUSIC_TOP_BG, 0, 0); - - StatusBar_DisplayBar(); - - if (isMP3) // Only print out ID3 tag info for MP3 - { - pp2d_draw_textf(5, 20, 0.5f, 0.5f, RGBA8(255, 255, 255, 255), "%s", fileName); - pp2d_draw_textf(5, 36, 0.45f, 0.45f, RGBA8(255, 255, 255, 255), "%s", ID3.artist); - - pp2d_draw_textf(184, 64, 0.5f, 0.5f, RGBA8(255, 255, 255, 255), "%.30s", ID3.title); - pp2d_draw_textf(184, 84, 0.5f, 0.5f, RGBA8(255, 255, 255, 255), "%.30s", ID3.album); - pp2d_draw_textf(184, 104, 0.5f, 0.5f, RGBA8(255, 255, 255, 255), "%.30s", ID3.year); - pp2d_draw_textf(184, 124, 0.5f, 0.5f, RGBA8(255, 255, 255, 255), "%.30s", ID3.genre); - } - + state = MUSIC_STATE_REPEAT; + } + else if ((kDown & KEY_X) || ((TouchInRect(((320 - btn_shuffle.subtex->width) / 2) - 65, ((240 - btn_shuffle.subtex->height) / 2) + 35, + (((320 - btn_shuffle.subtex->width) / 2) - 65) + 30, (((240 - btn_shuffle.subtex->height) / 2) + 35) + 30)) && (kDown & KEY_TOUCH))) + { + if (state == MUSIC_STATE_SHUFFLE) + state = MUSIC_STATE_NONE; else - pp2d_draw_textf(5, 25, 0.5f, 0.5f, RGBA8(255, 255, 255, 255), "%s", fileName); - - pp2d_end_draw(); + state = MUSIC_STATE_SHUFFLE; + } + + if ((kDown & KEY_LEFT) || (kDown & KEY_L) || ((TouchInRect(((320 - btn_rewind.subtex->width) / 2) - 80, ((240 - btn_rewind.subtex->height) / 2), + (((320 - btn_rewind.subtex->width) / 2) - 80) + 45, ((240 - btn_rewind.subtex->height) / 2) + 45)) && (kDown & KEY_TOUCH))) + { + wait(1); + Music_HandleNext(false, MUSIC_STATE_NONE); + } + else if ((kDown & KEY_RIGHT) || (kDown & KEY_R) || ((TouchInRect(((320 - btn_forward.subtex->width) / 2) + 80, ((240 - btn_forward.subtex->height) / 2), + (((320 - btn_forward.subtex->width) / 2) + 80) + 45, ((240 - btn_forward.subtex->height) / 2) + 45)) && (kDown & KEY_TOUCH))) + { + wait(1); + Music_HandleNext(true, MUSIC_STATE_NONE); + } if (kDown & KEY_B) { - wait(10); - Music_StopPlayback(); + wait(1); + Audio_StopPlayback(); break; } + if (!Audio_IsPlaying()) + { + wait(1); + + if (state == MUSIC_STATE_NONE) + { + Audio_StopPlayback(); + break; + } + else if (state == MUSIC_STATE_REPEAT) + Music_HandleNext(false, MUSIC_STATE_REPEAT); + else if (state == MUSIC_STATE_SHUFFLE) + Music_HandleNext(false, MUSIC_STATE_SHUFFLE); + } + if (((kHeld & KEY_L) && (kDown & KEY_R)) || ((kHeld & KEY_R) && (kDown & KEY_L))) Screenshot_Capture(); } @@ -311,11 +264,18 @@ void Music_Player(char * path) threadFree(thread); // Clear ID3 - memset(ID3.artist, 0, 30); - memset(ID3.title, 0, 30); - memset(ID3.album, 0, 30); - memset(ID3.year, 0, 4); - memset(ID3.genre, 0, 30); + if (isMP3) + { + memset(ID3.artist, 0, 30); + memset(ID3.title, 0, 30); + memset(ID3.album, 0, 30); + memset(ID3.year, 0, 4); + memset(ID3.genre, 0, 30); + } + memset(title, 0, sizeof(title)); + memset(playlist, 0, sizeof(playlist[0][0]) * 512 * 512); + count = 0; + aptSetSleepAllowed(true); return; } \ No newline at end of file diff --git a/source/menus/menu_properties.c b/source/menus/menu_properties.c deleted file mode 100644 index d818f09..0000000 --- a/source/menus/menu_properties.c +++ /dev/null @@ -1,82 +0,0 @@ -#include "common.h" -#include "dir_list.h" -#include "language.h" -#include "menu_properties.h" -#include "pp2d.h" -#include "textures.h" -#include "theme.h" -#include "touch.h" -#include "utils.h" - -struct colour Options_select_colour; -struct colour Options_text_colour; -struct colour Options_title_text_colour; -struct colour Settings_title_text_colour; - -void Menu_DisplayProperties(void) -{ - File * file = Dirlist_GetFileIndex(position); - - char path[255], fullPath[500]; - - strcpy(fileName, file->name); - - strcpy(path, cwd); - - char fileSize[16]; - if (!(file->isDir)) - Utils_GetSizeString(fileSize, file->size); - - u32 totalSize = 0, directories = 0, files = 0; - - pp2d_draw_texture(TEXTURE_PROPERTIES, 36, 20); - - pp2d_draw_text(41, 33, 0.45f, 0.45f, RGBA8(Settings_title_text_colour.r, Settings_title_text_colour.g, Settings_title_text_colour.b, 255), lang_properties[language][0]); - - pp2d_draw_text(247, 201, 0.45f, 0.45f, RGBA8(Settings_title_text_colour.r, Settings_title_text_colour.g, Settings_title_text_colour.b, 255), lang_properties[language][6]); - - pp2d_draw_text(((320 - pp2d_get_text_width(lang_properties[language][1], 0.45f, 0.45f)) / 2), 50, 0.45f, 0.45f, RGBA8(Options_title_text_colour.r, Options_title_text_colour.g, Options_title_text_colour.b, 255), lang_properties[language][1]); - - pp2d_draw_text(42, 74, 0.45f, 0.45f, RGBA8(Options_title_text_colour.r, Options_title_text_colour.g, Options_title_text_colour.b, 255), lang_properties[language][2]); - pp2d_draw_textf(100, 74, 0.45f, 0.45f, RGBA8(Options_text_colour.r, Options_text_colour.g, Options_text_colour.b, 255), "%.28s", fileName); - pp2d_draw_text(42, 94, 0.45f, 0.45f, RGBA8(Options_title_text_colour.r, Options_title_text_colour.g, Options_title_text_colour.b, 255), lang_properties[language][3]); - pp2d_draw_textf(100, 94, 0.45f, 0.45f, RGBA8(Options_text_colour.r, Options_text_colour.g, Options_text_colour.b, 255), "%.28s", path); - - pp2d_draw_text(42, 114, 0.45f, 0.45f, RGBA8(Options_title_text_colour.r, Options_title_text_colour.g, Options_title_text_colour.b, 255), lang_properties[language][4]); - - if (file->isDir) - pp2d_draw_text(100, 114, 0.45f, 0.45f, RGBA8(Options_text_colour.r, Options_text_colour.g, Options_text_colour.b, 255), lang_files[language][1]); - else if ((strncmp(file->ext, "CIA", 3) == 0) || (strncmp(file->ext, "cia", 3) == 0) || (strncmp(file->ext, "3DS", 3) == 0) || (strncmp(file->ext, "3ds", 3) == 0)) - pp2d_draw_text(100, 114, 0.45f, 0.45f, RGBA8(Options_text_colour.r, Options_text_colour.g, Options_text_colour.b, 255), lang_files[language][2]); - else if ((strncmp(file->ext, "bin", 3) == 0) || (strncmp(file->ext, "BIN", 3) == 0) || (strncmp(file->ext, "fir", 3) == 0) || (strncmp(file->ext, "FIR", 3) == 0)) - pp2d_draw_text(100, 114, 0.45f, 0.45f, RGBA8(Options_text_colour.r, Options_text_colour.g, Options_text_colour.b, 255), lang_files[language][3]); - else if ((strncmp(file->ext, "zip", 3) == 0) || (strncmp(file->ext, "ZIP", 3) == 0)) - pp2d_draw_text(100, 114, 0.45f, 0.45f, RGBA8(Options_text_colour.r, Options_text_colour.g, Options_text_colour.b, 255), lang_files[language][4]); - else if ((strncmp(file->ext, "rar", 3) == 0) || (strncmp(file->ext, "RAR", 3) == 0)) - pp2d_draw_text(100, 114, 0.45f, 0.45f, RGBA8(Options_text_colour.r, Options_text_colour.g, Options_text_colour.b, 255), lang_files[language][5]); - else if ((strncmp(file->ext, "PNG", 3) == 0) || (strncmp(file->ext, "png", 3) == 0)) - pp2d_draw_text(100, 114, 0.45f, 0.45f, RGBA8(Options_text_colour.r, Options_text_colour.g, Options_text_colour.b, 255), lang_files[language][6]); - else if ((strncmp(file->ext, "JPG", 3) == 0) || (strncmp(file->ext, "jpg", 3) == 0)) - pp2d_draw_text(100, 114, 0.45f, 0.45f, RGBA8(Options_text_colour.r, Options_text_colour.g, Options_text_colour.b, 255), lang_files[language][7]); - else if ((strncmp(file->ext, "MP3", 3) == 0) || (strncmp(file->ext, "mp3", 3) == 0)) - pp2d_draw_text(100, 114, 0.45f, 0.45f, RGBA8(Options_text_colour.r, Options_text_colour.g, Options_text_colour.b, 255), lang_files[language][8]); - else if ((strncmp(file->ext, "txt", 3) == 0) || (strncmp(file->ext, "TXT", 3) == 0) || (strncmp(file->ext, "XML", 3) == 0) || (strncmp(file->ext, "xml", 3) == 0)) - pp2d_draw_text(100, 114, 0.45f, 0.45f, RGBA8(Options_text_colour.r, Options_text_colour.g, Options_text_colour.b, 255), lang_files[language][9]); - else - pp2d_draw_text(100, 114, 0.45f, 0.45f, RGBA8(Options_text_colour.r, Options_text_colour.g, Options_text_colour.b, 255), lang_files[language][10]); - - if (!(file->isDir)) - { - pp2d_draw_text(42, 134, 0.45f, 0.45f, RGBA8(Options_title_text_colour.r, Options_title_text_colour.g, Options_title_text_colour.b, 255), lang_properties[language][5]); - pp2d_draw_textf(100, 134, 0.45f, 0.45f, RGBA8(Options_text_colour.r, Options_text_colour.g, Options_text_colour.b, 255), "%.28s", fileSize); - } -} - -void Menu_ControlProperties(u32 input) -{ - if ((input & KEY_B) || (input & KEY_A) || (touchInRect(36, 192, 284, 220))) - { - wait(1); - MENU_DEFAULT_STATE = MENU_STATE_OPTIONS; - } -} \ No newline at end of file diff --git a/source/menus/menu_settings.c b/source/menus/menu_settings.c index cb6b17a..e7d20a6 100644 --- a/source/menus/menu_settings.c +++ b/source/menus/menu_settings.c @@ -1,95 +1,253 @@ +#include "C2D_helper.h" #include "common.h" -#include "dir_list.h" -#include "language.h" +#include "config.h" +#include "dirbrowse.h" +#include "menu_main.h" #include "menu_settings.h" -#include "pp2d.h" +#include "status_bar.h" #include "textures.h" -#include "theme.h" #include "touch.h" #include "utils.h" -struct colour Settings_colour; -struct colour Settings_title_text_colour; -struct colour Settings_text_colour; -struct colour Settings_text_min_colour; +static int selection = 0, max_items = 3; +static float confirm_width = 0, confirm_height = 0; -void Menu_DisplaySettings(void) +void Menu_DisplayAbout(void) { - pp2d_draw_rectangle(0, 20, 320, 220, RGBA8(Settings_colour.r, Settings_colour.g, Settings_colour.b, 255)); + float text_width1 = 0, text_width2 = 0, text_width3 = 0, text_width4 = 0; + Draw_GetTextSize(0.45f, &text_width1, NULL, "3D Shell vx.x.x - xxxxxxx"); + Draw_GetTextSize(0.45f, &text_width2, NULL, "Author: Joel16"); + Draw_GetTextSize(0.45f, &text_width3, NULL, "Assets: Preetisketch/CyanogenMod/LineageOS"); + Draw_GetTextSize(0.45f, &text_width4, NULL, "Music player: deltabeard"); + Draw_GetTextSize(0.45f, &confirm_width, &confirm_height, "OK"); - pp2d_draw_text(10, 30, 0.45f, 0.45f, RGBA8(Settings_title_text_colour.r, Settings_title_text_colour.g, Settings_title_text_colour.b, 255), lang_settings[language][0]); + Draw_Image(config_dark_theme? dialog_dark : dialog, ((320 - (dialog.subtex->width)) / 2), ((240 - (dialog.subtex->height)) / 2)); - pp2d_draw_text(10, 50, 0.45f, 0.45f, RGBA8(Settings_text_colour.r, Settings_text_colour.g, Settings_text_colour.b, 255), "Sort by"); - pp2d_draw_text(10, 62, 0.45f, 0.45f, RGBA8(Settings_text_min_colour.r, Settings_text_min_colour.g, Settings_text_min_colour.b, 255), "Select from a list of sorting options."); + Draw_Text(((320 - (dialog.subtex->width)) / 2) + 6, ((240 - (dialog.subtex->height)) / 2) + 6, 0.45f, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR, "About"); - pp2d_draw_text(10, 85, 0.45f, 0.45f, RGBA8(Settings_text_colour.r, Settings_text_colour.g, Settings_text_colour.b, 255), lang_settings[language][5]); - pp2d_draw_text(10, 97, 0.45f, 0.45f, RGBA8(Settings_text_min_colour.r, Settings_text_min_colour.g, Settings_text_min_colour.b, 255), lang_settings[language][6]); + Draw_Textf(((320 - (text_width1)) / 2), ((240 - (dialog.subtex->height)) / 2) + 20, 0.45f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "3D Shell v%d.%d.%d - %s", VERSION_MAJOR, VERSION_MINOR, VERSION_MICRO, GITVERSION); + Draw_Text(((320 - (text_width2)) / 2), ((240 - (dialog.subtex->height)) / 2) + 34, 0.45f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Author: Joel16"); + Draw_Text(((320 - (text_width3)) / 2), ((240 - (dialog.subtex->height)) / 2) + 48, 0.45f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Assets: Preetisketch/CyanogenMod/LineageOS"); + Draw_Text(((320 - (text_width4)) / 2), ((240 - (dialog.subtex->height)) / 2) + 62, 0.45f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Music player: deltabeard"); - pp2d_draw_text(10, 120, 0.45f, 0.45f, RGBA8(Settings_text_colour.r, Settings_text_colour.g, Settings_text_colour.b, 255), lang_settings[language][1]); - pp2d_draw_text(10, 132, 0.45f, 0.45f, RGBA8(Settings_text_min_colour.r, Settings_text_min_colour.g, Settings_text_min_colour.b, 255), lang_settings[language][2]); + Draw_Rect((288 - confirm_width) - 5, (159 - confirm_height) - 5, confirm_width + 10, confirm_height + 10, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); + Draw_Text(288 - confirm_width, (159 - confirm_height), 0.45f, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR, "OK"); +} - pp2d_draw_text(10, 155, 0.45f, 0.45f, RGBA8(Settings_text_colour.r, Settings_text_colour.g, Settings_text_colour.b, 255), lang_settings[language][3]); - pp2d_draw_textf(10, 167, 0.45f, 0.45f, RGBA8(Settings_text_min_colour.r, Settings_text_min_colour.g, Settings_text_min_colour.b, 255), "%s %s", lang_settings[language][4], theme_dir); +void Menu_ControlAbout(u32 input) +{ + if ((input & KEY_B) || (input & KEY_A)) + MENU_STATE = MENU_STATE_SETTINGS; - pp2d_draw_text(10, 190, 0.45f, 0.45f, RGBA8(Settings_text_colour.r, Settings_text_colour.g, Settings_text_colour.b, 255), lang_settings[language][7]); - pp2d_draw_textf(10, 202, 0.45f, 0.45f, RGBA8(Settings_text_min_colour.r, Settings_text_min_colour.g, Settings_text_min_colour.b, 255), "%s", lang_settings[language][8]); + if (TouchInRect((288 - confirm_width) - 5, (159 - confirm_height) - 5, ((288 - confirm_width) - 5) + confirm_width + 10, ((159 - confirm_height) - 5) + confirm_height + 10)) + if (input & KEY_TOUCH) + MENU_STATE = MENU_STATE_SETTINGS; +} - if (recycleBin) - pp2d_draw_texture(TEXTURE_TOGGLE_ON, 280, 90); - else - pp2d_draw_texture(TEXTURE_TOGGLE_OFF, 280, 90); +void Menu_DisplaySortSettings(void) +{ + Draw_Rect(0, 0, 320, 20, config_dark_theme? STATUS_BAR_DARK : MENU_BAR_LIGHT); + Draw_Rect(0, 20, 320, 220, config_dark_theme? BLACK_BG : WHITE); + + Menu_DrawMenuBar(); + + Draw_Rect(0, 20, 400, 35, config_dark_theme? MENU_BAR_DARK : STATUS_BAR_LIGHT); // Menu bar + Draw_Text(10, 30, 0.48f, WHITE, "Sorting options"); + + Draw_Rect(0, 55 + (selection * 40), 320, 40, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); + + Draw_Text(10, 60, 0.48f, config_dark_theme? WHITE : BLACK, "Alphabetical \uE01B"); + Draw_Text(10, 75, 0.45f, config_dark_theme? WHITE : BLACK, "Sort alphabetically in ascending order."); + Draw_Text(10, 100, 0.48f, config_dark_theme? WHITE : BLACK, "Alphabetical \uE01C"); + Draw_Text(10, 115, 0.45f, config_dark_theme? WHITE : BLACK, "Sort alphabetically in descending order."); + Draw_Text(10, 140, 0.48f, config_dark_theme? WHITE : BLACK, "Size \uE01B"); + Draw_Text(10, 155, 0.45f, config_dark_theme? WHITE : BLACK, "Sort by size (largest first)."); + Draw_Text(10, 180, 0.48f, config_dark_theme? WHITE : BLACK, "Size \uE01C"); + Draw_Text(10, 195, 0.45f, config_dark_theme? WHITE : BLACK, "Sort by size (smallest first)."); + + Draw_Image(config_sort_by == 0? (config_dark_theme? icon_radio_dark_on : icon_radio_on) : (config_dark_theme? icon_radio_dark_off : icon_radio_off), 270, 60); + Draw_Image(config_sort_by == 1? (config_dark_theme? icon_radio_dark_on : icon_radio_on) : (config_dark_theme? icon_radio_dark_off : icon_radio_off), 270, 100); + Draw_Image(config_sort_by == 2? (config_dark_theme? icon_radio_dark_on : icon_radio_on) : (config_dark_theme? icon_radio_dark_off : icon_radio_off), 270, 140); + Draw_Image(config_sort_by == 3? (config_dark_theme? icon_radio_dark_on : icon_radio_on) : (config_dark_theme? icon_radio_dark_off : icon_radio_off), 270, 180); +} - if (galleryDisplay) - pp2d_draw_texture(TEXTURE_TOGGLE_ON, 280, 125); - else - pp2d_draw_texture(TEXTURE_TOGGLE_OFF, 280, 125); +void Menu_ControlSortSettings(u32 input) +{ + if (input & KEY_B) + MENU_STATE = MENU_STATE_SETTINGS; - if (isHiddenEnabled) - pp2d_draw_texture(TEXTURE_TOGGLE_ON, 280, 195); + if (input & KEY_A) + { + switch (selection) + { + case 0: + config_sort_by = 0; + break; + case 1: + config_sort_by = 1; + break; + case 2: + config_sort_by = 2; + break; + case 3: + config_sort_by = 3; + break; + } + + Dirbrowse_PopulateFiles(true); + Config_Save(config_dark_theme, config_hidden_files, config_sort_by); + } + + if (input & KEY_DDOWN) + selection++; + else if (input & KEY_DUP) + selection--; + + if (TouchInRect(0, 55, 320, 94)) + { + selection = 0; + + if (input & KEY_TOUCH) + { + config_sort_by = 0; + Dirbrowse_PopulateFiles(true); + Config_Save(config_dark_theme, config_hidden_files, config_sort_by); + } + } + else if (TouchInRect(0, 95, 320, 134)) + { + selection = 1; + if (input & KEY_TOUCH) + { + config_sort_by = 1; + Dirbrowse_PopulateFiles(true); + Config_Save(config_dark_theme, config_hidden_files, config_sort_by); + } + } + else if (TouchInRect(0, 135, 320, 174)) + { + selection = 2; + + if (input & KEY_TOUCH) + { + config_sort_by = 2; + Dirbrowse_PopulateFiles(true); + Config_Save(config_dark_theme, config_hidden_files, config_sort_by); + } + } + else if (TouchInRect(0, 175, 320, 215)) + { + selection = 3; + + if (input & KEY_TOUCH) + { + config_sort_by = 3; + Dirbrowse_PopulateFiles(true); + Config_Save(config_dark_theme, config_hidden_files, config_sort_by); + } + } + + Utils_SetMax(&selection, 0, max_items); + Utils_SetMin(&selection, max_items, 0); +} + +void Menu_DisplaySettings(void) +{ + Draw_Rect(0, 0, 320, 20, config_dark_theme? STATUS_BAR_DARK : MENU_BAR_LIGHT); + Draw_Rect(0, 20, 320, 220, config_dark_theme? BLACK_BG : WHITE); + + Menu_DrawMenuBar(); + + Draw_Rect(0, 20, 400, 35, config_dark_theme? MENU_BAR_DARK : STATUS_BAR_LIGHT); // Menu bar + Draw_Text(10, 30, 0.48f, WHITE, "Settings"); + + Draw_Rect(0, 55 + (selection * 40), 320, 40, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); + + Draw_Text(10, 60, 0.48f, config_dark_theme? WHITE : BLACK, "Sort by"); + Draw_Text(10, 75, 0.45f, config_dark_theme? WHITE : BLACK, "Select between various sorting options."); + Draw_Text(10, 100, 0.48f, config_dark_theme? WHITE : BLACK, "Dark theme"); + Draw_Text(10, 115, 0.45f, config_dark_theme? WHITE : BLACK, "Enables dark theme mode."); + Draw_Text(10, 140, 0.48f, config_dark_theme? WHITE : BLACK, "Hidden files"); + Draw_Text(10, 155, 0.45f, config_dark_theme? WHITE : BLACK, "Displays hidden files."); + Draw_Text(10, 180, 0.48f, config_dark_theme? WHITE : BLACK, "About"); + Draw_Text(10, 195, 0.45f, config_dark_theme? WHITE : BLACK, "Details about application."); + + if (config_dark_theme) + Draw_Image(config_dark_theme? icon_toggle_dark_on : icon_toggle_on, 270, 97); else - pp2d_draw_texture(TEXTURE_TOGGLE_OFF, 280, 195); + Draw_Image(icon_toggle_off, 270, 97); - pp2d_draw_texture(TEXTURE_THEMES_LAUNCHER, 283, 155); + Draw_Image(config_hidden_files? (config_dark_theme? icon_toggle_dark_on : icon_toggle_on) : icon_toggle_off, 270, 137); } void Menu_ControlSettings(u32 input) { - if ((input & KEY_TOUCH) && (touchInRect(0, 50, 320, 72))) + if (input & KEY_B) + MENU_STATE = MENU_STATE_HOME; + + if (input & KEY_A) { - wait(1); - MENU_DEFAULT_STATE = MENU_STATE_SORT; + switch (selection) + { + case 0: + MENU_STATE = MENU_STATE_SORT; + break; + case 1: + config_dark_theme = !config_dark_theme; + Config_Save(config_dark_theme, config_hidden_files, config_sort_by); + break; + case 2: + config_hidden_files = !config_hidden_files; + Config_Save(config_dark_theme, config_hidden_files, config_sort_by); + Dirbrowse_PopulateFiles(true); + break; + case 3: + MENU_STATE = MENU_STATE_ABOUT; + break; + } } - else if ((input & KEY_TOUCH) && (touchInRect(280, 90, 320, 110))) + if (input & KEY_DDOWN) + selection++; + else if (input & KEY_DUP) + selection--; + + if (TouchInRect(0, 55, 320, 94)) { - wait(1); - recycleBin = !recycleBin; - Utils_SaveConfig(sortBy, recycleBin, galleryDisplay, isHiddenEnabled); - } + selection = 0; - else if ((input & KEY_TOUCH) && (touchInRect(280, 125, 320, 145))) + if (input & KEY_TOUCH) + MENU_STATE = MENU_STATE_SORT; + } + else if (TouchInRect(0, 95, 320, 134)) { - wait(1); - galleryDisplay = !galleryDisplay; - Utils_SaveConfig(sortBy, recycleBin, galleryDisplay, isHiddenEnabled); + selection = 1; + + if (input & KEY_TOUCH) + { + config_dark_theme = !config_dark_theme; + Config_Save(config_dark_theme, config_hidden_files, config_sort_by); + } } - - else if ((input & KEY_TOUCH) && (touchInRect(283, 155, 303, 175))) + else if (TouchInRect(0, 135, 320, 174)) { - wait(1); - MENU_DEFAULT_STATE = MENU_STATE_THEMES; - strcpy(cwd, "/3ds/3DShell/themes/"); - Dirlist_PopulateFiles(true); - Dirlist_DisplayFiles(); + selection = 2; + + if (input & KEY_TOUCH) + { + config_hidden_files = !config_hidden_files; + Config_Save(config_dark_theme, config_hidden_files, config_sort_by); + Dirbrowse_PopulateFiles(true); + } } - - else if ((input & KEY_TOUCH) && (touchInRect(280, 195, 320, 215))) + else if (TouchInRect(0, 175, 320, 215)) { - wait(1); - isHiddenEnabled = !isHiddenEnabled; - Utils_SaveConfig(sortBy, recycleBin, galleryDisplay, isHiddenEnabled); + selection = 3; - Dirlist_PopulateFiles(true); - Dirlist_DisplayFiles(); + if (input & KEY_TOUCH) + MENU_STATE = MENU_STATE_ABOUT; } -} \ No newline at end of file + + Utils_SetMax(&selection, 0, max_items); + Utils_SetMin(&selection, max_items, 0); +} diff --git a/source/menus/menu_sort.c b/source/menus/menu_sort.c deleted file mode 100644 index c9c3570..0000000 --- a/source/menus/menu_sort.c +++ /dev/null @@ -1,96 +0,0 @@ -#include "common.h" -#include "dir_list.h" -#include "language.h" -#include "menu_sort.h" -#include "pp2d.h" -#include "textures.h" -#include "theme.h" -#include "touch.h" -#include "utils.h" - -struct colour Settings_colour; -struct colour Settings_title_text_colour; -struct colour Settings_text_colour; -struct colour Settings_text_min_colour; - -void Menu_DisplaySort(void) -{ - pp2d_draw_rectangle(0, 20, 320, 220, RGBA8(Settings_colour.r, Settings_colour.g, Settings_colour.b, 255)); - - pp2d_draw_text(10, 30, 0.45f, 0.45f, RGBA8(Settings_title_text_colour.r, Settings_title_text_colour.g, Settings_title_text_colour.b, 255), "Sorting options"); - - pp2d_draw_text(10, 50, 0.45f, 0.45f, RGBA8(Settings_text_colour.r, Settings_text_colour.g, Settings_text_colour.b, 255), "None"); - pp2d_draw_text(10, 62, 0.45f, 0.45f, RGBA8(Settings_text_min_colour.r, Settings_text_min_colour.g, Settings_text_min_colour.b, 255), "No sorting method is applied."); - - pp2d_draw_text(10, 85, 0.45f, 0.45f, RGBA8(Settings_text_colour.r, Settings_text_colour.g, Settings_text_colour.b, 255), "Alphabetical \uE01B"); - pp2d_draw_text(10, 97, 0.45f, 0.45f, RGBA8(Settings_text_min_colour.r, Settings_text_min_colour.g, Settings_text_min_colour.b, 255), "Sort alphabetically in ascending order."); - - pp2d_draw_text(10, 120, 0.45f, 0.45f, RGBA8(Settings_text_colour.r, Settings_text_colour.g, Settings_text_colour.b, 255), "Alphabetical \uE01C"); - pp2d_draw_text(10, 132, 0.45f, 0.45f, RGBA8(Settings_text_min_colour.r, Settings_text_min_colour.g, Settings_text_min_colour.b, 255), "Sort alphabetically in descending order."); - - pp2d_draw_text(10, 155, 0.45f, 0.45f, RGBA8(Settings_text_colour.r, Settings_text_colour.g, Settings_text_colour.b, 255), "Size \uE01B"); - pp2d_draw_text(10, 167, 0.45f, 0.45f, RGBA8(Settings_text_min_colour.r, Settings_text_min_colour.g, Settings_text_min_colour.b, 255), "Sort by size (largest first)."); - - pp2d_draw_text(10, 190, 0.45f, 0.45f, RGBA8(Settings_text_colour.r, Settings_text_colour.g, Settings_text_colour.b, 255), "Size \uE01C"); - pp2d_draw_text(10, 202, 0.45f, 0.45f, RGBA8(Settings_text_min_colour.r, Settings_text_min_colour.g, Settings_text_min_colour.b, 255), "Sort by size (smallest first)."); - - pp2d_draw_texture(sortBy == 0? TEXTURE_RADIO_ON : TEXTURE_RADIO_OFF, 280, 55); - pp2d_draw_texture(sortBy == 1? TEXTURE_RADIO_ON : TEXTURE_RADIO_OFF, 280, 90); - pp2d_draw_texture(sortBy == 2? TEXTURE_RADIO_ON : TEXTURE_RADIO_OFF, 280, 125); - pp2d_draw_texture(sortBy == 3? TEXTURE_RADIO_ON : TEXTURE_RADIO_OFF, 280, 160); - pp2d_draw_texture(sortBy == 4? TEXTURE_RADIO_ON : TEXTURE_RADIO_OFF, 280, 195); -} - -void Menu_ControlSort(u32 input) -{ - if ((input & KEY_TOUCH) && (touchInRect(280, 55, 320, 75))) - { - wait(1); - sortBy = 0; - Utils_SaveConfig(sortBy, recycleBin, galleryDisplay, isHiddenEnabled); - Dirlist_PopulateFiles(true); - Dirlist_DisplayFiles(); - } - - else if ((input & KEY_TOUCH) && (touchInRect(280, 90, 320, 110))) - { - wait(1); - sortBy = 1; - Utils_SaveConfig(sortBy, recycleBin, galleryDisplay, isHiddenEnabled); - Dirlist_PopulateFiles(true); - Dirlist_DisplayFiles(); - } - - else if ((input & KEY_TOUCH) && (touchInRect(280, 125, 320, 145))) - { - wait(1); - sortBy = 2; - Utils_SaveConfig(sortBy, recycleBin, galleryDisplay, isHiddenEnabled); - Dirlist_PopulateFiles(true); - Dirlist_DisplayFiles(); - } - - else if ((input & KEY_TOUCH) && (touchInRect(280, 160, 320, 180))) - { - wait(1); - sortBy = 3; - Utils_SaveConfig(sortBy, recycleBin, galleryDisplay, isHiddenEnabled); - Dirlist_PopulateFiles(true); - Dirlist_DisplayFiles(); - } - - else if ((input & KEY_TOUCH) && (touchInRect(280, 195, 320, 215))) - { - wait(1); - sortBy = 4; - Utils_SaveConfig(sortBy, recycleBin, galleryDisplay, isHiddenEnabled); - Dirlist_PopulateFiles(true); - Dirlist_DisplayFiles(); - } - - if (input & KEY_B) - { - wait(1); - MENU_DEFAULT_STATE = MENU_STATE_SETTINGS; - } -} \ No newline at end of file diff --git a/source/menus/menu_textviewer.c b/source/menus/menu_textviewer.c deleted file mode 100644 index 42b1692..0000000 --- a/source/menus/menu_textviewer.c +++ /dev/null @@ -1,273 +0,0 @@ -#include -#include -#include - -#include "common.h" -#include "dir_list.h" -#include "fs.h" -#include "menu_textviewer.h" -#include "pp2d.h" -#include "screenshot.h" -#include "status_bar.h" -#include "textures.h" -#include "utils.h" - -struct TextViewer -{ - Handle handle; - struct Text *text; - char *path; - int opened; - u64 lines; -}; - -struct Text -{ - int line; - char *contents; -}; - -static Result TextViewer_ReadData(struct TextViewer *textViewer, char **contents) -{ - Result ret = 0; - char *temp; - u32 bytesRead = 0; - u64 offset = 1; - - u64 fizeSize = FS_GetFileSize(archive, textViewer->path); - - temp = (char*)malloc(sizeof(char) * (fizeSize + 10)); - *contents = (char*)malloc(sizeof(char) * (fizeSize + 10)); - - if (temp == NULL) - return -1; - - if (R_FAILED(ret = FSFILE_Read(textViewer->handle, &bytesRead, offset, temp, fizeSize))) - { - FSFILE_Close(textViewer->handle); - return ret; - } - - offset += bytesRead; - - if (R_FAILED(ret = FSFILE_Close(textViewer->handle))) - return ret; - - strncpy(*contents, temp, fizeSize); - free(temp); - - return 0; -} - -static u64 TextViewer_CountLines(char *path) -{ - FILE *file = fopen(path, "r"); - int ch = 0; - u64 count = 0; - - do { - ch = fgetc(file); - if (ch == '\n') - count++; - } while(ch != EOF); - - fclose(file); - return count; -} - -static u64 TextViewer_ApplyContents(struct TextViewer *textViewer, char *contents) -{ - if (textViewer == NULL) - return -1; - - char *token; - int line_index = 0; - - token = strtok(contents, "\n"); - printf("token %s\n", token); - - if (token == NULL) - return -1; - - if (token != NULL) - { - textViewer->lines = TextViewer_CountLines(textViewer->path); - textViewer->text = (struct Text*)malloc(sizeof(struct Text) * textViewer->lines); - textViewer->text[line_index].contents = malloc(sizeof(char) * strlen(contents) + 1); - textViewer->text[line_index].line = line_index; - strcpy(textViewer->text[line_index].contents, token); - line_index += 1; - } - - token = strtok(NULL, "\n"); - - while(token != NULL) - { - textViewer->text[line_index].contents = malloc(sizeof(char*) * (strlen(token) + 1)); - strcpy(textViewer->text[line_index].contents, token); - textViewer->text[line_index].line = line_index; - line_index += 1; - token = strtok(NULL, "\n"); - } - - return 0; -} - -static Result TextViewer_Init(struct TextViewer *textViewer, const char path[]) -{ - Result ret = 0; - - if (textViewer == NULL) - return -1; - - if (R_FAILED(ret = FS_Open(&textViewer->handle, archive, path, FS_OPEN_READ))) - { - FSFILE_Close(textViewer->handle); - return ret; - } - - textViewer->path = (char*)malloc(sizeof(char) * (strlen(path) + 3)); - strcpy(textViewer->path, path); - - return 0; -} - -static int TextViewer_GetLineIndex(struct TextViewer *textViewer, int index, char **buf, int *line_number) -{ - *buf = (char*)malloc(sizeof(char) * (strlen(textViewer->text[index].contents) + 3)); - if (*buf == NULL) - return -1; - - strcpy(*buf, textViewer->text[index].contents); - *line_number = textViewer->text[index].line; - - return 0; -} - -static int TextViewer_Update(struct TextViewer *textViewer) -{ - if (textViewer == NULL) - return -1; - - /* must free */ - char *contents; - char **bak_contents = &contents; - - if (TextViewer_ReadData(textViewer, &contents) == -1) - { - printf("Failed to read file\n"); - return -1; - } - - if (TextViewer_ApplyContents(textViewer, contents) == -1) - { - printf("Failed to apply\n"); - return -1; - } - - if (*bak_contents) - free(*bak_contents); - - return 0; -} - -static void TextViewer_DrawUI(int current_line, struct TextViewer *textViewer) -{ - int textline_index = 0; - char *linebuf; - int line_number; - char *line_number_buf; - - line_number_buf = (char*)malloc(sizeof(char) * 100); - - pp2d_draw_texture(TEXTURE_TEXTVIEWER_BG, 0, 0); - - StatusBar_DisplayBar(); - - if (line_number_buf == NULL) - { - printf("Memory error\n"); - return ; - } - - pp2d_draw_text(36, 28, 0.45f, 0.45f, RGBA8(255, 255, 255, 255), fileName); - - for (textline_index = current_line; textline_index < textViewer->lines; textline_index++) - { - if ((textline_index-current_line) == 30) - break; - - if ((current_line+30) > textViewer->lines) - break; - - if (TextViewer_GetLineIndex(textViewer, textline_index, &linebuf, &line_number) == 0) - { - memset(line_number_buf, '\0', 100); - snprintf(line_number_buf, 10, "%d", line_number+1); - - pp2d_draw_text(10, 58 + ((textline_index - current_line) * 14), 0.45f, 0.45f, RGBA8(0, 0, 0, 255), linebuf); - - if (linebuf) - { - free(linebuf); - linebuf = NULL; - } - } - } - - if (line_number_buf) - free(line_number_buf); -} - -void TextViewer_DisplayText(char * path) -{ - int current_line = 0; - struct TextViewer textViewer; - - if (TextViewer_Init(&textViewer, path) == -1) - { - printf("failed to open\n"); - return; - } - - if (TextViewer_Update(&textViewer) == -1) - { - printf("failed to run\n"); - return; - } - - while (aptMainLoop()) - { - hidScanInput(); - - u32 kDown = hidKeysDown(); - u32 kHeld = hidKeysHeld(); - - pp2d_begin_draw(GFX_TOP, GFX_LEFT); - - TextViewer_DrawUI(current_line, &textViewer); - - if (kDown & KEY_DUP) - { - if (current_line > 0) - current_line -= 1; - } - - else if (kDown & KEY_DDOWN) - { - if (current_line + 30 <= textViewer.lines - 1) - current_line += 1; - } - - pp2d_end_draw(); - - if (kDown & KEY_B) - { - wait(10); - break; - } - - if (((kHeld & KEY_L) && (kDown & KEY_R)) || ((kHeld & KEY_R) && (kDown & KEY_L))) - Screenshot_Capture(); - } -} \ No newline at end of file diff --git a/source/menus/menu_update.c b/source/menus/menu_update.c index bf44446..e3e3511 100644 --- a/source/menus/menu_update.c +++ b/source/menus/menu_update.c @@ -1,27 +1,23 @@ +#include + +#include "C2D_helper.h" #include "cia.h" #include "common.h" +#include "config.h" #include "fs.h" -#include "language.h" +#include "menu_main.h" #include "menu_update.h" #include "net.h" -#include "pp2d.h" #include "textures.h" -#include "theme.h" #include "touch.h" #include "utils.h" -struct colour Settings_colour; -struct colour Settings_title_text_colour; -struct colour Settings_text_colour; -struct colour Settings_text_min_colour; - -struct colour BottomScreen_colour; -struct colour Options_title_text_colour; - +static int update_dialog_selection = 0; static bool err = false; -char ver[10]; +static u32 wifiStatus = 0; +static char ver[10]; -bool Menu_ValidateUpdate(bool nighlty) +static bool Menu_ValidateUpdate(bool nighlty) { if (nighlty) { @@ -30,9 +26,9 @@ bool Menu_ValidateUpdate(bool nighlty) u64 size64 = 0; u32 size = 0; - size64 = FS_GetFileSize(archive, "/3ds/3DShell/UPDATE_NIGHTLY.txt"); + FS_GetFileSize(archive, "/3ds/3DShell/UPDATE_NIGHTLY.txt", &size64); size = (u32)size64; - char * buf = (char *)malloc(size + 1); + char *buf = (char *)malloc(size + 1); if (R_FAILED(FS_Read(archive, "/3ds/3DShell/UPDATE_NIGHTLY.txt", size, buf))) { @@ -44,7 +40,7 @@ bool Menu_ValidateUpdate(bool nighlty) sscanf(buf, "%s", ver); free(buf); - if (strcmp(ver, GITVERSION) != 0) + if (strcasecmp(ver, GITVERSION) != 0) return true; return false; @@ -54,100 +50,142 @@ bool Menu_ValidateUpdate(bool nighlty) void Menu_DisplayUpdate(void) { - float err_width = ((320 - pp2d_get_text_height("No updates available.", 0.45f, 0.45f)) / 2); + float err_width = ((320 - Draw_GetTextWidth(0.45f, "No updates available.")) / 2); + + Draw_Rect(0, 0, 320, 20, config_dark_theme? STATUS_BAR_DARK : MENU_BAR_LIGHT); + Draw_Rect(0, 20, 320, 220, config_dark_theme? BLACK_BG : WHITE); - pp2d_draw_rectangle(0, 20, 320, 220, RGBA8(Settings_colour.r, Settings_colour.g, Settings_colour.b, 255)); + Menu_DrawMenuBar(); - pp2d_draw_text(10, 30, 0.45f, 0.45f, RGBA8(Settings_title_text_colour.r, Settings_title_text_colour.g, Settings_title_text_colour.b, 255), "Update Center"); + Draw_Rect(0, 20, 400, 35, config_dark_theme? MENU_BAR_DARK : STATUS_BAR_LIGHT); // Menu bar + Draw_Text(10, 30, 0.48f, WHITE, "Update Center"); - if (err) - pp2d_draw_text(err_width, 60, 0.45f, 0.45f, RGBA8(Settings_text_min_colour.r, Settings_text_min_colour.g, Settings_text_min_colour.b, 255), "No updates available."); + ACU_GetWifiStatus(&wifiStatus); - pp2d_draw_textf(122, 85, 0.45f, 0.45f, RGBA8(Settings_text_colour.r, Settings_text_colour.g, Settings_text_colour.b, 255), "Nightly builds"); - pp2d_draw_textf(52, 97, 0.45f, 0.45f, RGBA8(Settings_text_min_colour.r, Settings_text_min_colour.g, Settings_text_min_colour.b, 255), "Untested builds that may contain bugs."); + if (wifiStatus == 0) + Draw_Text(((320 - Draw_GetTextWidth(0.48f, "WiFi not enabled.")) / 2), 60, 0.45f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "WiFi not enabled."); + else if (err) + Draw_Text(err_width, 60, 0.45f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "No updates available."); - pp2d_draw_rectangle(106, 117, (pp2d_get_text_width("Check for updates", 0.45f, 0.45f) + 10), 20, - RGBA8(Settings_title_text_colour.r, Settings_title_text_colour.g, Settings_title_text_colour.b, 255)); - pp2d_draw_rectangle(110 - 3, 118, (pp2d_get_text_width("Check for updates", 0.45f, 0.45f) + 8), 18, - RGBA8(Settings_colour.r, Settings_colour.g, Settings_colour.b, 255)); - pp2d_draw_rectangle(110 - 2, 119, (pp2d_get_text_width("Check for updates", 0.45f, 0.45f) + 6), 16, - RGBA8(Settings_title_text_colour.r, Settings_title_text_colour.g, Settings_title_text_colour.b, 255)); - pp2d_draw_text(110, 120, 0.45f, 0.45f, RGBA8(Settings_colour.r, Settings_colour.g, Settings_colour.b, 255), "Check for updates"); + Draw_Text(122, 85, 0.45f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Nightly builds"); + Draw_Text(52, 97, 0.45f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Untested builds that may contain bugs."); - pp2d_draw_textf(115, 155, 0.45f, 0.45f, RGBA8(Settings_text_colour.r, Settings_text_colour.g, Settings_text_colour.b, 255), "Milestone builds"); - pp2d_draw_textf(102, 167, 0.45f, 0.45f, RGBA8(Settings_text_min_colour.r, Settings_text_min_colour.g, Settings_text_min_colour.b, 255), "Official release builds."); + Draw_Rect(106, 117, (Draw_GetTextWidth(0.45, "Check for updates") + 10), 20, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR); + Draw_Rect(110 - 3, 118, (Draw_GetTextWidth(0.45, "Check for updates") + 8), 18, config_dark_theme? BLACK_BG : WHITE); + Draw_Rect(110 - 2, 119, (Draw_GetTextWidth(0.45, "Check for updates") + 6), 16, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR); + Draw_Text(110, 120, 0.45f, config_dark_theme? BLACK_BG : WHITE, "Check for updates"); + + Draw_Text(115, 155, 0.45f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Milestone builds"); + Draw_Text(102, 167, 0.45f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Official release builds."); - pp2d_draw_rectangle(106, 187, (pp2d_get_text_width("Check for updates", 0.45f, 0.45f) + 10), 20, - RGBA8(Settings_title_text_colour.r, Settings_title_text_colour.g, Settings_title_text_colour.b, 255)); - pp2d_draw_rectangle(110 - 3, 188, (pp2d_get_text_width("Check for updates", 0.45f, 0.45f) + 8), 18, - RGBA8(Settings_colour.r, Settings_colour.g, Settings_colour.b, 255)); - pp2d_draw_rectangle(110 - 2, 189, (pp2d_get_text_width("Check for updates", 0.45f, 0.45f) + 6), 16, - RGBA8(Settings_title_text_colour.r, Settings_title_text_colour.g, Settings_title_text_colour.b, 255)); - pp2d_draw_text(110, 190, 0.45f, 0.45f, RGBA8(Settings_colour.r, Settings_colour.g, Settings_colour.b, 255), "Check for updates"); + Draw_Rect(106, 187, (Draw_GetTextWidth(0.45, "Check for updates") + 10), 20, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR); + Draw_Rect(110 - 3, 188, (Draw_GetTextWidth(0.45, "Check for updates") + 8), 18, config_dark_theme? BLACK_BG : WHITE); + Draw_Rect(110 - 2, 189, (Draw_GetTextWidth(0.45, "Check for updates") + 6), 16, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR); + Draw_Text(110, 190, 0.45f, config_dark_theme? BLACK_BG : WHITE, "Check for updates"); } void Menu_DisplayUpdate2(void) { - pp2d_draw_rectangle(0, 0, 320, 240, RGBA8(BottomScreen_colour.r, BottomScreen_colour.g, BottomScreen_colour.b, 255)); + float text_width = 0, text2_width = 0;; + float update_confirm_width = 0, update_confirm_height = 0; + float update_cancel_width = 0, update_cancel_height = 0; + + Draw_GetTextSize(0.45f, &text_width, NULL, "This action cannot be undone."); + Draw_GetTextSize(0.45f, &text2_width, NULL, "Do you wish to update?"); + Draw_GetTextSize(0.45f, &update_confirm_width, &update_confirm_height, "YES"); + Draw_GetTextSize(0.45f, &update_cancel_width, &update_cancel_height, "NO"); - pp2d_draw_texture(TEXTURE_DIALOG, 20, 55); + Draw_Image(config_dark_theme? dialog_dark : dialog, ((320 - (dialog.subtex->width)) / 2), ((240 - (dialog.subtex->height)) / 2)); - pp2d_draw_text(27, 72, 0.45f, 0.45f, RGBA8(Settings_title_text_colour.r, Settings_title_text_colour.g, Settings_title_text_colour.b, 255), "Confirm update"); + Draw_Textf(((320 - (dialog.subtex->width)) / 2) + 6, ((240 - (dialog.subtex->height)) / 2) + 6, 0.45f, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR, "New update: %s", ver); - pp2d_draw_text(206, 159, 0.45f, 0.45f, RGBA8(Settings_title_text_colour.r, Settings_title_text_colour.g, Settings_title_text_colour.b, 255), "NO"); - pp2d_draw_text(255, 159, 0.45f, 0.45f, RGBA8(Settings_title_text_colour.r, Settings_title_text_colour.g, Settings_title_text_colour.b, 255), "YES"); + Draw_Text(((320 - (text_width)) / 2), ((240 - (dialog.subtex->height)) / 2) + 40, 0.45f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "This action cannot be undone."); + Draw_Text(((320 - (text2_width)) / 2), ((240 - (dialog.subtex->height)) / 2) + 55, 0.45f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, "Do you wish to update?"); - pp2d_draw_text(((320 - pp2d_get_text_width(lang_deletion[language][1], 0.45f, 0.45f)) / 2), 100, 0.45f, 0.45f, RGBA8(Options_title_text_colour.r, Options_title_text_colour.g, Options_title_text_colour.b, 255), "This action cannot be undone."); - pp2d_draw_text(((320 - pp2d_get_text_width(lang_deletion[language][2], 0.45f, 0.45f)) / 2), 115, 0.45f, 0.45f, RGBA8(Options_title_text_colour.r, Options_title_text_colour.g, Options_title_text_colour.b, 255), "Do you wish to update?"); + if (update_dialog_selection == 0) + Draw_Rect((288 - update_cancel_width) - 5, (159 - update_cancel_height) - 5, update_cancel_width + 10, update_cancel_height + 10, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); + else if (update_dialog_selection == 1) + Draw_Rect((248 - (update_confirm_width)) - 5, (159 - update_confirm_height) - 5, update_confirm_width + 10, update_confirm_height + 10, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); + + Draw_Text(248 - (update_confirm_width), (159 - update_confirm_height), 0.45f, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR, "YES"); + Draw_Text(288 - update_cancel_width, (159 - update_cancel_height), 0.45f, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR, "NO"); } void Menu_ControlUpdate(u32 input) { - if ((input & KEY_TOUCH) && (touchInRect(106, 117, (106) + (pp2d_get_text_width("Check for updates", 0.45f, 0.45f) + 10), 137))) + if ((input & KEY_TOUCH) && (TouchInRect(106, 117, (106) + (Draw_GetTextWidth(0.45, "Check for updates") + 10), 137))) { - wait(1); - Net_DownloadFile("https://github.com/joel16/3DShell/raw/gh-pages/UPDATE_NIGHTLY.txt", "/3ds/3DShell/UPDATE_NIGHTLY.txt"); - if (Menu_ValidateUpdate(true)) - MENU_DEFAULT_STATE = MENU_STATE_UPDATE_2; - else - err = true; + if (wifiStatus != 0) + { + wait(1); + Net_DownloadFile("https://github.com/joel16/3DShell/raw/gh-pages/UPDATE_NIGHTLY.txt", "/3ds/3DShell/UPDATE_NIGHTLY.txt"); + + if (Menu_ValidateUpdate(true)) + MENU_STATE = MENU_STATE_UPDATE_2; + else + err = true; + } } - else if ((input & KEY_TOUCH) && (touchInRect(106, 187, (106) + (pp2d_get_text_width("Check for updates", 0.45f, 0.45f) + 10), 207))) + else if ((input & KEY_TOUCH) && (TouchInRect(106, 187, (106) + (Draw_GetTextWidth(0.45, "Check for updates") + 10), 207))) { - wait(1); - Net_DownloadFile("https://github.com/joel16/3DShell/raw/gh-pages/UPDATE_MILESTONE.txt", "/3ds/3DShell/UPDATE_MILESTONE.txt"); - if (Menu_ValidateUpdate(false)) - MENU_DEFAULT_STATE = MENU_STATE_UPDATE_2; - else - err = true; + if (wifiStatus != 0) + { + wait(1); + Net_DownloadFile("https://github.com/joel16/3DShell/raw/gh-pages/UPDATE_MILESTONE.txt", "/3ds/3DShell/UPDATE_MILESTONE.txt"); + if (Menu_ValidateUpdate(false)) + MENU_STATE = MENU_STATE_UPDATE_2; + else + err = true; + } } } void Menu_ControlUpdate2(u32 input) { - if ((input & KEY_A) || (touchInRect(240, 142, 320, 185))) - { - if(envIsHomebrew()) + if (input & KEY_RIGHT) + update_dialog_selection++; + else if (input & KEY_LEFT) + update_dialog_selection--; + + Utils_SetMax(&update_dialog_selection, 0, 1); + Utils_SetMin(&update_dialog_selection, 1, 0); + + if (input & KEY_B) + { + wait(1); + update_dialog_selection = 0; + MENU_STATE = MENU_STATE_UPDATE; + } + + if (input & KEY_A) + { + if (update_dialog_selection == 1) { - if (FS_FileExists(archive, "/3ds/3DShell/3DShell.3dsx")) - FS_Remove(archive, "/3ds/3DShell/3DShell.3dsx"); - Net_DownloadFile("https://github.com/joel16/3DShell/raw/gh-pages/3DShell.3dsx", "/3ds/3DShell/3DShell.3dsx"); - longjmp(exitJmp, 1); + if (wifiStatus != 0) + { + if (envIsHomebrew()) + { + if (FS_FileExists(archive, "/3ds/3DShell/3DShell.3dsx")) + FS_Remove(archive, "/3ds/3DShell/3DShell.3dsx"); + + Net_DownloadFile("https://github.com/joel16/3DShell/raw/gh-pages/3DShell.3dsx", "/3ds/3DShell/3DShell.3dsx"); + longjmp(exitJmp, 1); + } + else + { + Net_DownloadFile("https://github.com/joel16/3DShell/raw/gh-pages/3DShell.cia", "/3ds/3DShell/3DShell.cia"); + CIA_InstallTitle("/3ds/3DShell/3DShell.cia", MEDIATYPE_SD, true); + } + } } else { - Net_DownloadFile("https://github.com/joel16/3DShell/raw/gh-pages/3DShell.cia", "/3ds/3DShell/3DShell.cia"); - CIA_InstallTitle("/3ds/3DShell/3DShell.cia", MEDIATYPE_SD, true); + wait(1); + update_dialog_selection = 0; + MENU_STATE = MENU_STATE_UPDATE; } - wait(1); - MENU_DEFAULT_STATE = MENU_STATE_HOME; + update_dialog_selection = 0; } - - else if ((input & KEY_B) || (touchInRect(136, 142, 239, 185))) - { - wait(1); - MENU_DEFAULT_STATE = MENU_STATE_UPDATE; - } -} \ No newline at end of file +} diff --git a/source/misc/battery.c b/source/misc/battery.c deleted file mode 100644 index bbac68c..0000000 --- a/source/misc/battery.c +++ /dev/null @@ -1,52 +0,0 @@ -#include <3ds.h> - -#include "battery.h" -#include "pp2d.h" -#include "textures.h" - -static u8 Battery_GetBatteryPercent(void) -{ - u8 batteryPercent = 0; - - if (R_SUCCEEDED(MCUHWC_GetBatteryLevel(&batteryPercent))) - return batteryPercent; - - return 0; -} - -char * Battery_GetBatteryPercentString(void) -{ - static char str[5]; - snprintf(str, 5, "%d%%", Battery_GetBatteryPercent()); - return str; -} - -void Battery_DrawIcons(int x, int y) -{ - u8 batteryPercent = Battery_GetBatteryPercent(); - - if (batteryPercent == 0) - pp2d_draw_texture(TEXTURE_BATTERY_0, x, y); - else if (batteryPercent > 0 && batteryPercent <= 15) - pp2d_draw_texture(TEXTURE_BATTERY_15, x, y); - else if (batteryPercent > 15 && batteryPercent <= 28) - pp2d_draw_texture(TEXTURE_BATTERY_28, x, y); - else if (batteryPercent > 28 && batteryPercent <= 43) - pp2d_draw_texture(TEXTURE_BATTERY_43, x, y); - else if (batteryPercent > 43 && batteryPercent <= 57) - pp2d_draw_texture(TEXTURE_BATTERY_57, x, y); - else if (batteryPercent > 57 && batteryPercent <= 71) - pp2d_draw_texture(TEXTURE_BATTERY_71, x, y); - else if (batteryPercent > 71 && batteryPercent <= 99) - pp2d_draw_texture(TEXTURE_BATTERY_85, x, y); - else if (batteryPercent == 100) - pp2d_draw_texture(TEXTURE_BATTERY_100, x, y); - - u8 batteryState = false; // boolean that represnets charging state - - if (R_SUCCEEDED(PTMU_GetBatteryChargeState(&batteryState))) - { - if (batteryState) - pp2d_draw_texture(TEXTURE_BATTERY_CHARGE, x + 2, y + 2); - } -} \ No newline at end of file diff --git a/source/misc/clock.c b/source/misc/clock.c deleted file mode 100644 index f140b7b..0000000 --- a/source/misc/clock.c +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include - -#include "clock.h" -#include "language.h" - -char * Clock_GetCurrentTime(bool _12hour) -{ - static char buffer[10]; - - time_t unix_time = time(0); - struct tm* time_struct = gmtime((const time_t*)&unix_time); - int hours = time_struct->tm_hour; - int minutes = time_struct->tm_min; - int amOrPm = 0; - - if (_12hour) - { - if (hours < 12) - amOrPm = 1; - if (hours == 0) - hours = 12; - else if (hours > 12) - hours = hours - 12; - - if ((hours >= 1) && (hours < 10)) - snprintf(buffer, 10, "%2i:%02i %s", hours, minutes, amOrPm ? "AM" : "PM"); - else - snprintf(buffer, 10, "%2i:%02i %s", hours, minutes, amOrPm ? "AM" : "PM"); - } - - return buffer; -} - -char * Clock_GetDayOfWeek(bool brief) -{ - time_t unixTime = time(NULL); - struct tm* timeStruct = gmtime((const time_t *)&unixTime); - - static char buffer[16]; - sprintf(buffer, "%s", lang_days[language][timeStruct->tm_wday]); - - if (brief) - buffer[3] = 0; - - return buffer; -} - -char * Clock_GetMonthOfYear(int style) -{ - time_t unixTime = time(NULL); - struct tm* timeStruct = gmtime((const time_t *)&unixTime); - int day = timeStruct->tm_mday; - int year = timeStruct->tm_year + 1900; - - static char buffer[16]; - - if (style == 0) - sprintf(buffer, "%d %s, %d", day, lang_months[language][timeStruct->tm_mon], year); - else - sprintf(buffer, "%s", lang_months[language][timeStruct->tm_mon]); - - if (style == 1) - buffer[3] = 0; - - return buffer; -} diff --git a/source/misc/status_bar.c b/source/misc/status_bar.c deleted file mode 100644 index 4779f8a..0000000 --- a/source/misc/status_bar.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "battery.h" -#include "clock.h" -#include "pp2d.h" -#include "status_bar.h" -#include "textures.h" -#include "wifi.h" - -void StatusBar_DisplayBar(void) -{ - float time_x = 395 - pp2d_get_text_width(Clock_GetCurrentTime(true), 0.45f, 0.45f); - float battery_texture_x = time_x - pp2d_get_texture_width(TEXTURE_BATTERY_100) - 5; - float battery_string_x = battery_texture_x - pp2d_get_text_width(Battery_GetBatteryPercentString(), 0.45f, 0.45f) - 5; - float wifi_x = battery_string_x - pp2d_get_texture_width(TEXTURE_WIFI_3) - 10; - - pp2d_draw_text(time_x, 1, 0.45f, 0.45f, RGBA8(255, 255, 255, 255), Clock_GetCurrentTime(true)); - - Battery_DrawIcons(battery_texture_x, 1); - - pp2d_draw_text(battery_string_x, 1, 0.45f, 0.45f, RGBA8(255, 255, 255, 255), Battery_GetBatteryPercentString()); - - WiFi_DrawIcons(wifi_x, 1); -} \ No newline at end of file diff --git a/source/misc/touch.c b/source/misc/touch.c deleted file mode 100644 index 8101f4a..0000000 --- a/source/misc/touch.c +++ /dev/null @@ -1,19 +0,0 @@ -#include <3ds.h> - -#include "touch.h" - -u16 touchGetX(void) -{ - touchPosition pos; - hidTouchRead(&pos); - - return pos.px; -} - -u16 touchGetY(void) -{ - touchPosition pos; - hidTouchRead(&pos); - - return pos.py; -} \ No newline at end of file diff --git a/source/misc/wifi.c b/source/misc/wifi.c deleted file mode 100644 index a82b5fb..0000000 --- a/source/misc/wifi.c +++ /dev/null @@ -1,30 +0,0 @@ -#include <3ds.h> - -#include "pp2d.h" -#include "textures.h" -#include "wifi.h" - -void WiFi_DrawIcons(int x, int y) -{ - switch (osGetWifiStrength()) - { - case 0: - pp2d_draw_texture(TEXTURE_WIFI_0, x, y); - break; - - case 1: - pp2d_draw_texture(TEXTURE_WIFI_1, x, y); - break; - - case 2: - pp2d_draw_texture(TEXTURE_WIFI_2, x, y); - break; - - case 3: - pp2d_draw_texture(TEXTURE_WIFI_3, x, y); - break; - - default: - pp2d_draw_texture(TEXTURE_WIFI_NULL, x, y); - } -} \ No newline at end of file diff --git a/source/net.c b/source/net.c index e4bec13..1a32641 100644 --- a/source/net.c +++ b/source/net.c @@ -9,13 +9,13 @@ #define USER_AGENT APP_TITLE -static char* result_buf = NULL; +static char *result_buf = NULL; static size_t result_sz = 0; static size_t result_written = 0; // following function is from // https://github.com/angelsl/libctrfgh/blob/master/curl_test/src/main.c -static size_t Net_HandleData(char* ptr, size_t size, size_t nmemb, void* userdata) +static size_t Net_HandleData(char *ptr, size_t size, size_t nmemb, void *userdata) { (void) userdata; const size_t bsz = size*nmemb; @@ -54,7 +54,7 @@ static size_t Net_HandleData(char* ptr, size_t size, size_t nmemb, void* userdat } // From MultiUpdater -static Result Net_SetupContext(CURL *hnd, const char * url) +static Result Net_SetupContext(CURL *hnd, const char *url) { curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L); curl_easy_setopt(hnd, CURLOPT_URL, url); @@ -140,7 +140,7 @@ Result Net_DownloadFile(const char *url, const char *path) FSFILE_Write(fileHandle, &bytesWritten, offset, result_buf, result_written, 0); - ProgressBar_DisplayProgress("Downloading", Utils_Basename(path), 0, 0); + //ProgressBar_DisplayProgress("Downloading", Utils_Basename(path), 0, 0); u64 endTime = osGetTime(); u64 totalTime = endTime - startTime; @@ -155,7 +155,3 @@ Result Net_DownloadFile(const char *url, const char *path) FSFILE_Close(fileHandle); return 0; } - - - - diff --git a/source/pp2d/LICENSE b/source/pp2d/LICENSE deleted file mode 100644 index 51ef706..0000000 --- a/source/pp2d/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2017 Bernardo Giordano - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/source/pp2d/README.md b/source/pp2d/README.md deleted file mode 100644 index c1682cc..0000000 --- a/source/pp2d/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# [pp2d](https://discord.gg/bGKEyfY) - -Plug & Play 2D (unofficial) wrapper for Citro3D. - -## License - -pp2d is licensed under the MIT License. - -## Changes - -* depth parameter (Ryuzaki-MrL) -* standalone pp2d_free_texture (LiquidFenrir) -* 3d support (Robz8) -* load png from memory (ErmanSayin) -* BMP support (blujay) diff --git a/source/pp2d/libnsbmp.c b/source/pp2d/libnsbmp.c deleted file mode 100644 index 173581c..0000000 --- a/source/pp2d/libnsbmp.c +++ /dev/null @@ -1,1371 +0,0 @@ -/* - * Copyright 2006 Richard Wilson - * Copyright 2008 Sean Fox - * - * This file is part of NetSurf's libnsbmp, http://www.netsurf-browser.org/ - * Licenced under the MIT License, - * http://www.opensource.org/licenses/mit-license.php - */ - -/** - * \file - * BMP decoding implementation - * - * This library decode windows bitmaps and icons from their disc images. - * - * The image format is described in several documents: - * https://msdn.microsoft.com/en-us/library/dd183391(v=vs.85).aspx - * http://www.fileformat.info/format/bmp/egff.htm - * https://en.wikipedia.org/wiki/BMP_file_format - * - * Despite the format being clearly defined many bitmaps found on the web are - * not compliant and this implementation attempts to cope with as many issues - * as possible rather than simply failing. - */ - -#include -#include -#include -#include -#include -#include - -#include - -/* squashes unused variable compiler warnings */ -#define UNUSED(x) ((x)=(x)) - -/* BMP entry sizes */ -#define BMP_FILE_HEADER_SIZE 14 -#define ICO_FILE_HEADER_SIZE 6 -#define ICO_DIR_ENTRY_SIZE 16 - -/* the bitmap information header types (encoded as lengths) */ -#define BITMAPCOREHEADER 12 - -#ifdef WE_NEED_INT8_READING_NOW -static inline int8_t read_int8(uint8_t *data, unsigned int o) { - return (int8_t) data[o]; -} -#endif - -static inline uint8_t read_uint8(uint8_t *data, unsigned int o) { - return (uint8_t) data[o]; -} - -static inline int16_t read_int16(uint8_t *data, unsigned int o) { - return (int16_t) (data[o] | (data[o+1] << 8)); -} - -static inline uint16_t read_uint16(uint8_t *data, unsigned int o) { - return (uint16_t) (data[o] | (data[o+1] << 8)); -} - -static inline int32_t read_int32(uint8_t *data, unsigned int o) { - return (int32_t) (data[o] | (data[o+1] << 8) | (data[o+2] << 16) | (data[o+3] << 24)); -} - -static inline uint32_t read_uint32(uint8_t *data, unsigned int o) { - return (uint32_t) (data[o] | (data[o+1] << 8) | (data[o+2] << 16) | (data[o+3] << 24)); -} - - -/** - * Parse the bitmap info header - */ -static bmp_result bmp_info_header_parse(bmp_image *bmp, uint8_t *data) -{ - uint32_t header_size; - uint32_t i; - uint8_t j; - int32_t width, height; - uint8_t palette_size; - unsigned int flags = 0; - - /* must be at least enough data for a core header */ - if (bmp->buffer_size < (BMP_FILE_HEADER_SIZE + BITMAPCOREHEADER)) { - return BMP_INSUFFICIENT_DATA; - } - - header_size = read_uint32(data, 0); - - /* ensure there is enough data for the declared header size*/ - if ((bmp->buffer_size - BMP_FILE_HEADER_SIZE) < header_size) { - return BMP_INSUFFICIENT_DATA; - } - - /* a variety of different bitmap headers can follow, depending - * on the BMP variant. The header length field determines the type. - */ - if (header_size == BITMAPCOREHEADER) { - /* the following header is for os/2 and windows 2.x and consists of: - * - * +0 UINT32 size of this header (in bytes) - * +4 INT16 image width (in pixels) - * +6 INT16 image height (in pixels) - * +8 UINT16 number of colour planes (always 1) - * +10 UINT16 number of bits per pixel - */ - width = read_int16(data, 4); - height = read_int16(data, 6); - if ((width <= 0) || (height == 0)) - return BMP_DATA_ERROR; - if (height < 0) { - bmp->reversed = true; - height = -height; - } - /* ICOs only support 256*256 resolutions - * In the case of the ICO header, the height is actually the added - * height of XOR-Bitmap and AND-Bitmap (double the visible height) - * Technically we could remove this check and ICOs with bitmaps - * of any size could be processed; this is to conform to the spec. - */ - if (bmp->ico) { - if ((width > 256) || (height > 512)) { - return BMP_DATA_ERROR; - } else { - bmp->width = width; - bmp->height = height / 2; - } - } else { - bmp->width = width; - bmp->height = height; - } - if (read_uint16(data, 8) != 1) - return BMP_DATA_ERROR; - bmp->bpp = read_uint16(data, 10); - /** - * The bpp value should be in the range 1-32, but the only - * values considered legal are: - * RGB ENCODING: 1, 4, 8, 16, 24 and 32 - */ - if ((bmp->bpp != 1) && (bmp->bpp != 4) && - (bmp->bpp != 8) && - (bmp->bpp != 16) && - (bmp->bpp != 24) && - (bmp->bpp != 32)) - return BMP_DATA_ERROR; - bmp->colours = (1 << bmp->bpp); - palette_size = 3; - } else if (header_size < 40) { - return BMP_DATA_ERROR; - } else { - /* the following header is for windows 3.x and onwards. it is a - * minimum of 40 bytes and (as of Windows 95) a maximum of 108 bytes. - * - * +0 UINT32 size of this header (in bytes) - * +4 INT32 image width (in pixels) - * +8 INT32 image height (in pixels) - * +12 UINT16 number of colour planes (always 1) - * +14 UINT16 number of bits per pixel - * +16 UINT32 compression methods used - * +20 UINT32 size of bitmap (in bytes) - * +24 UINT32 horizontal resolution (in pixels per meter) - * +28 UINT32 vertical resolution (in pixels per meter) - * +32 UINT32 number of colours in the image - * +36 UINT32 number of important colours - * +40 UINT32 mask identifying bits of red component - * +44 UINT32 mask identifying bits of green component - * +48 UINT32 mask identifying bits of blue component - * +52 UINT32 mask identifying bits of alpha component - * +56 UINT32 color space type - * +60 UINT32 x coordinate of red endpoint - * +64 UINT32 y coordinate of red endpoint - * +68 UINT32 z coordinate of red endpoint - * +72 UINT32 x coordinate of green endpoint - * +76 UINT32 y coordinate of green endpoint - * +80 UINT32 z coordinate of green endpoint - * +84 UINT32 x coordinate of blue endpoint - * +88 UINT32 y coordinate of blue endpoint - * +92 UINT32 z coordinate of blue endpoint - * +96 UINT32 gamma red coordinate scale value - * +100 UINT32 gamma green coordinate scale value - * +104 UINT32 gamma blue coordinate scale value - */ - width = read_int32(data, 4); - height = read_int32(data, 8); - if ((width <= 0) || (height == 0)) - return BMP_DATA_ERROR; - if (height < 0) { - bmp->reversed = true; - if (height <= -INT32_MAX) { - height = INT32_MAX; - } else { - height = -height; - } - } - /* ICOs only support 256*256 resolutions - * In the case of the ICO header, the height is actually the added - * height of XOR-Bitmap and AND-Bitmap (double the visible height) - * Technically we could remove this check and ICOs with bitmaps - * of any size could be processed; this is to conform to the spec. - */ - if (bmp->ico) { - if ((width > 256) || (height > 512)) { - return BMP_DATA_ERROR; - } else { - bmp->width = width; - bmp->height = height / 2; - } - } else { - bmp->width = width; - bmp->height = height; - } - if (read_uint16(data, 12) != 1) - return BMP_DATA_ERROR; - bmp->bpp = read_uint16(data, 14); - if (bmp->bpp == 0) - bmp->bpp = 8; - bmp->encoding = read_uint32(data, 16); - /** - * The bpp value should be in the range 1-32, but the only - * values considered legal are: - * RGB ENCODING: 1, 4, 8, 16, 24 and 32 - * RLE4 ENCODING: 4 - * RLE8 ENCODING: 8 - * BITFIELD ENCODING: 16 and 32 - */ - switch (bmp->encoding) { - case BMP_ENCODING_RGB: - if ((bmp->bpp != 1) && (bmp->bpp != 4) && - (bmp->bpp != 8) && - (bmp->bpp != 16) && - (bmp->bpp != 24) && - (bmp->bpp != 32)) - return BMP_DATA_ERROR; - break; - case BMP_ENCODING_RLE8: - if (bmp->bpp != 8) - return BMP_DATA_ERROR; - break; - case BMP_ENCODING_RLE4: - if (bmp->bpp != 4) - return BMP_DATA_ERROR; - break; - case BMP_ENCODING_BITFIELDS: - if ((bmp->bpp != 16) && (bmp->bpp != 32)) - return BMP_DATA_ERROR; - break; - /* invalid encoding */ - default: - return BMP_DATA_ERROR; - break; - } - /* Bitfield encoding means we have red, green, blue, and alpha masks. - * Here we acquire the masks and determine the required bit shift to - * align them in our 24-bit color 8-bit alpha format. - */ - if (bmp->encoding == BMP_ENCODING_BITFIELDS) { - if (header_size == 40) { - header_size += 12; - if (bmp->buffer_size < (14 + header_size)) - return BMP_INSUFFICIENT_DATA; - for (i = 0; i < 3; i++) - bmp->mask[i] = read_uint32(data, 40 + (i << 2)); - } else { - for (i = 0; i < 4; i++) - bmp->mask[i] = read_uint32(data, 40 + (i << 2)); - } - for (i = 0; i < 4; i++) { - if (bmp->mask[i] == 0) - break; - for (j = 31; j > 0; j--) - if (bmp->mask[i] & (1 << j)) { - if ((j - 7) > 0) - bmp->mask[i] &= 0xff << (j - 7); - else - bmp->mask[i] &= 0xff >> (-(j - 7)); - bmp->shift[i] = (i << 3) - (j - 7); - break; - } - } - } - bmp->colours = read_uint32(data, 32); - if (bmp->colours == 0) - bmp->colours = (1 << bmp->bpp); - palette_size = 4; - } - data += header_size; - - /* if there's no alpha mask, flag the bmp opaque */ - if ((!bmp->ico) && (bmp->mask[3] == 0)) { - flags |= BMP_OPAQUE; - bmp->opaque = true; - } - - /* we only have a palette for <16bpp */ - if (bmp->bpp < 16) { - /* we now have a series of palette entries of the format: - * - * +0 BYTE blue - * +1 BYTE green - * +2 BYTE red - * - * if the palette is from an OS/2 or Win2.x file then the entries - * are padded with an extra byte. - */ - - /* boundary checking */ - if (bmp->buffer_size < (14 + header_size + ((uint64_t)4 * bmp->colours))) - return BMP_INSUFFICIENT_DATA; - - /* create the colour table */ - bmp->colour_table = (uint32_t *)malloc(bmp->colours * 4); - if (!bmp->colour_table) - return BMP_INSUFFICIENT_MEMORY; - for (i = 0; i < bmp->colours; i++) { - bmp->colour_table[i] = data[2] | (data[1] << 8) | (data[0] << 16); - if (bmp->opaque) - bmp->colour_table[i] |= (0xff << 24); - data += palette_size; - bmp->colour_table[i] = read_uint32((uint8_t *)&bmp->colour_table[i],0); - } - - /* some bitmaps have a bad offset if there is a pallete, work - * round this by fixing up the data offset to after the palette - * but only if there is data following the palette as some - * bitmaps encode data in the palette! - */ - if ((bmp->bitmap_offset < (uint32_t)(data - bmp->bmp_data)) && - ((bmp->buffer_size - (data - bmp->bmp_data)) > 0)) { - bmp->bitmap_offset = data - bmp->bmp_data; - } - } - - /* create our bitmap */ - flags |= BMP_NEW | BMP_CLEAR_MEMORY; - bmp->bitmap = bmp->bitmap_callbacks.bitmap_create(bmp->width, bmp->height, flags); - if (!bmp->bitmap) { - if (bmp->colour_table) - free(bmp->colour_table); - bmp->colour_table = NULL; - return BMP_INSUFFICIENT_MEMORY; - } - /* BMPs within ICOs don't have BMP file headers, so the image data should - * always be right after the colour table. - */ - if (bmp->ico) - bmp->bitmap_offset = (intptr_t)data - (intptr_t)bmp->bmp_data; - return BMP_OK; -} - - -/** - * Parse the bitmap file header - * - * \param bmp The bitmap. - * \param data The data for the file header - * \return BMP_OK on success or error code on faliure - */ -static bmp_result bmp_file_header_parse(bmp_image *bmp, uint8_t *data) -{ - /* standard 14-byte BMP file header is: - * - * +0 UINT16 File Type ('BM') - * +2 UINT32 Size of File (in bytes) - * +6 INT16 Reserved Field (1) - * +8 INT16 Reserved Field (2) - * +10 UINT32 Starting Position of Image Data (offset in bytes) - */ - if (bmp->buffer_size < BMP_FILE_HEADER_SIZE) - return BMP_INSUFFICIENT_DATA; - - if ((data[0] != (uint8_t)'B') || (data[1] != (uint8_t)'M')) - return BMP_DATA_ERROR; - - bmp->bitmap_offset = read_uint32(data, 10); - - /* check the offset to data lies within the file */ - if (bmp->bitmap_offset >= bmp->buffer_size) { - return BMP_INSUFFICIENT_DATA; - } - - return BMP_OK; -} - - -/** - * Allocates memory for the next BMP in an ICO collection - * - * Sets proper structure values - * - * \param ico the ICO collection to add the image to - * \param image a pointer to the ICO image to be initialised - */ -static bmp_result next_ico_image(ico_collection *ico, ico_image *image) { - bmp_create(&image->bmp, &ico->bitmap_callbacks); - image->next = ico->first; - ico->first = image; - return BMP_OK; -} - - -/** - * Parse the icon file header - * - * \param ico The icon collection. - * \param data The header data to parse. - * \return BMP_OK on successful parse else error code - */ -static bmp_result ico_header_parse(ico_collection *ico, uint8_t *data) -{ - uint16_t count, i; - bmp_result result; - int area, max_area = 0; - - /* 6-byte ICO file header is: - * - * +0 INT16 Reserved (should be 0) - * +2 UINT16 Type (1 for ICO, 2 for CUR) - * +4 UINT16 Number of BMPs to follow - */ - if (ico->buffer_size < ICO_FILE_HEADER_SIZE) - return BMP_INSUFFICIENT_DATA; - // if (read_int16(data, 2) != 0x0000) - // return BMP_DATA_ERROR; - if (read_uint16(data, 2) != 0x0001) - return BMP_DATA_ERROR; - count = read_uint16(data, 4); - if (count == 0) - return BMP_DATA_ERROR; - data += ICO_FILE_HEADER_SIZE; - - /* check if we have enough data for the directory */ - if (ico->buffer_size < (uint32_t)(ICO_FILE_HEADER_SIZE + (ICO_DIR_ENTRY_SIZE * count))) - return BMP_INSUFFICIENT_DATA; - - /* Decode the BMP files. - * - * 16-byte ICO directory entry is: - * - * +0 UINT8 Width (0 for 256 pixels) - * +1 UINT8 Height (0 for 256 pixels) - * +2 UINT8 Colour count (0 if more than 256 colours) - * +3 INT8 Reserved (should be 0, but may not be) - * +4 UINT16 Colour Planes (should be 0 or 1) - * +6 UINT16 Bits Per Pixel - * +8 UINT32 Size of BMP info header + bitmap data in bytes - * +12 UINT32 Offset (points to the BMP info header, not the bitmap data) - */ - for (i = 0; i < count; i++) { - ico_image *image; - image = calloc(1, sizeof(ico_image)); - if (!image) - return BMP_INSUFFICIENT_MEMORY; - result = next_ico_image(ico, image); - if (result != BMP_OK) - return result; - image->bmp.width = read_uint8(data, 0); - if (image->bmp.width == 0) - image->bmp.width = 256; - image->bmp.height = read_uint8(data, 1); - if (image->bmp.height == 0) - image->bmp.height = 256; - image->bmp.buffer_size = read_uint32(data, 8); - image->bmp.bmp_data = ico->ico_data + read_uint32(data, 12); - image->bmp.ico = true; - data += ICO_DIR_ENTRY_SIZE; - - /* Ensure that the bitmap data resides in the buffer */ - if (image->bmp.bmp_data - ico->ico_data >= 0 && - (uint32_t)(image->bmp.bmp_data - - ico->ico_data) >= ico->buffer_size) - return BMP_DATA_ERROR; - - /* Ensure that we have sufficient data to read the bitmap */ - if (image->bmp.buffer_size - ICO_DIR_ENTRY_SIZE >= - ico->buffer_size - (ico->ico_data - data)) - return BMP_INSUFFICIENT_DATA; - - result = bmp_info_header_parse(&image->bmp, - image->bmp.bmp_data); - if (result != BMP_OK) - return result; - - /* adjust the size based on the images available */ - area = image->bmp.width * image->bmp.height; - if (area > max_area) { - ico->width = image->bmp.width; - ico->height = image->bmp.height; - max_area = area; - } - } - return BMP_OK; -} - - -/** - * Decode BMP data stored in 32bpp colour. - * - * \param bmp the BMP image to decode - * \param start the data to decode, updated to last byte read on success - * \param bytes the number of bytes of data available - * \return BMP_OK on success - * BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly; - * in this case, the image may be partially viewable - */ -static bmp_result bmp_decode_rgb32(bmp_image *bmp, uint8_t **start, int bytes) -{ - uint8_t *top, *bottom, *end, *data; - uint32_t *scanline; - uint32_t x, y; - uint32_t swidth; - uint8_t i; - uint32_t word; - - assert(bmp->bpp == 32); - - data = *start; - swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width; - top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap); - if (!top) - return BMP_INSUFFICIENT_MEMORY; - bottom = top + (uint64_t)swidth * (bmp->height - 1); - end = data + bytes; - bmp->decoded = true; - - /* Determine transparent index */ - if (bmp->limited_trans) { - if ((data + 4) > end) - return BMP_INSUFFICIENT_DATA; - if (bmp->encoding == BMP_ENCODING_BITFIELDS) - bmp->transparent_index = read_uint32(data, 0); - else - bmp->transparent_index = data[2] | (data[1] << 8) | (data[0] << 16); - } - - for (y = 0; y < bmp->height; y++) { - if ((data + (4 * bmp->width)) > end) - return BMP_INSUFFICIENT_DATA; - if (bmp->reversed) - scanline = (void *)(top + (y * swidth)); - else - scanline = (void *)(bottom - (y * swidth)); - if (bmp->encoding == BMP_ENCODING_BITFIELDS) { - for (x = 0; x < bmp->width; x++) { - word = read_uint32(data, 0); - for (i = 0; i < 4; i++) - if (bmp->shift[i] > 0) - scanline[x] |= ((word & bmp->mask[i]) << bmp->shift[i]); - else - scanline[x] |= ((word & bmp->mask[i]) >> (-bmp->shift[i])); - /* 32-bit BMPs have alpha masks, but sometimes they're not utilized */ - if (bmp->opaque) - scanline[x] |= (0xff << 24); - data += 4; - scanline[x] = read_uint32((uint8_t *)&scanline[x],0); - } - } else { - for (x = 0; x < bmp->width; x++) { - scanline[x] = data[2] | (data[1] << 8) | (data[0] << 16); - if ((bmp->limited_trans) && (scanline[x] == bmp->transparent_index)) { - scanline[x] = bmp->trans_colour; - } - if (bmp->opaque) { - scanline[x] |= (0xff << 24); - } else { - scanline[x] |= data[3] << 24; - } - data += 4; - scanline[x] = read_uint32((uint8_t *)&scanline[x],0); - } - } - } - *start = data; - return BMP_OK; -} - - -/** - * Decode BMP data stored in 24bpp colour. - * - * \param bmp the BMP image to decode - * \param start the data to decode, updated to last byte read on success - * \param bytes the number of bytes of data available - * \return BMP_OK on success - * BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly; - * in this case, the image may be partially viewable - */ -static bmp_result bmp_decode_rgb24(bmp_image *bmp, uint8_t **start, int bytes) -{ - uint8_t *top, *bottom, *end, *data; - uint32_t *scanline; - uint32_t x, y; - uint32_t swidth; - intptr_t addr; - - assert(bmp->encoding == BMP_ENCODING_RGB); - assert(bmp->bpp == 24); - - data = *start; - swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width; - top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap); - if (!top) { - return BMP_INSUFFICIENT_MEMORY; - } - - bottom = top + (uint64_t)swidth * (bmp->height - 1); - end = data + bytes; - addr = ((intptr_t)data) & 3; - bmp->decoded = true; - - /* Determine transparent index */ - if (bmp->limited_trans) { - if ((data + 3) > end) { - return BMP_INSUFFICIENT_DATA; - } - - bmp->transparent_index = data[2] | (data[1] << 8) | (data[0] << 16); - } - - for (y = 0; y < bmp->height; y++) { - if ((data + (3 * bmp->width)) > end) { - return BMP_INSUFFICIENT_DATA; - } - - if (bmp->reversed) { - scanline = (void *)(top + (y * swidth)); - } else { - scanline = (void *)(bottom - (y * swidth)); - } - - for (x = 0; x < bmp->width; x++) { - scanline[x] = data[2] | (data[1] << 8) | (data[0] << 16); - if ((bmp->limited_trans) && (scanline[x] == bmp->transparent_index)) { - scanline[x] = bmp->trans_colour; - } else { - scanline[x] |= (0xff << 24); - } - data += 3; - scanline[x] = read_uint32((uint8_t *)&scanline[x],0); - } - - while (addr != (((intptr_t)data) & 3)) { - data++; - } - } - *start = data; - return BMP_OK; -} - - -/** - * Decode BMP data stored in 16bpp colour. - * - * \param bmp the BMP image to decode - * \param start the data to decode, updated to last byte read on success - * \param bytes the number of bytes of data available - * \return BMP_OK on success - * BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly; - * in this case, the image may be partially viewable - */ -static bmp_result bmp_decode_rgb16(bmp_image *bmp, uint8_t **start, int bytes) -{ - uint8_t *top, *bottom, *end, *data; - uint32_t *scanline; - uint32_t x, y, swidth; - intptr_t addr; - uint8_t i; - uint16_t word; - - data = *start; - swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width; - top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap); - if (!top) - return BMP_INSUFFICIENT_MEMORY; - bottom = top + (uint64_t)swidth * (bmp->height - 1); - end = data + bytes; - addr = ((intptr_t)data) & 3; - bmp->decoded = true; - - /* Determine transparent index */ - if (bmp->limited_trans) { - if ((data + 2) > end) - return BMP_INSUFFICIENT_DATA; - bmp->transparent_index = read_uint16(data, 0); - } - - for (y = 0; y < bmp->height; y++) { - if ((data + (2 * bmp->width)) > end) - return BMP_INSUFFICIENT_DATA; - if (bmp->reversed) - scanline = (void *)(top + (y * swidth)); - else - scanline = (void *)(bottom - (y * swidth)); - if (bmp->encoding == BMP_ENCODING_BITFIELDS) { - for (x = 0; x < bmp->width; x++) { - word = read_uint16(data, 0); - if ((bmp->limited_trans) && (word == bmp->transparent_index)) - scanline[x] = bmp->trans_colour; - else { - scanline[x] = 0; - for (i = 0; i < 4; i++) - if (bmp->shift[i] > 0) - scanline[x] |= ((word & bmp->mask[i]) << bmp->shift[i]); - else - scanline[x] |= ((word & bmp->mask[i]) >> (-bmp->shift[i])); - if (bmp->opaque) - scanline[x] |= (0xff << 24); - } - data += 2; - scanline[x] = read_uint32((uint8_t *)&scanline[x],0); - } - } else { - for (x = 0; x < bmp->width; x++) { - word = read_uint16(data, 0); - if ((bmp->limited_trans) && (word == bmp->transparent_index)) - scanline[x] = bmp->trans_colour; - else { - /* 16-bit RGB defaults to RGB555 */ - scanline[x] = ((word & (31 << 0)) << 19) | - ((word & (31 << 5)) << 6) | - ((word & (31 << 10)) >> 7); - } - if (bmp->opaque) - scanline[x] |= (0xff << 24); - data += 2; - scanline[x] = read_uint32((uint8_t *)&scanline[x],0); - } - } - while (addr != (((intptr_t)data) & 3)) - data += 2; - } - *start = data; - return BMP_OK; -} - - -/** - * Decode BMP data stored with a palette and in 8bpp colour or less. - * - * \param bmp the BMP image to decode - * \param start the data to decode, updated to last byte read on success - * \param bytes the number of bytes of data available - * \return BMP_OK on success - * BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly; - * in this case, the image may be partially viewable - */ -static bmp_result bmp_decode_rgb(bmp_image *bmp, uint8_t **start, int bytes) -{ - uint8_t *top, *bottom, *end, *data; - uint32_t *scanline; - intptr_t addr; - uint32_t x, y, swidth; - uint8_t bit_shifts[8]; - uint8_t ppb = 8 / bmp->bpp; - uint8_t bit_mask = (1 << bmp->bpp) - 1; - uint8_t cur_byte = 0, bit, i; - - for (i = 0; i < ppb; i++) - bit_shifts[i] = 8 - ((i + 1) * bmp->bpp); - - data = *start; - swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width; - top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap); - if (!top) - return BMP_INSUFFICIENT_MEMORY; - bottom = top + (uint64_t)swidth * (bmp->height - 1); - end = data + bytes; - addr = ((intptr_t)data) & 3; - bmp->decoded = true; - - /* Determine transparent index */ - if (bmp->limited_trans) { - uint32_t idx = (*data >> bit_shifts[0]) & bit_mask; - if (idx >= bmp->colours) - return BMP_DATA_ERROR; - bmp->transparent_index = bmp->colour_table[idx]; - } - - for (y = 0; y < bmp->height; y++) { - bit = 8; - if ((data + (bmp->width / ppb)) > end) - return BMP_INSUFFICIENT_DATA; - if (bmp->reversed) - scanline = (void *)(top + (y * swidth)); - else - scanline = (void *)(bottom - (y * swidth)); - for (x = 0; x < bmp->width; x++) { - uint32_t idx; - if (bit >= ppb) { - bit = 0; - cur_byte = *data++; - } - idx = (cur_byte >> bit_shifts[bit++]) & bit_mask; - if (idx < bmp->colours) { - /* ensure colour table index is in bounds */ - scanline[x] = bmp->colour_table[idx]; - if ((bmp->limited_trans) && - (scanline[x] == bmp->transparent_index)) { - scanline[x] = bmp->trans_colour; - } - } - } - while (addr != (((intptr_t)data) & 3)) - data++; - } - *start = data; - return BMP_OK; -} - - -/** - * Decode a 1bpp mask for an ICO - * - * \param bmp the BMP image to decode - * \param data the data to decode - * \param bytes the number of bytes of data available - * \return BMP_OK on success - */ -static bmp_result bmp_decode_mask(bmp_image *bmp, uint8_t *data, int bytes) -{ - uint8_t *top, *bottom, *end; - uint32_t *scanline; - intptr_t addr; - uint32_t x, y, swidth; - uint32_t cur_byte = 0; - - swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width; - top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap); - if (!top) - return BMP_INSUFFICIENT_MEMORY; - bottom = top + (uint64_t)swidth * (bmp->height - 1); - end = data + bytes; - - addr = ((intptr_t)data) & 3; - - for (y = 0; y < bmp->height; y++) { - if ((data + (bmp->width >> 3)) > end) - return BMP_INSUFFICIENT_DATA; - scanline = (void *)(bottom - (y * swidth)); - for (x = 0; x < bmp->width; x++) { - if ((x & 7) == 0) - cur_byte = *data++; - scanline[x] = read_uint32((uint8_t *)&scanline[x], 0); - if ((cur_byte & 128) == 0) { - scanline[x] |= (0xff << 24); - } else { - scanline[x] &= 0xffffff; - } - scanline[x] = read_uint32((uint8_t *)&scanline[x], 0); - cur_byte = cur_byte << 1; - } - while (addr != (((intptr_t)data) & 3)) - data++; - } - return BMP_OK; -} - - -/** - * Decode BMP data stored encoded in RLE8. - * - * \param bmp the BMP image to decode - * \param data the data to decode - * \param bytes the number of bytes of data available - * \return BMP_OK on success - * BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly; - * in this case, the image may be partially viewable - */ -static bmp_result -bmp_decode_rle8(bmp_image *bmp, uint8_t *data, int bytes) -{ - uint8_t *top, *bottom, *end; - uint32_t *scanline; - uint32_t swidth; - uint32_t i, length, pixels_left; - uint32_t x = 0, y = 0, last_y = 0; - uint32_t pixel = 0; - - if (bmp->ico) - return BMP_DATA_ERROR; - - swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width; - top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap); - if (!top) - return BMP_INSUFFICIENT_MEMORY; - bottom = top + (uint64_t)swidth * (bmp->height - 1); - end = data + bytes; - bmp->decoded = true; - - do { - if (data + 2 > end) - return BMP_INSUFFICIENT_DATA; - length = *data++; - if (length == 0) { - length = *data++; - switch (length) { - case 0: - /* 00 - 00 means end of scanline */ - x = 0; - if (last_y == y) { - y++; - if (y >= bmp->height) - return BMP_DATA_ERROR; - } - last_y = y; - break; - - case 1: - /* 00 - 01 means end of RLE data */ - return BMP_OK; - - case 2: - /* 00 - 02 - XX - YY means move cursor */ - if (data + 2 > end) - return BMP_INSUFFICIENT_DATA; - x += *data++; - if (x >= bmp->width) - return BMP_DATA_ERROR; - y += *data++; - if (y >= bmp->height) - return BMP_DATA_ERROR; - break; - - default: - /* 00 - NN means escape NN pixels */ - if (bmp->reversed) { - pixels_left = (bmp->height - y) * bmp->width - x; - scanline = (void *)(top + (y * swidth)); - } else { - pixels_left = (y + 1) * bmp->width - x; - scanline = (void *)(bottom - (y * swidth)); - } - if (length > pixels_left) - length = pixels_left; - if (data + length > end) - return BMP_INSUFFICIENT_DATA; - - /* the following code could be easily optimised - * by simply checking the bounds on entry and - * using some simple copying routines if so - */ - for (i = 0; i < length; i++) { - uint32_t idx = (uint32_t) *data++; - if (x >= bmp->width) { - x = 0; - y++; - if (y >= bmp->height) - return BMP_DATA_ERROR; - if (bmp->reversed) { - scanline += bmp->width; - } else { - scanline -= bmp->width; - } - } - if (idx >= bmp->colours) - return BMP_DATA_ERROR; - scanline[x++] = bmp->colour_table[idx]; - } - - if ((length & 1) && (*data++ != 0x00)) - return BMP_DATA_ERROR; - - break; - } - } else { - uint32_t idx; - - /* NN means perform RLE for NN pixels */ - if (bmp->reversed) { - pixels_left = (bmp->height - y) * bmp->width - x; - scanline = (void *)(top + (y * swidth)); - } else { - pixels_left = (y + 1) * bmp->width - x; - scanline = (void *)(bottom - (y * swidth)); - } - if (length > pixels_left) - length = pixels_left; - - /* boundary checking */ - if (data + 1 > end) - return BMP_INSUFFICIENT_DATA; - - /* the following code could be easily optimised by - * simply checking the bounds on entry and using some - * simply copying routines if so - */ - idx = (uint32_t) *data++; - if (idx >= bmp->colours) - return BMP_DATA_ERROR; - - pixel = bmp->colour_table[idx]; - for (i = 0; i < length; i++) { - if (x >= bmp->width) { - x = 0; - y++; - if (y >= bmp->height) - return BMP_DATA_ERROR; - if (bmp->reversed) { - scanline += bmp->width; - } else { - scanline -= bmp->width; - } - } - scanline[x++] = pixel; - } - } - } while (data < end); - - return BMP_OK; -} - - -/** - * Decode BMP data stored encoded in RLE4. - * - * \param bmp the BMP image to decode - * \param data the data to decode - * \param bytes the number of bytes of data available - * \return BMP_OK on success - * BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly; - * in this case, the image may be partially viewable - */ -static bmp_result -bmp_decode_rle4(bmp_image *bmp, uint8_t *data, int bytes) -{ - uint8_t *top, *bottom, *end; - uint32_t *scanline; - uint32_t swidth; - uint32_t i, length, pixels_left; - uint32_t x = 0, y = 0, last_y = 0; - uint32_t pixel = 0, pixel2; - - if (bmp->ico) - return BMP_DATA_ERROR; - - swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width; - top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap); - if (!top) - return BMP_INSUFFICIENT_MEMORY; - bottom = top + (uint64_t)swidth * (bmp->height - 1); - end = data + bytes; - bmp->decoded = true; - - do { - if (data + 2 > end) - return BMP_INSUFFICIENT_DATA; - length = *data++; - if (length == 0) { - length = *data++; - switch (length) { - case 0: - /* 00 - 00 means end of scanline */ - x = 0; - if (last_y == y) { - y++; - if (y >= bmp->height) - return BMP_DATA_ERROR; - } - last_y = y; - break; - - case 1: - /* 00 - 01 means end of RLE data */ - return BMP_OK; - - case 2: - /* 00 - 02 - XX - YY means move cursor */ - if (data + 2 > end) - return BMP_INSUFFICIENT_DATA; - x += *data++; - if (x >= bmp->width) - return BMP_DATA_ERROR; - y += *data++; - if (y >= bmp->height) - return BMP_DATA_ERROR; - break; - - default: - /* 00 - NN means escape NN pixels */ - if (bmp->reversed) { - pixels_left = (bmp->height - y) * bmp->width - x; - scanline = (void *)(top + (y * swidth)); - } else { - pixels_left = (y + 1) * bmp->width - x; - scanline = (void *)(bottom - (y * swidth)); - } - if (length > pixels_left) - length = pixels_left; - if (data + ((length + 1) / 2) > end) - return BMP_INSUFFICIENT_DATA; - - /* the following code could be easily optimised - * by simply checking the bounds on entry and - * using some simple copying routines - */ - - for (i = 0; i < length; i++) { - if (x >= bmp->width) { - x = 0; - y++; - if (y >= bmp->height) - return BMP_DATA_ERROR; - if (bmp->reversed) { - scanline += bmp->width; - } else { - scanline -= bmp->width; - } - - } - if ((i & 1) == 0) { - pixel = *data++; - if ((pixel >> 4) >= bmp->colours) - return BMP_DATA_ERROR; - scanline[x++] = bmp->colour_table - [pixel >> 4]; - } else { - if ((pixel & 0xf) >= bmp->colours) - return BMP_DATA_ERROR; - scanline[x++] = bmp->colour_table - [pixel & 0xf]; - } - } - length = (length + 1) >> 1; - - if ((length & 1) && (*data++ != 0x00)) - return BMP_DATA_ERROR; - - break; - } - } else { - /* NN means perform RLE for NN pixels */ - if (bmp->reversed) { - pixels_left = (bmp->height - y) * bmp->width - x; - scanline = (void *)(top + (y * swidth)); - } else { - pixels_left = (y + 1) * bmp->width - x; - scanline = (void *)(bottom - (y * swidth)); - } - if (length > pixels_left) - length = pixels_left; - - /* boundary checking */ - if (data + 1 > end) - return BMP_INSUFFICIENT_DATA; - - /* the following code could be easily optimised by - * simply checking the bounds on entry and using some - * simple copying routines - */ - - pixel2 = *data++; - if ((pixel2 >> 4) >= bmp->colours || - (pixel2 & 0xf) >= bmp->colours) - return BMP_DATA_ERROR; - pixel = bmp->colour_table[pixel2 >> 4]; - pixel2 = bmp->colour_table[pixel2 & 0xf]; - for (i = 0; i < length; i++) { - if (x >= bmp->width) { - x = 0; - y++; - if (y >= bmp->height) - return BMP_DATA_ERROR; - if (bmp->reversed) { - scanline += bmp->width; - } else { - scanline -= bmp->width; - } - } - if ((i & 1) == 0) - scanline[x++] = pixel; - else - scanline[x++] = pixel2; - } - - } - } while (data < end); - - return BMP_OK; -} - - -/* exported interface documented in libnsbmp.h */ -bmp_result -bmp_create(bmp_image *bmp, - bmp_bitmap_callback_vt *bitmap_callbacks) -{ - memset(bmp, 0, sizeof(bmp_image)); - bmp->bitmap_callbacks = *bitmap_callbacks; - - return BMP_OK; -} - - -/* exported interface documented in libnsbmp.h */ -bmp_result -ico_collection_create(ico_collection *ico, - bmp_bitmap_callback_vt *bitmap_callbacks) -{ - - memset(ico, 0, sizeof(ico_collection)); - ico->bitmap_callbacks = *bitmap_callbacks; - - return BMP_OK; -} - - -/* exported interface documented in libnsbmp.h */ -bmp_result bmp_analyse(bmp_image *bmp, size_t size, uint8_t *data) -{ - bmp_result res; - - /* ensure we aren't already initialised */ - if (bmp->bitmap) { - return BMP_OK; - } - - /* initialize source data values */ - bmp->buffer_size = size; - bmp->bmp_data = data; - - res = bmp_file_header_parse(bmp, data); - if (res == BMP_OK) { - res = bmp_info_header_parse(bmp, data + BMP_FILE_HEADER_SIZE); - } - return res; -} - - -/* exported interface documented in libnsbmp.h */ -bmp_result ico_analyse(ico_collection *ico, size_t size, uint8_t *data) -{ - /* ensure we aren't already initialised */ - if (ico->first) - return BMP_OK; - - /* initialize values */ - ico->buffer_size = size; - ico->ico_data = data; - - return ico_header_parse(ico, data); -} - - -/* exported interface documented in libnsbmp.h */ -bmp_result bmp_decode(bmp_image *bmp) -{ - uint8_t *data; - uint32_t bytes; - bmp_result result = BMP_OK; - - assert(bmp->bitmap); - - data = bmp->bmp_data + bmp->bitmap_offset; - bytes = bmp->buffer_size - bmp->bitmap_offset; - - switch (bmp->encoding) { - case BMP_ENCODING_RGB: - switch (bmp->bpp) { - case 32: - result = bmp_decode_rgb32(bmp, &data, bytes); - break; - - case 24: - result = bmp_decode_rgb24(bmp, &data, bytes); - break; - - case 16: - result = bmp_decode_rgb16(bmp, &data, bytes); - break; - - default: - result = bmp_decode_rgb(bmp, &data, bytes); - break; - } - break; - - case BMP_ENCODING_RLE8: - result = bmp_decode_rle8(bmp, data, bytes); - break; - - case BMP_ENCODING_RLE4: - result = bmp_decode_rle4(bmp, data, bytes); - break; - - case BMP_ENCODING_BITFIELDS: - switch (bmp->bpp) { - case 32: - result = bmp_decode_rgb32(bmp, &data, bytes); - break; - - case 16: - result = bmp_decode_rgb16(bmp, &data, bytes); - break; - - default: - result = BMP_DATA_ERROR; - break; - } - break; - } - - /* icons with less than 32bpp have a 1bpp alpha mask */ - if ((result == BMP_OK) && (bmp->ico) && (bmp->bpp != 32)) { - bytes = (uintptr_t)bmp->bmp_data + bmp->buffer_size - (uintptr_t)data; - result = bmp_decode_mask(bmp, data, bytes); - } - return result; -} - - -/* exported interface documented in libnsbmp.h */ -bmp_result bmp_decode_trans(bmp_image *bmp, uint32_t colour) -{ - bmp->limited_trans = true; - bmp->trans_colour = colour; - return bmp_decode(bmp); -} - - -/* exported interface documented in libnsbmp.h */ -bmp_image *ico_find(ico_collection *ico, uint16_t width, uint16_t height) -{ - bmp_image *bmp = NULL; - ico_image *image; - int x, y, cur, distance = (1 << 24); - - if (width == 0) - width = ico->width; - if (height == 0) - height = ico->height; - for (image = ico->first; image; image = image->next) { - if ((image->bmp.width == width) && (image->bmp.height == height)) - return &image->bmp; - x = image->bmp.width - width; - y = image->bmp.height - height; - cur = (x * x) + (y * y); - if (cur < distance) { - distance = cur; - bmp = &image->bmp; - } - } - return bmp; -} - - -/* exported interface documented in libnsbmp.h */ -void bmp_finalise(bmp_image *bmp) -{ - if (bmp->bitmap) - bmp->bitmap_callbacks.bitmap_destroy(bmp->bitmap); - bmp->bitmap = NULL; - if (bmp->colour_table) - free(bmp->colour_table); - bmp->colour_table = NULL; -} - - -/* exported interface documented in libnsbmp.h */ -void ico_finalise(ico_collection *ico) -{ - ico_image *image; - - for (image = ico->first; image; image = image->next) - bmp_finalise(&image->bmp); - while (ico->first) { - image = ico->first; - ico->first = image->next; - free(image); - } -} diff --git a/source/pp2d/pp2d.c b/source/pp2d/pp2d.c deleted file mode 100644 index a19c1f7..0000000 --- a/source/pp2d/pp2d.c +++ /dev/null @@ -1,969 +0,0 @@ -/* MIT License - * - * Copyright (c) 2017 Bernardo Giordano - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * https://discord.gg/bGKEyfY - */ - -/** - * Plug & Play 2D - * @file pp2d.c - * @author Bernardo Giordano - * @date 17 January 2018 - * @brief pp2d implementation - */ - -#include "pp2d.h" -#include "libnsbmp.h" -#define STB_IMAGE_IMPLEMENTATION -#include "stb_image.h" -#undef STB_IMAGE_IMPLEMENTATION - -static DVLB_s* vshader_dvlb; -static shaderProgram_s program; -static int uLoc_projection; -static C3D_Mtx projectionTopLeft; -static C3D_Mtx projectionTopRight; -static C3D_Mtx projectionBot; -static C3D_Tex* glyphSheets; -static float s_textScale; -static textVertex_s* textVtxArray; -static int textVtxArrayPos; -static C3D_RenderTarget* topLeft; -static C3D_RenderTarget* topRight; -static C3D_RenderTarget* bot; - -static struct { - GPU_TEXTURE_FILTER_PARAM magFilter; - GPU_TEXTURE_FILTER_PARAM minFilter; -} textureFilters; - -static struct { - size_t id; - int x; - int y; - int xbegin; - int ybegin; - int width; - int height; - u32 color; - flipType fliptype; - float scaleX; - float scaleY; - float angle; - float depth; - bool initialized; -} textureData; - -static struct { - C3D_Tex tex; - u32 width; - u32 height; - bool allocated; -} textures[MAX_TEXTURES]; - -static void pp2d_add_text_vertex(float vx, float vy, float vz, float tx, float ty); -static bool pp2d_add_quad(int x, int y, int height, int width, float left, float right, float top, float bottom, float depth); -static u32 pp2d_get_next_pow2(u32 n); -static void pp2d_get_text_size_internal(float* width, float* height, float scaleX, float scaleY, int wrapX, const char* text); -static void pp2d_set_text_color(u32 color); - -static void pp2d_add_text_vertex(float vx, float vy, float vz, float tx, float ty) -{ - textVertex_s* vtx = &textVtxArray[textVtxArrayPos++]; - vtx->position[0] = vx; - vtx->position[1] = vy; - vtx->position[2] = vz; - vtx->texcoord[0] = tx; - vtx->texcoord[1] = ty; -} - -void pp2d_begin_draw(gfxScreen_t target, gfx3dSide_t side) -{ - C3D_FrameBegin(C3D_FRAME_SYNCDRAW); - textVtxArrayPos = 0; - pp2d_draw_on(target, side); -} - -void pp2d_draw_on(gfxScreen_t target, gfx3dSide_t side) -{ - if (target == GFX_TOP) { - C3D_FrameDrawOn(side == GFX_LEFT ? topLeft : topRight); - C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_projection, side == GFX_LEFT ? &projectionTopLeft : &projectionTopRight); - } else { - C3D_FrameDrawOn(bot); - C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_projection, &projectionBot); - } -} - -void pp2d_draw_rectangle(int x, int y, int width, int height, u32 color) -{ - C3D_TexEnv* env = C3D_GetTexEnv(0); - C3D_TexEnvSrc(env, C3D_Both, GPU_CONSTANT, GPU_CONSTANT, 0); - C3D_TexEnvOpRgb(env, 0, 0, 0); - C3D_TexEnvOpAlpha(env, 0, 0, 0); - C3D_TexEnvFunc(env, C3D_RGB, GPU_INTERPOLATE); - C3D_TexEnvColor(env, color); - - if (pp2d_add_quad(x, y, height, width, 0, 0, 0, 0, DEFAULT_DEPTH)) - { - C3D_DrawArrays(GPU_TRIANGLE_STRIP, textVtxArrayPos - 4, 4); - } -} - -void pp2d_draw_text(float x, float y, float scaleX, float scaleY, u32 color, const char* text) -{ - pp2d_draw_text_wrap(x, y, scaleX, scaleY, color, -1, text); -} - -void pp2d_draw_text_center(gfxScreen_t target, float y, float scaleX, float scaleY, u32 color, const char* text) -{ - float width = pp2d_get_text_width(text, scaleX, scaleY); - float x = ((target == GFX_TOP ? TOP_WIDTH : BOTTOM_WIDTH) - width) / 2; - pp2d_draw_text(x, y, scaleX, scaleY, color, text); -} - -void pp2d_draw_textf(float x, float y, float scaleX, float scaleY, u32 color, const char* text, ...) -{ - char buffer[256]; - va_list args; - va_start(args, text); - vsnprintf(buffer, 256, text, args); - pp2d_draw_text(x, y, scaleX, scaleY, color, buffer); - va_end(args); -} - -void pp2d_draw_text_wrap(float x, float y, float scaleX, float scaleY, u32 color, float wrapX, const char* text) -{ - if (text == NULL) - return; - - pp2d_set_text_color(color); - - ssize_t units; - uint32_t code; - const uint8_t* p = (const uint8_t*)text; - float firstX = x; - int lastSheet = -1; - - scaleX *= s_textScale; - scaleY *= s_textScale; - - do - { - if (!*p) break; - units = decode_utf8(&code, p); - if (units == -1) - break; - p += units; - if (code == '\n' || (wrapX != -1 && x + scaleX * fontGetCharWidthInfo(fontGlyphIndexFromCodePoint(code))->charWidth >= firstX + wrapX)) - { - x = firstX; - y += scaleY*fontGetInfo()->lineFeed; - p -= code == '\n' ? 0 : 1; - } - else if (code > 0) - { - int glyphIdx = fontGlyphIndexFromCodePoint(code); - fontGlyphPos_s data; - fontCalcGlyphPos(&data, glyphIdx, GLYPH_POS_CALC_VTXCOORD, scaleX, scaleY); - - if (data.sheetIndex != lastSheet) - { - lastSheet = data.sheetIndex; - C3D_TexBind(0, &glyphSheets[lastSheet]); - } - - if ((textVtxArrayPos+4) >= TEXT_VTX_ARRAY_COUNT) - break; - - pp2d_add_text_vertex(x+data.vtxcoord.left, y+data.vtxcoord.bottom, DEFAULT_DEPTH, data.texcoord.left, data.texcoord.bottom); - pp2d_add_text_vertex(x+data.vtxcoord.right, y+data.vtxcoord.bottom, DEFAULT_DEPTH, data.texcoord.right, data.texcoord.bottom); - pp2d_add_text_vertex(x+data.vtxcoord.left, y+data.vtxcoord.top, DEFAULT_DEPTH, data.texcoord.left, data.texcoord.top); - pp2d_add_text_vertex(x+data.vtxcoord.right, y+data.vtxcoord.top, DEFAULT_DEPTH, data.texcoord.right, data.texcoord.top); - - C3D_DrawArrays(GPU_TRIANGLE_STRIP, textVtxArrayPos - 4, 4); - - x += data.xAdvance; - } - } while (code > 0); -} - -void pp2d_draw_texture(size_t id, int x, int y) -{ - pp2d_texture_select(id, x, y); - pp2d_texture_draw(); -} - -void pp2d_draw_texture_blend(size_t id, int x, int y, u32 color) -{ - pp2d_texture_select(id, x, y); - pp2d_texture_blend(color); - pp2d_texture_draw(); -} - -void pp2d_draw_texture_flip(size_t id, int x, int y, flipType fliptype) -{ - pp2d_texture_select(id, x, y); - pp2d_texture_flip(fliptype); - pp2d_texture_draw(); -} - -void pp2d_draw_texture_rotate(size_t id, int x, int y, float angle) -{ - pp2d_texture_select(id, x, y); - pp2d_texture_rotate(angle); - pp2d_texture_draw(); -} - -void pp2d_draw_texture_scale(size_t id, int x, int y, float scaleX, float scaleY) -{ - pp2d_texture_select(id, x, y); - pp2d_texture_scale(scaleX, scaleY); - pp2d_texture_draw(); -} - -void pp2d_draw_texture_part(size_t id, int x, int y, int xbegin, int ybegin, int width, int height) -{ - pp2d_texture_select_part(id, x, y, xbegin, ybegin, width, height); - pp2d_texture_draw(); -} - -void pp2d_draw_wtext(float x, float y, float scaleX, float scaleY, u32 color, const wchar_t* text) -{ - pp2d_draw_wtext_wrap(x, y, scaleX, scaleY, color, -1, text); -} - -void pp2d_draw_wtext_center(gfxScreen_t target, float y, float scaleX, float scaleY, u32 color, const wchar_t* text) -{ - float width = pp2d_get_wtext_width(text, scaleX, scaleY); - float x = ((target == GFX_TOP ? TOP_WIDTH : BOTTOM_WIDTH) - width) / 2; - pp2d_draw_wtext(x, y, scaleX, scaleY, color, text); -} - -void pp2d_draw_wtext_wrap(float x, float y, float scaleX, float scaleY, u32 color, float wrapX, const wchar_t* text) -{ - if (text == NULL) - return; - - u32 size = wcslen(text) * sizeof(wchar_t); - char buf[size]; - memset(buf, 0, size); - utf32_to_utf8((uint8_t*)buf, (uint32_t*)text, size); - buf[size - 1] = '\0'; - - pp2d_draw_text_wrap(x, y, scaleX, scaleY, color, wrapX, buf); -} - -void pp2d_draw_wtextf(float x, float y, float scaleX, float scaleY, u32 color, const wchar_t* text, ...) -{ - wchar_t buffer[256]; - va_list args; - va_start(args, text); - vswprintf(buffer, 256, text, args); - pp2d_draw_wtext(x, y, scaleX, scaleY, color, buffer); - va_end(args); -} - -void pp2d_end_draw(void) -{ - C3D_FrameEnd(0); -} - -void pp2d_exit(void) -{ - for (size_t id = 0; id < MAX_TEXTURES; id++) - { - pp2d_free_texture(id); - } - - linearFree(textVtxArray); - free(glyphSheets); - - shaderProgramFree(&program); - DVLB_Free(vshader_dvlb); - - C3D_Fini(); - gfxExit(); -} - -static bool pp2d_add_quad(int x, int y, int height, int width, float left, float right, float top, float bottom, float depth) -{ - if ((textVtxArrayPos+4) >= TEXT_VTX_ARRAY_COUNT) - return false; - - pp2d_add_text_vertex( x, y + height, depth, left, bottom); - pp2d_add_text_vertex(x + width, y + height, depth, right, bottom); - pp2d_add_text_vertex( x, y, depth, left, top); - pp2d_add_text_vertex(x + width, y, depth, right, top); - - return true; -} - -void pp2d_free_texture(size_t id) -{ - if (id >= MAX_TEXTURES) - return; - - if (!textures[id].allocated) - return; - - C3D_TexDelete(&textures[id].tex); - textures[id].width = 0; - textures[id].height = 0; - textures[id].allocated = false; -} - -Result pp2d_init(void) -{ - Result res = 0; - - gfxInitDefault(); - C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); - - topLeft = C3D_RenderTargetCreate(SCREEN_HEIGHT, TOP_WIDTH, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); - C3D_RenderTargetClear(topLeft, C3D_CLEAR_ALL, BACKGROUND_COLOR, 0); - C3D_RenderTargetSetOutput(topLeft, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS); - - topRight = C3D_RenderTargetCreate(SCREEN_HEIGHT, TOP_WIDTH, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); - C3D_RenderTargetClear(topRight, C3D_CLEAR_ALL, BACKGROUND_COLOR, 0); - C3D_RenderTargetSetOutput(topRight, GFX_TOP, GFX_RIGHT, DISPLAY_TRANSFER_FLAGS); - - bot = C3D_RenderTargetCreate(SCREEN_HEIGHT, BOTTOM_WIDTH, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); - C3D_RenderTargetClear(bot, C3D_CLEAR_ALL, BACKGROUND_COLOR, 0); - C3D_RenderTargetSetOutput(bot, GFX_BOTTOM, GFX_LEFT, DISPLAY_TRANSFER_FLAGS); - - res = fontEnsureMapped(); - if (R_FAILED(res)) - return res; - - pp2d_set_texture_filter(GPU_NEAREST, GPU_NEAREST); - -#ifdef BUILDTOOLS - vshader_dvlb = DVLB_ParseFile((u32*)vshader_shbin, vshader_shbin_len); -#else - vshader_dvlb = DVLB_ParseFile((u32*)vshader_shbin, vshader_shbin_size); -#endif - - shaderProgramInit(&program); - shaderProgramSetVsh(&program, &vshader_dvlb->DVLE[0]); - C3D_BindProgram(&program); - - uLoc_projection = shaderInstanceGetUniformLocation(program.vertexShader, "projection"); - - C3D_AttrInfo* attrInfo = C3D_GetAttrInfo(); - AttrInfo_Init(attrInfo); - AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3); - AttrInfo_AddLoader(attrInfo, 1, GPU_FLOAT, 2); - - Mtx_OrthoTilt(&projectionTopLeft, 0, TOP_WIDTH, SCREEN_HEIGHT, 0.0f, 0.0f, 1.0f, true); - Mtx_OrthoTilt(&projectionTopRight, 0, TOP_WIDTH, SCREEN_HEIGHT, 0.0f, 0.0f, 1.0f, true); - Mtx_OrthoTilt(&projectionBot, 0, BOTTOM_WIDTH, SCREEN_HEIGHT, 0.0f, 0.0f, 1.0f, true); - - C3D_DepthTest(true, GPU_GEQUAL, GPU_WRITE_ALL); - - int i; - TGLP_s* glyphInfo = fontGetGlyphInfo(); - glyphSheets = malloc(sizeof(C3D_Tex)*glyphInfo->nSheets); - for (i = 0; i < glyphInfo->nSheets; i ++) - { - C3D_Tex* tex = &glyphSheets[i]; - tex->data = fontGetGlyphSheetTex(i); - tex->fmt = glyphInfo->sheetFmt; - tex->size = glyphInfo->sheetSize; - tex->width = glyphInfo->sheetWidth; - tex->height = glyphInfo->sheetHeight; - tex->param = GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) - | GPU_TEXTURE_WRAP_S(GPU_CLAMP_TO_EDGE) | GPU_TEXTURE_WRAP_T(GPU_CLAMP_TO_EDGE); - tex->border = 0; - tex->lodParam = 0; - } - - charWidthInfo_s* cwi = fontGetCharWidthInfo(fontGlyphIndexFromCodePoint(0x3042)); - s_textScale = 20.0f / (cwi->glyphWidth); // 20 is glyphWidth in J machines - - textVtxArray = (textVertex_s*)linearAlloc(sizeof(textVertex_s)*TEXT_VTX_ARRAY_COUNT); - C3D_BufInfo* bufInfo = C3D_GetBufInfo(); - BufInfo_Init(bufInfo); - BufInfo_Add(bufInfo, textVtxArray, sizeof(textVertex_s), 2, 0x10); - - return 0; -} - -static u32 pp2d_get_next_pow2(u32 v) -{ - v--; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - v++; - return v >= 64 ? v : 64; -} - -float pp2d_get_text_height(const char* text, float scaleX, float scaleY) -{ - float height; - pp2d_get_text_size_internal(NULL, &height, scaleX, scaleY, -1, text); - return height; -} - -float pp2d_get_text_height_wrap(const char* text, float scaleX, float scaleY, int wrapX) -{ - float height; - pp2d_get_text_size_internal(NULL, &height, scaleX, scaleY, wrapX, text); - return height; -} - -void pp2d_get_text_size(float* width, float* height, float scaleX, float scaleY, const char* text) -{ - pp2d_get_text_size_internal(width, height, scaleX, scaleY, -1, text); -} - -static void pp2d_get_text_size_internal(float* width, float* height, float scaleX, float scaleY, int wrapX, const char* text) -{ - float maxW = 0.0f; - float w = 0.0f; - float h = 0.0f; - - ssize_t units; - uint32_t code; - float x = 0; - float firstX = x; - const uint8_t* p = (const uint8_t*)text; - - scaleX *= s_textScale; - scaleY *= s_textScale; - - do - { - if (!*p) break; - units = decode_utf8(&code, p); - if (units == -1) - break; - p += units; - if (code == '\n' || (wrapX != -1 && x + scaleX * fontGetCharWidthInfo(fontGlyphIndexFromCodePoint(code))->charWidth >= firstX + wrapX)) - { - x = firstX; - h += scaleY*fontGetInfo()->lineFeed; - p -= code == '\n' ? 0 : 1; - if (w > maxW) - maxW = w; - w = 0.f; - } - else if (code > 0) - { - float len = (scaleX * fontGetCharWidthInfo(fontGlyphIndexFromCodePoint(code))->charWidth); - w += len; - x += len; - } - } while (code > 0); - - if (width) - { - *width = w > maxW ? w : maxW; - } - - if (height) - { - h += scaleY*fontGetInfo()->lineFeed; - *height = h; - } -} - -float pp2d_get_text_width(const char* text, float scaleX, float scaleY) -{ - float width; - pp2d_get_text_size_internal(&width, NULL, scaleX, scaleY, -1, text); - return width; -} - -float pp2d_get_wtext_height(const wchar_t* text, float scaleX, float scaleY) -{ - u32 size = wcslen(text) * sizeof(wchar_t); - char buf[size]; - memset(buf, 0, size); - utf32_to_utf8((uint8_t*)buf, (uint32_t*)text, size); - buf[size - 1] = '\0'; - - float height; - pp2d_get_text_size_internal(NULL, &height, scaleX, scaleY, -1, buf); - return height; -} - -float pp2d_get_wtext_width(const wchar_t* text, float scaleX, float scaleY) -{ - u32 size = wcslen(text) * sizeof(wchar_t); - char buf[size]; - memset(buf, 0, size); - utf32_to_utf8((uint8_t*)buf, (uint32_t*)text, size); - buf[size - 1] = '\0'; - - float width; - pp2d_get_text_size_internal(&width, NULL, scaleX, scaleY, -1, buf); - return width; -} - -float pp2d_get_texture_width(size_t id) -{ - return textures[id].width; -} - -float pp2d_get_texture_height(size_t id) -{ - return textures[id].height; -} - -void pp2d_load_texture_memory(size_t id, void* buf, u32 size, u32 width, u32 height, GPU_TEXCOLOR format) -{ - u32 w_pow2 = pp2d_get_next_pow2(width); - u32 h_pow2 = pp2d_get_next_pow2(height); - - C3D_TexInit(&textures[id].tex, (u16)w_pow2, (u16)h_pow2, format); - C3D_TexSetFilter(&textures[id].tex, textureFilters.magFilter, textureFilters.minFilter); - - u32 pixelSize = size / width / height; - - textures[id].allocated = true; - textures[id].width = width; - textures[id].height = height; - - for (u32 x = 0; x < width; x++) - { - for (u32 y = 0; y < height; y++) - { - u32 dstPos = ((((y >> 3) * (w_pow2 >> 3) + (x >> 3)) << 6) + ((x & 1) | ((y & 1) << 1) | ((x & 2) << 1) | ((y & 2) << 2) | ((x & 4) << 2) | ((y & 4) << 3))) * pixelSize; - u32 srcPos = (y * width + x) * pixelSize; - - memcpy(&((u8*) textures[id].tex.data)[dstPos], &((u8*) buf)[srcPos], pixelSize); - } - } - - C3D_TexFlush(&textures[id].tex); -} - -static void *pp2d_create_bitmap(int width, int height, unsigned int state) -{ - (void) state; /* unused */ - return calloc(width * height, 4); -} - -static unsigned char *pp2d_get_bitmap_buf(void *bitmap) -{ - return (unsigned char *)bitmap; -} - -static size_t pp2d_get_bitmap_bpp(void *bitmap) -{ - (void) bitmap; /* unused */ - return 4; -} - -void pp2d_free_bitmap(void *bitmap) -{ - free(bitmap); -} - -static void *pp2d_bitmap_to_buf(const char *path, u32 *size) -{ - FILE *fd = fopen(path, "rb"); - - if (fd == NULL) - return NULL; - - u8 *buffer; - long lSize; - fseek(fd, 0, SEEK_END); - lSize = ftell(fd); - rewind(fd); - - buffer = (u8 *)malloc(lSize); - - if (size) - *size = lSize; - - if (!buffer) - { - fclose(fd); - return NULL; - } - - fread(buffer, 1, lSize, fd); - fclose(fd); - return buffer; -} - -void pp2d_load_texture_bmp(size_t id, const char* path) -{ - if (id >= MAX_TEXTURES) - return; - - u32 size; - u8 * buf = (u8 *)pp2d_bitmap_to_buf(path, &size); - - bmp_bitmap_callback_vt bitmap_callbacks = - { - pp2d_create_bitmap, - pp2d_free_bitmap, - pp2d_get_bitmap_buf, - pp2d_get_bitmap_bpp - }; - - bmp_result code; - bmp_image bmp; - - /* create our bmp image */ - bmp_create(&bmp, &bitmap_callbacks); - - /* analyse the BMP */ - code = bmp_analyse(&bmp, size, buf); - - if (code != BMP_OK) - { - bmp_finalise(&bmp); - return; - } - - /* decode the image */ - code = bmp_decode(&bmp); - - if (code != BMP_OK) - { - bmp_finalise(&bmp); - return; - } - - u8 * image; - image = (u8 *)bmp.bitmap; - - for (u32 x = 0; x < bmp.width; x++) - { - for (u32 y = 0; y < bmp.height; y++) - { - u32 pos = (y * bmp.width + x) * 4; - - u8 c1 = image[pos + 0]; - u8 c2 = image[pos + 1]; - u8 c3 = image[pos + 2]; - u8 c4 = image[pos + 3]; - - image[pos + 0] = c4; - image[pos + 1] = c3; - image[pos + 2] = c2; - image[pos + 3] = c1; - } - } - - pp2d_load_texture_memory(id, image, (bmp.width * bmp.height * 4), bmp.width, bmp.height, GPU_RGBA8); - - bmp_finalise(&bmp); - free(buf); -} - -void pp2d_load_texture_other(size_t id, const char* path) -{ - if (id >= MAX_TEXTURES) - return; - - int width = 0, height = 0, channel = 0; - stbi_uc *image = stbi_load(path, &width, &height, &channel, STBI_rgb_alpha); - - if ((image == NULL) || (channel != STBI_rgb_alpha)) - return; - - for (u32 x = 0; x < width; x++) - { - for (u32 y = 0; y < height; y++) - { - u32 pos = (y * width + x) * channel; - - u8 c1 = image[pos + 0]; - u8 c2 = image[pos + 1]; - u8 c3 = image[pos + 2]; - u8 c4 = image[pos + 3]; - - image[pos + 0] = c4; - image[pos + 1] = c3; - image[pos + 2] = c2; - image[pos + 3] = c1; - } - } - - pp2d_load_texture_memory(id, image, (u32)(width * height * channel), (u32)width, (u32)height, GPU_RGBA8); - stbi_image_free(image); -} - -void pp2d_load_texture_jpg(size_t id, const char* path) -{ - if (id >= MAX_TEXTURES) - return; - - int width = 0, height = 0, channel = 0; - stbi_uc *image = stbi_load(path, &width, &height, &channel, STBI_rgb); - - if ((image == NULL) || (channel != STBI_rgb)) - return; - - for (u32 x = 0; x < width; x++) - { - for (u32 y = 0; y < height; y++) - { - u32 pos = (y * width + x) * channel; - - u8 c1 = image[pos + 0]; - u8 c2 = image[pos + 1]; - u8 c3 = image[pos + 2]; - - image[pos + 0] = c3; - image[pos + 1] = c2; - image[pos + 2] = c1; - } - } - - pp2d_load_texture_memory(id, image, (u32)(width * height * channel), (u32)width, (u32)height, GPU_RGB8); - stbi_image_free(image); -} - -void pp2d_load_texture_png(size_t id, const char* path) -{ - if (id >= MAX_TEXTURES) - return; - - unsigned char *image; - unsigned width = 0, height = 0; - - lodepng_decode32_file(&image, &width, &height, path); - - for (u32 i = 0; i < width; i++) - { - for (u32 j = 0; j < height; j++) - { - u32 p = (i + j*width) * 4; - - u8 r = *(u8*)(image + p); - u8 g = *(u8*)(image + p + 1); - u8 b = *(u8*)(image + p + 2); - u8 a = *(u8*)(image + p + 3); - - *(image + p) = a; - *(image + p + 1) = b; - *(image + p + 2) = g; - *(image + p + 3) = r; - } - } - - pp2d_load_texture_memory(id, image, (u32)(width * height * 4), (u32)width, (u32)height, GPU_RGBA8); - free(image); -} - -void pp2d_set_3D(int enable) -{ - gfxSet3D(enable); -} - -void pp2d_set_screen_color(gfxScreen_t target, u32 color) -{ - if (target == GFX_TOP) - { - C3D_RenderTargetClear(topLeft, C3D_CLEAR_ALL, color, 0); - C3D_RenderTargetClear(topRight, C3D_CLEAR_ALL, color, 0); - } - else - { - C3D_RenderTargetClear(bot, C3D_CLEAR_ALL, color, 0); - } -} - -void pp2d_set_texture_filter(GPU_TEXTURE_FILTER_PARAM magFilter, GPU_TEXTURE_FILTER_PARAM minFilter) -{ - textureFilters.magFilter = magFilter; - textureFilters.minFilter = minFilter; -} - -static void pp2d_set_text_color(u32 color) -{ - C3D_TexEnv* env = C3D_GetTexEnv(0); - C3D_TexEnvSrc(env, C3D_RGB, GPU_CONSTANT, 0, 0); - C3D_TexEnvSrc(env, C3D_Alpha, GPU_TEXTURE0, GPU_CONSTANT, 0); - C3D_TexEnvOpRgb(env, 0, 0, 0); - C3D_TexEnvOpAlpha(env, 0, 0, 0); - C3D_TexEnvFunc(env, C3D_RGB, GPU_REPLACE); - C3D_TexEnvFunc(env, C3D_Alpha, GPU_MODULATE); - C3D_TexEnvColor(env, color); -} - -void pp2d_texture_select(size_t id, int x, int y) -{ - if (id >= MAX_TEXTURES) - { - textureData.initialized = false; - return; - } - - textureData.id = id; - textureData.x = x; - textureData.y = y; - textureData.xbegin = 0; - textureData.ybegin = 0; - textureData.width = textures[id].width; - textureData.height = textures[id].height; - textureData.color = PP2D_NEUTRAL; - textureData.fliptype = NONE; - textureData.scaleX = 1; - textureData.scaleY = 1; - textureData.angle = 0; - textureData.depth = DEFAULT_DEPTH; - textureData.initialized = true; -} - -void pp2d_texture_select_part(size_t id, int x, int y, int xbegin, int ybegin, int width, int height) -{ - if (id >= MAX_TEXTURES) - { - textureData.initialized = false; - return; - } - - textureData.id = id; - textureData.x = x; - textureData.y = y; - textureData.xbegin = xbegin; - textureData.ybegin = ybegin; - textureData.width = width; - textureData.height = height; - textureData.color = PP2D_NEUTRAL; - textureData.fliptype = NONE; - textureData.scaleX = 1; - textureData.scaleY = 1; - textureData.angle = 0; - textureData.depth = DEFAULT_DEPTH; - textureData.initialized = true; -} - -void pp2d_texture_blend(u32 color) -{ - textureData.color = color; -} - -void pp2d_texture_scale(float scaleX, float scaleY) -{ - textureData.scaleX = scaleX; - textureData.scaleY = scaleY; -} - -void pp2d_texture_flip(flipType fliptype) -{ - textureData.fliptype = fliptype; -} - -void pp2d_texture_rotate(float angle) -{ - textureData.angle = angle; -} - -void pp2d_texture_depth(float depth) -{ - textureData.depth = depth; -} - -void pp2d_texture_draw(void) -{ - if (!textureData.initialized) - return; - - if ((textVtxArrayPos+4) >= TEXT_VTX_ARRAY_COUNT) - return; - - size_t id = textureData.id; - - float left = (float)textureData.xbegin / (float)textures[id].tex.width; - float right = (float)(textureData.xbegin + textureData.width) / (float)textures[id].tex.width; - float top = (float)(textures[id].tex.height - textureData.ybegin) / (float)textures[id].tex.height; - float bottom = (float)(textures[id].tex.height - textureData.ybegin - textureData.height) / (float)textures[id].tex.height; - - // scaling - textureData.height *= textureData.scaleY; - textureData.width *= textureData.scaleX; - - float vert[4][2] = { - { textureData.x, textureData.height + textureData.y}, - {textureData.width + textureData.x, textureData.height + textureData.y}, - { textureData.x, textureData.y}, - {textureData.width + textureData.x, textureData.y}, - }; - - // flipping - if (textureData.fliptype == BOTH || textureData.fliptype == HORIZONTAL) - { - float tmp = left; - left = right; - right = tmp; - } - - if (textureData.fliptype == BOTH || textureData.fliptype == VERTICAL) - { - float tmp = top; - top = bottom; - bottom = tmp; - } - - // rotating - textureData.angle = fmod(textureData.angle, 360); - if (textureData.angle != 0) - { - const float rad = textureData.angle/(180/M_PI); - const float c = cosf(rad); - const float s = sinf(rad); - - const float xcenter = textureData.x + textureData.width/2.0f; - const float ycenter = textureData.y + textureData.height/2.0f; - - for (int i = 0; i < 4; i++) - { - float oldx = vert[i][0]; - float oldy = vert[i][1]; - - float newx = c * (oldx - xcenter) - s * (oldy - ycenter) + xcenter; - float newy = s * (oldx - xcenter) + c * (oldy - ycenter) + ycenter; - - vert[i][0] = newx; - vert[i][1] = newy; - } - } - - // blending - C3D_TexBind(0, &textures[id].tex); - C3D_TexEnv* env = C3D_GetTexEnv(0); - C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, GPU_CONSTANT, 0); - C3D_TexEnvOpRgb(env, 0, 0, 0); - C3D_TexEnvOpAlpha(env, 0, 0, 0); - C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE); - C3D_TexEnvColor(env, textureData.color); - - // rendering - pp2d_add_text_vertex(vert[0][0], vert[0][1], textureData.depth, left, bottom); - pp2d_add_text_vertex(vert[1][0], vert[1][1], textureData.depth, right, bottom); - pp2d_add_text_vertex(vert[2][0], vert[2][1], textureData.depth, left, top); - pp2d_add_text_vertex(vert[3][0], vert[3][1], textureData.depth, right, top); - - C3D_DrawArrays(GPU_TRIANGLE_STRIP, textVtxArrayPos - 4, 4); -} diff --git a/source/pp2d/vshader.v.pica b/source/pp2d/vshader.v.pica deleted file mode 100644 index f526f2f..0000000 --- a/source/pp2d/vshader.v.pica +++ /dev/null @@ -1,39 +0,0 @@ -; Uniforms -.fvec projection[4] - -; Constants -.constf myconst(0.0, 1.0, -1.0, 0.1) -.constf RGBA_TO_FLOAT4(0.00392156862, 0, 0, 0) -.alias zeros myconst.xxxx ; Vector full of zeros -.alias ones myconst.yyyy ; Vector full of ones - -; Outputs -.out outpos position -.out outclr color -.out outtc0 texcoord0 - -; Inputs (defined as aliases for convenience) -.alias inpos v0 -.alias intex v1 - -.bool test - -.proc main - ; Force the w component of inpos to be 1.0 - mov r0.xyz, inpos - mov r0.w, ones - - ; outpos = projectionMatrix * inpos - dp4 outpos.x, projection[0], r0 - dp4 outpos.y, projection[1], r0 - dp4 outpos.z, projection[2], r0 - dp4 outpos.w, projection[3], r0 - - ;outtc0 = intexcoord - mov outtc0, intex - - ;outclr - mul outclr, RGBA_TO_FLOAT4.xxxx, intex - - end -.end \ No newline at end of file diff --git a/source/progress_bar.c b/source/progress_bar.c index 4d4048c..badb05d 100644 --- a/source/progress_bar.c +++ b/source/progress_bar.c @@ -1,31 +1,31 @@ -#include "pp2d.h" -#include "textures.h" -#include "theme.h" +#include <3ds.h> -struct colour BottomScreen_colour; -struct colour Options_title_text_colour; -struct colour Settings_title_text_colour; -struct colour Storage_colour; +#include "common.h" +#include "config.h" +#include "progress_bar.h" +#include "C2D_helper.h" +#include "textures.h" -void ProgressBar_DisplayProgress(char * msg, char * src, u32 offset, u32 size) +void ProgressBar_DisplayProgress(char *msg, char *src, u32 offset, u32 size) { - pp2d_begin_draw(GFX_BOTTOM, GFX_LEFT); + C3D_FrameBegin(C3D_FRAME_SYNCDRAW); + C2D_TargetClear(RENDER_BOTTOM, config_dark_theme? BLACK_BG : WHITE); + C2D_SceneBegin(RENDER_BOTTOM); + + Draw_Rect(0, 0, 320, 20, config_dark_theme? STATUS_BAR_DARK : MENU_BAR_LIGHT); // Status bar + Draw_Rect(0, 20, 320, 220, config_dark_theme? MENU_BAR_DARK : STATUS_BAR_LIGHT); // Menu bar - pp2d_draw_rectangle(0, 0, 320, 240, RGBA8(BottomScreen_colour.r, BottomScreen_colour.g, BottomScreen_colour.b, 255)); + float text_width = 0; + Draw_GetTextSize(0.45f, &text_width, NULL, src); - pp2d_draw_texture(TEXTURE_DIALOG, ((320 - (pp2d_get_texture_width(TEXTURE_DIALOG))) / 2), - ((240 - (pp2d_get_texture_height(TEXTURE_DIALOG))) / 2)); + Draw_Image(config_dark_theme? dialog_dark : dialog, ((320 - (dialog.subtex->width)) / 2), ((240 - (dialog.subtex->height)) / 2)); - pp2d_draw_text(((320 - (pp2d_get_texture_width(TEXTURE_DIALOG))) / 2) + 10, ((240 - (pp2d_get_texture_height(TEXTURE_DIALOG))) / 2) + 20, - 0.45f, 0.45f, RGBA8(Settings_title_text_colour.r, Settings_title_text_colour.g, Settings_title_text_colour.b, 255), msg); + Draw_Text(((320 - (dialog.subtex->width)) / 2) + 6, ((240 - (dialog.subtex->height)) / 2) + 6, 0.45f, config_dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR, msg); - pp2d_draw_text(((320 - (pp2d_get_text_width(src, 0.45f, 0.45f))) / 2), ((240 - (pp2d_get_texture_height(TEXTURE_DIALOG))) / 2) + 45, - 0.45f, 0.45f, RGBA8(Options_title_text_colour.r, Options_title_text_colour.g, Options_title_text_colour.b, 255), src); + Draw_Text(((320 - (text_width)) / 2), ((240 - (dialog.subtex->height)) / 2) + 30, 0.45f, config_dark_theme? TEXT_MIN_COLOUR_DARK : TEXT_MIN_COLOUR_LIGHT, src); - pp2d_draw_rectangle(((320 - (pp2d_get_texture_width(TEXTURE_DIALOG))) / 2) + 20, ((240 - (pp2d_get_texture_height(TEXTURE_DIALOG))) / 2) + 70, - 240, 4, RGBA8(200, 200, 200, 255)); - pp2d_draw_rectangle(((320 - (pp2d_get_texture_width(TEXTURE_DIALOG))) / 2) + 20, ((240 - (pp2d_get_texture_height(TEXTURE_DIALOG))) / 2) + 70, - (double)offset / (double)size * 240.0, 4, RGBA8(Storage_colour.r, Storage_colour.g, Storage_colour.b, 255)); + Draw_Rect(((320 - (dialog.subtex->width)) / 2) + 20, ((240 - (dialog.subtex->height)) / 2) + 60, 240, 4, config_dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); + Draw_Rect(((320 - (dialog.subtex->width)) / 2) + 20, ((240 - (dialog.subtex->height)) / 2) + 60, (double)offset / (double)size * 240.0, 4, config_dark_theme? TITLE_COLOUR : PROGRESS_COLOUR); - pp2d_end_draw(); + Draw_EndFrame(); } \ No newline at end of file diff --git a/source/misc/screenshot.c b/source/screenshot.c similarity index 98% rename from source/misc/screenshot.c rename to source/screenshot.c index 55a4b62..727850d 100644 --- a/source/misc/screenshot.c +++ b/source/screenshot.c @@ -118,7 +118,7 @@ static void generateScreenshotFileName(int number, char *fileName, const char *e int month = timeStruct->tm_mon + 1; int year = timeStruct->tm_year + 1900; - if (!(BROWSE_STATE == STATE_NAND)) + if (!(BROWSE_STATE == BROWSE_STATE_NAND)) { if (!(FS_DirExists(archive, "/screenshots/"))) FS_MakeDir(archive, "/screenshots"); diff --git a/source/status_bar.c b/source/status_bar.c new file mode 100644 index 0000000..a5f0966 --- /dev/null +++ b/source/status_bar.c @@ -0,0 +1,42 @@ +#include <3ds.h> +#include + +#include "C2D_helper.h" +#include "common.h" +#include "status_bar.h" + +static char *Clock_GetCurrentTime(bool _12hour) +{ + static char buffer[10]; + + time_t unix_time = time(0); + struct tm* time_struct = gmtime((const time_t*)&unix_time); + int hours = time_struct->tm_hour; + int minutes = time_struct->tm_min; + int amOrPm = 0; + + if (_12hour) + { + if (hours < 12) + amOrPm = 1; + if (hours == 0) + hours = 12; + else if (hours > 12) + hours = hours - 12; + + if ((hours >= 1) && (hours < 10)) + snprintf(buffer, 10, "%2i:%02i %s", hours, minutes, amOrPm ? "AM" : "PM"); + else + snprintf(buffer, 10, "%2i:%02i %s", hours, minutes, amOrPm ? "AM" : "PM"); + } + + return buffer; +} + +void StatusBar_DisplayTime(void) +{ + float width = 0, height = 0; + Draw_GetTextSize(0.48f, &width, &height, Clock_GetCurrentTime(true)); + + Draw_Text(390 - width, (18 - height) / 2, 0.48f, WHITE, Clock_GetCurrentTime(true)); +} \ No newline at end of file diff --git a/source/texture.c b/source/texture.c deleted file mode 100644 index 5179f45..0000000 --- a/source/texture.c +++ /dev/null @@ -1,78 +0,0 @@ -#include "pp2d.h" -#include "textures.h" -#include "theme.h" - -void Load_Textures(void) -{ - Theme_Load(); - - pp2d_load_texture_png(TEXTURE_BACKGROUND, background_path); - pp2d_load_texture_png(TEXTURE_DIALOG, dialog_path); - pp2d_load_texture_png(TEXTURE_OPTIONS, options_path); - pp2d_load_texture_png(TEXTURE_PROPERTIES, properties_path); - pp2d_load_texture_png(TEXTURE_SELECTOR, selector_path); - - pp2d_load_texture_png(TEXTURE_ICON_APP, app_path); - pp2d_load_texture_png(TEXTURE_ICON_ARCHIVE, archive_path); - pp2d_load_texture_png(TEXTURE_ICON_AUDIO, audio_path); - pp2d_load_texture_png(TEXTURE_ICON_FILE, file_path); - pp2d_load_texture_png(TEXTURE_ICON_FOLDER, folder_path); - pp2d_load_texture_png(TEXTURE_ICON_IMG, img_path); - pp2d_load_texture_png(TEXTURE_ICON_SYSTEM, system_path); - pp2d_load_texture_png(TEXTURE_ICON_TEXT, text_path); - - pp2d_load_texture_png(TEXTURE_ICON_CHECK, check_path); - pp2d_load_texture_png(TEXTURE_ICON_UNCHECK, uncheck_path); - - pp2d_load_texture_png(TEXTURE_HOME_ICON, "romfs:/res/drawable/ic_material_light_home.png"); - pp2d_load_texture_png(TEXTURE_OPTIONS_ICON, "romfs:/res/drawable/ic_material_light_options.png"); - pp2d_load_texture_png(TEXTURE_SETTINGS_ICON, "romfs:/res/drawable/ic_material_light_settings.png"); - pp2d_load_texture_png(TEXTURE_FTP_ICON, "romfs:/res/drawable/ic_material_light_ftp.png"); - pp2d_load_texture_png(TEXTURE_UPDATE_ICON, "romfs:/res/drawable/ic_material_light_update.png"); - - pp2d_load_texture_png(TEXTURE_HOME_ICON_SELECTED, "romfs:/res/drawable/ic_overlay_home.png"); - pp2d_load_texture_png(TEXTURE_OPTIONS_ICON_SELECTED, "romfs:/res/drawable/ic_overlay_options.png"); - pp2d_load_texture_png(TEXTURE_SETTINGS_ICON_SELECTED, "romfs:/res/drawable/ic_overlay_settings.png"); - pp2d_load_texture_png(TEXTURE_FTP_ICON_SELECTED, "romfs:/res/drawable/ic_overlay_ftp.png"); - pp2d_load_texture_png(TEXTURE_UPDATE_ICON_SELECTED, "romfs:/res/drawable/ic_overlay_update.png"); - - pp2d_load_texture_png(TEXTURE_SD_ICON, "romfs:/res/drawable/ic_material_light_sd.png"); - pp2d_load_texture_png(TEXTURE_NAND_ICON, "romfs:/res/drawable/ic_material_light_nand.png"); - pp2d_load_texture_png(TEXTURE_SD_ICON_SELECTED, "romfs:/res/drawable/ic_overlay_sd.png"); - pp2d_load_texture_png(TEXTURE_NAND_ICON_SELECTED, "romfs:/res/drawable/ic_overlay_nand.png"); - - pp2d_load_texture_png(TEXTURE_TOGGLE_ON, "romfs:/res/drawable/btn_material_toggle_on.png"); - pp2d_load_texture_png(TEXTURE_TOGGLE_OFF, "romfs:/res/drawable/btn_material_toggle_off.png"); - pp2d_load_texture_png(TEXTURE_RADIO_ON, "romfs:/res/drawable/btn_material_radio_on.png"); - pp2d_load_texture_png(TEXTURE_RADIO_OFF, "romfs:/res/drawable/btn_material_radio_off.png"); - - pp2d_load_texture_png(TEXTURE_THEMES_LAUNCHER, "romfs:/res/drawable/ic_launcher_themes.png"); - - pp2d_load_texture_png(TEXTURE_SEARCH_ICON, "romfs:/res/drawable/ic_material_light_search.png"); - - pp2d_load_texture_png(TEXTURE_BATTERY_0, "romfs:/res/drawable/battery/0.png"); - pp2d_load_texture_png(TEXTURE_BATTERY_15, "romfs:/res/drawable/battery/15.png"); - pp2d_load_texture_png(TEXTURE_BATTERY_28, "romfs:/res/drawable/battery/28.png"); - pp2d_load_texture_png(TEXTURE_BATTERY_43, "romfs:/res/drawable/battery/43.png"); - pp2d_load_texture_png(TEXTURE_BATTERY_57, "romfs:/res/drawable/battery/57.png"); - pp2d_load_texture_png(TEXTURE_BATTERY_71, "romfs:/res/drawable/battery/71.png"); - pp2d_load_texture_png(TEXTURE_BATTERY_85, "romfs:/res/drawable/battery/85.png"); - pp2d_load_texture_png(TEXTURE_BATTERY_100, "romfs:/res/drawable/battery/100.png"); - pp2d_load_texture_png(TEXTURE_BATTERY_CHARGE, "romfs:/res/drawable/battery/charge.png"); - - pp2d_load_texture_png(TEXTURE_WIFI_NULL, "romfs:/res/drawable/wifi/stat_sys_wifi_signal_null.png"); - pp2d_load_texture_png(TEXTURE_WIFI_0, "romfs:/res/drawable/wifi/stat_sys_wifi_signal_0.png"); - pp2d_load_texture_png(TEXTURE_WIFI_1, "romfs:/res/drawable/wifi/stat_sys_wifi_signal_1.png"); - pp2d_load_texture_png(TEXTURE_WIFI_2, "romfs:/res/drawable/wifi/stat_sys_wifi_signal_2.png"); - pp2d_load_texture_png(TEXTURE_WIFI_3, "romfs:/res/drawable/wifi/stat_sys_wifi_signal_3.png"); - - pp2d_load_texture_png(TEXTURE_GALLERY_BAR, "romfs:/res/drawable/gallery/ic_gallery_bar.png"); - - pp2d_load_texture_png(TEXTURE_MUSIC_TOP_BG, "romfs:/res/drawable/music/ic_music_bg_top.png"); - pp2d_load_texture_png(TEXTURE_MUSIC_BOTTOM_BG, "romfs:/res/drawable/music/ic_music_bg_bottom.png"); - pp2d_load_texture_png(TEXTURE_MUSIC_PLAY, "romfs:/res/drawable/music/ic_music_play.png"); - pp2d_load_texture_png(TEXTURE_MUSIC_PAUSE, "romfs:/res/drawable/music/ic_music_pause.png"); - pp2d_load_texture_png(TEXTURE_MUSIC_STATUS, "romfs:/res/drawable/music/ic_music_status.png"); - - pp2d_load_texture_png(TEXTURE_TEXTVIEWER_BG, "romfs:/res/drawable/textviewer/textview.png"); -} \ No newline at end of file diff --git a/source/textures.c b/source/textures.c new file mode 100644 index 0000000..7a34294 --- /dev/null +++ b/source/textures.c @@ -0,0 +1,79 @@ +#include "C2D_helper.h" +#include "common.h" +#include "sprites.h" +#include "textures.h" + +static C2D_SpriteSheet spritesheet; + +void Textures_Load(void) +{ + spritesheet = C2D_SpriteSheetLoad("romfs:/res/drawable/sprites.t3x"); + + icon_app = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_fso_type_executable_idx); + icon_archive = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_fso_type_compress_idx); + icon_audio = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_fso_type_audio_idx); + icon_dir = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_fso_folder_idx); + icon_dir_dark = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_fso_folder_dark_idx); + icon_doc = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_fso_type_document_idx); + icon_file = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_fso_default_idx); + icon_image = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_fso_type_image_idx); + icon_text = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_fso_type_text_idx); + icon_check = C2D_SpriteSheetGetImage(spritesheet, sprites_btn_material_light_check_on_normal_idx); + icon_check_dark = C2D_SpriteSheetGetImage(spritesheet, sprites_btn_material_light_check_on_normal_dark_idx); + icon_uncheck = C2D_SpriteSheetGetImage(spritesheet, sprites_btn_material_light_check_off_normal_idx); + icon_uncheck_dark = C2D_SpriteSheetGetImage(spritesheet, sprites_btn_material_light_check_off_normal_dark_idx); + dialog = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_dialog_idx); + options_dialog = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_options_dialog_idx); + properties_dialog = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_properties_dialog_idx); + dialog_dark = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_dialog_dark_idx); + options_dialog_dark = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_options_dialog_dark_idx); + properties_dialog_dark = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_properties_dialog_dark_idx); + icon_radio_off = C2D_SpriteSheetGetImage(spritesheet, sprites_btn_material_light_radio_off_normal_idx); + icon_radio_on = C2D_SpriteSheetGetImage(spritesheet, sprites_btn_material_light_radio_on_normal_idx); + icon_radio_dark_off = C2D_SpriteSheetGetImage(spritesheet, sprites_btn_material_light_radio_off_normal_dark_idx); + icon_radio_dark_on = C2D_SpriteSheetGetImage(spritesheet, sprites_btn_material_light_radio_on_normal_dark_idx); + icon_toggle_on = C2D_SpriteSheetGetImage(spritesheet, sprites_btn_material_light_toggle_on_normal_idx); + icon_toggle_dark_on = C2D_SpriteSheetGetImage(spritesheet, sprites_btn_material_light_toggle_on_normal_dark_idx); + icon_toggle_off = C2D_SpriteSheetGetImage(spritesheet, sprites_btn_material_light_toggle_off_normal_idx); + icon_home = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_light_home_idx); + icon_home_dark = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_light_home_dark_idx); + icon_home_overlay = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_light_home_overlay_idx); + icon_options = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_light_filesystem_idx); + icon_options_dark = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_light_filesystem_dark_idx); + icon_options_overlay = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_light_filesystem_overlay_idx); + icon_settings = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_light_settings_idx); + icon_settings_dark = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_light_settings_dark_idx); + icon_settings_overlay = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_light_settings_overlay_idx); + icon_ftp = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_light_remote_idx); + icon_ftp_dark = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_light_remote_dark_idx); + icon_ftp_overlay = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_light_remote_overlay_idx); + icon_sd = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_light_sdcard_idx); + icon_sd_dark = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_light_sdcard_dark_idx); + icon_sd_overlay = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_light_sdcard_overlay_idx); + icon_secure = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_light_secure_idx); + icon_secure_dark = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_light_secure_dark_idx); + icon_secure_overlay = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_light_secure_overlay_idx); + icon_search = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_light_search_idx); + icon_updates = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_light_tab_idx); + icon_updates_dark = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_light_tab_dark_idx); + icon_updates_overlay = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_light_tab_overlay_idx); + default_artwork_blur = C2D_SpriteSheetGetImage(spritesheet, sprites_default_artwork_blur_idx); + default_artwork = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_album_lg_idx); + ic_music_bg_bottom = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_music_bg_bottom_idx); + btn_play = C2D_SpriteSheetGetImage(spritesheet, sprites_btn_playback_play_idx); + btn_pause = C2D_SpriteSheetGetImage(spritesheet, sprites_btn_playback_pause_idx); + btn_rewind = C2D_SpriteSheetGetImage(spritesheet, sprites_btn_playback_rewind_idx); + btn_forward = C2D_SpriteSheetGetImage(spritesheet, sprites_btn_playback_forward_idx); + btn_repeat = C2D_SpriteSheetGetImage(spritesheet, sprites_btn_playback_repeat_idx); + btn_shuffle = C2D_SpriteSheetGetImage(spritesheet, sprites_btn_playback_shuffle_idx); + btn_repeat_overlay = C2D_SpriteSheetGetImage(spritesheet, sprites_btn_playback_repeat_overlay_idx); + btn_shuffle_overlay = C2D_SpriteSheetGetImage(spritesheet, sprites_btn_playback_shuffle_overlay_idx); + icon_nav_drawer = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_light_navigation_drawer_idx); + icon_actions = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_material_light_contextual_action_idx); + icon_back = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_arrow_back_normal_idx); +} + +void Textures_Free(void) +{ + C2D_SpriteSheetFree(spritesheet); +} \ No newline at end of file diff --git a/source/theme.c b/source/theme.c deleted file mode 100644 index 076f933..0000000 --- a/source/theme.c +++ /dev/null @@ -1,257 +0,0 @@ -#include -#include -#include - -#include "fs.h" -#include "common.h" -#include "pp2d.h" -#include "textures.h" -#include "theme.h" -#include "utils.h" - -struct colour BottomScreen_colour; -struct colour BottomScreen_bar_colour; -struct colour BottomScreen_text_colour; -struct colour Options_select_colour; -struct colour Options_text_colour; -struct colour Options_title_text_colour; -struct colour Settings_colour; -struct colour Settings_text_colour; -struct colour Settings_text_min_colour; -struct colour Settings_title_text_colour; -struct colour Storage_colour; -struct colour TopScreen_colour; -struct colour TopScreen_bar_colour; -struct colour TopScreen_min_colour; - -const char * themeConfig = - "theme = %s\n" - "colours = %s"; - -const char * coloursConfig = - "storage = RGBA(%d, %d, %d, 255)\n" - "topscreen_bar = RGBA(%d, %d, %d, 255)\n" - "topscreen_text = RGBA(%d, %d, %d, 255)\n" - "topscreen_text_min = RGBA(%d, %d, %d, 255)\n" - "bottomscreen_bg = RGBA(%d, %d, %d, 255)\n" - "bottomscreen_bar = RGBA(%d, %d, %d, 255)\n" - "bottomscreen_text = RGBA(%d, %d, %d, 255)\n" - "options_selector = RGBA(%d, %d, %d, 255)\n" - "options_title_text = RGBA(%d, %d, %d, 255)\n" - "options_text = RGBA(%d, %d, %d, 255)\n" - "settings_bg = RGBA(%d, %d, %d, 255)\n" - "settings_title_text = RGBA(%d, %d, %d, 255)\n" - "settins_text = RGBA(%d, %d, %d, 255)\n" - "settings_text_min = RGBA(%d, %d, %d, 255)"; - -Result Theme_SaveConfig(char * themePath, char * coloursPath) -{ - Result ret = 0; - - char * buf = (char *)malloc(512); - snprintf(buf, 512, themeConfig, themePath, coloursPath); - - if (R_FAILED(ret = FS_Write(archive, "/3ds/3DShell/theme.cfg", buf))) - { - free(buf); - return ret; - } - - free(buf); - return 0; -} - -static Result Theme_LoadConfig(void) -{ - Handle handle; - Result ret = 0; - - if (!FS_FileExists(archive, "/3ds/3DShell/theme.cfg")) - Theme_SaveConfig("romfs:/res/drawable", "/3ds/3DShell/themes/default"); - - u64 size64 = 0; - u32 size = 0; - - size64 = FS_GetFileSize(archive, "/3ds/3DShell/theme.cfg"); - size = (u32)size64; - char * buf = (char *)malloc(size + 1); - - if (R_FAILED(ret = FS_Read(archive, "/3ds/3DShell/theme.cfg", size, buf))) - { - free(buf); - return ret; - } - - buf[size] = '\0'; - - sscanf(buf, themeConfig, theme_dir, colour_dir); - - free(buf); - return 0; -} - -static Result Theme_CreateFontColours(void) -{ - Result ret = 0; - - char * buf = (char *)malloc(1024); - snprintf(buf, 1024, coloursConfig, 48, 174, 222, - 255, 255, 255, - 0, 0, 0, - 95, 95, 95, - 30, 136, 229, - 25, 118, 210, - 251, 251, 251, - 237, 237, 237, - 32, 32, 32, - 120, 120, 120, - 251, 251, 251, - 30, 136, 229, - 32, 32, 32, - 120, 120, 120); - - if (R_FAILED(ret = FS_Write(archive, "/3ds/3DShell/themes/default/colours.cfg", buf))) - { - free(buf); - return ret; - } - - free(buf); - return 0; -} - -static Result Theme_LoadFontColours(void) -{ - Handle handle; - Result ret = 0; - - if (!FS_FileExists(archive, "/3ds/3DShell/themes/default/colours.cfg")) - Theme_CreateFontColours(); - - char colours_cfg[100] = "/colours.cfg"; - strcat(colour_dir, colours_cfg); - - u64 size64 = 0; - u32 size = 0; - - size64 = FS_GetFileSize(archive, colour_dir); - size = (u32)size64; - char * buf = (char *)malloc(size + 1); - - if (R_FAILED(ret = FS_Read(archive, colour_dir, size, buf))) - { - free(buf); - return ret; - } - - buf[size] = '\0'; - - sscanf(buf, coloursConfig, &Storage_colour.r, &Storage_colour.g, &Storage_colour.b, - &TopScreen_bar_colour.r, &TopScreen_bar_colour.g, &TopScreen_bar_colour.b, - &TopScreen_colour.r, &TopScreen_colour.g, &TopScreen_colour.b, - &TopScreen_min_colour.r, &TopScreen_min_colour.g, &TopScreen_min_colour.b, - &BottomScreen_colour.r, &BottomScreen_colour.g, &BottomScreen_colour.b, - &BottomScreen_bar_colour.r, &BottomScreen_bar_colour.g, &BottomScreen_bar_colour.b, - &BottomScreen_text_colour.r, &BottomScreen_text_colour.g, &BottomScreen_text_colour.b, - &Options_select_colour.r, &Options_select_colour.g, &Options_select_colour.b, - &Options_title_text_colour.r, &Options_title_text_colour.g, &Options_title_text_colour.b, - &Options_text_colour.r, &Options_text_colour.g, &Options_text_colour.b, - &Settings_colour.r, &Settings_colour.g, &Settings_colour.b, - &Settings_title_text_colour.r, &Settings_title_text_colour.g, &Settings_title_text_colour.b, - &Settings_text_colour.r, &Settings_text_colour.g, &Settings_text_colour.b, - &Settings_text_min_colour.r, &Settings_text_min_colour.g, &Settings_text_min_colour.b); - - free(buf); - return 0; -} - -static void Theme_ReplaceAsset(char arr[], char path[], char img_path[], char redirect_path[]) -{ - strcpy(arr, path); - strcat(arr, img_path); - strcpy(redirect_path, arr); -} - -void Theme_Load(void) -{ - Theme_LoadConfig(); - - char background_res[100] = "/ic_background.png"; - char dialog_res[100] = "/ic_dialog.png"; - char options_res[100] = "/ic_options.png"; - char properties_res[100] = "/ic_properties.png"; - char selector_res[100] = "/ic_selector.png"; - - char app_res[100] = "/ic_fso_type_app.png"; - char archive_res[100] = "/ic_fso_type_archive.png"; - char audio_res[100] = "/ic_fso_type_audio.png"; - char file_res[100] = "/ic_fso_type_file.png"; - char folder_res[100] = "/ic_fso_type_folder.png"; - char img_res[100] = "/ic_fso_type_img.png"; - char system_res[100] = "/ic_fso_type_system.png"; - char text_res[100] = "/ic_fso_type_text.png"; - - char check_res[100] = "/btn_material_check_on.png"; - char uncheck_res[100] = "/btn_material_check_off.png"; - - Theme_ReplaceAsset(temp_arr, theme_dir, background_res, background_path); - Theme_ReplaceAsset(temp_arr, theme_dir, dialog_res, dialog_path); - Theme_ReplaceAsset(temp_arr, theme_dir, options_res, options_path); - Theme_ReplaceAsset(temp_arr, theme_dir, properties_res, properties_path); - Theme_ReplaceAsset(temp_arr, theme_dir, selector_res, selector_path); - - Theme_ReplaceAsset(temp_arr, theme_dir, app_res, app_path); - Theme_ReplaceAsset(temp_arr, theme_dir, archive_res, archive_path); - Theme_ReplaceAsset(temp_arr, theme_dir, audio_res, audio_path); - Theme_ReplaceAsset(temp_arr, theme_dir, file_res, file_path); - Theme_ReplaceAsset(temp_arr, theme_dir, folder_res, folder_path); - Theme_ReplaceAsset(temp_arr, theme_dir, img_res, img_path); - Theme_ReplaceAsset(temp_arr, theme_dir, system_res, system_path); - Theme_ReplaceAsset(temp_arr, theme_dir, text_res, text_path); - - Theme_ReplaceAsset(temp_arr, theme_dir, check_res, check_path); - Theme_ReplaceAsset(temp_arr, theme_dir, uncheck_res, uncheck_path); - - Theme_LoadFontColours(); -} - -void Theme_Reload(void) -{ - pp2d_free_texture(TEXTURE_BACKGROUND); - pp2d_free_texture(TEXTURE_DIALOG); - pp2d_free_texture(TEXTURE_OPTIONS); - pp2d_free_texture(TEXTURE_PROPERTIES); - pp2d_free_texture(TEXTURE_SELECTOR); - - pp2d_free_texture(TEXTURE_ICON_APP); - pp2d_free_texture(TEXTURE_ICON_ARCHIVE); - pp2d_free_texture(TEXTURE_ICON_AUDIO); - pp2d_free_texture(TEXTURE_ICON_FILE); - pp2d_free_texture(TEXTURE_ICON_FOLDER); - pp2d_free_texture(TEXTURE_ICON_IMG); - pp2d_free_texture(TEXTURE_ICON_SYSTEM); - pp2d_free_texture(TEXTURE_ICON_TEXT); - - pp2d_free_texture(TEXTURE_ICON_CHECK); - pp2d_free_texture(TEXTURE_ICON_UNCHECK); - - pp2d_load_texture_png(TEXTURE_BACKGROUND, background_path); - pp2d_load_texture_png(TEXTURE_DIALOG, dialog_path); - pp2d_load_texture_png(TEXTURE_OPTIONS, options_path); - pp2d_load_texture_png(TEXTURE_PROPERTIES, properties_path); - pp2d_load_texture_png(TEXTURE_SELECTOR, selector_path); - - pp2d_load_texture_png(TEXTURE_ICON_APP, app_path); - pp2d_load_texture_png(TEXTURE_ICON_ARCHIVE, archive_path); - pp2d_load_texture_png(TEXTURE_ICON_AUDIO, audio_path); - pp2d_load_texture_png(TEXTURE_ICON_FILE, file_path); - pp2d_load_texture_png(TEXTURE_ICON_FOLDER, folder_path); - pp2d_load_texture_png(TEXTURE_ICON_IMG, img_path); - pp2d_load_texture_png(TEXTURE_ICON_SYSTEM, system_path); - pp2d_load_texture_png(TEXTURE_ICON_TEXT, text_path); - - pp2d_load_texture_png(TEXTURE_ICON_CHECK, check_path); - pp2d_load_texture_png(TEXTURE_ICON_UNCHECK, uncheck_path); - - Theme_LoadFontColours(); -} \ No newline at end of file diff --git a/source/touch.c b/source/touch.c new file mode 100644 index 0000000..ae588bd --- /dev/null +++ b/source/touch.c @@ -0,0 +1,19 @@ +#include <3ds.h> + +#include "touch.h" + +u16 Touch_GetX(void) +{ + touchPosition pos; + hidTouchRead(&pos); + + return pos.px; +} + +u16 Touch_GetY(void) +{ + touchPosition pos; + hidTouchRead(&pos); + + return pos.py; +} \ No newline at end of file diff --git a/source/utils.c b/source/utils.c index 7b10237..5d9a67e 100644 --- a/source/utils.c +++ b/source/utils.c @@ -1,134 +1,42 @@ #include -#include #include -#include "common.h" -#include "fs.h" -#include "utils.h" - -const char * configFile = - "sortBy = %d\n" - "recycleBin = %d\n" - "systemProtection = %d\n" - "showHiddenFiles = %d"; +#include <3ds.h> -void Utils_MakeDirectories(void) -{ - if (BROWSE_STATE != STATE_NAND) - { - if (!(FS_DirExists(archive, "/3ds/3DShell/themes/default/"))) - FS_RecursiveMakeDir(archive, "/3ds/3DShell/themes/default"); - if (!(FS_DirExists(archive, "/3ds/3DShell/bin/"))) - FS_RecursiveMakeDir(archive, "/3ds/3DShell/bin"); - } -} +#include "utils.h" -Result Utils_SaveConfig(int sortBy, bool recycleBin, bool galleryDisplay, bool hidden) -{ - Result ret = 0; - - char * buf = (char *)malloc(256); - snprintf(buf, 256, configFile, sortBy, recycleBin, galleryDisplay, hidden); - - if (R_FAILED(ret = FS_Write(archive, "/3ds/3DShell/config.cfg", buf))) - { - free(buf); - return ret; - } - - free(buf); - return 0; -} - -Result Utils_LoadConfig(void) +bool Utils_IsN3DS(void) { - Handle handle; - Result ret = 0; - - if (!FS_FileExists(archive, "/3ds/3DShell/config.cfg")) - { - // set these to the following by default: - sortBy = 1; - recycleBin = 0; - galleryDisplay = 1; - isHiddenEnabled = 0; - return Utils_SaveConfig(sortBy, recycleBin, galleryDisplay, isHiddenEnabled); - } - - u64 size64 = 0; - u32 size = 0; - - size64 = FS_GetFileSize(archive, "/3ds/3DShell/config.cfg"); - size = (u32)size64; - char * buf = (char *)malloc(size + 1); + bool isNew3DS = false; - if (R_FAILED(ret = FS_Read(archive, "/3ds/3DShell/config.cfg", size, buf))) - { - free(buf); - return ret; - } + if (R_SUCCEEDED(APT_CheckNew3DS(&isNew3DS))) + return isNew3DS; - buf[size] = '\0'; - - sscanf(buf, configFile, &sortBy, &recycleBin, &galleryDisplay, &isHiddenEnabled); - - free(buf); - return 0; + return false; } -Result Utils_GetLastDirectory(void) +void Utils_U16_To_U8(char *buf, const u16 *input, size_t bufsize) { - Handle handle; - Result ret = 0; - - if (!FS_FileExists(archive, "/3ds/3DShell/lastdir.txt")) - { - FS_Write(archive, "/3ds/3DShell/lastdir.txt", START_PATH); - strcpy(cwd, START_PATH); // Set Start Path to "sdmc:/" if lastDir.txt hasn't been created. - } - else - { - u64 size64 = 0; - u32 size = 0; - - size64 = FS_GetFileSize(archive, "/3ds/3DShell/lastdir.txt"); - size = (u32)size64; - char * buf = (char *)malloc(size + 1); - - if (R_FAILED(ret = FS_Read(archive, "/3ds/3DShell/lastdir.txt", size, buf))) - { - free(buf); - return ret; - } - - buf[size] = '\0'; + ssize_t units = utf16_to_utf8((u8 *)buf, input, bufsize); - char tempPath[256]; - sscanf(buf, "%[^\n]s", tempPath); - - if (FS_DirExists(archive, tempPath)) // Incase a directory previously visited had been deleted, set start path to sdmc:/ to avoid errors. - strcpy(cwd, tempPath); - else - strcpy(cwd, START_PATH); - - free(buf); - } + if (units < 0) + units = 0; - return 0; + buf[units] = 0; } -char * Utils_Basename(const char * filename) +char *Utils_Basename(const char *filename) { char *p = strrchr (filename, '/'); return p ? p + 1 : (char *) filename; } -void Utils_GetSizeString(char * string, uint64_t size) //Thanks TheOfficialFloW +void Utils_GetSizeString(char *string, u64 size) { double double_size = (double)size; int i = 0; - static char *units[] = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" }; + static char *units[] = {"B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}; while (double_size >= 1024.0f) { @@ -139,64 +47,45 @@ void Utils_GetSizeString(char * string, uint64_t size) //Thanks TheOfficialFloW sprintf(string, "%.*f %s", (i == 0) ? 0 : 2, double_size, units[i]); } -CFG_Region Utils_GetRegion(void) +void Utils_SetMax(int *set, int value, int max) { - CFG_Region region = 0; - - if (R_SUCCEEDED(CFGU_SecureInfoGetRegion(®ion))) - return region; - - return 0; + if (*set > max) + *set = value; } -CFG_Language Utils_GetLanguage(void) +void Utils_SetMin(int *set, int value, int min) { - CFG_Language language = 0; - - if (R_SUCCEEDED(CFGU_GetSystemLanguage(&language))) - return language; - - return 0; + if (*set < min) + *set = value; } -const char * Utils_GetUsername(void) +int Utils_Alphasort(const void *p1, const void *p2) { - u8 data[0x1C]; - static wchar_t whcar_username[0x13]; - char * username = (char *)malloc(0x1C); - - if (R_SUCCEEDED(CFGU_GetConfigInfoBlk2(0x1C, 0x000A0000, data))) - { - for (int i = 0; i < 0x13; i++) - whcar_username[i] = (wchar_t)((u16 *)data)[i]; - } - else - { - free(username); - return NULL; - } - - wcstombs(username, whcar_username, 0x1C); - - return username; -} + FS_DirectoryEntry* entryA = (FS_DirectoryEntry*) p1; + FS_DirectoryEntry* entryB = (FS_DirectoryEntry*) p2; -bool Utils_IsN3DS(void) -{ - bool isNew3DS = false; - - if (R_SUCCEEDED(APT_CheckNew3DS(&isNew3DS))) - return isNew3DS; - - return false; + if ((entryA->attributes & FS_ATTRIBUTE_DIRECTORY) && !(entryB->attributes & FS_ATTRIBUTE_DIRECTORY)) + return -1; + else if (!(entryA->attributes & FS_ATTRIBUTE_DIRECTORY) && (entryB->attributes & FS_ATTRIBUTE_DIRECTORY)) + return 1; + + char entryNameA[256] = {'\0'}, entryNameB[256] = {'\0'}; + Utils_U16_To_U8((u8 *) entryNameA, entryA->name, sizeof(entryNameA) - 1); + Utils_U16_To_U8((u8 *) entryNameB, entryB->name, sizeof(entryNameB) - 1); + return strcasecmp(entryNameA, entryNameB); } -void u16_to_u8(char * buf, const u16 * input, size_t bufsize) +void Utils_AppendArr(char subject[], const char insert[], int pos) { - ssize_t units = utf16_to_utf8((u8 *)buf, input, bufsize); - - if (units < 0) - units = 0; - - buf[units] = 0; + char buf[100] = {}; // 100 so that it's big enough. fill with 0 + // or you could use malloc() to allocate sufficient space + + strncpy(buf, subject, pos); // copy at most first pos characters + int len = strlen(buf); + strcpy(buf+len, insert); // copy all of insert[] at the end + len += strlen(insert); // increase the length by length of insert[] + strcpy(buf+len, subject+pos); // copy the rest + + strcpy(subject, buf); // copy it back to subject + // deallocate buf[] here, if used malloc() } \ No newline at end of file