Index: src/OFFile.m ================================================================== --- src/OFFile.m +++ src/OFFile.m @@ -46,10 +46,15 @@ #import "OFWriteFailedException.h" #ifdef OF_WINDOWS # include #endif + +#ifdef OF_AMIGAOS +# include +# include +#endif #ifdef OF_WII # include #endif @@ -56,13 +61,14 @@ #ifdef OF_NINTENDO_DS # include # include #endif -#ifdef OF_AMIGAOS -# include -# include +#ifdef OF_NINTENDO_SWITCH +# define id nx_id +# include +# undef id #endif #ifndef O_BINARY # define O_BINARY 0 #endif @@ -164,10 +170,20 @@ } return -1; } #endif + +#ifdef OF_NINTENDO_SWITCH +static bool initialized = false; + +OF_DESTRUCTOR() +{ + if (initialized) + romfsExit(); +} +#endif @implementation OFFile + (void)initialize { if (self != [OFFile class]) @@ -182,10 +198,19 @@ #ifdef OF_NINTENDO_DS if (!nitroFSInit(NULL)) @throw [OFInitializationFailedException exceptionWithClass: self]; #endif + +#ifdef OF_NINTENDO_SWITCH + if (R_SUCCEEDED(romfsInit())) + /* + * Errors are intentionally ignored, as it's possible we just + * have no romfs. + */ + initialized = true; +#endif } + (instancetype)fileWithPath: (OFString *)path mode: (OFString *)mode { return [[[self alloc] initWithPath: path mode: mode] autorelease]; Index: src/OFString+PathAdditions.m ================================================================== --- src/OFString+PathAdditions.m +++ src/OFString+PathAdditions.m @@ -19,10 +19,11 @@ #if defined(OF_WINDOWS) || defined(OF_MSDOS) || defined(OF_MINT) # import "platform/Windows/OFString+PathAdditions.m" #elif defined(OF_AMIGAOS) # import "platform/AmigaOS/OFString+PathAdditions.m" -#elif defined(OF_NINTENDO_3DS) || defined(OF_WII) +#elif defined(OF_NINTENDO_3DS) || defined(OF_WII) || \ + defined(OF_NINTENDO_SWITCH) # import "platform/libfat/OFString+PathAdditions.m" #else # import "platform/POSIX/OFString+PathAdditions.m" #endif Index: src/OFSystemInfo.m ================================================================== --- src/OFSystemInfo.m +++ src/OFSystemInfo.m @@ -38,10 +38,16 @@ #if defined(OF_AMIGAOS4) # include #elif defined(OF_MORPHOS) # include #endif + +#ifdef OF_NINTENDO_SWITCH +# define id nx_id +# import +# undef nx_id +#endif #import "OFSystemInfo.h" #import "OFApplication.h" #import "OFArray.h" #import "OFDictionary.h" @@ -233,10 +239,21 @@ operatingSystemVersion = [[OFString alloc] initWithCString: utsname.release encoding: [OFLocale encoding]]; #endif } + +#ifdef OF_NINTENDO_SWITCH +static OFString *tmpFSPath = nil; + +static void +mountTmpFS(void) +{ + if (R_SUCCEEDED(fsdevMountTemporaryStorage("tmpfs"))) + tmpFSPath = @"tmpfs:/"; +} +#endif #if defined(OF_X86_64) || defined(OF_X86) static OF_INLINE struct X86Regs OF_CONST_FUNC x86CPUID(uint32_t eax, uint32_t ecx) { @@ -566,10 +583,15 @@ return @"T:"; # elif defined(OF_MSDOS) return [[OFApplication environment] objectForKey: @"TEMP"]; # elif defined(OF_MINT) return @"u:\\tmp"; +# elif defined(OF_NINTENDO_SWITCH) + static OFOnceControl onceControl = OFOnceControlInitValue; + OFOnce(&onceControl, mountTmpFS); + + return tmpFSPath; # else OFString *path = [[OFApplication environment] objectForKey: @"XDG_RUNTIME_DIR"]; if (path != nil) Index: tests/Makefile ================================================================== --- tests/Makefile +++ tests/Makefile @@ -200,20 +200,28 @@ 3dsxtool $< $@ ${PROG_NOINST}.arm9: ${PROG_NOINST} arm-none-eabi-objcopy -O binary $< $@ -${PROG_NOINST}.nds: ${PROG_NOINST}.arm9 +${PROG_NOINST}.nds: ${PROG_NOINST}.arm9 testfile.bin testfile.txt testfile.ini +${PROG_NOINST}.nds: serialization.xml rm -fr nds-data mkdir -p nds-data cp testfile.bin testfile.txt testfile.ini serialization.xml nds-data - ndstool -c $@ -9 $< -d nds-data + ndstool -c $@ -9 ${PROG_NOINST} -d nds-data rm -fr nds-data -${PROG_NOINST}.nro: ${PROG_NOINST} - elf2nro $< $@ +${PROG_NOINST}.nro: ${PROG_NOINST} testfile.bin testfile.txt testfile.ini +${PROG_NOINST}.nro: serialization.xml + rm -fr romfs + mkdir -p romfs + cp testfile.bin testfile.txt testfile.ini serialization.xml romfs + nacptool --create "ObjFW tests" "Jonathan Schleifer" \ + "${PACKAGE_VERSION}" tests.nacp + elf2nro ${PROG_NOINST} $@ --nacp=tests.nacp --romfsdir=romfs + rm -fr romfs tests.nacp 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/OFStringTests.m ================================================================== --- tests/OFStringTests.m +++ tests/OFStringTests.m @@ -562,11 +562,12 @@ !C(@"foo").absolutePath && !C(@"b:foo").absolutePath) # elif defined(OF_AMIGAOS) TEST(@"-[isAbsolutePath]", C(@"dh0:foo").absolutePath && C(@"dh0:a/b").absolutePath && !C(@"foo/bar").absolutePath && !C(@"foo").absolutePath) -# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) +# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) || \ + defined(OF_NINTENDO_SWITCH) TEST(@"-[isAbsolutePath]", C(@"sdmc:/foo").absolutePath && !C(@"sdmc:foo").absolutePath && !C(@"foo/bar").absolutePath && !C(@"foo").absolutePath) # else TEST(@"-[isAbsolutePath]", @@ -728,11 +729,12 @@ [[stringClass pathWithComponents: [OFArray arrayWithObjects: @"foo/", @"bar", @"", @"baz", @"/", nil]] isEqual: @"foo//bar/baz//"] && [[stringClass pathWithComponents: [OFArray arrayWithObjects: @"foo", nil]] isEqual: @"foo"]) -# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) +# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) || \ + defined(OF_NINTENDO_SWITCH) TEST(@"+[pathWithComponents:]", [[stringClass pathWithComponents: [OFArray arrayWithObjects: @"foo", @"bar", @"baz", nil]] isEqual: @"foo/bar/baz"] && [[stringClass pathWithComponents: [OFArray arrayWithObjects: @"sdmc:", @"foo", @"bar", @"baz", nil]] @@ -852,11 +854,12 @@ /* foo// */ (array = C(@"foo//").pathComponents) && array.count == 2 && [[array objectAtIndex: 0] isEqual: @"foo"] && [[array objectAtIndex: 1] isEqual: @"/"] && C(@"").pathComponents.count == 0) -# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) +# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) || \ + defined(OF_NINTENDO_SWITCH) TEST(@"-[pathComponents]", /* sdmc:/tmp */ (array = C(@"sdmc:/tmp").pathComponents) && array.count == 2 && [[array objectAtIndex: 0] isEqual: @"sdmc:"] && [[array objectAtIndex: 1] isEqual: @"tmp"] && @@ -933,11 +936,12 @@ [C(@"dh0:/").lastPathComponent isEqual: @"/"] && [C(@"dh0:").lastPathComponent isEqual: @"dh0:"] && [C(@"foo").lastPathComponent isEqual: @"foo"] && [C(@"foo/bar").lastPathComponent isEqual: @"bar"] && [C(@"foo/bar/baz/").lastPathComponent isEqual: @"baz"]) -# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) +# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) || \ + defined(OF_NINTENDO_SWITCH) TEST(@"-[lastPathComponent]", [C(@"sdmc:/tmp").lastPathComponent isEqual: @"tmp"] && [C(@"sdmc:/tmp/").lastPathComponent isEqual: @"tmp"] && [C(@"sdmc:/").lastPathComponent isEqual: @"sdmc:/"] && [C(@"sdmc:").lastPathComponent isEqual: @"sdmc:"] && @@ -999,11 +1003,12 @@ [C(@"dh0:/").stringByDeletingLastPathComponent isEqual: @"dh0:"] && [C(@"dh0:tmp/foo/").stringByDeletingLastPathComponent isEqual: @"dh0:tmp"] && [C(@"foo/bar").stringByDeletingLastPathComponent isEqual: @"foo"] && [C(@"foo").stringByDeletingLastPathComponent isEqual: @""]) -# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) +# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) || \ + defined(OF_NINTENDO_SWITCH) TEST(@"-[stringByDeletingLastPathComponent]", [C(@"/tmp/").stringByDeletingLastPathComponent isEqual: @""] && [C(@"sdmc:/tmp/foo/").stringByDeletingLastPathComponent isEqual: @"sdmc:/tmp"] && [C(@"sdmc:/").stringByDeletingLastPathComponent @@ -1046,11 +1051,12 @@ [C(@"foo.bar/").stringByDeletingPathExtension isEqual: @"foo"] && [C(@".foo").stringByDeletingPathExtension isEqual: @".foo"] && [C(@".foo\\bar").stringByDeletingPathExtension isEqual: @".foo\\bar"] && [C(@".foo.bar").stringByDeletingPathExtension isEqual: @".foo"]) -# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) +# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) || \ + defined(OF_NINTENDO_SWITCH) TEST(@"-[stringByDeletingPathExtension]", [C(@"foo.bar").stringByDeletingPathExtension isEqual: @"foo"] && [C(@"foo..bar").stringByDeletingPathExtension isEqual: @"foo."] && [C(@"sdmc:/foo./bar").stringByDeletingPathExtension isEqual: @"sdmc:/foo./bar"] && Index: tests/TestsAppDelegate.m ================================================================== --- tests/TestsAppDelegate.m +++ tests/TestsAppDelegate.m @@ -158,10 +158,14 @@ #ifdef OF_NINTENDO_SWITCH consoleInit(NULL); padConfigureInput(1, HidNpadStyleSet_NpadStandard); updateConsole(true); + +# ifdef OF_HAVE_FILES + [[OFFileManager defaultManager] changeCurrentDirectoryPath: @"romfs:/"]; +# endif #endif #if defined(OF_WII) || defined(OF_PSP) || defined(OF_NINTENDO_DS) || \ defined(OF_NINTENDO_3DS) || defined(OF_NINTENDO_SWITCH) @try {