Merge branch 'master' into gpu_revamp

This commit is contained in:
smea 2014-12-31 13:34:25 -08:00
commit 3c4c2a6c04
70 changed files with 2482 additions and 310 deletions

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,63 @@
/*
Hello World example made by Aurelio Mannara for ctrulib
This code was modified for the last time on: 12/12/2014 21:00 UTC+1
This wouldn't be possible without the amazing work done by:
-Smealum
-fincs
-WinterMute
-yellows8
-plutoo
-mtheall
-Many others who worked on 3DS and I'm surely forgetting about
*/
#include <3ds.h>
#include <stdio.h>
int main(int argc, char **argv)
{
// Initialize services
srvInit();
aptInit();
gfxInit();
hidInit(NULL);
//Initialize console on top screen. Using NULL as the second argument tells the console library to use the internal console structure as current one
consoleInit(GFX_TOP, NULL);
//Move the cursor to row 15 and column 19 and then prints "Hello World!"
//To move the cursor you have tu print "\x1b[r;cH", where r and c are respectively
//the row and column where you want your cursor to move
//The top screen has 30 rows and 50 columns
//The bottom screen has 30 rows and 40 columns
printf("\x1b[15;19HHello World!");
printf("\x1b[29;15HPress Start to exit.");
// Main loop
while (aptMainLoop())
{
//Scan all the inputs. This should be done once for each frame
hidScanInput();
//hidKeysDown returns information about which buttons have been just pressed (and they weren't in the previous frame)
u32 kDown = hidKeysDown();
if (kDown & KEY_START) break; // break in order to return to hbmenu
// Flush and swap framebuffers
gfxFlushBuffers();
gfxSwapBuffers();
//Wait for VBlank
gspWaitForVBlank();
}
// Exit services
gfxExit();
hidExit();
aptExit();
srvExit();
return 0;
}

6
examples/qtm/README.md Normal file
View File

@ -0,0 +1,6 @@
# qtm
This is an example for using New3DS QTM for head-tracking.
This is currently not usable from the homebrew launcher.

View File

@ -0,0 +1,92 @@
#include <string.h>
#include <stdio.h>
#include <3ds.h>
int main()
{
u32 pos;
u32 x, y;
Result ret;
bool qtm_usable;
qtmHeadtrackingInfo qtminfo;
u32 colors[4] = {0x0000FF, 0x00FF00, 0xFF0000, 0xFFFFFF};
// Initialize services
srvInit();
aptInit();
hidInit(NULL);
gfxInit();
//gfxSet3D(true); // uncomment if using stereoscopic 3D
qtmInit();
consoleInit(GFX_BOTTOM, NULL);
printf("qtm example\n");
qtm_usable = qtmCheckInitialized();
if(!qtm_usable)printf("QTM is not usable, therefore this example won't do anything with QTM.\n");
// Main loop
while (aptMainLoop())
{
gspWaitForVBlank();
hidScanInput();
u32 kDown = hidKeysDown();
if (kDown & KEY_START)
break; // break in order to return to hbmenu
if(qtm_usable)
{
u8* fb = gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL);
memset(fb, 0, 400*240*3);
ret = qtmGetHeadtrackingInfo(0, &qtminfo);
if(ret==0)
{
consoleClear();
for(pos=0; pos<5; pos++)
{
printf("flags[%x]=0x%x", (unsigned int)pos, qtminfo.flags[pos]);
if(pos<4)printf(", ");
}
printf("\nfloatdata_x08: %f\n", qtminfo.floatdata_x08);
printf("coords0: ");
for(pos=0; pos<4; pos++)
{
printf("[%x].x=%f, y=%f", (unsigned int)pos, qtminfo.coords0[pos].x, qtminfo.coords0[pos].y);
if(pos<3)printf(", ");
}
printf("\n");
if(qtmCheckHeadFullyDetected(&qtminfo))
{
for(pos=0; pos<4; pos++)
{
ret = qtmConvertCoordToScreen(&qtminfo.coords0[pos], NULL, NULL, &x, &y);
if(ret==0)memcpy(&fb[(x*240 + y) * 3], &colors[pos], 3);
}
}
}
}
// Flush and swap framebuffers
gfxFlushBuffers();
gfxSwapBuffers();
}
// Exit services
qtmExit();
gfxExit();
hidExit();
aptExit();
srvExit();
return 0;
}

View File

@ -1,6 +1,5 @@
sdmc sdmc
======= =======
very simple example of how to access SD files with ctrulib; requires proper exheader flags for direct SDMC access. very simple example of how to access SD files with libctru;
**WARNING/TODO**: THIS EXAMPLE IS OUTDATED AND NEEDS TO BE FIXED - PLEASE DO NOT LOOK AT IT UNTIL IT IS UPDATED

View File

@ -0,0 +1,50 @@
#include <3ds/types.h>
s32 costable[] = { 4096, 4095, 4094, 4093, 4091, 4088, 4084, 4080, 4076, 4071, 4065,
4058, 4051, 4044, 4035, 4026, 4017, 4007, 3996, 3985, 3973, 3960,
3947, 3934, 3919, 3904, 3889, 3873, 3856, 3839, 3821, 3803, 3784,
3765, 3744, 3724, 3703, 3681, 3659, 3636, 3612, 3588, 3564, 3539,
3513, 3487, 3461, 3434, 3406, 3378, 3349, 3320, 3290, 3260, 3229,
3198, 3167, 3135, 3102, 3069, 3035, 3002, 2967, 2932, 2897, 2861,
2825, 2788, 2751, 2714, 2676, 2638, 2599, 2560, 2521, 2481, 2441,
2401, 2360, 2318, 2277, 2235, 2193, 2150, 2107, 2064, 2020, 1976,
1932, 1888, 1843, 1798, 1753, 1707, 1662, 1616, 1569, 1523, 1476,
1429, 1382, 1334, 1287, 1239, 1191, 1143, 1095, 1046, 997, 949,
900, 851, 801, 752, 703, 653, 603, 554, 504, 454, 404, 354, 304,
254, 204, 153, 103, 53, 3, -46, -97, -147, -197, -247, -297, -347,
-398, -448, -497, -547, -597, -647, -696, -746, -795, -844, -893,
-942, -991, -1040, -1088, -1137, -1185, -1233, -1281, -1328, -1376,
-1423, -1470, -1517, -1563, -1610, -1656, -1701, -1747, -1792, -1837,
-1882, -1927, -1971, -2015, -2058, -2102, -2144, -2187, -2229, -2271,
-2313, -2354, -2395, -2436, -2476, -2516, -2555, -2594, -2633, -2671,
-2709, -2747, -2784, -2820, -2857, -2892, -2928, -2963, -2997, -3031,
-3065, -3098, -3130, -3163, -3194, -3225, -3256, -3286, -3316, -3345,
-3374, -3402, -3430, -3457, -3484, -3510, -3536, -3561, -3585, -3609,
-3633, -3656, -3678, -3700, -3721, -3742, -3762, -3782, -3801, -3819,
-3837, -3854, -3871, -3887, -3902, -3917, -3932, -3946, -3959, -3971,
-3983, -3995, -4005, -4016, -4025, -4034, -4042, -4050, -4057, -4064,
-4070, -4075, -4080, -4084, -4087, -4090, -4092, -4094, -4095, -4095,
-4095, -4094, -4093, -4091, -4088, -4085, -4081, -4076, -4071, -4066,
-4059, -4052, -4045, -4036, -4028, -4018, -4008, -3997, -3986, -3974,
-3962, -3949, -3935, -3921, -3906, -3891, -3875, -3858, -3841, -3824,
-3805, -3787, -3767, -3747, -3727, -3705, -3684, -3662, -3639, -3615,
-3592, -3567, -3542, -3517, -3491, -3464, -3437, -3409, -3381, -3353,
-3324, -3294, -3264, -3233, -3202, -3171, -3139, -3106, -3073, -3040,
-3006, -2972, -2937, -2902, -2866, -2830, -2793, -2756, -2719, -2681,
-2643, -2604, -2565, -2526, -2486, -2446, -2406, -2365, -2324, -2282,
-2240, -2198, -2156, -2113, -2069, -2026, -1982, -1938, -1894, -1849,
-1804, -1759, -1713, -1668, -1622, -1575, -1529, -1482, -1435, -1388,
-1341, -1293, -1245, -1197, -1149, -1101, -1052, -1004, -955, -906,
-857, -808, -758, -709, -660, -610, -560, -510, -460, -411, -360,
-310, -260, -210, -160, -110, -60, -9, 40, 90, 140, 191, 241, 291,
341, 391, 441, 491, 541, 591, 640, 690, 739, 789, 838, 887, 936,
985, 1033, 1082, 1130, 1179, 1227, 1274, 1322, 1370, 1417, 1464,
1511, 1557, 1604, 1650, 1695, 1741, 1786, 1831, 1876, 1921, 1965,
2009, 2053, 2096, 2139, 2182, 2224, 2266, 2308, 2349, 2390, 2431,
2471, 2511, 2550, 2589, 2628, 2666, 2704, 2742, 2779, 2816, 2852,
2888, 2923, 2958, 2993, 3027, 3060, 3093, 3126, 3158, 3190, 3221,
3252, 3282, 3312, 3342, 3370, 3399, 3426, 3454, 3480, 3507, 3532,
3557, 3582, 3606, 3630, 3653, 3675, 3697, 3718, 3739, 3759, 3779,
3798, 3817, 3835, 3852, 3869, 3885, 3900, 3915, 3930, 3944, 3957,
3970, 3982, 3993, 4004, 4014, 4024, 4033, 4041, 4049, 4056, 4063,
4069, 4074, 4079, 4083, 4087, 4090, 4092, 4094, 4095};

View File

@ -1,6 +1,6 @@
#ifndef COSTABLE_H #ifndef COSTABLE_H
#define COSTABLE_H #define COSTABLE_H
s32 costable[] = {4096, 4095, 4094, 4093, 4091, 4088, 4084, 4080, 4076, 4071, 4065, 4058, 4051, 4044, 4035, 4026, 4017, 4007, 3996, 3985, 3973, 3960, 3947, 3934, 3919, 3904, 3889, 3873, 3856, 3839, 3821, 3803, 3784, 3765, 3744, 3724, 3703, 3681, 3659, 3636, 3612, 3588, 3564, 3539, 3513, 3487, 3461, 3434, 3406, 3378, 3349, 3320, 3290, 3260, 3229, 3198, 3167, 3135, 3102, 3069, 3035, 3002, 2967, 2932, 2897, 2861, 2825, 2788, 2751, 2714, 2676, 2638, 2599, 2560, 2521, 2481, 2441, 2401, 2360, 2318, 2277, 2235, 2193, 2150, 2107, 2064, 2020, 1976, 1932, 1888, 1843, 1798, 1753, 1707, 1662, 1616, 1569, 1523, 1476, 1429, 1382, 1334, 1287, 1239, 1191, 1143, 1095, 1046, 997, 949, 900, 851, 801, 752, 703, 653, 603, 554, 504, 454, 404, 354, 304, 254, 204, 153, 103, 53, 3, -46, -97, -147, -197, -247, -297, -347, -398, -448, -497, -547, -597, -647, -696, -746, -795, -844, -893, -942, -991, -1040, -1088, -1137, -1185, -1233, -1281, -1328, -1376, -1423, -1470, -1517, -1563, -1610, -1656, -1701, -1747, -1792, -1837, -1882, -1927, -1971, -2015, -2058, -2102, -2144, -2187, -2229, -2271, -2313, -2354, -2395, -2436, -2476, -2516, -2555, -2594, -2633, -2671, -2709, -2747, -2784, -2820, -2857, -2892, -2928, -2963, -2997, -3031, -3065, -3098, -3130, -3163, -3194, -3225, -3256, -3286, -3316, -3345, -3374, -3402, -3430, -3457, -3484, -3510, -3536, -3561, -3585, -3609, -3633, -3656, -3678, -3700, -3721, -3742, -3762, -3782, -3801, -3819, -3837, -3854, -3871, -3887, -3902, -3917, -3932, -3946, -3959, -3971, -3983, -3995, -4005, -4016, -4025, -4034, -4042, -4050, -4057, -4064, -4070, -4075, -4080, -4084, -4087, -4090, -4092, -4094, -4095, -4095, -4095, -4094, -4093, -4091, -4088, -4085, -4081, -4076, -4071, -4066, -4059, -4052, -4045, -4036, -4028, -4018, -4008, -3997, -3986, -3974, -3962, -3949, -3935, -3921, -3906, -3891, -3875, -3858, -3841, -3824, -3805, -3787, -3767, -3747, -3727, -3705, -3684, -3662, -3639, -3615, -3592, -3567, -3542, -3517, -3491, -3464, -3437, -3409, -3381, -3353, -3324, -3294, -3264, -3233, -3202, -3171, -3139, -3106, -3073, -3040, -3006, -2972, -2937, -2902, -2866, -2830, -2793, -2756, -2719, -2681, -2643, -2604, -2565, -2526, -2486, -2446, -2406, -2365, -2324, -2282, -2240, -2198, -2156, -2113, -2069, -2026, -1982, -1938, -1894, -1849, -1804, -1759, -1713, -1668, -1622, -1575, -1529, -1482, -1435, -1388, -1341, -1293, -1245, -1197, -1149, -1101, -1052, -1004, -955, -906, -857, -808, -758, -709, -660, -610, -560, -510, -460, -411, -360, -310, -260, -210, -160, -110, -60, -9, 40, 90, 140, 191, 241, 291, 341, 391, 441, 491, 541, 591, 640, 690, 739, 789, 838, 887, 936, 985, 1033, 1082, 1130, 1179, 1227, 1274, 1322, 1370, 1417, 1464, 1511, 1557, 1604, 1650, 1695, 1741, 1786, 1831, 1876, 1921, 1965, 2009, 2053, 2096, 2139, 2182, 2224, 2266, 2308, 2349, 2390, 2431, 2471, 2511, 2550, 2589, 2628, 2666, 2704, 2742, 2779, 2816, 2852, 2888, 2923, 2958, 2993, 3027, 3060, 3093, 3126, 3158, 3190, 3221, 3252, 3282, 3312, 3342, 3370, 3399, 3426, 3454, 3480, 3507, 3532, 3557, 3582, 3606, 3630, 3653, 3675, 3697, 3718, 3739, 3759, 3779, 3798, 3817, 3835, 3852, 3869, 3885, 3900, 3915, 3930, 3944, 3957, 3970, 3982, 3993, 4004, 4014, 4024, 4033, 4041, 4049, 4056, 4063, 4069, 4074, 4079, 4083, 4087, 4090, 4092, 4094, 4095}; extern s32 costable[];
#endif #endif

