Merge pull request #546 from nadiaholmquist/feature/unix-xdg
Make melonDS properly installable systemwide on UNIX systems
This commit is contained in:
commit
2c51a49527
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
app-id: net.kuribo64.melonds
|
app-id: net.kuribo64.melonDS
|
||||||
runtime: org.freedesktop.Platform
|
runtime: org.freedesktop.Platform
|
||||||
runtime-version: '18.08'
|
runtime-version: '18.08'
|
||||||
sdk: org.freedesktop.Sdk
|
sdk: org.freedesktop.Sdk
|
||||||
|
@ -22,10 +22,8 @@ modules:
|
||||||
buildsystem: cmake-ninja
|
buildsystem: cmake-ninja
|
||||||
sources:
|
sources:
|
||||||
- type: git
|
- type: git
|
||||||
url: https://github.com/StapleButter/melonDS.git
|
url: https://github.com/Arisotura/melonDS.git
|
||||||
commit: d4d4965b2fffc69958685a25a9d9fc0c78b54567
|
branch: master
|
||||||
- type: file
|
|
||||||
path: net.kuribo64.melonds.desktop
|
|
||||||
post-install:
|
post-install:
|
||||||
- "desktop-file-install --dir=/app/share/applications net.kuribo64.melonds.desktop"
|
- "desktop-file-install --dir=/app/share/applications net.kuribo64.melonDS.desktop"
|
||||||
- "install -D icon/melon_256x256.png /app/share/icons/hicolor/256x256/apps/net.kuribo64.melonds.png"
|
- "install -D icon/melon_256x256.png /app/share/icons/hicolor/256x256/apps/net.kuribo64.melonDS.png"
|
|
@ -1,8 +0,0 @@
|
||||||
[Desktop Entry]
|
|
||||||
Name=melonDS
|
|
||||||
Comment=Nintendo DS emulator
|
|
||||||
Exec=melonDS
|
|
||||||
Type=Application
|
|
||||||
Categories=Game;
|
|
||||||
Terminal=false
|
|
||||||
Icon=net.kuribo64.melonds
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
[Desktop Entry]
|
||||||
|
Name=melonDS
|
||||||
|
GenericName=Nintendo DS Emulator
|
||||||
|
Comment=A fast and accurate Nintendo DS emulator.
|
||||||
|
Exec=melonDS
|
||||||
|
Type=Application
|
||||||
|
Categories=Game;Emulator;
|
||||||
|
Terminal=false
|
||||||
|
Icon=net.kuribo64.melonDS
|
||||||
|
MimeType=application/x-nintendo-ds-rom;
|
||||||
|
Keywords=emulator;Nintendo;DS;NDS;Nintendo DS;
|
|
@ -814,7 +814,7 @@ bool ReadROMParams(u32 gamecode, u32* params)
|
||||||
// [gamecode] [ROM size] [save type] [reserved]
|
// [gamecode] [ROM size] [save type] [reserved]
|
||||||
// list must be sorted by gamecode
|
// list must be sorted by gamecode
|
||||||
|
|
||||||
FILE* f = Platform::OpenLocalFile("romlist.bin", "rb");
|
FILE* f = Platform::OpenDataFile("romlist.bin");
|
||||||
if (!f) return false;
|
if (!f) return false;
|
||||||
|
|
||||||
fseek(f, 0, SEEK_END);
|
fseek(f, 0, SEEK_END);
|
||||||
|
|
|
@ -32,15 +32,21 @@ void StopEmu();
|
||||||
// can be optionally restricted to only opening a file that already exists.
|
// can be optionally restricted to only opening a file that already exists.
|
||||||
// * OpenLocalFile():
|
// * OpenLocalFile():
|
||||||
// opens files local to the emulator (melonDS.ini, BIOS, firmware, ...)
|
// opens files local to the emulator (melonDS.ini, BIOS, firmware, ...)
|
||||||
// checks, by order of priority:
|
// For Windows builds, or portable UNIX builds it checks, by order of priority:
|
||||||
// * current working directory
|
// * current working directory
|
||||||
// * emulator directory (essentially where the melonDS executable is) if supported
|
// * emulator directory (essentially where the melonDS executable is) if supported
|
||||||
// * any platform-specific application data directories
|
// * any platform-specific application data directories
|
||||||
// in create mode, if the file doesn't exist, it will be created in the emulator
|
// in create mode, if the file doesn't exist, it will be created in the emulator
|
||||||
// directory if supported, or in the current directory otherwise
|
// directory if supported, or in the current directory otherwise
|
||||||
|
// For regular UNIX builds, the user's configuration directory is always used.
|
||||||
|
// * OpenDataFile():
|
||||||
|
// Opens a file that was installed alongside melonDS on UNIX systems in /usr/share, etc.
|
||||||
|
// Looks in the user's data directory first, then the system's.
|
||||||
|
// If on Windows or a portable UNIX build, this simply calls OpenLocalFile().
|
||||||
|
|
||||||
FILE* OpenFile(const char* path, const char* mode, bool mustexist=false);
|
FILE* OpenFile(const char* path, const char* mode, bool mustexist=false);
|
||||||
FILE* OpenLocalFile(const char* path, const char* mode);
|
FILE* OpenLocalFile(const char* path, const char* mode);
|
||||||
|
FILE* OpenDataFile(const char* path);
|
||||||
|
|
||||||
inline bool FileExists(const char* name)
|
inline bool FileExists(const char* name)
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,6 +31,11 @@ target_link_libraries(melonDS
|
||||||
core ${SDL2_LIBRARIES} libui)
|
core ${SDL2_LIBRARIES} libui)
|
||||||
|
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
|
option(UNIX_PORTABLE "Make a portable build that looks for its configuration in the current directory" OFF)
|
||||||
|
if (UNIX_PORTABLE)
|
||||||
|
add_definitions(-DUNIX_PORTABLE)
|
||||||
|
endif()
|
||||||
|
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
|
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
|
||||||
pkg_check_modules(SDL2 REQUIRED sdl2)
|
pkg_check_modules(SDL2 REQUIRED sdl2)
|
||||||
|
@ -61,4 +66,7 @@ elseif (WIN32)
|
||||||
target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi)
|
target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
install(FILES ../../net.kuribo64.melonDS.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
|
||||||
|
install(FILES ../../icon/melon_256x256.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME net.kuribo64.melonDS.png)
|
||||||
|
install(FILES ../../romlist.bin DESTINATION ${CMAKE_INSTALL_PREFIX}/share/melonDS)
|
||||||
install(TARGETS melonDS RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
install(TARGETS melonDS RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
||||||
|
|
|
@ -135,6 +135,66 @@ FILE* OpenFile(const char* path, const char* mode, bool mustexist)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(UNIX_PORTABLE) && !defined(__WIN32__)
|
||||||
|
|
||||||
|
FILE* OpenLocalFile(const char* path, const char* mode)
|
||||||
|
{
|
||||||
|
std::string fullpath;
|
||||||
|
if (path[0] == '/')
|
||||||
|
{
|
||||||
|
// If it's an absolute path, just open that.
|
||||||
|
fullpath = std::string(path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Check user configuration directory
|
||||||
|
std::string confpath = std::string(g_get_user_config_dir()) + "/melonDS/";
|
||||||
|
g_mkdir_with_parents(confpath.c_str(), 0755);
|
||||||
|
fullpath = confpath + path;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OpenFile(fullpath.c_str(), mode, mode[0] != 'w');
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* OpenDataFile(const char* path)
|
||||||
|
{
|
||||||
|
const char* melondir = "melonDS";
|
||||||
|
const char* const* sys_dirs = g_get_system_data_dirs();
|
||||||
|
const char* user_dir = g_get_user_data_dir();
|
||||||
|
|
||||||
|
// First check the user's data directory
|
||||||
|
char* fullpath = g_build_path("/", user_dir, melondir, path, NULL);
|
||||||
|
if (access(fullpath, R_OK) == 0)
|
||||||
|
{
|
||||||
|
FILE* f = fopen(fullpath, "r");
|
||||||
|
g_free(fullpath);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
free(fullpath);
|
||||||
|
|
||||||
|
// Then check the system data directories
|
||||||
|
for (size_t i = 0; sys_dirs[i] != NULL; i++)
|
||||||
|
{
|
||||||
|
const char* dir = sys_dirs[i];
|
||||||
|
char* fullpath = g_build_path("/", dir, melondir, path, NULL);
|
||||||
|
|
||||||
|
if (access(fullpath, R_OK) == 0)
|
||||||
|
{
|
||||||
|
FILE* f = fopen(fullpath, "r");
|
||||||
|
g_free(fullpath);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
free(fullpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* f = fopen(path, "rb");
|
||||||
|
if (f) return f;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
FILE* OpenLocalFile(const char* path, const char* mode)
|
FILE* OpenLocalFile(const char* path, const char* mode)
|
||||||
{
|
{
|
||||||
bool relpath = false;
|
bool relpath = false;
|
||||||
|
@ -178,7 +238,7 @@ FILE* OpenLocalFile(const char* path, const char* mode)
|
||||||
emudirpath[pathlen] = '\0';
|
emudirpath[pathlen] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Locations are application directory, and AppData/melonDS on Windows or XDG_CONFIG_HOME/melonds on Linux
|
// Locations are application directory, and AppData/melonDS on Windows or XDG_CONFIG_HOME/melonDS on Linux
|
||||||
|
|
||||||
FILE* f;
|
FILE* f;
|
||||||
|
|
||||||
|
@ -240,7 +300,7 @@ FILE* OpenLocalFile(const char* path, const char* mode)
|
||||||
{
|
{
|
||||||
// Now check XDG_CONFIG_HOME
|
// Now check XDG_CONFIG_HOME
|
||||||
// TODO: check for memory leak there
|
// TODO: check for memory leak there
|
||||||
std::string fullpath = std::string(g_get_user_config_dir()) + "/melonds/" + path;
|
std::string fullpath = std::string(g_get_user_config_dir()) + "/melonDS/" + path;
|
||||||
f = OpenFile(fullpath.c_str(), mode, true);
|
f = OpenFile(fullpath.c_str(), mode, true);
|
||||||
if (f) { delete[] emudirpath; return f; }
|
if (f) { delete[] emudirpath; return f; }
|
||||||
}
|
}
|
||||||
|
@ -257,6 +317,13 @@ FILE* OpenLocalFile(const char* path, const char* mode)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FILE* OpenDataFile(const char* path)
|
||||||
|
{
|
||||||
|
return OpenLocalFile(path, "rb");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void* Thread_Create(void (*func)())
|
void* Thread_Create(void (*func)())
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,6 +21,10 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef __WIN32__
|
||||||
|
#include <glib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include "libui/ui.h"
|
#include "libui/ui.h"
|
||||||
|
|
||||||
|
@ -2681,6 +2685,7 @@ int main(int argc, char** argv)
|
||||||
printf("melonDS " MELONDS_VERSION "\n");
|
printf("melonDS " MELONDS_VERSION "\n");
|
||||||
printf(MELONDS_URL "\n");
|
printf(MELONDS_URL "\n");
|
||||||
|
|
||||||
|
#if defined(__WIN32__) || defined(UNIX_PORTABLE)
|
||||||
if (argc > 0 && strlen(argv[0]) > 0)
|
if (argc > 0 && strlen(argv[0]) > 0)
|
||||||
{
|
{
|
||||||
int len = strlen(argv[0]);
|
int len = strlen(argv[0]);
|
||||||
|
@ -2707,6 +2712,13 @@ int main(int argc, char** argv)
|
||||||
EmuDirectory = new char[2];
|
EmuDirectory = new char[2];
|
||||||
strcpy(EmuDirectory, ".");
|
strcpy(EmuDirectory, ".");
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
const char* confdir = g_get_user_config_dir();
|
||||||
|
const char* confname = "/melonds";
|
||||||
|
EmuDirectory = new char[strlen(confdir) + strlen(confname) + 1];
|
||||||
|
strcat(EmuDirectory, confdir);
|
||||||
|
strcat(EmuDirectory, confname);
|
||||||
|
#endif
|
||||||
|
|
||||||
// http://stackoverflow.com/questions/14543333/joystick-wont-work-using-sdl
|
// http://stackoverflow.com/questions/14543333/joystick-wont-work-using-sdl
|
||||||
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
|
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
|
||||||
|
@ -2742,15 +2754,23 @@ int main(int argc, char** argv)
|
||||||
!Platform::LocalFileExists("bios9.bin") ||
|
!Platform::LocalFileExists("bios9.bin") ||
|
||||||
!Platform::LocalFileExists("firmware.bin"))
|
!Platform::LocalFileExists("firmware.bin"))
|
||||||
{
|
{
|
||||||
uiMsgBoxError(
|
#if defined(__WIN32__) || defined(UNIX_PORTABLE)
|
||||||
NULL,
|
const char* locationName = "the directory you run melonDS from";
|
||||||
"BIOS/Firmware not found",
|
#else
|
||||||
|
char* locationName = EmuDirectory;
|
||||||
|
#endif
|
||||||
|
char msgboxtext[512];
|
||||||
|
sprintf(msgboxtext,
|
||||||
"One or more of the following required files don't exist or couldn't be accessed:\n\n"
|
"One or more of the following required files don't exist or couldn't be accessed:\n\n"
|
||||||
"bios7.bin -- ARM7 BIOS\n"
|
"bios7.bin -- ARM7 BIOS\n"
|
||||||
"bios9.bin -- ARM9 BIOS\n"
|
"bios9.bin -- ARM9 BIOS\n"
|
||||||
"firmware.bin -- firmware image\n\n"
|
"firmware.bin -- firmware image\n\n"
|
||||||
"Dump the files from your DS and place them in the directory you run melonDS from.\n"
|
"Dump the files from your DS and place them in %s.\n"
|
||||||
"Make sure that the files can be accessed.");
|
"Make sure that the files can be accessed.",
|
||||||
|
locationName
|
||||||
|
);
|
||||||
|
|
||||||
|
uiMsgBoxError(NULL, "BIOS/Firmware not found", msgboxtext);
|
||||||
|
|
||||||
uiUninit();
|
uiUninit();
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
|
@ -2796,7 +2816,18 @@ int main(int argc, char** argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
FILE* f = Platform::OpenLocalFile("romlist.bin", "rb");
|
const char* romlist_missing = "Save memory type detection will not work correctly.\n\n"
|
||||||
|
"You should use the latest version of romlist.bin (provided in melonDS release packages).";
|
||||||
|
#if !defined(UNIX_PORTABLE) && !defined(__WIN32__)
|
||||||
|
std::string missingstr = std::string(romlist_missing) +
|
||||||
|
"\n\nThe ROM list should be placed in " + g_get_user_data_dir() + "/melonds/, otherwise "
|
||||||
|
"melonDS will search for it in the current working directory.";
|
||||||
|
const char* romlist_missing_text = missingstr.c_str();
|
||||||
|
#else
|
||||||
|
const char* romlist_missing_text = romlist_missing;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FILE* f = Platform::OpenDataFile("romlist.bin");
|
||||||
if (f)
|
if (f)
|
||||||
{
|
{
|
||||||
u32 data;
|
u32 data;
|
||||||
|
@ -2805,18 +2836,12 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
if ((data >> 24) == 0) // old CRC-based list
|
if ((data >> 24) == 0) // old CRC-based list
|
||||||
{
|
{
|
||||||
uiMsgBoxError(NULL,
|
uiMsgBoxError(NULL, "Your version of romlist.bin is outdated.", romlist_missing_text);
|
||||||
"Your version of romlist.bin is outdated.",
|
|
||||||
"Save memory type detection will not work correctly.\n\n"
|
|
||||||
"You should use the latest version of romlist.bin (provided in melonDS release packages).");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uiMsgBoxError(NULL,
|
uiMsgBoxError(NULL, "romlist.bin not found.", romlist_missing_text);
|
||||||
"romlist.bin not found.",
|
|
||||||
"Save memory type detection will not work correctly.\n\n"
|
|
||||||
"You should use the latest version of romlist.bin (provided in melonDS release packages).");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue