Major clean up and update to use citro2d

This commit is contained in:
Joel16 2019-10-19 20:07:54 -04:00
parent bca5aea337
commit 960e0fee32
74 changed files with 906 additions and 10253 deletions

249
Makefile
View File

@ -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,42 +31,40 @@ include $(DEVKITARM)/3ds_rules
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
GRAPHICS := res/drawable
ROMFS := romfs
GFXBUILD := $(ROMFS)/res/drawable
APP_TITLE := 3DS Recovery Tool
APP_DESCRIPTION := Restore and backup misc data
APP_AUTHOR := Joel16
TARGET := $(subst $e ,_,$(notdir $(APP_TITLE)))
OUTDIR := out
BUILD := build
RESOURCES := resources
SOURCES := source source/pp2d
DATA := data
INCLUDES := include include/pp2d
ROMFS := romfs
ICON := $(RESOURCES)/icon.png
BANNER := $(RESOURCES)/banner.png
JINGLE := $(RESOURCES)/banner.wav
LOGO := $(RESOURCES)/logo.bcma.lz
ICON_FLAGS := nosavebackups,visible
VERSION_MAJOR := 1
VERSION_MINOR := 5
VERSION_MICRO := 0
ICON := res/ic_launcher_recovery_tool.png
# CIA
APP_PRODUCT_CODE := CTR-3D-RECT
APP_UNIQUE_ID := 0x16600
RSF_FILE := $(RESOURCES)/cia.rsf
VERSION_MAJOR := 1
VERSION_MINOR := 4
BANNER_AUDIO := res/banner.wav
BANNER_IMAGE := res/banner.png
RSF_PATH := res/app.rsf
LOGO := res/logo.bcma.lz
UNIQUE_ID := 0x16600
PRODUCT_CODE := CTR-3D-RECT
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
CFLAGS := -g -Werror -O2 -mword-relocations \
-fomit-frame-pointer -ffunction-sections \
-DVERSION_MAJOR=$(VERSION_MAJOR) -DVERSION_MINOR=$(VERSION_MINOR) \
$(ARCH)
CFLAGS := -g -Wall -O3 -mword-relocations -fomit-frame-pointer -ffast-math \
-DVERSION_MAJOR=$(VERSION_MAJOR) -DVERSION_MINOR=$(VERSION_MINOR) -DVERSION_MICRO=$(VERSION_MICRO) \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
@ -71,13 +73,13 @@ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lmpg123 -lvorbisidec -logg -lcitro3d -lctru -lm -lz
LIBS := -lcitro2d -lcitro3d -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB) $(PORTLIBS)
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
@ -86,10 +88,11 @@ LIBDIRS := $(CTRULIB) $(PORTLIBS)
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(OUTDIR)/$(TARGET)
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
@ -99,6 +102,8 @@ 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)))
FONTFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.ttf)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
@ -115,15 +120,40 @@ else
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(PICAFILES:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.shbin.o) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
#---------------------------------------------------------------------------------
ifeq ($(GFXBUILD),$(BUILD))
#---------------------------------------------------------------------------------
export T3XFILES := $(GFXFILES:.t3s=.t3x)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export ROMFS_T3XFILES := $(patsubst %.t3s, $(GFXBUILD)/%.t3x, $(GFXFILES))
export ROMFS_FONTFILES := $(patsubst %.ttf, $(GFXBUILD)/%.bcfnt, $(FONTFILES))
export T3XHFILES := $(patsubst %.t3s, $(BUILD)/%.h, $(GFXFILES))
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
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 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) \
$(addsuffix .o,$(T3XFILES))
export OFILES := $(OFILES_BIN) $(OFILES_SOURCES)
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 _3DSXDEPS := $(if $(NO_SMDH),,$(OUTPUT).smdh)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
@ -139,95 +169,102 @@ else
endif
ifeq ($(strip $(NO_SMDH)),)
export _3DSXFLAGS += --smdh=$(OUTPUT).smdh
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
endif
ifneq ($(ROMFS),)
export _3DSXFLAGS += --romfs=$(CURDIR)/$(ROMFS)
endif
.PHONY: $(BUILD) clean all
.PHONY: all clean
#---------------------------------------------------------------------------------
all: 3dsx cia
3dsx: $(BUILD) $(OUTPUT).3dsx
cia : $(BUILD) $(OUTPUT).cia
citra: export CITRA_MODE = 1
citra: 3dsx
#---------------------------------------------------------------------------------
$(BUILD):
@mkdir -p $(OUTDIR)
@[ -d "$@" ] || mkdir -p "$@"
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(OUTDIR)
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
else
$(OUTPUT).3dsx : $(OUTPUT).elf
endif
#---------------------------------------------------------------------------------
MAKEROM ?= makerom
MAKEROM_ARGS := -elf "$(OUTPUT).elf" -rsf "$(RSF_FILE)" -banner "$(BUILD)/banner.bnr" -icon "$(BUILD)/icon.icn" -DAPP_TITLE="$(APP_TITLE)" -DAPP_PRODUCT_CODE="$(APP_PRODUCT_CODE)" -DAPP_UNIQUE_ID="$(APP_UNIQUE_ID)"
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
ifeq ($(strip $(ROMFS)),)
$(OUTPUT).cia: $(OUTPUT).elf $(BUILD)/banner.bnr $(BUILD)/icon.icn
$(MAKEROM) -f cia -o "$@" -target t -exefslogo $(MAKEROM_ARGS)
else
$(OUTPUT).cia: $(OUTPUT).elf $(BUILD)/banner.bnr $(BUILD)/icon.icn
$(MAKEROM) -f cia -o "$@" -target t -exefslogo $(MAKEROM_ARGS)
ifneq ($(strip $(ROMFS)),)
MAKEROM_ARGS += -DAPP_ROMFS="$(ROMFS)"
endif
BANNERTOOL ?= bannertool
BANNERTOOL ?= bannertool
ifeq ($(suffix $(BANNER)),.cgfx)
BANNER_ARG := -ci
ifeq ($(suffix $(BANNER_IMAGE)),.cgfx)
BANNER_IMAGE_ARG := -ci
else
BANNER_ARG := -i
BANNER_IMAGE_ARG := -i
endif
ifeq ($(suffix $(JINGLE)),.cwav)
JINGLE_ARG := -ca
ifeq ($(suffix $(BANNER_AUDIO)),.cwav)
BANNER_AUDIO_ARG := -ca
else
JINGLE_ARG := -a
BANNER_AUDIO_ARG := -a
endif
$(BUILD)/banner.bnr : $(BANNER) $(JINGLE)
$(BANNERTOOL) makebanner $(BANNER_ARG) "$(BANNER)" $(JINGLE_ARG) "$(JINGLE)" -o "$@"
#---------------------------------------------------------------------------------
all: $(BUILD) $(GFXBUILD) $(DEPSDIR) $(ROMFS_T3XFILES) $(ROMFS_FONTFILES) $(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)
$(BUILD)/icon.icn : $(APP_ICON)
$(BANNERTOOL) makesmdh -s "$(APP_TITLE)" -l "$(APP_DESCRIPTION)" -p "$(APP_AUTHOR)" -i "$(APP_ICON)" -f "$(ICON_FLAGS)" -o "$@"
$(BUILD):
@mkdir -p $@
ifneq ($(GFXBUILD),$(BUILD))
$(GFXBUILD):
@mkdir -p $@
endif
ifneq ($(DEPSDIR),$(BUILD))
$(DEPSDIR):
@mkdir -p $@
endif
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf $(GFXBUILD)
#---------------------------------------------------------------------------------
$(GFXBUILD)/%.t3x $(BUILD)/%.h : %.t3s
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@tex3ds -i $< -H $(BUILD)/$*.h -d $(DEPSDIR)/$*.d -o $(GFXBUILD)/$*.t3x
#---------------------------------------------------------------------------------
$(GFXBUILD)/%.bcfnt : %.ttf
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@mkbcfnt -o $(GFXBUILD)/$*.bcfnt $<
#---------------------------------------------------------------------------------
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)
@ -236,27 +273,41 @@ $(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)))
@$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)$(file)))
-include $(DEPENDS)
#---------------------------------------------------------------------------------
%.t3x %.h : %.t3s
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@tex3ds -i $< -H $*.h -d $*.d -o $*.t3x
#---------------------------------------------------------------------------------
%.bcfnt : %.ttf
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@mkbcfnt -o $*.bcfnt $<
-include $(DEPSDIR)/*.d
#---------------------------------------------------------------------------------------
endif

View File

@ -1,7 +0,0 @@
#ifndef BATTERY_H
#define BATTERY_H
char * Battery_GetBatteryPercentString(void);
void Battery_DrawIcons(int x, int y);
#endif

28
include/c2d_helper.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef _3DS_RECOVERY_TOOL_C2D_HELPER_H
#define _3DS_RECOVERY_TOOL_C2D_HELPER_H
#include <citro2d.h>
#define WHITE C2D_Color32(255, 255, 255, 255)
#define BG_COLOUR_LIGHT C2D_Color32(250, 250, 250, 255)
#define BG_COLOUR_DARK C2D_Color32(48, 48, 48, 255)
#define SELECTOR_COLOUR_LIGHT C2D_Color32(230, 232, 232, 255)
#define SELECTOR_COLOUR_DARK C2D_Color32(28, 30, 30, 255)
#define TEXT_COLOUR_LIGHT C2D_Color32(54, 54, 54, 255)
#define TEXT_COLOUR_DARK C2D_Color32(230, 230, 230, 255)
extern C3D_RenderTarget *RENDER_TOP, *RENDER_BOTTOM;
extern C2D_TextBuf c2d_static_buf, c2d_dynamic_buf, c2d_size_buf;
extern C2D_Font font;
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);
#endif

View File

@ -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

View File

@ -1,14 +0,0 @@
#ifndef COLOUR_H
#define COLOUR_H
#define BG_COLOUR_LIGHT RGBA8(250, 250, 250, 255)
#define BG_COLOUR_DARK RGBA8(48, 48, 48, 255)
#define SELECTOR_COLOUR_LIGHT RGBA8(230, 232, 232, 255)
#define SELECTOR_COLOUR_DARK RGBA8(28, 30, 30, 255)
#define TEXT_COLOUR_LIGHT RGBA8(54, 54, 54, 255)
#define TEXT_COLOUR_DARK RGBA8(230, 230, 230, 255)
#endif

View File

@ -1,8 +1,6 @@
#ifndef DIALOG_H
#define DIALOG_H
#ifndef _3DS_RECOVERY_TOOL_DIALOG_H
#define _3DS_RECOVERY_TOOL_DIALOG_H
#include <3ds.h>
Result Dialog_Draw(const char *top_message, const char *bottom_message);
Result Dialog_Draw(const char * topMessage, const char * bottomMessage);
#endif
#endif

View File

@ -1,18 +1,18 @@
#ifndef FS_H
#define FS_H
#ifndef _3DS_RECOVERY_TOOL_FS_H
#define _3DS_RECOVERY_TOOL_FS_H
#include <3ds.h>
FS_Archive sdmcArchive, nandArchive;
extern FS_Archive sdmc_archive, nand_archive;
Result FS_OpenArchive(FS_Archive * archive, FS_ArchiveID archiveID);
Result FS_OpenArchive(FS_Archive *archive, FS_ArchiveID id);
Result FS_CloseArchive(FS_Archive archive);
Result FS_MakeDir(FS_Archive archive, const char * path);
void 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);
u64 FS_GetFileSize(FS_Archive archive, const char * path);
Result FS_WriteFile(FS_Archive archive, FS_ArchiveID archiveID, const char * path, void * buf);
Result FS_Copy_File(FS_Archive srcArchive, FS_Archive destArchive, FS_ArchiveID srcArchiveID, FS_ArchiveID destArchiveID, char * src, char * dest);
Result FS_MakeDir(FS_Archive archive, const char *path);
Result FS_RecursiveMakeDir(FS_Archive archive, const char *path);
bool FS_FileExists(FS_Archive archive, const char *path);
bool FS_DirExists(FS_Archive archive, const char *path);
Result FS_GetFileSize(FS_Archive archive, const char *path, u64 *size);
Result FS_Write(FS_Archive archive, const char *path, const void *buf, u32 size);
Result FS_CopyFile(FS_Archive src_archive, FS_Archive dest_archive, char *src_path, char *dest_path);
#endif
#endif

View File

@ -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.

View File

@ -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)

File diff suppressed because it is too large Load Diff

View File

@ -1,480 +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 <citro3d.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#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 width, u32 height);
/**
* @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 Loads a texture from a buffer in memory
* @param id of the texture
* @param buf buffer where the png is stored
* @param buf_size size of buffer
*/
void pp2d_load_texture_png_memory(size_t id, void* buf, size_t buf_size);
/**
* @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*/