View File

@ -3,9 +3,11 @@
/////////////////////////////////////// ///////////////////////////////////////
//this example shows you how to load a binary image file from the SD card and display it on the lower screen //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 //for this to work you should copy test.bin to same folder as your .3dsx
//this file was generated with GIMP by saving a 240x320 image to raw RGB //this file was generated with GIMP by saving a 240x320 image to raw RGB
#include <string.h> #include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <3ds.h> #include <3ds.h>
#include "costable.h" #include "costable.h"
@ -42,42 +44,33 @@ void renderEffect()
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
//initialize the services we're going to be using
srvInit(); //needed for everything
aptInit(); //needed for everything
hidInit(NULL); //needed for input
gfxInit(); //makes displaying to screen easier gfxInit(); //makes displaying to screen easier
fsInit(); //needed for filesystem stuff
u64 size; FILE *file = fopen("test.bin","rb");
u32 bytesRead; if (file == NULL) goto exit;
Handle fileHandle;
//setup SDMC archive
FS_archive sdmcArchive=(FS_archive){ARCH_SDMC, (FS_path){PATH_EMPTY, 1, (u8*)""}};
//create file path struct (note : FS_makePath actually only supports PATH_CHAR, it will change in the future)
FS_path filePath=FS_makePath(PATH_CHAR, "/test.bin");
//open file // seek to end of file
Result ret=FSUSER_OpenFileDirectly(NULL, &fileHandle, sdmcArchive, filePath, FS_OPEN_READ, FS_ATTRIBUTE_NONE); fseek(file,0,SEEK_END);
//check for errors : exit if there is one
if(ret)goto exit;
//get file size // file pointer tells us the size
ret=FSFILE_GetSize(fileHandle, &size); off_t size = ftell(file);
if(ret)goto exit;
//allocate a buffer on linear heap (could just be a malloc fwiw) // seek back to start
buffer=linearAlloc(size); fseek(file,0,SEEK_SET);
//allocate a buffer
buffer=malloc(size);
if(!buffer)goto exit; if(!buffer)goto exit;
//read contents ! //read contents !
ret=FSFILE_Read(fileHandle, &bytesRead, 0x0, buffer, size); off_t bytesRead = fread(buffer,1,size,file);
if(ret || size!=bytesRead)goto exit;
//close the file because we like being nice and tidy //close the file because we like being nice and tidy
ret=FSFILE_Close(fileHandle); fclose(file);
if(ret)goto exit;
if(size!=bytesRead)goto exit;
while(aptMainLoop()) while(aptMainLoop())
{ {
//exit when user hits B //exit when user hits B
@ -98,13 +91,8 @@ int main(int argc, char** argv)
//cleanup and return //cleanup and return
//returning from main() returns to hbmenu when run under ninjhax //returning from main() returns to hbmenu when run under ninjhax
exit: exit:
//closing all handles is super important
svcCloseHandle(fileHandle);
//closing all services even more so //closing all services even more so
fsExit();
gfxExit(); gfxExit();
hidExit();
aptExit();
srvExit();
return 0; return 0;
} }

View File

@ -0,0 +1,175 @@
#---------------------------------------------------------------------------------
.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
ifeq ($(strip $(NO_SMDH)),)
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
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)),)
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
else
$(OUTPUT).3dsx : $(OUTPUT).elf
endif
$(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,3 @@
# template
This is a template for starting new 3DS libctru projects.

View File

@ -0,0 +1,121 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
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
#---------------------------------------------------------------------------------
TARGET := $(shell basename $(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\
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
ASFLAGS := -g $(ARCH)
#---------------------------------------------------------------------------------
# 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)/lib/lib$(TARGET).a
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)
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
lib:
@[ -d $@ ] || mkdir -p $@
$(BUILD): lib
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) lib
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT) : $(OFILES)
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,3 @@
# template
This is a template for starting new 3DS library projects.

View File

@ -0,0 +1,6 @@
#ifndef _templatelib_h_
#define _templatelib_h_
int myLibFunction();
#endif // _templatelib_h_

View File

@ -0,0 +1,6 @@
int myLibFunction() {
return 42;
}

View File

@ -29,7 +29,9 @@ SOURCES := source \
source/gpu \ source/gpu \
source/services \ source/services \
source/services/soc \ source/services/soc \
source/util source/util \
source/system
DATA := data DATA := data
INCLUDES := include INCLUDES := include

Binary file not shown.

View File

