Merge branch 'master' into gpu_revamp
This commit is contained in:
commit
b40d605660
26
examples/Makefile
Normal file
26
examples/Makefile
Normal file
@ -0,0 +1,26 @@
|
||||
SUBDIRS:= $(shell ls | egrep -v '^(CVS)$$')
|
||||
|
||||
DATESTRING := $(shell date +%Y)$(shell date +%m)$(shell date +%d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
all: examples
|
||||
#---------------------------------------------------------------------------------
|
||||
@rm -fr bin
|
||||
@mkdir -p bin
|
||||
@find . -name "*.3dsx" -exec cp -fv {} bin \;
|
||||
|
||||
examples:
|
||||
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i || { exit 1;} fi; done;
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
#---------------------------------------------------------------------------------
|
||||
@rm -fr bin
|
||||
@rm -f *.bz2
|
||||
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i clean || { exit 1;} fi; done;
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
dist: clean
|
||||
#---------------------------------------------------------------------------------
|
||||
@rm -fr bin
|
||||
@tar --exclude=.svn --exclude=*CVS* -cvjf 3ds-examples-$(DATESTRING).tar.bz2 *
|
@ -35,7 +35,7 @@ INCLUDES := include
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=softfp
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffast-math \
|
||||
@ -120,7 +120,7 @@ all: $(BUILD)
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
|
@ -6,10 +6,7 @@
|
||||
|
||||
int main()
|
||||
{
|
||||
srvInit(); // Needed
|
||||
aptInit(); // Needed
|
||||
gfxInit(); // Init graphic stuff
|
||||
hidInit(NULL); // For input (buttons, touchscreen...)
|
||||
gfxInitDefault(); // Init graphic stuff
|
||||
|
||||
|
||||
// We need these 2 buffers for APT_DoAppJump() later. They can be smaller too
|
||||
@ -46,11 +43,7 @@ int main()
|
||||
}
|
||||
|
||||
|
||||
// Deinit everything before the app process get's terminated
|
||||
hidExit();
|
||||
gfxExit();
|
||||
aptExit();
|
||||
srvExit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
170
examples/audio/mic/Makefile
Normal file
170
examples/audio/mic/Makefile
Normal file
@ -0,0 +1,170 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
include $(DEVKITARM)/3ds_rules
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# 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
|
||||
#
|
||||
# NO_SMDH: if set to anything, no SMDH file is generated.
|
||||
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
|
||||
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
|
||||
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
|
||||
# ICON is the filename of the icon (.png), relative to the project folder.
|
||||
# If not set, it attempts to use one of the following (in this order):
|
||||
# - <Project name>.png
|
||||
# - icon.png
|
||||
# - <libctru folder>/default_icon.png
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := $(notdir $(CURDIR))
|
||||
BUILD := build
|
||||
SOURCES := source
|
||||
DATA := data
|
||||
INCLUDES := include
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffast-math \
|
||||
$(ARCH)
|
||||
|
||||
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
|
||||
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||
|
||||
LIBS := -lctru -lm
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := $(CTRULIB)
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export TOPDIR := $(CURDIR)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CXX)
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||
|
||||
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)
|
||||
|
||||
ifeq ($(strip $(ICON)),)
|
||||
icons := $(wildcard *.png)
|
||||
ifneq (,$(findstring $(TARGET).png,$(icons)))
|
||||
export APP_ICON := $(TOPDIR)/$(TARGET).png
|
||||
else
|
||||
ifneq (,$(findstring icon.png,$(icons)))
|
||||
export APP_ICON := $(TOPDIR)/icon.png
|
||||
endif
|
||||
endif
|
||||
else
|
||||
export APP_ICON := $(TOPDIR)/$(ICON)
|
||||
endif
|
||||
|
||||
.PHONY: $(BUILD) clean all
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
all: $(BUILD)
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(NO_SMDH)),)
|
||||
.PHONY: all
|
||||
all : $(OUTPUT).3dsx $(OUTPUT).smdh
|
||||
endif
|
||||
$(OUTPUT).3dsx : $(OUTPUT).elf
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# you need a rule like this for each extension you use as binary data
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
# WARNING: This is not the right way to do this! TODO: Do it right!
|
||||
#---------------------------------------------------------------------------------
|
||||
%.vsh.o : %.vsh
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
|
||||
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
|
||||
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
|
||||
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
|
||||
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
|
||||
@rm ../$(notdir $<).shbin
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
@ -13,11 +13,8 @@ int main()
|
||||
u8 control=0x40;
|
||||
u32 audio_initialized = 0;
|
||||
|
||||
srvInit();
|
||||
aptInit();
|
||||
gfxInit();
|
||||
hidInit(NULL);
|
||||
|
||||
gfxInitDefault();
|
||||
|
||||
if(CSND_initialize(NULL)==0)audio_initialized = 1;
|
||||
|
||||
sharedmem = (u32*)memalign(0x1000, sharedmem_size);
|
||||
@ -85,10 +82,7 @@ int main()
|
||||
free(sharedmem);
|
||||
linearFree(audiobuf);
|
||||
|
||||
hidExit();
|
||||
gfxExit();
|
||||
aptExit();
|
||||
srvExit();
|
||||
return 0;
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ INCLUDES := include
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=softfp
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffast-math \
|
||||
@ -124,7 +124,7 @@ all: $(BUILD)
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
|
@ -6,7 +6,7 @@
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// Initialize services
|
||||
gfxInit();
|
||||
gfxInitDefault();
|
||||
initCfgu();
|
||||
|
||||
|
||||
|
@ -35,7 +35,7 @@ INCLUDES := include
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=softfp
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffast-math \
|
||||
@ -120,7 +120,7 @@ all: $(BUILD)
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@ -153,7 +153,7 @@ $(OUTPUT).elf : $(OFILES)
|
||||
|
||||
# WARNING: This is not the right way to do this! TODO: Do it right!
|
||||
#---------------------------------------------------------------------------------
|
||||
%.vsh.o : %.vsh
|
||||
%_vsh.h %.vsh.o : %.vsh
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
|
||||
|
@ -1,5 +1,11 @@
|
||||
gpu
|
||||
=======
|
||||
|
||||
example of how to use the GPU with ctrulib
|
||||
before trying to compile, make sure to download aemstro ( https://github.com/smealum/aemstro ) and update Makefile's AEMSTROPATH definition with the proper path
|
||||
example of how to use the GPU with libctru
|
||||
|
||||
before trying to compile, make sure to download aemstro
|
||||
( https://github.com/smealum/aemstro reflog: 55bf5056d199e0e9ec3d136dc830ac45a49da074 )
|
||||
and update Makefile's AEMSTROPATH definition with the proper path
|
||||
|
||||
You'll also need to install Python 3 and have that in your path.
|
||||
|
||||
|
@ -114,13 +114,13 @@ const vertex_s modelVboData[]=
|
||||
//stolen from staplebutt
|
||||
void GPU_SetDummyTexEnv(u8 num)
|
||||
{
|
||||
GPU_SetTexEnv(num,
|
||||
GPU_TEVSOURCES(GPU_PREVIOUS, 0, 0),
|
||||
GPU_TEVSOURCES(GPU_PREVIOUS, 0, 0),
|
||||
GPU_TEVOPERANDS(0,0,0),
|
||||
GPU_TEVOPERANDS(0,0,0),
|
||||
GPU_REPLACE,
|
||||
GPU_REPLACE,
|
||||
GPU_SetTexEnv(num,
|
||||
GPU_TEVSOURCES(GPU_PREVIOUS, 0, 0),
|
||||
GPU_TEVSOURCES(GPU_PREVIOUS, 0, 0),
|
||||
GPU_TEVOPERANDS(0,0,0),
|
||||
GPU_TEVOPERANDS(0,0,0),
|
||||
GPU_REPLACE,
|
||||
GPU_REPLACE,
|
||||
0xFFFFFFFF);
|
||||
}
|
||||
|
||||
@ -128,31 +128,31 @@ void GPU_SetDummyTexEnv(u8 num)
|
||||
void renderFrame()
|
||||
{
|
||||
GPU_SetViewport((u32*)osConvertVirtToPhys((u32)gpuDOut),(u32*)osConvertVirtToPhys((u32)gpuOut),0,0,240*2,400);
|
||||
|
||||
|
||||
GPU_DepthRange(-1.0f, 0.0f);
|
||||
GPU_SetFaceCulling(GPU_CULL_BACK_CCW);
|
||||
GPU_SetStencilTest(false, GPU_ALWAYS, 0x00, 0xFF, 0x00);
|
||||
GPU_SetStencilOp(GPU_KEEP, GPU_KEEP, GPU_KEEP);
|
||||
GPU_SetBlendingColor(0,0,0,0);
|
||||
GPU_SetDepthTestAndWriteMask(true, GPU_GREATER, GPU_WRITE_ALL);
|
||||
|
||||
GPUCMD_AddSingleParam(0x00010062, 0);
|
||||
|
||||
GPUCMD_AddSingleParam(0x00010062, 0);
|
||||
GPUCMD_AddSingleParam(0x000F0118, 0);
|
||||
|
||||
|
||||
//setup shader
|
||||
SHDR_UseProgram(shader, 0);
|
||||
|
||||
|
||||
GPU_SetAlphaBlending(GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA);
|
||||
GPU_SetAlphaTest(false, GPU_ALWAYS, 0x00);
|
||||
|
||||
|
||||
GPU_SetTextureEnable(GPU_TEXUNIT0);
|
||||
|
||||
GPU_SetTexEnv(0,
|
||||
GPU_TEVSOURCES(GPU_TEXTURE0, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR),
|
||||
|
||||
GPU_SetTexEnv(0,
|
||||
GPU_TEVSOURCES(GPU_TEXTURE0, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR),
|
||||
GPU_TEVOPERANDS(0,0,0),
|
||||
GPU_TEVOPERANDS(0,0,0),
|
||||
GPU_MODULATE, GPU_MODULATE,
|
||||
GPU_TEVSOURCES(GPU_TEXTURE0, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR),
|
||||
GPU_TEVOPERANDS(0,0,0),
|
||||
GPU_TEVOPERANDS(0,0,0),
|
||||
GPU_MODULATE, GPU_MODULATE,
|
||||
0xFFFFFFFF);
|
||||
GPU_SetDummyTexEnv(1);
|
||||
GPU_SetDummyTexEnv(2);
|
||||
@ -189,11 +189,8 @@ void renderFrame()
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
//setup services
|
||||
srvInit();
|
||||
aptInit();
|
||||
gfxInit();
|
||||
hidInit(NULL);
|
||||
|
||||
gfxInitDefault();
|
||||
|
||||
//initialize GPU
|
||||
GPU_Init(NULL);
|
||||
@ -321,9 +318,6 @@ int main(int argc, char** argv)
|
||||
}
|
||||
|
||||
gsExit();
|
||||
hidExit();
|
||||
gfxExit();
|
||||
aptExit();
|
||||
srvExit();
|
||||
return 0;
|
||||
}
|
||||
|
7
examples/graphics/Makefile
Normal file
7
examples/graphics/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
SUBDIRS:= `ls | egrep -v '^(CVS)$$'`
|
||||
all:
|
||||
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i || { exit 1;} fi; done;
|
||||
clean:
|
||||
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i clean || { exit 1;} fi; done;
|
||||
install:
|
||||
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i install || { exit 1;} fi; done;
|
190
examples/graphics/bitmap/24bit-color/Makefile
Executable file
190
examples/graphics/bitmap/24bit-color/Makefile
Executable file
@ -0,0 +1,190 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
include $(DEVKITARM)/3ds_rules
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# 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
|
||||
#
|
||||
# NO_SMDH: if set to anything, no SMDH file is generated.
|
||||
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
|
||||
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
|
||||
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
|
||||
# ICON is the filename of the icon (.png), relative to the project folder.
|
||||
# If not set, it attempts to use one of the following (in this order):
|
||||
# - <Project name>.png
|
||||
# - icon.png
|
||||
# - <libctru folder>/default_icon.png
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := $(notdir $(CURDIR))
|
||||
BUILD := build
|
||||
SOURCES := source
|
||||
DATA :=
|
||||
INCLUDES := include
|
||||
GRAPHICS := gfx
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffast-math \
|
||||
$(ARCH)
|
||||
|
||||
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
|
||||
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||
|
||||
LIBS := -lctru -lm
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := $(CTRULIB)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export TOPDIR := $(CURDIR)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
PNGFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.png)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CXX)
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||
$(PNGFILES:.png=.bgr.o) \
|
||||
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) \
|
||||
|
||||
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)
|
||||
|
||||
ifeq ($(strip $(ICON)),)
|
||||
icons := $(wildcard *.png)
|
||||
ifneq (,$(findstring $(TARGET).png,$(icons)))
|
||||
export APP_ICON := $(TOPDIR)/$(TARGET).png
|
||||
else
|
||||
ifneq (,$(findstring icon.png,$(icons)))
|
||||
export APP_ICON := $(TOPDIR)/icon.png
|
||||
endif
|
||||
endif
|
||||
else
|
||||
export APP_ICON := $(TOPDIR)/$(ICON)
|
||||
endif
|
||||
|
||||
IMAGEMAGICK := $(shell which convert)
|
||||
|
||||
|
||||
.PHONY: $(BUILD) clean all
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(IMAGEMAGICK)),)
|
||||
|
||||
all:
|
||||
@echo "Image Magick not found!"
|
||||
@echo
|
||||
@echo "Please install Image Magick from http://www.imagemagick.org/ to build this example"
|
||||
|
||||
else
|
||||
|
||||
all: $(BUILD)
|
||||
|
||||
endif
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(NO_SMDH)),)
|
||||
.PHONY: all
|
||||
all : $(OUTPUT).3dsx $(OUTPUT).smdh
|
||||
endif
|
||||
$(OUTPUT).3dsx : $(OUTPUT).elf
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# you need a rule like this for each extension you use as binary data
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bgr.o: %.bgr
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bgr: %.png
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@convert $< -rotate 90 $@
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
16
examples/graphics/bitmap/24bit-color/README.md
Normal file
16
examples/graphics/bitmap/24bit-color/README.md
Normal file
@ -0,0 +1,16 @@
|
||||
24bit Bitmap Example
|
||||
=======
|
||||
|
||||
This example shows on bottom screen an upscaled version of the nds examples Drunken Coders logo that can be found in devkitPro.
|
||||
|
||||
If you want to try with your own image follow these steps:
|
||||
|
||||
1. Download & install: http://www.imagemagick.org/ (If you get an option to add the application to the path make sure to check it!).
|
||||
2. convert fileIn.png -channel B -separate fileIn.png -channel G -separate fileIn.png -channel R -separate -channel RGB -combine -rotate 90 fileOut.rgb
|
||||
3. Rename fileOut.rgb in fileOut.bin
|
||||
4. Copy fileOut.bin in the data folder of your project
|
||||
5. Replace any reference of drunkenlogo_bin in main.cpp with fileOut_bin (or however you named it)
|
||||
6. Re-Build the project
|
||||
|
||||
|
||||
As you can see from the previos steps the image is clockwise rotated by 90 degrees and its B and R channels are swapped. The first operation is done because the 3DS screens are actually portrait screens rotated by 90 degrees (in a counter-clockwise direction), while the second one is done because the 3DS screens' framebuffers have a BGR888 color format, by default.
|
BIN
examples/graphics/bitmap/24bit-color/gfx/brew.png
Normal file
BIN
examples/graphics/bitmap/24bit-color/gfx/brew.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 138 KiB |
64
examples/graphics/bitmap/24bit-color/source/main.c
Normal file
64
examples/graphics/bitmap/24bit-color/source/main.c
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
Hello World example made by Aurelio Mannara for ctrulib
|
||||
This code was modified for the last time on: 12/13/2014 01:00 UTC+1
|
||||
|
||||
This wouldn't be possible without the amazing work done by:
|
||||
-Smealum
|
||||
-fincs
|
||||
-WinterMute
|
||||
-yellows8
|
||||
-plutoo
|
||||
-mtheall
|
||||
-Many others who worked on 3DS and I'm surely forgetting about
|
||||
*/
|
||||
|
||||
#include <3ds.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
//This include a header containing definitions of our image
|
||||
#include "brew_bgr.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
gfxInitDefault();
|
||||
|
||||
//Initialize console on top screen. Using NULL as the second argument tells the console library to use the internal console structure as current one
|
||||
consoleInit(GFX_TOP, NULL);
|
||||
|
||||
printf("Why so sad Smealum? We can haz 3DS homebrew!");
|
||||
|
||||
printf("\x1b[20;15HPress Start to exit.");
|
||||
|
||||
//We don't need double buffering in this example. In this way we can draw our image only once on screen.
|
||||
gfxSetDoubleBuffering(GFX_BOTTOM, false);
|
||||
|
||||
//Get the bottom screen's frame buffer
|
||||
u8* fb = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL);
|
||||
|
||||
//Copy our image in the bottom screen's frame buffer
|
||||
memcpy(fb, brew_bgr, brew_bgr_size);
|
||||
|
||||
// Main loop
|
||||
while (aptMainLoop())
|
||||
{
|
||||
//Scan all the inputs. This should be done once for each frame
|
||||
hidScanInput();
|
||||
|
||||
//hidKeysDown returns information about which buttons have been just pressed (and they weren't in the previous frame)
|
||||
u32 kDown = hidKeysDown();
|
||||
|
||||
if (kDown & KEY_START) break; // break in order to return to hbmenu
|
||||
|
||||
// Flush and swap framebuffers
|
||||
gfxFlushBuffers();
|
||||
gfxSwapBuffers();
|
||||
|
||||
//Wait for VBlank
|
||||
gspWaitForVBlank();
|
||||
}
|
||||
|
||||
// Exit services
|
||||
gfxExit();
|
||||
return 0;
|
||||
}
|
7
examples/graphics/printing/Makefile
Normal file
7
examples/graphics/printing/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
SUBDIRS:= `ls | egrep -v '^(CVS)$$'`
|
||||
all:
|
||||
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i || { exit 1;} fi; done;
|
||||
clean:
|
||||
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i clean || { exit 1;} fi; done;
|
||||
install:
|
||||
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i install || { exit 1;} fi; done;
|
@ -35,7 +35,7 @@ INCLUDES := include
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=softfp
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffast-math \
|
||||
@ -120,7 +120,7 @@ all: $(BUILD)
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
|
@ -17,17 +17,13 @@
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// Initialize services
|
||||
srvInit();
|
||||
aptInit();
|
||||
gfxInit();
|
||||
hidInit(NULL);
|
||||
gfxInitDefault();
|
||||
|
||||
//Initialize console on top screen. Using NULL as the second argument tells the console library to use the internal console structure as current one
|
||||
consoleInit(GFX_TOP, NULL);
|
||||
|
||||
//Move the cursor to row 15 and column 19 and then prints "Hello World!"
|
||||
//To move the cursor you have tu print "\x1b[r;cH", where r and c are respectively
|
||||
//Move the cursor to row 15 and column 19 and then prints "Hello World!"
|
||||
//To move the cursor you have to print "\x1b[r;cH", where r and c are respectively
|
||||
//the row and column where you want your cursor to move
|
||||
//The top screen has 30 rows and 50 columns
|
||||
//The bottom screen has 30 rows and 40 columns
|
||||
@ -54,10 +50,6 @@ int main(int argc, char **argv)
|
||||
gspWaitForVBlank();
|
||||
}
|
||||
|
||||
// Exit services
|
||||
gfxExit();
|
||||
hidExit();
|
||||
aptExit();
|
||||
srvExit();
|
||||
return 0;
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ INCLUDES := include
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=softfp
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffast-math \
|
||||
@ -120,7 +120,7 @@ all: $(BUILD)
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
|
@ -1,27 +1,18 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <3ds.h>
|
||||
|
||||
Result http_download(httpcContext *context)//This error handling needs updated with proper text printing once ctrulib itself supports that.
|
||||
{
|
||||
Result ret=0;
|
||||
u8* framebuf_top, *framebuf_bottom;
|
||||
u8* framebuf_top;
|
||||
u32 statuscode=0;
|
||||
u32 size=0, contentsize=0;
|
||||
u8 *buf;
|
||||
|
||||
framebuf_bottom = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL);
|
||||
memset(framebuf_bottom, 0x40, 240*320*3);
|
||||
gfxFlushBuffers();
|
||||
gfxSwapBuffers();
|
||||
|
||||
framebuf_bottom = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL);
|
||||
memset(framebuf_bottom, 0x40, 240*320*3);
|
||||
gfxFlushBuffers();
|
||||
gfxSwapBuffers();
|
||||
gspWaitForVBlank();
|
||||
|
||||
ret = httpcBeginRequest(context);
|
||||
if(ret!=0)return ret;
|
||||
|
||||
@ -33,23 +24,13 @@ Result http_download(httpcContext *context)//This error handling needs updated w
|
||||
ret=httpcGetDownloadSizeState(context, NULL, &contentsize);
|
||||
if(ret!=0)return ret;
|
||||
|
||||
printf("size: %"PRId32"\n",contentsize);
|
||||
gfxFlushBuffers();
|
||||
|
||||
buf = (u8*)malloc(contentsize);
|
||||
if(buf==NULL)return -1;
|
||||
memset(buf, 0, contentsize);
|
||||
|
||||
framebuf_bottom = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL);
|
||||
memset(framebuf_bottom, 0xc0, 240*320*3);
|
||||
gfxFlushBuffers();
|
||||
gfxSwapBuffers();
|
||||
|
||||
framebuf_bottom = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL);
|
||||
memset(framebuf_bottom, 0xc0, 240*320*3);
|
||||
gfxFlushBuffers();
|
||||
gfxSwapBuffers();
|
||||
gspWaitForVBlank();
|
||||
|
||||
framebuf_top = gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL);
|
||||
framebuf_bottom = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL);
|
||||
|
||||
ret = httpcDownloadData(context, buf, contentsize, NULL);
|
||||
if(ret!=0)
|
||||
@ -59,18 +40,15 @@ Result http_download(httpcContext *context)//This error handling needs updated w
|
||||
}
|
||||
|
||||
size = contentsize;
|
||||
if(size>(240*400*3))size = 240*400*3;
|
||||
if(size>(240*400*3*2))size = 240*400*3*2;
|
||||
|
||||
memset(framebuf_bottom, 0xff, 240*320*3);
|
||||
framebuf_top = gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL);
|
||||
memcpy(framebuf_top, buf, size);
|
||||
|
||||
gfxFlushBuffers();
|
||||
gfxSwapBuffers();
|
||||
|
||||
framebuf_top = gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL);
|
||||
framebuf_bottom = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL);
|
||||
|
||||
memset(framebuf_bottom, 0xff, 240*320*3);
|
||||
memcpy(framebuf_top, buf, size);
|
||||
|
||||
gfxFlushBuffers();
|
||||
@ -87,19 +65,26 @@ int main()
|
||||
Result ret=0;
|
||||
httpcContext context;
|
||||
|
||||
// Initialize services
|
||||
srvInit();
|
||||
aptInit();
|
||||
hidInit(NULL);
|
||||
gfxInit();
|
||||
//gfxSet3D(true); // uncomment if using stereoscopic 3D
|
||||
gfxInitDefault();
|
||||
httpcInit();
|
||||
|
||||
ret = httpcOpenContext(&context, "http://10.0.0.3/httpexample_rawimg.bin", 0);//Change this to your own URL.
|
||||
consoleInit(GFX_BOTTOM,NULL);
|
||||
|
||||
//Change this to your own URL.
|
||||
char *url = "http://devkitpro.org/misc/httpexample_rawimg.rgb";
|
||||
|
||||
printf("Downloading %s\n",url);
|
||||
gfxFlushBuffers();
|
||||
|
||||
ret = httpcOpenContext(&context, url , 0);
|
||||
printf("return from httpcOpenContext: %"PRId32"\n",ret);
|
||||
gfxFlushBuffers();
|
||||
|
||||
if(ret==0)
|
||||
{
|
||||
ret=http_download(&context);
|
||||
printf("return from http_download: %"PRId32"\n",ret);
|
||||
gfxFlushBuffers();
|
||||
httpcCloseContext(&context);
|
||||
}
|
||||
|
||||
@ -123,9 +108,6 @@ int main()
|
||||
// Exit services
|
||||
httpcExit();
|
||||
gfxExit();
|
||||
hidExit();
|
||||
aptExit();
|
||||
srvExit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
2
examples/mic/Makefile → examples/input/read-controls/Makefile
Normal file → Executable file
2
examples/mic/Makefile → examples/input/read-controls/Makefile
Normal file → Executable file
@ -35,7 +35,7 @@ INCLUDES := include
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=softfp
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffast-math \
|
105
examples/input/read-controls/source/main.c
Normal file
105
examples/input/read-controls/source/main.c
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
Circle Pad example made by Aurelio Mannara for ctrulib
|
||||
Please refer to https://github.com/smealum/ctrulib/blob/master/libctru/include/3ds/services/hid.h for more information
|
||||
This code was modified for the last time on: 12/13/2014 2:20 UTC+1
|
||||
|
||||
This wouldn't be possible without the amazing work done by:
|
||||
-Smealum
|
||||
-fincs
|
||||
-WinterMute
|
||||
-yellows8
|
||||
-plutoo
|
||||
-mtheall
|
||||
-Many others who worked on 3DS and I'm surely forgetting about
|
||||
*/
|
||||
|
||||
#include <3ds.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
//Matrix containing the name of each key. Useful for printing when a key is pressed
|
||||
char keysNames[32][32] = {
|
||||
"KEY_A", "KEY_B", "KEY_SELECT", "KEY_START",
|
||||
"KEY_DRIGHT", "KEY_DLEFT", "KEY_DUP", "KEY_DDOWN",
|
||||
"KEY_R", "KEY_L", "KEY_X", "KEY_Y",
|
||||
"", "", "KEY_ZL", "KEY_ZR",
|
||||
"", "", "", "",
|
||||
"KEY_TOUCH", "", "", "",
|
||||
"KEY_CSTICK_RIGHT", "KEY_CSTICK_LEFT", "KEY_CSTICK_UP", "KEY_CSTICK_DOWN",
|
||||
"KEY_CPAD_RIGHT", "KEY_CPAD_LEFT", "KEY_CPAD_UP", "KEY_CPAD_DOWN"
|
||||
};
|
||||
|
||||
// Initialize services
|
||||
gfxInitDefault();
|
||||
|
||||
//Initialize console on top screen. Using NULL as the second argument tells the console library to use the internal console structure as current one
|
||||
consoleInit(GFX_TOP, NULL);
|
||||
|
||||
u32 kDownOld = 0, kHeldOld = 0, kUpOld = 0; //In these variables there will be information about keys detected in the previous frame
|
||||
|
||||
printf("\x1b[0;0HPress Start to exit.");
|
||||
printf("\x1b[1;0HCirclePad position:");
|
||||
|
||||
// Main loop
|
||||
while (aptMainLoop())
|
||||
{
|
||||
//Scan all the inputs. This should be done once for each frame
|
||||
hidScanInput();
|
||||
|
||||
//hidKeysDown returns information about which buttons have been just pressed (and they weren't in the previous frame)
|
||||
u32 kDown = hidKeysDown();
|
||||
//hidKeysHeld returns information about which buttons have are held down in this frame
|
||||
u32 kHeld = hidKeysHeld();
|
||||
//hidKeysUp returns information about which buttons have been just released
|
||||
u32 kUp = hidKeysUp();
|
||||
|
||||
if (kDown & KEY_START) break; // break in order to return to hbmenu
|
||||
|
||||
//Do the keys printing only if keys have changed
|
||||
if (kDown != kDownOld || kHeld != kHeldOld || kUp != kUpOld)
|
||||
{
|
||||
//Clear console
|
||||
consoleClear();
|
||||
|
||||
//These two lines must be rewritten because we cleared the whole console
|
||||
printf("\x1b[0;0HPress Start to exit.");
|
||||
printf("\x1b[1;0HCirclePad position:");
|
||||
|
||||
printf("\x1b[3;0H"); //Move the cursor to the fourth row because on the third one we'll write the circle pad position
|
||||
|
||||
//Check if some of the keys are down, held or up
|
||||
int i;
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
if (kDown & BIT(i)) printf("%s down\n", keysNames[i]);
|
||||
if (kHeld & BIT(i)) printf("%s held\n", keysNames[i]);
|
||||
if (kUp & BIT(i)) printf("%s up\n", keysNames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//Set keys old values for the next frame
|
||||
kDownOld = kDown;
|
||||
kHeldOld = kHeld;
|
||||
kUpOld = kUp;
|
||||
|
||||
circlePosition pos;
|
||||
|
||||
//Read the CirclePad position
|
||||
hidCircleRead(&pos);
|
||||
|
||||
//Print the CirclePad position
|
||||
printf("\x1b[2;0H%04d; %04d", pos.dx, pos.dy);
|
||||
|
||||
// Flush and swap framebuffers
|
||||
gfxFlushBuffers();
|
||||
gfxSwapBuffers();
|
||||
|
||||
//Wait for VBlank
|
||||
gspWaitForVBlank();
|
||||
}
|
||||
|
||||
// Exit services
|
||||
gfxExit();
|
||||
return 0;
|
||||
}
|
@ -35,7 +35,7 @@ INCLUDES := include
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=softfp
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffast-math \
|
||||
@ -120,7 +120,7 @@ all: $(BUILD)
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
|
@ -4,11 +4,7 @@ int main()
|
||||
{
|
||||
u32 val, i;
|
||||
|
||||
// Initialize services
|
||||
srvInit();
|
||||
aptInit();
|
||||
hidInit(NULL);
|
||||
gfxInit();
|
||||
gfxInitDefault();
|
||||
//gfxSet3D(true); // uncomment if using stereoscopic 3D
|
||||
|
||||
val = 0x22447899;
|
||||
@ -42,9 +38,6 @@ int main()
|
||||
|
||||
// Exit services
|
||||
gfxExit();
|
||||
hidExit();
|
||||
aptExit();
|
||||
srvExit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ INCLUDES := include
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=softfp
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffast-math \
|
||||
@ -120,7 +120,7 @@ all: $(BUILD)
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
|
@ -106,13 +106,7 @@ void draw_startup()
|
||||
|
||||
int main()
|
||||
{
|
||||
// Initialize services
|
||||
srvInit();
|
||||
aptInit();
|
||||
hidInit(NULL);
|
||||
gfxInit();
|
||||
fsInit();
|
||||
sdmcInit();
|
||||
gfxInitDefault();
|
||||
//gfxSet3D(true); // uncomment if using stereoscopic 3D
|
||||
|
||||
memset(logstring, 0, 256);
|
||||
@ -143,13 +137,7 @@ int main()
|
||||
if(inaddr)linearFree(inaddr);
|
||||
if(outaddr)linearFree(outaddr);
|
||||
|
||||
// Exit services
|
||||
sdmcExit();
|
||||
fsExit();
|
||||
gfxExit();
|
||||
hidExit();
|
||||
aptExit();
|
||||
srvExit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ INCLUDES := include
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=softfp
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffast-math \
|
||||
@ -124,7 +124,7 @@ all: $(BUILD)
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
|
@ -11,11 +11,7 @@ int main()
|
||||
qtmHeadtrackingInfo qtminfo;
|
||||
u32 colors[4] = {0x0000FF, 0x00FF00, 0xFF0000, 0xFFFFFF};
|
||||
|
||||
// Initialize services
|
||||
srvInit();
|
||||
aptInit();
|
||||
hidInit(NULL);
|
||||
gfxInit();
|
||||
gfxInitDefault();
|
||||
//gfxSet3D(true); // uncomment if using stereoscopic 3D
|
||||
|
||||
qtmInit();
|
||||
@ -84,9 +80,6 @@ int main()
|
||||
// Exit services
|
||||
qtmExit();
|
||||
gfxExit();
|
||||
hidExit();
|
||||
aptExit();
|
||||
srvExit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ INCLUDES := include
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=softfp
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffast-math \
|
||||
@ -120,7 +120,7 @@ all: $(BUILD)
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
|
@ -45,7 +45,7 @@ void renderEffect()
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
|
||||
gfxInit(); //makes displaying to screen easier
|
||||
gfxInitDefault(); //makes displaying to screen easier
|
||||
|
||||
FILE *file = fopen("test.bin","rb");
|
||||
if (file == NULL) goto exit;
|
||||
|
7
examples/templates/Makefile
Normal file
7
examples/templates/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
SUBDIRS:= `ls | egrep -v '^(CVS)$$'`
|
||||
all:
|
||||
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i || { exit 1;} fi; done;
|
||||
clean:
|
||||
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i clean || { exit 1;} fi; done;
|
||||
install:
|
||||
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i install || { exit 1;} fi; done;
|
@ -35,7 +35,7 @@ INCLUDES := include
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=softfp
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffast-math \
|
||||
@ -124,7 +124,7 @@ all: $(BUILD)
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
|
@ -4,11 +4,7 @@
|
||||
|
||||
int main()
|
||||
{
|
||||
// Initialize services
|
||||
srvInit();
|
||||
aptInit();
|
||||
hidInit(NULL);
|
||||
gfxInit();
|
||||
gfxInitDefault();
|
||||
//gfxSet3D(true); // uncomment if using stereoscopic 3D
|
||||
|
||||
// Main loop
|
||||
@ -36,10 +32,6 @@ int main()
|
||||
gfxSwapBuffers();
|
||||
}
|
||||
|
||||
// Exit services
|
||||
gfxExit();
|
||||
hidExit();
|
||||
aptExit();
|
||||
srvExit();
|
||||
return 0;
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ INCLUDES := include
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=softfp
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||
|
||||
CFLAGS := -g -Wall -O2\
|
||||
$(ARCH)
|
||||
|
@ -9,7 +9,7 @@ endif
|
||||
include $(DEVKITARM)/base_rules
|
||||
|
||||
export LIBCTRU_MAJOR := 0
|
||||
export LIBCTRU_MINOR := 2
|
||||
export LIBCTRU_MINOR := 4
|
||||
export LIBCTRU_PATCH := 0
|
||||
|
||||
|
||||
@ -29,7 +29,8 @@ SOURCES := source \
|
||||
source/gpu \
|
||||
source/services \
|
||||
source/services/soc \
|
||||
source/util \
|
||||
source/util/rbtree \
|
||||
source/util/utf \
|
||||
source/system
|
||||
|
||||
DATA := data
|
||||
@ -38,7 +39,7 @@ INCLUDES := include
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=softfp
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffast-math \
|
||||
|
Binary file not shown.
@ -18,12 +18,13 @@ consoleInit()
|
||||
#define CONSOLE_H
|
||||
|
||||
#include <3ds/types.h>
|
||||
#include <3ds/gfx.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef bool(* ConsolePrint)(void* con, char c);
|
||||
typedef bool(* ConsolePrint)(void* con, int c);
|
||||
|
||||
//! a font struct for the console.
|
||||
typedef struct ConsoleFont
|
||||
|
@ -19,7 +19,8 @@ typedef enum
|
||||
}gfx3dSide_t;
|
||||
|
||||
//system stuff
|
||||
void gfxInit();
|
||||
void gfxInitDefault();
|
||||
void gfxInit(GSP_FramebufferFormats topFormat, GSP_FramebufferFormats bottomFormat, bool vrambuffers);
|
||||
void gfxExit();
|
||||
|
||||
//control stuff
|
||||
|
@ -1,30 +1,106 @@
|
||||
#pragma once
|
||||
#include <3ds/types.h>
|
||||
|
||||
#define CSND_NUM_CHANNELS 32
|
||||
#define CSND_SHAREDMEM_DEFAULT 0x10004000
|
||||
|
||||
typedef enum{
|
||||
CSND_LOOP_DISABLE,
|
||||
CSND_LOOP_ENABLE
|
||||
} CSND_LOOPING;
|
||||
#define CSND_TIMER(n) (0x3FEC3FC / ((u32)(n)))
|
||||
|
||||
typedef enum{
|
||||
CSND_ENCODING_PCM8,
|
||||
CSND_ENCODING_PCM16,
|
||||
CSND_ENCODING_IMA_ADPCM,
|
||||
CSND_ENCODING_PSG//"3 = PSG, similar to DS?"
|
||||
} CSND_ENCODING;
|
||||
enum
|
||||
{
|
||||
CSND_ENCODING_PCM8 = 0,
|
||||
CSND_ENCODING_PCM16,
|
||||
CSND_ENCODING_ADPCM, // IMA-ADPCM
|
||||
CSND_ENCODING_PSG, // Similar to DS?
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CSND_LOOPMODE_MANUAL = 0,
|
||||
CSND_LOOPMODE_NORMAL,
|
||||
CSND_LOOPMODE_ONESHOT,
|
||||
CSND_LOOPMODE_NORELOAD,
|
||||
};
|
||||
|
||||
//See here regarding CSND shared-mem commands, etc: http://3dbrew.org/wiki/CSND_Shared_Memory
|
||||
#define SOUND_CHANNEL(n) ((u32)(n) & 0x1F)
|
||||
#define SOUND_FORMAT(n) ((u32)(n) << 12)
|
||||
#define SOUND_LOOPMODE(n) ((u32)(n) << 10)
|
||||
|
||||
Result CSND_initialize(u32* sharedMem);
|
||||
Result CSND_shutdown();
|
||||
enum
|
||||
{
|
||||
SOUND_LINEAR_INTERP = BIT(6),
|
||||
SOUND_REPEAT = SOUND_LOOPMODE(CSND_LOOPMODE_NORMAL),
|
||||
SOUND_ONE_SHOT = SOUND_LOOPMODE(CSND_LOOPMODE_ONESHOT),
|
||||
SOUND_FORMAT_8BIT = SOUND_FORMAT(CSND_ENCODING_PCM8),
|
||||
SOUND_FORMAT_16BIT = SOUND_FORMAT(CSND_ENCODING_PCM16),
|
||||
SOUND_FORMAT_ADPCM = SOUND_FORMAT(CSND_ENCODING_ADPCM),
|
||||
SOUND_FORMAT_PSG = SOUND_FORMAT(CSND_ENCODING_PSG),
|
||||
SOUND_ENABLE = BIT(14),
|
||||
};
|
||||
|
||||
Result CSND_playsound(u32 channel, u32 looping, u32 encoding, u32 samplerate, u32 *vaddr0, u32 *vaddr1, u32 totalbytesize, u32 unk0, u32 unk1);
|
||||
void CSND_setchannel_playbackstate(u32 channel, u32 value);
|
||||
void CSND_sharedmemtype0_cmd0(u32 channel, u32 value);
|
||||
void CSND_writesharedmem_cmdtype0(u16 cmdid, u8 *cmdparams);
|
||||
Result CSND_sharedmemtype0_cmdupdatestate(int waitdone);
|
||||
// Duty cycles for a PSG channel
|
||||
enum
|
||||
{
|
||||
DutyCycle_0 = 7, /*!< 0.0% duty cycle */
|
||||
DutyCycle_12 = 0, /*!< 12.5% duty cycle */
|
||||
DutyCycle_25 = 1, /*!< 25.0% duty cycle */
|
||||
DutyCycle_37 = 2, /*!< 37.5% duty cycle */
|
||||
DutyCycle_50 = 3, /*!< 50.0% duty cycle */
|
||||
DutyCycle_62 = 4, /*!< 62.5% duty cycle */
|
||||
DutyCycle_75 = 5, /*!< 75.0% duty cycle */
|
||||
DutyCycle_87 = 6 /*!< 87.5% duty cycle */
|
||||
};
|
||||
|
||||
Result CSND_getchannelstate(u32 entryindex, u32 *out);
|
||||
Result CSND_getchannelstate_isplaying(u32 entryindex, u8 *status);
|
||||
typedef union
|
||||
{
|
||||
u32 value[3];
|
||||
struct
|
||||
{
|
||||
u8 active;
|
||||
u8 _pad1;
|
||||
u16 _pad2;
|
||||
s16 adpcmSample;
|
||||
u8 adpcmIndex;
|
||||
u8 _pad3;
|
||||
u32 samplePAddr;
|
||||
};
|
||||
} CSND_ChnInfo;
|
||||
|
||||
// See here regarding CSND shared-mem commands, etc: http://3dbrew.org/wiki/CSND_Shared_Memory
|
||||
|
||||
extern vu32* csndSharedMem;
|
||||
extern u32 csndSharedMemSize;
|
||||
extern u32 csndChannels; // Bitmask of channels that are allowed for usage
|
||||
|
||||
Result CSND_AcquireCapUnit(u32* capUnit);
|
||||
Result CSND_ReleaseCapUnit(u32 capUnit);
|
||||
|
||||
Result csndInit(void);
|
||||
Result csndExit(void);
|
||||
|
||||
void csndWriteCmd(int cmdid, u8 *cmdparams);
|
||||
Result csndExecCmds(bool waitDone);
|
||||
|
||||
void CSND_SetPlayStateR(u32 channel, u32 value);
|
||||
void CSND_SetPlayState(u32 channel, u32 value);
|
||||
void CSND_SetBlock(u32 channel, int block, u32 physaddr, u32 size);
|
||||
void CSND_SetVol(u32 channel, u16 left, u16 right);
|
||||
void CSND_SetTimer(u32 channel, u32 timer);
|
||||
void CSND_SetDuty(u32 channel, u32 duty);
|
||||
void CSND_SetAdpcmState(u32 channel, int block, int sample, int index);
|
||||
void CSND_SetAdpcmReload(u32 channel, bool reload);
|
||||
void CSND_SetChnRegs(u32 flags, u32 physaddr0, u32 physaddr1, u32 totalbytesize);
|
||||
|
||||
void CSND_CapEnable(u32 capUnit, bool enable);
|
||||
void CSND_CapSetBit(u32 capUnit, int bit, bool state); // Sets bit0..2 in the CNT register, purpose currently unknown
|
||||
void CSND_CapSetTimer(u32 capUnit, u32 timer);
|
||||
void CSND_CapSetBuffer(u32 capUnit, u32 paddr, u32 size);
|
||||
|
||||
Result CSND_UpdateInfo(bool waitDone);
|
||||
|
||||
Result csndPlaySound(int chn, u32 flags, u32 sampleRate, void* data0, void* data1, u32 size);
|
||||
|
||||
CSND_ChnInfo* csndGetChnInfo(u32 channel); // Requires previous CSND_UpdateInfo()
|
||||
|
||||
Result csndGetState(u32 channel, CSND_ChnInfo* out);
|
||||
Result csndIsPlaying(u32 channel, u8* status);
|
||||
|
@ -1,11 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
Result SOC_Initialize(u32 *context_addr, u32 context_size);//Example context_size: 0x48000. The specified context buffer can no longer be accessed by the process which called this function, since the userland permissions for this block are set to no-access.
|
||||
Result SOC_Shutdown();
|
||||
int SOC_GetErrno();
|
||||
|
||||
Result SOC_Shutdown(void);
|
||||
int SOC_GetErrno(void);
|
||||
|
||||
/* this is supposed to be in unistd.h but newlib only puts it for cygwin */
|
||||
long gethostid(void);
|
||||
|
@ -39,6 +39,12 @@ typedef volatile s64 vs64;
|
||||
|
||||
typedef u32 Handle;
|
||||
typedef s32 Result;
|
||||
typedef void (*ThreadFunc)(u32);
|
||||
typedef void (*ThreadFunc)(void *);
|
||||
|
||||
#define BIT(n) (1U<<(n))
|
||||
|
||||
//! aligns a struct (and other types?) to m, making sure that the size of the struct is a multiple of m.
|
||||
#define ALIGN(m) __attribute__((aligned (m)))
|
||||
|
||||
//! packs a struct (and other types?) so it won't include padding bytes.
|
||||
#define PACKED __attribute__ ((packed))
|
||||
|
108
libctru/include/3ds/util/utf.h
Normal file
108
libctru/include/3ds/util/utf.h
Normal file
@ -0,0 +1,108 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/*! Convert a UTF-8 sequence into a UTF-32 codepoint
|
||||
*
|
||||
* @param[out] out Output codepoint
|
||||
* @param[in] in Input sequence
|
||||
*
|
||||
* @returns number of input code units consumed
|
||||
* @returns -1 for error
|
||||
*/
|
||||
ssize_t decode_utf8 (uint32_t *out, const uint8_t *in);
|
||||
|
||||
/*! Convert a UTF-16 sequence into a UTF-32 codepoint
|
||||
*
|
||||
* @param[out] out Output codepoint
|
||||
* @param[in] in Input sequence
|
||||
*
|
||||
* @returns number of input code units consumed
|
||||
* @returns -1 for error
|
||||
*/
|
||||
ssize_t decode_utf16(uint32_t *out, const uint16_t *in);
|
||||
|
||||
/*! Convert a UTF-32 codepoint into a UTF-8 sequence
|
||||
*
|
||||
* @param[out] out Output sequence
|
||||
* @param[in] in Input codepoint
|
||||
*
|
||||
* @returns number of output code units produced
|
||||
* @returns -1 for error
|
||||
*
|
||||
* @note \a out must be able to store 4 code units
|
||||
*/
|
||||
ssize_t encode_utf8 (uint8_t *out, uint32_t in);
|
||||
|
||||
/*! Convert a UTF-32 codepoint into a UTF-16 sequence
|
||||
*
|
||||
* @param[out] out Output sequence
|
||||
* @param[in] in Input codepoint
|
||||
*
|
||||
* @returns number of output code units produced
|
||||
* @returns -1 for error
|
||||
*
|
||||
* @note \a out must be able to store 2 code units
|
||||
*/
|
||||
ssize_t encode_utf16(uint16_t *out, uint32_t in);
|
||||
|
||||
/*! Convert a UTF-8 sequence into a UTF-16 sequence
|
||||
*
|
||||
* @param[out] out Output sequence
|
||||
* @param[in] in Input sequence
|
||||
*
|
||||
* @returns number of output code units produced
|
||||
* @returns -1 for error
|
||||
*/
|
||||
size_t utf8_to_utf16(uint16_t *out, const uint8_t *in, size_t len);
|
||||
|
||||
/*! Convert a UTF-8 sequence into a UTF-32 sequence
|
||||
*
|
||||
* @param[out] out Output sequence
|
||||
* @param[in] in Input sequence
|
||||
*
|
||||
* @returns number of output code units produced
|
||||
* @returns -1 for error
|
||||
*/
|
||||
size_t utf8_to_utf32(uint32_t *out, const uint8_t *in, size_t len);
|
||||
|
||||
/*! Convert a UTF-16 sequence into a UTF-8 sequence
|
||||
*
|
||||
* @param[out] out Output sequence
|
||||
* @param[in] in Input sequence
|
||||
*
|
||||
* @returns number of output code units produced
|
||||
* @returns -1 for error
|
||||
*/
|
||||
size_t utf16_to_utf8(uint8_t *out, const uint16_t *in, size_t len);
|
||||
|
||||
/*! Convert a UTF-16 sequence into a UTF-32 sequence
|
||||
*
|
||||
* @param[out] out Output sequence
|
||||
* @param[in] in Input sequence
|
||||
*
|
||||
* @returns number of output code units produced
|
||||
* @returns -1 for error
|
||||
*/
|
||||
size_t utf16_to_utf32(uint32_t *out, const uint16_t *in, size_t len);
|
||||
|
||||
/*! Convert a UTF-32 sequence into a UTF-8 sequence
|
||||
*
|
||||
* @param[out] out Output sequence
|
||||
* @param[in] in Input sequence
|
||||
*
|
||||
* @returns number of output code units produced
|
||||
* @returns -1 for error
|
||||
*/
|
||||
size_t utf32_to_utf8(uint8_t *out, const uint32_t *in, size_t len);
|
||||
|
||||
/*! Convert a UTF-32 sequence into a UTF-16 sequence
|
||||
*
|
||||
* @param[out] out Output sequence
|
||||
* @param[in] in Input sequence
|
||||
*
|
||||
* @returns number of output code units produced
|
||||
* @returns -1 for error
|
||||
*/
|
||||
size_t utf32_to_utf16(uint16_t *out, const uint32_t *in, size_t len);
|
@ -22,6 +22,8 @@ extern "C" {
|
||||
|
||||
extern int h_errno;
|
||||
struct hostent* gethostbyname(const char *name);
|
||||
void herror(const char *s);
|
||||
const char* hstrerror(int err);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
2586
libctru/libctru.cfg
Normal file
2586
libctru/libctru.cfg
Normal file
File diff suppressed because it is too large
Load Diff
2
libctru/libctru.cppcheck
Normal file
2
libctru/libctru.cppcheck
Normal file
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="1"/>
|
@ -43,7 +43,7 @@ PrintConsole defaultConsole =
|
||||
{
|
||||
(u8*)default_font_bin, //font gfx
|
||||
0, //first ascii character in the set
|
||||
128 //number of characters in the font set
|
||||
256 //number of characters in the font set
|
||||
},
|
||||
(u16*)NULL,
|
||||
0,0, //cursorX cursorY
|
||||
@ -68,7 +68,7 @@ PrintConsole* currentConsole = ¤tCopy;
|
||||
|
||||
PrintConsole* consoleGetDefault(void){return &defaultConsole;}
|
||||
|
||||
void consolePrintChar(char c);
|
||||
void consolePrintChar(int c);
|
||||
void consoleDrawChar(int c);
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
@ -121,6 +121,7 @@ static void consoleCls(char mode) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
gfxFlushBuffers();
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
static void consoleClearLine(char mode) {
|
||||
@ -173,6 +174,7 @@ static void consoleClearLine(char mode) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
gfxFlushBuffers();
|
||||
}
|
||||
|
||||
|
||||
@ -605,6 +607,7 @@ static void newRow() {
|
||||
}
|
||||
|
||||
consoleClearLine('2');
|
||||
gfxFlushBuffers();
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
@ -672,7 +675,7 @@ void consoleDrawChar(int c) {
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
void consolePrintChar(char c) {
|
||||
void consolePrintChar(int c) {
|
||||
//---------------------------------------------------------------------------------
|
||||
if (c==0) return;
|
||||
|
||||
@ -718,6 +721,7 @@ void consolePrintChar(char c) {
|
||||
newRow();
|
||||
case 13:
|
||||
currentConsole->cursorX = 0;
|
||||
gfxFlushBuffers();
|
||||
break;
|
||||
default:
|
||||
consoleDrawChar(c);
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <3ds/gfx.h>
|
||||
#include <3ds/svc.h>
|
||||
#include <3ds/linear.h>
|
||||
#include <3ds/vram.h>
|
||||
|
||||
GSP_FramebufferInfo topFramebufferInfo, bottomFramebufferInfo;
|
||||
|
||||
@ -96,8 +97,23 @@ void gfxWriteFramebufferInfo(gfxScreen_t screen)
|
||||
framebufferInfoHeader[0x1]=1;
|
||||
}
|
||||
|
||||
void gfxInit()
|
||||
void (*screenFree)(void *) = NULL;
|
||||
|
||||
void gfxInit(GSP_FramebufferFormats topFormat, GSP_FramebufferFormats bottomFormat, bool vrambuffers)
|
||||
{
|
||||
void *(*screenAlloc)(size_t);
|
||||
|
||||
if (vrambuffers)
|
||||
{
|
||||
screenAlloc=vramAlloc;
|
||||
screenFree=vramFree;
|
||||
|
||||
} else {
|
||||
|
||||
screenAlloc=linearAlloc;
|
||||
screenFree=linearFree;
|
||||
}
|
||||
|
||||
gspInit();
|
||||
|
||||
gfxSharedMemory=(u8*)0x10002000;
|
||||
@ -117,15 +133,22 @@ void gfxInit()
|
||||
// if 3d enabled :
|
||||
// topright1 0x000FD200-0x00143700
|
||||
// topright2 0x00143700-0x00189C00
|
||||
u32 topSize = 400 * 240 * __get_bytes_per_pixel(topFormat);
|
||||
u32 bottomSize = 320 * 240 * __get_bytes_per_pixel(bottomFormat);
|
||||
|
||||
gfxTopLeftFramebuffers[0]=screenAlloc(topSize);
|
||||
gfxTopLeftFramebuffers[1]=screenAlloc(topSize);
|
||||
gfxBottomFramebuffers[0]=screenAlloc(bottomSize);
|
||||
gfxBottomFramebuffers[1]=screenAlloc(bottomSize);
|
||||
gfxTopRightFramebuffers[0]=screenAlloc(topSize);
|
||||
gfxTopRightFramebuffers[1]=screenAlloc(topSize);
|
||||
|
||||
gfxTopLeftFramebuffers[0]=linearAlloc(0x46500);
|
||||
gfxTopLeftFramebuffers[1]=linearAlloc(0x46500);
|
||||
gfxBottomFramebuffers[0]=linearAlloc(0x38400);
|
||||
gfxBottomFramebuffers[1]=linearAlloc(0x38400);
|
||||
gfxTopRightFramebuffers[0]=linearAlloc(0x46500);
|
||||
gfxTopRightFramebuffers[1]=linearAlloc(0x46500);
|
||||
enable3d=false;
|
||||
|
||||
//set requested modes
|
||||
gfxSetScreenFormat(GFX_TOP,topFormat);
|
||||
gfxSetScreenFormat(GFX_BOTTOM,bottomFormat);
|
||||
|
||||
//initialize framebuffer info structures
|
||||
gfxSetFramebufferInfo(GFX_TOP, 0);
|
||||
gfxSetFramebufferInfo(GFX_BOTTOM, 0);
|
||||
@ -143,18 +166,24 @@ void gfxInit()
|
||||
GSPGPU_SetLcdForceBlack(NULL, 0x0);
|
||||
}
|
||||
|
||||
void gfxInitDefault() {
|
||||
gfxInit(GSP_BGR8_OES,GSP_BGR8_OES,false);
|
||||
}
|
||||
|
||||
void gfxExit()
|
||||
{
|
||||
if (screenFree == NULL ) return;
|
||||
|
||||
// Exit event handler
|
||||
gspExitEventHandler();
|
||||
|
||||
// Free framebuffers
|
||||
linearFree(gfxTopRightFramebuffers[1]);
|
||||
linearFree(gfxTopRightFramebuffers[0]);
|
||||
linearFree(gfxBottomFramebuffers[1]);
|
||||
linearFree(gfxBottomFramebuffers[0]);
|
||||
linearFree(gfxTopLeftFramebuffers[1]);
|
||||
linearFree(gfxTopLeftFramebuffers[0]);
|
||||
screenFree(gfxTopRightFramebuffers[1]);
|
||||
screenFree(gfxTopRightFramebuffers[0]);
|
||||
screenFree(gfxBottomFramebuffers[1]);
|
||||
screenFree(gfxBottomFramebuffers[0]);
|
||||
screenFree(gfxTopLeftFramebuffers[1]);
|
||||
screenFree(gfxTopLeftFramebuffers[0]);
|
||||
|
||||
//unmap GSP shared mem
|
||||
svcUnmapMemoryBlock(gspSharedMemHandle, 0x10002000);
|
||||
@ -167,6 +196,8 @@ void gfxExit()
|
||||
GSPGPU_ReleaseRight(NULL);
|
||||
|
||||
gspExit();
|
||||
|
||||
screenFree = NULL;
|
||||
}
|
||||
|
||||
u8* gfxGetFramebuffer(gfxScreen_t screen, gfx3dSide_t side, u16* width, u16* height)
|
||||
@ -185,9 +216,12 @@ u8* gfxGetFramebuffer(gfxScreen_t screen, gfx3dSide_t side, u16* width, u16* hei
|
||||
|
||||
void gfxFlushBuffers()
|
||||
{
|
||||
GSPGPU_FlushDataCache(NULL, gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), 0x46500);
|
||||
if(enable3d)GSPGPU_FlushDataCache(NULL, gfxGetFramebuffer(GFX_TOP, GFX_RIGHT, NULL, NULL), 0x46500);
|
||||
GSPGPU_FlushDataCache(NULL, gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL), 0x38400);
|
||||
u32 topSize = 400 * 240 * __get_bytes_per_pixel(gfxGetScreenFormat(GFX_TOP));
|
||||
u32 bottomSize = 320 * 240 * __get_bytes_per_pixel(gfxGetScreenFormat(GFX_BOTTOM));
|
||||
|
||||
GSPGPU_FlushDataCache(NULL, gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), topSize);
|
||||
if(enable3d)GSPGPU_FlushDataCache(NULL, gfxGetFramebuffer(GFX_TOP, GFX_RIGHT, NULL, NULL), topSize);
|
||||
GSPGPU_FlushDataCache(NULL, gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL), bottomSize);
|
||||
}
|
||||
|
||||
void gfxSwapBuffers()
|
||||
|
@ -1,15 +1,17 @@
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/dirent.h>
|
||||
#include <sys/iosupport.h>
|
||||
#include <sys/param.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <3ds/types.h>
|
||||
#include <3ds/sdmc.h>
|
||||
#include <3ds/services/fs.h>
|
||||
|
||||
#include <3ds/util/utf.h>
|
||||
|
||||
|
||||
/*! @internal
|
||||
@ -19,6 +21,8 @@
|
||||
* SDMC Device
|
||||
*/
|
||||
|
||||
static int sdmc_translate_error(Result error);
|
||||
|
||||
static int sdmc_open(struct _reent *r, void *fileStruct, const char *path, int flags, int mode);
|
||||
static int sdmc_close(struct _reent *r, int fd);
|
||||
static ssize_t sdmc_write(struct _reent *r, int fd, const char *ptr, size_t len);
|
||||
@ -40,6 +44,7 @@ static int sdmc_ftruncate(struct _reent *r, int fd, off_t len);
|
||||
static int sdmc_fsync(struct _reent *r, int fd);
|
||||
static int sdmc_chmod(struct _reent *r, const char *path, mode_t mode);
|
||||
static int sdmc_fchmod(struct _reent *r, int fd, mode_t mode);
|
||||
static int sdmc_rmdir(struct _reent *r, const char *name);
|
||||
|
||||
/*! @cond INTERNAL */
|
||||
|
||||
@ -87,6 +92,7 @@ sdmc_devoptab =
|
||||
.deviceData = NULL,
|
||||
.chmod_r = sdmc_chmod,
|
||||
.fchmod_r = sdmc_fchmod,
|
||||
.rmdir_r = sdmc_rmdir,
|
||||
};
|
||||
|
||||
/*! SDMC archive handle */
|
||||
@ -103,28 +109,106 @@ static FS_archive sdmcArchive =
|
||||
|
||||
/*! @endcond */
|
||||
|
||||
static char __cwd[PATH_MAX+1] = "/";
|
||||
static char __fixedpath[PATH_MAX+1];
|
||||
static char __cwd[PATH_MAX+1] = "/";
|
||||
static char __fixedpath[PATH_MAX+1];
|
||||
static uint16_t __utf16path[PATH_MAX+1];
|
||||
|
||||
static const char *sdmc_fixpath(const char *path)
|
||||
static const char*
|
||||
sdmc_fixpath(struct _reent *r,
|
||||
const char *path)
|
||||
{
|
||||
size_t units;
|
||||
uint32_t code;
|
||||
const uint8_t *p = (const uint8_t*)path;
|
||||
|
||||
// Move the path pointer to the start of the actual path
|
||||
if (strchr (path, ':') != NULL)
|
||||
do
|
||||
{
|
||||
path = strchr (path, ':') + 1;
|
||||
units = decode_utf8(&code, p);
|
||||
if(units == (size_t)-1)
|
||||
{
|
||||
r->_errno = EILSEQ;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p += units;
|
||||
} while(code != ':' && code != 0);
|
||||
|
||||
// We found a colon; p points to the actual path
|
||||
if(code == ':')
|
||||
path = (const char*)p;
|
||||
|
||||
// Make sure there are no more colons and that the
|
||||
// remainder of the filename is valid UTF-8
|
||||
p = (const uint8_t*)path;
|
||||
do
|
||||
{
|
||||
units = decode_utf8(&code, p);
|
||||
if(units == (size_t)-1)
|
||||
{
|
||||
r->_errno = EILSEQ;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(code == ':')
|
||||
{
|
||||
r->_errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p += units;
|
||||
} while(code != 0);
|
||||
|
||||
if(path[0] == '/')
|
||||
strncpy(__fixedpath, path, PATH_MAX+1);
|
||||
else
|
||||
{
|
||||
strncpy(__fixedpath, __cwd, PATH_MAX+1);
|
||||
strncat(__fixedpath, path, PATH_MAX+1);
|
||||
}
|
||||
|
||||
if (strchr (path, ':') != NULL) return NULL;
|
||||
|
||||
|
||||
if (path[0]=='/') return path;
|
||||
|
||||
strncpy(__fixedpath,__cwd,PATH_MAX);
|
||||
strncat(__fixedpath,path,PATH_MAX);
|
||||
__fixedpath[PATH_MAX] = 0;
|
||||
if(__fixedpath[PATH_MAX] != 0)
|
||||
{
|
||||
__fixedpath[PATH_MAX] = 0;
|
||||
r->_errno = ENAMETOOLONG;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return __fixedpath;
|
||||
}
|
||||
|
||||
static const FS_path
|
||||
sdmc_utf16path(struct _reent *r,
|
||||
const char *path)
|
||||
{
|
||||
size_t units;
|
||||
FS_path fspath;
|
||||
|
||||
fspath.data = NULL;
|
||||
|
||||
if(sdmc_fixpath(r, path) == NULL)
|
||||
return fspath;
|
||||
|
||||
units = utf8_to_utf16(__utf16path, (const uint8_t*)__fixedpath, PATH_MAX+1);
|
||||
if(units == (size_t)-1)
|
||||
{
|
||||
r->_errno = EILSEQ;
|
||||
return fspath;
|
||||
}
|
||||
|
||||
if(__utf16path[PATH_MAX] != 0)
|
||||
{
|
||||
r->_errno = ENAMETOOLONG;
|
||||
return fspath;
|
||||
}
|
||||
|
||||
__utf16path[units] = 0;
|
||||
|
||||
fspath.type = PATH_WCHAR;
|
||||
fspath.size = (units+1)*sizeof(uint16_t);
|
||||
fspath.data = (const u8*)__utf16path;
|
||||
|
||||
return fspath;
|
||||
}
|
||||
|
||||
extern int __system_argc;
|
||||
@ -135,29 +219,56 @@ static bool sdmcInitialised = false;
|
||||
/*! Initialize SDMC device */
|
||||
Result sdmcInit(void)
|
||||
{
|
||||
Result rc = 0;
|
||||
size_t units;
|
||||
uint32_t code;
|
||||
char *p;
|
||||
Result rc = 0;
|
||||
|
||||
if (sdmcInitialised) return rc;
|
||||
if(sdmcInitialised)
|
||||
return rc;
|
||||
|
||||
rc = FSUSER_OpenArchive(NULL, &sdmcArchive);
|
||||
|
||||
|
||||
if(rc == 0)
|
||||
{
|
||||
|
||||
int dev = AddDevice(&sdmc_devoptab);
|
||||
|
||||
if (dev != -1) {
|
||||
if(dev != -1)
|
||||
{
|
||||
setDefaultDevice(dev);
|
||||
if (__system_argc != 0 && __system_argv[0] != NULL)
|
||||
if(__system_argc != 0 && __system_argv[0] != NULL)
|
||||
{
|
||||
if (FindDevice(__system_argv[0]) == dev)
|
||||
if(FindDevice(__system_argv[0]) == dev)
|
||||
{
|
||||
strncpy(__fixedpath,__system_argv[0],PATH_MAX);
|
||||
char *last_slash = strrchr(__fixedpath,'/');
|
||||
if (last_slash != NULL) {
|
||||
last_slash[0] = 0;
|
||||
chdir(__fixedpath);
|
||||
if(__fixedpath[PATH_MAX] != 0)
|
||||
{
|
||||
__fixedpath[PATH_MAX] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *last_slash = NULL;
|
||||
p = __fixedpath;
|
||||
do
|
||||
{
|
||||
units = decode_utf8(&code, (const uint8_t*)p);
|
||||
if(units == (size_t)-1)
|
||||
{
|
||||
last_slash = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if(code == '/')
|
||||
last_slash = p;
|
||||
|
||||
p += units;
|
||||
} while(code != 0);
|
||||
|
||||
if(last_slash != NULL)
|
||||
{
|
||||
last_slash[0] = 0;
|
||||
chdir(__fixedpath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -174,13 +285,14 @@ Result sdmcExit(void)
|
||||
{
|
||||
Result rc = 0;
|
||||
|
||||
if (!sdmcInitialised) return rc;
|
||||
if(!sdmcInitialised) return rc;
|
||||
|
||||
rc = FSUSER_CloseArchive(NULL, &sdmcArchive);
|
||||
if(rc == 0)
|
||||
{
|
||||
RemoveDevice("sdmc");
|
||||
|
||||
sdmcInitialised = false;
|
||||
sdmcInitialised = false;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -207,15 +319,11 @@ sdmc_open(struct _reent *r,
|
||||
Result rc;
|
||||
u32 sdmc_flags = 0;
|
||||
u32 attributes = FS_ATTRIBUTE_NONE;
|
||||
const char *pathptr = NULL;
|
||||
FS_path fs_path;
|
||||
|
||||
pathptr = sdmc_fixpath(path);
|
||||
|
||||
if(pathptr==NULL)
|
||||
{
|
||||
r->_errno=EINVAL;
|
||||
fs_path = sdmc_utf16path(r, path);
|
||||
if(fs_path.data == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* get pointer to our data */
|
||||
sdmc_file_t *file = (sdmc_file_t*)fileStruct;
|
||||
@ -256,14 +364,10 @@ sdmc_open(struct _reent *r,
|
||||
/* Test O_EXCL. */
|
||||
if((flags & O_CREAT) && (flags & O_EXCL))
|
||||
{
|
||||
rc = FSUSER_CreateFile(NULL, sdmcArchive, FS_makePath(PATH_CHAR, pathptr), 0);
|
||||
rc = FSUSER_CreateFile(NULL, sdmcArchive, fs_path, 0);
|
||||
if(rc != 0)
|
||||
{
|
||||
r->_errno = rc;
|
||||
if(rc == 0x82044BE)
|
||||
r->_errno = EEXIST;
|
||||
if(rc == 0x86044D2)
|
||||
r->_errno = ENOSPC;
|
||||
r->_errno = sdmc_translate_error(rc);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -273,7 +377,7 @@ sdmc_open(struct _reent *r,
|
||||
attributes |= FS_ATTRIBUTE_READONLY;*/
|
||||
|
||||
/* open the file */
|
||||
rc = FSUSER_OpenFile(NULL, &fd, sdmcArchive, FS_makePath(PATH_CHAR, pathptr),
|
||||
rc = FSUSER_OpenFile(NULL, &fd, sdmcArchive, fs_path,
|
||||
sdmc_flags, attributes);
|
||||
if(rc == 0)
|
||||
{
|
||||
@ -283,17 +387,18 @@ sdmc_open(struct _reent *r,
|
||||
if(rc != 0)
|
||||
{
|
||||
FSFILE_Close(fd);
|
||||
r->_errno = rc;
|
||||
r->_errno = sdmc_translate_error(rc);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
file->fd = fd;
|
||||
file->flags = (flags & (O_ACCMODE|O_APPEND|O_SYNC));
|
||||
file->offset = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r->_errno = rc;
|
||||
r->_errno = sdmc_translate_error(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -318,7 +423,7 @@ sdmc_close(struct _reent *r,
|
||||
if(rc == 0)
|
||||
return 0;
|
||||
|
||||
r->_errno = rc;
|
||||
r->_errno = sdmc_translate_error(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -339,9 +444,8 @@ sdmc_write(struct _reent *r,
|
||||
size_t len)
|
||||
{
|
||||
Result rc;
|
||||
u32 bytes;
|
||||
u32 bytes, bytesWritten = 0;
|
||||
u32 sync = 0;
|
||||
u64 offset;
|
||||
|
||||
/* get pointer to our data */
|
||||
sdmc_file_t *file = (sdmc_file_t*)fd;
|
||||
@ -355,38 +459,52 @@ sdmc_write(struct _reent *r,
|
||||
|
||||
/* check if this is synchronous or not */
|
||||
if(file->flags & O_SYNC)
|
||||
sync = 0x10001;
|
||||
sync = FS_WRITE_FLUSH;
|
||||
|
||||
/* initialize offset */
|
||||
offset = file->offset;
|
||||
if(file->flags & O_APPEND)
|
||||
{
|
||||
/* append means write from the end of the file */
|
||||
rc = FSFILE_GetSize(file->fd, &offset);
|
||||
rc = FSFILE_GetSize(file->fd, &file->offset);
|
||||
if(rc != 0)
|
||||
{
|
||||
r->_errno = rc;
|
||||
r->_errno = sdmc_translate_error(rc);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Copy to internal buffer and write in chunks.
|
||||
* You cannot write from read-only memory.
|
||||
/* Copy to internal buffer and write in chunks.
|
||||
* You cannot write from read-only memory.
|
||||
*/
|
||||
|
||||
/* write the data */
|
||||
rc = FSFILE_Write(file->fd, &bytes, offset, (u32*)ptr, (u32)len, sync);
|
||||
if(rc == 0)
|
||||
static char tmp_buffer[8192];
|
||||
while(len > 0)
|
||||
{
|
||||
/* update current file offset; if O_APPEND, this moves it to the
|
||||
* new end-of-file
|
||||
*/
|
||||
file->offset = offset + bytes;
|
||||
return (ssize_t)bytes;
|
||||
size_t toWrite = len;
|
||||
if(toWrite > sizeof(tmp_buffer))
|
||||
toWrite = sizeof(tmp_buffer);
|
||||
|
||||
/* copy to internal buffer */
|
||||
memcpy(tmp_buffer, ptr, toWrite);
|
||||
|
||||
/* write the data */
|
||||
rc = FSFILE_Write(file->fd, &bytes, file->offset,
|
||||
(u32*)tmp_buffer, (u32)toWrite, sync);
|
||||
if(rc != 0)
|
||||
{
|
||||
/* return partial transfer */
|
||||
if(bytesWritten > 0)
|
||||
return bytesWritten;
|
||||
|
||||
r->_errno = sdmc_translate_error(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
file->offset += bytes;
|
||||
bytesWritten += bytes;
|
||||
ptr += bytes;
|
||||
len -= bytes;
|
||||
}
|
||||
|
||||
r->_errno = rc;
|
||||
return -1;
|
||||
return bytesWritten;
|
||||
}
|
||||
|
||||
/*! Read from an open file
|
||||
@ -427,7 +545,7 @@ sdmc_read(struct _reent *r,
|
||||
return (ssize_t)bytes;
|
||||
}
|
||||
|
||||
r->_errno = rc;
|
||||
r->_errno = sdmc_translate_error(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -471,7 +589,7 @@ sdmc_seek(struct _reent *r,
|
||||
rc = FSFILE_GetSize(file->fd, &offset);
|
||||
if(rc != 0)
|
||||
{
|
||||
r->_errno = rc;
|
||||
r->_errno = sdmc_translate_error(rc);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
@ -509,7 +627,21 @@ sdmc_fstat(struct _reent *r,
|
||||
int fd,
|
||||
struct stat *st)
|
||||
{
|
||||
r->_errno = ENOSYS;
|
||||
Result rc;
|
||||
u64 size;
|
||||
sdmc_file_t *file = (sdmc_file_t*)fd;
|
||||
|
||||
rc = FSFILE_GetSize(file->fd, &size);
|
||||
if(rc == 0)
|
||||
{
|
||||
memset(st, 0, sizeof(struct stat));
|
||||
st->st_size = (off_t)size;
|
||||
st->st_nlink = 1;
|
||||
st->st_mode = S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r->_errno = sdmc_translate_error(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -527,48 +659,33 @@ sdmc_stat(struct _reent *r,
|
||||
const char *file,
|
||||
struct stat *st)
|
||||
{
|
||||
Handle fd;
|
||||
Result rc;
|
||||
const char *pathptr = NULL;
|
||||
Handle fd;
|
||||
Result rc;
|
||||
FS_path fs_path;
|
||||
|
||||
pathptr = sdmc_fixpath(file);
|
||||
|
||||
if(pathptr==NULL)
|
||||
{
|
||||
r->_errno=EINVAL;
|
||||
fs_path = sdmc_utf16path(r, file);
|
||||
if(fs_path.data == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( (rc = FSUSER_OpenFile(NULL, &fd, sdmcArchive, FS_makePath(PATH_CHAR, pathptr),
|
||||
FS_OPEN_READ, FS_ATTRIBUTE_NONE))==0)
|
||||
if((rc = FSUSER_OpenFile(NULL, &fd, sdmcArchive, fs_path,
|
||||
FS_OPEN_READ, FS_ATTRIBUTE_NONE)) == 0)
|
||||
{
|
||||
u64 tmpsize = 0;
|
||||
rc = FSFILE_GetSize(fd, &tmpsize);
|
||||
|
||||
sdmc_file_t tmpfd = { .fd = fd };
|
||||
rc = sdmc_fstat(r, (int)&tmpfd, st);
|
||||
FSFILE_Close(fd);
|
||||
|
||||
if(rc==0)
|
||||
{
|
||||
memset(st, 0, sizeof(struct stat));
|
||||
st->st_size = (off_t)tmpsize;
|
||||
st->st_nlink = 1;
|
||||
st->st_uid = 1;
|
||||
st->st_gid = 2;
|
||||
st->st_mode = S_IFREG | S_IWUSR | S_IWGRP | S_IWOTH | S_IRUSR | S_IRGRP | S_IROTH;
|
||||
return 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
else if((rc = FSUSER_OpenDirectory(NULL, &fd, sdmcArchive, fs_path)) == 0)
|
||||
{
|
||||
memset(st, 0, sizeof(struct stat));
|
||||
st->st_nlink = 1;
|
||||
st->st_mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO;
|
||||
FSDIR_Close(fd);
|
||||
return 0;
|
||||
}
|
||||
if( (rc = FSUSER_OpenDirectory(NULL, &fd, sdmcArchive, FS_makePath(PATH_CHAR, pathptr))) == 0 )
|
||||
{
|
||||
memset(st, 0, sizeof(struct stat));
|
||||
st->st_nlink = 1;
|
||||
st->st_uid = 1;
|
||||
st->st_gid = 2;
|
||||
st->st_mode = S_IFDIR | S_IWUSR | S_IWGRP | S_IWOTH | S_IRUSR | S_IRGRP | S_IROTH;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r->_errno = EBADF;
|
||||
r->_errno = sdmc_translate_error(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -602,7 +719,18 @@ static int
|
||||
sdmc_unlink(struct _reent *r,
|
||||
const char *name)
|
||||
{
|
||||
r->_errno = ENOSYS;
|
||||
Result rc;
|
||||
FS_path fs_path;
|
||||
|
||||
fs_path = sdmc_utf16path(r, name);
|
||||
if(fs_path.data == NULL)
|
||||
return -1;
|
||||
|
||||
rc = FSUSER_DeleteFile(NULL, sdmcArchive, fs_path);
|
||||
if(rc == 0)
|
||||
return 0;
|
||||
|
||||
r->_errno = sdmc_translate_error(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -618,32 +746,24 @@ static int
|
||||
sdmc_chdir(struct _reent *r,
|
||||
const char *name)
|
||||
{
|
||||
Handle fd;
|
||||
Result rc;
|
||||
const char *pathptr = NULL;
|
||||
Handle fd;
|
||||
Result rc;
|
||||
FS_path fs_path;
|
||||
|
||||
pathptr = sdmc_fixpath(name);
|
||||
|
||||
if(pathptr==NULL)
|
||||
{
|
||||
r->_errno=EINVAL;
|
||||
fs_path = sdmc_utf16path(r, name);
|
||||
if(fs_path.data == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = FSUSER_OpenDirectory(NULL, &fd, sdmcArchive, FS_makePath(PATH_CHAR, pathptr));
|
||||
rc = FSUSER_OpenDirectory(NULL, &fd, sdmcArchive, fs_path);
|
||||
if(rc == 0)
|
||||
{
|
||||
FSDIR_Close(fd);
|
||||
strncpy(__cwd,pathptr,PATH_MAX);
|
||||
}
|
||||
else
|
||||
{
|
||||
r->_errno=EINVAL;
|
||||
return -1;
|
||||
strncpy(__cwd, __fixedpath, PATH_MAX);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
r->_errno = sdmc_translate_error(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*! Rename a file
|
||||
@ -660,7 +780,30 @@ sdmc_rename(struct _reent *r,
|
||||
const char *oldName,
|
||||
const char *newName)
|
||||
{
|
||||
r->_errno = ENOSYS;
|
||||
Result rc;
|
||||
FS_path fs_path_old, fs_path_new;
|
||||
static uint16_t __utf16path_old[PATH_MAX+1];
|
||||
|
||||
fs_path_old = sdmc_utf16path(r, oldName);
|
||||
if(fs_path_old.data == NULL)
|
||||
return -1;
|
||||
|
||||
memcpy(__utf16path_old, __utf16path, sizeof(__utf16path));
|
||||
fs_path_old.data = (const u8*)__utf16path_old;
|
||||
|
||||
fs_path_new = sdmc_utf16path(r, newName);
|
||||
if(fs_path_new.data == NULL)
|
||||
return -1;
|
||||
|
||||
rc = FSUSER_RenameFile(NULL, sdmcArchive, fs_path_old, sdmcArchive, fs_path_new);
|
||||
if(rc == 0)
|
||||
return 0;
|
||||
|
||||
rc = FSUSER_RenameDirectory(NULL, sdmcArchive, fs_path_old, sdmcArchive, fs_path_new);
|
||||
if(rc == 0)
|
||||
return 0;
|
||||
|
||||
r->_errno = sdmc_translate_error(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -679,23 +822,19 @@ sdmc_mkdir(struct _reent *r,
|
||||
int mode)
|
||||
{
|
||||
Result rc;
|
||||
const char *pathptr = NULL;
|
||||
FS_path fs_path;
|
||||
|
||||
pathptr = sdmc_fixpath(path);
|
||||
|
||||
if(pathptr==NULL)
|
||||
{
|
||||
r->_errno=EINVAL;
|
||||
fs_path = sdmc_utf16path(r, path);
|
||||
if(fs_path.data == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* TODO: Use mode to set directory attributes. */
|
||||
|
||||
rc = FSUSER_CreateDirectory(NULL, sdmcArchive, FS_makePath(PATH_CHAR, pathptr));
|
||||
rc = FSUSER_CreateDirectory(NULL, sdmcArchive, fs_path);
|
||||
if(rc == 0)
|
||||
return 0;
|
||||
|
||||
r->_errno = ENOSYS;
|
||||
r->_errno = sdmc_translate_error(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -713,23 +852,20 @@ sdmc_diropen(struct _reent *r,
|
||||
DIR_ITER *dirState,
|
||||
const char *path)
|
||||
{
|
||||
Handle fd;
|
||||
Result rc;
|
||||
const char *pathptr = NULL;
|
||||
Handle fd;
|
||||
Result rc;
|
||||
FS_path fs_path;
|
||||
|
||||
pathptr = sdmc_fixpath(path);
|
||||
fs_path = sdmc_utf16path(r, path);
|
||||
|
||||
if(pathptr==NULL)
|
||||
{
|
||||
r->_errno=EINVAL;
|
||||
if(fs_path.data == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* get pointer to our data */
|
||||
sdmc_dir_t *dir = (sdmc_dir_t*)(dirState->dirStruct);
|
||||
|
||||
/* open the directory */
|
||||
rc = FSUSER_OpenDirectory(NULL, &fd, sdmcArchive, FS_makePath(PATH_CHAR, pathptr));
|
||||
rc = FSUSER_OpenDirectory(NULL, &fd, sdmcArchive, fs_path);
|
||||
if(rc == 0)
|
||||
{
|
||||
dir->fd = fd;
|
||||
@ -737,7 +873,7 @@ sdmc_diropen(struct _reent *r,
|
||||
return dirState;
|
||||
}
|
||||
|
||||
r->_errno = rc;
|
||||
r->_errno = sdmc_translate_error(rc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -773,14 +909,15 @@ sdmc_dirnext(struct _reent *r,
|
||||
char *filename,
|
||||
struct stat *filestat)
|
||||
{
|
||||
Result rc;
|
||||
u32 entries;
|
||||
u16 *name;
|
||||
Result rc;
|
||||
u32 entries;
|
||||
size_t units;
|
||||
|
||||
/* get pointer to our data */
|
||||
sdmc_dir_t *dir = (sdmc_dir_t*)(dirState->dirStruct);
|
||||
|
||||
/* fetch the next entry */
|
||||
memset(&dir->entry_data, 0, sizeof(dir->entry_data));
|
||||
rc = FSDIR_Read(dir->fd, &entries, 1, &dir->entry_data);
|
||||
if(rc == 0)
|
||||
{
|
||||
@ -798,16 +935,25 @@ sdmc_dirnext(struct _reent *r,
|
||||
else
|
||||
filestat->st_mode = S_IFREG;
|
||||
|
||||
/* copy the name */
|
||||
name = dir->entry_data.name;
|
||||
while(*name)
|
||||
*filename++ = *name++;
|
||||
*filename = 0;
|
||||
/* convert name from UTF-16 to UTF-8 */
|
||||
memset(filename, 0, NAME_MAX);
|
||||
units = utf16_to_utf8((uint8_t*)filename, dir->entry_data.name, NAME_MAX);
|
||||
if(units == (size_t)-1)
|
||||
{
|
||||
r->_errno = EILSEQ;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(filename[NAME_MAX-1] != 0)
|
||||
{
|
||||
r->_errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
r->_errno = rc;
|
||||
r->_errno = sdmc_translate_error(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -833,7 +979,7 @@ sdmc_dirclose(struct _reent *r,
|
||||
if(rc == 0)
|
||||
return 0;
|
||||
|
||||
r->_errno = rc;
|
||||
r->_errno = sdmc_translate_error(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -882,7 +1028,7 @@ sdmc_statvfs(struct _reent *r,
|
||||
return 0;
|
||||
}
|
||||
|
||||
r->_errno = rc;
|
||||
r->_errno = sdmc_translate_error(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -917,7 +1063,7 @@ sdmc_ftruncate(struct _reent *r,
|
||||
if(rc == 0)
|
||||
return 0;
|
||||
|
||||
r->_errno = rc;
|
||||
r->_errno = sdmc_translate_error(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -942,7 +1088,7 @@ sdmc_fsync(struct _reent *r,
|
||||
if(rc == 0)
|
||||
return 0;
|
||||
|
||||
r->_errno = rc;
|
||||
r->_errno = sdmc_translate_error(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -981,3 +1127,91 @@ sdmc_fchmod(struct _reent *r,
|
||||
r->_errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*! Remove a directory
|
||||
*
|
||||
* @param[in,out] r newlib reentrancy struct
|
||||
* @param[in] name Path of directory to remove
|
||||
*
|
||||
* @returns 0 for success
|
||||
* @returns -1 for error
|
||||
*/
|
||||
static int
|
||||
sdmc_rmdir(struct _reent *r,
|
||||
const char *name)
|
||||
{
|
||||
Result rc;
|
||||
FS_path fs_path;
|
||||
|
||||
fs_path = sdmc_utf16path(r, name);
|
||||
if(fs_path.data == NULL)
|
||||
return -1;
|
||||
|
||||
rc = FSUSER_DeleteDirectory(NULL, sdmcArchive, fs_path);
|
||||
if(rc == 0)
|
||||
return 0;
|
||||
|
||||
r->_errno = sdmc_translate_error(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*! Error map */
|
||||
typedef struct
|
||||
{
|
||||
Result fs_error; //!< Error from FS service
|
||||
int error; //!< POSIX errno
|
||||
} error_map_t;
|
||||
|
||||
/*! Error table */
|
||||
static const error_map_t error_table[] =
|
||||
{
|
||||
/* keep this list sorted! */
|
||||
{ 0x082044BE, EEXIST, },
|
||||
{ 0x086044D2, ENOSPC, },
|
||||
{ 0xC8804478, ENOENT, },
|
||||
{ 0xC92044FA, ENOENT, },
|
||||
{ 0xE0E046BE, EINVAL, },
|
||||
{ 0xE0E046BF, ENAMETOOLONG, },
|
||||
};
|
||||
static const size_t num_errors = sizeof(error_table)/sizeof(error_table[0]);
|
||||
|
||||
/*! Comparison function for bsearch on error_table
|
||||
*
|
||||
* @param[in] p1 Left side of comparison
|
||||
* @param[in] p2 Right side of comparison
|
||||
*
|
||||
* @returns <0 if lhs < rhs
|
||||
* @returns >0 if lhs > rhs
|
||||
* @returns 0 if lhs == rhs
|
||||
*/
|
||||
static int
|
||||
error_cmp(const void *p1, const void *p2)
|
||||
{
|
||||
const error_map_t *lhs = (const error_map_t*)p1;
|
||||
const error_map_t *rhs = (const error_map_t*)p2;
|
||||
|
||||
if((u32)lhs->fs_error < (u32)rhs->fs_error)
|
||||
return -1;
|
||||
else if((u32)lhs->fs_error > (u32)rhs->fs_error)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! Translate FS service error to errno
|
||||
*
|
||||
* @param[in] error FS service error
|
||||
*
|
||||
* @returns errno
|
||||
*/
|
||||
static int
|
||||
sdmc_translate_error(Result error)
|
||||
{
|
||||
error_map_t key = { .fs_error = error };
|
||||
const error_map_t *rc = bsearch(&key, error_table, num_errors,
|
||||
sizeof(error_map_t), error_cmp);
|
||||
|
||||
if(rc != NULL)
|
||||
return rc->error;
|
||||
|
||||
return (int)error;
|
||||
}
|
||||
|
@ -380,7 +380,7 @@ static bool __handle_incoming_parameter() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void aptEventHandler(u32 arg)
|
||||
void aptEventHandler(void *arg)
|
||||
{
|
||||
bool runThread = true;
|
||||
|
||||
|
@ -38,7 +38,7 @@ Result CFGU_GenHashConsoleUnique(u32 appIDSalt, u64* hash)
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = 0x00030000;
|
||||
cmdbuf[0] = 0x00030040;
|
||||
cmdbuf[1] = appIDSalt;
|
||||
|
||||
if((ret = svcSendSyncRequest(CFGU_handle))!=0)return ret;
|
||||
|
@ -6,102 +6,160 @@
|
||||
#include <3ds/os.h>
|
||||
#include <3ds/services/csnd.h>
|
||||
|
||||
//See here regarding CSND shared-mem commands, etc: http://3dbrew.org/wiki/CSND_Shared_Memory
|
||||
// See here regarding CSND shared-mem commands, etc: http://3dbrew.org/wiki/CSND_Shared_Memory
|
||||
|
||||
Handle CSND_handle = 0;
|
||||
Handle CSND_mutexhandle = 0;
|
||||
Handle CSND_sharedmemhandle = 0;
|
||||
u32 *CSND_sharedmem = NULL;
|
||||
static u32 CSND_bitmask=0;
|
||||
vu32* csndSharedMem = NULL;
|
||||
u32 csndSharedMemSize;
|
||||
u32 csndChannels = 0;
|
||||
u32 csndOffsets[4];
|
||||
|
||||
static u32 CSND_sharedmem_cmdblocksize = 0x2000;
|
||||
static u32 CSND_sharedmem_startcmdoff = 0;
|
||||
static u32 CSND_sharedmem_currentcmdoff = 0;
|
||||
static Handle csndHandle = 0;
|
||||
static Handle csndMutex = 0;
|
||||
static Handle csndSharedMemBlock = 0;
|
||||
|
||||
Result CSND_cmd1(Handle *mutexhandle, Handle *sharedmemhandle, u32 sharedmem_size, u32 off0, u32 off1, u32 off2, u32 off3)
|
||||
static u8 csndChnIdx[CSND_NUM_CHANNELS];
|
||||
static u32 csndCmdBlockSize = 0x2000;
|
||||
static u32 csndCmdStartOff = 0;
|
||||
static u32 csndCmdCurOff = 0;
|
||||
|
||||
static Result CSND_Initialize(void)
|
||||
{
|
||||
Result ret=0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = 0x00010140;
|
||||
cmdbuf[1] = sharedmem_size;
|
||||
cmdbuf[2] = off0;
|
||||
cmdbuf[3] = off1;
|
||||
cmdbuf[4] = off2;
|
||||
cmdbuf[5] = off3;
|
||||
cmdbuf[1] = csndSharedMemSize;
|
||||
memcpy(&cmdbuf[2], &csndOffsets[0], 4*sizeof(u32));
|
||||
|
||||
if((ret = svcSendSyncRequest(CSND_handle))!=0)return ret;
|
||||
if((ret = svcSendSyncRequest(csndHandle))!=0)return ret;
|
||||
|
||||
*mutexhandle = cmdbuf[3];
|
||||
*sharedmemhandle = cmdbuf[4];
|
||||
csndMutex = cmdbuf[3];
|
||||
csndSharedMemBlock = cmdbuf[4];
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result CSND_cmd2()
|
||||
static Result CSND_Shutdown()
|
||||
{
|
||||
Result ret=0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = 0x00020000;
|
||||
|
||||
if((ret = svcSendSyncRequest(CSND_handle))!=0)return ret;
|
||||
if((ret = svcSendSyncRequest(csndHandle))!=0)return ret;
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result CSND_cmd5(u32 *bitmask)
|
||||
static Result CSND_AcquireSoundChannels(u32* channelMask)
|
||||
{
|
||||
Result ret=0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = 0x00050000;
|
||||
|
||||
if((ret = svcSendSyncRequest(CSND_handle))!=0)return ret;
|
||||
if((ret = svcSendSyncRequest(csndHandle))!=0)return ret;
|
||||
|
||||
*bitmask = cmdbuf[2];
|
||||
*channelMask = cmdbuf[2];
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result CSND_initialize(u32* sharedMem)
|
||||
static Result CSND_ReleaseSoundChannels(void)
|
||||
{
|
||||
Result ret=0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
if(sharedMem==NULL)sharedMem = (u32*)CSND_SHAREDMEM_DEFAULT;
|
||||
CSND_sharedmem = sharedMem;
|
||||
cmdbuf[0] = 0x00060000;
|
||||
|
||||
ret = srvGetServiceHandle(&CSND_handle, "csnd:SND");
|
||||
if(ret!=0)return ret;
|
||||
if((ret = svcSendSyncRequest(csndHandle))!=0)return ret;
|
||||
|
||||
ret = CSND_cmd1(&CSND_mutexhandle, &CSND_sharedmemhandle, CSND_sharedmem_cmdblocksize+0x114, CSND_sharedmem_cmdblocksize, CSND_sharedmem_cmdblocksize+8, CSND_sharedmem_cmdblocksize+0xc8, CSND_sharedmem_cmdblocksize+0xd8);
|
||||
if(ret!=0)return ret;
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
ret = svcMapMemoryBlock(CSND_sharedmemhandle, (u32)CSND_sharedmem, 3, 0x10000000);
|
||||
if(ret!=0)return ret;
|
||||
Result CSND_AcquireCapUnit(u32* capUnit)
|
||||
{
|
||||
Result ret=0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
memset(CSND_sharedmem, 0, 0x2114);
|
||||
cmdbuf[0] = 0x00070000;
|
||||
|
||||
ret = CSND_cmd5(&CSND_bitmask);
|
||||
if(ret!=0)return ret;
|
||||
if((ret = svcSendSyncRequest(csndHandle))!=0)return ret;
|
||||
|
||||
*capUnit = cmdbuf[2];
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result CSND_ReleaseCapUnit(u32 capUnit)
|
||||
{
|
||||
Result ret=0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = 0x00080040;
|
||||
cmdbuf[1] = capUnit;
|
||||
|
||||
if((ret = svcSendSyncRequest(csndHandle))!=0)return ret;
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result csndInit(void)
|
||||
{
|
||||
Result ret=0;
|
||||
csndSharedMem = (vu32*)CSND_SHAREDMEM_DEFAULT;
|
||||
|
||||
// TODO: proper error handling!
|
||||
|
||||
ret = srvGetServiceHandle(&csndHandle, "csnd:SND");
|
||||
if (ret != 0) return ret;
|
||||
|
||||
// Calculate offsets and sizes required by the CSND module
|
||||
csndOffsets[0] = csndCmdBlockSize; // Offset to some unknown DSP status flags
|
||||
csndOffsets[1] = csndOffsets[0] + 8; // Offset to sound channel information
|
||||
csndOffsets[2] = csndOffsets[1] + 32*sizeof(CSND_ChnInfo); // Offset to information for an 'unknown' sort of channels
|
||||
csndOffsets[3] = csndOffsets[2] + 2*8; // Offset to more unknown information
|
||||
csndSharedMemSize = csndOffsets[3] + 0x3C; // Total size of the CSND shared memory
|
||||
|
||||
ret = CSND_Initialize();
|
||||
if (ret != 0) return ret;
|
||||
|
||||
ret = svcMapMemoryBlock(csndSharedMemBlock, (u32)csndSharedMem, 3, 0x10000000);
|
||||
if (ret != 0) return ret;
|
||||
|
||||
memset((void*)csndSharedMem, 0, csndSharedMemSize);
|
||||
|
||||
ret = CSND_AcquireSoundChannels(&csndChannels);
|
||||
if (ret != 0) return ret;
|
||||
|
||||
// Build channel indices for the sound channel information table
|
||||
int i, j = 0;
|
||||
for (i = 0; i < CSND_NUM_CHANNELS; i ++)
|
||||
{
|
||||
csndChnIdx[i] = j;
|
||||
if (csndChannels & BIT(i))
|
||||
j ++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result CSND_shutdown()
|
||||
Result csndExit(void)
|
||||
{
|
||||
Result ret;
|
||||
|
||||
svcUnmapMemoryBlock(CSND_sharedmemhandle, (u32)CSND_sharedmem);
|
||||
svcCloseHandle(CSND_sharedmemhandle);
|
||||
ret = CSND_ReleaseSoundChannels();
|
||||
if (ret != 0) return ret;
|
||||
|
||||
ret = CSND_cmd2();
|
||||
if(ret!=0)return ret;
|
||||
svcUnmapMemoryBlock(csndSharedMemBlock, (u32)csndSharedMem);
|
||||
svcCloseHandle(csndSharedMemBlock);
|
||||
|
||||
return svcCloseHandle(CSND_handle);
|
||||
ret = CSND_Shutdown();
|
||||
svcCloseHandle(csndHandle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Result CSND_cmd3(u32 offset)
|
||||
static Result CSND_ExecCmd0(u32 offset)
|
||||
{
|
||||
Result ret=0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
@ -109,66 +167,66 @@ Result CSND_cmd3(u32 offset)
|
||||
cmdbuf[0] = 0x00030040;
|
||||
cmdbuf[1] = offset;
|
||||
|
||||
if((ret = svcSendSyncRequest(CSND_handle))!=0)return ret;
|
||||
if((ret = svcSendSyncRequest(csndHandle))!=0)return ret;
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
void CSND_writesharedmem_cmdtype0(u16 cmdid, u8 *cmdparams)
|
||||
void csndWriteCmd(int cmdid, u8 *cmdparams)
|
||||
{
|
||||
u16 *ptr;
|
||||
vu16* ptr;
|
||||
u32 prevoff;
|
||||
s32 outindex=0;
|
||||
|
||||
svcWaitSynchronizationN(&outindex, &CSND_mutexhandle, 1, 0, ~0);
|
||||
svcWaitSynchronizationN(&outindex, &csndMutex, 1, 0, ~0);
|
||||
|
||||
if(CSND_sharedmem_startcmdoff != CSND_sharedmem_currentcmdoff)
|
||||
if (csndCmdStartOff != csndCmdCurOff)
|
||||
{
|
||||
if(CSND_sharedmem_currentcmdoff>=0x20)
|
||||
{
|
||||
prevoff = CSND_sharedmem_currentcmdoff-0x20;
|
||||
}
|
||||
if (csndCmdCurOff>=0x20)
|
||||
prevoff = csndCmdCurOff-0x20;
|
||||
else
|
||||
{
|
||||
prevoff = CSND_sharedmem_cmdblocksize-0x20;
|
||||
}
|
||||
prevoff = csndCmdBlockSize-0x20;
|
||||
|
||||
ptr = (u16*)&CSND_sharedmem[prevoff>>2];
|
||||
*ptr = CSND_sharedmem_currentcmdoff;
|
||||
ptr = (vu16*)&csndSharedMem[prevoff>>2];
|
||||
*ptr = csndCmdCurOff;
|
||||
}
|
||||
|
||||
ptr = (u16*)&CSND_sharedmem[CSND_sharedmem_currentcmdoff>>2];
|
||||
ptr = (vu16*)&csndSharedMem[csndCmdCurOff>>2];
|
||||
|
||||
ptr[0] = 0xffff;
|
||||
ptr[0] = 0xFFFF;
|
||||
ptr[1] = cmdid;
|
||||
ptr[2] = 0;
|
||||
ptr[3] = 0;
|
||||
memcpy(&ptr[8>>1], cmdparams, 0x18);
|
||||
memcpy((void*)&ptr[4], cmdparams, 0x18);
|
||||
|
||||
CSND_sharedmem_currentcmdoff+= 0x20;
|
||||
if(CSND_sharedmem_currentcmdoff >= CSND_sharedmem_cmdblocksize)CSND_sharedmem_currentcmdoff = 0;
|
||||
csndCmdCurOff += 0x20;
|
||||
if (csndCmdCurOff >= csndCmdBlockSize)
|
||||
csndCmdCurOff = 0;
|
||||
|
||||
svcReleaseMutex(CSND_mutexhandle);
|
||||
svcReleaseMutex(csndMutex);
|
||||
}
|
||||
|
||||
Result CSND_processtype0cmds()
|
||||
Result csndExecCmds(bool waitDone)
|
||||
{
|
||||
Result ret=0;
|
||||
|
||||
if(CSND_sharedmem_startcmdoff == CSND_sharedmem_currentcmdoff)return 0;
|
||||
// Check we actually wrote commands
|
||||
if (csndCmdStartOff == csndCmdCurOff)
|
||||
return 0;
|
||||
|
||||
ret = CSND_cmd3(CSND_sharedmem_startcmdoff);
|
||||
CSND_sharedmem_startcmdoff = CSND_sharedmem_currentcmdoff;
|
||||
vu8* flag = (vu8*)&csndSharedMem[(csndCmdStartOff + 4) >> 2];
|
||||
|
||||
ret = CSND_ExecCmd0(csndCmdStartOff);
|
||||
csndCmdStartOff = csndCmdCurOff;
|
||||
if (ret != 0) return ret;
|
||||
|
||||
// FIXME: This is a really ugly busy waiting loop!
|
||||
while (waitDone && *flag == 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 CSND_convertsamplerate(u32 samplerate)
|
||||
{
|
||||
return (u32)(6.7027964E+07f / ((float)samplerate));
|
||||
}
|
||||
|
||||
void CSND_sharedmemtype0_cmd0(u32 channel, u32 value)
|
||||
void CSND_SetPlayStateR(u32 channel, u32 value)
|
||||
{
|
||||
u32 cmdparams[0x18>>2];
|
||||
|
||||
@ -177,10 +235,10 @@ void CSND_sharedmemtype0_cmd0(u32 channel, u32 value)
|
||||
cmdparams[0] = channel & 0x1f;
|
||||
cmdparams[1] = value;
|
||||
|
||||
CSND_writesharedmem_cmdtype0(0x0, (u8*)&cmdparams);
|
||||
csndWriteCmd(0x0, (u8*)&cmdparams);
|
||||
}
|
||||
|
||||
void CSND_setchannel_playbackstate(u32 channel, u32 value)
|
||||
void CSND_SetPlayState(u32 channel, u32 value)
|
||||
{
|
||||
u32 cmdparams[0x18>>2];
|
||||
|
||||
@ -189,10 +247,10 @@ void CSND_setchannel_playbackstate(u32 channel, u32 value)
|
||||
cmdparams[0] = channel & 0x1f;
|
||||
cmdparams[1] = value;
|
||||
|
||||
CSND_writesharedmem_cmdtype0(0x1, (u8*)&cmdparams);
|
||||
csndWriteCmd(0x1, (u8*)&cmdparams);
|
||||
}
|
||||
|
||||
void CSND_sharedmemtype0_cmd3(u32 channel, u32 physaddr, u32 size)
|
||||
void CSND_SetBlock(u32 channel, int block, u32 physaddr, u32 size)
|
||||
{
|
||||
u32 cmdparams[0x18>>2];
|
||||
|
||||
@ -202,127 +260,210 @@ void CSND_sharedmemtype0_cmd3(u32 channel, u32 physaddr, u32 size)
|
||||
cmdparams[1] = physaddr;
|
||||
cmdparams[2] = size;
|
||||
|
||||
CSND_writesharedmem_cmdtype0(0x3, (u8*)&cmdparams);
|
||||
csndWriteCmd(block ? 0x3 : 0xA, (u8*)&cmdparams);
|
||||
}
|
||||
|
||||
void CSND_sharedmemtype0_cmd9(u32 channel, u16 value)
|
||||
void CSND_SetVol(u32 channel, u16 left, u16 right)
|
||||
{
|
||||
u32 cmdparams[0x18>>2];
|
||||
|
||||
memset(cmdparams, 0, 0x18);
|
||||
|
||||
cmdparams[0] = channel & 0x1f;
|
||||
cmdparams[1] = value | (value<<16);
|
||||
cmdparams[1] = left | (right<<16);
|
||||
|
||||
CSND_writesharedmem_cmdtype0(0x9, (u8*)&cmdparams);
|
||||
csndWriteCmd(0x9, (u8*)&cmdparams);
|
||||
}
|
||||
|
||||
void CSND_sharedmemtype0_cmd8(u32 channel, u32 samplerate)
|
||||
void CSND_SetTimer(u32 channel, u32 timer)
|
||||
{
|
||||
u32 cmdparams[0x18>>2];
|
||||
|
||||
memset(cmdparams, 0, 0x18);
|
||||
|
||||
cmdparams[0] = channel & 0x1f;
|
||||
cmdparams[1] = CSND_convertsamplerate(samplerate);
|
||||
cmdparams[1] = timer;
|
||||
|
||||
CSND_writesharedmem_cmdtype0(0x8, (u8*)&cmdparams);
|
||||
csndWriteCmd(0x8, (u8*)&cmdparams);
|
||||
}
|
||||
|
||||
void CSND_sharedmemtype0_cmde(u32 channel, u32 looping, u32 encoding, u32 samplerate, u32 unk0, u32 unk1, u32 physaddr0, u32 physaddr1, u32 totalbytesize)
|
||||
void CSND_SetDuty(u32 channel, u32 duty)
|
||||
{
|
||||
u32 val;
|
||||
u32 cmdparams[0x18>>2];
|
||||
|
||||
memset(cmdparams, 0, 0x18);
|
||||
|
||||
cmdparams[0] = channel & 0x1f;
|
||||
cmdparams[0] |= (unk0 & 0xf) << 6;
|
||||
if(!looping)cmdparams[0] |= 2 << 10;
|
||||
if(looping)cmdparams[0] |= 1 << 10;
|
||||
cmdparams[0] |= (encoding & 3) << 12;
|
||||
cmdparams[0] |= (unk1 & 3) << 14;
|
||||
cmdparams[1] = duty;
|
||||
|
||||
val = CSND_convertsamplerate(samplerate);
|
||||
if(val<0x42)val = 0x42;
|
||||
if(val>0xffff)val = 0xffff;
|
||||
cmdparams[0] |= val<<16;
|
||||
csndWriteCmd(0x7, (u8*)&cmdparams);
|
||||
}
|
||||
|
||||
void CSND_SetAdpcmState(u32 channel, int block, int sample, int index)
|
||||
{
|
||||
u32 cmdparams[0x18>>2];
|
||||
|
||||
memset(cmdparams, 0, 0x18);
|
||||
|
||||
cmdparams[0] = channel & 0x1f;
|
||||
cmdparams[1] = sample & 0xFFFF;
|
||||
cmdparams[2] = index & 0x7F;
|
||||
|
||||
csndWriteCmd(block ? 0xC : 0xB, (u8*)&cmdparams);
|
||||
}
|
||||
|
||||
void CSND_SetAdpcmReload(u32 channel, bool reload)
|
||||
{
|
||||
u32 cmdparams[0x18>>2];
|
||||
|
||||
memset(cmdparams, 0, 0x18);
|
||||
|
||||
cmdparams[0] = channel & 0x1f;
|
||||
cmdparams[1] = reload ? 1 : 0;
|
||||
|
||||
csndWriteCmd(0xD, (u8*)&cmdparams);
|
||||
}
|
||||
|
||||
void CSND_SetChnRegs(u32 flags, u32 physaddr0, u32 physaddr1, u32 totalbytesize)
|
||||
{
|
||||
u32 cmdparams[0x18>>2];
|
||||
|
||||
memset(cmdparams, 0, 0x18);
|
||||
|
||||
cmdparams[0] = flags;
|
||||
cmdparams[1] = 0x7FFF7FFF; // Volume
|
||||
cmdparams[2] = 0; // Unknown
|
||||
cmdparams[3] = physaddr0;
|
||||
cmdparams[4] = physaddr1;
|
||||
cmdparams[5] = totalbytesize;
|
||||
|
||||
CSND_writesharedmem_cmdtype0(0xe, (u8*)&cmdparams);
|
||||
csndWriteCmd(0xe, (u8*)&cmdparams);
|
||||
}
|
||||
|
||||
Result CSND_sharedmemtype0_cmdupdatestate(int waitdone)
|
||||
Result CSND_UpdateInfo(bool waitDone)
|
||||
{
|
||||
u8 *ptr;
|
||||
int ret=0;
|
||||
|
||||
u32 cmdparams[0x18>>2];
|
||||
|
||||
memset(cmdparams, 0, 0x18);
|
||||
|
||||
ptr = (u8*)&CSND_sharedmem[CSND_sharedmem_startcmdoff>>2];
|
||||
csndWriteCmd(0x300, (u8*)&cmdparams);
|
||||
return csndExecCmds(waitDone);
|
||||
}
|
||||
|
||||
CSND_writesharedmem_cmdtype0(0x300, (u8*)&cmdparams);
|
||||
void CSND_CapEnable(u32 capUnit, bool enable)
|
||||
{
|
||||
u32 cmdparams[0x18>>2];
|
||||
memset(cmdparams, 0, 0x18);
|
||||
|
||||
ret = CSND_processtype0cmds();
|
||||
if(ret!=0)return ret;
|
||||
cmdparams[0] = capUnit;
|
||||
cmdparams[1] = enable ? 1 : 0;
|
||||
|
||||
if(waitdone)
|
||||
csndWriteCmd(0x100, (u8*)&cmdparams);
|
||||
}
|
||||
|
||||
void CSND_CapSetBit(u32 capUnit, int bit, bool state)
|
||||
{
|
||||
u32 cmdparams[0x18>>2];
|
||||
memset(cmdparams, 0, 0x18);
|
||||
|
||||
cmdparams[0] = capUnit;
|
||||
cmdparams[1] = state ? 1 : 0;
|
||||
|
||||
csndWriteCmd(0x101 + bit, (u8*)&cmdparams);
|
||||
}
|
||||
|
||||
void CSND_CapSetTimer(u32 capUnit, u32 timer)
|
||||
{
|
||||
u32 cmdparams[0x18>>2];
|
||||
memset(cmdparams, 0, 0x18);
|
||||
|
||||
cmdparams[0] = capUnit;
|
||||
cmdparams[1] = timer & 0xFFFF;
|
||||
|
||||
csndWriteCmd(0x104, (u8*)&cmdparams);
|
||||
}
|
||||
|
||||
void CSND_CapSetBuffer(u32 capUnit, u32 paddr, u32 size)
|
||||
{
|
||||
u32 cmdparams[0x18>>2];
|
||||
memset(cmdparams, 0, 0x18);
|
||||
|
||||
cmdparams[0] = capUnit;
|
||||
cmdparams[1] = paddr;
|
||||
cmdparams[2] = size;
|
||||
|
||||
csndWriteCmd(0x105, (u8*)&cmdparams);
|
||||
}
|
||||
|
||||
Result csndPlaySound(int chn, u32 flags, u32 sampleRate, void* data0, void* data1, u32 size)
|
||||
{
|
||||
if (!(csndChannels & BIT(chn)))
|
||||
return 1;
|
||||
|
||||
u32 paddr0 = 0, paddr1 = 0;
|
||||
|
||||
int encoding = (flags >> 12) & 3;
|
||||
int loopMode = (flags >> 10) & 3;
|
||||
|
||||
if (encoding != CSND_ENCODING_PSG)
|
||||
{
|
||||
while(*ptr == 0);
|
||||
if (data0) paddr0 = osConvertVirtToPhys((u32)data0);
|
||||
if (data1) paddr1 = osConvertVirtToPhys((u32)data1);
|
||||
|
||||
if (data0 && encoding == CSND_ENCODING_ADPCM)
|
||||
{
|
||||
int adpcmSample = ((s16*)data0)[-2];
|
||||
int adpcmIndex = ((u8*)data0)[-2];
|
||||
CSND_SetAdpcmState(chn, 0, adpcmSample, adpcmIndex);
|
||||
}
|
||||
}
|
||||
|
||||
u32 timer = CSND_TIMER(sampleRate);
|
||||
if (timer < 0x0042) timer = 0x0042;
|
||||
else if (timer > 0xFFFF) timer = 0xFFFF;
|
||||
flags &= ~0xFFFF001F;
|
||||
flags |= SOUND_ENABLE | SOUND_CHANNEL(chn) | (timer << 16);
|
||||
|
||||
CSND_SetChnRegs(flags, paddr0, paddr1, size);
|
||||
|
||||
if (loopMode == CSND_LOOPMODE_NORMAL && paddr1 > paddr0)
|
||||
{
|
||||
// Now that the first block is playing, configure the size of the subsequent blocks
|
||||
size -= paddr1 - paddr0;
|
||||
CSND_SetBlock(chn, 1, paddr1, size);
|
||||
}
|
||||
|
||||
return csndExecCmds(true);
|
||||
}
|
||||
|
||||
CSND_ChnInfo* csndGetChnInfo(u32 channel)
|
||||
{
|
||||
channel = csndChnIdx[channel];
|
||||
return (CSND_ChnInfo*)(&csndSharedMem[(csndOffsets[1] + channel*0xc) >> 2]);
|
||||
}
|
||||
|
||||
Result csndGetState(u32 channel, CSND_ChnInfo* out)
|
||||
{
|
||||
Result ret = 0;
|
||||
channel = csndChnIdx[channel];
|
||||
|
||||
if ((ret = CSND_UpdateInfo(true)) != 0)return ret;
|
||||
|
||||
memcpy(out, (const void*)&csndSharedMem[(csndOffsets[1] + channel*0xc) >> 2], 0xc);
|
||||
//out[2] -= 0x0c000000;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result CSND_playsound(u32 channel, u32 looping, u32 encoding, u32 samplerate, u32 *vaddr0, u32 *vaddr1, u32 totalbytesize, u32 unk0, u32 unk1)
|
||||
{
|
||||
u32 physaddr0 = 0;
|
||||
u32 physaddr1 = 0;
|
||||
|
||||
physaddr0 = osConvertVirtToPhys((u32)vaddr0);
|
||||
physaddr1 = osConvertVirtToPhys((u32)vaddr1);
|
||||
|
||||
CSND_sharedmemtype0_cmde(channel, looping, encoding, samplerate, unk0, unk1, physaddr0, physaddr1, totalbytesize);
|
||||
CSND_sharedmemtype0_cmd8(channel, samplerate);
|
||||
if(looping)
|
||||
{
|
||||
if(physaddr1>physaddr0)totalbytesize-= (u32)physaddr1 - (u32)physaddr0;
|
||||
CSND_sharedmemtype0_cmd3(channel, physaddr1, totalbytesize);
|
||||
}
|
||||
CSND_sharedmemtype0_cmd8(channel, samplerate);
|
||||
CSND_sharedmemtype0_cmd9(channel, 0xffff);
|
||||
CSND_setchannel_playbackstate(channel, 1);
|
||||
|
||||
return CSND_sharedmemtype0_cmdupdatestate(0);
|
||||
}
|
||||
|
||||
Result CSND_getchannelstate(u32 entryindex, u32 *out)
|
||||
{
|
||||
Result ret=0;
|
||||
|
||||
if((ret = CSND_sharedmemtype0_cmdupdatestate(1))!=0)return ret;
|
||||
|
||||
memcpy(out, &CSND_sharedmem[(CSND_sharedmem_cmdblocksize+8 + entryindex*0xc) >> 2], 0xc);
|
||||
out[2] -= 0x0c000000;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result CSND_getchannelstate_isplaying(u32 entryindex, u8 *status)
|
||||
Result csndIsPlaying(u32 channel, u8* status)
|
||||
{
|
||||
Result ret;
|
||||
u32 entry[0xc>>2];
|
||||
CSND_ChnInfo entry;
|
||||
|
||||
ret = CSND_getchannelstate(entryindex, entry);
|
||||
ret = csndGetState(channel, &entry);
|
||||
if(ret!=0)return ret;
|
||||
|
||||
*status = entry[0] & 0xff;
|
||||
*status = entry.active;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ Handle gspEventThread;
|
||||
static Handle gspEvent;
|
||||
static vu8* gspEventData;
|
||||
|
||||
static void gspEventThreadMain(u32 arg);
|
||||
static void gspEventThreadMain(void *arg);
|
||||
|
||||
|
||||
Result gspInit()
|
||||
@ -82,7 +82,7 @@ void gspWaitForEvent(GSP_Event id, bool nextEvent)
|
||||
svcClearEvent(gspEvents[id]);
|
||||
}
|
||||
|
||||
void gspEventThreadMain(u32 arg)
|
||||
void gspEventThreadMain(void *arg)
|
||||
{
|
||||
while (gspRunEvents)
|
||||
{
|
||||
@ -114,7 +114,7 @@ void gspEventThreadMain(u32 arg)
|
||||
Result GSPGPU_WriteHWRegs(Handle* handle, u32 regAddr, u32* data, u8 size)
|
||||
{
|
||||
if(!handle)handle=&gspGpuHandle;
|
||||
|
||||
|
||||
if(size>0x80 || !data)return -1;
|
||||
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
@ -133,7 +133,7 @@ Result GSPGPU_WriteHWRegs(Handle* handle, u32 regAddr, u32* data, u8 size)
|
||||
Result GSPGPU_WriteHWRegsWithMask(Handle* handle, u32 regAddr, u32* data, u8 datasize, u32* maskdata, u8 masksize)
|
||||
{
|
||||
if(!handle)handle=&gspGpuHandle;
|
||||
|
||||
|
||||
if(datasize>0x80 || !data)return -1;
|
||||
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
@ -154,7 +154,7 @@ Result GSPGPU_WriteHWRegsWithMask(Handle* handle, u32 regAddr, u32* data, u8 dat
|
||||
Result GSPGPU_ReadHWRegs(Handle* handle, u32 regAddr, u32* data, u8 size)
|
||||
{
|
||||
if(!handle)handle=&gspGpuHandle;
|
||||
|
||||
|
||||
if(size>0x80 || !data)return -1;
|
||||
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
@ -180,7 +180,7 @@ Result GSPGPU_SetBufferSwap(Handle* handle, u32 screenid, GSP_FramebufferInfo *f
|
||||
cmdbuf[0] = 0x00050200;
|
||||
cmdbuf[1] = screenid;
|
||||
memcpy(&cmdbuf[2], framebufinfo, sizeof(GSP_FramebufferInfo));
|
||||
|
||||
|
||||
if((ret=svcSendSyncRequest(*handle)))return ret;
|
||||
|
||||
return cmdbuf[1];
|
||||
@ -189,7 +189,7 @@ Result GSPGPU_SetBufferSwap(Handle* handle, u32 screenid, GSP_FramebufferInfo *f
|
||||
Result GSPGPU_FlushDataCache(Handle* handle, u8* adr, u32 size)
|
||||
{
|
||||
if(!handle)handle=&gspGpuHandle;
|
||||
|
||||
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
cmdbuf[0]=0x00080082; //request header code
|
||||
cmdbuf[1]=(u32)adr;
|
||||
@ -224,7 +224,7 @@ Result GSPGPU_InvalidateDataCache(Handle* handle, u8* adr, u32 size)
|
||||
Result GSPGPU_SetLcdForceBlack(Handle* handle, u8 flags)
|
||||
{
|
||||
if(!handle)handle=&gspGpuHandle;
|
||||
|
||||
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
cmdbuf[0]=0x000B0040; //request header code
|
||||
cmdbuf[1]=flags;
|
||||
@ -238,7 +238,7 @@ Result GSPGPU_SetLcdForceBlack(Handle* handle, u8 flags)
|
||||
Result GSPGPU_TriggerCmdReqQueue(Handle* handle)
|
||||
{
|
||||
if(!handle)handle=&gspGpuHandle;
|
||||
|
||||
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
cmdbuf[0]=0x000C0000; //request header code
|
||||
|
||||
@ -251,7 +251,7 @@ Result GSPGPU_TriggerCmdReqQueue(Handle* handle)
|
||||
Result GSPGPU_RegisterInterruptRelayQueue(Handle* handle, Handle eventHandle, u32 flags, Handle* outMemHandle, u8* threadID)
|
||||
{
|
||||
if(!handle)handle=&gspGpuHandle;
|
||||
|
||||
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
cmdbuf[0]=0x00130042; //request header code
|
||||
cmdbuf[1]=flags;
|
||||
@ -263,27 +263,27 @@ Result GSPGPU_RegisterInterruptRelayQueue(Handle* handle, Handle eventHandle, u3
|
||||
|
||||
if(threadID)*threadID=cmdbuf[2];
|
||||
if(outMemHandle)*outMemHandle=cmdbuf[4];
|
||||
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
Result GSPGPU_UnregisterInterruptRelayQueue(Handle* handle)
|
||||
{
|
||||
if(!handle)handle=&gspGpuHandle;
|
||||
|
||||
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
cmdbuf[0]=0x00140000; //request header code
|
||||
|
||||
Result ret=0;
|
||||
if((ret=svcSendSyncRequest(*handle)))return ret;
|
||||
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
Result GSPGPU_AcquireRight(Handle* handle, u8 flags)
|
||||
{
|
||||
if(!handle)handle=&gspGpuHandle;
|
||||
|
||||
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
cmdbuf[0]=0x160042; //request header code
|
||||
cmdbuf[1]=flags;
|
||||
@ -299,7 +299,7 @@ Result GSPGPU_AcquireRight(Handle* handle, u8 flags)
|
||||
Result GSPGPU_ReleaseRight(Handle* handle)
|
||||
{
|
||||
if(!handle)handle=&gspGpuHandle;
|
||||
|
||||
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
cmdbuf[0]=0x170000; //request header code
|
||||
|
||||
@ -312,7 +312,7 @@ Result GSPGPU_ReleaseRight(Handle* handle)
|
||||
Result GSPGPU_ImportDisplayCaptureInfo(Handle* handle, GSP_CaptureInfo *captureinfo)
|
||||
{
|
||||
if(!handle)handle=&gspGpuHandle;
|
||||
|
||||
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
cmdbuf[0]=0x00180000; //request header code
|
||||
|
||||
@ -332,7 +332,7 @@ Result GSPGPU_ImportDisplayCaptureInfo(Handle* handle, GSP_CaptureInfo *capturei
|
||||
Result GSPGPU_SaveVramSysArea(Handle* handle)
|
||||
{
|
||||
if(!handle)handle=&gspGpuHandle;
|
||||
|
||||
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
cmdbuf[0]=0x00190000; //request header code
|
||||
|
||||
@ -345,7 +345,7 @@ Result GSPGPU_SaveVramSysArea(Handle* handle)
|
||||
Result GSPGPU_RestoreVramSysArea(Handle* handle)
|
||||
{
|
||||
if(!handle)handle=&gspGpuHandle;
|
||||
|
||||
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
cmdbuf[0]=0x001A0000; //request header code
|
||||
|
||||
@ -361,7 +361,7 @@ Result GSPGPU_RestoreVramSysArea(Handle* handle)
|
||||
Result GSPGPU_SubmitGxCommand(u32* sharedGspCmdBuf, u32 gxCommand[0x8], Handle* handle)
|
||||
{
|
||||
if(!sharedGspCmdBuf || !gxCommand)return -1;
|
||||
|
||||
|
||||
u32 cmdBufHeader;
|
||||
__asm__ __volatile__ ("ldrex %[result], [%[adr]]" : [result] "=r" (cmdBufHeader) : [adr] "r" (sharedGspCmdBuf));
|
||||
|
||||
|
@ -43,8 +43,8 @@ Result httpcOpenContext(httpcContext *context, char* url, u32 use_defaultproxy)
|
||||
|
||||
ret = HTTPC_InitializeConnectionSession(context->servhandle, context->httphandle);
|
||||
if(ret!=0) {
|
||||
HTTPC_CloseContext(__httpc_servhandle, context->httphandle);
|
||||
svcCloseHandle(context->servhandle);
|
||||
HTTPC_CloseContext(__httpc_servhandle, context->httphandle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -52,8 +52,8 @@ Result httpcOpenContext(httpcContext *context, char* url, u32 use_defaultproxy)
|
||||
|
||||
ret = HTTPC_SetProxyDefault(context->servhandle, context->httphandle);
|
||||
if(ret!=0) {
|
||||
HTTPC_CloseContext(__httpc_servhandle, context->httphandle);
|
||||
svcCloseHandle(context->servhandle);
|
||||
HTTPC_CloseContext(__httpc_servhandle, context->httphandle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -64,8 +64,8 @@ Result httpcCloseContext(httpcContext *context)
|
||||
{
|
||||
Result ret=0;
|
||||
|
||||
ret = HTTPC_CloseContext(context->servhandle, context->httphandle);
|
||||
svcCloseHandle(context->servhandle);
|
||||
ret = HTTPC_CloseContext(__httpc_servhandle, context->httphandle);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -216,16 +216,16 @@ Result HTTPC_AddRequestHeaderField(Handle handle, Handle contextHandle, char* na
|
||||
{
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
|
||||
int l1=strlen(name)+1;
|
||||
int l2=strlen(value)+1;
|
||||
int name_len=strlen(name)+1;
|
||||
int value_len=strlen(value)+1;
|
||||
|
||||
cmdbuf[0]=0x1100c4; //request header code
|
||||
cmdbuf[1]=contextHandle;
|
||||
cmdbuf[2]=l1;
|
||||
cmdbuf[3]=l2;
|
||||
cmdbuf[4]=(l1<<14)|0xC02;
|
||||
cmdbuf[2]=name_len;
|
||||
cmdbuf[3]=value_len;
|
||||
cmdbuf[4]=(name_len<<14)|0xC02;
|
||||
cmdbuf[5]=(u32)name;
|
||||
cmdbuf[6]=(l1<<4)|0xA;
|
||||
cmdbuf[6]=(value_len<<4)|0xA;
|
||||
cmdbuf[7]=(u32)value;
|
||||
|
||||
Result ret=0;
|
||||
|
@ -1,14 +1,39 @@
|
||||
#include "soc_common.h"
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
|
||||
{
|
||||
int ret=0;
|
||||
int tmp_addrlen=0x1c;
|
||||
int ret = 0;
|
||||
int tmp_addrlen = 0x1c;
|
||||
int fd, dev;
|
||||
__handle *handle;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
u8 tmpaddr[0x1c];
|
||||
u32 saved_threadstorage[2];
|
||||
|
||||
sockfd = soc_get_fd(sockfd);
|
||||
if(sockfd < 0) {
|
||||
errno = -sockfd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
dev = FindDevice("soc:");
|
||||
if(dev < 0) {
|
||||
errno = ENODEV;
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = __alloc_handle(sizeof(__handle) + sizeof(Handle));
|
||||
if(fd < 0) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
handle = __get_handle(fd);
|
||||
handle->device = dev;
|
||||
handle->fileStruct = ((void *)handle) + sizeof(__handle);
|
||||
|
||||
memset(tmpaddr, 0, 0x1c);
|
||||
|
||||
cmdbuf[0] = 0x00040082;
|
||||
@ -22,22 +47,36 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
|
||||
cmdbuf[0x100>>2] = (tmp_addrlen<<14) | 2;
|
||||
cmdbuf[0x104>>2] = (u32)tmpaddr;
|
||||
|
||||
if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
if(ret != 0) {
|
||||
__release_handle(fd);
|
||||
errno = SYNC_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
cmdbuf[0x100>>2] = saved_threadstorage[0];
|
||||
cmdbuf[0x104>>2] = saved_threadstorage[1];
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret==0)ret = _net_convert_error(cmdbuf[2]);
|
||||
if(ret<0)SOCU_errno = ret;
|
||||
if(ret == 0)
|
||||
ret = _net_convert_error(cmdbuf[2]);
|
||||
|
||||
if(ret>=0 && addr!=NULL)
|
||||
{
|
||||
if(ret < 0)
|
||||
errno = -ret;
|
||||
|
||||
if(ret >= 0 && addr != NULL) {
|
||||
addr->sa_family = tmpaddr[1];
|
||||
if(*addrlen > tmpaddr[0])*addrlen = tmpaddr[0];
|
||||
if(*addrlen > tmpaddr[0])
|
||||
*addrlen = tmpaddr[0];
|
||||
memcpy(addr->sa_data, &tmpaddr[2], *addrlen - 2);
|
||||
}
|
||||
|
||||
if(ret<0)return -1;
|
||||
return ret;
|
||||
if(ret < 0) {
|
||||
__release_handle(fd);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
*(Handle*)handle->fileStruct = ret;
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
@ -4,25 +4,26 @@
|
||||
|
||||
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
|
||||
{
|
||||
int ret=0;
|
||||
int tmp_addrlen=0;
|
||||
int ret = 0;
|
||||
int tmp_addrlen = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
u8 tmpaddr[0x1c];
|
||||
|
||||
sockfd = soc_get_fd(sockfd);
|
||||
if(sockfd < 0) {
|
||||
errno = -sockfd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(tmpaddr, 0, 0x1c);
|
||||
|
||||
if(addr->sa_family == AF_INET)
|
||||
{
|
||||
tmp_addrlen = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp_addrlen = 0x1c;
|
||||
}
|
||||
|
||||
if(addrlen < tmp_addrlen)
|
||||
{
|
||||
SOCU_errno = EINVAL;
|
||||
if(addrlen < tmp_addrlen) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -37,12 +38,20 @@ int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
|
||||
cmdbuf[5] = (((u32)tmp_addrlen)<<14) | 2;
|
||||
cmdbuf[6] = (u32)tmpaddr;
|
||||
|
||||
if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
if(ret != 0) {
|
||||
errno = SYNC_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret==0)ret = _net_convert_error(cmdbuf[2]);
|
||||
SOCU_errno = ret;
|
||||
if(ret == 0)
|
||||
ret = _net_convert_error(cmdbuf[2]);
|
||||
|
||||
if(ret < 0) {
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(ret<0)return -1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,21 +1,15 @@
|
||||
#include "soc_common.h"
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int closesocket(int sockfd)
|
||||
{
|
||||
int ret=0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
int fd = soc_get_fd(sockfd);
|
||||
if(fd < 0) {
|
||||
errno = -fd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmdbuf[0] = 0x000B0042;
|
||||
cmdbuf[1] = (u32)sockfd;
|
||||
cmdbuf[2] = 0x20;
|
||||
|
||||
if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret==0)ret =_net_convert_error(cmdbuf[2]);
|
||||
SOCU_errno = ret;
|
||||
|
||||
if(ret!=0)return -1;
|
||||
return 0;
|
||||
return close(sockfd);
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
#include "soc_common.h"
|
||||
#include <errno.h>
|
||||
#include <sys/iosupport.h>
|
||||
|
||||
Handle SOCU_handle = 0;
|
||||
int SOCU_errno = 0;
|
||||
Handle socMemhandle = 0;
|
||||
|
||||
//This is based on the array from libogc network_wii.c.
|
||||
@ -91,14 +91,11 @@ static u8 _net_error_code_map[] = {
|
||||
//This is based on the function from libogc network_wii.c.
|
||||
s32 _net_convert_error(s32 sock_retval)
|
||||
{
|
||||
if (sock_retval >= 0) return sock_retval;
|
||||
if (sock_retval < -sizeof(_net_error_code_map)
|
||||
|| !_net_error_code_map[-sock_retval])
|
||||
return NET_UNKNOWN_ERROR_OFFSET + sock_retval;
|
||||
if(sock_retval >= 0)
|
||||
return sock_retval;
|
||||
|
||||
if(sock_retval < -sizeof(_net_error_code_map)
|
||||
|| !_net_error_code_map[-sock_retval])
|
||||
return NET_UNKNOWN_ERROR_OFFSET + sock_retval;
|
||||
return -_net_error_code_map[-sock_retval];
|
||||
}
|
||||
|
||||
int SOC_GetErrno(void)
|
||||
{
|
||||
return SOCU_errno;
|
||||
}
|
||||
|
@ -1,13 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/iosupport.h>
|
||||
#include <sys/socket.h>
|
||||
#include <3ds/types.h>
|
||||
#include <3ds/svc.h>
|
||||
#include <3ds/srv.h>
|
||||
#include <3ds/services/soc.h>
|
||||
|
||||
#define SYNC_ERROR ENODEV
|
||||
|
||||
int __alloc_handle(size_t size);
|
||||
__handle *__get_handle(int fd);
|
||||
void __release_handle(int fd);
|
||||
|
||||
extern Handle SOCU_handle;
|
||||
extern int SOCU_errno;
|
||||
extern Handle socMemhandle;
|
||||
|
||||
static inline int
|
||||
soc_get_fd(int fd)
|
||||
{
|
||||
__handle *handle = __get_handle(fd);
|
||||
if(handle == NULL)
|
||||
return -ENODEV;
|
||||
if(strcmp(devoptab_list[handle->device]->name, "soc") != 0)
|
||||
return -ENOTSOCK;
|
||||
return *(Handle*)handle->fileStruct;
|
||||
}
|
||||
|
||||
s32 _net_convert_error(s32 sock_retval);
|
||||
|
||||
ssize_t soc_recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
|
||||
|
||||
ssize_t soc_sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
|
||||
|
@ -4,25 +4,26 @@
|
||||
|
||||
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
|
||||
{
|
||||
int ret=0;
|
||||
int tmp_addrlen=0;
|
||||
int ret = 0;
|
||||
int tmp_addrlen = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
u8 tmpaddr[0x1c];
|
||||
|
||||
sockfd = soc_get_fd(sockfd);
|
||||
if(sockfd < 0) {
|
||||
errno = -sockfd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(tmpaddr, 0, 0x1c);
|
||||
|
||||
if(addr->sa_family == AF_INET)
|
||||
{
|
||||
tmp_addrlen = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp_addrlen = 0x1c;
|
||||
}
|
||||
|
||||
if(addrlen < tmp_addrlen)
|
||||
{
|
||||
SOCU_errno = -EINVAL;
|
||||
if(addrlen < tmp_addrlen) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -37,12 +38,20 @@ int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
|
||||
cmdbuf[5] = (((u32)tmp_addrlen)<<14) | 2;
|
||||
cmdbuf[6] = (u32)tmpaddr;
|
||||
|
||||
if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
if(ret != 0) {
|
||||
errno = SYNC_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret==0)ret = _net_convert_error(cmdbuf[2]);
|
||||
SOCU_errno = ret;
|
||||
if(ret == 0)
|
||||
ret = _net_convert_error(cmdbuf[2]);
|
||||
|
||||
if(ret < 0) {
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(ret<0)return -1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -12,7 +12,8 @@ static int from_3ds(int flags)
|
||||
{
|
||||
int newflags = 0;
|
||||
|
||||
if(flags & O_NONBLOCK_3DS) newflags |= O_NONBLOCK;
|
||||
if(flags & O_NONBLOCK_3DS)
|
||||
newflags |= O_NONBLOCK;
|
||||
/* add other flag translations here, but I have only seen O_NONBLOCK */
|
||||
|
||||
return newflags;
|
||||
@ -22,13 +23,14 @@ static int to_3ds(int flags)
|
||||
{
|
||||
int newflags = 0;
|
||||
|
||||
if(flags & O_NONBLOCK) newflags |= O_NONBLOCK_3DS;
|
||||
if(flags & O_NONBLOCK)
|
||||
newflags |= O_NONBLOCK_3DS;
|
||||
/* add other flag translations here, but I have only seen O_NONBLOCK */
|
||||
|
||||
return newflags;
|
||||
}
|
||||
|
||||
int fcntl(int fd, int cmd, ...)
|
||||
int fcntl(int sockfd, int cmd, ...)
|
||||
{
|
||||
int ret = 0;
|
||||
int arg = 0;
|
||||
@ -36,49 +38,53 @@ int fcntl(int fd, int cmd, ...)
|
||||
|
||||
va_list args;
|
||||
|
||||
if(cmd != F_GETFL && cmd != F_SETFL)
|
||||
{
|
||||
SOCU_errno = -EINVAL;
|
||||
sockfd = soc_get_fd(sockfd);
|
||||
if(sockfd < 0) {
|
||||
errno = -sockfd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
va_start(args, cmd);
|
||||
if(cmd == F_SETFL)
|
||||
{
|
||||
if(cmd != F_GETFL && cmd != F_SETFL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(cmd == F_SETFL) {
|
||||
va_start(args, cmd);
|
||||
arg = va_arg(args, int);
|
||||
va_end(args);
|
||||
|
||||
/* make sure they only used known flags */
|
||||
if(arg & ~ALL_FLAGS)
|
||||
{
|
||||
SOCU_errno = -EINVAL;
|
||||
va_end(args);
|
||||
if(arg & ~ALL_FLAGS) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
arg = to_3ds(arg);
|
||||
}
|
||||
va_end(args);
|
||||
|
||||
cmdbuf[0] = 0x001300C2;
|
||||
cmdbuf[1] = (u32)fd;
|
||||
cmdbuf[1] = (u32)sockfd;
|
||||
cmdbuf[2] = (u32)cmd;
|
||||
cmdbuf[3] = (u32)arg;
|
||||
cmdbuf[4] = 0x20;
|
||||
|
||||
if((ret = svcSendSyncRequest(SOCU_handle)) != 0)
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
if(ret != 0) {
|
||||
errno = SYNC_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret == 0)
|
||||
ret = _net_convert_error(cmdbuf[2]);
|
||||
if(ret < 0)
|
||||
SOCU_errno = ret;
|
||||
|
||||
if(ret < 0)
|
||||
if(ret < 0) {
|
||||
errno = ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(ret & ~ALL_3DS)
|
||||
{
|
||||
if(ret & ~ALL_3DS) {
|
||||
/* somehow report unknown flags */
|
||||
}
|
||||
|
||||
|
@ -10,11 +10,13 @@ int h_errno = 0;
|
||||
|
||||
struct hostent* gethostbyname(const char *name)
|
||||
{
|
||||
int ret=0;
|
||||
int ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
u32 saved_threadstorage[2];
|
||||
static u8 outbuf[0x1A88];
|
||||
|
||||
h_errno = 0;
|
||||
|
||||
cmdbuf[0] = 0x000D0082;
|
||||
cmdbuf[1] = strlen(name)+1;
|
||||
cmdbuf[2] = sizeof(outbuf);
|
||||
@ -27,17 +29,25 @@ struct hostent* gethostbyname(const char *name)
|
||||
cmdbuf[0x100>>2] = (sizeof(outbuf) << 14) | 2;
|
||||
cmdbuf[0x104>>2] = (u32)outbuf;
|
||||
|
||||
if(( ret = svcSendSyncRequest(SOCU_handle))!=0)return NULL;
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
if(ret != 0) {
|
||||
h_errno = NO_RECOVERY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
cmdbuf[0x100>>2] = saved_threadstorage[0];
|
||||
cmdbuf[0x104>>2] = saved_threadstorage[1];
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret==0)ret = _net_convert_error(cmdbuf[2]);
|
||||
if(ret<0)SOCU_errno = ret;
|
||||
/* TODO: set h_errno based on SOCU_errno */
|
||||
if(ret == 0)
|
||||
ret = _net_convert_error(cmdbuf[2]);
|
||||
|
||||
if(ret<0)return NULL;
|
||||
if(ret < 0) {
|
||||
/* TODO: set h_errno based on ret */
|
||||
h_errno = HOST_NOT_FOUND;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u32 num_results, i;
|
||||
memcpy(&num_results, (char*)outbuf+4, sizeof(num_results));
|
||||
|
@ -1,16 +1,22 @@
|
||||
#include "soc_common.h"
|
||||
#include <errno.h>
|
||||
|
||||
long gethostid(void)
|
||||
{
|
||||
int ret=0;
|
||||
int ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = 0x00160000;
|
||||
|
||||
if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
if(ret != 0) {
|
||||
errno = SYNC_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret==0)ret = cmdbuf[2];
|
||||
if(ret == 0)
|
||||
ret = cmdbuf[2];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1,13 +1,20 @@
|
||||
#include "soc_common.h"
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
|
||||
{
|
||||
int ret=0;
|
||||
int ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
u32 saved_threadstorage[2];
|
||||
u8 tmpaddr[0x1c];
|
||||
|
||||
sockfd = soc_get_fd(sockfd);
|
||||
if(sockfd < 0) {
|
||||
errno = -sockfd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmdbuf[0] = 0x00180082;
|
||||
cmdbuf[1] = (u32)sockfd;
|
||||
cmdbuf[2] = 0x1c;
|
||||
@ -19,23 +26,29 @@ int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
|
||||
cmdbuf[0x100>>2] = (0x1c<<14) | 2;
|
||||
cmdbuf[0x104>>2] = (u32)tmpaddr;
|
||||
|
||||
if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
if(ret != 0) {
|
||||
errno = SYNC_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
cmdbuf[0x100>>2] = saved_threadstorage[0];
|
||||
cmdbuf[0x104>>2] = saved_threadstorage[1];
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret==0)ret = _net_convert_error(cmdbuf[2]);
|
||||
if(ret<0)SOCU_errno = ret;
|
||||
if(ret == 0)
|
||||
ret = _net_convert_error(cmdbuf[2]);
|
||||
|
||||
if(ret==0)
|
||||
{
|
||||
if(*addrlen > tmpaddr[0])*addrlen = tmpaddr[0];
|
||||
memset(addr, 0, sizeof(struct sockaddr));
|
||||
addr->sa_family = tmpaddr[1];
|
||||
memcpy(addr->sa_data, &tmpaddr[2], *addrlen - 2);
|
||||
if(ret < 0) {
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(ret<0)return -1;
|
||||
if(*addrlen > tmpaddr[0])
|
||||
*addrlen = tmpaddr[0];
|
||||
memset(addr, 0, sizeof(struct sockaddr));
|
||||
addr->sa_family = tmpaddr[1];
|
||||
memcpy(addr->sa_data, &tmpaddr[2], *addrlen - 2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1,13 +1,20 @@
|
||||
#include "soc_common.h"
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
|
||||
{
|
||||
int ret=0;
|
||||
int ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
u32 saved_threadstorage[2];
|
||||
u8 tmpaddr[0x1c];
|
||||
|
||||
sockfd = soc_get_fd(sockfd);
|
||||
if(sockfd < 0) {
|
||||
errno = -sockfd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmdbuf[0] = 0x00170082;
|
||||
cmdbuf[1] = (u32)sockfd;
|
||||
cmdbuf[2] = 0x1c;
|
||||
@ -19,23 +26,29 @@ int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
|
||||
cmdbuf[0x100>>2] = (0x1c<<14) | 2;
|
||||
cmdbuf[0x104>>2] = (u32)tmpaddr;
|
||||
|
||||
if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
if(ret != 0) {
|
||||
errno = SYNC_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
cmdbuf[0x100>>2] = saved_threadstorage[0];
|
||||
cmdbuf[0x104>>2] = saved_threadstorage[1];
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret==0)ret = _net_convert_error(cmdbuf[2]);
|
||||
if(ret<0)SOCU_errno = ret;
|
||||
if(ret == 0)
|
||||
ret = _net_convert_error(cmdbuf[2]);
|
||||
|
||||
if(ret==0)
|
||||
{
|
||||
if(*addrlen > tmpaddr[0])*addrlen = tmpaddr[0];
|
||||
memset(addr, 0, sizeof(struct sockaddr));
|
||||
addr->sa_family = tmpaddr[1];
|
||||
memcpy(addr->sa_data, &tmpaddr[2], *addrlen - 2);
|
||||
if(ret < 0) {
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(ret<0)return -1;
|
||||
if(*addrlen > tmpaddr[0])
|
||||
*addrlen = tmpaddr[0];
|
||||
memset(addr, 0, sizeof(struct sockaddr));
|
||||
addr->sa_family = tmpaddr[1];
|
||||
memcpy(addr->sa_data, &tmpaddr[2], *addrlen - 2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1,12 +1,19 @@
|
||||
#include "soc_common.h"
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen)
|
||||
{
|
||||
int ret=0;
|
||||
int ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
u32 saved_threadstorage[2];
|
||||
|
||||
sockfd = soc_get_fd(sockfd);
|
||||
if(sockfd < 0) {
|
||||
errno = -sockfd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmdbuf[0] = 0x00110102;
|
||||
cmdbuf[1] = (u32)sockfd;
|
||||
cmdbuf[2] = (u32)level;
|
||||
@ -20,17 +27,25 @@ int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optl
|
||||
cmdbuf[0x100>>2] = ((*optlen)<<14) | 2;
|
||||
cmdbuf[0x104>>2] = (u32)optval;
|
||||
|
||||
if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
if(ret != 0) {
|
||||
errno = SYNC_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
cmdbuf[0x100>>2] = saved_threadstorage[0];
|
||||
cmdbuf[0x104>>2] = saved_threadstorage[1];
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret==0)ret = _net_convert_error(cmdbuf[2]);
|
||||
if(ret<0)SOCU_errno = ret;
|
||||
if(ret == 0)
|
||||
ret = _net_convert_error(cmdbuf[2]);
|
||||
|
||||
if(ret==0)*optlen = cmdbuf[3];
|
||||
if(ret < 0) {
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*optlen = cmdbuf[3];
|
||||
|
||||
if(ret<0)return -1;
|
||||
return ret;
|
||||
}
|
||||
|
10
libctru/source/services/soc/soc_herror.c
Normal file
10
libctru/source/services/soc/soc_herror.c
Normal file
@ -0,0 +1,10 @@
|
||||
#include "soc_common.h"
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
|
||||
void herror(const char *s) {
|
||||
if(s)
|
||||
fiprintf(stderr, "%s\n", hstrerror(h_errno));
|
||||
else
|
||||
fiprintf(stderr, "%s: %s\n", s, hstrerror(h_errno));
|
||||
}
|
26
libctru/source/services/soc/soc_hstrerror.c
Normal file
26
libctru/source/services/soc/soc_hstrerror.c
Normal file
@ -0,0 +1,26 @@
|
||||
#include "soc_common.h"
|
||||
#include <netdb.h>
|
||||
|
||||
static const struct
|
||||
{
|
||||
int err;
|
||||
const char *str;
|
||||
} error_strings[] =
|
||||
{
|
||||
{ 0, "Resolver Error 0 (no error)", },
|
||||
{ HOST_NOT_FOUND, "Unknown host", },
|
||||
{ NO_DATA, "No address associated with name", },
|
||||
{ NO_RECOVERY, "Unknown server error", },
|
||||
{ TRY_AGAIN, "Host name lookup failure", },
|
||||
};
|
||||
static const size_t num_error_strings = sizeof(error_strings)/sizeof(error_strings[0]);
|
||||
|
||||
const char* hstrerror(int err) {
|
||||
size_t i;
|
||||
for(i = 0; i < num_error_strings; ++i) {
|
||||
if(error_strings[i].err == err)
|
||||
return error_strings[i].str;
|
||||
}
|
||||
|
||||
return "Unknown resolver error";
|
||||
}
|
@ -1,8 +1,46 @@
|
||||
#include "soc_common.h"
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
static int soc_open(struct _reent *r, void *fileStruct, const char *path, int flags, int mode);
|
||||
static int soc_close(struct _reent *r, int fd);
|
||||
static ssize_t soc_write(struct _reent *r, int fd, const char *ptr, size_t len);
|
||||
static ssize_t soc_read(struct _reent *r, int fd, char *ptr, size_t len);
|
||||
|
||||
static devoptab_t
|
||||
soc_devoptab =
|
||||
{
|
||||
.name = "soc",
|
||||
.structSize = sizeof(Handle),
|
||||
.open_r = soc_open,
|
||||
.close_r = soc_close,
|
||||
.write_r = soc_write,
|
||||
.read_r = soc_read,
|
||||
.seek_r = NULL,
|
||||
.fstat_r = NULL,
|
||||
.stat_r = NULL,
|
||||
.link_r = NULL,
|
||||
.unlink_r = NULL,
|
||||
.chdir_r = NULL,
|
||||
.rename_r = NULL,
|
||||
.mkdir_r = NULL,
|
||||
.dirStateSize = 0,
|
||||
.diropen_r = NULL,
|
||||
.dirreset_r = NULL,
|
||||
.dirnext_r = NULL,
|
||||
.dirclose_r = NULL,
|
||||
.statvfs_r = NULL,
|
||||
.ftruncate_r = NULL,
|
||||
.fsync_r = NULL,
|
||||
.deviceData = NULL,
|
||||
.chmod_r = NULL,
|
||||
.fchmod_r = NULL,
|
||||
};
|
||||
|
||||
|
||||
static Result socu_cmd1(Handle memhandle, u32 memsize)
|
||||
{
|
||||
Result ret=0;
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = 0x00010044;
|
||||
@ -11,34 +49,132 @@ static Result socu_cmd1(Handle memhandle, u32 memsize)
|
||||
cmdbuf[4] = 0;
|
||||
cmdbuf[5] = memhandle;
|
||||
|
||||
if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
if(ret != 0) {
|
||||
errno = SYNC_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
Result SOC_Initialize(u32 *context_addr, u32 context_size)
|
||||
{
|
||||
Result ret=0;
|
||||
Result ret = 0;
|
||||
|
||||
/* check that the "soc" device doesn't already exist */
|
||||
int dev = FindDevice("soc:");
|
||||
if(dev >= 0)
|
||||
return -1;
|
||||
|
||||
/* add the "soc" device */
|
||||
dev = AddDevice(&soc_devoptab);
|
||||
if(dev < 0)
|
||||
return dev;
|
||||
|
||||
ret = svcCreateMemoryBlock(&socMemhandle, (u32)context_addr, context_size, 0, 3);
|
||||
if(ret!=0)return ret;
|
||||
if(ret != 0) {
|
||||
RemoveDevice("soc");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if((ret = srvGetServiceHandle(&SOCU_handle, "soc:U"))!=0)return ret;
|
||||
ret = srvGetServiceHandle(&SOCU_handle, "soc:U");
|
||||
if(ret != 0) {
|
||||
RemoveDevice("soc");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return socu_cmd1(socMemhandle, context_size);
|
||||
ret = socu_cmd1(socMemhandle, context_size);
|
||||
if(ret != 0) {
|
||||
RemoveDevice("soc");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result SOC_Shutdown(void)
|
||||
{
|
||||
Result ret=0;
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
int dev;
|
||||
|
||||
cmdbuf[0] = 0x00190000;
|
||||
|
||||
if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
if(ret != 0) {
|
||||
errno = SYNC_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
svcCloseHandle(SOCU_handle);
|
||||
svcCloseHandle(socMemhandle);
|
||||
|
||||
dev = FindDevice("soc:");
|
||||
if(dev >= 0)
|
||||
RemoveDevice("soc");
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
static int
|
||||
soc_open(struct _reent *r,
|
||||
void *fileStruct,
|
||||
const char *path,
|
||||
int flags,
|
||||
int mode)
|
||||
{
|
||||
r->_errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
soc_close(struct _reent *r,
|
||||
int fd)
|
||||
{
|
||||
Handle sockfd = *(Handle*)fd;
|
||||
|
||||
int ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = 0x000B0042;
|
||||
cmdbuf[1] = (u32)sockfd;
|
||||
cmdbuf[2] = 0x20;
|
||||
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
if(ret != 0) {
|
||||
errno = SYNC_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret == 0)
|
||||
ret =_net_convert_error(cmdbuf[2]);
|
||||
|
||||
if(ret < 0) {
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
soc_write(struct _reent *r,
|
||||
int fd,
|
||||
const char *ptr,
|
||||
size_t len)
|
||||
{
|
||||
Handle sockfd = *(Handle*)fd;
|
||||
return soc_sendto(sockfd, ptr, len, 0, NULL, 0);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
soc_read(struct _reent *r,
|
||||
int fd,
|
||||
char *ptr,
|
||||
size_t len)
|
||||
{
|
||||
Handle sockfd = *(Handle*)fd;
|
||||
return soc_recvfrom(sockfd, ptr, len, 0, NULL, 0);
|
||||
}
|
||||
|
@ -4,35 +4,38 @@
|
||||
#include <stdarg.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
int ioctl(int fd, int request, ...)
|
||||
int ioctl(int sockfd, int request, ...)
|
||||
{
|
||||
int ret;
|
||||
int flags;
|
||||
int *value;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, request);
|
||||
sockfd = soc_get_fd(sockfd);
|
||||
if(sockfd < 0) {
|
||||
errno = -sockfd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch(request) {
|
||||
case FIONBIO:
|
||||
va_start(ap, request);
|
||||
value = va_arg(ap, int*);
|
||||
va_end(ap);
|
||||
|
||||
if(value == NULL) {
|
||||
errno = EFAULT;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
flags = fcntl(fd, F_GETFL, 0);
|
||||
if(flags == -1) {
|
||||
errno = SOC_GetErrno();
|
||||
va_end(ap);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(*value) ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
||||
else ret = fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
|
||||
flags = fcntl(sockfd, F_GETFL, 0);
|
||||
if(flags == -1)
|
||||
return -1;
|
||||
|
||||
if(ret != 0)
|
||||
errno = SOC_GetErrno();
|
||||
if(*value)
|
||||
ret = fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
|
||||
else
|
||||
ret = fcntl(sockfd, F_SETFL, flags & ~O_NONBLOCK);
|
||||
|
||||
break;
|
||||
|
||||
@ -42,7 +45,5 @@ int ioctl(int fd, int request, ...)
|
||||
break;
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1,22 +1,37 @@
|
||||
#include "soc_common.h"
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
int listen(int sockfd, int max_connections)
|
||||
{
|
||||
int ret=0;
|
||||
int ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
sockfd = soc_get_fd(sockfd);
|
||||
if(sockfd < 0) {
|
||||
errno = -sockfd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmdbuf[0] = 0x00030082;
|
||||
cmdbuf[1] = (u32)sockfd;
|
||||
cmdbuf[2] = (u32)max_connections;
|
||||
cmdbuf[3] = 0x20;
|
||||
|
||||
if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
if(ret != 0) {
|
||||
errno = SYNC_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret==0)ret = _net_convert_error(cmdbuf[2]);
|
||||
SOCU_errno = ret;
|
||||
if(ret == 0)
|
||||
ret = _net_convert_error(cmdbuf[2]);
|
||||
|
||||
if(ret < 0) {
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(ret!=0)return -1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,35 +1,77 @@
|
||||
#include "soc_common.h"
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int poll(struct pollfd *fds, nfds_t nfsd, int timeout)
|
||||
int poll(struct pollfd *fds, nfds_t nfds, int timeout)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 size = sizeof(struct pollfd)*nfsd;
|
||||
nfds_t i;
|
||||
u32 size = sizeof(struct pollfd)*nfds;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
u32 saved_threadstorage[2];
|
||||
|
||||
if(nfds == 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct pollfd *tmp_fds = (struct pollfd*)malloc(sizeof(struct pollfd) * nfds);
|
||||
if(tmp_fds == NULL) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(tmp_fds, fds, sizeof(struct pollfd) * nfds);
|
||||
|
||||
for(i = 0; i < nfds; ++i) {
|
||||
tmp_fds[i].fd = soc_get_fd(fds[i].fd);
|
||||
if(tmp_fds[i].fd < 0) {
|
||||
errno = -tmp_fds[i].fd;
|
||||
free(tmp_fds);
|
||||
return -1;
|
||||
}
|
||||
tmp_fds[i].revents = 0;
|
||||
}
|
||||
|
||||
cmdbuf[0] = 0x00140084;
|
||||
cmdbuf[1] = (u32)nfsd;
|
||||
cmdbuf[1] = (u32)nfds;
|
||||
cmdbuf[2] = (u32)timeout;
|
||||
cmdbuf[3] = 0x20;
|
||||
cmdbuf[5] = (size<<14) | 0x2802;
|
||||
cmdbuf[6] = (u32)fds;
|
||||
cmdbuf[6] = (u32)tmp_fds;
|
||||
|
||||
saved_threadstorage[0] = cmdbuf[0x100>>2];
|
||||
saved_threadstorage[1] = cmdbuf[0x104>>2];
|
||||
|
||||
cmdbuf[0x100>>2] = (size<<14) | 2;
|
||||
cmdbuf[0x104>>2] = (u32)fds;
|
||||
cmdbuf[0x104>>2] = (u32)tmp_fds;
|
||||
|
||||
if((ret = svcSendSyncRequest(SOCU_handle)) != 0)return ret;
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
if(ret != 0) {
|
||||
free(tmp_fds);
|
||||
errno = SYNC_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
cmdbuf[0x100>>2] = saved_threadstorage[0];
|
||||
cmdbuf[0x104>>2] = saved_threadstorage[1];
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret==0)ret = _net_convert_error(cmdbuf[2]);
|
||||
if(ret<0)SOCU_errno = ret;
|
||||
if(ret == 0)
|
||||
ret = _net_convert_error(cmdbuf[2]);
|
||||
|
||||
if(ret < 0) {
|
||||
free(tmp_fds);
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(i = 0; i < nfds; ++i)
|
||||
fds[i].revents = tmp_fds[i].revents;
|
||||
|
||||
free(tmp_fds);
|
||||
|
||||
if(ret<0)return -1;
|
||||
return ret;
|
||||
}
|
||||
|
@ -1,17 +1,19 @@
|
||||
#include "soc_common.h"
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
ssize_t socuipc_cmd7(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
|
||||
{
|
||||
int ret=0;
|
||||
int ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
u32 tmp_addrlen=0;
|
||||
u32 tmp_addrlen = 0;
|
||||
u8 tmpaddr[0x1c];
|
||||
u32 saved_threadstorage[2];
|
||||
|
||||
memset(tmpaddr, 0, 0x1c);
|
||||
|
||||
if(src_addr)tmp_addrlen = 0x1c;
|
||||
if(src_addr)
|
||||
tmp_addrlen = 0x1c;
|
||||
|
||||
cmdbuf[0] = 0x00070104;
|
||||
cmdbuf[1] = (u32)sockfd;
|
||||
@ -28,35 +30,44 @@ ssize_t socuipc_cmd7(int sockfd, void *buf, size_t len, int flags, struct sockad
|
||||
cmdbuf[0x100>>2] = (tmp_addrlen<<14) | 2;
|
||||
cmdbuf[0x104>>2] = (u32)tmpaddr;
|
||||
|
||||
if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
if(ret != 0) {
|
||||
errno = SYNC_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmdbuf[0x100>>2] = saved_threadstorage[0];
|
||||
cmdbuf[0x104>>2] = saved_threadstorage[1];
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret==0)ret = _net_convert_error(cmdbuf[2]);
|
||||
if(ret<0)SOCU_errno = ret;
|
||||
if(ret == 0)
|
||||
ret = _net_convert_error(cmdbuf[2]);
|
||||
|
||||
if(ret>0 && src_addr!=NULL)
|
||||
{
|
||||
if(ret < 0) {
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(src_addr != NULL) {
|
||||
src_addr->sa_family = tmpaddr[1];
|
||||
if(*addrlen > tmpaddr[0])*addrlen = tmpaddr[0];
|
||||
if(*addrlen > tmpaddr[0])
|
||||
*addrlen = tmpaddr[0];
|
||||
memcpy(src_addr->sa_data, &tmpaddr[2], *addrlen - 2);
|
||||
}
|
||||
|
||||
if(ret<0)return -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t socuipc_cmd8(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
|
||||
{
|
||||
int ret=0;
|
||||
int ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
u32 tmp_addrlen=0;
|
||||
u32 tmp_addrlen = 0;
|
||||
u8 tmpaddr[0x1c];
|
||||
u32 saved_threadstorage[4];
|
||||
|
||||
if(src_addr)tmp_addrlen = 0x1c;
|
||||
if(src_addr)
|
||||
tmp_addrlen = 0x1c;
|
||||
|
||||
memset(tmpaddr, 0, 0x1c);
|
||||
|
||||
@ -77,7 +88,11 @@ ssize_t socuipc_cmd8(int sockfd, void *buf, size_t len, int flags, struct sockad
|
||||
cmdbuf[0x108>>2] = (tmp_addrlen<<14) | 2;
|
||||
cmdbuf[0x10c>>2] = (u32)tmpaddr;
|
||||
|
||||
if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
if(ret != 0) {
|
||||
errno = SYNC_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
cmdbuf[0x100>>2] = saved_threadstorage[0];
|
||||
cmdbuf[0x104>>2] = saved_threadstorage[1];
|
||||
@ -85,23 +100,38 @@ ssize_t socuipc_cmd8(int sockfd, void *buf, size_t len, int flags, struct sockad
|
||||
cmdbuf[0x10c>>2] = saved_threadstorage[3];
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret==0)ret = _net_convert_error(cmdbuf[2]);
|
||||
if(ret<0)SOCU_errno = ret;
|
||||
if(ret == 0)
|
||||
ret = _net_convert_error(cmdbuf[2]);
|
||||
|
||||
if(ret>0 && src_addr!=NULL)
|
||||
{
|
||||
if(ret < 0) {
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(src_addr != NULL) {
|
||||
src_addr->sa_family = tmpaddr[1];
|
||||
if(*addrlen > tmpaddr[0])*addrlen = tmpaddr[0];
|
||||
if(*addrlen > tmpaddr[0])
|
||||
*addrlen = tmpaddr[0];
|
||||
memcpy(src_addr->sa_data, &tmpaddr[2], *addrlen - 2);
|
||||
}
|
||||
|
||||
if(ret<0)return -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t soc_recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
|
||||
{
|
||||
if(len < 0x2000)
|
||||
return socuipc_cmd8(sockfd, buf, len, flags, src_addr, addrlen);
|
||||
return socuipc_cmd7(sockfd, buf, len, flags, src_addr, addrlen);
|
||||
}
|
||||
|
||||
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
|
||||
{
|
||||
if(len<0x2000)return socuipc_cmd8(sockfd, buf, len, flags, src_addr, addrlen);
|
||||
return socuipc_cmd7(sockfd, buf, len, flags, src_addr, addrlen);
|
||||
sockfd = soc_get_fd(sockfd);
|
||||
if(sockfd < 0) {
|
||||
errno = -sockfd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return soc_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struc
|
||||
|
||||
pollinfo = (struct pollfd*)calloc(numfds, sizeof(struct pollfd));
|
||||
if(pollinfo == NULL) {
|
||||
SOCU_errno = ENOMEM;
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -79,7 +79,8 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struc
|
||||
FD_CLR(i, exceptfds);
|
||||
}
|
||||
|
||||
if(found) ++rc;
|
||||
if(found)
|
||||
++rc;
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
@ -4,27 +4,21 @@
|
||||
|
||||
ssize_t socuipc_cmd9(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)
|
||||
{
|
||||
int ret=0;
|
||||
int ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
u32 tmp_addrlen=0;
|
||||
u32 tmp_addrlen = 0;
|
||||
u8 tmpaddr[0x1c];
|
||||
|
||||
memset(tmpaddr, 0, 0x1c);
|
||||
|
||||
if(dest_addr)
|
||||
{
|
||||
if(dest_addr) {
|
||||
if(dest_addr->sa_family == AF_INET)
|
||||
{
|
||||
tmp_addrlen = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp_addrlen = 0x1c;
|
||||
}
|
||||
|
||||
if(addrlen < tmp_addrlen)
|
||||
{
|
||||
SOCU_errno = -EINVAL;
|
||||
if(addrlen < tmp_addrlen) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -44,39 +38,41 @@ ssize_t socuipc_cmd9(int sockfd, const void *buf, size_t len, int flags, const s
|
||||
cmdbuf[9] = (((u32)len)<<4) | 10;
|
||||
cmdbuf[10] = (u32)buf;
|
||||
|
||||
if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
if(ret != 0) {
|
||||
errno = SYNC_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret==0)ret = _net_convert_error(cmdbuf[2]);
|
||||
if(ret<0)SOCU_errno = ret;
|
||||
if(ret == 0)
|
||||
ret = _net_convert_error(cmdbuf[2]);
|
||||
|
||||
if(ret < 0) {
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(ret<0)return -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t socuipc_cmda(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)
|
||||
{
|
||||
int ret=0;
|
||||
int ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
u32 tmp_addrlen=0;
|
||||
u32 tmp_addrlen = 0;
|
||||
u8 tmpaddr[0x1c];
|
||||
|
||||
memset(tmpaddr, 0, 0x1c);
|
||||
|
||||
if(dest_addr)
|
||||
{
|
||||
if(dest_addr) {
|
||||
if(dest_addr->sa_family == AF_INET)
|
||||
{
|
||||
tmp_addrlen = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp_addrlen = 0x1c;
|
||||
}
|
||||
|
||||
if(addrlen < tmp_addrlen)
|
||||
{
|
||||
SOCU_errno = -EINVAL;
|
||||
if(addrlen < tmp_addrlen) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -96,18 +92,38 @@ ssize_t socuipc_cmda(int sockfd, const void *buf, size_t len, int flags, const s
|
||||
cmdbuf[9] = (tmp_addrlen<<14) | 0x402;
|
||||
cmdbuf[10] = (u32)tmpaddr;
|
||||
|
||||
if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
if(ret != 0) {
|
||||
errno = SYNC_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret==0)ret = _net_convert_error(cmdbuf[2]);
|
||||
if(ret<0)SOCU_errno = ret;
|
||||
if(ret == 0)
|
||||
ret = _net_convert_error(cmdbuf[2]);
|
||||
|
||||
if(ret < 0) {
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(ret<0)return -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t soc_sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)
|
||||
{
|
||||
if(len < 0x2000)
|
||||
return socuipc_cmda(sockfd, buf, len, flags, dest_addr, addrlen);
|
||||
return socuipc_cmd9(sockfd, buf, len, flags, dest_addr, addrlen);
|
||||
}
|
||||
|
||||
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)
|
||||
{
|
||||
if(len<0x2000)return socuipc_cmda(sockfd, buf, len, flags, dest_addr, addrlen);
|
||||
return socuipc_cmd9(sockfd, buf, len, flags, (struct sockaddr*)dest_addr, addrlen);
|
||||
sockfd = soc_get_fd(sockfd);
|
||||
if(sockfd < 0) {
|
||||
errno = -sockfd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return soc_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
|
||||
}
|
||||
|
@ -1,11 +1,18 @@
|
||||
#include "soc_common.h"
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen)
|
||||
{
|
||||
int ret=0;
|
||||
int ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
sockfd = soc_get_fd(sockfd);
|
||||
if(sockfd < 0) {
|
||||
errno = -sockfd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmdbuf[0] = 0x00120104;
|
||||
cmdbuf[1] = (u32)sockfd;
|
||||
cmdbuf[2] = (u32)level;
|
||||
@ -15,12 +22,20 @@ int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t
|
||||
cmdbuf[7] = (optlen<<14) | 0x2402;
|
||||
cmdbuf[8] = (u32)optval;
|
||||
|
||||
if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
if(ret != 0) {
|
||||
errno = SYNC_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret==0)ret = _net_convert_error(cmdbuf[2]);
|
||||
if(ret<0)SOCU_errno = ret;
|
||||
if(ret == 0)
|
||||
ret = _net_convert_error(cmdbuf[2]);
|
||||
|
||||
if(ret < 0) {
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(ret<0)return -1;
|
||||
return ret;
|
||||
}
|
||||
|
@ -1,22 +1,37 @@
|
||||
#include "soc_common.h"
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
int shutdown(int sockfd, int shutdown_type)
|
||||
{
|
||||
int ret=0;
|
||||
int ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
sockfd = soc_get_fd(sockfd);
|
||||
if(sockfd < 0) {
|
||||
errno = -sockfd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmdbuf[0] = 0x000C0082;
|
||||
cmdbuf[1] = (u32)sockfd;
|
||||
cmdbuf[2] = (u32)shutdown_type;
|
||||
cmdbuf[3] = 0x20;
|
||||
|
||||
if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
if(ret != 0) {
|
||||
errno = SYNC_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret==0)ret = _net_convert_error(cmdbuf[2]);
|
||||
SOCU_errno = ret;
|
||||
if(ret == 0)
|
||||
ret = _net_convert_error(cmdbuf[2]);
|
||||
|
||||
if(ret < 0) {
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(ret!=0)return -1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,21 +1,36 @@
|
||||
#include "soc_common.h"
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
int sockatmark(int sockfd)
|
||||
{
|
||||
int ret=0;
|
||||
int ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
sockfd = soc_get_fd(sockfd);
|
||||
if(sockfd < 0) {
|
||||
errno = -sockfd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmdbuf[0] = 0x00150042;
|
||||
cmdbuf[1] = (u32)sockfd;
|
||||
cmdbuf[2] = 0x20;
|
||||
|
||||
if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
if(ret != 0) {
|
||||
errno = SYNC_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret==0)ret = _net_convert_error(cmdbuf[2]);
|
||||
if(ret<0)SOCU_errno = ret;
|
||||
if(ret == 0)
|
||||
ret = _net_convert_error(cmdbuf[2]);
|
||||
|
||||
if(ret < 0) {
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(ret<0)return -1;
|
||||
return ret;
|
||||
}
|
||||
|
@ -1,9 +1,13 @@
|
||||
#include "soc_common.h"
|
||||
#include <errno.h>
|
||||
#include <sys/iosupport.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
int socket(int domain, int type, int protocol)
|
||||
{
|
||||
int ret=0;
|
||||
int ret = 0;
|
||||
int fd, dev;
|
||||
__handle *handle;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = 0x000200C2;
|
||||
@ -12,11 +16,37 @@ int socket(int domain, int type, int protocol)
|
||||
cmdbuf[3] = protocol;
|
||||
cmdbuf[4] = 0x20;
|
||||
|
||||
if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
|
||||
dev = FindDevice("soc:");
|
||||
if(dev < 0) {
|
||||
errno = ENODEV;
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = __alloc_handle(sizeof(__handle) + sizeof(Handle));
|
||||
if(fd < 0) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
handle = __get_handle(fd);
|
||||
handle->device = dev;
|
||||
handle->fileStruct = ((void *)handle) + sizeof(__handle);
|
||||
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
if(ret != 0)
|
||||
{
|
||||
__release_handle(fd);
|
||||
errno = SYNC_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
SOCU_errno = ret;
|
||||
if(ret != 0) {
|
||||
__release_handle(fd);
|
||||
errno = _net_convert_error(cmdbuf[2]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(ret!=0)return -1;
|
||||
return _net_convert_error(cmdbuf[2]);
|
||||
*(Handle*)handle->fileStruct = cmdbuf[2];
|
||||
return fd;
|
||||
}
|
||||
|
@ -15,9 +15,6 @@ void __attribute__((weak)) __attribute__((noreturn)) __libctru_exit(int rc)
|
||||
{
|
||||
u32 tmp=0;
|
||||
|
||||
// Run the global destructors
|
||||
__libc_fini_array();
|
||||
|
||||
__appExit();
|
||||
|
||||
// Unmap the linear heap
|
||||
|
@ -12,9 +12,6 @@ void __system_allocateHeaps();
|
||||
void __system_initArgv();
|
||||
void __appInit();
|
||||
|
||||
// newlib definitions we need
|
||||
void __libc_init_array(void);
|
||||
|
||||
|
||||
void __ctru_exit(int rc);
|
||||
|
||||
@ -32,6 +29,4 @@ void __attribute__((weak)) __libctru_init(void (*retAddr)(void))
|
||||
|
||||
__appInit();
|
||||
|
||||
// Run the global constructors
|
||||
__libc_init_array();
|
||||
}
|
||||
|
@ -16,12 +16,14 @@ initSystem:
|
||||
ldr sp, [r2]
|
||||
|
||||
ldr r3, =__stacksize__
|
||||
ldr r3, [r3]
|
||||
ldr r3, [r3]
|
||||
add sp, sp, r3
|
||||
add sp, sp, #7
|
||||
bics sp, sp, #7
|
||||
str sp, [r2]
|
||||
|
||||
bl __libc_init_array
|
||||
|
||||
ldr r2, =saved_stack
|
||||
ldr lr, [r2,#4]
|
||||
bx lr
|
||||
@ -31,6 +33,8 @@ initSystem:
|
||||
.type __ctru_exit, %function
|
||||
|
||||
__ctru_exit:
|
||||
bl __libc_fini_array
|
||||
|
||||
ldr r2, =saved_stack
|
||||
ldr sp, [r2]
|
||||
b __libctru_exit
|
||||
|
25
libctru/source/util/utf/decode_utf16.c
Normal file
25
libctru/source/util/utf/decode_utf16.c
Normal file
@ -0,0 +1,25 @@
|
||||
#include "3ds/util/utf.h"
|
||||
|
||||
ssize_t
|
||||
decode_utf16(uint32_t *out,
|
||||
const uint16_t *in)
|
||||
{
|
||||
uint16_t code1, code2;
|
||||
|
||||
code1 = *in++;
|
||||
if(code1 >= 0xD800 && code1 < 0xDC00)
|
||||
{
|
||||
/* surrogate pair */
|
||||
code2 = *in++;
|
||||
if(code2 >= 0xDC00 && code2 < 0xE000)
|
||||
{
|
||||
*out = (code1 << 10) + code2 - 0x35FDC00;
|
||||
return 2;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
*out = code1;
|
||||
return 1;
|
||||
}
|
88
libctru/source/util/utf/decode_utf8.c
Normal file
88
libctru/source/util/utf/decode_utf8.c
Normal file
@ -0,0 +1,88 @@
|
||||
#include "3ds/util/utf.h"
|
||||
|
||||
ssize_t
|
||||
decode_utf8(uint32_t *out,
|
||||
const uint8_t *in)
|
||||
{
|
||||
uint8_t code1, code2, code3, code4;
|
||||
|
||||
code1 = *in++;
|
||||
if(code1 < 0x80)
|
||||
{
|
||||
/* 1-byte sequence */
|
||||
*out = code1;
|
||||
return 1;
|
||||
}
|
||||
else if(code1 < 0xC2)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if(code1 < 0xE0)
|
||||
{
|
||||
/* 2-byte sequence */
|
||||
code2 = *in++;
|
||||
if((code2 & 0xC0) != 0x80)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
*out = (code1 << 6) + code2 - 0x3080;
|
||||
return 2;
|
||||
}
|
||||
else if(code1 < 0xF0)
|
||||
{
|
||||
/* 3-byte sequence */
|
||||
code2 = *in++;
|
||||
if((code2 & 0xC0) != 0x80)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if(code1 == 0xE0 && code2 < 0xA0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
code3 = *in++;
|
||||
if((code3 & 0xC0) != 0x80)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
*out = (code1 << 12) + (code2 << 6) + code3 - 0xE2080;
|
||||
return 3;
|
||||
}
|
||||
else if(code1 < 0xF5)
|
||||
{
|
||||
/* 4-byte sequence */
|
||||
code2 = *in++;
|
||||
if((code2 & 0xC0) != 0x80)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if(code1 == 0xF0 && code2 < 0x90)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if(code1 == 0xF4 && code2 >= 0x90)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
code3 = *in++;
|
||||
if((code3 & 0xC0) != 0x80)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
code4 = *in++;
|
||||
if((code4 & 0xC0) != 0x80)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
*out = (code1 << 18) + (code2 << 12) + (code3 << 6) + code4 - 0x3C82080;
|
||||
return 4;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
24
libctru/source/util/utf/encode_utf16.c
Normal file
24
libctru/source/util/utf/encode_utf16.c
Normal file
@ -0,0 +1,24 @@
|
||||
#include "3ds/util/utf.h"
|
||||
|
||||
ssize_t
|
||||
encode_utf16(uint16_t *out,
|
||||
uint32_t in)
|
||||
{
|
||||
if(in < 0x10000)
|
||||
{
|
||||
if(out != NULL)
|
||||
*out++ = in;
|
||||
return 1;
|
||||
}
|
||||
else if(in < 0x110000)
|
||||
{
|
||||
if(out != NULL)
|
||||
{
|
||||
*out++ = (in >> 10) + 0xD7C0;
|
||||
*out++ = (in & 0x3FF) + 0xDC00;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
45
libctru/source/util/utf/encode_utf8.c
Normal file
45
libctru/source/util/utf/encode_utf8.c
Normal file
@ -0,0 +1,45 @@
|
||||
#include "3ds/util/utf.h"
|
||||
|
||||
ssize_t
|
||||
encode_utf8(uint8_t *out,
|
||||
uint32_t in)
|
||||
{
|
||||
if(in < 0x80)
|
||||
{
|
||||
if(out != NULL)
|
||||
*out++ = in;
|
||||
return 1;
|
||||
}
|
||||
else if(in < 0x800)
|
||||
{
|
||||
if(out != NULL)
|
||||
{
|
||||
*out++ = (in >> 6) + 0xC0;
|
||||
*out++ = (in & 0x3F) + 0x80;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
else if(in < 0x10000)
|
||||
{
|
||||
if(out != NULL)
|
||||
{
|
||||
*out++ = (in >> 12) + 0xE0;
|
||||
*out++ = ((in >> 6) & 0x3F) + 0x80;
|
||||
*out++ = (in & 0x3F) + 0x80;
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
else if(in < 0x110000)
|
||||
{
|
||||
if(out != NULL)
|
||||
{
|
||||
*out++ = (in >> 18) + 0xF0;
|
||||
*out++ = ((in >> 12) & 0x3F) + 0x80;
|
||||
*out++ = ((in >> 6) & 0x3F) + 0x80;
|
||||
*out++ = (in & 0x3F) + 0x80;
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
35
libctru/source/util/utf/utf16_to_utf32.c
Normal file
35
libctru/source/util/utf/utf16_to_utf32.c
Normal file
@ -0,0 +1,35 @@
|
||||
#include "3ds/util/utf.h"
|
||||
|
||||
size_t
|
||||
utf16_to_utf32(uint32_t *out,
|
||||
const uint16_t *in,
|
||||
size_t len)
|
||||
{
|
||||
size_t rc = 0;
|
||||
ssize_t units;
|
||||
uint32_t code;
|
||||
|
||||
do
|
||||
{
|
||||
units = decode_utf16(&code, in);
|
||||
if(units == -1)
|
||||
return (size_t)-1;
|
||||
|
||||
if(code > 0)
|
||||
{
|
||||
in += units;
|
||||
|
||||
if(out != NULL)
|
||||
{
|
||||
if(rc < len)
|
||||
*out++ = code;
|
||||
else
|
||||
return rc;
|
||||
}
|
||||
|
||||
++rc;
|
||||
}
|
||||
} while(code > 0);
|
||||
|
||||
return rc;
|
||||
}
|
48
libctru/source/util/utf/utf16_to_utf8.c
Normal file
48
libctru/source/util/utf/utf16_to_utf8.c
Normal file
@ -0,0 +1,48 @@
|
||||
#include "3ds/util/utf.h"
|
||||
|
||||
size_t
|
||||
utf16_to_utf8(uint8_t *out,
|
||||
const uint16_t *in,
|
||||
size_t len)
|
||||
{
|
||||
size_t rc = 0;
|
||||
ssize_t units;
|
||||
uint32_t code;
|
||||
uint8_t encoded[4];
|
||||
|
||||
do
|
||||
{
|
||||
units = decode_utf16(&code, in);
|
||||
if(units == -1)
|
||||
return (size_t)-1;
|
||||
|
||||
if(code > 0)
|
||||
{
|
||||
in += units;
|
||||
|
||||
units = encode_utf8(encoded, code);
|
||||
if(units == -1)
|
||||
return (size_t)-1;
|
||||
|
||||
if(out != NULL)
|
||||
{
|
||||
if(rc + units <= len)
|
||||
{
|
||||
*out++ = encoded[0];
|
||||
if(units > 1)
|
||||
*out++ = encoded[1];
|
||||
if(units > 2)
|
||||
*out++ = encoded[2];
|
||||
if(units > 3)
|
||||
*out++ = encoded[3];
|
||||
}
|
||||
else
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc += units;
|
||||
}
|
||||
} while(code > 0);
|
||||
|
||||
return rc;
|
||||
}
|
34
libctru/source/util/utf/utf32_to_utf16.c
Normal file
34
libctru/source/util/utf/utf32_to_utf16.c
Normal file
@ -0,0 +1,34 @@
|
||||
#include "3ds/util/utf.h"
|
||||
|
||||
size_t
|
||||
utf32_to_utf16(uint16_t *out,
|
||||
const uint32_t *in,
|
||||
size_t len)
|
||||
{
|
||||
size_t rc = 0;
|
||||
ssize_t units;
|
||||
uint16_t encoded[2];
|
||||
|
||||
while(*in > 0)
|
||||
{
|
||||
units = encode_utf16(encoded, *in++);
|
||||
if(units == -1)
|
||||
return (size_t)-1;
|
||||
|
||||
if(out != NULL)
|
||||
{
|
||||
if(rc + units <= len)
|
||||
{
|
||||
*out++ = encoded[0];
|
||||
if(units > 1)
|
||||
*out++ = encoded[1];
|
||||
}
|
||||
else
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc += units;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user