diff --git a/Makefile.ctr b/Makefile.ctr
new file mode 100644
index 0000000000..a2e23b0638
--- /dev/null
+++ b/Makefile.ctr
@@ -0,0 +1,137 @@
+TARGET := retroarch_3ds
+OBJS :=
+OBJS += gfx/drivers/ctr_blit.o griffin/griffin.o
+#NO_SMDH = 1
+DEBUG = 0
+
+
+CTRULIB = /home/lethalis/3ds/ctrulib/libctru
+AEMSTRO = /home/lethalis/3ds/aemstro
+
+export PATH := $(DEVKITARM)/bin:$(PATH)
+
+INCDIRS := -I$(CTRULIB)/include
+LIBDIRS := -L. -L$(CTRULIB)/lib
+
+
+ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
+
+CFLAGS += -mword-relocations \
+ -fomit-frame-pointer -ffast-math \
+ $(ARCH)
+
+#CFLAGS += -Wall
+CFLAGS += -DARM11 -D_3DS
+
+ifeq ($(DEBUG), 1)
+ CFLAGS += -O0 -g
+else
+ CFLAGS += -O3
+endif
+CFLAGS += -I. -Ideps/zlib -Ideps/7zip -Ilibretro-common/include
+
+CFLAGS += -DRARCH_INTERNAL -DRARCH_CONSOLE -DSINC_LOWEST_QUALITY
+CFLAGS += -DHAVE_GRIFFIN=1 -DHAVE_FILTERS_BUILTIN -DHAVE_MENU -DHAVE_RGUI
+CFLAGS += -DHAVE_ZLIB -DWANT_ZLIB
+#-DHAVE_LIBRETRO_MANAGEMENT -DWANT_RPNG -DHAVE_BUILTIN_AUTOCONFIG -DHAVE_FILTERS_BUILTIN -DHAVE_7ZIP
+
+
+CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
+
+ASFLAGS := -g $(ARCH)
+LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
+CFLAGS += -std=gnu99 -ffast-math
+
+
+LIBS := -lretro_ctr -lctru -lm
+
+
+
+.PHONY: $(BUILD) clean all
+
+#---------------------------------------------------------------------------------
+all: $(TARGET)
+
+clean:
+ rm -f $(OBJS)
+ rm -f $(TARGET).3dsx
+ rm -f $(TARGET).elf
+
+
+$(TARGET): $(TARGET).3dsx
+$(TARGET).3dsx : $(TARGET).elf
+$(TARGET).elf : $(OBJS)
+
+ifeq ($(strip $(APP_TITLE)),)
+APP_TITLE := $(notdir $(TARGET))
+endif
+
+ifeq ($(strip $(APP_DESCRIPTION)),)
+APP_DESCRIPTION := Built with devkitARM & libctru
+endif
+
+ifeq ($(strip $(APP_AUTHOR)),)
+APP_AUTHOR := Unspecified Author
+endif
+
+ifeq ($(strip $(APP_ICON)),)
+APP_ICON := $(CTRULIB)/default_icon.png
+endif
+
+PREFIX := $(DEVKITARM)/bin/arm-none-eabi-
+
+CC := $(PREFIX)gcc
+CXX := $(PREFIX)g++
+AS := $(PREFIX)as
+AR := $(PREFIX)ar
+OBJCOPY := $(PREFIX)objcopy
+STRIP := $(PREFIX)strip
+NM := $(PREFIX)nm
+LD := $(CXX)
+
+
+%.o: %.shader
+#---------------------------------------------------------------------------------
+ @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
+
+
+%.o: %.cpp
+ $(CXX) -c -o $@ $< $(CXXFLAGS) $(INCDIRS)
+
+%.o: %.c
+ $(CC) -c -o $@ $< $(CFLAGS) $(INCDIRS)
+
+%.o: %.s
+ $(CC) -c -o $@ $< $(ASFLAGS)
+
+%.o: %.S
+ $(CC) -c -o $@ $< $(ASFLAGS)
+
+%.a:
+ $(AR) -rc $@ $^
+
+%.vsh:
+
+#---------------------------------------------------------------------------------
+%.smdh: $(APP_ICON) $(MAKEFILE_LIST)
+ @echo building ... $(notdir $@)
+ smdhtool --create "$(APP_TITLE)" "$(APP_DESCRIPTION)" "$(APP_AUTHOR)" $(APP_ICON) $@
+
+#---------------------------------------------------------------------------------
+%.3dsx: %.elf
+ @echo building ... $(notdir $@)
+ 3dsxtool $< $@ $(_3DSXFLAGS)
+
+#---------------------------------------------------------------------------------
+%.elf:
+ @echo linking $(notdir $@)
+ $(LD) $(LDFLAGS) $(OBJS) $(LIBDIRS) $(LIBS) -o $@
+ $(NM) -CSn $@ > $(notdir $*.lst)
+
+
diff --git a/audio/audio_driver.c b/audio/audio_driver.c
index a8ba7357da..a1a26fb93f 100644
--- a/audio/audio_driver.c
+++ b/audio/audio_driver.c
@@ -79,6 +79,9 @@ static const audio_driver_t *audio_drivers[] = {
#ifdef PSP
&audio_psp1,
#endif
+#ifdef _3DS
+ &audio_ctr,
+#endif
&audio_null,
NULL,
};
diff --git a/audio/audio_driver.h b/audio/audio_driver.h
index 14ac349feb..0d2365bf47 100644
--- a/audio/audio_driver.h
+++ b/audio/audio_driver.h
@@ -89,6 +89,7 @@ extern audio_driver_t audio_xenon360;
extern audio_driver_t audio_ps3;
extern audio_driver_t audio_gx;
extern audio_driver_t audio_psp1;
+extern audio_driver_t audio_ctr;
extern audio_driver_t audio_rwebaudio;
extern audio_driver_t audio_null;
diff --git a/audio/drivers/ctr_audio.c b/audio/drivers/ctr_audio.c
new file mode 100644
index 0000000000..9da928b0d1
--- /dev/null
+++ b/audio/drivers/ctr_audio.c
@@ -0,0 +1,89 @@
+
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
+ *
+ * RetroArch is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with RetroArch.
+ * If not, see .
+ */
+
+#include "../../general.h"
+#include "../../driver.h"
+
+static void *ctr_audio_init(const char *device, unsigned rate, unsigned latency)
+{
+ (void)device;
+ (void)rate;
+ (void)latency;
+ return (void*)-1;
+}
+
+static void ctr_audio_free(void *data)
+{
+ (void)data;
+}
+
+static ssize_t ctr_audio_write(void *data, const void *buf, size_t size)
+{
+ (void)data;
+ (void)buf;
+
+ return size;
+}
+
+static bool ctr_audio_stop(void *data)
+{
+ (void)data;
+ return true;
+}
+
+static bool ctr_audio_alive(void *data)
+{
+ (void)data;
+ return true;
+}
+
+static bool ctr_audio_start(void *data)
+{
+ (void)data;
+ return true;
+}
+
+static void ctr_audio_set_nonblock_state(void *data, bool state)
+{
+ (void)data;
+ (void)state;
+}
+
+static bool ctr_audio_use_float(void *data)
+{
+ (void)data;
+ return true;
+}
+
+static size_t ctr_audio_write_avail(void *data)
+{
+ (void)data;
+ return 0;
+}
+
+audio_driver_t audio_ctr = {
+ ctr_audio_init,
+ ctr_audio_write,
+ ctr_audio_stop,
+ ctr_audio_start,
+ ctr_audio_alive,
+ ctr_audio_set_nonblock_state,
+ ctr_audio_free,
+ ctr_audio_use_float,
+ "ctr",
+ ctr_audio_write_avail,
+ NULL
+};
diff --git a/config.def.h b/config.def.h
index d4b24a2439..f7d0c7d2df 100644
--- a/config.def.h
+++ b/config.def.h
@@ -36,8 +36,9 @@ enum
VIDEO_WII,
VIDEO_XENON360,
VIDEO_XDK_D3D,
- VIDEO_PSP1,
+ VIDEO_PSP1,
VIDEO_VITA,
+ VIDEO_CTR,
VIDEO_D3D9,
VIDEO_VG,
VIDEO_NULL,
@@ -66,6 +67,7 @@ enum
AUDIO_WII,
AUDIO_RWEBAUDIO,
AUDIO_PSP1,
+ AUDIO_CTR,
AUDIO_NULL,
AUDIO_RESAMPLER_CC,
@@ -80,6 +82,7 @@ enum
INPUT_DINPUT,
INPUT_PS3,
INPUT_PSP,
+ INPUT_CTR,
INPUT_XENON360,
INPUT_WII,
INPUT_XINPUT,
@@ -95,6 +98,7 @@ enum
JOYPAD_GX,
JOYPAD_XDK,
JOYPAD_PSP,
+ JOYPAD_CTR,
JOYPAD_DINPUT,
JOYPAD_UDEV,
JOYPAD_LINUXRAW,
@@ -142,6 +146,8 @@ enum
#define VIDEO_DEFAULT_DRIVER VIDEO_VITA
#elif defined(PSP)
#define VIDEO_DEFAULT_DRIVER VIDEO_PSP1
+#elif defined(_3DS)
+#define VIDEO_DEFAULT_DRIVER VIDEO_CTR
#elif defined(HAVE_XVIDEO)
#define VIDEO_DEFAULT_DRIVER VIDEO_XVIDEO
#elif defined(HAVE_SDL)
@@ -162,6 +168,8 @@ enum
#define AUDIO_DEFAULT_DRIVER AUDIO_WII
#elif defined(PSP)
#define AUDIO_DEFAULT_DRIVER AUDIO_PSP1
+#elif defined(_3DS)
+#define AUDIO_DEFAULT_DRIVER AUDIO_CTR
#elif defined(HAVE_ALSA) && defined(HAVE_VIDEOCORE)
#define AUDIO_DEFAULT_DRIVER AUDIO_ALSATHREAD
#elif defined(HAVE_ALSA)
@@ -218,6 +226,8 @@ enum
#define INPUT_DEFAULT_DRIVER INPUT_PS3
#elif (defined(SN_TARGET_PSP2) || defined(PSP))
#define INPUT_DEFAULT_DRIVER INPUT_PSP
+#elif defined(_3DS)
+#define INPUT_DEFAULT_DRIVER INPUT_CTR
#elif defined(GEKKO)
#define INPUT_DEFAULT_DRIVER INPUT_WII
#elif defined(HAVE_UDEV)
@@ -250,6 +260,8 @@ enum
#define JOYPAD_DEFAULT_DRIVER JOYPAD_XDK
#elif defined(PSP)
#define JOYPAD_DEFAULT_DRIVER JOYPAD_PSP
+#elif defined(_3DS)
+#define JOYPAD_DEFAULT_DRIVER JOYPAD_CTR
#elif defined(HAVE_DINPUT)
#define JOYPAD_DEFAULT_DRIVER JOYPAD_DINPUT
#elif defined(HAVE_UDEV)
diff --git a/configuration.c b/configuration.c
index c30fdfc6c1..7d4e4d79f8 100644
--- a/configuration.c
+++ b/configuration.c
@@ -113,6 +113,8 @@ const char *config_get_default_audio(void)
return "gx";
case AUDIO_PSP1:
return "psp1";
+ case AUDIO_CTR:
+ return "ctr";
case AUDIO_RWEBAUDIO:
return "rwebaudio";
default:
@@ -170,6 +172,8 @@ const char *config_get_default_video(void)
return "psp1";
case VIDEO_VITA:
return "vita";
+ case VIDEO_CTR:
+ return "ctr";
case VIDEO_XVIDEO:
return "xvideo";
case VIDEO_SDL:
@@ -212,6 +216,8 @@ const char *config_get_default_input(void)
return "ps3";
case INPUT_PSP:
return "psp";
+ case INPUT_CTR:
+ return "ctr";
case INPUT_SDL:
return "sdl";
case INPUT_SDL2:
@@ -266,6 +272,8 @@ const char *config_get_default_joypad(void)
return "xdk";
case JOYPAD_PSP:
return "psp";
+ case JOYPAD_CTR:
+ return "ctr";
case JOYPAD_DINPUT:
return "dinput";
case JOYPAD_UDEV:
diff --git a/frontend/drivers/platform_ctr.c b/frontend/drivers/platform_ctr.c
new file mode 100644
index 0000000000..9868a37394
--- /dev/null
+++ b/frontend/drivers/platform_ctr.c
@@ -0,0 +1,211 @@
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
+ * Copyright (C) 2011-2015 - Daniel De Matteis
+ *
+ * RetroArch is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with RetroArch.
+ * If not, see .
+ */
+
+#include <3ds.h>
+
+#include
+#include
+#include
+#include
+
+#include
+#include "../../general.h"
+
+#ifdef IS_SALAMANDER
+#include "../../file_ext.h"
+#endif
+
+
+int __stacksize__ = 1*1024*1024;
+//char elf_path[512];
+
+const char* elf_path_cst = "sdmc:/retroarch/test.3dsx";
+
+
+void wait_for_input(void);
+#define DEBUG_HOLD() do{printf("%s@%s:%d.\n",__FUNCTION__, __FILE__, __LINE__);fflush(stdout);wait_for_input();}while(0)
+
+static void frontend_ctr_get_environment_settings(int *argc, char *argv[],
+ void *args, void *params_data)
+{
+ (void)args;
+
+// return;
+#ifndef IS_SALAMANDER
+#if defined(HAVE_LOGGER)
+ logger_init();
+#elif defined(HAVE_FILE_LOGGER)
+ global_t *global = global_get_ptr();
+ global->log_file = fopen("sdmc:/retroarch/retroarch-log.txt", "w");
+#endif
+#endif
+
+// strlcpy(elf_path, argv[0], sizeof(elf_path));
+
+// fill_pathname_basedir(g_defaults.port_dir, argv[0], sizeof(g_defaults.port_dir));
+ fill_pathname_basedir(g_defaults.port_dir, elf_path_cst, sizeof(g_defaults.port_dir));
+ RARCH_LOG("port dir: [%s]\n", g_defaults.port_dir);
+
+ fill_pathname_join(g_defaults.assets_dir, g_defaults.port_dir,
+ "media", sizeof(g_defaults.assets_dir));
+ fill_pathname_join(g_defaults.core_dir, g_defaults.port_dir,
+ "cores", sizeof(g_defaults.core_dir));
+ fill_pathname_join(g_defaults.core_info_dir, g_defaults.port_dir,
+ "cores", sizeof(g_defaults.core_info_dir));
+ fill_pathname_join(g_defaults.savestate_dir, g_defaults.core_dir,
+ "savestates", sizeof(g_defaults.savestate_dir));
+ fill_pathname_join(g_defaults.sram_dir, g_defaults.core_dir,
+ "savefiles", sizeof(g_defaults.sram_dir));
+ fill_pathname_join(g_defaults.system_dir, g_defaults.core_dir,
+ "system", sizeof(g_defaults.system_dir));
+ fill_pathname_join(g_defaults.playlist_dir, g_defaults.core_dir,
+ "playlists", sizeof(g_defaults.playlist_dir));
+ fill_pathname_join(g_defaults.config_path, g_defaults.port_dir,
+ "retroarch.cfg", sizeof(g_defaults.config_path));
+
+#ifndef IS_SALAMANDER
+// if (argv[1] && (argv[1][0] != '\0'))
+// {
+// static char path[PATH_MAX_LENGTH];
+// struct rarch_main_wrap *args = NULL;
+
+// *path = '\0';
+// args = (struct rarch_main_wrap*)params_data;
+
+// if (args)
+// {
+// strlcpy(path, argv[1], sizeof(path));
+
+// args->touched = true;
+// args->no_content = false;
+// args->verbose = false;
+// args->config_path = NULL;
+// args->sram_path = NULL;
+// args->state_path = NULL;
+// args->content_path = path;
+// args->libretro_path = NULL;
+
+// RARCH_LOG("argv[0]: %s\n", argv[0]);
+// RARCH_LOG("argv[1]: %s\n", argv[1]);
+// RARCH_LOG("argv[2]: %s\n", argv[2]);
+
+// RARCH_LOG("Auto-start game %s.\n", argv[1]);
+// }
+// }
+#endif
+}
+
+static void frontend_ctr_deinit(void *data)
+{
+ (void)data;
+#ifndef IS_SALAMANDER
+ global_t *global = global_get_ptr();
+ global->verbosity = true;
+
+#ifdef HAVE_FILE_LOGGER
+ if (global->log_file)
+ fclose(global->log_file);
+ global->log_file = NULL;
+#endif
+
+ gfxExit();
+ // sdmcExit();
+ // fsExit();
+ // hidExit();
+ // aptExit();
+ // srvExit();
+#endif
+}
+
+static void frontend_ctr_shutdown(bool unused)
+{
+ (void)unused;
+}
+
+static int exit_callback(int arg1, int arg2, void *common)
+{
+ frontend_ctr_deinit(NULL);
+ frontend_ctr_shutdown(false);
+ return 0;
+}
+
+#define PRINTFPOS(X,Y) "\x1b["#X";"#Y"H"
+#define PRINTFPOS_STR(X,Y) "\x1b["X";"Y"H"
+static void frontend_ctr_init(void *data)
+{
+#ifndef IS_SALAMANDER
+ (void)data;
+ global_t *global = global_get_ptr();
+ global->verbosity = true;
+
+ gfxInitDefault();
+ gfxSet3D(false);
+ consoleInit(GFX_BOTTOM, NULL);
+
+// consoleInit(GFX_BOTTOM, NULL);
+
+// gfxInitDefault();
+// gfxInit(GSP_RGBA8_OES,GSP_RGBA8_OES,false);
+
+// gfxSet3D(false);
+
+// consoleInit(GFX_BOTTOM, NULL);
+// printf(PRINTFPOS(0,0)"3ds_test");
+// printf(PRINTFPOS(0,1)"Press Start to exit.");
+
+// gfxFlushBuffers();
+// gfxSwapBuffers();
+#endif
+
+}
+
+
+static int frontend_ctr_get_rating(void)
+{
+ return 4;
+}
+bool select_pressed = false;
+void wait_for_input()
+{
+ printf("Press Start.\n\n\n\n");fflush(stdout);
+ while(aptMainLoop())
+ {
+ hidScanInput();
+ u32 kDown = hidKeysDown();
+ if (kDown & KEY_START)
+ break;
+
+ if (kDown & KEY_SELECT)
+ select_pressed = true;
+
+ svcSleepThread(1000000);
+ }
+}
+
+const frontend_ctx_driver_t frontend_ctx_ctr = {
+ frontend_ctr_get_environment_settings, /* get_environment_settings */
+ frontend_ctr_init, /* init */
+ frontend_ctr_deinit, /* deinit */
+ NULL, /* exitspawn */
+ NULL, /* process_args */
+ NULL, /* exec */
+ NULL, /* set_fork */
+ frontend_ctr_shutdown, /* shutdown */
+ NULL, /* get_name */
+ frontend_ctr_get_rating, /* get_rating */
+ NULL, /* load_content */
+ "ctr",
+};
diff --git a/frontend/frontend_driver.c b/frontend/frontend_driver.c
index 3f7f2602b6..1593d72dc1 100644
--- a/frontend/frontend_driver.c
+++ b/frontend/frontend_driver.c
@@ -42,6 +42,9 @@ static const frontend_ctx_driver_t *frontend_ctx_drivers[] = {
#endif
#if defined(PSP)
&frontend_ctx_psp,
+#endif
+#if defined(_3DS)
+ &frontend_ctx_ctr,
#endif
&frontend_ctx_null,
NULL
diff --git a/frontend/frontend_driver.h b/frontend/frontend_driver.h
index 60b8a3cfb0..6a82ff4f7b 100644
--- a/frontend/frontend_driver.h
+++ b/frontend/frontend_driver.h
@@ -59,6 +59,7 @@ extern const frontend_ctx_driver_t frontend_ctx_qnx;
extern const frontend_ctx_driver_t frontend_ctx_apple;
extern const frontend_ctx_driver_t frontend_ctx_android;
extern const frontend_ctx_driver_t frontend_ctx_psp;
+extern const frontend_ctx_driver_t frontend_ctx_ctr;
extern const frontend_ctx_driver_t frontend_ctx_null;
/**
diff --git a/gfx/drivers/ctr_blit.shader b/gfx/drivers/ctr_blit.shader
new file mode 100644
index 0000000000..f4f161e822
--- /dev/null
+++ b/gfx/drivers/ctr_blit.shader
@@ -0,0 +1,39 @@
+; setup constants
+ .const c20, 0.0, 1.0, 0.0, 1.0
+
+; setup outmap
+ .out o0, result.position, 0xF
+ .out o1, result.color, 0xF
+ .out o2, result.texcoord0, 0x3
+
+; setup uniform map (not required)
+ .uniform c0, c3, projection
+
+ .vsh vmain, end_vmain
+
+;code
+ vmain:
+ mov r0, v0 (0x4)
+ mov r0, c20 (0x3)
+ dp4 o0, c0, r0 (0x0)
+ dp4 o0, c1, r0 (0x1)
+ dp4 o0, c2, r0 (0x2)
+ mov o0, c20 (0x3)
+ mov o1, c20 (0x5)
+ ;mov o2, v1 (0x6)
+ mul r0, c3, v1 (0x6)
+ add o2, c20, r0 (0x7)
+ flush
+ nop
+ end
+ end_vmain:
+
+;operand descriptors
+ .opdesc x___, xyzw, xyzw ; 0x0
+ .opdesc _y__, xyzw, xyzw ; 0x1
+ .opdesc __z_, xyzw, xyzw ; 0x2
+ .opdesc ___w, xyzw, xyzw ; 0x3
+ .opdesc xyz_, xyzw, xyzw ; 0x4
+ .opdesc xyzw, wwww, wwww ; 0x5
+ .opdesc xyzw, xyzw, xyzw ; 0x6
+ .opdesc xyzw, xyzz, xyzw ; 0x7
diff --git a/gfx/drivers/ctr_gfx.c b/gfx/drivers/ctr_gfx.c
new file mode 100644
index 0000000000..8bb2f96994
--- /dev/null
+++ b/gfx/drivers/ctr_gfx.c
@@ -0,0 +1,533 @@
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
+ * Copyright (C) 2011-2015 - Daniel De Matteis
+ *
+ * RetroArch is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with RetroArch.
+ * If not, see .
+ */
+
+/* using code the from GPU example in crtulib */
+
+#include <3ds.h>
+#include
+#include
+#include
+#include "ctr_blit_shader_shbin.h"
+
+
+#include "../../general.h"
+#include "../../driver.h"
+#include "../video_viewport.h"
+#include "../video_monitor.h"
+
+#include "retroarch.h"
+
+typedef struct ctr_video
+{
+ bool rgb32;
+ bool vsync;
+ bool smooth;
+ bool menu_texture_enable;
+ unsigned rotation;
+} ctr_video_t;
+
+DVLB_s* dvlb;
+shaderProgram_s shader;
+u32* texData;
+u32* texData2;
+
+//GPU framebuffer address
+u32* gpuOut = (u32*)0x1F119400;
+//GPU depth buffer address
+u32* gpuDOut = (u32*)0x1F370800;
+
+typedef struct
+{
+ struct
+ {
+ float x, y, z;
+ } position;
+ float texcoord[2];
+} vertex_s;
+
+
+u32 gpuCmdSize;
+u32* gpuCmd;
+u32* gpuCmdRight;
+
+
+u32* texture_bin;
+
+#define tex_w 512
+#define tex_h 512
+#define gpu_tex_w 512
+#define gpu_tex_h 512
+
+#define TEX_MAKE_SIZE(W,H) (((u32)(W))|((u32)(H)<<16))
+#define tex_size TEX_MAKE_SIZE(tex_w, tex_h)
+#define gpu_tex_size TEX_MAKE_SIZE(gpu_tex_w, gpu_tex_h)
+
+#define texture_bin_size (tex_w * tex_h * sizeof(*texture_bin))
+#define gpu_texture_bin_size (gpu_tex_w * gpu_tex_h * 4)
+
+#define fbwidth 400
+#define fbheight 240
+
+#define CTR_MATRIX(X0,Y0,Z0,W0,X1,Y1,Z1,W1,X2,Y2,Z2,W2,X3,Y3,Z3,W3) {W0,Z0,Y0,X0,W1,Z1,Y1,X1,W2,Z2,Y2,X2,W3,Z3,Y3,X3}
+
+float proj_m[16] = CTR_MATRIX
+ (
+ 0.0, -2.0 / fbheight, 0.0, 1.0,
+ -2.0 / fbwidth, 0.0, 0.0, 1.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 1.0 / gpu_tex_w, -1.0 / gpu_tex_h, 1.0, 1.0
+ );
+
+
+
+
+const vertex_s modelVboData[] =
+{
+ {{ 40 + 0.0f, 0.0f, -1.0f}, {0.0f, 0.0f}},
+ {{ 40 + 320, 0.0f, -1.0f}, {320, 0.0f}},
+ {{ 40 + 320, tex_h, -1.0f}, {320, tex_h}},
+
+ {{ 40 + 0.0f, 0.0f, -1.0f}, {0.0f, 0.0f}},
+ {{ 40 + 320, tex_h, -1.0f}, {320, tex_h}},
+ {{ 40 + 0.0f, tex_h, -1.0f}, {0.0f, tex_h}}
+};
+
+void* vbo_buffer;
+
+//stolen from staplebutt
+void GPU_SetDummyTexEnv(u8 num)
+{
+ GPU_SetTexEnv(num,
+ GPU_TEVSOURCES(GPU_PREVIOUS, 0, 0),
+ GPU_TEVSOURCES(GPU_PREVIOUS, 0, 0),
+ GPU_TEVOPERANDS(0, 0, 0),
+ GPU_TEVOPERANDS(0, 0, 0),
+ GPU_REPLACE,
+ GPU_REPLACE,
+ 0xFFFFFFFF);
+}
+
+// topscreen
+void renderFrame()
+{
+ GPU_SetViewport((u32*)osConvertVirtToPhys((u32)gpuDOut),
+ (u32*)osConvertVirtToPhys((u32)gpuOut), 0, 0, fbheight * 2, fbwidth);
+
+ GPU_DepthMap(-1.0f, 0.0f);
+ GPU_SetFaceCulling(GPU_CULL_NONE);
+ GPU_SetStencilTest(false, GPU_ALWAYS, 0x00, 0xFF, 0x00);
+ GPU_SetStencilOp(GPU_KEEP, GPU_KEEP, GPU_KEEP);
+ GPU_SetBlendingColor(0, 0, 0, 0);
+ // GPU_SetDepthTestAndWriteMask(true, GPU_GREATER, GPU_WRITE_ALL);
+ GPU_SetDepthTestAndWriteMask(false, GPU_ALWAYS, GPU_WRITE_ALL);
+ // GPU_SetDepthTestAndWriteMask(true, GPU_ALWAYS, GPU_WRITE_ALL);
+
+ GPUCMD_AddMaskedWrite(GPUREG_0062, 0x1, 0);
+ GPUCMD_AddWrite(GPUREG_0118, 0);
+
+ GPU_SetAlphaBlending(GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_SRC_ALPHA,
+ GPU_ONE_MINUS_SRC_ALPHA, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_SetAlphaTest(false, GPU_ALWAYS, 0x00);
+
+ GPU_SetTextureEnable(GPU_TEXUNIT0);
+
+ GPU_SetTexEnv(0,
+ GPU_TEVSOURCES(GPU_TEXTURE0, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR),
+ GPU_TEVSOURCES(GPU_TEXTURE0, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR),
+ GPU_TEVOPERANDS(0, 0, 0),
+ GPU_TEVOPERANDS(0, 0, 0),
+ GPU_MODULATE, GPU_MODULATE,
+ 0xFFFFFFFF);
+ GPU_SetDummyTexEnv(1);
+ GPU_SetDummyTexEnv(2);
+ GPU_SetDummyTexEnv(3);
+ GPU_SetDummyTexEnv(4);
+ GPU_SetDummyTexEnv(5);
+
+ //texturing stuff
+ GPU_SetTexture(GPU_TEXUNIT0, (u32*)osConvertVirtToPhys((u32)texData), gpu_tex_w, gpu_tex_h,
+ GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR),
+ GPU_RGBA4);
+
+ u32 bufferoffset = 0x00000000;
+ u64 bufferpermutations = 0x210;
+ u8 numattributes = 2;
+ GPU_SetAttributeBuffers(3, (u32*)osConvertVirtToPhys((u32)vbo_buffer),
+ GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT),
+ 0xFFC, 0x210, 1, &bufferoffset, &bufferpermutations, &numattributes);
+
+ GPU_DrawArray(GPU_TRIANGLES, sizeof(modelVboData) / sizeof(vertex_s));
+
+ GPU_FinishDrawing();
+}
+
+void gpu_init_calls(void)
+{
+ GPU_Init(NULL);
+ gpuCmdSize = 0x40000;
+ gpuCmd = (u32*)linearAlloc(gpuCmdSize * 4);
+ gpuCmdRight = (u32*)linearAlloc(gpuCmdSize * 4);
+ GPU_Reset(NULL, gpuCmd, gpuCmdSize);
+ dvlb = DVLB_ParseFile((u32*)ctr_blit_shader_shbin, ctr_blit_shader_shbin_size);
+ shaderProgramInit(&shader);
+ shaderProgramSetVsh(&shader, &dvlb->DVLE[0]);
+ shaderProgramUse(&shader);
+
+ // Flush the command buffer so that the shader upload gets executed
+ GPUCMD_Finalize();
+ GPUCMD_FlushAndRun(NULL);
+ gspWaitForP3D();
+
+ //create texture
+ texData = (u32*)linearMemAlign(gpu_texture_bin_size,
+ 0x80); //textures need to be 0x80-byte aligned
+
+ texData2 = (u32*)linearMemAlign(texture_bin_size,
+ 0x80); //textures need to be 0x80-byte aligned
+
+ memcpy(texData2, texture_bin, texture_bin_size);
+ vbo_buffer = linearAlloc(sizeof(modelVboData));
+ memcpy(vbo_buffer, (void*)modelVboData, sizeof(modelVboData));
+}
+
+#define PRINTFPOS(X,Y) "\x1b["#X";"#Y"H"
+#define PRINTFPOS_STR(X,Y) "\x1b["X";"Y"H"
+
+static void* ctr_init(const video_info_t* video,
+ const input_driver_t** input, void** input_data)
+{
+ void* ctrinput = NULL;
+ global_t* global = global_get_ptr();
+ ctr_video_t* ctr = (ctr_video_t*)calloc(1, sizeof(ctr_video_t));
+
+ if (!ctr)
+ return NULL;
+
+ printf("%s@%s:%d.\n",__FUNCTION__, __FILE__, __LINE__);fflush(stdout);
+
+// gfxInitDefault();
+// gfxSet3D(false);
+ texture_bin = (typeof(texture_bin))malloc(texture_bin_size);
+ int i, j;
+ for (j = 0; j < tex_h; j++)
+ {
+ for (i = 0; i < tex_w; i++)
+ {
+ if ((i & 0x8) || (j & 0x8))
+ texture_bin[i + j * tex_w] = 0x0000FFFF;
+ else
+ texture_bin[i + j * tex_w] = 0xFFFFFFFF;
+
+ if (i > 64)
+ texture_bin[i + j * tex_w] = 0xFF0000FF;
+
+ }
+
+ }
+
+ gpu_init_calls();
+
+ if (input && input_data)
+ {
+ ctrinput = input_ctr.init();
+ *input = ctrinput ? &input_ctr : NULL;
+ *input_data = ctrinput;
+ }
+
+ printf("%s@%s:%d.\n",__FUNCTION__, __FILE__, __LINE__);fflush(stdout);
+ return ctr;
+}
+
+static bool ctr_frame(void* data, const void* frame,
+ unsigned width, unsigned height, unsigned pitch, const char* msg)
+{
+ ctr_video_t* ctr = (ctr_video_t*)data;
+ settings_t* settings = config_get_ptr();
+
+// int i;
+ static int frames = 0;
+
+ if (!width || !height)
+ {
+ gspWaitForEvent(GSPEVENT_VBlank0, true);
+ return true;
+ }
+
+ if(!aptMainLoop())
+ {
+ rarch_main_command(RARCH_CMD_QUIT);
+ return true;
+ }
+
+ extern bool select_pressed;
+ if (select_pressed)
+ {
+ rarch_main_command(RARCH_CMD_QUIT);
+ return true;
+ }
+
+ hidScanInput();
+ u32 kDown = hidKeysDown();
+ if (kDown & KEY_START)
+ {
+ rarch_main_command(RARCH_CMD_QUIT);
+ return true;
+ }
+
+
+ printf("frames: %i\r", frames++);fflush(stdout);
+// gfxFlushBuffers();
+// gspWaitForEvent(GSPEVENT_VBlank0, true);
+
+ u32 backgroundColor = 0x00000000;
+
+// hidScanInput();
+// u32 kDown = hidKeysDown();
+
+// if (kDown & KEY_START) rarch_main_command(RARCH_CMD_QUIT); // break in order to return to hbmenu
+
+ GPUCMD_SetBufferOffset(0);
+ GPU_SetFloatUniform(GPU_VERTEX_SHADER,
+ shaderInstanceGetUniformLocation(shader.vertexShader, "projection"),
+ (u32*)proj_m, 4);
+
+
+
+ GSPGPU_FlushDataCache(NULL, (u8*)texData2, texture_bin_size);
+ GX_SetDisplayTransfer(NULL, (u32*)texData2, tex_size, (u32*)texData, gpu_tex_size,
+ 0x3302); // rgb32=0x0 rgb32=0x0 ??=0x0 linear2swizzeled=0x2
+ gspWaitForPPF();
+
+ renderFrame();
+ GPUCMD_Finalize();
+
+// for (i = 0; i < 16; i++)
+// printf(PRINTFPOS_STR("%i", "%i")"%f", i >> 2, 10 * (i & 0x3), proj_m[i]);
+
+// printf(PRINTFPOS(20, 10)"frames: %i", frames++);
+
+ //draw the frame
+ GPUCMD_FlushAndRun(NULL);
+ gspWaitForP3D();
+
+ //clear the screen
+ GX_SetDisplayTransfer(NULL, (u32*)gpuOut, 0x019001E0,
+ (u32*)gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), 0x019001E0, 0x01001000);
+ gspWaitForPPF();
+
+ //clear the screen
+ GX_SetMemoryFill(NULL, (u32*)gpuOut, backgroundColor, (u32*)&gpuOut[0x2EE00],
+ 0x201, (u32*)gpuDOut, 0x00000000, (u32*)&gpuDOut[0x2EE00], 0x201);
+ gspWaitForPSC0();
+ gfxSwapBuffersGpu();
+
+ gspWaitForEvent(GSPEVENT_VBlank0, true);
+
+
+ // gfxFlushBuffers();
+ // gfxSwapBuffers();
+
+ return true;
+}
+
+static void ctr_set_nonblock_state(void* data, bool toggle)
+{
+ ctr_video_t* ctr = (ctr_video_t*)data;
+
+ if (ctr)
+ ctr->vsync = !toggle;
+}
+
+static bool ctr_alive(void* data)
+{
+ (void)data;
+ return true;
+}
+
+static bool ctr_focus(void* data)
+{
+ (void)data;
+ return true;
+}
+
+static bool ctr_suppress_screensaver(void* data, bool enable)
+{
+ (void)data;
+ (void)enable;
+ return false;
+}
+
+static bool ctr_has_windowed(void* data)
+{
+ (void)data;
+ return false;
+}
+
+static void ctr_free(void* data)
+{
+ ctr_video_t* ctr = (ctr_video_t*)data;
+
+ if (!ctr)
+ return;
+
+ printf("%s@%s:%d.\n",__FUNCTION__, __FILE__, __LINE__);fflush(stdout);
+ shaderProgramFree(&shader);
+ DVLB_Free(dvlb);
+ linearFree(gpuCmd);
+ linearFree(gpuCmdRight);
+ linearFree(texData);
+ linearFree(texData2);
+ linearFree(vbo_buffer);
+ free(texture_bin);
+// gfxExit();
+
+ free(ctr);
+}
+
+static void ctr_set_texture_frame(void* data, const void* frame, bool rgb32,
+ unsigned width, unsigned height, float alpha)
+{
+ ctr_video_t* ctr = (ctr_video_t*)data;
+
+ int i;
+ uint8_t* dst = (uint8_t*)texData2;
+ const uint8_t* src = frame;
+ for (i = 0; i < height; i++)
+ {
+ memcpy(dst, src, width*2);
+ dst += tex_w*2;
+ src += width*2;
+ }
+
+
+
+}
+
+static void ctr_set_texture_enable(void* data, bool state, bool full_screen)
+{
+ (void) full_screen;
+
+ ctr_video_t* ctr = (ctr_video_t*)data;
+
+ if (ctr)
+ ctr->menu_texture_enable = state;
+}
+
+
+static void ctr_set_rotation(void* data, unsigned rotation)
+{
+ ctr_video_t* ctr = (ctr_video_t*)data;
+
+ if (!ctr)
+ return;
+
+ ctr->rotation = rotation;
+}
+static void ctr_set_filtering(void* data, unsigned index, bool smooth)
+{
+ ctr_video_t* ctr = (ctr_video_t*)data;
+
+ if (ctr)
+ ctr->smooth = smooth;
+}
+
+static void ctr_set_aspect_ratio(void* data, unsigned aspectratio_index)
+{
+ (void)data;
+ (void)aspectratio_index;
+ return;
+}
+
+static void ctr_apply_state_changes(void* data)
+{
+ (void)data;
+ return;
+}
+
+static void ctr_viewport_info(void* data, struct video_viewport* vp)
+{
+ (void)data;
+ return;
+}
+
+static const video_poke_interface_t ctr_poke_interface =
+{
+ NULL,
+ ctr_set_filtering,
+ NULL, /* get_video_output_size */
+ NULL, /* get_video_output_prev */
+ NULL, /* get_video_output_next */
+#ifdef HAVE_FBO
+ NULL,
+#endif
+ NULL,
+ ctr_set_aspect_ratio,
+ ctr_apply_state_changes,
+#ifdef HAVE_MENU
+ ctr_set_texture_frame,
+ ctr_set_texture_enable,
+#endif
+ NULL,
+ NULL,
+ NULL
+};
+
+static void ctr_get_poke_interface(void* data,
+ const video_poke_interface_t** iface)
+{
+ (void)data;
+ *iface = &ctr_poke_interface;
+}
+
+static bool ctr_read_viewport(void* data, uint8_t* buffer)
+{
+ (void)data;
+ (void)buffer;
+ return false;
+}
+
+static bool ctr_set_shader(void* data,
+ enum rarch_shader_type type, const char* path)
+{
+ (void)data;
+ (void)type;
+ (void)path;
+
+ return false;
+}
+
+video_driver_t video_ctr =
+{
+ ctr_init,
+ ctr_frame,
+ ctr_set_nonblock_state,
+ ctr_alive,
+ ctr_focus,
+ ctr_suppress_screensaver,
+ ctr_has_windowed,
+ ctr_set_shader,
+ ctr_free,
+ "ctr",
+
+ ctr_set_rotation,
+ ctr_viewport_info,
+ ctr_read_viewport,
+ NULL, /* read_frame_raw */
+#ifdef HAVE_OVERLAY
+ NULL,
+#endif
+ ctr_get_poke_interface
+};
diff --git a/gfx/video_driver.c b/gfx/video_driver.c
index 87a995a767..33cb25aa8d 100644
--- a/gfx/video_driver.c
+++ b/gfx/video_driver.c
@@ -40,6 +40,9 @@ static const video_driver_t *video_drivers[] = {
#ifdef PSP
&video_psp1,
#endif
+#ifdef _3DS
+ &video_ctr,
+#endif
#ifdef HAVE_SDL
&video_sdl,
#endif
diff --git a/gfx/video_driver.h b/gfx/video_driver.h
index 5298fdce2e..374c156f88 100644
--- a/gfx/video_driver.h
+++ b/gfx/video_driver.h
@@ -184,6 +184,7 @@ typedef struct video_driver
extern video_driver_t video_gl;
extern video_driver_t video_psp1;
extern video_driver_t video_vita;
+extern video_driver_t video_ctr;
extern video_driver_t video_d3d;
extern video_driver_t video_gx;
extern video_driver_t video_xenon360;
diff --git a/griffin/griffin.c b/griffin/griffin.c
index 5e588bd964..af39239486 100644
--- a/griffin/griffin.c
+++ b/griffin/griffin.c
@@ -235,10 +235,11 @@ VIDEO DRIVER
#include "../gfx/drivers/gx_gfx.c"
#elif defined(PSP)
#include "../gfx/drivers/psp1_gfx.c"
+#elif defined(_3DS)
+#include "../gfx/drivers/ctr_gfx.c"
#elif defined(XENON)
#include "../gfx/drivers/xenon360_gfx.c"
#endif
-
#include "../gfx/drivers/nullgfx.c"
/*============================================================
@@ -308,6 +309,10 @@ INPUT
#include "../input/drivers/psp_input.c"
#include "../input/drivers_joypad/psp_input_joypad.c"
#include "../input/autoconf/builtin_psp.c"
+#elif defined(_3DS)
+#include "../input/drivers/ctr_input.c"
+#include "../input/drivers_joypad/ctr_input_joypad.c"
+#include "../input/autoconf/builtin_ctr.c"
#elif defined(GEKKO)
#ifdef HAVE_LIBSICKSAXIS
#include "../input/drivers_joypad/gx_input_sicksaxis.c"
@@ -359,7 +364,7 @@ INPUT
#include "../input/drivers_joypad/winxinput_joypad.c"
#endif
-#if defined(__linux__) && !defined(ANDROID)
+#if defined(__linux__) && !defined(ANDROID)
#include "../input/drivers/linuxraw_input.c"
#include "../input/drivers_joypad/linuxraw_joypad.c"
#endif
@@ -463,6 +468,8 @@ AUDIO
#include "../audio/drivers/rwebaudio.c"
#elif defined(PSP)
#include "../audio/drivers/psp1_audio.c"
+#elif defined(_3DS)
+#include "../audio/drivers/ctr_audio.c"
#endif
#ifdef HAVE_XAUDIO
@@ -604,6 +611,8 @@ FRONTEND
#include "../frontend/drivers/platform_xdk.c"
#elif defined(PSP)
#include "../frontend/drivers/platform_psp.c"
+#elif defined(_3DS)
+#include "../frontend/drivers/platform_ctr.c"
#elif defined(__QNX__)
#include "../frontend/drivers/platform_qnx.c"
#elif defined(OSX) || defined(IOS)
diff --git a/input/autoconf/builtin_ctr.c b/input/autoconf/builtin_ctr.c
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/input/autoconf/builtin_ctr.c
@@ -0,0 +1 @@
+
diff --git a/input/drivers/ctr_input.c b/input/drivers/ctr_input.c
new file mode 100644
index 0000000000..a20b437d64
--- /dev/null
+++ b/input/drivers/ctr_input.c
@@ -0,0 +1,101 @@
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
+ * Copyright (C) 2011-2015 - Daniel De Matteis
+ *
+ * RetroArch is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with RetroArch.
+ * If not, see .
+ */
+
+#include "../../general.h"
+#include "../../driver.h"
+
+static void *ctrinput_input_init(void)
+{
+ return (void*)-1;
+}
+
+static void ctrinput_input_poll(void *data)
+{
+ (void)data;
+}
+
+static int16_t ctrinput_input_state(void *data,
+ const struct retro_keybind **retro_keybinds, unsigned port,
+ unsigned device, unsigned idx, unsigned id)
+{
+ (void)data;
+ (void)retro_keybinds;
+ (void)port;
+ (void)device;
+ (void)idx;
+ (void)id;
+
+ return 0;
+}
+
+static bool ctrinput_input_key_pressed(void *data, int key)
+{
+ (void)data;
+ (void)key;
+
+ return false;
+}
+
+static void ctrinput_input_free_input(void *data)
+{
+ (void)data;
+}
+
+static uint64_t ctrinput_get_capabilities(void *data)
+{
+ uint64_t caps = 0;
+
+ caps |= (1 << RETRO_DEVICE_JOYPAD);
+
+ return caps;
+}
+
+static bool ctrinput_set_sensor_state(void *data,
+ unsigned port, enum retro_sensor_action action, unsigned event_rate)
+{
+ return false;
+}
+
+static void ctrinput_grab_mouse(void *data, bool state)
+{
+ (void)data;
+ (void)state;
+}
+
+static bool ctrinput_set_rumble(void *data, unsigned port,
+ enum retro_rumble_effect effect, uint16_t strength)
+{
+ (void)data;
+ (void)port;
+ (void)effect;
+ (void)strength;
+
+ return false;
+}
+
+input_driver_t input_ctr = {
+ ctrinput_input_init,
+ ctrinput_input_poll,
+ ctrinput_input_state,
+ ctrinput_input_key_pressed,
+ ctrinput_input_free_input,
+ ctrinput_set_sensor_state,
+ NULL,
+ ctrinput_get_capabilities,
+ "ctr",
+ ctrinput_grab_mouse,
+ ctrinput_set_rumble,
+};
diff --git a/input/drivers_joypad/ctr_input_joypad.c b/input/drivers_joypad/ctr_input_joypad.c
new file mode 100644
index 0000000000..1f67d99374
--- /dev/null
+++ b/input/drivers_joypad/ctr_input_joypad.c
@@ -0,0 +1,73 @@
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
+ * Copyright (C) 2011-2015 - Daniel De Matteis
+ * Copyright (C) 2013-2014 - CatalystG
+ *
+ * RetroArch is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with RetroArch.
+ * If not, see .
+ */
+
+#include
+#include
+#include
+#include "../input_joypad_driver.h"
+
+static const char *ctr_joypad_name(unsigned pad)
+{
+ return "ctr";
+}
+
+static bool ctr_joypad_init(void)
+{
+ return true;
+}
+
+static bool ctr_joypad_button(unsigned port_num, uint16_t joykey)
+{
+ return false;
+}
+
+static uint64_t ctr_joypad_get_buttons(unsigned port_num)
+{
+ return 0;
+}
+
+static int16_t ctr_joypad_axis(unsigned port_num, uint32_t joyaxis)
+{
+ return 0;
+}
+
+static void ctr_joypad_poll(void)
+{
+}
+
+static bool ctr_joypad_query_pad(unsigned pad)
+{
+ return true;
+}
+
+
+static void ctr_joypad_destroy(void)
+{
+}
+
+rarch_joypad_driver_t ctr_joypad = {
+ ctr_joypad_init,
+ ctr_joypad_query_pad,
+ ctr_joypad_destroy,
+ ctr_joypad_button,
+ ctr_joypad_get_buttons,
+ ctr_joypad_axis,
+ ctr_joypad_poll,
+ NULL,
+ ctr_joypad_name,
+ "ctr",
+};
diff --git a/input/input_driver.c b/input/input_driver.c
index 4a6134b720..f4cb50d15d 100644
--- a/input/input_driver.c
+++ b/input/input_driver.c
@@ -28,6 +28,9 @@ static const input_driver_t *input_drivers[] = {
#if defined(SN_TARGET_PSP2) || defined(PSP)
&input_psp,
#endif
+#if defined(_3DS)
+ &input_ctr,
+#endif
#if defined(HAVE_SDL) || defined(HAVE_SDL2)
&input_sdl,
#endif
diff --git a/input/input_driver.h b/input/input_driver.h
index 535def4b50..033ceec141 100644
--- a/input/input_driver.h
+++ b/input/input_driver.h
@@ -84,6 +84,7 @@ extern input_driver_t input_x;
extern input_driver_t input_wayland;
extern input_driver_t input_ps3;
extern input_driver_t input_psp;
+extern input_driver_t input_ctr;
extern input_driver_t input_xenon360;
extern input_driver_t input_gx;
extern input_driver_t input_xinput;
diff --git a/input/input_joypad_driver.c b/input/input_joypad_driver.c
index eb012703e4..03029fb0e2 100644
--- a/input/input_joypad_driver.c
+++ b/input/input_joypad_driver.c
@@ -38,6 +38,9 @@ static rarch_joypad_driver_t *joypad_drivers[] = {
#ifdef PSP
&psp_joypad,
#endif
+#ifdef _3DS
+ &ctr_joypad,
+#endif
#ifdef HAVE_DINPUT
&dinput_joypad,
#endif
diff --git a/input/input_joypad_driver.h b/input/input_joypad_driver.h
index b46e48386c..fb99d6f64b 100644
--- a/input/input_joypad_driver.h
+++ b/input/input_joypad_driver.h
@@ -52,6 +52,7 @@ extern rarch_joypad_driver_t winxinput_joypad;
extern rarch_joypad_driver_t sdl_joypad;
extern rarch_joypad_driver_t ps3_joypad;
extern rarch_joypad_driver_t psp_joypad;
+extern rarch_joypad_driver_t ctr_joypad;
extern rarch_joypad_driver_t xdk_joypad;
extern rarch_joypad_driver_t gx_joypad;
extern rarch_joypad_driver_t apple_hid_joypad;
diff --git a/libretro-common/include/retro_miscellaneous.h b/libretro-common/include/retro_miscellaneous.h
index 61f835dd40..5d0337a9e8 100644
--- a/libretro-common/include/retro_miscellaneous.h
+++ b/libretro-common/include/retro_miscellaneous.h
@@ -31,6 +31,8 @@
#include
#elif defined(PSP)
#include
+#elif defined(_3DS)
+#include <3ds.h>
#else
#include
#endif
@@ -87,6 +89,8 @@ static INLINE void rarch_sleep(unsigned msec)
sys_timer_usleep(1000 * msec);
#elif defined(PSP)
sceKernelDelayThread(1000 * msec);
+#elif defined(_3DS)
+ svcSleepThread(1000000 * (s64)msec);
#elif defined(_WIN32)
Sleep(msec);
#elif defined(XENON)
diff --git a/libretro-common/include/rthreads/rthreads.h b/libretro-common/include/rthreads/rthreads.h
index 57bdffb81d..0a5b9b63b8 100644
--- a/libretro-common/include/rthreads/rthreads.h
+++ b/libretro-common/include/rthreads/rthreads.h
@@ -179,6 +179,8 @@ void scond_signal(scond_t *cond);
#elif defined(PSP)
#include
#include
+#elif defined(_3DS)
+#include <3ds.h>
#elif defined(_WIN32) && !defined(_XBOX)
#include #elif defined(_XBOX)
#include
@@ -198,6 +200,8 @@ static INLINE void retro_sleep(unsigned msec)
sys_timer_usleep(1000 * msec);
#elif defined(PSP)
sceKernelDelayThread(1000 * msec);
+#elif defined(_3DS)
+ svcSleepThread(1000000 * (s64)msec);
#elif defined(_WIN32)
Sleep(msec);
#elif defined(XENON)
diff --git a/menu/menu_entries.c b/menu/menu_entries.c
index 915c93cc06..08ed0dd7b5 100644
--- a/menu/menu_entries.c
+++ b/menu/menu_entries.c
@@ -300,6 +300,9 @@ static void menu_entries_parse_drive_list(file_list_t *list)
"ef0:/", "", MENU_FILE_DIRECTORY, 0);
menu_list_push(list,
"host0:/", "", MENU_FILE_DIRECTORY, 0);
+#elif defined(_3DS)
+ menu_list_push(list,
+ "sdmc:/", "", MENU_FILE_DIRECTORY, 0);
#elif defined(IOS)
menu_list_push(list,
"/var/mobile/Documents/", "", MENU_FILE_DIRECTORY, 0);
diff --git a/performance.c b/performance.c
index 8030dcefb9..7a5deda5cc 100644
--- a/performance.c
+++ b/performance.c
@@ -195,6 +195,8 @@ retro_perf_tick_t rarch_get_perf_counter(void)
time_ticks = __mftb();
#elif defined(PSP)
sceRtcGetCurrentTick(&time_ticks);
+#elif defined(_3DS)
+ time_ticks = osGetTime();
#elif defined(__mips__)
struct timeval tv;
gettimeofday(&tv,NULL);
@@ -254,6 +256,8 @@ retro_time_t rarch_get_time_usec(void)
struct timeval tv;
gettimeofday(&tv,NULL);
return (1000000 * tv.tv_sec + tv.tv_usec);
+#elif defined(_3DS)
+ return osGetTime();
#else
#error "Your platform does not have a timer function implemented in rarch_get_time_usec(). Cannot continue."
#endif
@@ -357,6 +361,8 @@ unsigned rarch_get_cpu_cores(void)
return 1;
#elif defined(PSP)
return 1;
+#elif defined(_3DS)
+ return 1;
#elif defined(_SC_NPROCESSORS_ONLN)
/* Linux, most UNIX-likes. */
long ret = sysconf(_SC_NPROCESSORS_ONLN);