@ -9,8 +9,10 @@ extern "C" {
#include <3ds/svc.h> #include <3ds/svc.h>
#include <3ds/srv.h> #include <3ds/srv.h>
#include <3ds/linear.h> #include <3ds/linear.h>
#include <3ds/vram.h>
#include <3ds/os.h> #include <3ds/os.h>
#include <3ds/gfx.h> #include <3ds/gfx.h>
#include <3ds/console.h>
#include <3ds/services/ac.h> #include <3ds/services/ac.h>
#include <3ds/services/apt.h> #include <3ds/services/apt.h>
@ -27,6 +29,8 @@ extern "C" {
#include <3ds/services/soc.h> #include <3ds/services/soc.h>
#include <3ds/services/mic.h> #include <3ds/services/mic.h>
#include <3ds/services/mvd.h> #include <3ds/services/mvd.h>
#include <3ds/services/qtm.h>
#include <3ds/services/hb.h>
#include <3ds/gpu/gx.h> #include <3ds/gpu/gx.h>
#include <3ds/gpu/gpu.h> #include <3ds/gpu/gpu.h>

View File

@ -0,0 +1,159 @@
/*! \file console.h
\brief 3ds stdio support.
<div class="fileHeader">
Provides stdio integration for printing to the 3DS screen as well as debug print
functionality provided by stderr.
General usage is to initialize the console by:
consoleDemoInit()
or to customize the console usage by:
consoleInit()
*/
#ifndef CONSOLE_H
#define CONSOLE_H
#include <3ds/types.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef bool(* ConsolePrint)(void* con, char c);
//! a font struct for the console.
typedef struct ConsoleFont
{
u8* gfx; //!< A pointer to the font graphics
u16 asciiOffset; //!< Offset to the first valid character in the font table
u16 numChars; //!< Number of characters in the font graphics
}ConsoleFont;
/** \brief console structure used to store the state of a console render context.
Default values from consoleGetDefault();
<div class="fixedFont"><pre>
PrintConsole defaultConsole =
{
//Font:
{
(u8*)default_font_bin, //font gfx
0, //first ascii character in the set
128, //number of characters in the font set
},
0,0, //cursorX cursorY
0,0, //prevcursorX prevcursorY
40, //console width
30, //console height
0, //window x
0, //window y
32, //window width
24, //window height
3, //tab size
0, //font character offset
0, //print callback
false //console initialized
};
</pre></div>
*/
typedef struct PrintConsole
{
ConsoleFont font; //!< font of the console.
u16 *frameBuffer; //!< framebuffer address.
int cursorX; /*!< Current X location of the cursor (as a tile offset by default) */
int cursorY; /*!< Current Y location of the cursor (as a tile offset by default) */
int prevCursorX; /*!< Internal state */
int prevCursorY; /*!< Internal state */
int consoleWidth; /*!< Width of the console hardware layer in characters */
int consoleHeight; /*!< Height of the console hardware layer in characters */
int windowX; /*!< Window X location in characters (not implemented) */
int windowY; /*!< Window Y location in characters (not implemented) */
int windowWidth; /*!< Window width in characters (not implemented) */
int windowHeight; /*!< Window height in characters (not implemented) */
int tabSize; /*!< Size of a tab*/
int fg; /*!< foreground color*/
int bg; /*!< background color*/
int flags; /*!< reverse/bright flags*/
ConsolePrint PrintChar; /*!< callback for printing a character. Should return true if it has handled rendering the graphics
(else the print engine will attempt to render via tiles) */
bool consoleInitialised; /*!< True if the console is initialized */
}PrintConsole;
#define CONSOLE_COLOR_BOLD (1<<0)
#define CONSOLE_COLOR_FAINT (1<<1)
#define CONSOLE_ITALIC (1<<2)
#define CONSOLE_UNDERLINE (1<<3)
#define CONSOLE_BLINK_SLOW (1<<4)
#define CONSOLE_BLINK_FAST (1<<5)
#define CONSOLE_COLOR_REVERSE (1<<6)
#define CONSOLE_CONCEAL (1<<7)
#define CONSOLE_CROSSED_OUT (1<<8)
//! Console debug devices supported by libnds.
typedef enum {
debugDevice_NULL, //!< swallows prints to stderr
debugDevice_3DMOO, //!< Directs stderr debug statements to 3dmoo
debugDevice_CONSOLE, //!< Directs stderr debug statements to 3DS console window
} debugDevice;
/*! \brief Loads the font into the console
\param console pointer to the console to update, if NULL it will update the current console
\param font the font to load
*/
void consoleSetFont(PrintConsole* console, ConsoleFont* font);
/*! \brief Sets the print window
\param console console to set, if NULL it will set the current console window
\param x x location of the window
\param y y location of the window
\param width width of the window
\param height height of the window
*/
void consoleSetWindow(PrintConsole* console, int x, int y, int width, int height);
/*! \brief Gets a pointer to the console with the default values
this should only be used when using a single console or without changing the console that is returned, other wise use consoleInit()
\return A pointer to the console with the default values
*/
PrintConsole* consoleGetDefault(void);
/*! \brief Make the specified console the render target
\param console A pointer to the console struct (must have been initialized with consoleInit(PrintConsole* console)
\return a pointer to the previous console
*/
PrintConsole *consoleSelect(PrintConsole* console);
/*! \brief Initialise the console.
\param screen The screen to use for the console
\param console A pointer to the console data to initialze (if it's NULL, the default console will be used)
\return A pointer to the current console.
*/
PrintConsole* consoleInit(gfxScreen_t screen, PrintConsole* console);
/*! \brief Initializes debug console output on stderr to the specified device
\param device The debug device (or devices) to output debug print statements to
*/
void consoleDebugInit(debugDevice device);
//! Clears the screan by using iprintf("\x1b[2J");
void consoleClear(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -2,6 +2,9 @@
#include <3ds/types.h> #include <3ds/types.h>
#include <3ds/services/gsp.h> #include <3ds/services/gsp.h>
#define RGB565(r,g,b) (((b)&0x1f)|(((g)&0x3f)<<5)|(((r)&0x1f)<<11))
#define RGB8_to_565(r,g,b) (((b)>>3)&0x1f)|((((g)>>2)&0x3f)<<5)|((((r)>>3)&0x1f)<<11)
typedef enum typedef enum
{ {
GFX_TOP = 0, GFX_TOP = 0,
@ -22,7 +25,8 @@ void gfxExit();
//control stuff //control stuff
void gfxSet3D(bool enable); void gfxSet3D(bool enable);
void gfxSetScreenFormat(gfxScreen_t screen, GSP_FramebufferFormats format); void gfxSetScreenFormat(gfxScreen_t screen, GSP_FramebufferFormats format);
void gfxSetDoubleBuffering(bool doubleBuffering); GSP_FramebufferFormats gfxGetScreenFormat(gfxScreen_t screen);
void gfxSetDoubleBuffering(gfxScreen_t screen, bool doubleBuffering);
void gfxFlushBuffers(); void gfxFlushBuffers();
void gfxSwapBuffers(); void gfxSwapBuffers();
void gfxSwapBuffersGpu(); void gfxSwapBuffersGpu();

View File

@ -0,0 +1,27 @@
#ifndef HB_H
#define HB_H
// WARNING ! THIS FILE PROVIDES AN INTERFACE TO A NON-OFFICIAL SERVICE PROVIDED BY NINJHAX
// BY USING COMMANDS FROM THIS SERVICE YOU WILL LIKELY MAKE YOUR APPLICATION INCOMPATIBLE WITH OTHER HOMEBREW LAUNCHING METHODS
// A GOOD WAY TO COPE WITH THIS IS TO CHECK THE OUTPUT OF initHb FOR ERRORS
#include <3ds/types.h>
Result hbInit();
void hbExit();
// flushes/invalidates entire data/instruction cache
// can be useful when writing code to executable pages
Result HB_FlushInvalidateCache(void);
// fetches the address for ninjhax bootloader addresses, useful for running 3dsx executables
// void (*callBootloader)(Handle hb, Handle file);
// void (*setArgs)(u32* src, u32 length);
Result HB_GetBootloaderAddresses(void** load3dsx, void** setArgv);
// changes the permissions of a given number of pages at address addr to mode
// should it fail, the appropriate kernel error code will be returned and *reprotectedPages (if not NULL)
// will be set to the number of sequential pages which were successfully reprotected + 1
Result HB_ReprotectMemory(u32* addr, u32 pages, u32 mode, u32* reprotectedPages);
#endif

View File

@ -102,4 +102,5 @@ Result HIDUSER_EnableAccelerometer();
Result HIDUSER_DisableAccelerometer(); Result HIDUSER_DisableAccelerometer();
Result HIDUSER_EnableGyroscope(); Result HIDUSER_EnableGyroscope();
Result HIDUSER_DisableGyroscope(); Result HIDUSER_DisableGyroscope();
Result HIDUSER_GetGyroscopeRawToDpsCoefficient(float *coeff);
Result HIDUSER_GetSoundVolume(u8 *volume); //Return the volume slider value (0-63)

View File

@ -14,7 +14,7 @@ About: Launches a title
titleid TitleId of title to launch titleid TitleId of title to launch
launch_flags use if you know of any launch_flags use if you know of any
*/ */
Result PM_LaunchTitle(u8 mediatype, u64 titleid); Result PM_LaunchTitle(u8 mediatype, u64 titleid, u32 launch_flags);
/* PM_GetTitleExheaderFlags() /* PM_GetTitleExheaderFlags()
About: Writes to a buffer the launch flags (8 bytes) from a title exheader. About: Writes to a buffer the launch flags (8 bytes) from a title exheader.
@ -28,7 +28,7 @@ Result PM_GetTitleExheaderFlags(u8 mediatype, u64 titleid, u8* out);
/* PM_SetFIRMLaunchParams() /* PM_SetFIRMLaunchParams()
About: Sets the FIRM launch params from in About: Sets the FIRM launch params from in
size size of FIRM launch params size size of FIRM launch params
in ptr to location of FIRM launch params in ptr to location of FIRM launch params
*/ */
Result PM_SetFIRMLaunchParams(u32 size, u8* in); Result PM_SetFIRMLaunchParams(u32 size, u8* in);
@ -36,7 +36,7 @@ Result PM_SetFIRMLaunchParams(u32 size, u8* in);
/* PM_GetFIRMLaunchParams() /* PM_GetFIRMLaunchParams()
About: Sets the FIRM launch params from in About: Sets the FIRM launch params from in
size size of buffer to store FIRM launch params size size of buffer to store FIRM launch params
out ptr to location to write FIRM launch params out ptr to location to write FIRM launch params
*/ */
Result PM_GetFIRMLaunchParams(u32 size, u8* out); Result PM_GetFIRMLaunchParams(u32 size, u8* out);
@ -45,7 +45,7 @@ Result PM_GetFIRMLaunchParams(u32 size, u8* out);
About: Same as PM_SetFIRMLaunchParams(), but also triggers a FIRM launch About: Same as PM_SetFIRMLaunchParams(), but also triggers a FIRM launch
firm_titleid_low TitleID low of firm title to launch firm_titleid_low TitleID low of firm title to launch
size size of FIRM launch params size size of FIRM launch params
in ptr to location of FIRM launch params in ptr to location of FIRM launch params
*/ */
Result PM_LaunchFIRMSetParams(u64 firm_titleid_low, u32 size, u8* in); Result PM_LaunchFIRMSetParams(u32 firm_titleid_low, u32 size, u8* in);

View File

@ -0,0 +1,25 @@
#pragma once
//See also: http://3dbrew.org/wiki/QTM_Services
typedef struct {
float x;
float y;
} qtmHeadtrackingInfoCoord;
typedef struct {
u8 flags[5];
u8 padding[3];
float floatdata_x08;//"not used by System_Settings."
qtmHeadtrackingInfoCoord coords0[4];
u32 unk_x2c[5];//"Not used by System_Settings."
} qtmHeadtrackingInfo;
Result qtmInit();
void qtmExit();
bool qtmCheckInitialized();
Result qtmGetHeadtrackingInfo(u64 val, qtmHeadtrackingInfo *out);//val is normally 0.
bool qtmCheckHeadFullyDetected(qtmHeadtrackingInfo *info);
Result qtmConvertCoordToScreen(qtmHeadtrackingInfoCoord *coord, float *screen_width, float *screen_height, u32 *x, u32 *y);//screen_* can be NULL to use the default values for the top-screen.

View File

@ -16,10 +16,11 @@ typedef enum {
} MemOp; } MemOp;
typedef enum { typedef enum {
MEMPERM_READ =1, MEMPERM_READ = 1,
MEMPERM_WRITE =2, MEMPERM_WRITE = 2,
MEMPERM_EXECUTE=4, MEMPERM_EXECUTE = 4,
MEMPERM_MAX =0xFFFFFFFF //force 4-byte MEMPERM_DONTCARE = 0x10000000,
MEMPERM_MAX = 0xFFFFFFFF //force 4-byte
} MemPerm; } MemPerm;
typedef struct { typedef struct {

View File

@ -0,0 +1,8 @@
#pragma once
// Functions for allocating/deallocating VRAM
void* vramAlloc(size_t size); // returns a 16-byte aligned address
void* vramMemAlign(size_t size, size_t alignment);
void* vramRealloc(void* mem, size_t size); // not implemented yet
void vramFree(void* mem);
u32 vramSpaceFree(); // get free VRAM space in bytes

View File

@ -0,0 +1,48 @@
#pragma once
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);
}

View File

@ -1,57 +1,16 @@
#include <3ds.h> extern "C"
#include <3ds/util/rbtree.h> {
#include <3ds/types.h>
#include <3ds/linear.h>
#include <3ds/util/rbtree.h>
}
#include "mem_pool.h" #include "mem_pool.h"
#include "addrmap.h"
extern u32 __linear_heap, __linear_heap_size; extern u32 __linear_heap, __linear_heap_size;
static MemPool sLinearPool; 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() static bool linearInit()
{ {

View File

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

View File

@ -0,0 +1,86 @@
extern "C"
{
#include <3ds/types.h>
#include <3ds/vram.h>
#include <3ds/util/rbtree.h>
}
#include "mem_pool.h"
#include "addrmap.h"
static MemPool sVramPool;
static bool vramInit()
{
auto blk = MemBlock::Create((u8*)0x1F000000, 0x00600000);
if (blk)
{
sVramPool.AddBlock(blk);
rbtree_init(&sAddrMap, addrMapNodeComparator);
return true;
}
return false;
}
void* vramMemAlign(size_t size, size_t alignment)
{
// Enforce minimum alignment
if (alignment < 16)
alignment = 16;
// Convert alignment to shift amount
int shift;
for (shift = 4; shift < 32; shift ++)
{
if ((1U<<shift) == alignment)
break;
}
if (shift == 32) // Invalid alignment
return nullptr;
// Initialize the pool if it is not ready
if (!sVramPool.Ready() && !vramInit())
return nullptr;
// Allocate the chunk
MemChunk chunk;
if (!sVramPool.Allocate(chunk, size, shift))
return nullptr;
auto node = newNode(chunk);
if (!node)
{
sVramPool.Deallocate(chunk);
return nullptr;
}
if (rbtree_insert(&sAddrMap, &node->node));
return chunk.addr;
}
void* vramAlloc(size_t size)
{
return vramMemAlign(size, 16);
}
void* vramRealloc(void* mem, size_t size)
{
// TODO
return NULL;
}
void vramFree(void* mem)
{
auto node = getNode(mem);
if (!node) return;
// Free the chunk
sVramPool.Deallocate(node->chunk);
// Free the node
delNode(node);
}
u32 vramSpaceFree()
{
return sVramPool.GetFreeSpace();
}

751
libctru/source/console.c Normal file
View File

@ -0,0 +1,751 @@
#include <stdio.h>
#include <string.h>
#include <sys/iosupport.h>
#include <3ds/gfx.h>
#include <3ds/console.h>
#include <3ds/svc.h>
#include "default_font_bin.h"
//set up the palette for color printing
static u16 colorTable[] = {
RGB8_to_565( 0, 0, 0), // black
RGB8_to_565(128, 0, 0), // red
RGB8_to_565( 0,128, 0), // green
RGB8_to_565(128,128, 0), // yellow
RGB8_to_565( 0, 0,128), // blue
RGB8_to_565(128, 0,128), // magenta
RGB8_to_565( 0,128,128), // cyan
RGB8_to_565(192,192,192), // white
RGB8_to_565(128,128,128), // bright black
RGB8_to_565(255, 0, 0), // bright red
RGB8_to_565( 0,255, 0), // bright green
RGB8_to_565(255,255, 0), // bright yellow
RGB8_to_565( 0, 0,255), // bright blue
RGB8_to_565(255, 0,255), // bright magenta
RGB8_to_565( 0,255,255), // bright cyan
RGB8_to_565(255,255,255), // bright white
RGB8_to_565( 0, 0, 0), // faint black
RGB8_to_565( 64, 0, 0), // faint red
RGB8_to_565( 0, 64, 0), // faint green
RGB8_to_565( 64, 64, 0), // faint yellow
RGB8_to_565( 0, 0, 64), // faint blue
RGB8_to_565( 64, 0, 64), // faint magenta
RGB8_to_565( 0, 64, 64), // faint cyan
RGB8_to_565( 96, 96, 96), // faint white
};
PrintConsole defaultConsole =
{
//Font:
{
(u8*)default_font_bin, //font gfx
0, //first ascii character in the set
128 //number of characters in the font set
},
(u16*)NULL,
0,0, //cursorX cursorY
0,0, //prevcursorX prevcursorY
40, //console width
30, //console height
0, //window x
0, //window y
40, //window width
30, //window height
3, //tab size
7, // foreground color
0, // background color
0, // flags
0, //print callback
false //console initialized
};
PrintConsole currentCopy;
PrintConsole* currentConsole = &currentCopy;
PrintConsole* consoleGetDefault(void){return &defaultConsole;}
void consolePrintChar(char c);
void consoleDrawChar(int c);
//---------------------------------------------------------------------------------
static void consoleCls(char mode) {
//---------------------------------------------------------------------------------
int i = 0;
int colTemp,rowTemp;
switch (mode)
{
case '[':
case '0':
{
colTemp = currentConsole->cursorX ;
rowTemp = currentConsole->cursorY ;
while(i++ < ((currentConsole->windowHeight * currentConsole->windowWidth) - (rowTemp * currentConsole->consoleWidth + colTemp)))
consolePrintChar(' ');
currentConsole->cursorX = colTemp;
currentConsole->cursorY = rowTemp;
break;
}
case '1':
{
colTemp = currentConsole->cursorX ;
rowTemp = currentConsole->cursorY ;
currentConsole->cursorY = 0;
currentConsole->cursorX = 0;
while (i++ < (rowTemp * currentConsole->windowWidth + colTemp))
consolePrintChar(' ');
currentConsole->cursorX = colTemp;
currentConsole->cursorY = rowTemp;
break;
}
case '2':
{
currentConsole->cursorY = 0;
currentConsole->cursorX = 0;
while(i++ < currentConsole->windowHeight * currentConsole->windowWidth)
consolePrintChar(' ');
currentConsole->cursorY = 0;
currentConsole->cursorX = 0;
break;
}
}
}
//---------------------------------------------------------------------------------
static void consoleClearLine(char mode) {
//---------------------------------------------------------------------------------
int i = 0;
int colTemp;
switch (mode)
{
case '[':
case '0':
{
colTemp = currentConsole->cursorX ;
while(i++ < (currentConsole->windowWidth - colTemp)) {
consolePrintChar(' ');
}
currentConsole->cursorX = colTemp;
break;
}
case '1':
{
colTemp = currentConsole->cursorX ;
currentConsole->cursorX = 0;
while(i++ < ((currentConsole->windowWidth - colTemp)-2)) {
consolePrintChar(' ');
}
currentConsole->cursorX = colTemp;
break;
}
case '2':
{
colTemp = currentConsole->cursorX ;
currentConsole->cursorX = 0;
while(i++ < currentConsole->windowWidth) {
consolePrintChar(' ');
}
currentConsole->cursorX = colTemp;
break;
}
}
}
//---------------------------------------------------------------------------------
ssize_t con_write(struct _reent *r,int fd,const char *ptr, size_t len) {
//---------------------------------------------------------------------------------
char chr;
int i, count = 0;
char *tmp = (char*)ptr;
if(!tmp || len<=0) return -1;
i = 0;
while(i<len) {
chr = *(tmp++);
i++; count++;
if ( chr == 0x1b && *tmp == '[' ) {
bool escaping = true;
char *escapeseq = tmp++;
int escapelen = 1;
i++; count++;
do {
chr = *(tmp++);
i++; count++; escapelen++;
int parameter, assigned, consumed;
// make sure parameters are positive values and delimited by semicolon
if((chr >= '0' && chr <= '9') || chr == ';')
continue;
switch (chr) {
//---------------------------------------
// Cursor directional movement
//---------------------------------------
case 'A':
consumed = 0;
assigned = sscanf(escapeseq,"[%dA%n", &parameter, &consumed);
if (assigned==0) parameter = 1;
if (consumed)
currentConsole->cursorY = (currentConsole->cursorY - parameter) < 0 ? 0 : currentConsole->cursorY - parameter;
escaping = false;
break;
case 'B':
consumed = 0;
assigned = sscanf(escapeseq,"[%dB%n", &parameter, &consumed);
if (assigned==0) parameter = 1;
if (consumed)
currentConsole->cursorY = (currentConsole->cursorY + parameter) > currentConsole->windowHeight - 1 ? currentConsole->windowHeight - 1 : currentConsole->cursorY + parameter;
escaping = false;
break;
case 'C':
consumed = 0;
assigned = sscanf(escapeseq,"[%dC%n", &parameter, &consumed);
if (assigned==0) parameter = 1;
if (consumed)
currentConsole->cursorX = (currentConsole->cursorX + parameter) > currentConsole->windowWidth - 1 ? currentConsole->windowWidth - 1 : currentConsole->cursorX + parameter;
escaping = false;
break;
case 'D':
consumed = 0;
assigned = sscanf(escapeseq,"[%dD%n", &parameter, &consumed);
if (assigned==0) parameter = 1;
if (consumed)
currentConsole->cursorX = (currentConsole->cursorX - parameter) < 0 ? 0 : currentConsole->cursorX - parameter;
escaping = false;
break;
//---------------------------------------
// Cursor position movement
//---------------------------------------
case 'H':
case 'f':
{
int x, y;
char c;
if(sscanf(escapeseq,"[%d;%d%c", &y, &x, &c) == 3 && (c == 'f' || c == 'H')) {
currentConsole->cursorX = x;
currentConsole->cursorY = y;
escaping = false;
break;
}
x = y = 1;
if(sscanf(escapeseq,"[%d;%c", &y, &c) == 2 && (c == 'f' || c == 'H')) {
currentConsole->cursorX = x;
currentConsole->cursorY = y;
escaping = false;
break;
}
x = y = 1;
if(sscanf(escapeseq,"[;%d%c", &x, &c) == 2 && (c == 'f' || c == 'H')) {
currentConsole->cursorX = x;
currentConsole->cursorY = y;
escaping = false;
break;
}
x = y = 1;
if(sscanf(escapeseq,"[;%c", &c) == 1 && (c == 'f' || c == 'H')) {
currentConsole->cursorX = x;
currentConsole->cursorY = y;
escaping = false;
break;
}
// invalid format
escaping = false;
break;
}
//---------------------------------------
// Screen clear
//---------------------------------------
case 'J':
if(escapelen <= 3)
consoleCls(escapeseq[escapelen-2]);
escaping = false;
break;
//---------------------------------------
// Line clear
//---------------------------------------
case 'K':
if(escapelen <= 3)
consoleClearLine(escapeseq[escapelen-2]);
escaping = false;
break;
//---------------------------------------
// Save cursor position
//---------------------------------------
case 's':
if(escapelen == 2) {
currentConsole->prevCursorX = currentConsole->cursorX ;
currentConsole->prevCursorY = currentConsole->cursorY ;
}
escaping = false;
break;
//---------------------------------------
// Load cursor position
//---------------------------------------
case 'u':
if(escapelen == 2) {
currentConsole->cursorX = currentConsole->prevCursorX ;
currentConsole->cursorY = currentConsole->prevCursorY ;
}
escaping = false;
break;
//---------------------------------------
// Color scan codes
//---------------------------------------
case 'm':
escapeseq++;
escapelen--;
do {
parameter = 0;
if (escapelen == 1) {
consumed = 1;
} else if (strchr(escapeseq,';')) {
sscanf(escapeseq,"%d;%n", &parameter, &consumed);
} else {
sscanf(escapeseq,"%dm%n", &parameter, &consumed);
}
escapeseq += consumed;
escapelen -= consumed;
switch(parameter) {
case 0: // reset
currentConsole->flags = 0;
currentConsole->bg = 0;
currentConsole->fg = 7;
break;
case 1: // bold
currentConsole->flags &= ~CONSOLE_COLOR_FAINT;
currentConsole->flags |= CONSOLE_COLOR_BOLD;
break;
case 2: // faint
currentConsole->flags &= ~CONSOLE_COLOR_BOLD;
currentConsole->flags |= CONSOLE_COLOR_FAINT;
break;
case 3: // italic
currentConsole->flags |= CONSOLE_ITALIC;
break;
case 4: // underline
currentConsole->flags |= CONSOLE_UNDERLINE;
break;
case 5: // blink slow
currentConsole->flags &= ~CONSOLE_BLINK_FAST;
currentConsole->flags |= CONSOLE_BLINK_SLOW;
break;
case 6: // blink fast
currentConsole->flags &= ~CONSOLE_BLINK_SLOW;
currentConsole->flags |= CONSOLE_BLINK_FAST;
break;
case 7: // reverse video
currentConsole->flags |= CONSOLE_COLOR_REVERSE;
break;
case 8: // conceal
currentConsole->flags |= CONSOLE_CONCEAL;
break;
case 9: // crossed-out
currentConsole->flags |= CONSOLE_CROSSED_OUT;
break;
case 21: // bold off
currentConsole->flags &= ~CONSOLE_COLOR_BOLD;
break;
case 22: // normal color
currentConsole->flags &= ~CONSOLE_COLOR_BOLD;
currentConsole->flags &= ~CONSOLE_COLOR_FAINT;
break;
case 23: // italic off
currentConsole->flags &= ~CONSOLE_ITALIC;
break;
case 24: // underline off
currentConsole->flags &= ~CONSOLE_UNDERLINE;
break;
case 25: // blink off
currentConsole->flags &= ~CONSOLE_BLINK_SLOW;
currentConsole->flags &= ~CONSOLE_BLINK_FAST;
break;
case 27: // reverse off
currentConsole->flags &= ~CONSOLE_COLOR_REVERSE;
break;
case 29: // crossed-out off
currentConsole->flags &= ~CONSOLE_CROSSED_OUT;
break;
case 30 ... 37: // writing color
currentConsole->fg = parameter - 30;
break;
case 39: // reset foreground color
currentConsole->fg = 7;
break;
case 40 ... 47: // screen color
currentConsole->bg = parameter - 40;
break;
case 49: // reset background color
currentConsole->fg = 0;
break;
}
} while (escapelen > 0);
escaping = false;
break;
default:
// some sort of unsupported escape; just gloss over it
escaping = false;
break;
}
} while (escaping);
continue;
}
consolePrintChar(chr);
}
return count;
}
static const devoptab_t dotab_stdout = {
"con",
0,
NULL,
NULL,
con_write,
NULL,
NULL,
NULL
};
//---------------------------------------------------------------------------------
ssize_t debug_write(struct _reent *r, int fd, const char *ptr, size_t len) {
//---------------------------------------------------------------------------------
svcOutputDebugString(ptr,len);
return len;
}
static const devoptab_t dotab_3dmoo = {
"3dmoo",
0,
NULL,
NULL,
debug_write,
NULL,
NULL,
NULL
};
static const devoptab_t dotab_null = {
"null",
0,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};
//---------------------------------------------------------------------------------
PrintConsole* consoleInit(gfxScreen_t screen, PrintConsole* console) {
//---------------------------------------------------------------------------------
static bool firstConsoleInit = true;
if(firstConsoleInit) {
devoptab_list[STD_OUT] = &dotab_stdout;
devoptab_list[STD_ERR] = &dotab_stdout;
setvbuf(stdout, NULL , _IONBF, 0);
setvbuf(stderr, NULL , _IONBF, 0);
firstConsoleInit = false;
}
if(console) {
currentConsole = console;
} else {
console = currentConsole;
}
*currentConsole = defaultConsole;
console->consoleInitialised = 1;
gfxSetScreenFormat(screen,GSP_RGB565_OES);
gfxSetDoubleBuffering(screen,false);
console->frameBuffer = (u16*)gfxGetFramebuffer(screen, GFX_LEFT, NULL, NULL);
if(screen==GFX_TOP) {
console->consoleWidth = 50;
console->windowWidth = 50;
}
consoleCls('2');
return currentConsole;
}
//---------------------------------------------------------------------------------
void consoleDebugInit(debugDevice device){
//---------------------------------------------------------------------------------
int buffertype = _IONBF;
switch(device) {
case debugDevice_3DMOO:
devoptab_list[STD_ERR] = &dotab_3dmoo;
buffertype = _IOLBF;
break;
case debugDevice_CONSOLE:
devoptab_list[STD_ERR] = &dotab_stdout;
break;
case debugDevice_NULL:
devoptab_list[STD_ERR] = &dotab_null;
break;
}
setvbuf(stderr, NULL , buffertype, 0);
}
//---------------------------------------------------------------------------------
PrintConsole *consoleSelect(PrintConsole* console){
//---------------------------------------------------------------------------------
PrintConsole *tmp = currentConsole;
currentConsole = console;
return tmp;
}
//---------------------------------------------------------------------------------
void consoleSetFont(PrintConsole* console, ConsoleFont* font){
//---------------------------------------------------------------------------------
if(!console) console = currentConsole;
console->font = *font;
}
//---------------------------------------------------------------------------------
static void newRow() {
//---------------------------------------------------------------------------------
currentConsole->cursorY ++;
if(currentConsole->cursorY >= currentConsole->windowHeight) {
currentConsole->cursorY --;
u16 *dst = &currentConsole->frameBuffer[(currentConsole->windowX * 8 * 240) + (239 - (currentConsole->windowY * 8))];
u16 *src = dst - 8;
int i,j;
for (i=0; i<currentConsole->windowWidth*8; i++) {
u32 *from = (u32*)((int)src & ~3);
u32 *to = (u32*)((int)dst & ~3);
for (j=0;j<(((currentConsole->windowHeight-1)*8)/2);j++) *(to--) = *(from--);
dst += 240;
src += 240;
}
consoleClearLine('2');
}
}
//---------------------------------------------------------------------------------
void consoleDrawChar(int c) {
//---------------------------------------------------------------------------------
c -= currentConsole->font.asciiOffset;
if ( c < 0 || c > currentConsole->font.numChars ) return;
u8 *fontdata = currentConsole->font.gfx + (8 * c);
int writingColor = currentConsole->fg;
int screenColor = currentConsole->bg;
if (currentConsole->flags & CONSOLE_COLOR_BOLD) {
writingColor += 8;
} else if (currentConsole->flags & CONSOLE_COLOR_FAINT) {
writingColor += 16;
}
if (currentConsole->flags & CONSOLE_COLOR_REVERSE) {
int tmp = writingColor;
writingColor = screenColor;
screenColor = tmp;
}
u16 bg = colorTable[screenColor];
u16 fg = colorTable[writingColor];
u8 b1 = *(fontdata++);
u8 b2 = *(fontdata++);
u8 b3 = *(fontdata++);
u8 b4 = *(fontdata++);
u8 b5 = *(fontdata++);
u8 b6 = *(fontdata++);
u8 b7 = *(fontdata++);
u8 b8 = *(fontdata++);
if (currentConsole->flags & CONSOLE_UNDERLINE) b8 = 0xff;
if (currentConsole->flags & CONSOLE_CROSSED_OUT) b4 = 0xff;
u8 mask = 0x80;
int i;
int x = (currentConsole->cursorX + currentConsole->windowX) * 8;
int y = ((currentConsole->cursorY + currentConsole->windowY) *8 );
u16 *screen = &currentConsole->frameBuffer[(x * 240) + (239 - (y + 7))];
for (i=0;i<8;i++) {
if (b8 & mask) { *(screen++) = fg; }else{ *(screen++) = bg; }
if (b7 & mask) { *(screen++) = fg; }else{ *(screen++) = bg; }
if (b6 & mask) { *(screen++) = fg; }else{ *(screen++) = bg; }
if (b5 & mask) { *(screen++) = fg; }else{ *(screen++) = bg; }
if (b4 & mask) { *(screen++) = fg; }else{ *(screen++) = bg; }
if (b3 & mask) { *(screen++) = fg; }else{ *(screen++) = bg; }
if (b2 & mask) { *(screen++) = fg; }else{ *(screen++) = bg; }
if (b1 & mask) { *(screen++) = fg; }else{ *(screen++) = bg; }
mask >>= 1;
screen += 240 - 8;
}
}
//---------------------------------------------------------------------------------
void consolePrintChar(char c) {
//---------------------------------------------------------------------------------
if (c==0) return;
if(currentConsole->PrintChar)
if(currentConsole->PrintChar(currentConsole, c))
return;
if(currentConsole->cursorX >= currentConsole->windowWidth) {
currentConsole->cursorX = 0;
newRow();
}
switch(c) {
/*
The only special characters we will handle are tab (\t), carriage return (\r), line feed (\n)
and backspace (\b).
Carriage return & line feed will function the same: go to next line and put cursor at the beginning.
For everything else, use VT sequences.
Reason: VT sequences are more specific to the task of cursor placement.
The special escape sequences \b \f & \v are archaic and non-portable.
*/
case 8:
currentConsole->cursorX--;
if(currentConsole->cursorX < 0) {
if(currentConsole->cursorY > 0) {
currentConsole->cursorX = currentConsole->windowX - 1;
currentConsole->cursorY--;
} else {
currentConsole->cursorX = 0;
}
}
consoleDrawChar(' ');
break;
case 9:
currentConsole->cursorX += currentConsole->tabSize - ((currentConsole->cursorX)%(currentConsole->tabSize));
break;
case 10:
newRow();
case 13:
currentConsole->cursorX = 0;
break;
default:
consoleDrawChar(c);
++currentConsole->cursorX ;
break;
}
}
//---------------------------------------------------------------------------------
void consoleClear(void) {
//---------------------------------------------------------------------------------
iprintf("\x1b[2J");
}
//---------------------------------------------------------------------------------
void consoleSetWindow(PrintConsole* console, int x, int y, int width, int height){
//---------------------------------------------------------------------------------
if(!console) console = currentConsole;
console->windowWidth = width;
console->windowHeight = height;
console->windowX = x;
console->windowY = y;
console->cursorX = 0;
console->cursorY = 0;
}

View File

@ -1,7 +1,10 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <3ds.h> #include <3ds/types.h>
#include <3ds/gfx.h>
#include <3ds/svc.h>
#include <3ds/linear.h>
GSP_FramebufferInfo topFramebufferInfo, bottomFramebufferInfo; GSP_FramebufferInfo topFramebufferInfo, bottomFramebufferInfo;
@ -12,9 +15,9 @@ u8* gfxTopLeftFramebuffers[2];
u8* gfxTopRightFramebuffers[2]; u8* gfxTopRightFramebuffers[2];
u8* gfxBottomFramebuffers[2]; u8* gfxBottomFramebuffers[2];
static u8 currentBuffer;
static bool enable3d; static bool enable3d;
static int doubleBuf = 1; static u8 currentBuffer[2];
static int doubleBuf[2] = {1,1};
Handle gspEvent, gspSharedMemHandle; Handle gspEvent, gspSharedMemHandle;
@ -33,8 +36,15 @@ void gfxSetScreenFormat(gfxScreen_t screen, GSP_FramebufferFormats format) {
botFormat = format; botFormat = format;
} }
void gfxSetDoubleBuffering(bool doubleBuffering) { GSP_FramebufferFormats gfxGetScreenFormat(gfxScreen_t screen) {
doubleBuf = doubleBuffering ? 1 : 0; // make sure they're the integer values '1' and '0' if(screen==GFX_TOP)
return topFormat;
else
return botFormat;
}
void gfxSetDoubleBuffering( gfxScreen_t screen, bool doubleBuffering) {
doubleBuf[screen] = doubleBuffering ? 1 : 0; // make sure they're the integer values '1' and '0'
} }
static u32 __get_bytes_per_pixel(GSP_FramebufferFormats format) { static u32 __get_bytes_per_pixel(GSP_FramebufferFormats format) {
@ -81,7 +91,7 @@ void gfxWriteFramebufferInfo(gfxScreen_t screen)
u8* framebufferInfoHeader=gfxSharedMemory+0x200+gfxThreadID*0x80; u8* framebufferInfoHeader=gfxSharedMemory+0x200+gfxThreadID*0x80;
if(screen==GFX_BOTTOM)framebufferInfoHeader+=0x40; if(screen==GFX_BOTTOM)framebufferInfoHeader+=0x40;
GSP_FramebufferInfo* framebufferInfo=(GSP_FramebufferInfo*)&framebufferInfoHeader[0x4]; GSP_FramebufferInfo* framebufferInfo=(GSP_FramebufferInfo*)&framebufferInfoHeader[0x4];
framebufferInfoHeader[0x0]^=doubleBuf; framebufferInfoHeader[0x0]^=doubleBuf[screen];
framebufferInfo[framebufferInfoHeader[0x0]]=(screen==GFX_TOP)?(topFramebufferInfo):(bottomFramebufferInfo); framebufferInfo[framebufferInfoHeader[0x0]]=(screen==GFX_TOP)?(topFramebufferInfo):(bottomFramebufferInfo);
framebufferInfoHeader[0x1]=1; framebufferInfoHeader[0x1]=1;
} }
@ -93,7 +103,6 @@ void gfxInit()
gfxSharedMemory=(u8*)0x10002000; gfxSharedMemory=(u8*)0x10002000;
GSPGPU_AcquireRight(NULL, 0x0); GSPGPU_AcquireRight(NULL, 0x0);
GSPGPU_SetLcdForceBlack(NULL, 0x0);
//setup our gsp shared mem section //setup our gsp shared mem section
svcCreateEvent(&gspEvent, 0x0); svcCreateEvent(&gspEvent, 0x0);
@ -124,11 +133,14 @@ void gfxInit()
//GSP shared mem : 0x2779F000 //GSP shared mem : 0x2779F000
gxCmdBuf=(u32*)(gfxSharedMemory+0x800+gfxThreadID*0x200); gxCmdBuf=(u32*)(gfxSharedMemory+0x800+gfxThreadID*0x200);
currentBuffer=0; currentBuffer[0]=0;
currentBuffer[1]=0;
// Initialize event handler and wait for VBlank // Initialize event handler and wait for VBlank
gspInitEventHandler(gspEvent, (vu8*)gfxSharedMemory, gfxThreadID); gspInitEventHandler(gspEvent, (vu8*)gfxSharedMemory, gfxThreadID);
gspWaitForVBlank(); gspWaitForVBlank();
GSPGPU_SetLcdForceBlack(NULL, 0x0);
} }
void gfxExit() void gfxExit()
@ -153,7 +165,7 @@ void gfxExit()
svcCloseHandle(gspEvent); svcCloseHandle(gspEvent);
GSPGPU_ReleaseRight(NULL); GSPGPU_ReleaseRight(NULL);
gspExit(); gspExit();
} }
@ -164,10 +176,10 @@ u8* gfxGetFramebuffer(gfxScreen_t screen, gfx3dSide_t side, u16* width, u16* hei
if(screen==GFX_TOP) if(screen==GFX_TOP)
{ {
if(height)*height=400; if(height)*height=400;
return (side==GFX_LEFT || !enable3d)?(gfxTopLeftFramebuffers[currentBuffer^doubleBuf]):(gfxTopRightFramebuffers[currentBuffer^doubleBuf]); return (side==GFX_LEFT || !enable3d)?(gfxTopLeftFramebuffers[currentBuffer[0]^doubleBuf[0]]):(gfxTopRightFramebuffers[currentBuffer[0]^doubleBuf[0]]);
}else{ }else{
if(height)*height=320; if(height)*height=320;
return gfxBottomFramebuffers[currentBuffer^doubleBuf]; return gfxBottomFramebuffers[currentBuffer[1]^doubleBuf[1]];
} }
} }
@ -180,18 +192,20 @@ void gfxFlushBuffers()
void gfxSwapBuffers() void gfxSwapBuffers()
{ {
currentBuffer^=doubleBuf; currentBuffer[0]^=doubleBuf[0];
gfxSetFramebufferInfo(GFX_TOP, currentBuffer); currentBuffer[1]^=doubleBuf[1];
gfxSetFramebufferInfo(GFX_BOTTOM, currentBuffer); gfxSetFramebufferInfo(GFX_TOP, currentBuffer[0]);
gfxSetFramebufferInfo(GFX_BOTTOM, currentBuffer[1]);
GSPGPU_SetBufferSwap(NULL, GFX_TOP, &topFramebufferInfo); GSPGPU_SetBufferSwap(NULL, GFX_TOP, &topFramebufferInfo);
GSPGPU_SetBufferSwap(NULL, GFX_BOTTOM, &bottomFramebufferInfo); GSPGPU_SetBufferSwap(NULL, GFX_BOTTOM, &bottomFramebufferInfo);
} }
void gfxSwapBuffersGpu() void gfxSwapBuffersGpu()
{ {
currentBuffer^=doubleBuf; currentBuffer[0]^=doubleBuf[0];
gfxSetFramebufferInfo(GFX_TOP, currentBuffer); currentBuffer[1]^=doubleBuf[1];
gfxSetFramebufferInfo(GFX_BOTTOM, currentBuffer); gfxSetFramebufferInfo(GFX_TOP, currentBuffer[0]);
gfxSetFramebufferInfo(GFX_BOTTOM, currentBuffer[1]);
gfxWriteFramebufferInfo(GFX_TOP); gfxWriteFramebufferInfo(GFX_TOP);
gfxWriteFramebufferInfo(GFX_BOTTOM); gfxWriteFramebufferInfo(GFX_BOTTOM);
} }

