Merge branch 'master' of github.com:smealum/ctrulib

This commit is contained in:
smea 2014-12-09 21:49:30 -08:00
commit 1322d44f22
49 changed files with 1714 additions and 282 deletions

View File

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

View File

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

View File

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

View File

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

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

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

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,6 @@
#include <stdio.h>
#include <string.h>
#include <3ds.h>
#include "costable.h"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -4,7 +4,6 @@
#pragma once
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>

View File

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

View File

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

View File

@ -1,5 +1,6 @@
#pragma once
#include <3ds.h>
#include <stdlib.h>
struct MemChunk
{

View File

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

View File

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

View File

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

View File

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

View File

@ -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,8 +541,32 @@ 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
@ -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,

View File

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

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,5 @@
#include <stdlib.h>
#include <string.h>
#include <3ds.h>
static Handle pmHandle;

View File

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

View File

@ -1,5 +1,6 @@
#pragma once
#include <string.h>
#include <3ds.h>
extern Handle SOCU_handle;

View File

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

View File

@ -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,17 +16,17 @@ 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]
str r3, [r6,#8]
str r4, [r6,#0xc]
ldr r6, [sp,#4]
str r2, [r6, #4]
str r3, [r6, #8]
str r4, [r6, #0xc]
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:
@ -86,7 +83,7 @@ svcReleaseMutex:
.global svcCreateEvent
.type svcCreateEvent, %function
svcCreateEvent:
str r0, [sp,#-4]!
str r0, [sp, #-4]!
svc 0x17
ldr r2, [sp], #4
str r1, [r2]
@ -107,7 +104,7 @@ svcClearEvent:
.global svcCreateTimer
.type svcCreateTimer, %function
svcCreateTimer:
str r0, [sp,#-4]!
str r0, [sp, #-4]!
svc 0x1A
ldr r2, [sp], #4
str r1, [r2]
@ -162,13 +159,13 @@ svcCreateAddressArbiter:
.global svcArbitrateAddress
.type svcArbitrateAddress, %function
svcArbitrateAddress:
push {r4,r5}
push {r4, r5}
add sp, #8
ldr r5, [sp]
ldr r4, [sp, #4]
sub sp, #8
svc 0x22
pop {r4,r5}
pop {r4, r5}
bx lr
.global svcCloseHandle
@ -187,18 +184,20 @@ 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
.global svcDuplicateHandle
.type svcDuplicateHandle, %function
svcDuplicateHandle:
str r0, [sp,#-0x4]!
str r0, [sp, #-0x4]!
svc 0x27
ldr r3, [sp], #4
str r1, [r3]
@ -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]
@ -236,7 +235,7 @@ svcGetProcessInfo:
.global svcConnectToPort
.type svcConnectToPort, %function
svcConnectToPort:
str r0, [sp,#-0x4]!
str r0, [sp, #-0x4]!
svc 0x2D
ldr r3, [sp], #4
str r1, [r3]
@ -251,7 +250,7 @@ svcSendSyncRequest:
.global svcGetProcessId
.type svcGetProcessId, %function
svcGetProcessId:
str r0, [sp,#-0x4]!
str r0, [sp, #-0x4]!
svc 0x35
ldr r3, [sp], #4
str r1, [r3]
@ -260,9 +259,35 @@ svcGetProcessId:
.global svcOutputDebugString
.type svcOutputDebugString, %function
svcOutputDebugString:
str r0, [sp,#-0x4]!
str r0, [sp, #-0x4]!
svc 0x3D
ldr r2, [sp], #4
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

View File

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

View File

@ -1,3 +1,5 @@
#include <string.h>
#include <3ds.h>
int main()