Major clean up and update to use citro2d
249
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,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
|
||||
|
@ -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
@ -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
|
@ -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
|
@ -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
|
@ -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
|
||||
|
24
include/fs.h
@ -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
|
||||
|
@ -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.
|
@ -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)
|
@ -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*/
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,6 +0,0 @@
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
void WiFi_DrawIcons(int x, int y);
|
||||
|
||||
#endif
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
BIN
res/drawable/Roboto-Regular.ttf
Normal file
BIN
res/drawable/battery_20.png
Normal file
After Width: | Height: | Size: 230 B |
BIN
res/drawable/battery_20_charging.png
Normal file
After Width: | Height: | Size: 327 B |
BIN
res/drawable/battery_30.png
Normal file
After Width: | Height: | Size: 230 B |
BIN
res/drawable/battery_30_charging.png
Normal file
After Width: | Height: | Size: 332 B |
BIN
res/drawable/battery_50.png
Normal file
After Width: | Height: | Size: 231 B |
BIN
res/drawable/battery_50_charging.png
Normal file
After Width: | Height: | Size: 332 B |
BIN
res/drawable/battery_60.png
Normal file
After Width: | Height: | Size: 231 B |
BIN
res/drawable/battery_60_charging.png
Normal file
After Width: | Height: | Size: 331 B |
BIN
res/drawable/battery_80.png
Normal file
After Width: | Height: | Size: 227 B |
BIN
res/drawable/battery_80_charging.png
Normal file
After Width: | Height: | Size: 328 B |
BIN
res/drawable/battery_90.png
Normal file
After Width: | Height: | Size: 222 B |
BIN
res/drawable/battery_90_charging.png
Normal file
After Width: | Height: | Size: 340 B |
BIN
res/drawable/battery_full.png
Normal file
After Width: | Height: | Size: 178 B |
BIN
res/drawable/battery_full_charging.png
Normal file
After Width: | Height: | Size: 305 B |
BIN
res/drawable/battery_low.png
Normal file
After Width: | Height: | Size: 230 B |
BIN
res/drawable/battery_unknown.png
Normal file
After Width: | Height: | Size: 318 B |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
BIN
res/drawable/ic_arrow_back_normal.png
Normal file
After Width: | Height: | Size: 271 B |
25
res/drawable/sprites.t3s
Normal 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
|
||||
|
BIN
res/drawable/stat_sys_wifi_signal_0.png
Normal file
After Width: | Height: | Size: 326 B |
BIN
res/drawable/stat_sys_wifi_signal_1.png
Normal file
After Width: | Height: | Size: 399 B |
BIN
res/drawable/stat_sys_wifi_signal_2.png
Normal file
After Width: | Height: | Size: 436 B |
BIN
res/drawable/stat_sys_wifi_signal_3.png
Normal file
After Width: | Height: | Size: 407 B |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 14 KiB |
@ -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
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
227
source/fs.c
@ -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;
|
||||
}
|
||||
|
805
source/main.c
@ -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.
|
@ -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)
|
@ -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);
|
||||
}
|
@ -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
|
@ -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
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|