View File

@ -4,7 +4,10 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <3ds.h> #include <3ds/types.h>
#include <3ds/gpu/gpu.h>
#include <3ds/gpu/gx.h>
#include <3ds/gpu/shdr.h>
u32* gpuCmdBuf; u32* gpuCmdBuf;
u32 gpuCmdBufSize; u32 gpuCmdBufSize;

View File

@ -4,8 +4,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <3ds.h> #include <3ds/types.h>
#include <3ds/gpu/gpu.h>
#include <3ds/gpu/shdr.h>
//please don't feed this an invalid SHBIN //please don't feed this an invalid SHBIN
DVLB_s* SHDR_ParseSHBIN(u32* shbinData, u32 shbinSize) DVLB_s* SHDR_ParseSHBIN(u32* shbinData, u32 shbinSize)

View File

@ -1,118 +0,0 @@
#include <sys/iosupport.h>
#include <string.h>
#include <3ds.h>
// System globals we define here
int __system_argc;
char** __system_argv;
void (*__system_retAddr)(void);
u32 __linear_heap;
// Data from _prm structure
extern void* __service_ptr; // used to detect if we're run from a homebrew launcher
extern u32 __heap_size, __linear_heap_size;
extern const char* __system_arglist;
// newlib definitions we need
void __libc_init_array(void);
void __libc_fini_array(void);
extern char* fake_heap_start;
extern char* fake_heap_end;
static void initArgv();
static u32 heapBase;
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(&tmp, __linear_heap, 0x0, __linear_heap_size, MEMOP_FREE, 0x0);
// Unmap the application heap
svcControlMemory(&tmp, heapBase, 0x0, __heap_size, MEMOP_FREE, 0x0);
// Close some handles
__destroy_handle_list();
// Jump to the loader if it provided a callback
if (__system_retAddr)
__system_retAddr();
// Since above did not jump, end this process
svcExitProcess();
}
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(&tmp, heapBase, 0x0, __heap_size, MEMOP_ALLOC, 0x3);
// Allocate the linear heap
svcControlMemory(&__linear_heap, 0x0, 0x0, __linear_heap_size, MEMOP_ALLOC_LINEAR, 0x3);
// Set up newlib heap
fake_heap_start = (char*)heapBase;
fake_heap_end = fake_heap_start + __heap_size;
// Build argc/argv if present
initArgv();
// TODO: APT init goes here
// Run the global constructors
__libc_init_array();
}
void initArgv()
{
int i;
const char* temp = __system_arglist;
// Check if the argument list is present
if (!temp)
return;
// Retrieve argc
__system_argc = *(u32*)temp;
temp += sizeof(u32);
// Find the end of the argument data
for (i = 0; i < __system_argc; i ++)
{
for (; *temp; temp ++);
temp ++;
}
// Reserve heap memory for argv data
u32 argSize = temp - __system_arglist - sizeof(u32);
__system_argv = (char**)fake_heap_start;
fake_heap_start += sizeof(char**)*(__system_argc + 1);
char* argCopy = fake_heap_start;
fake_heap_start += argSize;
// Fill argv array
memcpy(argCopy, &__system_arglist[4], argSize);
temp = argCopy;
for (i = 0; i < __system_argc; i ++)
{
__system_argv[i] = (char*)temp;
for (; *temp; temp ++);
temp ++;
}
__system_argv[__system_argc] = NULL;
}

