aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--melonDS.cbp1
-rw-r--r--src/Config.cpp106
-rw-r--r--src/NDS.cpp5
-rw-r--r--src/SPI.cpp7
-rw-r--r--src/libui_sdl/main.cpp74
-rw-r--r--src/melon_fopen.cpp176
-rw-r--r--src/melon_fopen.h29
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