config/data folders improvements
linux: look for legacy ~/.reicast and ~/.reicast/data else look for ~/.config/flycast and ~/.local/share/flycast and ~/.config/reicast and ~/.local/share/reicast (defaults to flycast) look for bios files in home folder and data folders (android, windows ,macos), then in game folder. on linux, search in /usr/share/flycast and /usr/local/share/flycast and legacy locations
This commit is contained in:
parent
d485da19b7
commit
8f77a5482a
|
@ -81,7 +81,7 @@ bool cfgOpen()
|
|||
// Config dir not set (android onboarding)
|
||||
return false;
|
||||
|
||||
const char* filename = "/emu.cfg";
|
||||
const char* filename = "emu.cfg";
|
||||
std::string config_path_read = get_readonly_config_path(filename);
|
||||
cfgPath = get_writable_config_path(filename);
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
void AICA_Sample();
|
||||
void AICA_Sample32();
|
||||
|
||||
//u32 ReadChannelReg(u32 channel,u32 reg);
|
||||
void WriteChannelReg(u32 channel, u32 reg, int size);
|
||||
|
||||
void sgc_Init();
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#pragma once
|
||||
#include <cmath>
|
||||
#include "types.h"
|
||||
#include "stdclass.h"
|
||||
|
||||
struct MemChip
|
||||
{
|
||||
|
@ -75,54 +76,41 @@ struct MemChip
|
|||
}
|
||||
}
|
||||
|
||||
bool Load(const std::string& root, const std::string& prefix, const std::string& names_ro, const std::string& title)
|
||||
bool Load(const std::string& prefix, const std::string& names_ro, const std::string& title)
|
||||
{
|
||||
char base[512];
|
||||
char temp[512];
|
||||
char names[512];
|
||||
|
||||
// FIXME: Data loss if buffer is too small
|
||||
strncpy(names,names_ro.c_str(), sizeof(names));
|
||||
names[sizeof(names) - 1] = '\0';
|
||||
|
||||
sprintf(base,"%s",root.c_str());
|
||||
|
||||
char* curr=names;
|
||||
char* next;
|
||||
do
|
||||
const size_t npos = std::string::npos;
|
||||
size_t start = 0;
|
||||
while (start < names_ro.size())
|
||||
{
|
||||
next=strstr(curr,";");
|
||||
if(next) *next=0;
|
||||
if (curr[0]=='%')
|
||||
{
|
||||
sprintf(temp,"%s%s%s",base,prefix.c_str(),curr+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(temp,"%s%s",base,curr);
|
||||
}
|
||||
|
||||
curr=next+1;
|
||||
size_t semicolon = names_ro.find(';', start);
|
||||
std::string name = names_ro.substr(start, semicolon == npos ? semicolon : semicolon - start);
|
||||
|
||||
if (Load(temp))
|
||||
size_t percent = name.find('%');
|
||||
if (percent != npos)
|
||||
name = name.replace(percent, 1, prefix);
|
||||
|
||||
std::string fullpath = get_readonly_data_path(name);
|
||||
if (file_exists(fullpath) && Load(fullpath))
|
||||
{
|
||||
INFO_LOG(FLASHROM, "Loaded %s as %s", temp, title.c_str());
|
||||
INFO_LOG(FLASHROM, "Loaded %s as %s", fullpath.c_str(), title.c_str());
|
||||
return true;
|
||||
}
|
||||
} while(next);
|
||||
|
||||
|
||||
start = semicolon;
|
||||
if (start != npos)
|
||||
start++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void Save(const std::string& root, const std::string& prefix, const std::string& name_ro, const std::string& title)
|
||||
{
|
||||
char path[512];
|
||||
|
||||
sprintf(path,"%s%s%s",root.c_str(),prefix.c_str(),name_ro.c_str());
|
||||
void Save(const std::string& prefix, const std::string& name_ro, const std::string& title)
|
||||
{
|
||||
std::string path = get_writable_data_path(prefix + name_ro);
|
||||
Save(path);
|
||||
|
||||
INFO_LOG(FLASHROM, "Saved %s as %s", path, title.c_str());
|
||||
INFO_LOG(FLASHROM, "Saved %s as %s", path.c_str(), title.c_str());
|
||||
}
|
||||
|
||||
virtual void Reset() {}
|
||||
virtual bool Serialize(void **data, unsigned int *total_size) { return true; }
|
||||
virtual bool Unserialize(void **data, unsigned int *total_size) { return true; }
|
||||
|
|
|
@ -164,11 +164,11 @@ void FixUpFlash()
|
|||
}
|
||||
}
|
||||
|
||||
static bool nvmem_load(const std::string& root)
|
||||
static bool nvmem_load()
|
||||
{
|
||||
bool rc;
|
||||
if (settings.platform.system == DC_PLATFORM_DREAMCAST)
|
||||
rc = sys_nvmem->Load(root, getRomPrefix(), "%nvmem.bin", "nvram");
|
||||
rc = sys_nvmem->Load(getRomPrefix(), "%nvmem.bin", "nvram");
|
||||
else
|
||||
rc = sys_nvmem->Load(get_game_save_prefix() + ".nvmem");
|
||||
if (!rc)
|
||||
|
@ -180,12 +180,12 @@ static bool nvmem_load(const std::string& root)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool LoadRomFiles(const std::string& root)
|
||||
bool LoadRomFiles()
|
||||
{
|
||||
nvmem_load(root);
|
||||
nvmem_load();
|
||||
if (settings.platform.system != DC_PLATFORM_ATOMISWAVE)
|
||||
{
|
||||
if (sys_rom->Load(root, getRomPrefix(), "%boot.bin;%boot.bin.bin;%bios.bin;%bios.bin.bin", "bootrom"))
|
||||
if (sys_rom->Load(getRomPrefix(), "%boot.bin;%boot.bin.bin;%bios.bin;%bios.bin.bin", "bootrom"))
|
||||
bios_loaded = true;
|
||||
else if (settings.platform.system == DC_PLATFORM_DREAMCAST)
|
||||
return false;
|
||||
|
@ -194,19 +194,19 @@ bool LoadRomFiles(const std::string& root)
|
|||
return true;
|
||||
}
|
||||
|
||||
void SaveRomFiles(const std::string& root)
|
||||
void SaveRomFiles()
|
||||
{
|
||||
if (settings.platform.system == DC_PLATFORM_DREAMCAST)
|
||||
sys_nvmem->Save(root, getRomPrefix(), "nvmem.bin", "nvmem");
|
||||
sys_nvmem->Save(getRomPrefix(), "nvmem.bin", "nvmem");
|
||||
else
|
||||
sys_nvmem->Save(get_game_save_prefix() + ".nvmem");
|
||||
if (settings.platform.system == DC_PLATFORM_ATOMISWAVE)
|
||||
sys_rom->Save(get_game_save_prefix() + ".nvmem2");
|
||||
}
|
||||
|
||||
bool LoadHle(const std::string& root)
|
||||
bool LoadHle()
|
||||
{
|
||||
if (!nvmem_load(root))
|
||||
if (!nvmem_load())
|
||||
WARN_LOG(FLASHROM, "No nvmem loaded\n");
|
||||
|
||||
reios_reset(sys_rom->data);
|
||||
|
|
|
@ -7,4 +7,9 @@ void map_area0(u32 base);
|
|||
//Init/Res/Term
|
||||
void sh4_area0_Init();
|
||||
void sh4_area0_Reset(bool Manual);
|
||||
void sh4_area0_Term();
|
||||
void sh4_area0_Term();
|
||||
|
||||
bool LoadRomFiles();
|
||||
void SaveRomFiles();
|
||||
bool LoadHle();
|
||||
void FixUpFlash();
|
||||
|
|
|
@ -482,8 +482,11 @@ struct maple_sega_vmu: maple_base
|
|||
memset(flash_data, 0, sizeof(flash_data));
|
||||
memset(lcd_data, 0, sizeof(lcd_data));
|
||||
char tempy[512];
|
||||
sprintf(tempy, "/vmu_save_%s.bin", logical_port);
|
||||
std::string apath = get_writable_data_path(tempy);
|
||||
sprintf(tempy, "vmu_save_%s.bin", logical_port);
|
||||
// VMU saves used to be stored in .reicast, not in .reicast/data
|
||||
std::string apath = get_writable_config_path(tempy);
|
||||
if (!file_exists(apath))
|
||||
apath = get_writable_data_path(tempy);
|
||||
|
||||
file = fopen(apath.c_str(), "rb+");
|
||||
if (!file)
|
||||
|
@ -492,25 +495,19 @@ struct maple_sega_vmu: maple_base
|
|||
file = fopen(apath.c_str(), "wb");
|
||||
if (file) {
|
||||
if (!init_emptyvmu())
|
||||
INFO_LOG(MAPLE, "Failed to initialize an empty VMU, you should reformat it using the BIOS");
|
||||
WARN_LOG(MAPLE, "Failed to initialize an empty VMU, you should reformat it using the BIOS");
|
||||
|
||||
fwrite(flash_data, sizeof(flash_data), 1, file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
}
|
||||
else
|
||||
{
|
||||
INFO_LOG(MAPLE, "Unable to create VMU!");
|
||||
ERROR_LOG(MAPLE, "Failed to create VMU save file \"%s\"", apath.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (!file)
|
||||
{
|
||||
INFO_LOG(MAPLE, "Failed to create VMU save file \"%s\"", apath.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (file != nullptr)
|
||||
fread(flash_data, 1, sizeof(flash_data), file);
|
||||
}
|
||||
|
||||
u8 sum = 0;
|
||||
for (u32 i = 0; i < sizeof(flash_data); i++)
|
||||
|
@ -521,20 +518,15 @@ struct maple_sega_vmu: maple_base
|
|||
|
||||
if (init_emptyvmu())
|
||||
{
|
||||
if (!file)
|
||||
file = fopen(apath.c_str(), "wb");
|
||||
|
||||
if (file) {
|
||||
if (file != nullptr)
|
||||
{
|
||||
fwrite(flash_data, sizeof(flash_data), 1, file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
}
|
||||
else {
|
||||
INFO_LOG(MAPLE, "Unable to create VMU!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
INFO_LOG(MAPLE, "Failed to initialize an empty VMU, you should reformat it using the BIOS");
|
||||
WARN_LOG(MAPLE, "Failed to initialize an empty VMU, you should reformat it using the BIOS");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3001,7 +2993,7 @@ u32 jvs_io_board::handle_jvs_message(u8 *buffer_in, u32 length_in, u8 *buffer_ou
|
|||
jvs_length = length - 2;
|
||||
|
||||
u8 calc_crc = 0;
|
||||
for (int i = 1; i < length; i++)
|
||||
for (u32 i = 1; i < length; i++)
|
||||
calc_crc = ((calc_crc + buffer_out[i]) & 0xFF);
|
||||
|
||||
JVS_OUT(calc_crc);
|
||||
|
|
|
@ -76,8 +76,12 @@ static bool naomi_LoadBios(const char *filename, Archive *child_archive, Archive
|
|||
|
||||
struct BIOS_t *bios = &BIOS[biosid];
|
||||
|
||||
std::string basepath = get_readonly_data_path(DATA_PATH);
|
||||
std::unique_ptr<Archive> bios_archive(OpenArchive((basepath + filename).c_str()));
|
||||
std::string arch_name(filename);
|
||||
std::string path = get_readonly_data_path(arch_name + ".zip");
|
||||
if (!file_exists(path.c_str()))
|
||||
path = get_readonly_data_path(arch_name + ".7z");
|
||||
DEBUG_LOG(NAOMI, "Loading BIOS from %s", path.c_str());
|
||||
std::unique_ptr<Archive> bios_archive(OpenArchive(path.c_str()));
|
||||
|
||||
bool found_region = false;
|
||||
|
||||
|
@ -232,7 +236,7 @@ static void naomi_cart_LoadZip(const char *filename)
|
|||
{
|
||||
// If a specific BIOS is needed for this game, fail.
|
||||
if (game->bios != NULL || !bios_loaded)
|
||||
throw NaomiCartException(std::string("Error: cannot load BIOS ") + (game->bios != NULL ? game->bios : "naomi.zip") + " in " + get_readonly_data_path(DATA_PATH));
|
||||
throw NaomiCartException(std::string("Error: cannot load BIOS ") + (game->bios != NULL ? game->bios : "naomi.zip"));
|
||||
|
||||
// otherwise use the default BIOS
|
||||
}
|
||||
|
|
|
@ -652,7 +652,7 @@ void print_blocks()
|
|||
|
||||
if (print_stats)
|
||||
{
|
||||
f=fopen(get_writable_data_path("/blkmap.lst").c_str(),"w");
|
||||
f=fopen(get_writable_data_path("blkmap.lst").c_str(),"w");
|
||||
print_stats=0;
|
||||
|
||||
INFO_LOG(DYNAREC, "Writing blocks to %p", f);
|
||||
|
@ -680,9 +680,7 @@ void print_blocks()
|
|||
fprintf(f,"host_opcodes: %d\n",blk->host_opcodes);
|
||||
fprintf(f,"il_opcodes: %zd\n",blk->oplist.size());
|
||||
|
||||
u32 hcode=0;
|
||||
s32 gcode=-1;
|
||||
u8* pucode=(u8*)blk->code;
|
||||
|
||||
size_t j=0;
|
||||
|
||||
|
|
|
@ -223,12 +223,6 @@ void mem_Term()
|
|||
sh4_mmr_term();
|
||||
sh4_area0_Term();
|
||||
|
||||
// done by emulator thread
|
||||
//SaveRomFiles(get_writable_data_path(DATA_PATH));
|
||||
|
||||
//mem_b.Term(); // handled by vmem
|
||||
|
||||
//vmem
|
||||
_vmem_term();
|
||||
}
|
||||
|
||||
|
|
|
@ -85,8 +85,4 @@ u8* GetMemPtr(u32 Addr,u32 size);
|
|||
|
||||
bool IsOnRam(u32 addr);
|
||||
|
||||
bool LoadRomFiles(const std::string& root);
|
||||
void SaveRomFiles(const std::string& root);
|
||||
bool LoadHle(const std::string& root);
|
||||
void FixUpFlash();
|
||||
void SetMemoryHandlers();
|
||||
|
|
|
@ -205,7 +205,7 @@ std::shared_ptr<InputMapping> InputMapping::LoadMapping(const char *name)
|
|||
if (it != loaded_mappings.end())
|
||||
return it->second;
|
||||
|
||||
std::string path = get_writable_config_path((std::string("/mappings/") + name).c_str());
|
||||
std::string path = get_readonly_config_path((std::string("mappings/") + name).c_str());
|
||||
FILE *fp = fopen(path.c_str(), "r");
|
||||
if (fp == NULL)
|
||||
return NULL;
|
||||
|
@ -222,9 +222,9 @@ bool InputMapping::save(const char *name)
|
|||
if (!dirty)
|
||||
return true;
|
||||
|
||||
std::string path = get_writable_config_path("/mappings/");
|
||||
std::string path = get_writable_config_path("mappings/");
|
||||
make_directory(path);
|
||||
path = get_writable_config_path((std::string("/mappings/") + name).c_str());
|
||||
path = get_writable_config_path((std::string("mappings/") + name).c_str());
|
||||
FILE *fp = fopen(path.c_str(), "w");
|
||||
if (fp == NULL)
|
||||
{
|
||||
|
|
|
@ -151,89 +151,139 @@ void* rend_thread(void* p);
|
|||
}
|
||||
#endif
|
||||
|
||||
// Find the user config directory.
|
||||
// The following folders are checked in this order:
|
||||
// $HOME/.reicast
|
||||
// $HOME/.config/flycast
|
||||
// $HOME/.config/reicast
|
||||
// If no folder exists, $HOME/.config/flycast is created and used.
|
||||
std::string find_user_config_dir()
|
||||
{
|
||||
struct stat info;
|
||||
std::string home = "";
|
||||
if(getenv("HOME") != NULL)
|
||||
std::string xdg_home;
|
||||
if (getenv("HOME") != NULL)
|
||||
{
|
||||
// Support for the legacy config dir at "$HOME/.reicast"
|
||||
std::string legacy_home = (std::string)getenv("HOME") + "/.reicast";
|
||||
if((stat(legacy_home.c_str(), &info) == 0) && (info.st_mode & S_IFDIR))
|
||||
{
|
||||
std::string legacy_home = (std::string)getenv("HOME") + "/.reicast/";
|
||||
if (stat(legacy_home.c_str(), &info) == 0 && (info.st_mode & S_IFDIR))
|
||||
// "$HOME/.reicast" already exists, let's use it!
|
||||
return legacy_home;
|
||||
}
|
||||
|
||||
/* If $XDG_CONFIG_HOME is not set, we're supposed to use "$HOME/.config" instead.
|
||||
* Consult the XDG Base Directory Specification for details:
|
||||
* http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html#variables
|
||||
*/
|
||||
home = (std::string)getenv("HOME") + "/.config/reicast";
|
||||
xdg_home = (std::string)getenv("HOME") + "/.config";
|
||||
}
|
||||
if(getenv("XDG_CONFIG_HOME") != NULL)
|
||||
{
|
||||
if (getenv("XDG_CONFIG_HOME") != NULL)
|
||||
// If XDG_CONFIG_HOME is set explicitly, we'll use that instead of $HOME/.config
|
||||
home = (std::string)getenv("XDG_CONFIG_HOME") + "/reicast";
|
||||
}
|
||||
xdg_home = (std::string)getenv("XDG_CONFIG_HOME");
|
||||
|
||||
if(!home.empty())
|
||||
if (!xdg_home.empty())
|
||||
{
|
||||
if((stat(home.c_str(), &info) != 0) || !(info.st_mode & S_IFDIR))
|
||||
{
|
||||
// If the directory doesn't exist yet, create it!
|
||||
mkdir(home.c_str(), 0755);
|
||||
}
|
||||
return home;
|
||||
std::string fullpath = xdg_home + "/flycast/";
|
||||
if (stat(fullpath.c_str(), &info) == 0 && (info.st_mode & S_IFDIR))
|
||||
// Found .config/flycast
|
||||
return fullpath;
|
||||
fullpath = xdg_home + "/reicast/";
|
||||
if (stat(fullpath.c_str(), &info) == 0 && (info.st_mode & S_IFDIR))
|
||||
// Found .config/reicast
|
||||
return fullpath;
|
||||
|
||||
// Create .config/flycast
|
||||
fullpath = xdg_home + "/flycast/";
|
||||
mkdir(fullpath.c_str(), 0755);
|
||||
|
||||
return fullpath;
|
||||
}
|
||||
|
||||
// Unable to detect config dir, use the current folder
|
||||
return ".";
|
||||
}
|
||||
|
||||
// Find the user data directory.
|
||||
// The following folders are checked in this order:
|
||||
// $HOME/.reicast/data
|
||||
// $HOME/.local/share/flycast
|
||||
// $HOME/.local/share/reicast
|
||||
// If no folder exists, $HOME/.local/share/flycast is created and used.
|
||||
std::string find_user_data_dir()
|
||||
{
|
||||
struct stat info;
|
||||
std::string data = "";
|
||||
if(getenv("HOME") != NULL)
|
||||
std::string xdg_home;
|
||||
if (getenv("HOME") != NULL)
|
||||
{
|
||||
// Support for the legacy config dir at "$HOME/.reicast"
|
||||
std::string legacy_data = (std::string)getenv("HOME") + "/.reicast";
|
||||
if((stat(legacy_data.c_str(), &info) == 0) && (info.st_mode & S_IFDIR))
|
||||
{
|
||||
// "$HOME/.reicast" already exists, let's use it!
|
||||
// Support for the legacy config dir at "$HOME/.reicast/data"
|
||||
std::string legacy_data = (std::string)getenv("HOME") + "/.reicast/data/";
|
||||
if (stat(legacy_data.c_str(), &info) == 0 && (info.st_mode & S_IFDIR))
|
||||
// "$HOME/.reicast/data" already exists, let's use it!
|
||||
return legacy_data;
|
||||
}
|
||||
|
||||
/* If $XDG_DATA_HOME is not set, we're supposed to use "$HOME/.local/share" instead.
|
||||
* Consult the XDG Base Directory Specification for details:
|
||||
* http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html#variables
|
||||
*/
|
||||
data = (std::string)getenv("HOME") + "/.local/share/reicast";
|
||||
xdg_home = (std::string)getenv("HOME") + "/.local/share";
|
||||
}
|
||||
if(getenv("XDG_DATA_HOME") != NULL)
|
||||
if (getenv("XDG_DATA_HOME") != NULL)
|
||||
// If XDG_DATA_HOME is set explicitly, we'll use that instead of $HOME/.local/share
|
||||
xdg_home = (std::string)getenv("XDG_DATA_HOME");
|
||||
|
||||
if (!xdg_home.empty())
|
||||
{
|
||||
// If XDG_DATA_HOME is set explicitly, we'll use that instead of $HOME/.config
|
||||
data = (std::string)getenv("XDG_DATA_HOME") + "/reicast";
|
||||
std::string fullpath = xdg_home + "/flycast/";
|
||||
if (stat(fullpath.c_str(), &info) == 0 && (info.st_mode & S_IFDIR))
|
||||
// Found .local/share/flycast
|
||||
return fullpath;
|
||||
fullpath = xdg_home + "/reicast/";
|
||||
if (stat(fullpath.c_str(), &info) == 0 && (info.st_mode & S_IFDIR))
|
||||
// Found .local/share/reicast
|
||||
return fullpath;
|
||||
|
||||
// Create .local/share/flycast
|
||||
fullpath = xdg_home + "/flycast/";
|
||||
mkdir(fullpath.c_str(), 0755);
|
||||
|
||||
return fullpath;
|
||||
}
|
||||
|
||||
if(!data.empty())
|
||||
{
|
||||
if((stat(data.c_str(), &info) != 0) || !(info.st_mode & S_IFDIR))
|
||||
{
|
||||
// If the directory doesn't exist yet, create it!
|
||||
mkdir(data.c_str(), 0755);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
// Unable to detect config dir, use the current folder
|
||||
// Unable to detect data dir, use the current folder
|
||||
return ".";
|
||||
}
|
||||
|
||||
// Find a file in the user and system config directories.
|
||||
// The following folders are checked in this order:
|
||||
// $HOME/.reicast
|
||||
// $HOME/.config/flycast
|
||||
// $HOME/.config/reicast
|
||||
// if XDG_CONFIG_DIRS is defined:
|
||||
// <$XDG_CONFIG_DIRS>/flycast
|
||||
// <$XDG_CONFIG_DIRS>/reicast
|
||||
// else
|
||||
// /etc/flycast/
|
||||
// /etc/xdg/flycast/
|
||||
// .
|
||||
std::vector<std::string> find_system_config_dirs()
|
||||
{
|
||||
std::vector<std::string> dirs;
|
||||
|
||||
std::string xdg_home;
|
||||
if (getenv("HOME") != NULL)
|
||||
{
|
||||
// Support for the legacy config dir at "$HOME/.reicast"
|
||||
dirs.push_back((std::string)getenv("HOME") + "/.reicast/");
|
||||
xdg_home = (std::string)getenv("HOME") + "/.config";
|
||||
}
|
||||
if (getenv("XDG_CONFIG_HOME") != NULL)
|
||||
// If XDG_CONFIG_HOME is set explicitly, we'll use that instead of $HOME/.config
|
||||
xdg_home = (std::string)getenv("XDG_CONFIG_HOME");
|
||||
if (!xdg_home.empty())
|
||||
{
|
||||
// XDG config locations
|
||||
dirs.push_back(xdg_home + "/flycast/");
|
||||
dirs.push_back(xdg_home + "/reicast/");
|
||||
}
|
||||
|
||||
if (getenv("XDG_CONFIG_DIRS") != NULL)
|
||||
{
|
||||
std::string s = (std::string)getenv("XDG_CONFIG_DIRS");
|
||||
|
@ -242,24 +292,61 @@ std::vector<std::string> find_system_config_dirs()
|
|||
std::string::size_type n = s.find(':', pos);
|
||||
while(n != std::string::npos)
|
||||
{
|
||||
dirs.push_back(s.substr(pos, n-pos) + "/reicast");
|
||||
dirs.push_back(s.substr(pos, n-pos) + "/flycast/");
|
||||
dirs.push_back(s.substr(pos, n-pos) + "/reicast/");
|
||||
pos = n + 1;
|
||||
n = s.find(':', pos);
|
||||
}
|
||||
// Separator not found
|
||||
dirs.push_back(s.substr(pos) + "/reicast");
|
||||
dirs.push_back(s.substr(pos) + "/flycast/");
|
||||
dirs.push_back(s.substr(pos) + "/reicast/");
|
||||
}
|
||||
else
|
||||
{
|
||||
dirs.push_back("/etc/reicast"); // This isn't part of the XDG spec, but much more common than /etc/xdg/
|
||||
dirs.push_back("/etc/xdg/reicast");
|
||||
dirs.push_back("/etc/flycast/"); // This isn't part of the XDG spec, but much more common than /etc/xdg/
|
||||
dirs.push_back("/etc/xdg/flycast/");
|
||||
}
|
||||
dirs.push_back("./");
|
||||
|
||||
return dirs;
|
||||
}
|
||||
|
||||
// Find a file in the user data directories.
|
||||
// The following folders are checked in this order:
|
||||
// $HOME/.reicast/data
|
||||
// $HOME/.local/share/flycast
|
||||
// $HOME/.local/share/reicast
|
||||
// if XDG_DATA_DIRS is defined:
|
||||
// <$XDG_DATA_DIRS>/flycast
|
||||
// <$XDG_DATA_DIRS>/reicast
|
||||
// else
|
||||
// /usr/local/share/flycast
|
||||
// /usr/share/flycast
|
||||
// /usr/local/share/reicast
|
||||
// /usr/share/reicast
|
||||
// ./data
|
||||
std::vector<std::string> find_system_data_dirs()
|
||||
{
|
||||
std::vector<std::string> dirs;
|
||||
|
||||
std::string xdg_home;
|
||||
if (getenv("HOME") != NULL)
|
||||
{
|
||||
// Support for the legacy data dir at "$HOME/.reicast/data"
|
||||
dirs.push_back((std::string)getenv("HOME") + "/.reicast/data/");
|
||||
xdg_home = (std::string)getenv("HOME") + "/.local/share";
|
||||
}
|
||||
if (getenv("XDG_DATA_HOME") != NULL)
|
||||
// If XDG_DATA_HOME is set explicitly, we'll use that instead of $HOME/.local/share
|
||||
xdg_home = (std::string)getenv("XDG_DATA_HOME");
|
||||
if (!xdg_home.empty())
|
||||
{
|
||||
// XDG data locations
|
||||
dirs.push_back(xdg_home + "/flycast/");
|
||||
dirs.push_back(xdg_home + "/reicast/");
|
||||
dirs.push_back(xdg_home + "/reicast/data/");
|
||||
}
|
||||
|
||||
if (getenv("XDG_DATA_DIRS") != NULL)
|
||||
{
|
||||
std::string s = (std::string)getenv("XDG_DATA_DIRS");
|
||||
|
@ -268,18 +355,25 @@ std::vector<std::string> find_system_data_dirs()
|
|||
std::string::size_type n = s.find(':', pos);
|
||||
while(n != std::string::npos)
|
||||
{
|
||||
dirs.push_back(s.substr(pos, n-pos) + "/reicast");
|
||||
dirs.push_back(s.substr(pos, n-pos) + "/flycast/");
|
||||
dirs.push_back(s.substr(pos, n-pos) + "/reicast/");
|
||||
pos = n + 1;
|
||||
n = s.find(':', pos);
|
||||
}
|
||||
// Separator not found
|
||||
dirs.push_back(s.substr(pos) + "/reicast");
|
||||
dirs.push_back(s.substr(pos) + "/flycast/");
|
||||
dirs.push_back(s.substr(pos) + "/reicast/");
|
||||
}
|
||||
else
|
||||
{
|
||||
dirs.push_back("/usr/local/share/reicast");
|
||||
dirs.push_back("/usr/share/reicast");
|
||||
dirs.push_back("/usr/local/share/flycast/");
|
||||
dirs.push_back("/usr/share/flycast/");
|
||||
dirs.push_back("/usr/local/share/reicast/");
|
||||
dirs.push_back("/usr/share/reicast/");
|
||||
}
|
||||
dirs.push_back("./");
|
||||
dirs.push_back("data/");
|
||||
|
||||
return dirs;
|
||||
}
|
||||
|
||||
|
@ -291,22 +385,15 @@ int main(int argc, char* argv[])
|
|||
signal(SIGKILL, clean_exit);
|
||||
#endif
|
||||
|
||||
/* Set directories */
|
||||
// Set directories
|
||||
set_user_config_dir(find_user_config_dir());
|
||||
set_user_data_dir(find_user_data_dir());
|
||||
std::vector<std::string> dirs;
|
||||
dirs = find_system_config_dirs();
|
||||
for (std::size_t i = 0; i < dirs.size(); i++)
|
||||
{
|
||||
add_system_data_dir(dirs[i]);
|
||||
}
|
||||
dirs = find_system_data_dirs();
|
||||
for (std::size_t i = 0; i < dirs.size(); i++)
|
||||
{
|
||||
add_system_data_dir(dirs[i]);
|
||||
}
|
||||
INFO_LOG(BOOT, "Config dir is: %s", get_writable_config_path("/").c_str());
|
||||
INFO_LOG(BOOT, "Data dir is: %s", get_writable_data_path("/").c_str());
|
||||
for (const auto& dir : find_system_config_dirs())
|
||||
add_system_config_dir(dir);
|
||||
for (const auto& dir : find_system_data_dirs())
|
||||
add_system_data_dir(dir);
|
||||
INFO_LOG(BOOT, "Config dir is: %s", get_writable_config_path("").c_str());
|
||||
INFO_LOG(BOOT, "Data dir is: %s", get_writable_data_path("").c_str());
|
||||
|
||||
#if defined(USE_SDL)
|
||||
// init video now: on rpi3 it installs a sigsegv handler(?)
|
||||
|
|
|
@ -121,7 +121,7 @@ static int allocate_shared_filemem(unsigned size) {
|
|||
|
||||
// if shmem does not work (or using OSX) fallback to a regular file on disk
|
||||
if (fd < 0) {
|
||||
std::string path = get_writable_data_path("/dcnzorz_mem");
|
||||
std::string path = get_writable_data_path("dcnzorz_mem");
|
||||
fd = open(path.c_str(), O_CREAT|O_RDWR|O_TRUNC, S_IRWXU|S_IRWXG|S_IRWXO);
|
||||
unlink(path.c_str());
|
||||
}
|
||||
|
|
|
@ -131,7 +131,7 @@ LogManager::LogManager()
|
|||
if (cfgLoadBool("log", "LogToFile", false))
|
||||
{
|
||||
#ifdef __ANDROID__
|
||||
std::string logPath = get_writable_data_path("/flycast.log");
|
||||
std::string logPath = get_writable_data_path("flycast.log");
|
||||
#else
|
||||
std::string logPath = "flycast.log";
|
||||
#endif
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "hw/maple/maple_cfg.h"
|
||||
#include "hw/sh4/sh4_mem.h"
|
||||
#include "hw/holly/sb_mem.h"
|
||||
|
||||
#include "hw/naomi/naomi_cart.h"
|
||||
#include "reios/reios.h"
|
||||
|
@ -551,15 +552,14 @@ static void dc_start_game(const char *path)
|
|||
dc_reset(true);
|
||||
LoadSettings(false);
|
||||
|
||||
std::string data_path = get_readonly_data_path(DATA_PATH);
|
||||
if (settings.platform.system == DC_PLATFORM_DREAMCAST)
|
||||
{
|
||||
if ((settings.bios.UseReios && !forced_bios_file) || !LoadRomFiles(data_path))
|
||||
if ((settings.bios.UseReios && !forced_bios_file) || !LoadRomFiles())
|
||||
{
|
||||
if (forced_bios_file)
|
||||
throw ReicastException("No BIOS file found");
|
||||
|
||||
if (!LoadHle(data_path))
|
||||
if (!LoadHle())
|
||||
throw ReicastException("Failed to initialize HLE BIOS");
|
||||
|
||||
NOTICE_LOG(BOOT, "Did not load BIOS, using reios");
|
||||
|
@ -567,7 +567,7 @@ static void dc_start_game(const char *path)
|
|||
}
|
||||
else
|
||||
{
|
||||
LoadRomFiles(data_path);
|
||||
LoadRomFiles();
|
||||
}
|
||||
if (settings.platform.system == DC_PLATFORM_DREAMCAST)
|
||||
{
|
||||
|
@ -591,7 +591,7 @@ static void dc_start_game(const char *path)
|
|||
// Content load failed. Boot the BIOS
|
||||
settings.imgread.ImagePath[0] = '\0';
|
||||
forced_bios_file = true;
|
||||
if (!LoadRomFiles(data_path))
|
||||
if (!LoadRomFiles())
|
||||
throw ReicastException("No BIOS file found");
|
||||
InitDrive();
|
||||
}
|
||||
|
@ -656,7 +656,7 @@ void* dc_run(void*)
|
|||
|
||||
sh4_cpu.Run();
|
||||
|
||||
SaveRomFiles(get_writable_data_path(DATA_PATH));
|
||||
SaveRomFiles();
|
||||
if (reset_requested)
|
||||
{
|
||||
dc_reset(false);
|
||||
|
@ -933,7 +933,7 @@ static void LoadCustom()
|
|||
if (*p == '\0')
|
||||
return;
|
||||
}
|
||||
else if (settings.platform.system == DC_PLATFORM_NAOMI || settings.platform.system == DC_PLATFORM_ATOMISWAVE)
|
||||
else
|
||||
{
|
||||
reios_id = naomi_game_id;
|
||||
}
|
||||
|
@ -951,9 +951,9 @@ void SaveSettings()
|
|||
{
|
||||
cfgSetAutoSave(false);
|
||||
cfgSaveBool("config", "Dynarec.Enabled", settings.dynarec.Enable);
|
||||
if (forced_game_cable == -1 || forced_game_cable != settings.dreamcast.cable)
|
||||
if (forced_game_cable == -1 || forced_game_cable != (int)settings.dreamcast.cable)
|
||||
cfgSaveInt("config", "Dreamcast.Cable", settings.dreamcast.cable);
|
||||
if (forced_game_region == -1 || forced_game_region != settings.dreamcast.region)
|
||||
if (forced_game_region == -1 || forced_game_region != (int)settings.dreamcast.region)
|
||||
cfgSaveInt("config", "Dreamcast.Region", settings.dreamcast.region);
|
||||
cfgSaveInt("config", "Dreamcast.Broadcast", settings.dreamcast.broadcast);
|
||||
cfgSaveBool("config", "Dreamcast.ForceWindowsCE", settings.dreamcast.ForceWindowsCE);
|
||||
|
@ -1064,7 +1064,7 @@ static void cleanup_serialize(void *data)
|
|||
free(data) ;
|
||||
}
|
||||
|
||||
static std::string get_savestate_file_path()
|
||||
static std::string get_savestate_file_path(bool writable)
|
||||
{
|
||||
std::string state_file = settings.imgread.ImagePath;
|
||||
size_t lastindex = state_file.find_last_of('/');
|
||||
|
@ -1081,7 +1081,10 @@ static std::string get_savestate_file_path()
|
|||
if (lastindex != std::string::npos)
|
||||
state_file = state_file.substr(0, lastindex);
|
||||
state_file = state_file + ".state";
|
||||
return get_writable_data_path(DATA_PATH) + state_file;
|
||||
if (writable)
|
||||
return get_writable_data_path(state_file);
|
||||
else
|
||||
return get_readonly_data_path(state_file);
|
||||
}
|
||||
|
||||
void dc_savestate()
|
||||
|
@ -1121,7 +1124,7 @@ void dc_savestate()
|
|||
return;
|
||||
}
|
||||
|
||||
filename = get_savestate_file_path();
|
||||
filename = get_savestate_file_path(true);
|
||||
f = fopen(filename.c_str(), "wb") ;
|
||||
|
||||
if ( f == NULL )
|
||||
|
@ -1150,7 +1153,7 @@ void dc_loadstate()
|
|||
|
||||
dc_stop();
|
||||
|
||||
filename = get_savestate_file_path();
|
||||
filename = get_savestate_file_path(false);
|
||||
f = fopen(filename.c_str(), "rb") ;
|
||||
|
||||
if ( f == NULL )
|
||||
|
|
|
@ -739,7 +739,7 @@ void reios_reset(u8* rom)
|
|||
// 7078 24 × 24 pixels (72 bytes) characters
|
||||
// 129 32 × 32 pixels (128 bytes) characters
|
||||
memset(pFont, 0, 536496);
|
||||
FILE *font = fopen(get_readonly_data_path(DATA_PATH "font.bin").c_str(), "rb");
|
||||
FILE *font = fopen(get_readonly_data_path("font.bin").c_str(), "rb");
|
||||
if (font == NULL)
|
||||
{
|
||||
INFO_LOG(REIOS, "font.bin not found. Using built-in font");
|
||||
|
|
|
@ -102,7 +102,7 @@ bool CustomTexture::Init()
|
|||
std::string game_id = GetGameId();
|
||||
if (game_id.length() > 0)
|
||||
{
|
||||
textures_path = get_readonly_data_path(DATA_PATH) + "textures/" + game_id + "/";
|
||||
textures_path = get_readonly_data_path("textures/" + game_id) + "/";
|
||||
|
||||
DIR *dir = opendir(textures_path.c_str());
|
||||
if (dir != NULL)
|
||||
|
@ -156,7 +156,7 @@ void CustomTexture::LoadCustomTextureAsync(BaseTextureCacheData *texture_data)
|
|||
|
||||
void CustomTexture::DumpTexture(u32 hash, int w, int h, TextureType textype, void *src_buffer)
|
||||
{
|
||||
std::string base_dump_dir = get_writable_data_path(DATA_PATH "texdump/");
|
||||
std::string base_dump_dir = get_writable_data_path("texdump/");
|
||||
if (!file_exists(base_dump_dir))
|
||||
make_directory(base_dump_dir);
|
||||
std::string game_id = GetGameId();
|
||||
|
|
|
@ -1674,8 +1674,10 @@ static void systemdir_selected_callback(bool cancelled, std::string selection)
|
|||
{
|
||||
if (!cancelled)
|
||||
{
|
||||
selection += "/";
|
||||
set_user_config_dir(selection);
|
||||
set_user_data_dir(selection);
|
||||
add_system_data_dir(selection);
|
||||
set_user_data_dir(selection + "data/");
|
||||
if (cfgOpen())
|
||||
{
|
||||
LoadSettings(false);
|
||||
|
|
|
@ -150,7 +150,7 @@ u8 *loadOSDButtons(int &width, int &height)
|
|||
{
|
||||
int n;
|
||||
stbi_set_flip_vertically_on_load(1);
|
||||
u8 *image_data = stbi_load(get_readonly_data_path(DATA_PATH "buttons.png").c_str(), &width, &height, &n, STBI_rgb_alpha);
|
||||
u8 *image_data = stbi_load(get_readonly_data_path("buttons.png").c_str(), &width, &height, &n, STBI_rgb_alpha);
|
||||
if (image_data == nullptr)
|
||||
{
|
||||
if (DefaultOSDButtons.empty())
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
VulkanContext *VulkanContext::contextInstance;
|
||||
|
||||
static const char *PipelineCacheFileName = DATA_PATH "vulkan_pipeline.cache";
|
||||
static const char *PipelineCacheFileName = "vulkan_pipeline.cache";
|
||||
|
||||
#ifndef __ANDROID__
|
||||
VKAPI_ATTR static VkBool32 VKAPI_CALL debugUtilsMessengerCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes,
|
||||
|
@ -450,7 +450,7 @@ bool VulkanContext::InitDevice()
|
|||
10000, ARRAY_SIZE(pool_sizes), pool_sizes));
|
||||
|
||||
|
||||
std::string cachePath = get_writable_data_path(PipelineCacheFileName);
|
||||
std::string cachePath = get_readonly_data_path(PipelineCacheFileName);
|
||||
FILE *f = fopen(cachePath.c_str(), "rb");
|
||||
if (f == nullptr)
|
||||
pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo());
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
std::string user_config_dir;
|
||||
std::string user_data_dir;
|
||||
std::vector<std::string> system_config_dirs;
|
||||
std::vector<std::string> system_data_dirs;
|
||||
static std::string user_config_dir;
|
||||
static std::string user_data_dir;
|
||||
static std::vector<std::string> system_config_dirs;
|
||||
static std::vector<std::string> system_data_dirs;
|
||||
|
||||
bool file_exists(const std::string& filename)
|
||||
{
|
||||
|
@ -55,24 +55,20 @@ std::string get_writable_config_path(const std::string& filename)
|
|||
/* Only stuff in the user_config_dir is supposed to be writable,
|
||||
* so we always return that.
|
||||
*/
|
||||
return (user_config_dir + filename);
|
||||
return user_config_dir + filename;
|
||||
}
|
||||
|
||||
std::string get_readonly_config_path(const std::string& filename)
|
||||
{
|
||||
std::string user_filepath = get_writable_config_path(filename);
|
||||
if(file_exists(user_filepath))
|
||||
{
|
||||
if (file_exists(user_filepath))
|
||||
return user_filepath;
|
||||
}
|
||||
|
||||
std::string filepath;
|
||||
for (size_t i = 0; i < system_config_dirs.size(); i++) {
|
||||
filepath = system_config_dirs[i] + filename;
|
||||
for (const auto& config_dir : system_config_dirs)
|
||||
{
|
||||
std::string filepath = config_dir + filename;
|
||||
if (file_exists(filepath))
|
||||
{
|
||||
return filepath;
|
||||
}
|
||||
}
|
||||
|
||||
// Not found, so we return the user variant
|
||||
|
@ -84,31 +80,31 @@ std::string get_writable_data_path(const std::string& filename)
|
|||
/* Only stuff in the user_data_dir is supposed to be writable,
|
||||
* so we always return that.
|
||||
*/
|
||||
return (user_data_dir + filename);
|
||||
return user_data_dir + filename;
|
||||
}
|
||||
|
||||
std::string get_readonly_data_path(const std::string& filename)
|
||||
{
|
||||
std::string user_filepath = get_writable_data_path(filename);
|
||||
if(file_exists(user_filepath))
|
||||
{
|
||||
if (file_exists(user_filepath))
|
||||
return user_filepath;
|
||||
}
|
||||
|
||||
std::string filepath;
|
||||
for (size_t i = 0; i < system_data_dirs.size(); i++) {
|
||||
filepath = system_data_dirs[i] + filename;
|
||||
for (const auto& data_dir : system_data_dirs)
|
||||
{
|
||||
std::string filepath = data_dir + filename;
|
||||
if (file_exists(filepath))
|
||||
{
|
||||
return filepath;
|
||||
}
|
||||
}
|
||||
// Try the game directory
|
||||
std::string filepath = get_game_dir() + filename;
|
||||
if (file_exists(filepath))
|
||||
return filepath;
|
||||
|
||||
// Not found, so we return the user variant
|
||||
return user_filepath;
|
||||
}
|
||||
|
||||
static size_t get_last_slash_pos(const std::string& path)
|
||||
size_t get_last_slash_pos(const std::string& path)
|
||||
{
|
||||
size_t lastindex = path.find_last_of('/');
|
||||
#ifdef _WIN32
|
||||
|
@ -127,7 +123,7 @@ std::string get_game_save_prefix()
|
|||
size_t lastindex = get_last_slash_pos(save_file);
|
||||
if (lastindex != std::string::npos)
|
||||
save_file = save_file.substr(lastindex + 1);
|
||||
return get_writable_data_path(DATA_PATH) + save_file;
|
||||
return get_writable_data_path(save_file);
|
||||
}
|
||||
|
||||
std::string get_game_basename()
|
||||
|
|
|
@ -49,12 +49,6 @@ public :
|
|||
void Wait(); //Wait for signal , then reset[if auto]
|
||||
};
|
||||
|
||||
#if !defined(TARGET_IPHONE)
|
||||
#define DATA_PATH "/data/"
|
||||
#else
|
||||
#define DATA_PATH "/"
|
||||
#endif
|
||||
|
||||
//Set the path !
|
||||
void set_user_config_dir(const std::string& dir);
|
||||
void set_user_data_dir(const std::string& dir);
|
||||
|
@ -72,6 +66,7 @@ bool make_directory(const std::string& path);
|
|||
std::string get_game_save_prefix();
|
||||
std::string get_game_basename();
|
||||
std::string get_game_dir();
|
||||
size_t get_last_slash_pos(const std::string& path);
|
||||
|
||||
bool mem_region_lock(void *start, std::size_t len);
|
||||
bool mem_region_unlock(void *start, std::size_t len);
|
||||
|
|
|
@ -192,11 +192,16 @@ LONG ExeptionHandler(EXCEPTION_POINTERS *ExceptionInfo)
|
|||
void SetupPath()
|
||||
{
|
||||
char fname[512];
|
||||
GetModuleFileName(0,fname,512);
|
||||
GetModuleFileName(0, fname, sizeof(fname));
|
||||
std::string fn = std::string(fname);
|
||||
fn=fn.substr(0,fn.find_last_of('\\'));
|
||||
size_t pos = get_last_slash_pos(fn);
|
||||
if (pos != std::string::npos)
|
||||
fn = fn.substr(0, pos) + "\\";
|
||||
else
|
||||
fn = ".\\";
|
||||
set_user_config_dir(fn);
|
||||
set_user_data_dir(fn);
|
||||
add_system_data_dir(fn);
|
||||
set_user_data_dir(fn + "data\\");
|
||||
}
|
||||
|
||||
static Win32KeyboardDevice keyboard(0);
|
||||
|
|
|
@ -195,13 +195,22 @@ JNIEXPORT jstring JNICALL Java_com_reicast_emulator_emu_JNIdc_initEnvironment(JN
|
|||
saveAndroidSettingsMid = env->GetMethodID(env->GetObjectClass(emulator), "SaveAndroidSettings", "(Ljava/lang/String;)V");
|
||||
}
|
||||
// Set home directory based on User config
|
||||
const char* path = homeDirectory != NULL ? env->GetStringUTFChars(homeDirectory, 0) : "";
|
||||
set_user_config_dir(path);
|
||||
set_user_data_dir(path);
|
||||
if (homeDirectory != NULL)
|
||||
{
|
||||
const char *jchar = env->GetStringUTFChars(homeDirectory, 0);
|
||||
std::string path = jchar;
|
||||
if (!path.empty())
|
||||
{
|
||||
if (path.back() != '/')
|
||||
path += '/';
|
||||
set_user_config_dir(path);
|
||||
add_system_data_dir(path);
|
||||
set_user_data_dir(path + "data/");
|
||||
}
|
||||
env->ReleaseStringUTFChars(homeDirectory, jchar);
|
||||
}
|
||||
INFO_LOG(BOOT, "Config dir is: %s", get_writable_config_path("").c_str());
|
||||
INFO_LOG(BOOT, "Data dir is: %s", get_writable_data_path("").c_str());
|
||||
if (homeDirectory != NULL)
|
||||
env->ReleaseStringUTFChars(homeDirectory, path);
|
||||
|
||||
if (first_init)
|
||||
{
|
||||
|
|
|
@ -134,27 +134,32 @@ extern "C" void emu_gles_init(int width, int height) {
|
|||
char *home = getenv("HOME");
|
||||
if (home != NULL)
|
||||
{
|
||||
std::string config_dir = std::string(home) + "/.reicast";
|
||||
std::string config_dir = std::string(home) + "/.reicast/";
|
||||
if (!file_exists(config_dir))
|
||||
config_dir = std::string(home) + "/.flycast/";
|
||||
int instanceNumber = (int)[[NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.reicast.Flycast"] count];
|
||||
if (instanceNumber > 1){
|
||||
config_dir += "/" + std::to_string(instanceNumber);
|
||||
config_dir += std::to_string(instanceNumber) + "/";
|
||||
[[NSApp dockTile] setBadgeLabel:@(instanceNumber).stringValue];
|
||||
}
|
||||
mkdir(config_dir.c_str(), 0755); // create the directory if missing
|
||||
set_user_config_dir(config_dir);
|
||||
add_system_data_dir(config_dir);
|
||||
config_dir += "data/";
|
||||
mkdir(config_dir.c_str(), 0755);
|
||||
set_user_data_dir(config_dir);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_user_config_dir(".");
|
||||
set_user_data_dir(".");
|
||||
set_user_config_dir("./");
|
||||
set_user_data_dir("./");
|
||||
}
|
||||
// Add bundle resources path
|
||||
CFBundleRef mainBundle = CFBundleGetMainBundle();
|
||||
CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
|
||||
char path[PATH_MAX];
|
||||
if (CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)path, PATH_MAX))
|
||||
add_system_data_dir(std::string(path));
|
||||
add_system_data_dir(std::string(path) + "/");
|
||||
CFRelease(resourcesURL);
|
||||
CFRelease(mainBundle);
|
||||
|
||||
|
|
Loading…
Reference in New Issue