View File

@ -1,4 +1,7 @@
#include <3ds.h> #include <3ds/types.h>
#include <3ds/os.h>
#include <3ds/svc.h>
#define TICKS_PER_MSEC 268123.480 #define TICKS_PER_MSEC 268123.480
@ -10,9 +13,9 @@ typedef struct {
static volatile u32* __datetime_selector = static volatile u32* __datetime_selector =
(u32*) 0x1FF81000; (u32*) 0x1FF81000;
static volatile datetime_t* __datetime1 = static volatile datetime_t* __datetime0 =
(datetime_t*) 0x1FF81020; (datetime_t*) 0x1FF81020;
static volatile datetime_t* __datetime2 = static volatile datetime_t* __datetime1 =
(datetime_t*) 0x1FF81040; (datetime_t*) 0x1FF81040;
@ -38,19 +41,27 @@ u32 osConvertOldLINEARMemToNew(u32 vaddr)
// Returns number of milliseconds since 1st Jan 1900 00:00. // Returns number of milliseconds since 1st Jan 1900 00:00.
u64 osGetTime() { u64 osGetTime() {
volatile datetime_t* dt; u32 s1, s2 = *__datetime_selector & 1;
datetime_t dt;
switch(*__datetime_selector & 1) { do {
case 0: s1 = s2;
dt = __datetime1; if(!s1)
break; dt = *__datetime0;
case 1: else
dt = __datetime2; dt = *__datetime1;
break; s2 = *__datetime_selector & 1;
} } while(s2 != s1);
u64 offset = (u32)((u32)(svcGetSystemTick() - dt->update_tick) / TICKS_PER_MSEC); u64 delta = svcGetSystemTick() - dt.update_tick;
return dt->date_time + offset;
// Work around the VFP not supporting 64-bit integer <--> floating point conversion
double temp = (u32)(delta >> 32);
temp *= 0x100000000ULL;
temp += (u32)delta;
u32 offset = temp / TICKS_PER_MSEC;
return dt.date_time + offset;
} }
u32 osGetFirmVersion() { u32 osGetFirmVersion() {

View File

@ -6,7 +6,11 @@
#include <sys/param.h> #include <sys/param.h>
#include <string.h> #include <string.h>
#include <3ds.h> #include <3ds/types.h>
#include <3ds/sdmc.h>
#include <3ds/services/fs.h>
/*! @internal /*! @internal
* *
@ -126,11 +130,14 @@ static const char *sdmc_fixpath(const char *path)
extern int __system_argc; extern int __system_argc;
extern char** __system_argv; extern char** __system_argv;
static bool sdmcInitialised = false;
/*! Initialize SDMC device */ /*! Initialize SDMC device */
Result sdmcInit(void) Result sdmcInit(void)
{ {
Result rc; Result rc = 0;
if (sdmcInitialised) return rc;
rc = FSUSER_OpenArchive(NULL, &sdmcArchive); rc = FSUSER_OpenArchive(NULL, &sdmcArchive);
@ -157,18 +164,24 @@ Result sdmcInit(void)
} }
} }
sdmcInitialised = true;
return rc; return rc;
} }
/*! Clean up SDMC device */ /*! Clean up SDMC device */
Result sdmcExit(void) Result sdmcExit(void)
{ {
Result rc; Result rc = 0;
if (!sdmcInitialised) return rc;
rc = FSUSER_CloseArchive(NULL, &sdmcArchive); rc = FSUSER_CloseArchive(NULL, &sdmcArchive);
if(rc == 0) if(rc == 0)
RemoveDevice("sdmc"); RemoveDevice("sdmc");
sdmcInitialised = false;
return rc; return rc;
} }
@ -240,7 +253,20 @@ sdmc_open(struct _reent *r,
if(flags & O_CREAT) if(flags & O_CREAT)
sdmc_flags |= FS_OPEN_CREATE; sdmc_flags |= FS_OPEN_CREATE;
/* TODO: Test O_EXCL. */ /* Test O_EXCL. */
if((flags & O_CREAT) && (flags & O_EXCL))
{
rc = FSUSER_CreateFile(NULL, sdmcArchive, FS_makePath(PATH_CHAR, pathptr), 0);
if(rc != 0)
{
r->_errno = rc;
if(rc == 0x82044BE)
r->_errno = EEXIST;
if(rc == 0x86044D2)
r->_errno = ENOSPC;
return -1;
}
}
/* set attributes */ /* set attributes */
/*if(!(mode & S_IWUSR)) /*if(!(mode & S_IWUSR))
@ -251,6 +277,16 @@ sdmc_open(struct _reent *r,
sdmc_flags, attributes); sdmc_flags, attributes);
if(rc == 0) if(rc == 0)
{ {
if((flags & O_ACCMODE) != O_RDONLY && (flags & O_TRUNC))
{
rc = FSFILE_SetSize(fd, 0);
if(rc != 0)
{
FSFILE_Close(fd);
r->_errno = rc;
return -1;
}
}
file->fd = fd; file->fd = fd;
file->flags = (flags & (O_ACCMODE|O_APPEND|O_SYNC)); file->flags = (flags & (O_ACCMODE|O_APPEND|O_SYNC));
file->offset = 0; file->offset = 0;

View File

@ -1,5 +1,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <3ds.h> #include <3ds/types.h>
#include <3ds/svc.h>
#include <3ds/srv.h>
#include <3ds/services/ac.h>
static Handle acHandle; static Handle acHandle;

View File

@ -1,5 +1,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <3ds.h> #include <3ds/types.h>
#include <3ds/svc.h>
#include <3ds/srv.h>
#include <3ds/services/am.h>
static Handle amHandle = 0; static Handle amHandle = 0;

View File

@ -4,7 +4,12 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <3ds.h> #include <3ds/types.h>
#include <3ds/svc.h>
#include <3ds/srv.h>
#include <3ds/services/apt.h>
#include <3ds/services/gsp.h>
#define APT_HANDLER_STACKSIZE (0x1000) #define APT_HANDLER_STACKSIZE (0x1000)
@ -405,10 +410,14 @@ void aptEventHandler(u32 arg)
svcExitThread(); svcExitThread();
} }
static bool aptInitialised = false;
Result aptInit(void) Result aptInit(void)
{ {
Result ret=0; Result ret=0;
if (aptInitialised) return ret;
// Initialize APT stuff, escape load screen. // Initialize APT stuff, escape load screen.
ret = __apt_initservicehandle(); ret = __apt_initservicehandle();
if(ret!=0)return ret; if(ret!=0)return ret;
@ -440,11 +449,15 @@ Result aptInit(void)
} else } else
aptAppStarted(); aptAppStarted();
aptInitialised = true;
return 0; return 0;
} }
void aptExit() void aptExit()
{ {
if (!aptInitialised) return;
if(!(__system_runflags&RUNFLAG_APTWORKAROUND))aptAppletUtility_Exit_RetToApp(0); 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. // This is only executed when application-termination was triggered via the home-menu power-off screen.
@ -471,6 +484,8 @@ void aptExit()
svcCloseHandle(aptStatusMutex); svcCloseHandle(aptStatusMutex);
svcCloseHandle(aptLockHandle); svcCloseHandle(aptLockHandle);
svcCloseHandle(aptStatusEvent); svcCloseHandle(aptStatusEvent);
aptInitialised = false;
} }
bool aptMainLoop() bool aptMainLoop()

View File

@ -1,5 +1,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <3ds.h> #include <3ds/types.h>
#include <3ds/svc.h>
#include <3ds/srv.h>
#include <3ds/services/cfgnor.h>
Handle CFGNOR_handle = 0; Handle CFGNOR_handle = 0;

View File

@ -1,5 +1,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <3ds.h> #include <3ds/types.h>
#include <3ds/svc.h>
#include <3ds/srv.h>
#include <3ds/services/cfgu.h>
static Handle CFGU_handle = 0; static Handle CFGU_handle = 0;

View File

@ -1,6 +1,10 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <3ds.h> #include <3ds/types.h>
#include <3ds/svc.h>
#include <3ds/srv.h>
#include <3ds/os.h>
#include <3ds/services/csnd.h>
//See here regarding CSND shared-mem commands, etc: http://3dbrew.org/wiki/CSND_Shared_Memory //See here regarding CSND shared-mem commands, etc: http://3dbrew.org/wiki/CSND_Shared_Memory

View File

@ -1,5 +1,8 @@
#include <string.h> #include <string.h>
#include <3ds.h> #include <3ds/types.h>
#include <3ds/svc.h>
#include <3ds/srv.h>
#include <3ds/services/fs.h>
/*! @internal /*! @internal
* *
@ -34,12 +37,21 @@ FS_makePath(FS_pathType type,
* *
* @returns error * @returns error
*/ */
static bool fsInitialised = false;
Result Result
fsInit(void) fsInit(void)
{ {
Result ret; Result ret = 0;
if (fsInitialised) return ret;
if((ret=srvGetServiceHandle(&fsuHandle, "fs:USER"))!=0)return ret; if((ret=srvGetServiceHandle(&fsuHandle, "fs:USER"))!=0)return ret;
if(__get_handle_from_list("fs:USER")==0)ret=FSUSER_Initialize(NULL); if(__get_handle_from_list("fs:USER")==0)ret=FSUSER_Initialize(NULL);
fsInitialised = true;
return ret; return ret;
} }
@ -50,6 +62,10 @@ fsInit(void)
Result Result
fsExit(void) fsExit(void)
{ {
if (!fsInitialised) return 0;
fsInitialised = false;
return svcCloseHandle(fsuHandle); return svcCloseHandle(fsuHandle);
} }

View File

@ -4,7 +4,10 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <3ds.h> #include <3ds/types.h>
#include <3ds/svc.h>
#include <3ds/srv.h>
#include <3ds/services/gsp.h>
#define GSP_EVENT_STACK_SIZE 0x1000 #define GSP_EVENT_STACK_SIZE 0x1000

View File

@ -3,7 +3,11 @@
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <3ds.h> #include <3ds/types.h>
#include <3ds/svc.h>
#include <3ds/srv.h>
#include <3ds/gpu/gx.h>
#include <3ds/services/gsp.h>
u32* gxCmdBuf; u32* gxCmdBuf;

View File

@ -0,0 +1,67 @@
#include <3ds/types.h>
#include <3ds/svc.h>
#include <3ds/srv.h>
#include <3ds/services/hb.h>
static Handle hbHandle;
Result hbInit()
{
return srvGetServiceHandle(&hbHandle, "hb:HB");
}
void hbExit()
{
svcCloseHandle(hbHandle);
}
Result HB_FlushInvalidateCache(void)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00010042;
cmdbuf[1] = 0x00000000;
cmdbuf[2] = 0x00000000;
cmdbuf[3] = 0xFFFF8001;
if((ret = svcSendSyncRequest(hbHandle))!=0) return ret;
return (Result)cmdbuf[1];
}
Result HB_GetBootloaderAddresses(void** load3dsx, void** setArgv)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00060000;
if((ret = svcSendSyncRequest(hbHandle))!=0) return ret;
if(load3dsx)*load3dsx=(void*)cmdbuf[2];
if(setArgv)*setArgv=(void*)cmdbuf[3];
return (Result)cmdbuf[1];
}
Result HB_ReprotectMemory(u32* addr, u32 pages, u32 mode, u32* reprotectedPages)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x000900C0;
cmdbuf[1] = (u32)addr;
cmdbuf[2] = pages;
cmdbuf[3] = mode;
if((ret = svcSendSyncRequest(hbHandle))!=0) return ret;
if(reprotectedPages)
{
if(!ret)*reprotectedPages=(u32)cmdbuf[2];
else *reprotectedPages=0;
}
return (Result)cmdbuf[1];
}

