Merge branch 'master' into gpu_revamp

This commit is contained in:
Dave Murphy 2015-02-19 18:35:10 +00:00
commit b40d605660
103 changed files with 5389 additions and 779 deletions

26
examples/Makefile Normal file
View 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 *

View 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 \
@ -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:

View File

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

View File

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

View 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 \
@ -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:

View File

@ -6,7 +6,7 @@
int main(int argc, char** argv)
{
// Initialize services
gfxInit();
gfxInitDefault();
initCfgu();

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

View File

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

View File

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

View 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;

View 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
#---------------------------------------------------------------------------------------

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

View 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;
}

View 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;

View 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 \
@ -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:

View File

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

View 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 \
@ -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:

View File

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

View 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 \

View 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;
}

View 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 \
@ -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:

View File

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

View 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 \
@ -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:

View File

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

View 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 \
@ -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:

View File

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

View 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 \
@ -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:

View File

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

View 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;

View 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 \
@ -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:

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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);

View File

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

File diff suppressed because it is too large Load Diff

2
libctru/libctru.cppcheck Normal file
View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="1"/>

View File

@ -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 = &currentCopy;
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);

View File

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

View File

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

View File

@ -380,7 +380,7 @@ static bool __handle_incoming_parameter() {
return true;
}
void aptEventHandler(u32 arg)
void aptEventHandler(void *arg)
{
bool runThread = true;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 */
}

View File

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

View File

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

View File

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

View File

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

View File

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

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

View 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";
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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