mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-23 14:19:55 -06:00
move config-file seeking code to its own thing.
look also into the same directory as melonDS. make it the preferred place for storing melonDS.ini. rewrite WinMain() wrapper.
This commit is contained in:
176
src/melon_fopen.cpp
Normal file
176
src/melon_fopen.cpp
Normal file
@ -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* GetConfigFile(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
|
Reference in New Issue
Block a user