Index: .fossil-settings/clean-glob ================================================================== --- .fossil-settings/clean-glob +++ .fossil-settings/clean-glob @@ -42,10 +42,11 @@ tests/terminal/terminal_tests tests/tests tests/tests.3dsx tests/tests.arm9 tests/tests.nds +tests/tests.nro utils/objfw-config utils/ofarc/ofarc utils/ofdns/ofdns utils/ofhash/ofhash utils/ofhttp/ofhttp Index: .fossil-settings/ignore-glob ================================================================== --- .fossil-settings/ignore-glob +++ .fossil-settings/ignore-glob @@ -47,10 +47,11 @@ tests/terminal/terminal_tests tests/tests tests/tests.3dsx tests/tests.arm9 tests/tests.nds +tests/tests.nro utils/objfw-config utils/ofarc/ofarc utils/ofdns/ofdns utils/ofhash/ofhash utils/ofhttp/ofhttp Index: .gitignore ================================================================== --- .gitignore +++ .gitignore @@ -47,10 +47,11 @@ tests/terminal/terminal_tests tests/tests tests/tests.3dsx tests/tests.arm9 tests/tests.nds +tests/tests.nro utils/objfw-config utils/ofarc/ofarc utils/ofdns/ofdns utils/ofhash/ofhash utils/ofhttp/ofhttp Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -242,10 +242,33 @@ AC_DEFINE(OF_NINTENDO_3DS, 1, [Whether we are compiling for Nintendo 3DS]) OBJFW_CPPFLAGS="$OBJFW_CPPFLAGS -DARM11 -I\$DEVKITPRO/libctru/include" AC_SUBST(MAP_LDFLAGS, ['-Wl,-Map,$@.map']) ]) + +AC_ARG_WITH(nintendo-switch, + AS_HELP_STRING([--with-nintendo-switch], [build for Nintendo Switch])) +AS_IF([test x"$with_nintendo_switch" = x"yes"], [ + AS_IF([test x"$DEVKITPRO" = x""], [ + AC_MSG_ERROR([DEVKITPRO is not set! Please set DEVKITPRO.]) + ]) + + flags="-march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE" + OBJCFLAGS="$OBJCFLAGS $flags" + OBJFW_OBJCFLAGS="$OBJFW_OBJCFLAGS $flags" + CPPFLAGS="$CPPFLAGS -D__SWITCH__ -I$DEVKITPRO/libnx/include" + ASFLAGS="$ASFLAGS $flags" + LDFLAGS="$LDFLAGS -specs=$DEVKITPRO/libnx/switch.specs $flags" + LIBS="$LIBS -L$DEVKITPRO/libnx/lib -lnx" + enable_shared="no" + enable_threads="no" # TODO + enable_sockets="no" # TODO + check_pedantic="no" + + AC_DEFINE(OF_NINTENDO_SWITCH, 1, + [Whether we are compiling for Nintendo Switch]) +]) CPP="$OBJCPP" CPPFLAGS="$CPPFLAGS $OBJCPPFLAGS -DOF_COMPILING_OBJFW" flags="-fexceptions -fobjc-exceptions -funwind-tables" flags="$flags -fconstant-string-class=OFConstantString" Index: src/objfw-defs.h.in ================================================================== --- src/objfw-defs.h.in +++ src/objfw-defs.h.in @@ -41,9 +41,10 @@ #undef OF_HAVE_UNIX_SOCKETS #undef OF_HAVE__THREAD_LOCAL #undef OF_HAVE___THREAD #undef OF_NINTENDO_3DS #undef OF_NINTENDO_DS +#undef OF_NINTENDO_SWITCH #undef OF_NO_SHARED #undef OF_OBJFW_RUNTIME #undef OF_UNIVERSAL #undef OF_WII Index: tests/Makefile ================================================================== --- tests/Makefile +++ tests/Makefile @@ -5,11 +5,12 @@ terminal CLEAN = EBOOT.PBP \ boot.dol \ ${PROG_NOINST}.arm9 \ - ${PROG_NOINST}.nds + ${PROG_NOINST}.nds \ + ${PROG_NOINST}.nro DISTCLEAN = Info.plist PROG_NOINST = tests${PROG_SUFFIX} STATIC_LIB_NOINST = ${TESTS_STATIC_LIB} SRCS = ForwardingTests.m \ @@ -192,10 +193,13 @@ boot.dol: ${PROG_NOINST} elf2dol ${PROG_NOINST} $@ ${PROG_NOINST}: ${LIBOBJFW_DEP} ${LIBOBJFWRT_DEP} + +${PROG_NOINST}.3dsx: ${PROG_NOINST} + 3dsxtool $< $@ ${PROG_NOINST}.arm9: ${PROG_NOINST} arm-none-eabi-objcopy -O binary $< $@ ${PROG_NOINST}.nds: ${PROG_NOINST}.arm9 @@ -203,13 +207,13 @@ mkdir -p nds-data cp testfile.bin testfile.txt testfile.ini serialization.xml nds-data ndstool -c $@ -9 $< -d nds-data rm -fr nds-data -${PROG_NOINST}.3dsx: ${PROG_NOINST} - 3dsxtool $< $@ +${PROG_NOINST}.nro: ${PROG_NOINST} + elf2nro $< $@ CPPFLAGS += -I../src -I../src/exceptions -I../src/runtime -I.. -DSTDOUT OBJCFLAGS_RuntimeARCTests.m = -fobjc-arc -fobjc-arc-exceptions LIBS := ${TESTS_LIBS} ${LIBS} LDFLAGS += ${MAP_LDFLAGS} LD = ${OBJC} Index: tests/TestsAppDelegate.m ================================================================== --- tests/TestsAppDelegate.m +++ tests/TestsAppDelegate.m @@ -48,10 +48,28 @@ /* Newer versions of libctru started using id as a parameter name. */ # define id id_3ds # include <3ds.h> # undef id #endif + +#ifdef OF_NINTENDO_SWITCH +# define id nx_id +# include +# undef id + +static OFDate *lastConsoleUpdate; + +static void +updateConsole(bool force) +{ + if (force || lastConsoleUpdate.timeIntervalSinceNow <= -1.0 / 60) { + consoleUpdate(NULL); + [lastConsoleUpdate release]; + lastConsoleUpdate = [[OFDate alloc] init]; + } +} +#endif extern unsigned long OFHashSeed; #ifdef OF_PSP static int @@ -135,13 +153,19 @@ gfxInitDefault(); atexit(gfxExit); consoleInit(GFX_TOP, NULL); #endif + +#ifdef OF_NINTENDO_SWITCH + consoleInit(NULL); + padConfigureInput(1, HidNpadStyleSet_NpadStandard); + updateConsole(true); +#endif #if defined(OF_WII) || defined(OF_PSP) || defined(OF_NINTENDO_DS) || \ - defined(OF_NINTENDO_3DS) + defined(OF_NINTENDO_3DS) || defined(OF_NINTENDO_SWITCH) @try { return OFApplicationMain(&argc, &argv, [[TestsAppDelegate alloc] init]); } @catch (id e) { OFString *string = [OFString stringWithFormat: @@ -188,10 +212,16 @@ if (hidKeysDown() & KEY_START) [OFApplication terminateWithStatus: 1]; gspWaitForVBlank(); } +# elif defined(OF_NINTENDO_SWITCH) + while (appletMainLoop()) + updateConsole(true); + + consoleExit(NULL); + abort(); # else abort(); # endif } #else @@ -205,10 +235,14 @@ if (OFStdOut.hasTerminal) { [OFStdOut setForegroundColor: [OFColor yellow]]; [OFStdOut writeFormat: @"[%@] %@: testing...", module, test]; } else [OFStdOut writeFormat: @"[%@] %@: ", module, test]; + +#ifdef OF_NINTENDO_SWITCH + updateConsole(false); +#endif } - (void)outputSuccess: (OFString *)test inModule: (OFString *)module { if (OFStdOut.hasTerminal) { @@ -215,79 +249,99 @@ [OFStdOut setForegroundColor: [OFColor lime]]; [OFStdOut eraseLine]; [OFStdOut writeFormat: @"\r[%@] %@: ok\n", module, test]; } else [OFStdOut writeLine: @"ok"]; + +#ifdef OF_NINTENDO_SWITCH + updateConsole(false); +#endif } - (void)outputFailure: (OFString *)test inModule: (OFString *)module { if (OFStdOut.hasTerminal) { [OFStdOut setForegroundColor: [OFColor red]]; [OFStdOut eraseLine]; [OFStdOut writeFormat: @"\r[%@] %@: failed\n", module, test]; - -#ifdef OF_WII - [OFStdOut reset]; - [OFStdOut writeLine: @"Press A to continue!"]; - - for (;;) { - WPAD_ScanPads(); - - if (WPAD_ButtonsDown(0) & WPAD_BUTTON_A) - return; - - VIDEO_WaitVSync(); - } -#endif -#ifdef OF_PSP - [OFStdOut reset]; - [OFStdOut writeLine: @"Press X to continue!"]; - - for (;;) { - SceCtrlData pad; - - sceCtrlReadBufferPositive(&pad, 1); - if (pad.Buttons & PSP_CTRL_CROSS) { - for (;;) { - sceCtrlReadBufferPositive(&pad, 1); - if (!(pad.Buttons & PSP_CTRL_CROSS)) - return; - } - } - } -#endif -#ifdef OF_NINTENDO_DS - [OFStdOut reset]; - [OFStdOut writeString: @"Press A to continue!"]; - - for (;;) { - swiWaitForVBlank(); - scanKeys(); - if (keysDown() & KEY_A) - break; - } -#endif -#ifdef OF_NINTENDO_3DS - [OFStdOut reset]; - [OFStdOut writeString: @"Press A to continue!"]; - - for (;;) { - hidScanInput(); - - if (hidKeysDown() & KEY_A) - break; - - gspWaitForVBlank(); - } -#endif - + } else + [OFStdOut writeLine: @"failed"]; + +#ifdef OF_WII + [OFStdOut reset]; + [OFStdOut writeLine: @"Press A to continue!"]; + + for (;;) { + WPAD_ScanPads(); + + if (WPAD_ButtonsDown(0) & WPAD_BUTTON_A) + return; + + VIDEO_WaitVSync(); + } +#endif +#ifdef OF_PSP + [OFStdOut reset]; + [OFStdOut writeLine: @"Press X to continue!"]; + + for (;;) { + SceCtrlData pad; + + sceCtrlReadBufferPositive(&pad, 1); + if (pad.Buttons & PSP_CTRL_CROSS) { + for (;;) { + sceCtrlReadBufferPositive(&pad, 1); + if (!(pad.Buttons & PSP_CTRL_CROSS)) + return; + } + } + } +#endif +#ifdef OF_NINTENDO_DS + [OFStdOut reset]; + [OFStdOut writeString: @"Press A to continue!"]; + + for (;;) { + swiWaitForVBlank(); + scanKeys(); + if (keysDown() & KEY_A) + break; + } +#endif +#ifdef OF_NINTENDO_3DS + [OFStdOut reset]; + [OFStdOut writeString: @"Press A to continue!"]; + + for (;;) { + hidScanInput(); + + if (hidKeysDown() & KEY_A) + break; + + gspWaitForVBlank(); + } +#endif +#ifdef OF_NINTENDO_SWITCH + [OFStdOut reset]; + [OFStdOut writeString: @"Press A to continue!"]; + + while (appletMainLoop()) { + PadState pad; + + padUpdate(&pad); + updateConsole(true); + + if (padGetButtonsDown(&pad) & HidNpadButton_A) + break; + } +#endif + + if (OFStdOut.hasTerminal) { [OFStdOut writeString: @"\r"]; [OFStdOut reset]; [OFStdOut eraseLine]; - } else - [OFStdOut writeLine: @"failed"]; + } } - (void)applicationDidFinishLaunching { #if defined(OF_IOS) && defined(OF_HAVE_FILES) @@ -432,10 +486,17 @@ if (hidKeysDown() & KEY_START) [OFApplication terminateWithStatus: _fails]; gspWaitForVBlank(); } +#elif defined(OF_NINTENDO_SWITCH) + while (appletMainLoop()) + updateConsole(true); + + consoleExit(NULL); + + [OFApplication terminateWithStatus: _fails]; #else [OFApplication terminateWithStatus: _fails]; #endif } @end