View File

@ -3,7 +3,12 @@
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <3ds.h> #include <3ds/types.h>
#include <3ds/svc.h>
#include <3ds/srv.h>
#include <3ds/services/apt.h>
#include <3ds/services/hid.h>
#include <3ds/services/irrst.h>
Handle hidHandle; Handle hidHandle;
Handle hidMemHandle; Handle hidMemHandle;
@ -18,13 +23,16 @@ static circlePosition cPos;
static accelVector aVec; static accelVector aVec;
static angularRate gRate; static angularRate gRate;
static bool hidInitialised;
Result hidInit(u32* sharedMem) Result hidInit(u32* sharedMem)
{ {
u8 val=0; u8 val=0;
Result ret=0;
if(hidInitialised) return ret;
if(!sharedMem)sharedMem=(u32*)HID_SHAREDMEM_DEFAULT; if(!sharedMem)sharedMem=(u32*)HID_SHAREDMEM_DEFAULT;
Result ret=0;
// Request service. // Request service.
if((ret=srvGetServiceHandle(&hidHandle, "hid:USER")))return ret; if((ret=srvGetServiceHandle(&hidHandle, "hid:USER")))return ret;
@ -44,6 +52,7 @@ Result hidInit(u32* sharedMem)
} }
// Reset internal state. // Reset internal state.
hidInitialised = true;
kOld = kHeld = kDown = kUp = 0; kOld = kHeld = kDown = kUp = 0;
return ret; return ret;
@ -56,6 +65,8 @@ cleanup1:
void hidExit() void hidExit()
{ {
if(!hidInitialised) return;
// Unmap HID sharedmem and close handles. // Unmap HID sharedmem and close handles.
u8 val=0; u8 val=0;
int i; for(i=0; i<5; i++)svcCloseHandle(hidEvents[i]); int i; for(i=0; i<5; i++)svcCloseHandle(hidEvents[i]);
@ -69,6 +80,8 @@ void hidExit()
{ {
irrstExit(); irrstExit();
} }
hidInitialised = false;
} }
void hidWaitForEvent(HID_Event id, bool nextEvent) void hidWaitForEvent(HID_Event id, bool nextEvent)
@ -245,3 +258,28 @@ Result HIDUSER_DisableGyroscope()
return cmdbuf[1]; return cmdbuf[1];
} }
Result HIDUSER_GetGyroscopeRawToDpsCoefficient(float *coeff)
{
u32* cmdbuf=getThreadCommandBuffer();
cmdbuf[0]=0x150000; //request header code
Result ret=0;
if((ret=svcSendSyncRequest(hidHandle)))return ret;
*coeff = (float)cmdbuf[2];
return cmdbuf[1];
}
Result HIDUSER_GetSoundVolume(u8 *volume)
{
u32* cmdbuf=getThreadCommandBuffer();
cmdbuf[0]=0x170000; //request header code
Result ret=0;
if((ret=svcSendSyncRequest(hidHandle)))return ret;
*volume = (u8)cmdbuf[2];
return cmdbuf[1];
}

View File

@ -1,5 +1,8 @@
#include <string.h> #include <string.h>
#include <3ds.h> #include <3ds/types.h>
#include <3ds/svc.h>
#include <3ds/srv.h>
#include <3ds/services/httpc.h>
Handle __httpc_servhandle = 0; Handle __httpc_servhandle = 0;
@ -33,15 +36,26 @@ Result httpcOpenContext(httpcContext *context, char* url, u32 use_defaultproxy)
if(ret!=0)return ret; if(ret!=0)return ret;
ret = srvGetServiceHandle(&context->servhandle, "http:C"); ret = srvGetServiceHandle(&context->servhandle, "http:C");
if(ret!=0)return ret; if(ret!=0) {
HTTPC_CloseContext(__httpc_servhandle, context->httphandle);
return ret;
}
ret = HTTPC_InitializeConnectionSession(context->servhandle, context->httphandle); ret = HTTPC_InitializeConnectionSession(context->servhandle, context->httphandle);
if(ret!=0)return ret; if(ret!=0) {
HTTPC_CloseContext(__httpc_servhandle, context->httphandle);
svcCloseHandle(context->servhandle);
return ret;
}
if(use_defaultproxy==0)return 0; if(use_defaultproxy==0)return 0;
ret = HTTPC_SetProxyDefault(context->servhandle, context->httphandle); ret = HTTPC_SetProxyDefault(context->servhandle, context->httphandle);
if(ret!=0)return ret; if(ret!=0) {
HTTPC_CloseContext(__httpc_servhandle, context->httphandle);
svcCloseHandle(context->servhandle);
return ret;
}
return 0; return 0;
} }
@ -51,7 +65,6 @@ Result httpcCloseContext(httpcContext *context)
Result ret=0; Result ret=0;
ret = HTTPC_CloseContext(context->servhandle, context->httphandle); ret = HTTPC_CloseContext(context->servhandle, context->httphandle);
svcCloseHandle(context->servhandle); svcCloseHandle(context->servhandle);
return ret; return ret;

View File

@ -1,6 +1,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <3ds.h> #include <3ds/types.h>
#include <3ds/svc.h>
#include <3ds/srv.h>
#include <3ds/services/ir.h>
static Handle iru_handle=0; static Handle iru_handle=0;
static Handle iru_sharedmem_handle=0; static Handle iru_sharedmem_handle=0;

View File

@ -3,7 +3,10 @@
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <3ds.h> #include <3ds/types.h>
#include <3ds/svc.h>
#include <3ds/srv.h>
#include <3ds/services/irrst.h>
Handle irrstHandle; Handle irrstHandle;
Handle irrstMemHandle; Handle irrstMemHandle;

View File

@ -1,6 +1,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <3ds.h> #include <3ds/types.h>
#include <3ds/svc.h>
#include <3ds/srv.h>
#include <3ds/services/mic.h>
//See also: http://3dbrew.org/wiki/MIC_Services //See also: http://3dbrew.org/wiki/MIC_Services

View File

@ -4,7 +4,12 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <3ds.h> #include <3ds/types.h>
#include <3ds/svc.h>
#include <3ds/srv.h>
#include <3ds/os.h>
#include <3ds/linear.h>
#include <3ds/services/mvd.h>
Handle mvdstdHandle; Handle mvdstdHandle;
static u32 mvdstdInitialized = 0; static u32 mvdstdInitialized = 0;

View File

@ -1,5 +1,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <3ds.h> #include <3ds/types.h>
#include <3ds/svc.h>
#include <3ds/srv.h>
#include <3ds/services/ns.h>
static Handle nsHandle; static Handle nsHandle;

View File

@ -1,6 +1,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <3ds.h> #include <3ds/types.h>
#include <3ds/svc.h>
#include <3ds/srv.h>
#include <3ds/services/pm.h>
static Handle pmHandle; static Handle pmHandle;

View File