View File

@ -1,6 +1,6 @@
#ifndef STATUS_BAR_H
#define STATUS_BAR_H
#ifndef _3DS_RECOVERY_TOOL_STATUS_BAR_H
#define _3DS_RECOVERY_TOOL_STATUS_BAR_H
void StatusBar_DisplayBar(void);
#endif
#endif

View File

@ -1,23 +1,12 @@
#ifndef TEXTURES_H
#define TEXTURES_H
#ifndef _3DS_RECOVERY_TOOL_TEXTURES_H
#define _3DS_RECOVERY_TOOL_TEXTURES_H
#define TEXTURE_TOGGLE_ON 0
#define TEXTURE_TOGGLE_OFF 1
C2D_Image icon_toggle_on, icon_toggle_off, icon_back, icon_wifi_0, icon_wifi_1, icon_wifi_2, icon_wifi_3, \
battery_20, battery_20_charging, battery_30, battery_30_charging, battery_50, battery_50_charging, \
battery_60, battery_60_charging, battery_80, battery_80_charging, battery_90, battery_90_charging, \
battery_full, battery_full_charging, battery_low, battery_unknown;
#define TEXTURE_BATTERY_0 2
#define TEXTURE_BATTERY_15 3
#define TEXTURE_BATTERY_28 4
#define TEXTURE_BATTERY_43 5
#define TEXTURE_BATTERY_57 6
#define TEXTURE_BATTERY_71 7
#define TEXTURE_BATTERY_85 8
#define TEXTURE_BATTERY_100 9
#define TEXTURE_BATTERY_CHARGE 10
void Textures_Load(void);
void Textures_Free(void);
#define TEXTURE_WIFI_NULL 11
#define TEXTURE_WIFI_0 12
#define TEXTURE_WIFI_1 13
#define TEXTURE_WIFI_2 14
#define TEXTURE_WIFI_3 15
#endif
#endif

