Merge branch 'master' of github.com:smealum/ctrulib
This commit is contained in:
commit
1322d44f22
@ -13,9 +13,9 @@ setup
|
||||
|
||||
ctrulib is just a library and needs a toolchain to function. we built ctrulib to be used in conjunction with devkitARM. you may find instructions on how to install devkitARM here : http://devkitpro.org/wiki/Getting_Started
|
||||
|
||||
once devkitARM is installed, you will need to manually patch it with the following : http://mtheall.com/~fincs/3dsdkA/
|
||||
The most recent devkitARM (r43) includes 3DS support and a prebuilt libctru.
|
||||
|
||||
that done, just checkout ctrulib, build it, set your CTRULIB path and you should be good to go !
|
||||
To keep up to date with the most recent changes you'll want to checkout ctrulib, build it and install it.
|
||||
|
||||
license
|
||||
=======
|
||||
|
@ -6,11 +6,6 @@ ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(CTRULIB)),)
|
||||
# THIS IS TEMPORARY - in the future it should be at $(DEVKITPRO)/libctru
|
||||
$(error "Please set CTRULIB in your environment. export CTRULIB=<path to>libctru")
|
||||
endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
include $(DEVKITARM)/3ds_rules
|
||||
|
||||
|
@ -6,11 +6,6 @@ ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(CTRULIB)),)
|
||||
# THIS IS TEMPORARY - in the future it should be at $(DEVKITPRO)/libctru
|
||||
$(error "Please set CTRULIB in your environment. export CTRULIB=<path to>libctru")
|
||||
endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
include $(DEVKITARM)/3ds_rules
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <3ds.h>
|
||||
|
||||
@ -167,8 +168,8 @@ void renderFrame()
|
||||
|
||||
//setup lighting (this is specific to our shader)
|
||||
vect3Df_s lightDir=vnormf(vect3Df(cos(lightAngle), -1.0f, sin(lightAngle)));
|
||||
GPU_SetUniform(SHDR_GetUniformRegister(shader, "lightDirection", 0), (u32*)(float[]){0.0f, -lightDir.z, -lightDir.y, -lightDir.x}, 4);
|
||||
GPU_SetUniform(SHDR_GetUniformRegister(shader, "lightAmbient", 0), (u32*)(float[]){0.7f, 0.4f, 0.4f, 0.4f}, 4);
|
||||
GPU_SetUniform(SHDR_GetUniformRegister(shader, "lightDirection", 0), (u32*)(float[]){0.0f, -lightDir.z, -lightDir.y, -lightDir.x}, 1);
|
||||
GPU_SetUniform(SHDR_GetUniformRegister(shader, "lightAmbient", 0), (u32*)(float[]){0.7f, 0.4f, 0.4f, 0.4f}, 1);
|
||||
|
||||
//initialize projection matrix to standard perspective stuff
|
||||
gsMatrixMode(GS_PROJECTION);
|
||||
|
170
examples/http/Makefile
Normal file
170
examples/http/Makefile
Normal file
@ -0,0 +1,170 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
include $(DEVKITARM)/3ds_rules
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# DATA is a list of directories containing data files
|
||||
# INCLUDES is a list of directories containing header files
|
||||
#
|
||||
# NO_SMDH: if set to anything, no SMDH file is generated.
|
||||
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
|
||||
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
|
||||
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
|
||||
# ICON is the filename of the icon (.png), relative to the project folder.
|
||||
# If not set, it attempts to use one of the following (in this order):
|
||||
# - <Project name>.png
|
||||
# - icon.png
|
||||
# - <libctru folder>/default_icon.png
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := $(notdir $(CURDIR))
|
||||
BUILD := build
|
||||
SOURCES := source
|
||||
DATA := data
|
||||
INCLUDES := include
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=softfp
|
||||
|
||||
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
|
||||
#---------------------------------------------------------------------------------------
|
4
examples/http/README.md
Normal file
4
examples/http/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# http
|
||||
|
||||
This is an example for using HTTPC. This downloads a raw image for displaying on the top-screen. The URL used here is a LAN-only one, hence this URL must be changed before building+running this example.
|
||||
|
131
examples/http/source/main.c
Normal file
131
examples/http/source/main.c
Normal file
@ -0,0 +1,131 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.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;
|
||||
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;
|
||||
|
||||
ret = httpcGetResponseStatusCode(context, &statuscode, 0);
|
||||
if(ret!=0)return ret;
|
||||
|
||||
if(statuscode!=200)return -2;
|
||||
|
||||
ret=httpcGetDownloadSizeState(context, NULL, &contentsize);
|
||||
if(ret!=0)return ret;
|
||||
|
||||
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)
|
||||
{
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
size = contentsize;
|
||||
if(size>(240*400*3))size = 240*400*3;
|
||||
|
||||
memset(framebuf_bottom, 0xff, 240*320*3);
|
||||
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();
|
||||
gfxSwapBuffers();
|
||||
gspWaitForVBlank();
|
||||
|
||||
free(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
Result ret=0;
|
||||
httpcContext context;
|
||||
|
||||
// Initialize services
|
||||
srvInit();
|
||||
aptInit();
|
||||
hidInit(NULL);
|
||||
gfxInit();
|
||||
//gfxSet3D(true); // uncomment if using stereoscopic 3D
|
||||
httpcInit();
|
||||
|
||||
ret = httpcOpenContext(&context, "http://10.0.0.3/httpexample_rawimg.bin", 0);//Change this to your own URL.
|
||||
|
||||
if(ret==0)
|
||||
{
|
||||
ret=http_download(&context);
|
||||
httpcCloseContext(&context);
|
||||
}
|
||||
|
||||
// Main loop
|
||||
while (aptMainLoop())
|
||||
{
|
||||
gspWaitForVBlank();
|
||||
hidScanInput();
|
||||
|
||||
// Your code goes here
|
||||
|
||||
u32 kDown = hidKeysDown();
|
||||
if (kDown & KEY_START)
|
||||
break; // break in order to return to hbmenu
|
||||
|
||||
// Flush and swap framebuffers
|
||||
gfxFlushBuffers();
|
||||
gfxSwapBuffers();
|
||||
}
|
||||
|
||||
// Exit services
|
||||
httpcExit();
|
||||
gfxExit();
|
||||
hidExit();
|
||||
aptExit();
|
||||
srvExit();
|
||||
return 0;
|
||||
}
|
||||
|
170
examples/libapplet_launch/Makefile
Normal file
170
examples/libapplet_launch/Makefile
Normal file
@ -0,0 +1,170 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
include $(DEVKITARM)/3ds_rules
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# DATA is a list of directories containing data files
|
||||
# INCLUDES is a list of directories containing header files
|
||||
#
|
||||
# NO_SMDH: if set to anything, no SMDH file is generated.
|
||||
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
|
||||
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
|
||||
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
|
||||
# ICON is the filename of the icon (.png), relative to the project folder.
|
||||
# If not set, it attempts to use one of the following (in this order):
|
||||
# - <Project name>.png
|
||||
# - icon.png
|
||||
# - <libctru folder>/default_icon.png
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := $(notdir $(CURDIR))
|
||||
BUILD := build
|
||||
SOURCES := source
|
||||
DATA := data
|
||||
INCLUDES := include
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=softfp
|
||||
|
||||
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
|
||||
#---------------------------------------------------------------------------------------
|
7
examples/libapplet_launch/README.md
Normal file
7
examples/libapplet_launch/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
libapplet_launch
|
||||
=======
|
||||
|
||||
Example for launching library applets. This launches the extrapad library applet(Circle Pad Pro calibration applet) when the B button is pressed.
|
||||
|
||||
This is not usable from the homebrew launcher.
|
||||
|
50
examples/libapplet_launch/source/main.c
Normal file
50
examples/libapplet_launch/source/main.c
Normal file
@ -0,0 +1,50 @@
|
||||
#include <3ds.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
u32 val, i;
|
||||
|
||||
// Initialize services
|
||||
srvInit();
|
||||
aptInit();
|
||||
hidInit(NULL);
|
||||
gfxInit();
|
||||
//gfxSet3D(true); // uncomment if using stereoscopic 3D
|
||||
|
||||
val = 0x22447899;
|
||||
|
||||
// Main loop
|
||||
while (aptMainLoop())
|
||||
{
|
||||
gspWaitForVBlank();
|
||||
hidScanInput();
|
||||
|
||||
// Your code goes here
|
||||
|
||||
u32 kDown = hidKeysDown();
|
||||
if (kDown & KEY_START)
|
||||
break; // break in order to return to hbmenu
|
||||
|
||||
if (kDown & KEY_B)APT_LaunchLibraryApplet(0x408, 0, NULL, 0);//Launch the extrapad library applet when button B is pressed.
|
||||
|
||||
// Example rendering code that displays a white pixel
|
||||
// Please note that the 3DS screens are sideways (thus 240x400 and 240x320)
|
||||
u32* fb = (u32*)gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL);
|
||||
|
||||
for(i=0; i<(0x46500>>2); i++)fb[i] = val;
|
||||
|
||||
val+= 0x44;
|
||||
|
||||
// Flush and swap framebuffers
|
||||
gfxFlushBuffers();
|
||||
gfxSwapBuffers();
|
||||
}
|
||||
|
||||
// Exit services
|
||||
gfxExit();
|
||||
hidExit();
|
||||
aptExit();
|
||||
srvExit();
|
||||
return 0;
|
||||
}
|
||||
|
@ -6,11 +6,6 @@ ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(CTRULIB)),)
|
||||
# THIS IS TEMPORARY - in the future it should be at $(DEVKITPRO)/libctru
|
||||
$(error "Please set CTRULIB in your environment. export CTRULIB=<path to>libctru")
|
||||
endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
include $(DEVKITARM)/3ds_rules
|
||||
|
||||
|
@ -11,13 +11,14 @@ int main()
|
||||
u8 *audiobuf;
|
||||
u32 audiobuf_size = 0x100000, audiobuf_pos = 0;
|
||||
u8 control=0x40;
|
||||
u32 audio_initialized = 0;
|
||||
|
||||
srvInit();
|
||||
aptInit();
|
||||
gfxInit();
|
||||
hidInit(NULL);
|
||||
|
||||
CSND_initialize(NULL);
|
||||
if(CSND_initialize(NULL)==0)audio_initialized = 1;
|
||||
|
||||
sharedmem = (u32*)memalign(0x1000, sharedmem_size);
|
||||
audiobuf = linearAlloc(audiobuf_size);
|
||||
@ -26,10 +27,18 @@ int main()
|
||||
|
||||
while(aptMainLoop())
|
||||
{
|
||||
framebuf = gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL);
|
||||
hidScanInput();
|
||||
gspWaitForVBlank();
|
||||
|
||||
if(hidKeysDown() & KEY_A)
|
||||
u32 kDown = hidKeysDown();
|
||||
if (kDown & KEY_START)
|
||||
break; // break in order to return to hbmenu
|
||||
|
||||
if(audio_initialized)
|
||||
{
|
||||
framebuf = gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL);
|
||||
|
||||
if(kDown & KEY_A)
|
||||
{
|
||||
audiobuf_pos = 0;
|
||||
|
||||
@ -63,15 +72,18 @@ int main()
|
||||
framebuf = gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL);
|
||||
memset(framebuf, 0xe0, 0x46500);
|
||||
}
|
||||
}
|
||||
|
||||
gfxFlushBuffers();
|
||||
gfxSwapBuffers();
|
||||
gspWaitForVBlank();
|
||||
}
|
||||
|
||||
MIC_Shutdown();
|
||||
|
||||
CSND_shutdown();
|
||||
if(audio_initialized)CSND_shutdown();
|
||||
|
||||
free(sharedmem);
|
||||
linearFree(audiobuf);
|
||||
|
||||
hidExit();
|
||||
gfxExit();
|
||||
|
@ -6,11 +6,6 @@ ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(CTRULIB)),)
|
||||
# THIS IS TEMPORARY - in the future it should be at $(DEVKITPRO)/libctru
|
||||
$(error "Please set CTRULIB in your environment. export CTRULIB=<path to>libctru")
|
||||
endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
include $(DEVKITARM)/3ds_rules
|
||||
|
||||
|
@ -1,4 +1,6 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <3ds.h>
|
||||
|
||||
#include "costable.h"
|
||||
|
@ -6,11 +6,6 @@ ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(CTRULIB)),)
|
||||
# THIS IS TEMPORARY - in the future it should be at $(DEVKITPRO)/libctru
|
||||
$(error "Please set CTRULIB in your environment. export CTRULIB=<path to>libctru")
|
||||
endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
include $(DEVKITARM)/3ds_rules
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
//this example shows you how to load a binary image file from the SD card and display it on the lower screen
|
||||
//for this to work you should copy test.bin to the root of your SD card
|
||||
//this file was generated with GIMP by saving a 240x320 image to raw RGB
|
||||
#include <string.h>
|
||||
|
||||
#include <3ds.h>
|
||||
#include "costable.h"
|
||||
@ -100,6 +101,7 @@ int main(int argc, char** argv)
|
||||
//closing all handles is super important
|
||||
svcCloseHandle(fileHandle);
|
||||
//closing all services even more so
|
||||
fsExit();
|
||||
gfxExit();
|
||||
hidExit();
|
||||
aptExit();
|
||||
|
@ -9,7 +9,7 @@ endif
|
||||
include $(DEVKITARM)/base_rules
|
||||
|
||||
export LIBCTRU_MAJOR := 0
|
||||
export LIBCTRU_MINOR := 1
|
||||
export LIBCTRU_MINOR := 2
|
||||
export LIBCTRU_PATCH := 0
|
||||
|
||||
|
||||
@ -105,6 +105,8 @@ dist-bin: all
|
||||
dist-src:
|
||||
@tar -cjf libctru-src-$(VERSION).tar.bz2 include source Makefile Doxyfile Doxyfile.internal default_icon.png
|
||||
|
||||
dist: dist-src dist-bin
|
||||
|
||||
install: dist-bin
|
||||
mkdir -p $(DEVKITPRO)/libctru
|
||||
bzip2 -cd libctru-$(VERSION).tar.bz2 | tar -x -C $(DEVKITPRO)/libctru
|
||||
|
@ -15,6 +15,7 @@ extern "C" {
|
||||
#include <3ds/services/ac.h>
|
||||
#include <3ds/services/apt.h>
|
||||
#include <3ds/services/cfgnor.h>
|
||||
#include <3ds/services/cfgu.h>
|
||||
#include <3ds/services/csnd.h>
|
||||
#include <3ds/services/fs.h>
|
||||
#include <3ds/services/gsp.h>
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include <3ds/types.h>
|
||||
#include <3ds/services/gsp.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@ -20,6 +21,8 @@ void gfxExit();
|
||||
|
||||
//control stuff
|
||||
void gfxSet3D(bool enable);
|
||||
void gfxSetScreenFormat(gfxScreen_t screen, GSP_FramebufferFormats format);
|
||||
void gfxSetDoubleBuffering(bool doubleBuffering);
|
||||
void gfxFlushBuffers();
|
||||
void gfxSwapBuffers();
|
||||
void gfxSwapBuffersGpu();
|
||||
|
@ -59,7 +59,7 @@ typedef struct{
|
||||
DVLB_s* SHDR_ParseSHBIN(u32* shbinData, u32 shbinSize);
|
||||
void SHDR_UseProgram(DVLB_s* dvlb, u8 id);
|
||||
void SHDR_FreeDVLB(DVLB_s* dvlb);
|
||||
s8 SHDR_GetUniformRegister(DVLB_s* dvlb, char* name, u8 programID);
|
||||
s8 SHDR_GetUniformRegister(DVLB_s* dvlb, const char* name, u8 programID);
|
||||
|
||||
void DVLP_SendCode(DVLP_s* dvlp);
|
||||
void DVLP_SendOpDesc(DVLP_s* dvlp);
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
// Functions for allocating/deallocating memory from linear heap
|
||||
void* linearAlloc(size_t size); // returns a 16-byte aligned address
|
||||
void* linearMemAlign(size_t size, size_t alignment); // WARNING: wastes 'alignment' bytes
|
||||
void* linearMemAlign(size_t size, size_t alignment);
|
||||
void* linearRealloc(void* mem, size_t size); // not implemented yet
|
||||
void linearFree(void* mem);
|
||||
u32 linearSpaceFree(); // get free linear space in bytes
|
||||
|
@ -17,7 +17,9 @@ typedef enum{
|
||||
APP_EXITING,
|
||||
APP_SUSPENDING,
|
||||
APP_SLEEPMODE,
|
||||
APP_PREPARE_SLEEPMODE
|
||||
APP_PREPARE_SLEEPMODE,
|
||||
APP_APPLETSTARTED,
|
||||
APP_APPLETCLOSED
|
||||
}APP_STATUS;
|
||||
|
||||
enum {
|
||||
@ -58,6 +60,7 @@ Result APT_Enable(Handle* handle, u32 a);
|
||||
Result APT_GetAppletManInfo(Handle* handle, u8 inval, u8 *outval8, u32 *outval32, NS_APPID *menu_appid, NS_APPID *active_appid);
|
||||
Result APT_PrepareToJumpToHomeMenu(Handle* handle);
|
||||
Result APT_JumpToHomeMenu(Handle* handle, u32 a, u32 b, u32 c);
|
||||
Result APT_IsRegistered(Handle* handle, NS_APPID appID, u8* out);
|
||||
Result APT_InquireNotification(Handle* handle, u32 appID, u8* signalType);
|
||||
Result APT_NotifyToWait(Handle* handle, NS_APPID appID);
|
||||
Result APT_AppletUtility(Handle* handle, u32* out, u32 a, u32 size1, u8* buf1, u32 size2, u8* buf2);
|
||||
@ -76,4 +79,7 @@ Result APT_CheckNew3DS_System(Handle* handle, u8 *out);
|
||||
Result APT_CheckNew3DS(Handle* handle, u8 *out);
|
||||
Result APT_PrepareToDoAppJump(Handle* handle, u8 flags, u64 programID, u8 mediatype);
|
||||
Result APT_DoAppJump(Handle* handle, u32 NSbuf0Size, u32 NSbuf1Size, u8 *NSbuf0Ptr, u8 *NSbuf1Ptr);
|
||||
Result APT_PrepareToStartLibraryApplet(Handle* handle, NS_APPID appID);
|
||||
Result APT_StartLibraryApplet(Handle* handle, NS_APPID appID, Handle inhandle, u32 *parambuf, u32 parambufsize);
|
||||
Result APT_LaunchLibraryApplet(NS_APPID appID, Handle inhandle, u32 *parambuf, u32 parambufsize);//This should be used for launching library applets, this uses the above APT_StartLibraryApplet/APT_PrepareToStartLibraryApplet funcs + apt*Session(). parambuf is used for APT params input, when the applet closes the output param block is copied here. This is not usable from the homebrew launcher. This is broken: when the applet does get launched at all, the applet process doesn't actually get terminated when the applet gets closed.
|
||||
|
||||
|
10
libctru/include/3ds/services/cfgu.h
Normal file
10
libctru/include/3ds/services/cfgu.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
Result initCfgu(void);
|
||||
Result exitCfgu(void);
|
||||
|
||||
Result CFGU_GetRegionCanadaUSA(u8* value);
|
||||
Result CFGU_GetSystemModel(u8* model);
|
||||
Result CFGU_GetModelNintendo2DS(u8* value);
|
||||
Result CFGU_GetCountryCodeString(u16 code, u16* string);
|
||||
Result CFGU_GetCountryCodeID(u16 string, u16* code);
|
@ -1,5 +1,4 @@
|
||||
#pragma once
|
||||
#include <string.h>
|
||||
#include <3ds/types.h>
|
||||
|
||||
/*! @file FS.h
|
||||
@ -128,25 +127,11 @@ typedef struct
|
||||
u64 fileSize; //!< file size
|
||||
} FS_dirent;
|
||||
|
||||
/*! Create an FS_path from a type and data pointer.
|
||||
*
|
||||
* @param[in] type Path type.
|
||||
* @param[in] path Pointer to path data.
|
||||
*
|
||||
* @returns FS_path
|
||||
*
|
||||
* @sa FS_pathType
|
||||
*/
|
||||
static inline FS_path
|
||||
FS_makePath(FS_pathType type,
|
||||
const char *path)
|
||||
{
|
||||
return (FS_path){type, strlen(path)+1, (const u8*)path};
|
||||
}
|
||||
|
||||
Result fsInit(void);
|
||||
Result fsExit(void);
|
||||
|
||||
FS_path FS_makePath(FS_pathType type, const char *path);
|
||||
|
||||
Result FSUSER_Initialize(Handle* handle);
|
||||
Result FSUSER_OpenArchive(Handle* handle, FS_archive* archive);
|
||||
Result FSUSER_OpenDirectory(Handle* handle, Handle* out, FS_archive archive, FS_path dirLowPath);
|
||||
@ -156,9 +141,11 @@ Result FSUSER_CloseArchive(Handle* handle, FS_archive* archive);
|
||||
Result FSUSER_CreateDirectory(Handle* handle, FS_archive archive, FS_path dirLowPath);
|
||||
Result FSUSER_DeleteFile(Handle *handle, FS_archive archive, FS_path fileLowPath);
|
||||
Result FSUSER_DeleteDirectory(Handle *handle, FS_archive archive, FS_path dirLowPath);
|
||||
Result FSUSER_RenameFile(Handle *handle, FS_archive srcArchive, FS_path srcFileLowPath, FS_archive destArchive, FS_path destFileLowPath);
|
||||
Result FSUSER_RenameDirectory(Handle *handle, FS_archive srcArchive, FS_path srcDirLowPath, FS_archive destArchive, FS_path destDirLowPath);
|
||||
Result FSUSER_GetSdmcArchiveResource(Handle *handle, u32 *sectorSize, u32 *clusterSize, u32 *numClusters, u32 *freeClusters);
|
||||
Result FSUSER_IsSdmcDetected(Handle *handle, u32 *detected);
|
||||
Result FSUSER_IsSdmcWritable(Handle *handle, u32 *writable);
|
||||
Result FSUSER_IsSdmcDetected(Handle *handle, u8 *detected);
|
||||
Result FSUSER_IsSdmcWritable(Handle *handle, u8 *writable);
|
||||
|
||||
Result FSFILE_Close(Handle handle);
|
||||
Result FSFILE_Read(Handle handle, u32 *bytesRead, u64 offset, void *buffer, u32 size);
|
||||
|
@ -15,11 +15,11 @@ typedef struct
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GSP_RGBA8_OES=0,
|
||||
GSP_BGR8_OES=1,
|
||||
GSP_RGB565_OES=2,
|
||||
GSP_RGB5_A1_OES=3,
|
||||
GSP_RGBA4_OES=4
|
||||
GSP_RGBA8_OES=0, //pixel_size = 4-bytes
|
||||
GSP_BGR8_OES=1, //pixel_size = 3-bytes
|
||||
GSP_RGB565_OES=2, //pixel_size = 2-bytes
|
||||
GSP_RGB5_A1_OES=3, //pixel_size = 2-bytes
|
||||
GSP_RGBA4_OES=4 //pixel_size = 2-bytes
|
||||
}GSP_FramebufferFormats;
|
||||
|
||||
typedef struct//See this for GSP_CaptureInfoEntry and GSP_CaptureInfo: http://3dbrew.org/wiki/GSPGPU:ImportDisplayCaptureInfo
|
||||
|
@ -1,5 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
typedef struct {
|
||||
Handle servhandle;
|
||||
u32 httphandle;
|
||||
} httpcContext;
|
||||
|
||||
typedef enum{
|
||||
HTTPCREQSTAT_INPROGRESS_REQSENT = 0x5,
|
||||
HTTPCREQSTAT_DLREADY = 0x7
|
||||
} httpcReqStatus;
|
||||
|
||||
#define HTTPC_RESULTCODE_DOWNLOADPENDING 0xd840a02b
|
||||
|
||||
Result httpcInit();
|
||||
void httpcExit();
|
||||
|
||||
Result httpcOpenContext(httpcContext *context, char* url, u32 use_defaultproxy);//use_defaultproxy should be zero normally, unless you don't want HTTPC_SetProxyDefault() to be used automatically.
|
||||
Result httpcCloseContext(httpcContext *context);
|
||||
Result httpcBeginRequest(httpcContext *context);
|
||||
Result httpcReceiveData(httpcContext *context, u8* buffer, u32 size);
|
||||
Result httpcGetRequestState(httpcContext *context, httpcReqStatus* out);
|
||||
Result httpcGetDownloadSizeState(httpcContext *context, u32* downloadedsize, u32* contentsize);
|
||||
Result httpcGetResponseStatusCode(httpcContext *context, u32* out, u64 delay);//delay isn't used yet. This writes the HTTP status code from the server to out.
|
||||
|
||||
Result httpcDownloadData(httpcContext *context, u8* buffer, u32 size, u32 *downloadedsize);//The *entire* content must be downloaded before using httpcCloseContext(), otherwise httpcCloseContext() will hang.
|
||||
|
||||
//Using the below functions directly is not recommended, use the above functions. See also the http example.
|
||||
|
||||
Result HTTPC_Initialize(Handle handle);
|
||||
Result HTTPC_InitializeConnectionSession(Handle handle, Handle contextHandle);
|
||||
Result HTTPC_CreateContext(Handle handle, char* url, Handle* contextHandle);
|
||||
@ -8,3 +35,7 @@ Result HTTPC_SetProxyDefault(Handle handle, Handle contextHandle);
|
||||
Result HTTPC_AddRequestHeaderField(Handle handle, Handle contextHandle, char* name, char* value);
|
||||
Result HTTPC_BeginRequest(Handle handle, Handle contextHandle);
|
||||
Result HTTPC_ReceiveData(Handle handle, Handle contextHandle, u8* buffer, u32 size);
|
||||
Result HTTPC_GetRequestState(Handle handle, Handle contextHandle, httpcReqStatus* out);
|
||||
Result HTTPC_GetDownloadSizeState(Handle handle, Handle contextHandle, u32* downloadedsize, u32* contentsize);
|
||||
Result HTTPC_GetResponseStatusCode(Handle handle, Handle contextHandle, u32* out);
|
||||
|
||||
|
@ -3,5 +3,8 @@
|
||||
Result ptmInit();
|
||||
Result ptmExit();
|
||||
|
||||
Result PTMU_GetShellState(Handle* servhandle, u8 *out);
|
||||
Result PTMU_GetBatteryLevel(Handle* servhandle, u8 *out);
|
||||
Result PTMU_GetBatteryChargeState(Handle* servhandle, u8 *out);
|
||||
Result PTMU_GetPedometerState(Handle* servhandle, u8 *out);
|
||||
Result PTMU_GetTotalStepCount(Handle* servhandle, u32 *steps);
|
||||
|
@ -2,8 +2,7 @@
|
||||
svc.h _ Syscall wrappers.
|
||||
*/
|
||||
|
||||
#ifndef SVC_H
|
||||
#define SVC_H
|
||||
#pragma once
|
||||
|
||||
typedef enum {
|
||||
MEMOP_FREE =1, // Free heap
|
||||
@ -42,8 +41,17 @@ typedef enum {
|
||||
ARBITER_KERNEL4 =4,
|
||||
} ArbitrationType;
|
||||
|
||||
static inline void* getThreadLocalStorage(void)
|
||||
{
|
||||
void* ret;
|
||||
asm volatile("mrc p15, 0, %[data], c13, c0, 3" : [data] "=r" (ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32* getThreadCommandBuffer(void);
|
||||
static inline u32* getThreadCommandBuffer(void)
|
||||
{
|
||||
return (u32*)((u8*)getThreadLocalStorage() + 0x80);
|
||||
}
|
||||
|
||||
s32 svcControlMemory(u32* addr_out, u32 addr0, u32 addr1, u32 size, MemOp op, MemPerm perm);
|
||||
s32 svcQueryMemory(MemInfo* info, PageInfo* out, u32 addr);
|
||||
@ -51,8 +59,11 @@ void __attribute__((noreturn)) svcExitProcess();
|
||||
s32 svcCreateThread(Handle* thread, ThreadFunc entrypoint, u32 arg, u32* stack_top, s32 thread_priority, s32 processor_id);
|
||||
void __attribute__((noreturn)) svcExitThread();
|
||||
void svcSleepThread(s64 ns);
|
||||
s32 svcSetThreadPriority(Handle thread, s32 prio);
|
||||
s32 svcCreateMutex(Handle* mutex, bool initially_locked);
|
||||
s32 svcReleaseMutex(Handle handle);
|
||||
s32 svcCreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count);
|
||||
s32 svcReleaseSemaphore(s32* count, Handle semaphore, s32 release_count);
|
||||
s32 svcCreateEvent(Handle* event, u8 reset_type);
|
||||
s32 svcSignalEvent(Handle handle);
|
||||
s32 svcClearEvent(Handle handle);
|
||||
@ -75,6 +86,5 @@ s32 svcGetProcessInfo(s64* out, Handle process, u32 type);
|
||||
s32 svcConnectToPort(volatile Handle* out, const char* portName);
|
||||
s32 svcSendSyncRequest(Handle session);
|
||||
s32 svcGetProcessId(u32 *out, Handle handle);
|
||||
s32 svcGetThreadId(u32 *out, Handle handle);
|
||||
s32 svcOutputDebugString(const char* str, int length);
|
||||
|
||||
#endif
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
@ -2,17 +2,12 @@
|
||||
|
||||
#include <3ds/types.h>
|
||||
|
||||
/* only POLLIN confirmed to work so far */
|
||||
#define POLLIN 0x001
|
||||
#define POLLPRI 0x002
|
||||
#define POLLOUT 0x004
|
||||
#define POLLERR 0x008
|
||||
#define POLLHUP 0x010
|
||||
#define POLLNVAL 0x020
|
||||
#define POLLRDNORM 0x040
|
||||
#define POLLRDBAND 0x080
|
||||
#define POLLWRNORM 0x100
|
||||
#define POLLWRBAND 0x200
|
||||
#define POLLIN 0x01
|
||||
#define POLLPRI 0x02
|
||||
#define POLLHUP 0x04 // unknown ???
|
||||
#define POLLERR 0x08 // probably
|
||||
#define POLLOUT 0x10
|
||||
#define POLLNVAL 0x20
|
||||
|
||||
typedef u32 nfds_t;
|
||||
|
||||
|
@ -1,9 +1,57 @@
|
||||
#include <3ds.h>
|
||||
#include <3ds/util/rbtree.h>
|
||||
|
||||
#include "mem_pool.h"
|
||||
|
||||
extern u32 __linear_heap, __linear_heap_size;
|
||||
|
||||
static MemPool sLinearPool;
|
||||
static rbtree_t sAddrMap;
|
||||
|
||||
struct addrMapNode
|
||||
{
|
||||
rbtree_node node;
|
||||
MemChunk chunk;
|
||||
};
|
||||
|
||||
#define getAddrMapNode(x) rbtree_item((x), addrMapNode, node)
|
||||
|
||||
static int addrMapNodeComparator(const rbtree_node_t* _lhs, const rbtree_node_t* _rhs)
|
||||
{
|
||||
auto lhs = getAddrMapNode(_lhs)->chunk.addr;
|
||||
auto rhs = getAddrMapNode(_rhs)->chunk.addr;
|
||||
if (lhs < rhs)
|
||||
return -1;
|
||||
if (lhs > rhs)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void addrMapNodeDestructor(rbtree_node_t* a)
|
||||
{
|
||||
free(getAddrMapNode(a));
|
||||
}
|
||||
|
||||
static addrMapNode* getNode(void* addr)
|
||||
{
|
||||
addrMapNode n;
|
||||
n.chunk.addr = (u8*)addr;
|
||||
auto p = rbtree_find(&sAddrMap, &n.node);
|
||||
return p ? getAddrMapNode(p) : nullptr;
|
||||
}
|
||||
|
||||
static addrMapNode* newNode(const MemChunk& chunk)
|
||||
{
|
||||
auto p = (addrMapNode*)malloc(sizeof(addrMapNode));
|
||||
if (!p) return nullptr;
|
||||
p->chunk = chunk;
|
||||
return p;
|
||||
}
|
||||
|
||||
static void delNode(addrMapNode* node)
|
||||
{
|
||||
rbtree_remove(&sAddrMap, &node->node, addrMapNodeDestructor);
|
||||
}
|
||||
|
||||
static bool linearInit()
|
||||
{
|
||||
@ -11,6 +59,7 @@ static bool linearInit()
|
||||
if (blk)
|
||||
{
|
||||
sLinearPool.AddBlock(blk);
|
||||
rbtree_init(&sAddrMap, addrMapNodeComparator);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -36,19 +85,19 @@ void* linearMemAlign(size_t size, size_t alignment)
|
||||
if (!sLinearPool.Ready() && !linearInit())
|
||||
return nullptr;
|
||||
|
||||
// Reserve memory for MemChunk structure
|
||||
size += alignment;
|
||||
|
||||
// Allocate the chunk
|
||||
MemChunk chunk;
|
||||
if (!sLinearPool.Allocate(chunk, size, shift))
|
||||
return nullptr;
|
||||
|
||||
// Copy the MemChunk structure and return memory
|
||||
auto addr = chunk.addr;
|
||||
*(MemChunk*)addr = chunk;
|
||||
*(u32*)(addr + alignment - sizeof(u32)) = alignment;
|
||||
return addr + alignment;
|
||||
auto node = newNode(chunk);
|
||||
if (!node)
|
||||
{
|
||||
sLinearPool.Deallocate(chunk);
|
||||
return nullptr;
|
||||
}
|
||||
if (rbtree_insert(&sAddrMap, &node->node));
|
||||
return chunk.addr;
|
||||
}
|
||||
|
||||
void* linearAlloc(size_t size)
|
||||
@ -64,10 +113,14 @@ void* linearRealloc(void* mem, size_t size)
|
||||
|
||||
void linearFree(void* mem)
|
||||
{
|
||||
// Find MemChunk structure and free the chunk
|
||||
u32 alignment = *((u32*)mem - 1);
|
||||
auto pChunk = (MemChunk*)((u8*)mem - alignment);
|
||||
sLinearPool.Deallocate(*pChunk);
|
||||
auto node = getNode(mem);
|
||||
if (!node) return;
|
||||
|
||||
// Free the chunk
|
||||
sLinearPool.Deallocate(node->chunk);
|
||||
|
||||
// Free the node
|
||||
delNode(node);
|
||||
}
|
||||
|
||||
u32 linearSpaceFree()
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include <3ds.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct MemChunk
|
||||
{
|
||||
|
@ -12,16 +12,46 @@ u8* gfxTopLeftFramebuffers[2];
|
||||
u8* gfxTopRightFramebuffers[2];
|
||||
u8* gfxBottomFramebuffers[2];
|
||||
|
||||
u8 currentBuffer;
|
||||
bool enable3d;
|
||||
static u8 currentBuffer;
|
||||
static bool enable3d;
|
||||
static int doubleBuf = 1;
|
||||
|
||||
Handle gspEvent, gspSharedMemHandle;
|
||||
|
||||
static GSP_FramebufferFormats topFormat = GSP_BGR8_OES;
|
||||
static GSP_FramebufferFormats botFormat = GSP_BGR8_OES;
|
||||
|
||||
void gfxSet3D(bool enable)
|
||||
{
|
||||
enable3d=enable;
|
||||
}
|
||||
|
||||
void gfxSetScreenFormat(gfxScreen_t screen, GSP_FramebufferFormats format) {
|
||||
if(screen==GFX_TOP)
|
||||
topFormat = format;
|
||||
else
|
||||
botFormat = format;
|
||||
}
|
||||
|
||||
void gfxSetDoubleBuffering(bool doubleBuffering) {
|
||||
doubleBuf = doubleBuffering ? 1 : 0; // make sure they're the integer values '1' and '0'
|
||||
}
|
||||
|
||||
static u32 __get_bytes_per_pixel(GSP_FramebufferFormats format) {
|
||||
switch(format) {
|
||||
case GSP_RGBA8_OES:
|
||||
return 4;
|
||||
case GSP_BGR8_OES:
|
||||
return 3;
|
||||
case GSP_RGB565_OES:
|
||||
case GSP_RGB5_A1_OES:
|
||||
case GSP_RGBA4_OES:
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
void gfxSetFramebufferInfo(gfxScreen_t screen, u8 id)
|
||||
{
|
||||
if(screen==GFX_TOP)
|
||||
@ -30,17 +60,17 @@ void gfxSetFramebufferInfo(gfxScreen_t screen, u8 id)
|
||||
topFramebufferInfo.framebuf0_vaddr=(u32*)gfxTopLeftFramebuffers[id];
|
||||
if(enable3d)topFramebufferInfo.framebuf1_vaddr=(u32*)gfxTopRightFramebuffers[id];
|
||||
else topFramebufferInfo.framebuf1_vaddr=topFramebufferInfo.framebuf0_vaddr;
|
||||
topFramebufferInfo.framebuf_widthbytesize=240*3;
|
||||
topFramebufferInfo.framebuf_widthbytesize=240*__get_bytes_per_pixel(topFormat);
|
||||
u8 bit5=(enable3d!=0);
|
||||
topFramebufferInfo.format=((1)<<8)|((1^bit5)<<6)|((bit5)<<5)|GSP_BGR8_OES;
|
||||
topFramebufferInfo.format=((1)<<8)|((1^bit5)<<6)|((bit5)<<5)|topFormat;
|
||||
topFramebufferInfo.framebuf_dispselect=id;
|
||||
topFramebufferInfo.unk=0x00000000;
|
||||
}else{
|
||||
bottomFramebufferInfo.active_framebuf=id;
|
||||
bottomFramebufferInfo.framebuf0_vaddr=(u32*)gfxBottomFramebuffers[id];
|
||||
bottomFramebufferInfo.framebuf1_vaddr=0x00000000;
|
||||
bottomFramebufferInfo.framebuf_widthbytesize=240*3;
|
||||
bottomFramebufferInfo.format=GSP_BGR8_OES;
|
||||
bottomFramebufferInfo.framebuf_widthbytesize=240*__get_bytes_per_pixel(botFormat);
|
||||
bottomFramebufferInfo.format=botFormat;
|
||||
bottomFramebufferInfo.framebuf_dispselect=id;
|
||||
bottomFramebufferInfo.unk=0x00000000;
|
||||
}
|
||||
@ -51,7 +81,7 @@ void gfxWriteFramebufferInfo(gfxScreen_t screen)
|
||||
u8* framebufferInfoHeader=gfxSharedMemory+0x200+gfxThreadID*0x80;
|
||||
if(screen==GFX_BOTTOM)framebufferInfoHeader+=0x40;
|
||||
GSP_FramebufferInfo* framebufferInfo=(GSP_FramebufferInfo*)&framebufferInfoHeader[0x4];
|
||||
framebufferInfoHeader[0x0]^=1;
|
||||
framebufferInfoHeader[0x0]^=doubleBuf;
|
||||
framebufferInfo[framebufferInfoHeader[0x0]]=(screen==GFX_TOP)?(topFramebufferInfo):(bottomFramebufferInfo);
|
||||
framebufferInfoHeader[0x1]=1;
|
||||
}
|
||||
@ -106,7 +136,7 @@ void gfxExit()
|
||||
// Exit event handler
|
||||
gspExitEventHandler();
|
||||
|
||||
// Free framebuffers (let's pretend linearFree is actually implemented...)
|
||||
// Free framebuffers
|
||||
linearFree(gfxTopRightFramebuffers[1]);
|
||||
linearFree(gfxTopRightFramebuffers[0]);
|
||||
linearFree(gfxBottomFramebuffers[1]);
|
||||
@ -134,10 +164,10 @@ u8* gfxGetFramebuffer(gfxScreen_t screen, gfx3dSide_t side, u16* width, u16* hei
|
||||
if(screen==GFX_TOP)
|
||||
{
|
||||
if(height)*height=400;
|
||||
return (side==GFX_LEFT || !enable3d)?(gfxTopLeftFramebuffers[currentBuffer^1]):(gfxTopRightFramebuffers[currentBuffer^1]);
|
||||
return (side==GFX_LEFT || !enable3d)?(gfxTopLeftFramebuffers[currentBuffer^doubleBuf]):(gfxTopRightFramebuffers[currentBuffer^doubleBuf]);
|
||||
}else{
|
||||
if(height)*height=320;
|
||||
return gfxBottomFramebuffers[currentBuffer^1];
|
||||
return gfxBottomFramebuffers[currentBuffer^doubleBuf];
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,7 +180,7 @@ void gfxFlushBuffers()
|
||||
|
||||
void gfxSwapBuffers()
|
||||
{
|
||||
currentBuffer^=1;
|
||||
currentBuffer^=doubleBuf;
|
||||
gfxSetFramebufferInfo(GFX_TOP, currentBuffer);
|
||||
gfxSetFramebufferInfo(GFX_BOTTOM, currentBuffer);
|
||||
GSPGPU_SetBufferSwap(NULL, GFX_TOP, &topFramebufferInfo);
|
||||
@ -159,7 +189,7 @@ void gfxSwapBuffers()
|
||||
|
||||
void gfxSwapBuffersGpu()
|
||||
{
|
||||
currentBuffer^=1;
|
||||
currentBuffer^=doubleBuf;
|
||||
gfxSetFramebufferInfo(GFX_TOP, currentBuffer);
|
||||
gfxSetFramebufferInfo(GFX_BOTTOM, currentBuffer);
|
||||
gfxWriteFramebufferInfo(GFX_TOP);
|
||||
|
@ -56,7 +56,7 @@ DVLB_s* SHDR_ParseSHBIN(u32* shbinData, u32 shbinSize)
|
||||
return ret;
|
||||
}
|
||||
|
||||
s8 SHDR_GetUniformRegister(DVLB_s* dvlb, char* name, u8 programID)
|
||||
s8 SHDR_GetUniformRegister(DVLB_s* dvlb, const char* name, u8 programID)
|
||||
{
|
||||
if(!dvlb || !name)return -1;
|
||||
|
||||
|
@ -26,16 +26,18 @@ void __destroy_handle_list(void);
|
||||
|
||||
void __attribute__((noreturn)) __ctru_exit(int rc)
|
||||
{
|
||||
u32 tmp=0;
|
||||
|
||||
// Run the global destructors
|
||||
__libc_fini_array();
|
||||
|
||||
// TODO: APT exit goes here
|
||||
|
||||
// Unmap the linear heap
|
||||
svcControlMemory(&__linear_heap, __linear_heap, 0x0, __linear_heap_size, MEMOP_FREE, 0x0);
|
||||
svcControlMemory(&tmp, __linear_heap, 0x0, __linear_heap_size, MEMOP_FREE, 0x0);
|
||||
|
||||
// Unmap the application heap
|
||||
svcControlMemory(&heapBase, heapBase, 0x0, __heap_size, MEMOP_FREE, 0x0);
|
||||
svcControlMemory(&tmp, heapBase, 0x0, __heap_size, MEMOP_FREE, 0x0);
|
||||
|
||||
// Close some handles
|
||||
__destroy_handle_list();
|
||||
@ -50,13 +52,15 @@ void __attribute__((noreturn)) __ctru_exit(int rc)
|
||||
|
||||
void initSystem(void (*retAddr)(void))
|
||||
{
|
||||
u32 tmp=0;
|
||||
|
||||
// Register newlib exit() syscall
|
||||
__syscalls.exit = __ctru_exit;
|
||||
__system_retAddr = __service_ptr ? retAddr : NULL;
|
||||
|
||||
// Allocate the application heap
|
||||
heapBase = 0x08000000;
|
||||
svcControlMemory(&heapBase, heapBase, 0x0, __heap_size, MEMOP_ALLOC, 0x3);
|
||||
svcControlMemory(&tmp, heapBase, 0x0, __heap_size, MEMOP_ALLOC, 0x3);
|
||||
|
||||
// Allocate the linear heap
|
||||
svcControlMemory(&__linear_heap, 0x0, 0x0, __linear_heap_size, MEMOP_ALLOC_LINEAR, 0x3);
|
||||
|
@ -49,7 +49,7 @@ u64 osGetTime() {
|
||||
break;
|
||||
}
|
||||
|
||||
u64 offset = (svcGetSystemTick() - dt->update_tick) / TICKS_PER_MSEC;
|
||||
u64 offset = (u32)((u32)(svcGetSystemTick() - dt->update_tick) / TICKS_PER_MSEC);
|
||||
return dt->date_time + offset;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,11 @@
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <sys/iosupport.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <3ds.h>
|
||||
|
||||
/*! @internal
|
||||
@ -95,14 +99,63 @@ static FS_archive sdmcArchive =
|
||||
|
||||
/*! @endcond */
|
||||
|
||||
static char __cwd[PATH_MAX+1] = "/";
|
||||
static char __fixedpath[PATH_MAX+1];
|
||||
|
||||
static const char *sdmc_fixpath(const char *path)
|
||||
{
|
||||
// Move the path pointer to the start of the actual path
|
||||
if (strchr (path, ':') != NULL)
|
||||
{
|
||||
path = strchr (path, ':') + 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;
|
||||
|
||||
return __fixedpath;
|
||||
|
||||
}
|
||||
|
||||
extern int __system_argc;
|
||||
extern char** __system_argv;
|
||||
|
||||
/*! Initialize SDMC device */
|
||||
Result sdmcInit(void)
|
||||
{
|
||||
Result rc;
|
||||
|
||||
|
||||
rc = FSUSER_OpenArchive(NULL, &sdmcArchive);
|
||||
|
||||
|
||||
if(rc == 0)
|
||||
AddDevice(&sdmc_devoptab);
|
||||
{
|
||||
|
||||
int dev = AddDevice(&sdmc_devoptab);
|
||||
|
||||
if (dev != -1) {
|
||||
setDefaultDevice(dev);
|
||||
if (__system_argc != 0 && __system_argv[0] != NULL)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -141,10 +194,15 @@ sdmc_open(struct _reent *r,
|
||||
Result rc;
|
||||
u32 sdmc_flags = 0;
|
||||
u32 attributes = FS_ATTRIBUTE_NONE;
|
||||
char *pathptr = NULL;
|
||||
const char *pathptr = NULL;
|
||||
|
||||
pathptr = strchr(path, '/');
|
||||
if(pathptr==NULL)pathptr = (char*)path;
|
||||
pathptr = sdmc_fixpath(path);
|
||||
|
||||
if(pathptr==NULL)
|
||||
{
|
||||
r->_errno=EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* get pointer to our data */
|
||||
sdmc_file_t *file = (sdmc_file_t*)fileStruct;
|
||||
@ -483,10 +541,34 @@ static int
|
||||
sdmc_chdir(struct _reent *r,
|
||||
const char *name)
|
||||
{
|
||||
r->_errno = ENOSYS;
|
||||
Handle fd;
|
||||
Result rc;
|
||||
const char *pathptr = NULL;
|
||||
|
||||
pathptr = sdmc_fixpath(name);
|
||||
|
||||
if(pathptr==NULL)
|
||||
{
|
||||
r->_errno=EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = FSUSER_OpenDirectory(NULL, &fd, sdmcArchive, FS_makePath(PATH_CHAR, pathptr));
|
||||
if(rc == 0)
|
||||
{
|
||||
FSDIR_Close(fd);
|
||||
strncpy(__cwd,pathptr,PATH_MAX);
|
||||
}
|
||||
else
|
||||
{
|
||||
r->_errno=EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/*! Rename a file
|
||||
*
|
||||
* @param[in,out] r newlib reentrancy struct
|
||||
@ -520,10 +602,15 @@ sdmc_mkdir(struct _reent *r,
|
||||
int mode)
|
||||
{
|
||||
Result rc;
|
||||
char *pathptr = NULL;
|
||||
const char *pathptr = NULL;
|
||||
|
||||
pathptr = strchr(path, '/');
|
||||
if(pathptr==NULL)pathptr = (char*)path;
|
||||
pathptr = sdmc_fixpath(path);
|
||||
|
||||
if(pathptr==NULL)
|
||||
{
|
||||
r->_errno=EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* TODO: Use mode to set directory attributes. */
|
||||
|
||||
@ -551,10 +638,15 @@ sdmc_diropen(struct _reent *r,
|
||||
{
|
||||
Handle fd;
|
||||
Result rc;
|
||||
char *pathptr = NULL;
|
||||
const char *pathptr = NULL;
|
||||
|
||||
pathptr = strchr(path, '/');
|
||||
if(pathptr==NULL)pathptr = (char*)path;
|
||||
pathptr = sdmc_fixpath(path);
|
||||
|
||||
if(pathptr==NULL)
|
||||
{
|
||||
r->_errno=EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* get pointer to our data */
|
||||
sdmc_dir_t *dir = (sdmc_dir_t*)(dirState->dirStruct);
|
||||
@ -684,7 +776,7 @@ sdmc_statvfs(struct _reent *r,
|
||||
{
|
||||
Result rc;
|
||||
u32 clusterSize, numClusters, freeClusters;
|
||||
u32 writable = 0;
|
||||
u8 writable = 0;
|
||||
|
||||
rc = FSUSER_GetSdmcArchiveResource(NULL,
|
||||
NULL,
|
||||
|
@ -36,6 +36,13 @@ Handle aptSleepSync = 0;
|
||||
|
||||
u32 aptParameters[0x1000/4]; //TEMP
|
||||
|
||||
static u32 __ns_capinfo[0x20>>2];
|
||||
|
||||
static NS_APPID __apt_launchapplet_appID;
|
||||
static Handle __apt_launchapplet_inhandle;
|
||||
static u32 *__apt_launchapplet_parambuf;
|
||||
static u32 __apt_launchapplet_parambufsize;
|
||||
|
||||
static void aptAppStarted(void);
|
||||
|
||||
static Result __apt_initservicehandle()
|
||||
@ -96,7 +103,7 @@ void aptWaitStatusEvent()
|
||||
svcClearEvent(aptStatusEvent);
|
||||
}
|
||||
|
||||
void aptAppletUtility_Exit_RetToApp()
|
||||
void aptAppletUtility_Exit_RetToApp(u32 type)
|
||||
{
|
||||
u8 buf1[4], buf2[4];
|
||||
|
||||
@ -125,6 +132,13 @@ void aptAppletUtility_Exit_RetToApp()
|
||||
aptOpenSession();
|
||||
APT_AppletUtility(NULL, NULL, 0x4, 0x1, buf1, 0x1, buf2);
|
||||
aptCloseSession();
|
||||
|
||||
if(type)
|
||||
{
|
||||
aptOpenSession();
|
||||
APT_AppletUtility(NULL, NULL, 0x4, 0x1, buf1, 0x1, buf2);
|
||||
aptCloseSession();
|
||||
}
|
||||
}
|
||||
|
||||
NS_APPID aptGetMenuAppID()
|
||||
@ -142,8 +156,6 @@ void aptReturnToMenu()
|
||||
{
|
||||
NS_APPID menu_appid;
|
||||
u32 tmp0 = 1, tmp1 = 0;
|
||||
u32 ns_capinfo[0x20>>2];
|
||||
u32 tmp_params[0x20>>2];
|
||||
|
||||
if(__system_runflags&RUNFLAG_APTWORKAROUND)
|
||||
{
|
||||
@ -173,20 +185,19 @@ void aptReturnToMenu()
|
||||
GSPGPU_SaveVramSysArea(NULL);
|
||||
|
||||
// Capture screen.
|
||||
memset(tmp_params, 0, 0x20);
|
||||
memset(ns_capinfo, 0, 0x20);
|
||||
memset(__ns_capinfo, 0, 0x20);
|
||||
|
||||
aptInitCaptureInfo(ns_capinfo);
|
||||
aptInitCaptureInfo(__ns_capinfo);
|
||||
|
||||
menu_appid = aptGetMenuAppID();
|
||||
|
||||
// Send capture-screen info to menu.
|
||||
aptOpenSession();
|
||||
APT_SendParameter(NULL, currentAppId, menu_appid, 0x20, ns_capinfo, 0x0, 0x10);
|
||||
APT_SendParameter(NULL, currentAppId, menu_appid, 0x20, __ns_capinfo, 0x0, 0x10);
|
||||
aptCloseSession();
|
||||
|
||||
aptOpenSession();
|
||||
APT_SendCaptureBufferInfo(NULL, 0x20, ns_capinfo);
|
||||
APT_SendCaptureBufferInfo(NULL, 0x20, __ns_capinfo);
|
||||
aptCloseSession();
|
||||
|
||||
// Release GSP module.
|
||||
@ -214,6 +225,54 @@ void aptReturnToMenu()
|
||||
aptWaitStatusEvent();
|
||||
}
|
||||
|
||||
void aptAppletStarted()
|
||||
{
|
||||
u8 buf1[4], buf2[4];
|
||||
|
||||
memset(buf1, 0, 4);
|
||||
|
||||
// Set status to SUSPENDED.
|
||||
svcClearEvent(aptStatusEvent);
|
||||
aptSetStatus(APP_SUSPENDED);
|
||||
|
||||
aptOpenSession();
|
||||
APT_SendCaptureBufferInfo(NULL, 0x20, __ns_capinfo);
|
||||
aptCloseSession();
|
||||
|
||||
aptOpenSession();
|
||||
APT_ReplySleepQuery(NULL, currentAppId, 0x0);
|
||||
aptCloseSession();
|
||||
|
||||
aptOpenSession();
|
||||
APT_StartLibraryApplet(NULL, __apt_launchapplet_appID, __apt_launchapplet_inhandle, __apt_launchapplet_parambuf, __apt_launchapplet_parambufsize);
|
||||
aptCloseSession();
|
||||
|
||||
buf1[0]=0x00;
|
||||
aptOpenSession();
|
||||
APT_AppletUtility(NULL, NULL, 0x4, 0x1, buf1, 0x1, buf2);
|
||||
aptCloseSession();
|
||||
|
||||
aptOpenSession();
|
||||
APT_NotifyToWait(NULL, currentAppId);
|
||||
aptCloseSession();
|
||||
|
||||
buf1[0]=0x00;
|
||||
aptOpenSession();
|
||||
APT_AppletUtility(NULL, NULL, 0x4, 0x1, buf1, 0x1, buf2);
|
||||
aptCloseSession();
|
||||
}
|
||||
|
||||
void aptAppletClosed()
|
||||
{
|
||||
aptAppletUtility_Exit_RetToApp(1);
|
||||
|
||||
GSPGPU_AcquireRight(NULL, 0x0);
|
||||
GSPGPU_RestoreVramSysArea(NULL);
|
||||
|
||||
svcClearEvent(aptStatusEvent);
|
||||
aptSetStatus(APP_RUNNING);
|
||||
}
|
||||
|
||||
static void __handle_notification() {
|
||||
u8 type;
|
||||
Result ret=0;
|
||||
@ -292,10 +351,19 @@ static bool __handle_incoming_parameter() {
|
||||
aptAppStarted();
|
||||
return true;
|
||||
|
||||
case 0x3: // "Launched library applet finished loading"
|
||||
if (aptGetStatus() == APP_SUSPENDED) return true;
|
||||
aptSetStatus(APP_APPLETSTARTED);
|
||||
return true;
|
||||
case 0xA: // "Launched library applet closed"
|
||||
if (aptGetStatus() == APP_SUSPENDED) return true;
|
||||
if(__apt_launchapplet_parambuf && __apt_launchapplet_parambufsize)memcpy(__apt_launchapplet_parambuf, aptParameters, __apt_launchapplet_parambufsize);
|
||||
aptSetStatus(APP_APPLETCLOSED);
|
||||
return true;
|
||||
case 0xB: // Just returned from menu.
|
||||
GSPGPU_AcquireRight(NULL, 0x0);
|
||||
GSPGPU_RestoreVramSysArea(NULL);
|
||||
aptAppletUtility_Exit_RetToApp();
|
||||
aptAppletUtility_Exit_RetToApp(0);
|
||||
aptSetStatus(APP_RUNNING);
|
||||
return true;
|
||||
|
||||
@ -377,7 +445,7 @@ Result aptInit(void)
|
||||
|
||||
void aptExit()
|
||||
{
|
||||
if(!(__system_runflags&RUNFLAG_APTWORKAROUND))aptAppletUtility_Exit_RetToApp();
|
||||
if(!(__system_runflags&RUNFLAG_APTWORKAROUND))aptAppletUtility_Exit_RetToApp(0);
|
||||
|
||||
// This is only executed when application-termination was triggered via the home-menu power-off screen.
|
||||
if(aptGetStatusPower() == 1)
|
||||
@ -420,6 +488,12 @@ bool aptMainLoop()
|
||||
case APP_SUSPENDING:
|
||||
aptReturnToMenu();
|
||||
break;
|
||||
case APP_APPLETSTARTED:
|
||||
aptAppletStarted();
|
||||
break;
|
||||
case APP_APPLETCLOSED:
|
||||
aptAppletClosed();
|
||||
break;
|
||||
case APP_PREPARE_SLEEPMODE:
|
||||
aptSignalReadyForSleep();
|
||||
// Fall through
|
||||
@ -479,7 +553,7 @@ void aptSetStatus(APP_STATUS status)
|
||||
|
||||
//if(prevstatus != APP_NOTINITIALIZED)
|
||||
//{
|
||||
if(status == APP_RUNNING || status == APP_EXITING || status == APP_SLEEPMODE)
|
||||
if(status == APP_RUNNING || status == APP_EXITING || status == APP_APPLETSTARTED || status == APP_APPLETCLOSED)
|
||||
svcSignalEvent(aptStatusEvent);
|
||||
//}
|
||||
|
||||
@ -596,6 +670,21 @@ Result APT_GetAppletManInfo(Handle* handle, u8 inval, u8 *outval8, u32 *outval32
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
Result APT_IsRegistered(Handle* handle, NS_APPID appID, u8* out)
|
||||
{
|
||||
if(!handle)handle=&aptuHandle;
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
cmdbuf[0]=0x90040; //request header code
|
||||
cmdbuf[1]=appID;
|
||||
|
||||
Result ret=0;
|
||||
if((ret=svcSendSyncRequest(*handle)))return ret;
|
||||
|
||||
if(out)*out=cmdbuf[2];
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
Result APT_InquireNotification(Handle* handle, u32 appID, u8* signalType)
|
||||
{
|
||||
if(!handle)handle=&aptuHandle;
|
||||
@ -949,3 +1038,105 @@ Result APT_DoAppJump(Handle* handle, u32 NSbuf0Size, u32 NSbuf1Size, u8 *NSbuf0P
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
Result APT_PrepareToStartLibraryApplet(Handle* handle, NS_APPID appID)
|
||||
{
|
||||
if(!handle)handle=&aptuHandle;
|
||||
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
cmdbuf[0]=0x180040; //request header code
|
||||
cmdbuf[1]=appID;
|
||||
|
||||
Result ret=0;
|
||||
if((ret=svcSendSyncRequest(*handle)))return ret;
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
Result APT_StartLibraryApplet(Handle* handle, NS_APPID appID, Handle inhandle, u32 *parambuf, u32 parambufsize)
|
||||
{
|
||||
if(!handle)handle=&aptuHandle;
|
||||
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
cmdbuf[0]=0x1E0084; //request header code
|
||||
cmdbuf[1]=appID;
|
||||
cmdbuf[2]=parambufsize;
|
||||
cmdbuf[3]=0;
|
||||
cmdbuf[4]=inhandle;
|
||||
cmdbuf[5]=(parambufsize<<14)|2;
|
||||
cmdbuf[6]=(u32)parambuf;
|
||||
|
||||
Result ret=0;
|
||||
if((ret=svcSendSyncRequest(*handle)))return ret;
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
Result APT_LaunchLibraryApplet(NS_APPID appID, Handle inhandle, u32 *parambuf, u32 parambufsize)
|
||||
{
|
||||
Result ret=0;
|
||||
u8 tmp=0;
|
||||
|
||||
u8 buf1[4];
|
||||
u8 buf2[4];
|
||||
|
||||
aptOpenSession();
|
||||
APT_ReplySleepQuery(NULL, currentAppId, 0);
|
||||
aptCloseSession();
|
||||
|
||||
memset(buf1, 0, 4);
|
||||
aptOpenSession();
|
||||
APT_AppletUtility(NULL, NULL, 0x4, 0x1, buf1, 0x1, buf2);
|
||||
aptCloseSession();
|
||||
|
||||
aptOpenSession();
|
||||
APT_ReplySleepQuery(NULL, currentAppId, 0);
|
||||
aptCloseSession();
|
||||
|
||||
aptOpenSession();
|
||||
ret=APT_PrepareToStartLibraryApplet(NULL, appID);
|
||||
aptCloseSession();
|
||||
if(ret!=0)return ret;
|
||||
|
||||
memset(buf1, 0, 4);
|
||||
aptOpenSession();
|
||||
APT_AppletUtility(NULL, NULL, 0x4, 0x1, buf1, 0x1, buf2);
|
||||
aptCloseSession();
|
||||
|
||||
while(1)
|
||||
{
|
||||
aptOpenSession();
|
||||
ret=APT_IsRegistered(NULL, appID, &tmp);
|
||||
aptCloseSession();
|
||||
if(ret!=0)return ret;
|
||||
|
||||
if(tmp!=0)break;
|
||||
}
|
||||
|
||||
// Set status to SUSPENDED.
|
||||
svcClearEvent(aptStatusEvent);
|
||||
aptSetStatus(APP_SUSPENDED);
|
||||
|
||||
// Save Vram
|
||||
GSPGPU_SaveVramSysArea(NULL);
|
||||
|
||||
// Capture screen.
|
||||
memset(__ns_capinfo, 0, 0x20);
|
||||
|
||||
aptInitCaptureInfo(__ns_capinfo);
|
||||
|
||||
// Send capture-screen info to the library applet.
|
||||
aptOpenSession();
|
||||
APT_SendParameter(NULL, currentAppId, appID, 0x20, __ns_capinfo, 0x0, 0x2);
|
||||
aptCloseSession();
|
||||
|
||||
// Release GSP module.
|
||||
GSPGPU_ReleaseRight(NULL);
|
||||
|
||||
__apt_launchapplet_appID = appID;
|
||||
__apt_launchapplet_inhandle = inhandle;
|
||||
__apt_launchapplet_parambuf = parambuf;
|
||||
__apt_launchapplet_parambufsize = parambufsize;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
89
libctru/source/services/cfgu.c
Normal file
89
libctru/source/services/cfgu.c
Normal file
@ -0,0 +1,89 @@
|
||||
#include <stdlib.h>
|
||||
#include <3ds.h>
|
||||
|
||||
static Handle CFGU_handle = 0;
|
||||
|
||||
Result initCfgu()
|
||||
{
|
||||
return srvGetServiceHandle(&CFGU_handle, "cfg:u");
|
||||
}
|
||||
|
||||
Result exitCfgu()
|
||||
{
|
||||
Result ret = svcCloseHandle(CFGU_handle);
|
||||
CFGU_handle = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Result CFGU_GetRegionCanadaUSA(u8* value)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = 0x00040000;
|
||||
|
||||
if((ret = svcSendSyncRequest(CFGU_handle))!=0)return ret;
|
||||
|
||||
*value = (u8)cmdbuf[2];
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result CFGU_GetSystemModel(u8* model)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = 0x00050000;
|
||||
|
||||
if((ret = svcSendSyncRequest(CFGU_handle))!=0)return ret;
|
||||
|
||||
*model = (u8)cmdbuf[2];
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result CFGU_GetModelNintendo2DS(u8* value)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = 0x00060000;
|
||||
|
||||
if((ret = svcSendSyncRequest(CFGU_handle))!=0)return ret;
|
||||
|
||||
*value = (u8)cmdbuf[2];
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result CFGU_GetCountryCodeString(u16 code, u16* string)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = 0x00090040;
|
||||
cmdbuf[1] = (u32)code;
|
||||
|
||||
if((ret = svcSendSyncRequest(CFGU_handle))!=0)return ret;
|
||||
|
||||
*string = (u16)cmdbuf[2];
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result CFGU_GetCountryCodeID(u16 string, u16* code)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = 0x000A0040;
|
||||
cmdbuf[1] = (u32)string;
|
||||
|
||||
if((ret = svcSendSyncRequest(CFGU_handle))!=0)return ret;
|
||||
|
||||
*code = (u16)cmdbuf[2];
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
@ -14,6 +14,22 @@ static Handle fsuHandle;
|
||||
// used to determine whether or not we should do FSUSER_Initialize on fsuHandle
|
||||
Handle __get_handle_from_list(char* name);
|
||||
|
||||
/*! Create an FS_path from a type and data pointer.
|
||||
*
|
||||
* @param[in] type Path type.
|
||||
* @param[in] path Pointer to path data.
|
||||
*
|
||||
* @returns FS_path
|
||||
*
|
||||
* @sa FS_pathType
|
||||
*/
|
||||
FS_path
|
||||
FS_makePath(FS_pathType type,
|
||||
const char *path)
|
||||
{
|
||||
return (FS_path){type, strlen(path)+1, (const u8*)path};
|
||||
}
|
||||
|
||||
/*! Initialize FS service
|
||||
*
|
||||
* @returns error
|
||||
@ -298,11 +314,76 @@ FSUSER_DeleteFile(Handle *handle,
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
/* stub */
|
||||
/*! Renames or moves a file.
|
||||
*
|
||||
* @param[in] handle fs:USER handle
|
||||
* @param[in] srcArchive Open archive of source
|
||||
* @param[in] srcFileLowPath File path to source
|
||||
* @param[in] destArchive Open archive of destination
|
||||
* @param[in] destFileLowPath File path to destination
|
||||
*
|
||||
* @returns error
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* #### Request
|
||||
*
|
||||
* Index Word | Description
|
||||
* -----------|-------------------------
|
||||
* 0 | Header code [0x08050244]
|
||||
* 1 | 0
|
||||
* 2 | srcArchive.handleLow
|
||||
* 3 | srcArchive.handleHigh
|
||||
* 4 | srcFileLowPath.type
|
||||
* 5 | srcFileLowPath.size
|
||||
* 6 | destArchive.handleLow
|
||||
* 7 | destArchive.handleHigh
|
||||
* 8 | destFileLowPath.type
|
||||
* 9 | destFileLowPath.size
|
||||
* 10 | (srcFileLowPath.size << 14) \| 0x402
|
||||
* 11 | srcFileLowPath.data
|
||||
* 12 | (destFileLowPath.size << 14) \| 0x802
|
||||
* 13 | destFileLowPath.data
|
||||
*
|
||||
* #### Response
|
||||
*
|
||||
* Index Word | Description
|
||||
* -----------|-------------------------
|
||||
* 0 | Header code
|
||||
* 1 | Result code
|
||||
*/
|
||||
Result
|
||||
FSUSER_RenameFile(void)
|
||||
FSUSER_RenameFile(Handle *handle,
|
||||
FS_archive srcArchive,
|
||||
FS_path srcFileLowPath,
|
||||
FS_archive destArchive,
|
||||
FS_path destFileLowPath)
|
||||
{
|
||||
return -1;
|
||||
if(!handle)
|
||||
handle = &fsuHandle;
|
||||
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = 0x08050244;
|
||||
cmdbuf[1] = 0;
|
||||
cmdbuf[2] = srcArchive.handleLow;
|
||||
cmdbuf[3] = srcArchive.handleHigh;
|
||||
cmdbuf[4] = srcFileLowPath.type;
|
||||
cmdbuf[5] = srcFileLowPath.size;
|
||||
cmdbuf[6] = destArchive.handleLow;
|
||||
cmdbuf[7] = destArchive.handleHigh;
|
||||
cmdbuf[8] = destFileLowPath.type;
|
||||
cmdbuf[9] = destFileLowPath.size;
|
||||
cmdbuf[10] = (srcFileLowPath.size << 14) | 0x402;
|
||||
cmdbuf[11] = (u32)srcFileLowPath.data;
|
||||
cmdbuf[12] = (destFileLowPath.size << 14) | 0x802;
|
||||
cmdbuf[13] = (u32)destFileLowPath.data;
|
||||
|
||||
Result ret = 0;
|
||||
if((ret = svcSendSyncRequest(*handle)))
|
||||
return ret;
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
/*! Delete a directory
|
||||
@ -433,11 +514,76 @@ FSUSER_CreateDirectory(Handle *handle,
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
/* stub */
|
||||
/*! Renames or moves a directory.
|
||||
*
|
||||
* @param[in] handle fs:USER handle
|
||||
* @param[in] srcArchive Open archive of source
|
||||
* @param[in] srcDirLowPath Dir path to source
|
||||
* @param[in] destArchive Open archive of destination
|
||||
* @param[in] destDirLowPath Dir path to destination
|
||||
*
|
||||
* @returns error
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* #### Request
|
||||
*
|
||||
* Index Word | Description
|
||||
* -----------|-------------------------
|
||||
* 0 | Header code [0x080A0244]
|
||||
* 1 | 0
|
||||
* 2 | srcArchive.handleLow
|
||||
* 3 | srcArchive.handleHigh
|
||||
* 4 | srcDirLowPath.type
|
||||
* 5 | srcDirLowPath.size
|
||||
* 6 | destArchive.handleLow
|
||||
* 7 | destArchive.handleHigh
|
||||
* 8 | destDirLowPath.type
|
||||
* 9 | destDirLowPath.size
|
||||
* 10 | (srcDirLowPath.size << 14) \| 0x402
|
||||
* 11 | srcDirLowPath.data
|
||||
* 12 | (destDirLowPath.size << 14) \| 0x802
|
||||
* 13 | destDirLowPath.data
|
||||
*
|
||||
* #### Response
|
||||
*
|
||||
* Index Word | Description
|
||||
* -----------|-------------------------
|
||||
* 0 | Header code
|
||||
* 1 | Result code
|
||||
*/
|
||||
Result
|
||||
FSUSER_RenameDirectory(void)
|
||||
FSUSER_RenameDirectory(Handle *handle,
|
||||
FS_archive srcArchive,
|
||||
FS_path srcDirLowPath,
|
||||
FS_archive destArchive,
|
||||
FS_path destDirLowPath)
|
||||
{
|
||||
return -1;
|
||||
if(!handle)
|
||||
handle = &fsuHandle;
|
||||
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = 0x080A0244;
|
||||
cmdbuf[1] = 0;
|
||||
cmdbuf[2] = srcArchive.handleLow;
|
||||
cmdbuf[3] = srcArchive.handleHigh;
|
||||
cmdbuf[4] = srcDirLowPath.type;
|
||||
cmdbuf[5] = srcDirLowPath.size;
|
||||
cmdbuf[6] = destArchive.handleLow;
|
||||
cmdbuf[7] = destArchive.handleHigh;
|
||||
cmdbuf[8] = destDirLowPath.type;
|
||||
cmdbuf[9] = destDirLowPath.size;
|
||||
cmdbuf[10] = (srcDirLowPath.size << 14) | 0x402;
|
||||
cmdbuf[11] = (u32)srcDirLowPath.data;
|
||||
cmdbuf[12] = (destDirLowPath.size << 14) | 0x802;
|
||||
cmdbuf[13] = (u32)destDirLowPath.data;
|
||||
|
||||
Result ret = 0;
|
||||
if((ret = svcSendSyncRequest(*handle)))
|
||||
return ret;
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
/*! Open a directory
|
||||
@ -693,7 +839,7 @@ FSUSER_GetSdmcArchiveResource(Handle *handle,
|
||||
*/
|
||||
Result
|
||||
FSUSER_IsSdmcDetected(Handle *handle,
|
||||
u32 *detected)
|
||||
u8 *detected)
|
||||
{
|
||||
if(!handle)
|
||||
handle = &fsuHandle;
|
||||
@ -737,7 +883,7 @@ FSUSER_IsSdmcDetected(Handle *handle,
|
||||
*/
|
||||
Result
|
||||
FSUSER_IsSdmcWritable(Handle *handle,
|
||||
u32 *writable)
|
||||
u8 *writable)
|
||||
{
|
||||
if(!handle)
|
||||
handle = &fsuHandle;
|
||||
@ -1201,6 +1347,7 @@ FSDIR_Close(Handle handle)
|
||||
Result ret = 0;
|
||||
if((ret = svcSendSyncRequest(handle)))
|
||||
return ret;
|
||||
|
||||
return cmdbuf[1];
|
||||
ret = cmdbuf[1];
|
||||
if(!ret)ret = svcCloseHandle(handle);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1,13 +1,138 @@
|
||||
#include <string.h>
|
||||
#include <3ds.h>
|
||||
|
||||
Handle __httpc_servhandle = 0;
|
||||
|
||||
Result httpcInit()
|
||||
{
|
||||
Result ret=0;
|
||||
|
||||
if(__httpc_servhandle)return 0;
|
||||
if((ret=srvGetServiceHandle(&__httpc_servhandle, "http:C")))return ret;
|
||||
|
||||
//*((u32*)0x600) = __httpc_servhandle;
|
||||
|
||||
ret = HTTPC_Initialize(__httpc_servhandle);
|
||||
if(ret!=0)return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void httpcExit()
|
||||
{
|
||||
if(__httpc_servhandle==0)return;
|
||||
|
||||
svcCloseHandle(__httpc_servhandle);
|
||||
}
|
||||
|
||||
Result httpcOpenContext(httpcContext *context, char* url, u32 use_defaultproxy)
|
||||
{
|
||||
Result ret=0;
|
||||
|
||||
ret = HTTPC_CreateContext(__httpc_servhandle, url, &context->httphandle);
|
||||
if(ret!=0)return ret;
|
||||
|
||||
ret = srvGetServiceHandle(&context->servhandle, "http:C");
|
||||
if(ret!=0)return ret;
|
||||
|
||||
ret = HTTPC_InitializeConnectionSession(context->servhandle, context->httphandle);
|
||||
if(ret!=0)return ret;
|
||||
|
||||
if(use_defaultproxy==0)return 0;
|
||||
|
||||
ret = HTTPC_SetProxyDefault(context->servhandle, context->httphandle);
|
||||
if(ret!=0)return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result httpcCloseContext(httpcContext *context)
|
||||
{
|
||||
Result ret=0;
|
||||
|
||||
ret = HTTPC_CloseContext(context->servhandle, context->httphandle);
|
||||
|
||||
svcCloseHandle(context->servhandle);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Result httpcAddRequestHeaderField(httpcContext *context, char* name, char* value)
|
||||
{
|
||||
return HTTPC_AddRequestHeaderField(context->servhandle, context->httphandle, name, value);
|
||||
}
|
||||
|
||||
Result httpcBeginRequest(httpcContext *context)
|
||||
{
|
||||
return HTTPC_BeginRequest(context->servhandle, context->httphandle);
|
||||
}
|
||||
|
||||
Result httpcReceiveData(httpcContext *context, u8* buffer, u32 size)
|
||||
{
|
||||
return HTTPC_ReceiveData(context->servhandle, context->httphandle, buffer, size);
|
||||
}
|
||||
|
||||
Result httpcGetRequestState(httpcContext *context, httpcReqStatus* out)
|
||||
{
|
||||
return HTTPC_GetRequestState(context->servhandle, context->httphandle, out);
|
||||
}
|
||||
|
||||
Result httpcGetDownloadSizeState(httpcContext *context, u32* downloadedsize, u32* contentsize)
|
||||
{
|
||||
return HTTPC_GetDownloadSizeState(context->servhandle, context->httphandle, downloadedsize, contentsize);
|
||||
}
|
||||
|
||||
Result httpcGetResponseStatusCode(httpcContext *context, u32* out, u64 delay)
|
||||
{
|
||||
return HTTPC_GetResponseStatusCode(context->servhandle, context->httphandle, out);
|
||||
}
|
||||
|
||||
Result httpcDownloadData(httpcContext *context, u8* buffer, u32 size, u32 *downloadedsize)
|
||||
{
|
||||
Result ret=0;
|
||||
u32 contentsize=0;
|
||||
u32 pos=0, sz=0;
|
||||
|
||||
if(downloadedsize)*downloadedsize = 0;
|
||||
|
||||
ret=httpcGetDownloadSizeState(context, NULL, &contentsize);
|
||||
if(ret!=0)return ret;
|
||||
|
||||
while(pos < size)
|
||||
{
|
||||
sz = size - pos;
|
||||
|
||||
ret=httpcReceiveData(context, &buffer[pos], sz);
|
||||
|
||||
if(ret==HTTPC_RESULTCODE_DOWNLOADPENDING)
|
||||
{
|
||||
ret=httpcGetDownloadSizeState(context, &pos, NULL);
|
||||
if(ret!=0)return ret;
|
||||
}
|
||||
else if(ret!=0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos+= sz;
|
||||
}
|
||||
|
||||
if(downloadedsize)*downloadedsize = pos;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result HTTPC_Initialize(Handle handle)
|
||||
{
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0]=0x10044; //request header code
|
||||
cmdbuf[1]=0x1000; //unk
|
||||
cmdbuf[2]=0x20; //unk
|
||||
cmdbuf[2]=0x20;//processID header, following word is set to processID by the arm11kernel.
|
||||
cmdbuf[4]=0;
|
||||
cmdbuf[5]=0;//Some sort of handle.
|
||||
|
||||
Result ret=0;
|
||||
if((ret=svcSendSyncRequest(handle)))return ret;
|
||||
@ -124,3 +249,50 @@ Result HTTPC_ReceiveData(Handle handle, Handle contextHandle, u8* buffer, u32 si
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
Result HTTPC_GetRequestState(Handle handle, Handle contextHandle, httpcReqStatus* out)
|
||||
{
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0]=0x50040; //request header code
|
||||
cmdbuf[1]=contextHandle;
|
||||
|
||||
Result ret=0;
|
||||
if((ret=svcSendSyncRequest(handle)))return ret;
|
||||
|
||||
*out = cmdbuf[2];
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
Result HTTPC_GetDownloadSizeState(Handle handle, Handle contextHandle, u32* downloadedsize, u32* contentsize)
|
||||
{
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0]=0x60040; //request header code
|
||||
cmdbuf[1]=contextHandle;
|
||||
|
||||
Result ret=0;
|
||||
if((ret=svcSendSyncRequest(handle)))return ret;
|
||||
|
||||
if(downloadedsize)*downloadedsize = cmdbuf[2];
|
||||
if(contentsize)*contentsize = cmdbuf[3];
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
Result HTTPC_GetResponseStatusCode(Handle handle, Handle contextHandle, u32* out)
|
||||
{
|
||||
u32* cmdbuf=getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0]=0x220040; //request header code
|
||||
cmdbuf[1]=contextHandle;
|
||||
|
||||
Result ret=0;
|
||||
if((ret=svcSendSyncRequest(handle)))return ret;
|
||||
|
||||
*out = cmdbuf[2];
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
|
@ -63,9 +63,6 @@ Result MIC_Shutdown()
|
||||
|
||||
MIC_cmd5();
|
||||
|
||||
ret = svcUnmapMemoryBlock(MIC_sharedmem_handle, (u32)MIC_sharedmem);
|
||||
if(ret!=0)return ret;
|
||||
|
||||
ret = svcCloseHandle(MIC_sharedmem_handle);
|
||||
if(ret!=0)return ret;
|
||||
|
||||
@ -207,7 +204,7 @@ Result MIC_GetEventHandle(Handle *handle)
|
||||
|
||||
if((ret = svcSendSyncRequest(MIC_handle))!=0)return ret;
|
||||
|
||||
if(handle)*handle = cmdbuf[2];
|
||||
if(handle)*handle = cmdbuf[3];
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <3ds.h>
|
||||
|
||||
static Handle pmHandle;
|
||||
|
@ -13,6 +13,21 @@ Result ptmExit()
|
||||
return svcCloseHandle(ptmHandle);
|
||||
}
|
||||
|
||||
Result PTMU_GetShellState(Handle* servhandle, u8 *out)
|
||||
{
|
||||
if(!servhandle)servhandle=&ptmHandle;
|
||||
Result ret=0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = 0x00060000;
|
||||
|
||||
if((ret = svcSendSyncRequest(*servhandle))!=0)return ret;
|
||||
|
||||
*out = (u8)cmdbuf[2];
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result PTMU_GetBatteryLevel(Handle* servhandle, u8 *out)
|
||||
{
|
||||
if(!servhandle)servhandle=&ptmHandle;
|
||||
@ -42,3 +57,33 @@ Result PTMU_GetBatteryChargeState(Handle* servhandle, u8 *out)
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result PTMU_GetPedometerState(Handle* servhandle, u8 *out)
|
||||
{
|
||||
if(!servhandle)servhandle=&ptmHandle;
|
||||
Result ret=0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = 0x00090000;
|
||||
|
||||
if((ret = svcSendSyncRequest(*servhandle))!=0)return ret;
|
||||
|
||||
*out = (u8)cmdbuf[2];
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result PTMU_GetTotalStepCount(Handle* servhandle, u32 *steps)
|
||||
{
|
||||
if(!servhandle)servhandle=&ptmHandle;
|
||||
Result ret=0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = 0x000C0000;
|
||||
|
||||
if((ret = svcSendSyncRequest(*servhandle))!=0)return ret;
|
||||
|
||||
*steps = cmdbuf[2];
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <string.h>
|
||||
#include <3ds.h>
|
||||
|
||||
extern Handle SOCU_handle;
|
||||
|
@ -16,15 +16,24 @@ int ioctl(int fd, int request, ...)
|
||||
switch(request) {
|
||||
case FIONBIO:
|
||||
value = va_arg(ap, int*);
|
||||
if(value == NULL) ret = -1;
|
||||
else if(*value) {
|
||||
flags = fcntl(fd, F_GETFL, 0);
|
||||
ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
||||
if(value == NULL) {
|
||||
errno = EFAULT;
|
||||
ret = -1;
|
||||
}
|
||||
else {
|
||||
|
||||
flags = fcntl(fd, F_GETFL, 0);
|
||||
ret = fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
|
||||
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);
|
||||
|
||||
if(ret != 0)
|
||||
errno = SOC_GetErrno();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -33,5 +42,7 @@ int ioctl(int fd, int request, ...)
|
||||
break;
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1,19 +1,10 @@
|
||||
.arm
|
||||
.align 4
|
||||
|
||||
/* THIS DOES NOT BELONG HERE */
|
||||
.global getThreadCommandBuffer
|
||||
.type getThreadCommandBuffer, %function
|
||||
getThreadCommandBuffer:
|
||||
mrc p15, 0, r0, c13, c0, 3
|
||||
add r0, #0x80
|
||||
bx lr
|
||||
|
||||
|
||||
.global svcControlMemory
|
||||
.type svcControlMemory, %function
|
||||
svcControlMemory:
|
||||
stmfd sp!, {r0, r4}
|
||||
push {r0, r4}
|
||||
ldr r0, [sp, #0x8]
|
||||
ldr r4, [sp, #0x8+0x4]
|
||||
svc 0x01
|
||||
@ -25,8 +16,8 @@ svcControlMemory:
|
||||
.global svcQueryMemory
|
||||
.type svcQueryMemory, %function
|
||||
svcQueryMemory:
|
||||
stmfd sp!, {r0,r1,r4-r6}
|
||||
svc 2
|
||||
push {r0, r1, r4-r6}
|
||||
svc 0x02
|
||||
ldr r6, [sp]
|
||||
str r1, [r6]
|
||||
str r2, [r6, #4]
|
||||
@ -35,7 +26,7 @@ svcQueryMemory:
|
||||
ldr r6, [sp, #4]
|
||||
str r5, [r6]
|
||||
add sp, sp, #8
|
||||
ldmfd sp!, {r4-r6}
|
||||
pop {r4-r6}
|
||||
bx lr
|
||||
|
||||
.global svcExitProcess
|
||||
@ -47,7 +38,7 @@ svcExitProcess:
|
||||
.global svcCreateThread
|
||||
.type svcCreateThread, %function
|
||||
svcCreateThread:
|
||||
stmfd sp!, {r0, r4}
|
||||
push {r0, r4}
|
||||
ldr r0, [sp, #0x8]
|
||||
ldr r4, [sp, #0x8+0x4]
|
||||
svc 0x08
|
||||
@ -68,6 +59,12 @@ svcSleepThread:
|
||||
svc 0x0A
|
||||
bx lr
|
||||
|
||||
.global svcSetThreadPriority
|
||||
.type svcSetThreadPriority, %function
|
||||
svcSetThreadPriority:
|
||||
svc 0x0C
|
||||
bx lr
|
||||
|
||||
.global svcCreateMutex
|
||||
.type svcCreateMutex, %function
|
||||
svcCreateMutex:
|
||||
@ -187,11 +184,13 @@ svcWaitSynchronization:
|
||||
.type svcWaitSynchronizationN, %function
|
||||
svcWaitSynchronizationN:
|
||||
str r5, [sp, #-4]!
|
||||
str r4, [sp, #-4]!
|
||||
mov r5, r0
|
||||
ldr r0, [sp, #0x4]
|
||||
ldr r4, [sp, #0x4+0x4]
|
||||
ldr r0, [sp, #0x8]
|
||||
ldr r4, [sp, #0x8+0x4]
|
||||
svc 0x25
|
||||
str r1, [r5]
|
||||
ldr r4, [sp], #4
|
||||
ldr r5, [sp], #4
|
||||
bx lr
|
||||
|
||||
@ -213,7 +212,7 @@ svcGetSystemTick:
|
||||
.global svcGetSystemInfo
|
||||
.type svcGetSystemInfo, %function
|
||||
svcGetSystemInfo:
|
||||
stmfd sp!, {r0, r4}
|
||||
push {r0, r4}
|
||||
svc 0x2A
|
||||
ldr r4, [sp], #4
|
||||
str r1, [r4]
|
||||
@ -225,7 +224,7 @@ svcGetSystemInfo:
|
||||
.global svcGetProcessInfo
|
||||
.type svcGetProcessInfo, %function
|
||||
svcGetProcessInfo:
|
||||
stmfd sp!, {r0, r4}
|
||||
push {r0,r4}
|
||||
svc 0x2B
|
||||
ldr r4, [sp], #4
|
||||
str r1, [r4]
|
||||
@ -266,3 +265,29 @@ svcOutputDebugString:
|
||||
str r1, [r2]
|
||||
bx lr
|
||||
|
||||
.global svcCreateSemaphore
|
||||
.type svcCreateSemaphore, %function
|
||||
svcCreateSemaphore:
|
||||
push {r0}
|
||||
svc 0x15
|
||||
pop {r3}
|
||||
str r1, [r3]
|
||||
bx lr
|
||||
|
||||
.global svcReleaseSemaphore
|
||||
.type svcReleaseSemaphore, %function
|
||||
svcReleaseSemaphore:
|
||||
push {r0}
|
||||
svc 0x16
|
||||
pop {r3}
|
||||
str r1, [r3]
|
||||
bx lr
|
||||
|
||||
.global svcGetThreadId
|
||||
.type svcGetThreadId, %function
|
||||
svcGetThreadId:
|
||||
str r0, [sp, #-0x4]!
|
||||
svc 0x37
|
||||
ldr r3, [sp], #4
|
||||
str r1, [r3]
|
||||
bx lr
|
||||
|
@ -6,11 +6,6 @@ ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(CTRULIB)),)
|
||||
# THIS IS TEMPORARY - in the future it should be at $(DEVKITPRO)/libctru
|
||||
$(error "Please set CTRULIB in your environment. export CTRULIB=<path to>libctru")
|
||||
endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
include $(DEVKITARM)/3ds_rules
|
||||
|
||||
@ -118,6 +113,10 @@ else
|
||||
export APP_ICON := $(TOPDIR)/$(ICON)
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(NO_SMDH)),)
|
||||
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
|
||||
endif
|
||||
|
||||
.PHONY: $(BUILD) clean all
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
@ -142,10 +141,11 @@ DEPENDS := $(OFILES:.o=.d)
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(NO_SMDH)),)
|
||||
.PHONY: all
|
||||
all : $(OUTPUT).3dsx $(OUTPUT).smdh
|
||||
endif
|
||||
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
|
||||
else
|
||||
$(OUTPUT).3dsx : $(OUTPUT).elf
|
||||
endif
|
||||
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
|
@ -1,3 +1,5 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <3ds.h>
|
||||
|
||||
int main()
|
||||
|
Loading…
Reference in New Issue
Block a user