aboutsummaryrefslogtreecommitdiff
path: root/src/melon_fopen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/melon_fopen.cpp')
-rw-r--r--src/melon_fopen.cpp176
1 files changed, 176 insertions, 0 deletions
diff --git a/src/melon_fopen.cpp b/src/melon_fopen.cpp
new file mode 100644
index 0000000..04d3caf
--- /dev/null
+++ b/src/melon_fopen.cpp
@@ -0,0 +1,176 @@
+/*
+ Copyright 2016-2019 StapleButter
+
+ This file is part of melonDS.
+
+ melonDS 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 Foundation, either version 3 of the License, or (at your option)
+ any later version.
+
+ melonDS 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 melonDS. If not, see http://www.gnu.org/licenses/.
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <string>
+#ifdef _WIN32
+#define NTDDI_VERSION 0x06000000 // GROSS FUCKING HACK
+#include <windows.h>
+//#include <knownfolders.h> // FUCK THAT SHIT
+extern "C" const GUID DECLSPEC_SELECTANY FOLDERID_RoamingAppData = {0x3eb685db, 0x65f9, 0x4cf6, {0xa0, 0x3a, 0xe3, 0xef, 0x65, 0x72, 0x9f, 0x3d}};
+#include <shlobj.h>
+#else
+#include <glib.h>
+#endif
+
+extern char* EmuDirectory;
+
+
+#ifdef __WIN32__
+
+
+
+FILE* melon_fopen(const char* path, const char* mode)
+{
+ int len = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0);
+ if (len < 1) return NULL;
+ WCHAR* fatass = new WCHAR[len];
+ int res = MultiByteToWideChar(CP_UTF8, 0, path, -1, fatass, len);
+ if (res != len) { delete[] fatass; return NULL; } // checkme?
+
+ // this will be more than enough
+ WCHAR fatmode[4];
+ fatmode[0] = mode[0];
+ fatmode[1] = mode[1];
+ fatmode[2] = mode[2];
+ fatmode[3] = 0;
+
+ FILE* ret = _wfopen(fatass, fatmode);
+ delete[] fatass;
+ return ret;
+}
+
+FILE* melon_fopen_local(const char* fileName, const char* permissions)
+{
+ // Locations are application directory, and AppData/melonDS on windows
+
+ FILE* f;
+
+ // First check current working directory
+ f = fopen(fileName, permissions);
+ if (f) return f;
+
+ // then emu directory
+ {
+ int dirlen = strlen(EmuDirectory);
+ if (dirlen)
+ {
+ int filelen = strlen(fileName);
+ int len = dirlen + 1 + filelen + 1;
+ char* tmp = new char[len];
+ strncpy(&tmp[0], EmuDirectory, dirlen);
+ tmp[dirlen] = '\\';
+ strncpy(&tmp[dirlen+1], fileName, filelen);
+ tmp[dirlen+1+filelen] = '\0';
+
+ f = melon_fopen(tmp, permissions);
+ delete[] tmp;
+ if (f) return f;
+ }
+ }
+
+ // Now check AppData
+ PWSTR appDataPath = NULL;
+ SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &appDataPath);
+ if (!appDataPath)
+ return NULL;
+
+ // this will be more than enough
+ WCHAR fatperm[4];
+ fatperm[0] = permissions[0];
+ fatperm[1] = permissions[1];
+ fatperm[2] = permissions[2];
+ fatperm[3] = 0;
+
+ int fnlen = MultiByteToWideChar(CP_UTF8, 0, fileName, -1, NULL, 0);
+ if (fnlen < 1) return NULL;
+ WCHAR* wfileName = new WCHAR[fnlen];
+ int res = MultiByteToWideChar(CP_UTF8, 0, fileName, -1, wfileName, fnlen);
+ if (res != fnlen) { delete[] wfileName; return NULL; } // checkme?
+
+ const WCHAR* appdir = L"\\melonDS\\";
+
+ int pos = wcslen(appDataPath);
+ void* ptr = CoTaskMemRealloc(appDataPath, (pos+wcslen(appdir)+fnlen+1)*sizeof(WCHAR));
+ if (!ptr) { delete[] wfileName; return NULL; } // oh well
+ appDataPath = (PWSTR)ptr;
+
+ wcscpy(&appDataPath[pos], appdir); pos += wcslen(appdir);
+ wcscpy(&appDataPath[pos], wfileName);
+
+ f = _wfopen(appDataPath, fatperm);
+ CoTaskMemFree(appDataPath);
+ delete[] wfileName;
+ if (f) return f;
+
+ return NULL;
+
+}
+
+
+
+#else
+
+
+
+FILE* melon_fopen(const char* filename, const char* perm) { return fopen(filename, perm); }
+
+FILE* melon_fopen_local(const char* fileName, const char* permissions)
+{
+ // Locations are application directory, and XDG_CONFIG_HOME/melonds
+
+ FILE* f;
+
+ // First check current working directory
+ f = fopen(fileName, permissions);
+ if (f) return f;
+
+ // then emu directory
+ {
+ int dirlen = strlen(EmuDirectory);
+ if (dirlen)
+ {
+ int filelen = strlen(fileName);
+ int len = dirlen + 1 + filelen + 1;
+ char* tmp = new char[len];
+ strncpy(&tmp[0], EmuDirectory, dirlen);
+ tmp[dirlen] = '/';
+ strncpy(&tmp[dirlen+1], fileName, filelen);
+ tmp[dirlen+1+filelen] = '\0';
+
+ f = fopen(tmp, permissions);
+ delete[] tmp;
+ if (f) return f;
+ }
+ }
+
+ // Now check XDG_CONFIG_HOME
+ // TODO: check for memory leak there
+ std::string path = std::string(g_get_user_config_dir()) + "/melonds/" + fileName;
+ f = fopen(path.c_str(), permissions);
+ if (f) return f;
+
+ return NULL;
+
+}
+
+
+
+#endif