View File

@ -1,16 +1,17 @@
#ifndef UTILS_H
#define UTILS_H
#ifndef _3DS_RECOVERY_TOOL_UTILS_H
#define _3DS_RECOVERY_TOOL_UTILS_H
#include <3ds.h>
#define touchInRect(x1, y1, x2, y2) ((touchGetX() >= (x1) && touchGetX() <= (x2)) && (touchGetY() >= (y1) && touchGetY() <= (y2)))
bool darkTheme;
extern bool dark_theme;
Result Utils_SaveConfig(bool dark_theme);
Result Utils_LoadConfig(void);
bool Utils_IsN3DS(void);
u16 touchGetX(void);
u16 touchGetY(void);
void Utils_SetMax(int *set, int value, int max);
void Utils_SetMin(int *set, int value, int min);
#endif
#endif

View File

@ -1,6 +0,0 @@
#ifndef COMMON_H
#define COMMON_H
void WiFi_DrawIcons(int x, int y);
#endif

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

BIN
res/drawable/battery_20.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 B

BIN
res/drawable/battery_30.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

BIN
res/drawable/battery_50.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

BIN
res/drawable/battery_60.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 B

BIN
res/drawable/battery_80.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 B

BIN
res/drawable/battery_90.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 B

25
res/drawable/sprites.t3s Normal file
View File

