Add a UNIX_PORTABLE build option, turning it off makes a build of melonDS suitable for systemwide installation.

This commit is contained in:
Nadia Holmquist Pedersen 2019-12-04 22:46:33 +01:00
parent 3f7bc1a6c1
commit 7af658f089
6 changed files with 117 additions and 8 deletions

11
melonDS.desktop Normal file
View File

@ -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=melon_256x256
MimeType=application/x-nintendo-ds-rom;
Keywords=emulator;Nintendo;DS;NDS;Nintendo DS;

View File

@ -815,7 +815,7 @@ bool ReadROMParams(u32 gamecode, u32* params)
// [gamecode] [ROM size] [save type] [reserved]
// list must be sorted by gamecode
FILE* f = Platform::OpenLocalFile("romlist.bin", "rb");
FILE* f = Platform::OpenDataFile("romlist.bin");
if (!f) return false;
fseek(f, 0, SEEK_END);

View File

@ -32,15 +32,21 @@ void StopEmu();
// can be optionally restricted to only opening a file that already exists.
// * OpenLocalFile():
// 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
// * emulator directory (essentially where the melonDS executable is) if supported
// * any platform-specific application data directories
// 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
// 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* OpenLocalFile(const char* path, const char* mode);
FILE* OpenDataFile(const char* path);
inline bool FileExists(const char* name)
{

View File

@ -31,6 +31,11 @@ target_link_libraries(melonDS
core ${SDL2_LIBRARIES} libui)
if (UNIX)
option(UNIX_PORTABLE "Make a portable build that looks for its configuration in the current directory" ON)
if (UNIX_PORTABLE)
add_definitions(-DUNIX_PORTABLE)
endif()
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
pkg_check_modules(SDL2 REQUIRED sdl2)
@ -61,4 +66,7 @@ elseif (WIN32)
target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi)
endif ()
install(FILES ../../melonDS.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
install(FILES ../../icon/melon_256x256.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps)
install(FILES ../../romlist.bin DESTINATION ${CMAKE_INSTALL_PREFIX}/share/melonds)
install(TARGETS melonDS RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)

View File

@ -135,6 +135,63 @@ FILE* OpenFile(const char* path, const char* mode, bool mustexist)
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);
}
return NULL;
}
#else
FILE* OpenLocalFile(const char* path, const char* mode)
{
bool relpath = false;
@ -257,6 +314,13 @@ FILE* OpenLocalFile(const char* path, const char* mode)
return NULL;
}
FILE* OpenDataFile(const char* path)
{
return OpenLocalFile(path, "r");
}
#endif
void* Thread_Create(void (*func)())
{

View File

@ -21,6 +21,10 @@
#include <stdio.h>
#include <string.h>
#ifndef __WIN32__
#include <glib.h>
#endif
#include <SDL2/SDL.h>
#include "libui/ui.h"
@ -2589,6 +2593,7 @@ int main(int argc, char** argv)
printf("melonDS " MELONDS_VERSION "\n");
printf(MELONDS_URL "\n");
#if defined(__WIN32__) || defined(UNIX_PORTABLE)
if (argc > 0 && strlen(argv[0]) > 0)
{
int len = strlen(argv[0]);
@ -2615,6 +2620,13 @@ int main(int argc, char** argv)
EmuDirectory = new char[2];
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
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
@ -2650,15 +2662,23 @@ int main(int argc, char** argv)
!Platform::LocalFileExists("bios9.bin") ||
!Platform::LocalFileExists("firmware.bin"))
{
uiMsgBoxError(
NULL,
"BIOS/Firmware not found",
#if defined(__WIN32__) || defined(UNIX_PORTABLE)
const char* locationName = "the directory you run melonDS from";
#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"
"bios7.bin -- ARM7 BIOS\n"
"bios9.bin -- ARM9 BIOS\n"
"firmware.bin -- firmware image\n\n"
"Dump the files from your DS and place them in the directory you run melonDS from.\n"
"Make sure that the files can be accessed.");
"Dump the files from your DS and place them in %s.\n"
"Make sure that the files can be accessed.",
locationName
);
uiMsgBoxError(NULL, "BIOS/Firmware not found", msgboxtext);
uiUninit();
SDL_Quit();
@ -2704,7 +2724,7 @@ int main(int argc, char** argv)
}
}
{
FILE* f = Platform::OpenLocalFile("romlist.bin", "rb");
FILE* f = Platform::OpenDataFile("romlist.bin");
if (f)
{
u32 data;