Merge branch 'master' into gpu_revamp
This commit is contained in:
commit
3c4c2a6c04
170
examples/graphics/printing/hello-world/Makefile
Executable file
170
examples/graphics/printing/hello-world/Makefile
Executable 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
|
||||||
|
#---------------------------------------------------------------------------------------
|
63
examples/graphics/printing/hello-world/source/main.c
Normal file
63
examples/graphics/printing/hello-world/source/main.c
Normal 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
6
examples/qtm/README.md
Normal 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.
|
||||||
|
|
92
examples/qtm/source/main.c
Normal file
92
examples/qtm/source/main.c
Normal 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;
|
||||||
|
}
|
||||||
|
|
@ -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
|
|
||||||
|
50
examples/sdmc/source/costable.c
Normal file
50
examples/sdmc/source/costable.c
Normal 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};
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
175
examples/templates/application/Makefile
Normal file
175
examples/templates/application/Makefile
Normal 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
|
||||||
|
#---------------------------------------------------------------------------------------
|
3
examples/templates/application/README.md
Normal file
3
examples/templates/application/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# template
|
||||||
|
|
||||||
|
This is a template for starting new 3DS libctru projects.
|
121
examples/templates/library/Makefile
Normal file
121
examples/templates/library/Makefile
Normal 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
|
||||||
|
#---------------------------------------------------------------------------------------
|
3
examples/templates/library/README.md
Normal file
3
examples/templates/library/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# template
|
||||||
|
|
||||||
|
This is a template for starting new 3DS library projects.
|
6
examples/templates/library/include/templatelib.h
Normal file
6
examples/templates/library/include/templatelib.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _templatelib_h_
|
||||||
|
#define _templatelib_h_
|
||||||
|
|
||||||
|
int myLibFunction();
|
||||||
|
|
||||||
|
#endif // _templatelib_h_
|
6
examples/templates/library/source/templatelib.c
Normal file
6
examples/templates/library/source/templatelib.c
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
int myLibFunction() {
|
||||||
|
|
||||||
|
|
||||||
|
return 42;
|
||||||
|
|
||||||
|
}
|
@ -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
|
||||||
|
|
||||||
|
BIN
libctru/data/default_font.bin
Normal file
BIN
libctru/data/default_font.bin
Normal file
Binary file not shown.
@ -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>
|
||||||
|
159
libctru/include/3ds/console.h
Normal file
159
libctru/include/3ds/console.h
Normal 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
|
@ -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();
|
||||||
|
27
libctru/include/3ds/services/hb.h
Normal file
27
libctru/include/3ds/services/hb.h
Normal 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
|
@ -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)
|
||||||
|
@ -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);
|
||||||
|
25
libctru/include/3ds/services/qtm.h
Normal file
25
libctru/include/3ds/services/qtm.h
Normal 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.
|
||||||
|
|
@ -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 {
|
||||||
|
8
libctru/include/3ds/vram.h
Normal file
8
libctru/include/3ds/vram.h
Normal 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
|
48
libctru/source/allocator/addrmap.h
Normal file
48
libctru/source/allocator/addrmap.h
Normal 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);
|
||||||
|
}
|
@ -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()
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
|
86
libctru/source/allocator/vram.cpp
Normal file
86
libctru/source/allocator/vram.cpp
Normal 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
751
libctru/source/console.c
Normal 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 = ¤tCopy;
|
||||||
|
|
||||||
|
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", ¶meter, &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", ¶meter, &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", ¶meter, &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", ¶meter, &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", ¶meter, &consumed);
|
||||||
|
} else {
|
||||||
|
sscanf(escapeseq,"%dm%n", ¶meter, &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 = ¤tConsole->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 = ¤tConsole->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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
|
||||||
}
|
|
@ -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() {
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
67
libctru/source/services/hb.c
Normal file
67
libctru/source/services/hb.c
Normal 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];
|
||||||
|
}
|
@ -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];
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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];
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
87
libctru/source/services/qtm.c
Normal file
87
libctru/source/services/qtm.c
Normal 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;
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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())) {
|
||||||
|
@ -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
|
||||||
|
24
libctru/source/system/allocateHeaps.c
Normal file
24
libctru/source/system/allocateHeaps.c
Normal 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;
|
||||||
|
|
||||||
|
}
|
17
libctru/source/system/appExit.c
Normal file
17
libctru/source/system/appExit.c
Normal 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();
|
||||||
|
}
|
17
libctru/source/system/appInit.c
Normal file
17
libctru/source/system/appInit.c
Normal 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();
|
||||||
|
}
|
38
libctru/source/system/ctru_exit.c
Normal file
38
libctru/source/system/ctru_exit.c
Normal 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();
|
||||||
|
}
|
50
libctru/source/system/initArgv.c
Normal file
50
libctru/source/system/initArgv.c
Normal 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;
|
||||||
|
}
|
37
libctru/source/system/initSystem.c
Normal file
37
libctru/source/system/initSystem.c
Normal 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();
|
||||||
|
}
|
@ -1,3 +0,0 @@
|
|||||||
# template
|
|
||||||
|
|
||||||
This is a template for starting new 3DS/ctrulib projects.
|
|
Loading…
Reference in New Issue
Block a user