diff options
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | melonDS.cbp | 1 | ||||
-rw-r--r-- | src/Config.cpp | 106 | ||||
-rw-r--r-- | src/NDS.cpp | 5 | ||||
-rw-r--r-- | src/SPI.cpp | 7 | ||||
-rw-r--r-- | src/libui_sdl/main.cpp | 74 | ||||
-rw-r--r-- | src/melon_fopen.cpp | 176 | ||||
-rw-r--r-- | src/melon_fopen.h | 29 |
8 files changed, 256 insertions, 143 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 132bf5b..718287a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,7 @@ SET(SOURCES src/GPU2D.cpp src/GPU3D.cpp src/GPU3D_Soft.cpp + src/melon_fopen.cpp src/NDS.cpp src/NDSCart.cpp src/RTC.cpp diff --git a/melonDS.cbp b/melonDS.cbp index a93b225..8831c70 100644 --- a/melonDS.cbp +++ b/melonDS.cbp @@ -234,6 +234,7 @@ <Unit filename="src/libui_sdl/libui/windows/winpublic.cpp" /> <Unit filename="src/libui_sdl/libui/windows/winutil.cpp" /> <Unit filename="src/libui_sdl/main.cpp" /> + <Unit filename="src/melon_fopen.cpp" /> <Unit filename="src/melon_fopen.h" /> <Unit filename="src/pcap/bluetooth.h" /> <Unit filename="src/pcap/bpf.h" /> diff --git a/src/Config.cpp b/src/Config.cpp index fea92e9..ac769d5 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -20,21 +20,17 @@ #include <string.h> #include <stdlib.h> #include "Config.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 +#include "melon_fopen.h" +bool LocalFileExists(const char* name); +extern char* EmuDirectory; + namespace Config { +const char* kConfigFile = "melonDS.ini"; + int KeyMapping[12]; int JoyMapping[12]; @@ -114,72 +110,6 @@ ConfigEntry ConfigFile[] = {"", -1, NULL, 0, NULL, 0} }; -FILE* GetConfigFile(const char* fileName, const char* permissions) -{ - // Locations are application directory, and XDG_CONFIG_HOME/melonds or AppData/MelonDS on windows - - FILE* f; - - // First check application directory - f = fopen(fileName, permissions); - if (f) return f; -#ifdef _WIN32 - // Now check AppData - PWSTR appDataPath = NULL; - SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &appDataPath); - if (!appDataPath) - return NULL; - - const WCHAR* appdir = L"\\melonDS\\"; - - 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? - - 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); - - // this will be more than enough - WCHAR fatperm[4]; - fatperm[0] = permissions[0]; - fatperm[1] = permissions[1]; - fatperm[2] = permissions[2]; - fatperm[3] = 0; - - f = _wfopen(appDataPath, fatperm); - CoTaskMemFree(appDataPath); - delete[] wfileName; - if (f) return f; -#else - // 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; -#endif - - return NULL; - -} - -bool HasConfigFile(const char* fileName) -{ - FILE* f = GetConfigFile(fileName, "rb"); - if (f) - { - fclose(f); - return true; - } - else - return false; -} void Load() { @@ -196,7 +126,7 @@ void Load() entry++; } - FILE* f = Config::GetConfigFile("melonDS.ini", "r"); + FILE* f = melon_fopen_local(kConfigFile, "r"); if (!f) return; char linebuf[1024]; @@ -232,8 +162,26 @@ void Load() void Save() { - FILE* f = Config::GetConfigFile("melonDS.ini", "w"); - if (!f) return; + FILE* f; + if (LocalFileExists(kConfigFile)) + { + f = melon_fopen_local(kConfigFile, "w"); + if (!f) return; + } + else + { + int dirlen = strlen(EmuDirectory); + int filelen = strlen(kConfigFile); + char* path = new char[dirlen + 1 + filelen + 1]; + strncpy(&path[0], EmuDirectory, dirlen); + path[dirlen] = '/'; + strncpy(&path[dirlen+1], kConfigFile, filelen); + path[dirlen+1+filelen] = '\0'; + + f = melon_fopen(path, "w"); + delete[] path; + if (!f) return; + } ConfigEntry* entry = &ConfigFile[0]; for (;;) diff --git a/src/NDS.cpp b/src/NDS.cpp index d267cb7..8b5912c 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -30,6 +30,7 @@ #include "RTC.h" #include "Wifi.h" #include "Platform.h" +#include "melon_fopen.h" namespace NDS @@ -386,7 +387,7 @@ void Reset() dbg_CyclesTimer7 = 0; #endif // DEBUG_CHECK_DESYNC - f = Config::GetConfigFile("bios9.bin", "rb"); + f = melon_fopen_local("bios9.bin", "rb"); if (!f) { printf("ARM9 BIOS not found\n"); @@ -403,7 +404,7 @@ void Reset() fclose(f); } - f = Config::GetConfigFile("bios7.bin", "rb"); + f = melon_fopen_local("bios7.bin", "rb"); if (!f) { printf("ARM7 BIOS not found\n"); diff --git a/src/SPI.cpp b/src/SPI.cpp index 3ffb20f..76b5b75 100644 --- a/src/SPI.cpp +++ b/src/SPI.cpp @@ -22,6 +22,7 @@ #include "Config.h" #include "NDS.h" #include "SPI.h" +#include "melon_fopen.h" namespace SPI_Firmware @@ -89,7 +90,7 @@ void Reset() if (Firmware) delete[] Firmware; Firmware = NULL; - FILE* f = Config::GetConfigFile("firmware.bin", "rb"); + FILE* f = melon_fopen_local("firmware.bin", "rb"); if (!f) { printf("firmware.bin not found\n"); @@ -129,7 +130,7 @@ void Reset() // take a backup char* firmbkp = "firmware.bin.bak"; - f = Config::GetConfigFile(firmbkp, "rb"); + f = melon_fopen_local(firmbkp, "rb"); if (f) fclose(f); else { @@ -324,7 +325,7 @@ void Write(u8 val, u32 hold) if (!hold && (CurCmd == 0x02 || CurCmd == 0x0A)) { - FILE* f = Config::GetConfigFile("firmware.bin", "r+b"); + FILE* f = melon_fopen_local("firmware.bin", "r+b"); if (f) { u32 cutoff = 0x7FA00 & FirmwareMask; diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index 6aa6c5d..1a2cc6f 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -52,6 +52,9 @@ const int kScreenLayout[3] = {0, 1, 2}; const int kScreenSizing[4] = {0, 1, 2, 3}; +char* EmuDirectory; + + uiWindow* MainWindow; uiArea* MainDrawArea; @@ -116,7 +119,7 @@ void GetSavestateName(int slot, char* filename, int len); -bool FileExists(char* name) +bool FileExists(const char* name) { FILE* f = melon_fopen(name, "rb"); if (!f) return false; @@ -124,6 +127,14 @@ bool FileExists(char* name) return true; } +bool LocalFileExists(const char* name) +{ + FILE* f = melon_fopen_local(name, "rb"); + if (!f) return false; + fclose(f); + return true; +} + void UpdateWindowTitle(void* data) { @@ -1308,6 +1319,19 @@ int main(int argc, char** argv) printf("melonDS " MELONDS_VERSION "\n"); printf(MELONDS_URL "\n"); + { + int len = strlen(argv[0]); + while (len > 0) + { + if (argv[0][len] == '/') break; + if (argv[0][len] == '\\') break; + len--; + } + EmuDirectory = new char[len]; + strncpy(EmuDirectory, argv[0], len); + EmuDirectory[len] = '\0'; + } + // http://stackoverflow.com/questions/14543333/joystick-wont-work-using-sdl SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); @@ -1335,7 +1359,7 @@ int main(int argc, char** argv) Config::Load(); - if (!Config::HasConfigFile("bios7.bin") || !Config::HasConfigFile("bios9.bin") || !Config::HasConfigFile("firmware.bin")) + if (!LocalFileExists("bios7.bin") || !LocalFileExists("bios9.bin") || !LocalFileExists("firmware.bin")) { uiMsgBoxError( NULL, @@ -1618,6 +1642,7 @@ int main(int argc, char** argv) uiUninit(); SDL_Quit(); + delete[] EmuDirectory; return 0; } @@ -1627,41 +1652,26 @@ int main(int argc, char** argv) int CALLBACK WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int cmdshow) { - char cmdargs[16][256]; - int arg = 1; - int j = 0; - bool inquote = false; - int len = strlen(cmdline); - for (int i = 0; i < len; i++) + int argc = 0; + wchar_t** argv_w = CommandLineToArgvW(GetCommandLineW(), &argc); + char* nullarg = ""; + + char** argv = new char*[argc]; + for (int i = 0; i < argc; i++) { - char c = cmdline[i]; - if (c == '\0') break; - if (c == '"') inquote = !inquote; - if (!inquote && c==' ') - { - if (j > 255) j = 255; - if (arg < 16) cmdargs[arg][j] = '\0'; - arg++; - j = 0; - } - else - { - if (arg < 16 && j < 255) cmdargs[arg][j] = c; - j++; - } + int len = WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1, NULL, 0, NULL, NULL); + if (len < 1) return NULL; + argv[i] = new char[len]; + int res = WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1, argv[i], len, NULL, NULL); + if (res != len) { delete[] argv[i]; argv[i] = nullarg; } } - if (j > 255) j = 255; - if (arg < 16) cmdargs[arg][j] = '\0'; - if (len > 0) arg++; - // FIXME!! - strncpy(cmdargs[0], "melonDS.exe", 256); + int ret = main(argc, argv); - char* cmdargptr[16]; - for (int i = 0; i < 16; i++) - cmdargptr[i] = &cmdargs[i][0]; + for (int i = 0; i < argc; i++) if (argv[i] != nullarg) delete[] argv[i]; + delete[] argv; - return main(arg, cmdargptr); + return ret; } #endif diff --git a/src/melon_fopen.cpp b/src/melon_fopen.cpp new file mode 100644 index 0000000..18f413c --- /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* 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 diff --git a/src/melon_fopen.h b/src/melon_fopen.h index a45ad97..40709e1 100644 --- a/src/melon_fopen.h +++ b/src/melon_fopen.h @@ -19,34 +19,9 @@ #ifndef MELON_FOPEN_H #define MELON_FOPEN_H -#ifdef __WIN32__ -#include <windows.h> +FILE* melon_fopen(const char* filename, const char* perm); +FILE* melon_fopen_local(const char* filename, const char* perm); -static 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; -} - -#else - -#define melon_fopen fopen - -#endif #endif // MELON_FOPEN_H |