@ -1,11 +1,14 @@
#include <stdlib.h> #include <stdlib.h>
#include <3ds.h> #include <3ds/types.h>
#include <3ds/svc.h>
#include <3ds/srv.h>
#include <3ds/services/ps.h>
static Handle psHandle; static Handle psHandle;
Result psInit() Result psInit()
{ {
return srvGetServiceHandle(&psHandle, "ps:ps"); return srvGetServiceHandle(&psHandle, "ps:ps");
} }
Result psExit() Result psExit()
@ -17,7 +20,7 @@ Result PS_EncryptDecryptAes(u32 size, u8* in, u8* out, u32 aes_algo, u32 key_typ
{ {
Result ret = 0; Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer(); u32 *cmdbuf = getThreadCommandBuffer();
u32 *_iv = (u32*)iv; u32 *_iv = (u32*)iv;
cmdbuf[0] = 0x000401C4; cmdbuf[0] = 0x000401C4;
@ -32,14 +35,14 @@ Result PS_EncryptDecryptAes(u32 size, u8* in, u8* out, u32 aes_algo, u32 key_typ
cmdbuf[9] = (u32)in; cmdbuf[9] = (u32)in;
cmdbuf[10] = (size << 0x8) | 0x14; cmdbuf[10] = (size << 0x8) | 0x14;
cmdbuf[11] = (u32)out; cmdbuf[11] = (u32)out;
if((ret = svcSendSyncRequest(psHandle))!=0)return ret; if((ret = svcSendSyncRequest(psHandle))!=0)return ret;
_iv[0] = cmdbuf[2]; _iv[0] = cmdbuf[2];
_iv[1] = cmdbuf[3]; _iv[1] = cmdbuf[3];
_iv[2] = cmdbuf[4]; _iv[2] = cmdbuf[4];
_iv[3] = cmdbuf[5]; _iv[3] = cmdbuf[5];
return (Result)cmdbuf[1]; return (Result)cmdbuf[1];
} }
@ -47,7 +50,7 @@ Result PS_EncryptSignDecryptVerifyAesCcm(u8* in, u32 in_size, u8* out, u32 out_s
{ {
Result ret = 0; Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer(); u32 *cmdbuf = getThreadCommandBuffer();
u32 *_nonce = (u32*)nonce; u32 *_nonce = (u32*)nonce;
cmdbuf[0] = 0x00050284; cmdbuf[0] = 0x00050284;
@ -65,9 +68,9 @@ Result PS_EncryptSignDecryptVerifyAesCcm(u8* in, u32 in_size, u8* out, u32 out_s
cmdbuf[9] = (u32)in; cmdbuf[9] = (u32)in;
cmdbuf[10] = (out_size << 0x8) | 0x14; cmdbuf[10] = (out_size << 0x8) | 0x14;
cmdbuf[11] = (u32)out; cmdbuf[11] = (u32)out;
if((ret = svcSendSyncRequest(psHandle))!=0)return ret; if((ret = svcSendSyncRequest(psHandle))!=0)return ret;
return (Result)cmdbuf[1]; return (Result)cmdbuf[1];
} }
@ -75,13 +78,13 @@ Result PS_GetLocalFriendCodeSeed(u64* seed)
{ {
Result ret = 0; Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer(); u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x000A0000; cmdbuf[0] = 0x000A0000;
if((ret = svcSendSyncRequest(psHandle))!=0)return ret; if((ret = svcSendSyncRequest(psHandle))!=0)return ret;
*seed = (u64)cmdbuf[2] | (u64)cmdbuf[3] << 32; *seed = (u64)cmdbuf[2] | (u64)cmdbuf[3] << 32;
return (Result)cmdbuf[1]; return (Result)cmdbuf[1];
} }
@ -89,12 +92,12 @@ Result PS_GetDeviceId(u32* device_id)
{ {
Result ret = 0; Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer(); u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x000B0000; cmdbuf[0] = 0x000B0000;
if((ret = svcSendSyncRequest(psHandle))!=0)return ret; if((ret = svcSendSyncRequest(psHandle))!=0)return ret;
*device_id = cmdbuf[2]; *device_id = cmdbuf[2];
return (Result)cmdbuf[1]; return (Result)cmdbuf[1];
} }

View File

@ -1,5 +1,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <3ds.h> #include <3ds/types.h>
#include <3ds/svc.h>
#include <3ds/srv.h>
#include <3ds/services/ptm.h>
static Handle ptmHandle; static Handle ptmHandle;

View File

@ -0,0 +1,87 @@
/*
qtm.c - New3DS head-tracking
*/
#include <stdlib.h>
#include <string.h>
#include <3ds/types.h>
#include <3ds/svc.h>
#include <3ds/srv.h>
#include <3ds/services/qtm.h>
Handle qtmHandle;
static bool qtmInitialized = false;
Result qtmInit()
{
Result ret=0;
if(qtmInitialized)return 0;
if((ret=srvGetServiceHandle(&qtmHandle, "qtm:u")))return ret;
qtmInitialized = true;
return 0;
}
void qtmExit()
{
if(!qtmInitialized)return;
svcCloseHandle(qtmHandle);
qtmInitialized = false;
}
bool qtmCheckInitialized()
{
return qtmInitialized;
}
Result qtmGetHeadtrackingInfo(u64 val, qtmHeadtrackingInfo *out)
{
u32* cmdbuf=getThreadCommandBuffer();
if(!qtmInitialized)return -1;
cmdbuf[0]=0x00020080; //request header code
memcpy(&cmdbuf[1], &val, 8);
Result ret=0;
if((ret=svcSendSyncRequest(qtmHandle)))return ret;
ret = (Result)cmdbuf[1];
if(ret!=0)return ret;
if(out)memcpy(out, &cmdbuf[2], sizeof(qtmHeadtrackingInfo));
return 0;
}
bool qtmCheckHeadFullyDetected(qtmHeadtrackingInfo *info)
{
if(info==NULL)return false;
if(info->flags[0] && info->flags[1] && info->flags[2])return true;
return false;
}
Result qtmConvertCoordToScreen(qtmHeadtrackingInfoCoord *coord, float *screen_width, float *screen_height, u32 *x, u32 *y)
{
float width = 200.0f;
float height = 160.0f;
if(coord==NULL || x==NULL || y==NULL)return -1;
if(screen_width)width = (*screen_width) / 2;
if(screen_height)height = (*screen_height) / 2;
if(coord->x > 1.0f || coord->x < -1.0f)return -2;
if(coord->y > 1.0f || coord->y < -1.0f)return -2;
*x = (u32)((coord->x * width) + width);
*y = (u32)((coord->y * height) + height);
return 0;
}

View File

@ -1,7 +1,10 @@
#pragma once #pragma once
#include <string.h> #include <string.h>
#include <3ds.h> #include <3ds/types.h>
#include <3ds/svc.h>
#include <3ds/srv.h>
#include <3ds/services/soc.h>
extern Handle SOCU_handle; extern Handle SOCU_handle;
extern int SOCU_errno; extern int SOCU_errno;

View File

@ -54,23 +54,20 @@ int inet_aton(const char *cp, struct in_addr *inp)
switch(num_bytes) { switch(num_bytes) {
case 0: case 0:
return 0;
case 1:
break; break;
case 2: case 1:
if(val > 0xFFFFFF) return 0; if(val > 0xFFFFFF) return 0;
val |= bytes[0] << 24; val |= bytes[0] << 24;
break; break;
case 3: case 2:
if(val > 0xFFFF) return 0; if(val > 0xFFFF) return 0;
val |= bytes[0] << 24; val |= bytes[0] << 24;
val |= bytes[1] << 16; val |= bytes[1] << 16;
break; break;
case 4: case 3:
if(val > 0xFF) return 0; if(val > 0xFF) return 0;
val |= bytes[0] << 24; val |= bytes[0] << 24;
val |= bytes[1] << 16; val |= bytes[1] << 16;

View File

@ -3,7 +3,9 @@
*/ */
#include <string.h> #include <string.h>
#include <3ds.h> #include <3ds/types.h>
#include <3ds/srv.h>
#include <3ds/svc.h>
/* /*
@ -70,10 +72,13 @@ void __destroy_handle_list(void) {
__service_ptr->num = 0; __service_ptr->num = 0;
} }
Result srvInit() Result srvInit()
{ {
Result rc = 0; Result rc = 0;
if(g_srv_handle != 0) return rc;
if((rc = svcConnectToPort(&g_srv_handle, "srv:")))return rc; if((rc = svcConnectToPort(&g_srv_handle, "srv:")))return rc;
if((rc = srvRegisterClient())) { if((rc = srvRegisterClient())) {

View File

@ -100,7 +100,7 @@ svcSignalEvent:
svcClearEvent: svcClearEvent:
svc 0x19 svc 0x19
bx lr bx lr
.global svcCreateTimer .global svcCreateTimer
.type svcCreateTimer, %function .type svcCreateTimer, %function
svcCreateTimer: svcCreateTimer:
@ -109,19 +109,19 @@ svcCreateTimer:
ldr r2, [sp], #4 ldr r2, [sp], #4
str r1, [r2] str r1, [r2]
bx lr bx lr
.global svcSetTimer .global svcSetTimer
.type svcSetTimer, %function .type svcSetTimer, %function
svcSetTimer: svcSetTimer:
svc 0x1B svc 0x1B
bx lr bx lr
.global svcCancelTimer .global svcCancelTimer
.type svcCancelTimer, %function .type svcCancelTimer, %function
svcCancelTimer: svcCancelTimer:
svc 0x1C svc 0x1C
bx lr bx lr
.global svcClearTimer .global svcClearTimer
.type svcClearTimer, %function .type svcClearTimer, %function
svcClearTimer: svcClearTimer:
@ -259,10 +259,7 @@ svcGetProcessId:
.global svcOutputDebugString .global svcOutputDebugString
.type svcOutputDebugString, %function .type svcOutputDebugString, %function
svcOutputDebugString: svcOutputDebugString:
str r0, [sp, #-0x4]!
svc 0x3D svc 0x3D
ldr r2, [sp], #4
str r1, [r2]
bx lr bx lr
.global svcCreateSemaphore .global svcCreateSemaphore

View File

@ -0,0 +1,24 @@
#include <3ds/types.h>
#include <3ds/svc.h>
extern char* fake_heap_start;
extern char* fake_heap_end;
u32 __linear_heap;
u32 __heapBase;
extern u32 __heap_size, __linear_heap_size;
void __attribute__((weak)) __system_allocateHeaps() {
u32 tmp=0;
// Allocate the application heap
__heapBase = 0x08000000;
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);
// Set up newlib heap
fake_heap_start = (char*)__heapBase;
fake_heap_end = fake_heap_start + __heap_size;
}

View File

@ -0,0 +1,17 @@
#include <3ds/types.h>
#include <3ds/srv.h>
#include <3ds/gfx.h>
#include <3ds/sdmc.h>
#include <3ds/services/apt.h>
#include <3ds/services/fs.h>
#include <3ds/services/hid.h>
void __attribute__((weak)) __appExit() {
// Exit services
sdmcExit();
fsExit();
hidExit();
aptExit();
srvExit();
}

View File

@ -0,0 +1,17 @@
#include <3ds/types.h>
#include <3ds/srv.h>
#include <3ds/gfx.h>
#include <3ds/sdmc.h>
#include <3ds/services/apt.h>
#include <3ds/services/fs.h>
#include <3ds/services/hid.h>
void __attribute__((weak)) __appInit() {
// Initialize services
srvInit();
aptInit();
hidInit(NULL);
fsInit();
sdmcInit();
}

View File

@ -0,0 +1,38 @@
#include <3ds/types.h>
#include <3ds/svc.h>
extern u32 __linear_heap;
extern u32 __heapBase;
extern u32 __heap_size, __linear_heap_size;
extern void (*__system_retAddr)(void);
void __destroy_handle_list(void);
void __appExit();
void __libc_fini_array(void);
void __attribute__((weak)) __attribute__((noreturn)) __ctru_exit(int rc)
{
u32 tmp=0;
// Run the global destructors
__libc_fini_array();
__appExit();
// Unmap the linear heap
svcControlMemory(&tmp, __linear_heap, 0x0, __linear_heap_size, MEMOP_FREE, 0x0);
// Unmap the application heap
svcControlMemory(&tmp, __heapBase, 0x0, __heap_size, MEMOP_FREE, 0x0);
// Close some handles
__destroy_handle_list();
// Jump to the loader if it provided a callback
if (__system_retAddr)
__system_retAddr();
// Since above did not jump, end this process
svcExitProcess();
}

View File

@ -0,0 +1,50 @@
#include <3ds/types.h>
#include <string.h>
// System globals we define here
int __system_argc;
char** __system_argv;
extern const char* __system_arglist;
extern char* fake_heap_start;
extern char* fake_heap_end;
void __system_initArgv()
{
int i;
const char* temp = __system_arglist;
// Check if the argument list is present
if (!temp)
return;
// Retrieve argc
__system_argc = *(u32*)temp;
temp += sizeof(u32);
// Find the end of the argument data
for (i = 0; i < __system_argc; i ++)
{
for (; *temp; temp ++);
temp ++;
}
// Reserve heap memory for argv data
u32 argSize = temp - __system_arglist - sizeof(u32);
__system_argv = (char**)fake_heap_start;
fake_heap_start += sizeof(char**)*(__system_argc + 1);
char* argCopy = fake_heap_start;
fake_heap_start += argSize;
// Fill argv array
memcpy(argCopy, &__system_arglist[4], argSize);
temp = argCopy;
for (i = 0; i < __system_argc; i ++)
{
__system_argv[i] = (char*)temp;
for (; *temp; temp ++);
temp ++;
}
__system_argv[__system_argc] = NULL;
}

View File

@ -0,0 +1,37 @@
#include <sys/iosupport.h>
#include <string.h>
#include <3ds/types.h>
#include <3ds/svc.h>
void (*__system_retAddr)(void);
// Data from _prm structure
extern void* __service_ptr; // used to detect if we're run from a homebrew launcher
void __system_allocateHeaps();
void __system_initArgv();
void __appInit();
// newlib definitions we need
void __libc_init_array(void);
void __ctru_exit(int rc);
void __attribute__((weak)) initSystem(void (*retAddr)(void))
{
// Register newlib exit() syscall
__syscalls.exit = __ctru_exit;
__system_retAddr = __service_ptr ? retAddr : NULL;
__system_allocateHeaps();
// Build argc/argv if present
__system_initArgv();
__appInit();
// Run the global constructors
__libc_init_array();
}

View File

@ -1,3 +0,0 @@
# template
This is a template for starting new 3DS/ctrulib projects.