@ -0,0 +1,25 @@
--atlas -f rgba -z auto
battery_20.png
battery_20_charging.png
battery_30.png
battery_30_charging.png
battery_50.png
battery_50_charging.png
battery_60.png
battery_60_charging.png
battery_80.png
battery_80_charging.png
battery_90.png
battery_90_charging.png
battery_full.png
battery_full_charging.png
battery_low.png
battery_unknown.png
btn_material_light_toggle_off_normal.png
btn_material_light_toggle_on_normal.png
ic_arrow_back_normal.png
stat_sys_wifi_signal_0.png
stat_sys_wifi_signal_1.png
stat_sys_wifi_signal_2.png
stat_sys_wifi_signal_3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 436 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

View File

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@ -1,62 +0,0 @@
#include <3ds.h>
#include <stdio.h>
#include "battery.h"
#include "pp2d.h"
#include "textures.h"
static u8 Battery_GetBatteryPercent(void)
{
u8 batteryPercent = 0;
if (R_SUCCEEDED(mcuHwcInit()))
{
if (R_SUCCEEDED(MCUHWC_GetBatteryLevel(&batteryPercent)))
mcuHwcExit();
}
return batteryPercent;
}
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(ptmuInit()))
{
if (R_SUCCEEDED(PTMU_GetBatteryChargeState(&batteryState)))
{
if (batteryState)
pp2d_draw_texture(TEXTURE_BATTERY_CHARGE, x + 2, y + 2);
}
ptmuExit();
}
}

55
source/c2d_helper.c Normal file
View File

@ -0,0 +1,55 @@
#include <stdarg.h>
#include "c2d_helper.h"
C3D_RenderTarget *RENDER_TOP, *RENDER_BOTTOM;
C2D_TextBuf c2d_static_buf, c2d_dynamic_buf, c2d_size_buf;
C2D_Font font;
void Draw_EndFrame(void) {
C2D_TextBufClear(c2d_dynamic_buf);
C2D_TextBufClear(c2d_size_buf);
C3D_FrameEnd(0);
}
void Draw_Text(float x, float y, float size, Colour colour, const char *text) {
C2D_Text c2d_text;
C2D_TextFontParse(&c2d_text, font, c2d_dynamic_buf, 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_TextFontParse(&c2d_text, font, c2d_size_buf, 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);
}

View File

@ -1,32 +0,0 @@
#include <stdio.h>
#include <time.h>
#include "clock.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;
}

View File

