--- /dev/null
+#---------------------------------------------------------------------------------\r
+.SUFFIXES:\r
+#---------------------------------------------------------------------------------\r
+\r
+ifeq ($(strip $(DEVKITARM)),)\r
+$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")\r
+endif\r
+\r
+TOPDIR ?= $(CURDIR)\r
+include $(DEVKITARM)/3ds_rules\r
+\r
+#---------------------------------------------------------------------------------\r
+# TARGET is the name of the output\r
+# BUILD is the directory where object files & intermediate files will be placed\r
+# SOURCES is a list of directories containing source code\r
+# DATA is a list of directories containing data files\r
+# INCLUDES is a list of directories containing header files\r
+#\r
+# NO_SMDH: if set to anything, no SMDH file is generated.\r
+# APP_TITLE is the name of the app stored in the SMDH file (Optional)\r
+# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)\r
+# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)\r
+# ICON is the filename of the icon (.png), relative to the project folder.\r
+# If not set, it attempts to use one of the following (in this order):\r
+# - <Project name>.png\r
+# - icon.png\r
+# - <libctru folder>/default_icon.png\r
+#---------------------------------------------------------------------------------\r
+TARGET := $(notdir $(CURDIR))\r
+BUILD := build\r
+SOURCES := src\r
+DATA := data\r
+INCLUDES := include\r
+APP_TITLE := 3D Camera Example\r
+APP_DESCRIPTION := Example application that takes 3D pictures\r
+APP_AUTHOR := wchill\r
+\r
+#---------------------------------------------------------------------------------\r
+# options for code generation\r
+#---------------------------------------------------------------------------------\r
+ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard\r
+\r
+CFLAGS := -g -Wall -O2 -mword-relocations \\r
+ -fomit-frame-pointer -ffast-math \\r
+ $(ARCH)\r
+\r
+CFLAGS += $(INCLUDE) -DARM11 -D_3DS\r
+\r
+CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11\r
+\r
+ASFLAGS := -g $(ARCH)\r
+LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)\r
+\r
+LIBS := -lctru -lm\r
+\r
+#---------------------------------------------------------------------------------\r
+# list of directories containing libraries, this must be the top level containing\r
+# include and lib\r
+#---------------------------------------------------------------------------------\r
+LIBDIRS := $(CTRULIB)\r
+\r
+\r
+#---------------------------------------------------------------------------------\r
+# no real need to edit anything past this point unless you need to add additional\r
+# rules for different file extensions\r
+#---------------------------------------------------------------------------------\r
+ifneq ($(BUILD),$(notdir $(CURDIR)))\r
+#---------------------------------------------------------------------------------\r
+\r
+export OUTPUT := $(CURDIR)/$(TARGET)\r
+export TOPDIR := $(CURDIR)\r
+\r
+export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \\r
+ $(foreach dir,$(DATA),$(CURDIR)/$(dir))\r
+\r
+export DEPSDIR := $(CURDIR)/$(BUILD)\r
+\r
+CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))\r
+CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))\r
+SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))\r
+BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))\r
+\r
+#---------------------------------------------------------------------------------\r
+# use CXX for linking C++ projects, CC for standard C\r
+#---------------------------------------------------------------------------------\r
+ifeq ($(strip $(CPPFILES)),)\r
+#---------------------------------------------------------------------------------\r
+ export LD := $(CC)\r
+#---------------------------------------------------------------------------------\r
+else\r
+#---------------------------------------------------------------------------------\r
+ export LD := $(CXX)\r
+#---------------------------------------------------------------------------------\r
+endif\r
+#---------------------------------------------------------------------------------\r
+\r
+export OFILES := $(addsuffix .o,$(BINFILES)) \\r
+ $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)\r
+\r
+export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \\r
+ $(foreach dir,$(LIBDIRS),-I$(dir)/include) \\r
+ -I$(CURDIR)/$(BUILD)\r
+\r
+export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)\r
+\r
+ifeq ($(strip $(ICON)),)\r
+ icons := $(wildcard *.png)\r
+ ifneq (,$(findstring $(TARGET).png,$(icons)))\r
+ export APP_ICON := $(TOPDIR)/$(TARGET).png\r
+ else\r
+ ifneq (,$(findstring icon.png,$(icons)))\r
+ export APP_ICON := $(TOPDIR)/icon.png\r
+ endif\r
+ endif\r
+else\r
+ export APP_ICON := $(TOPDIR)/$(ICON)\r
+endif\r
+\r
+.PHONY: $(BUILD) clean all\r
+\r
+#---------------------------------------------------------------------------------\r
+all: $(BUILD)\r
+\r
+$(BUILD):\r
+ @[ -d $@ ] || mkdir -p $@\r
+ @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile\r
+\r
+#---------------------------------------------------------------------------------\r
+clean:\r
+ @echo clean ...\r
+ @rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf\r
+\r
+#---------------------------------------------------------------------------------\r
+else\r
+\r
+DEPENDS := $(OFILES:.o=.d)\r
+\r
+#---------------------------------------------------------------------------------\r
+# main targets\r
+#---------------------------------------------------------------------------------\r
+ifeq ($(strip $(NO_SMDH)),)\r
+.PHONY: all\r
+all : $(OUTPUT).3dsx $(OUTPUT).smdh\r
+endif\r
+$(OUTPUT).3dsx : $(OUTPUT).elf\r
+$(OUTPUT).elf : $(OFILES)\r
+\r
+#---------------------------------------------------------------------------------\r
+# you need a rule like this for each extension you use as binary data\r
+#---------------------------------------------------------------------------------\r
+%.bin.o : %.bin\r
+#---------------------------------------------------------------------------------\r
+ @echo $(notdir $<)\r
+ @$(bin2o)\r
+\r
+# WARNING: This is not the right way to do this! TODO: Do it right!\r
+#---------------------------------------------------------------------------------\r
+%.vsh.o : %.vsh\r
+#---------------------------------------------------------------------------------\r
+ @echo $(notdir $<)\r
+ @python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin\r
+ @bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@\r
+ @echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h\r
+ @echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h\r
+ @echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h\r
+ @rm ../$(notdir $<).shbin\r
+\r
+-include $(DEPENDS)\r
+\r
+#---------------------------------------------------------------------------------------\r
+endif\r
+#---------------------------------------------------------------------------------------\r
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <setjmp.h>
+#include <3ds.h>
+#include <sys/dirent.h>
+#include <sys/errno.h>
+#include <sys/unistd.h>
+#include <stdbool.h>
+
+#define CONFIG_3D_SLIDERSTATE (*(volatile float*)0x1FF81080)
+#define WAIT_TIMEOUT 300000000ULL
+
+#define WIDTH 400
+#define HEIGHT 240
+#define SCREEN_SIZE WIDTH * HEIGHT * 2
+#define BUF_SIZE SCREEN_SIZE * 2
+
+static jmp_buf exitJmp;
+
+inline void clearScreen(void) {
+ u8 *frame = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL);
+ memset(frame, 0, 320 * 240 * 3);
+}
+
+void hang(char *message) {
+ clearScreen();
+ printf("%s", message);
+ printf("Press start to exit");
+
+ while (aptMainLoop()) {
+ hidScanInput();
+
+ u32 kHeld = hidKeysHeld();
+ if (kHeld & KEY_START) longjmp(exitJmp, 1);
+ }
+}
+
+void cleanup() {
+ camExit();
+ gfxExit();
+ acExit();
+}
+
+void writePictureToFramebufferRGB565(void *fb, void *img, u16 x, u16 y, u16 width, u16 height) {
+ u8 *fb_8 = (u8*) fb;
+ u16 *img_16 = (u16*) img;
+ int i, j, draw_x, draw_y;
+ for(j = 0; j < height; j++) {
+ for(i = 0; i < width; i++) {
+ draw_y = y + height - j;
+ draw_x = x + i;
+ u32 v = (draw_y + draw_x * height) * 3;
+ u16 data = img_16[j * width + i];
+ uint8_t b = ((data >> 11) & 0x1F) << 3;
+ uint8_t g = ((data >> 5) & 0x3F) << 2;
+ uint8_t r = (data & 0x1F) << 3;
+ fb_8[v] = r;
+ fb_8[v+1] = g;
+ fb_8[v+2] = b;
+ }
+ }
+}
+
+// TODO: Figure out how to use CAMU_GetStereoCameraCalibrationData
+void takePicture3D(u8 *buf) {
+
+ u32 bufSize;
+ printf("CAMU_GetMaxBytes: 0x%08X\n", (unsigned int) CAMU_GetMaxBytes(&bufSize, WIDTH, HEIGHT));
+ printf("CAMU_SetTransferBytes: 0x%08X\n", (unsigned int) CAMU_SetTransferBytes(PORT_CAM1, bufSize, WIDTH, HEIGHT));
+ printf("CAMU_SetTransferBytes: 0x%08X\n", (unsigned int) CAMU_SetTransferBytes(PORT_CAM2, bufSize, WIDTH, HEIGHT));
+
+ printf("CAMU_Activate: 0x%08X\n", (unsigned int) CAMU_Activate(SELECT_OUT1_OUT2));
+
+ Handle camReceiveEvent = 0;
+ Handle camReceiveEvent2 = 0;
+
+ printf("CAMU_ClearBuffer: 0x%08X\n", (unsigned int) CAMU_ClearBuffer(PORT_CAM1));
+ printf("CAMU_ClearBuffer: 0x%08X\n", (unsigned int) CAMU_ClearBuffer(PORT_CAM2));
+ printf("CAMU_SynchronizeVsyncTiming: 0x%08X\n", (unsigned int) CAMU_SynchronizeVsyncTiming(SELECT_OUT1, SELECT_OUT2));
+ printf("CAMU_SetReceiving: 0x%08X\n", (unsigned int) CAMU_SetReceiving(&camReceiveEvent, buf, PORT_CAM1, SCREEN_SIZE, (s16) bufSize));
+ printf("CAMU_SetReceiving: 0x%08X\n", (unsigned int) CAMU_SetReceiving(&camReceiveEvent2, buf + SCREEN_SIZE, PORT_CAM2, SCREEN_SIZE, (s16) bufSize));
+ printf("CAMU_StartCapture: 0x%08X\n", (unsigned int) CAMU_StartCapture(PORT_CAM1));
+ printf("CAMU_StartCapture: 0x%08X\n", (unsigned int) CAMU_StartCapture(PORT_CAM2));
+ printf("svcWaitSynchronization: 0x%08X\n", (unsigned int) svcWaitSynchronization(camReceiveEvent, WAIT_TIMEOUT));
+ printf("svcWaitSynchronization: 0x%08X\n", (unsigned int) svcWaitSynchronization(camReceiveEvent2, WAIT_TIMEOUT));
+
+ // TODO: Figure out why system hangs here sometimes
+ printf("CAMU_SetReceiving: 0x%08X\n", (unsigned int) CAMU_SetReceiving(&camReceiveEvent, buf, PORT_CAM1, SCREEN_SIZE, (s16) bufSize));
+ printf("CAMU_SetReceiving: 0x%08X\n", (unsigned int) CAMU_SetReceiving(&camReceiveEvent2, buf + SCREEN_SIZE, PORT_CAM2, SCREEN_SIZE, (s16) bufSize));
+ printf("CAMU_PlayShutterSound: 0x%08X\n", (unsigned int) CAMU_PlayShutterSound(SHUTTER_SOUND_TYPE_NORMAL));
+ printf("svcWaitSynchronization: 0x%08X\n", (unsigned int) svcWaitSynchronization(camReceiveEvent, WAIT_TIMEOUT));
+ printf("svcWaitSynchronization: 0x%08X\n", (unsigned int) svcWaitSynchronization(camReceiveEvent2, WAIT_TIMEOUT));
+ printf("CAMU_StopCapture: 0x%08X\n", (unsigned int) CAMU_StopCapture(PORT_CAM1));
+ printf("CAMU_StopCapture: 0x%08X\n", (unsigned int) CAMU_StopCapture(PORT_CAM2));
+
+ printf("CAMU_Activate: 0x%08X\n", (unsigned int) CAMU_Activate(SELECT_NONE));
+}
+
+int main() {
+ // Initializations
+ acInit();
+ gfxInitDefault();
+ consoleInit(GFX_BOTTOM, NULL);
+
+ // Enable double buffering to remove screen tearing
+ gfxSetDoubleBuffering(GFX_TOP, true);
+ gfxSetDoubleBuffering(GFX_BOTTOM, false);
+
+ // Save current stack frame for easy exit
+ if(setjmp(exitJmp)) {
+ cleanup();
+ return 0;
+ }
+
+ u32 kDown;
+ u32 kHeld;
+
+ printf("Initializing camera\n");
+
+ printf("camInit: 0x%08X\n", (unsigned int) camInit());
+
+ printf("CAMU_SetSize: 0x%08X\n", (unsigned int) CAMU_SetSize(SELECT_OUT1_OUT2, SIZE_CTR_TOP_LCD, CONTEXT_A));
+ printf("CAMU_SetOutputFormat: 0x%08X\n", (unsigned int) CAMU_SetOutputFormat(SELECT_OUT1_OUT2, OUTPUT_RGB_565, CONTEXT_A));
+
+ printf("CAMU_SetNoiseFilter: 0x%08X\n", (unsigned int) CAMU_SetNoiseFilter(SELECT_OUT1_OUT2, true));
+ printf("CAMU_SetAutoExposure: 0x%08X\n", (unsigned int) CAMU_SetAutoExposure(SELECT_OUT1_OUT2, true));
+ printf("CAMU_SetAutoWhiteBalance: 0x%08X\n", (unsigned int) CAMU_SetAutoWhiteBalance(SELECT_OUT1_OUT2, true));
+ //printf("CAMU_SetEffect: 0x%08X\n", (unsigned int) CAMU_SetEffect(SELECT_OUT1_OUT2, EFFECT_MONO, CONTEXT_A));
+
+ printf("CAMU_SetTrimming: 0x%08X\n", (unsigned int) CAMU_SetTrimming(PORT_CAM1, false));
+ printf("CAMU_SetTrimming: 0x%08X\n", (unsigned int) CAMU_SetTrimming(PORT_CAM2, false));
+ //printf("CAMU_SetTrimmingParamsCenter: 0x%08X\n", (unsigned int) CAMU_SetTrimmingParamsCenter(PORT_CAM1, 512, 240, 512, 384));
+
+ u8 *buf = malloc(400*240*3*2);
+ if(!buf) {
+ hang("Failed to allocate memory!");
+ }
+
+ gfxFlushBuffers();
+ gspWaitForVBlank();
+ gfxSwapBuffers();
+
+ bool held_R = false;
+
+ printf("\nPress R to take a new picture\n");
+ printf("Use slider to enable/disable 3D\n");
+ printf("Press Start to exit to Homebrew Launcher\n");
+
+ // Main loop
+ while (aptMainLoop()) {
+ // Read which buttons are currently pressed or not
+ hidScanInput();
+ kDown = hidKeysDown();
+ kHeld = hidKeysHeld();
+
+ // If START button is pressed, break loop and quit
+ if (kDown & KEY_START) {
+ break;
+ }
+
+ if (kHeld & KEY_R) {
+ if(!held_R) {
+ printf("Capturing new image (may hang!)\n");
+ gfxFlushBuffers();
+ gspWaitForVBlank();
+ gfxSwapBuffers();
+ held_R = true;
+ takePicture3D(buf);
+ }
+ } else if (!(kHeld & KEY_R)) {
+ held_R = false;
+ }
+
+ if(CONFIG_3D_SLIDERSTATE > 0.0f) {
+ gfxSet3D(true);
+ writePictureToFramebufferRGB565(gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), buf, 0, 0, WIDTH, HEIGHT);
+ writePictureToFramebufferRGB565(gfxGetFramebuffer(GFX_TOP, GFX_RIGHT, NULL, NULL), buf + SCREEN_SIZE, 0, 0, WIDTH, HEIGHT);
+ } else {
+ gfxSet3D(false);
+ writePictureToFramebufferRGB565(gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), buf, 0, 0, WIDTH, HEIGHT);
+ }
+
+ // Flush and swap framebuffers
+ gfxFlushBuffers();
+ gspWaitForVBlank();
+ gfxSwapBuffers();
+ }
+
+ // Exit
+ free(buf);
+ cleanup();
+
+ // Return to hbmenu
+ return 0;
+}