@ -1,55 +1,46 @@
#include "colours.h"
#include "dialog.h"
#include "pp2d.h"
#include <3ds.h>
#include "c2d_helper.h"
#include "utils.h"
Result Dialog_Draw(const char * topMessage, const char * bottomMessage)
{
Result Dialog_Draw(const char *top_message, const char *bottom_message) {
Result ret = 0;
float topWidth = pp2d_get_text_width(topMessage, 0.6f, 0.6f);
float topHeight = pp2d_get_text_height(topMessage, 0.6f, 0.6f);
float top_width = Draw_GetTextWidth(0.6f, top_message);
float top_height = Draw_GetTextHeight(0.6f, top_message);
float bottomWidth = pp2d_get_text_width(bottomMessage, 0.6f, 0.6f);
float bottomHeight = pp2d_get_text_height(bottomMessage, 0.6f, 0.6f);
float bottom_width = Draw_GetTextWidth(0.6f, bottom_message);
float bottom_height = Draw_GetTextHeight(0.6f, bottom_message);
touchPosition touch;
while (aptMainLoop())
{
pp2d_begin_draw(GFX_TOP, GFX_LEFT);
while (aptMainLoop()) {
C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
C2D_SceneBegin(RENDER_TOP);
Draw_Rect(0, 0, 400, 240, dark_theme? BG_COLOUR_DARK : BG_COLOUR_LIGHT);
Draw_Text(((400 - top_width) / 2), (((240 - top_height) / 2) - 20), 0.6f, dark_theme? TEXT_COLOUR_DARK : TEXT_COLOUR_LIGHT, top_message);
Draw_Text(((400 - bottom_width) / 2), (((240 - bottom_height) / 2) + 20), 0.6f, dark_theme? TEXT_COLOUR_DARK : TEXT_COLOUR_LIGHT, bottom_message);
pp2d_draw_rectangle(0, 0, 400, 240, darkTheme? BG_COLOUR_DARK : BG_COLOUR_LIGHT);
C2D_SceneBegin(RENDER_BOTTOM);
Draw_Rect(0, 0, 320, 240, dark_theme? BG_COLOUR_DARK : BG_COLOUR_LIGHT);
Draw_Text(((160 - Draw_GetTextWidth(0.5f, "CANCEL")) / 2), (220 - Draw_GetTextHeight(0.5f, "CANCEL")), 0.5f, C2D_Color32(0, 151, 136, 255), "CANCEL");
Draw_Text((((160 - Draw_GetTextWidth(0.5f, "OK")) / 2) + 160), (220 - Draw_GetTextHeight(0.5f, "OK")), 0.5f, C2D_Color32(0, 151, 136, 255), "OK");
pp2d_draw_text(((400 - topWidth) / 2), (((240 - topHeight) / 2) - 20), 0.6f, 0.6f, darkTheme? TEXT_COLOUR_DARK : TEXT_COLOUR_LIGHT, topMessage);
pp2d_draw_text(((400 - bottomWidth) / 2), (((240 - bottomHeight) / 2) + 20), 0.6f, 0.6f, darkTheme? TEXT_COLOUR_DARK : TEXT_COLOUR_LIGHT, bottomMessage);
pp2d_end_draw();
pp2d_begin_draw(GFX_BOTTOM, GFX_LEFT);
pp2d_draw_rectangle(0, 0, 320, 240, darkTheme? BG_COLOUR_DARK : BG_COLOUR_LIGHT);
pp2d_draw_text(((160 - pp2d_get_text_width("CANCEL", 0.5f, 0.5f)) / 2), (220 - pp2d_get_text_height("CANCEL", 0.5f, 0.5f)), 0.5f, 0.5f, RGBA8(0, 151, 136, 255), "CANCEL");
pp2d_draw_text((((160 - pp2d_get_text_width("OK", 0.5f, 0.5f)) / 2) + 160), (220 - pp2d_get_text_height("OK", 0.5f, 0.5f)), 0.5f, 0.5f, RGBA8(0, 151, 136, 255), "OK");
pp2d_end_draw();
Draw_EndFrame();
hidScanInput();
hidTouchRead(&touch);
u32 kDown = hidKeysDown();
if ((kDown & KEY_A) || ((touchInRect(160, 190, 320, 240)) && (kDown & KEY_TOUCH)))
{
if ((kDown & KEY_A) || ((touchInRect(160, 190, 320, 240)) && (kDown & KEY_TOUCH))) {
ret = 1;
break;
}
else if ((kDown & KEY_B) || ((touchInRect(0, 190, 159, 240)) && (kDown & KEY_TOUCH)))
{
else if ((kDown & KEY_B) || ((touchInRect(0, 190, 159, 240)) && (kDown & KEY_TOUCH))) {
ret = -1;
break;
}
}
return ret;
}
}

View File

@ -4,8 +4,9 @@
#include "fs.h"
Result FS_OpenArchive(FS_Archive * archive, FS_ArchiveID archiveID)
{
FS_Archive sdmc_archive, nand_archive;
Result FS_OpenArchive(FS_Archive *archive, FS_ArchiveID archiveID) {
Result ret = 0;
if (R_FAILED(ret = FSUSER_OpenArchive(archive, archiveID, fsMakePath(PATH_EMPTY, ""))))
@ -14,8 +15,7 @@ Result FS_OpenArchive(FS_Archive * archive, FS_ArchiveID archiveID)
return 0;
}
Result FS_CloseArchive(FS_Archive archive)
{
Result FS_CloseArchive(FS_Archive archive) {
Result ret = 0;
if (R_FAILED(ret = FSUSER_CloseArchive(archive)))
@ -24,8 +24,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;
if (R_FAILED(ret = FSUSER_CreateDirectory(archive, fsMakePath(PATH_ASCII, path), 0)))
@ -34,32 +33,36 @@ Result FS_MakeDir(FS_Archive archive, const char * path)
return 0;
}
void FS_RecursiveMakeDir(FS_Archive archive, const char * dir)
{
char tmp[256];
Result FS_RecursiveMakeDir(FS_Archive archive, const char *path) {
Result ret = 0;
char buf[256];
char *p = NULL;
size_t len;
snprintf(tmp, sizeof(tmp), "%s",dir);
len = strlen(tmp);
snprintf(buf, sizeof(buf), "%s", path);
len = strlen(buf);
if (tmp[len - 1] == '/')
tmp[len - 1] = 0;
if (buf[len - 1] == '/')
buf[len - 1] = 0;
for (p = tmp + 1; *p; p++)
{
if (*p == '/')
{
for (p = buf + 1; *p; p++) {
if (*p == '/') {
*p = 0;
FS_MakeDir(archive, tmp);
if (!FS_DirExists(archive, buf))
ret = FS_MakeDir(archive, buf);
*p = '/';
}
FS_MakeDir(archive, tmp);
if (!FS_DirExists(archive, buf))
ret = FS_MakeDir(archive, buf);
}
return ret;
}
bool FS_FileExists(FS_Archive archive, const char * path)
{
bool FS_FileExists(FS_Archive archive, const char *path) {
Handle handle;
if (R_FAILED(FSUSER_OpenFile(&handle, archive, fsMakePath(PATH_ASCII, path), FS_OPEN_READ, 0)))
@ -71,8 +74,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;
if (R_FAILED(FSUSER_OpenDirectory(&handle, archive, fsMakePath(PATH_ASCII, path))))
@ -84,103 +86,100 @@ bool FS_DirExists(FS_Archive archive, const char * path)
return true;
}
u64 FS_GetFileSize(FS_Archive archive, const char * path)
{
Handle handle;
Result FS_GetFileSize(FS_Archive archive, const char *path, u64 *size) {
Result ret = 0;
u64 st_size = 0;
Handle handle;
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))) {
FSFILE_Close(handle);
return ret;
if (R_FAILED(ret = FSFILE_Close(handle)))
return ret;
return st_size;
}
Result FS_WriteFile(FS_Archive archive, FS_ArchiveID archiveID, const char * path, void * buf)
{
Handle handle;
Result ret = 0;
u32 len = strlen(buf);
u64 size;
u32 written;
if (FS_FileExists(archive, path))
FSUSER_DeleteFile(archive, fsMakePath(PATH_ASCII, path));
if (R_FAILED(ret = FSUSER_OpenFileDirectly(&handle, archiveID, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, path), (FS_OPEN_WRITE | FS_OPEN_CREATE), 0)))
return ret;
if (R_FAILED(ret = FSFILE_GetSize(handle, &size)))
return ret;
if (R_FAILED(ret = FSFILE_SetSize(handle, size + len)))
return ret;
if (R_FAILED(ret = FSFILE_Write(handle, &written, size, buf, len, FS_WRITE_FLUSH)))
return ret;
if (R_FAILED(ret = FSFILE_Close(handle)))
return ret;
return 0;
}
Result FS_Copy_File(FS_Archive srcArchive, FS_Archive destArchive, FS_ArchiveID srcArchiveID, FS_ArchiveID destArchiveID, char * src, char * dest)
{
int chunksize = (512 * 1024);
char * buffer = (char *)malloc(chunksize);
u32 bytesWritten = 0, bytesRead = 0;
u64 offset = 0;
Result ret = 0;
Handle inputHandle, outputHandle;
Result in = FSUSER_OpenFileDirectly(&inputHandle, srcArchiveID, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, src), FS_OPEN_READ, 0);
u64 size = FS_GetFileSize(srcArchive, src);
if (R_SUCCEEDED(in))
{
// Delete output file (if existing)
FSUSER_DeleteFile(destArchive, fsMakePath(PATH_ASCII, dest));
Result out = FSUSER_OpenFileDirectly(&outputHandle, destArchiveID, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, dest), (FS_OPEN_CREATE | FS_OPEN_WRITE), 0);
if (R_SUCCEEDED(out))
{
// Copy loop (512KB at a time)
do
{
ret = FSFILE_Read(inputHandle, &bytesRead, offset, buffer, chunksize);
bytesWritten += FSFILE_Write(outputHandle, &bytesWritten, offset, buffer, size, FS_WRITE_FLUSH);
if (bytesWritten == bytesRead)
break;
}
while(bytesRead);
ret = FSFILE_Close(outputHandle);
if (bytesRead != bytesWritten)
return ret;
}
else
return out;
FSFILE_Close(inputHandle);
}
else
return in;
free(buffer);
if (R_FAILED(ret = FSFILE_Close(handle)))
return ret;
return 0;
}
}
static Result FS_RemoveFile(FS_Archive archive, const char *path) {
Result ret = 0;
if (R_FAILED(ret = FSUSER_DeleteFile(archive, fsMakePath(PATH_ASCII, path))))
return ret;
return 0;
}
Result FS_Write(FS_Archive archive, const char *path, const void *buf, u32 size) {
Result ret = 0;
Handle handle;
u32 bytes_written = 0;
if (FS_FileExists(archive, path)) {
if (R_FAILED(ret = FS_RemoveFile(archive, path)))
return ret;
}
if (R_FAILED(ret = FSUSER_CreateFile(archive, fsMakePath(PATH_ASCII, path), 0, size)))
return ret;
if (R_FAILED(ret = FSUSER_OpenFile(&handle, archive, fsMakePath(PATH_ASCII, path), FS_OPEN_WRITE, 0)))
return ret;
if (R_FAILED(ret = FSFILE_Write(handle, &bytes_written, 0, buf, size, FS_WRITE_FLUSH))) {
FSFILE_Close(handle);
return ret;
}
if (R_FAILED(ret = FSFILE_Close(handle)))
return ret;
return 0;
}
Result FS_CopyFile(FS_Archive src_archive, FS_Archive dest_archive, char *src_path, char *dest_path) {
Handle src_handle, dst_handle;
Result ret = 0;
if (R_FAILED(ret = FSUSER_OpenFile(&src_handle, src_archive, fsMakePath(PATH_ASCII, src_path), FS_OPEN_READ, 0)))
return ret;
if (R_FAILED(ret = FSUSER_OpenFile(&dst_handle, dest_archive, fsMakePath(PATH_ASCII, dest_path), FS_OPEN_CREATE | FS_OPEN_WRITE, 0))) {
FSFILE_Close(src_handle);
return ret;
}
u32 bytes_read = 0;
u64 offset = 0, size = 0;
size_t buf_size = 0x10000;
u8 *buf = malloc(buf_size); // Chunk size
FS_GetFileSize(src_archive, src_path, &size);
do {
memset(buf, 0, buf_size);
if (R_FAILED(ret = FSFILE_Read(src_handle, &bytes_read, offset, buf, buf_size))) {
free(buf);
FSFILE_Close(src_handle);
FSFILE_Close(dst_handle);
return ret;
}
if (R_FAILED(ret = FSFILE_Write(dst_handle, NULL, offset, buf, bytes_read, FS_WRITE_FLUSH))) {
free(buf);
FSFILE_Close(src_handle);
FSFILE_Close(dst_handle);
return ret;
}
offset += bytes_read;
}
while(offset < size);
free(buf);
FSFILE_Close(src_handle);
FSFILE_Close(dst_handle);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -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.

View File

@ -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)

File diff suppressed because it is too large Load Diff

View File

@ -1,811 +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"
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_TexEnvOp(env, C3D_Both, 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_RenderTargetSetClear(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_RenderTargetSetClear(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_RenderTargetSetClear(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 width, u32 height)
{
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, GPU_RGBA8);
C3D_TexSetFilter(&textures[id].tex, textureFilters.magFilter, textureFilters.minFilter);
textures[id].allocated = true;
textures[id].width = width;
textures[id].height = height;
memset(textures[id].tex.data, 0, textures[id].tex.size);
for (u32 i = 0; i < width; i++)
{
for (u32 j = 0; j < height; j++)
{
u32 dst = ((((j >> 3) * (w_pow2 >> 3) + (i >> 3)) << 6) + ((i & 1) | ((j & 1) << 1) | ((i & 2) << 1) | ((j & 2) << 2) | ((i & 4) << 2) | ((j & 4) << 3))) * 4;
u32 src = (j * width + i) * 4;
memcpy(textures[id].tex.data + dst, buf + src, 4);
}
}
C3D_TexFlush(&textures[id].tex);
}
void pp2d_load_texture_png(size_t id, const char* path)
{
if (id >= MAX_TEXTURES)
return;
u8* image;
unsigned width, height;
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, width, height);
free(image);
}
void pp2d_load_texture_png_memory(size_t id, void* buf, size_t buf_size)
{
if (id >= MAX_TEXTURES)
return;
u8* image;
unsigned width;
unsigned height;
lodepng_decode32(&image, &width, &height, buf, buf_size);
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, width, height);
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_RenderTargetSetClear(topLeft, C3D_CLEAR_ALL, color, 0);
C3D_RenderTargetSetClear(topRight, C3D_CLEAR_ALL, color, 0);
}
else
{
C3D_RenderTargetSetClear(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_TexEnvOp(env, C3D_Both, 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_TexEnvOp(env, C3D_Both, 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);
}

View File

@ -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

View File

@ -1,22 +1,81 @@
#include "battery.h"
#include "clock.h"
#include "pp2d.h"
#include <3ds.h>
#include <time.h>
#include "c2d_helper.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;
static char *Clock_GetCurrentTime(void) {
time_t t = time(0);
int hour = localtime(&t)->tm_hour % 12;
int min = localtime(&t)->tm_min;
int AmPm = localtime(&t)->tm_hour / 12;
static char buffer[27];
snprintf(buffer, 27, "%2i:%02i %s", (hour == 0)? 12 : hour, min, AmPm? "PM" : "AM");
return buffer;
}
pp2d_draw_text(time_x, 1, 0.45f, 0.45f, RGBA8(255, 255, 255, 255), Clock_GetCurrentTime(true));
static void StatusBar_GetBatteryStatus(int x, int y, float *percent_width) {
u8 percent = 0, state = 0;
char buf[5];
Battery_DrawIcons(battery_texture_x, 1);
if (R_FAILED(PTMU_GetBatteryChargeState(&state)))
state = 0;
pp2d_draw_text(battery_string_x, 1, 0.45f, 0.45f, RGBA8(255, 255, 255, 255), Battery_GetBatteryPercentString());
if (R_SUCCEEDED(MCUHWC_GetBatteryLevel(&percent))) {
if (percent < 20)
Draw_Image(battery_low, x, 1);
else if ((percent >= 20) && (percent < 30))
Draw_Image(state == 1? battery_20_charging : battery_20, x, 1);
else if ((percent >= 30) && (percent < 50))
Draw_Image(state == 1? battery_50_charging : battery_50, x, 1);
else if ((percent >= 50) && (percent < 60))
Draw_Image(state == 1? battery_50_charging : battery_50, x, 1);
else if ((percent >= 60) && (percent < 80))
Draw_Image(state == 1? battery_60_charging : battery_60, x, 1);
else if ((percent >= 80) && (percent < 90))
Draw_Image(state == 1? battery_80_charging : battery_80, x, 1);
else if ((percent >= 90) && (percent < 100))
Draw_Image(state == 1? battery_90_charging : battery_90, x, 1);
else if (percent == 100)
Draw_Image(state == 1? battery_full_charging : battery_full, x, 1);
WiFi_DrawIcons(wifi_x, 1);
}
snprintf(buf, 5, "%d%%", percent);
*percent_width = Draw_GetTextWidth(0.45f, buf);
Draw_Text((float)(x - *percent_width - 5), y - 1, 0.4f, WHITE, buf);
}
else {
snprintf(buf, 5, "%d%%", percent);
*percent_width = Draw_GetTextWidth(0.45f, buf);
Draw_Text((float)(x - *percent_width - 5), y - 1, 0.4f, WHITE, buf);
Draw_Image(battery_unknown, x, 1);
}
}
static void StatusBar_GetWifiStatus(int x) {
switch(osGetWifiStrength()) {
case 0:
Draw_Image(icon_wifi_0, x, 2);
break;
case 1:
Draw_Image(icon_wifi_1, x, 2);
break;
case 2:
Draw_Image(icon_wifi_2, x, 2);
break;
case 3:
Draw_Image(icon_wifi_3, x, 2);
break;
}
}
void StatusBar_DisplayBar(void) {
float width = 0, height = 0, percent_width = 0;
Draw_GetTextSize(0.4f, &width, &height, Clock_GetCurrentTime());
StatusBar_GetBatteryStatus((float)((395 - width) - (10 + 12)), (float)((18 - height) / 2), &percent_width);
StatusBar_GetWifiStatus((float)((395 - width) - (10 + 14) - (10 + 12) - (percent_width + 10)));
Draw_Text((float)(395 - width), (float)((18 - height) / 2) - 2, 0.4f, WHITE, Clock_GetCurrentTime());
}

36
source/textures.c Normal file
View File

@ -0,0 +1,36 @@
#include "c2d_helper.h"
#include "sprites.h"
#include "textures.h"
static C2D_SpriteSheet spritesheet;
void Textures_Load(void) {
spritesheet = C2D_SpriteSheetLoad("romfs:/res/drawable/sprites.t3x");
icon_toggle_on = C2D_SpriteSheetGetImage(spritesheet, sprites_btn_material_light_toggle_on_normal_idx);
icon_toggle_off = C2D_SpriteSheetGetImage(spritesheet, sprites_btn_material_light_toggle_off_normal_idx);
icon_back = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_arrow_back_normal_idx);
icon_wifi_0 = C2D_SpriteSheetGetImage(spritesheet, sprites_stat_sys_wifi_signal_0_idx);
icon_wifi_1 = C2D_SpriteSheetGetImage(spritesheet, sprites_stat_sys_wifi_signal_1_idx);
icon_wifi_2 = C2D_SpriteSheetGetImage(spritesheet, sprites_stat_sys_wifi_signal_2_idx);
icon_wifi_3 = C2D_SpriteSheetGetImage(spritesheet, sprites_stat_sys_wifi_signal_3_idx);
battery_20 = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_20_idx);
battery_20_charging = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_20_charging_idx);
battery_30 = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_30_idx);
battery_30_charging = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_30_charging_idx);
battery_50 = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_50_idx);
battery_50_charging = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_50_charging_idx);
battery_60 = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_60_idx);
battery_60_charging = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_60_charging_idx);
battery_80 = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_80_idx);
battery_80_charging = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_80_charging_idx);
battery_90 = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_90_idx);
battery_90_charging = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_90_charging_idx);
battery_full = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_full_idx);
battery_full_charging = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_full_charging_idx);
battery_low = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_low_idx);
battery_unknown = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_unknown_idx);
}
void Textures_Free(void) {
C2D_SpriteSheetFree(spritesheet);
}

View File

@ -4,18 +4,15 @@
#include "fs.h"
#include "utils.h"
const char * configFile =
"dark_theme = %d\n";
Result Utils_SaveConfig(bool dark_theme)
{
bool dark_theme = false;
Result Utils_SaveConfig(bool dark_theme) {
Result ret = 0;
char * buf = (char *)malloc(1024);
snprintf(buf, 1024, configFile, dark_theme);
char *buf = malloc(32);
int length = snprintf(buf, 32, "dark_theme = %d\n", dark_theme);
if (R_FAILED(ret = FS_WriteFile(sdmcArchive, ARCHIVE_SDMC, "/3ds/3ds_rec_tool/config.cfg", buf)))
{
if (R_FAILED(ret = FS_Write(sdmc_archive, "/3ds/3DSRecoveryTool/config.cfg", buf, length))) {
free(buf);
return ret;
}
@ -24,41 +21,30 @@ Result Utils_SaveConfig(bool dark_theme)
return 0;
}
Result Utils_LoadConfig(void)
{
Result Utils_LoadConfig(void) {
Handle handle;
Result ret = 0;
if (!FS_FileExists(sdmcArchive, "/3ds/3ds_rec_tool/config.cfg"))
{
darkTheme = false;
return Utils_SaveConfig(darkTheme);
if (!FS_FileExists(sdmc_archive, "/3ds/3DSRecoveryTool/config.cfg")) {
dark_theme = false;
return Utils_SaveConfig(dark_theme);
}
if (R_FAILED(ret = FSUSER_OpenFileDirectly(&handle, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, "/3ds/3ds_rec_tool/config.cfg"), FS_OPEN_READ, 0)))
if (R_FAILED(ret = FSUSER_OpenFile(&handle, sdmc_archive, fsMakePath(PATH_ASCII, "/3ds/3DSRecoveryTool/config.cfg"), FS_OPEN_READ, 0)))
return ret;
u64 size64 = 0;
u32 size = 0;
if (R_FAILED(ret = FSFILE_GetSize(handle, &size64)))
u64 size = 0;
if (R_FAILED(ret = FSFILE_GetSize(handle, &size)))
return ret;
size = (u32)size64;
char * buf = (char *)malloc(size + 1);
u32 bytesread = 0;
if (R_FAILED(ret = FSFILE_Read(handle, &bytesread, 0, (u32 *)buf, size)))
{
char *buf = malloc(size + 1);
if (R_FAILED(ret = FSFILE_Read(handle, NULL, 0, (u32 *)buf, size))) {
free(buf);
return ret;
}
buf[size] = '\0';
sscanf(buf, configFile, &darkTheme);
sscanf(buf, "dark_theme = %d\n", (int *)&dark_theme);
free(buf);
if (R_FAILED(ret = FSFILE_Close(handle)))
@ -67,8 +53,7 @@ Result Utils_LoadConfig(void)
return 0;
}
bool Utils_IsN3DS(void)
{
bool Utils_IsN3DS(void) {
bool isNew3DS = false;
if (R_SUCCEEDED(APT_CheckNew3DS(&isNew3DS)))
@ -77,16 +62,24 @@ bool Utils_IsN3DS(void)
return false;
}
u16 touchGetX(void)
{
u16 touchGetX(void) {
touchPosition pos;
hidTouchRead(&pos);
return pos.px;
}
u16 touchGetY(void)
{
u16 touchGetY(void) {
touchPosition pos;
hidTouchRead(&pos);
return pos.py;
}
}
void Utils_SetMax(int *set, int value, int max) {
if (*set > max)
*set = value;
}
void Utils_SetMin(int *set, int value, int min) {
if (*set < min)
*set = value;
}

View File

@ -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);
}
}