2013-12-19 17:10:14 +00:00
|
|
|
#include "types.h"
|
2019-04-27 12:08:43 +00:00
|
|
|
#include "stdclass.h"
|
2020-03-28 16:58:01 +00:00
|
|
|
|
2020-04-02 16:48:23 +00:00
|
|
|
#include <chrono>
|
2020-03-28 16:58:01 +00:00
|
|
|
#include <cstring>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <vector>
|
|
|
|
|
2020-04-22 21:27:57 +00:00
|
|
|
#ifdef _WIN32
|
2020-03-28 16:58:01 +00:00
|
|
|
#include <algorithm>
|
2015-08-23 00:21:53 +00:00
|
|
|
#include <io.h>
|
2019-04-12 20:59:39 +00:00
|
|
|
#include <direct.h>
|
2015-08-23 00:21:53 +00:00
|
|
|
#define access _access
|
2020-04-22 21:27:57 +00:00
|
|
|
#ifndef R_OK
|
|
|
|
#define R_OK 4
|
|
|
|
#endif
|
|
|
|
#define mkdir(dir, mode) _mkdir(dir)
|
2015-08-23 00:21:53 +00:00
|
|
|
#else
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
2020-11-26 15:45:57 +00:00
|
|
|
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;
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2020-03-29 17:29:14 +00:00
|
|
|
bool file_exists(const std::string& filename)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
2015-08-23 00:21:53 +00:00
|
|
|
return (access(filename.c_str(), R_OK) == 0);
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
2020-03-29 17:29:14 +00:00
|
|
|
void set_user_config_dir(const std::string& dir)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
2015-08-22 19:49:12 +00:00
|
|
|
user_config_dir = dir;
|
|
|
|
}
|
|
|
|
|
2020-03-29 17:29:14 +00:00
|
|
|
void set_user_data_dir(const std::string& dir)
|
2015-08-22 19:49:12 +00:00
|
|
|
{
|
|
|
|
user_data_dir = dir;
|
|
|
|
}
|
|
|
|
|
2020-03-29 17:29:14 +00:00
|
|
|
void add_system_config_dir(const std::string& dir)
|
2015-08-22 19:49:12 +00:00
|
|
|
{
|
|
|
|
system_config_dirs.push_back(dir);
|
|
|
|
}
|
|
|
|
|
2020-03-29 17:29:14 +00:00
|
|
|
void add_system_data_dir(const std::string& dir)
|
2015-08-22 19:49:12 +00:00
|
|
|
{
|
|
|
|
system_data_dirs.push_back(dir);
|
|
|
|
}
|
|
|
|
|
2020-03-29 17:29:14 +00:00
|
|
|
std::string get_writable_config_path(const std::string& filename)
|
2015-08-22 19:49:12 +00:00
|
|
|
{
|
2015-08-28 23:28:51 +00:00
|
|
|
/* Only stuff in the user_config_dir is supposed to be writable,
|
|
|
|
* so we always return that.
|
|
|
|
*/
|
2020-11-26 15:45:57 +00:00
|
|
|
return user_config_dir + filename;
|
2015-08-28 23:28:51 +00:00
|
|
|
}
|
|
|
|
|
2020-03-29 17:29:14 +00:00
|
|
|
std::string get_readonly_config_path(const std::string& filename)
|
2015-08-28 23:28:51 +00:00
|
|
|
{
|
2020-03-29 17:29:14 +00:00
|
|
|
std::string user_filepath = get_writable_config_path(filename);
|
2020-11-26 15:45:57 +00:00
|
|
|
if (file_exists(user_filepath))
|
2015-08-28 23:28:51 +00:00
|
|
|
return user_filepath;
|
2015-08-22 19:49:12 +00:00
|
|
|
|
2020-11-26 15:45:57 +00:00
|
|
|
for (const auto& config_dir : system_config_dirs)
|
|
|
|
{
|
|
|
|
std::string filepath = config_dir + filename;
|
2015-08-22 19:49:12 +00:00
|
|
|
if (file_exists(filepath))
|
|
|
|
return filepath;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Not found, so we return the user variant
|
2015-08-28 23:28:51 +00:00
|
|
|
return user_filepath;
|
2015-08-22 19:49:12 +00:00
|
|
|
}
|
|
|
|
|
2020-03-29 17:29:14 +00:00
|
|
|
std::string get_writable_data_path(const std::string& filename)
|
2015-08-22 19:49:12 +00:00
|
|
|
{
|
2015-08-28 23:28:51 +00:00
|
|
|
/* Only stuff in the user_data_dir is supposed to be writable,
|
|
|
|
* so we always return that.
|
|
|
|
*/
|
2020-11-26 15:45:57 +00:00
|
|
|
return user_data_dir + filename;
|
2015-08-28 23:28:51 +00:00
|
|
|
}
|
|
|
|
|
2020-03-29 17:29:14 +00:00
|
|
|
std::string get_readonly_data_path(const std::string& filename)
|
2015-08-28 23:28:51 +00:00
|
|
|
{
|
2020-03-29 17:29:14 +00:00
|
|
|
std::string user_filepath = get_writable_data_path(filename);
|
2020-11-26 15:45:57 +00:00
|
|
|
if (file_exists(user_filepath))
|
2015-08-28 23:28:51 +00:00
|
|
|
return user_filepath;
|
2015-08-22 19:49:12 +00:00
|
|
|
|
2020-11-26 15:45:57 +00:00
|
|
|
for (const auto& data_dir : system_data_dirs)
|
|
|
|
{
|
|
|
|
std::string filepath = data_dir + filename;
|
2015-08-22 19:49:12 +00:00
|
|
|
if (file_exists(filepath))
|
|
|
|
return filepath;
|
|
|
|
}
|
2020-11-26 15:45:57 +00:00
|
|
|
// Try the game directory
|
|
|
|
std::string filepath = get_game_dir() + filename;
|
|
|
|
if (file_exists(filepath))
|
|
|
|
return filepath;
|
2015-08-22 19:49:12 +00:00
|
|
|
|
|
|
|
// Not found, so we return the user variant
|
2015-08-28 23:28:51 +00:00
|
|
|
return user_filepath;
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
2020-11-26 15:45:57 +00:00
|
|
|
size_t get_last_slash_pos(const std::string& path)
|
2018-11-12 16:54:38 +00:00
|
|
|
{
|
2020-04-30 10:49:56 +00:00
|
|
|
size_t lastindex = path.find_last_of('/');
|
2018-11-12 16:54:38 +00:00
|
|
|
#ifdef _WIN32
|
2020-04-30 10:49:56 +00:00
|
|
|
size_t lastindex2 = path.find_last_of('\\');
|
|
|
|
if (lastindex == std::string::npos)
|
|
|
|
lastindex = lastindex2;
|
|
|
|
else if (lastindex2 != std::string::npos)
|
|
|
|
lastindex = std::max(lastindex, lastindex2);
|
2018-11-12 16:54:38 +00:00
|
|
|
#endif
|
2020-04-30 10:49:56 +00:00
|
|
|
return lastindex;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string get_game_save_prefix()
|
|
|
|
{
|
|
|
|
std::string save_file = settings.imgread.ImagePath;
|
|
|
|
size_t lastindex = get_last_slash_pos(save_file);
|
2020-03-29 18:58:49 +00:00
|
|
|
if (lastindex != std::string::npos)
|
2018-11-12 16:54:38 +00:00
|
|
|
save_file = save_file.substr(lastindex + 1);
|
2020-11-26 15:45:57 +00:00
|
|
|
return get_writable_data_path(save_file);
|
2018-11-12 16:54:38 +00:00
|
|
|
}
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2020-03-29 17:29:14 +00:00
|
|
|
std::string get_game_basename()
|
2018-11-17 11:29:59 +00:00
|
|
|
{
|
2020-03-29 17:29:14 +00:00
|
|
|
std::string game_dir = settings.imgread.ImagePath;
|
2019-09-07 12:37:39 +00:00
|
|
|
size_t lastindex = game_dir.find_last_of('.');
|
2020-03-29 18:58:49 +00:00
|
|
|
if (lastindex != std::string::npos)
|
2018-11-17 11:29:59 +00:00
|
|
|
game_dir = game_dir.substr(0, lastindex);
|
|
|
|
return game_dir;
|
|
|
|
}
|
|
|
|
|
2020-03-29 17:29:14 +00:00
|
|
|
std::string get_game_dir()
|
2018-11-23 17:46:21 +00:00
|
|
|
{
|
2020-03-29 17:29:14 +00:00
|
|
|
std::string game_dir = settings.imgread.ImagePath;
|
2020-04-30 10:49:56 +00:00
|
|
|
size_t lastindex = get_last_slash_pos(game_dir);
|
2020-03-29 18:58:49 +00:00
|
|
|
if (lastindex != std::string::npos)
|
2018-11-23 17:46:21 +00:00
|
|
|
game_dir = game_dir.substr(0, lastindex + 1);
|
2020-04-30 10:49:56 +00:00
|
|
|
else
|
|
|
|
game_dir = "./";
|
2018-11-23 17:46:21 +00:00
|
|
|
return game_dir;
|
|
|
|
}
|
|
|
|
|
2020-03-29 17:29:14 +00:00
|
|
|
bool make_directory(const std::string& path)
|
2019-02-13 19:29:49 +00:00
|
|
|
{
|
2019-03-30 18:26:05 +00:00
|
|
|
return mkdir(path.c_str(), 0755) == 0;
|
2019-02-13 19:29:49 +00:00
|
|
|
}
|
|
|
|
|
2020-04-04 08:53:19 +00:00
|
|
|
void cThread::Start()
|
|
|
|
{
|
|
|
|
verify(!thread.joinable());
|
|
|
|
thread = std::thread(entry, param);
|
2019-04-27 12:08:43 +00:00
|
|
|
}
|
2020-04-04 08:53:19 +00:00
|
|
|
|
|
|
|
void cThread::WaitToEnd()
|
|
|
|
{
|
2020-05-08 16:41:36 +00:00
|
|
|
if (thread.joinable() && thread.get_id() != std::this_thread::get_id())
|
2020-04-04 08:53:19 +00:00
|
|
|
thread.join();
|
2019-04-27 12:08:43 +00:00
|
|
|
}
|
|
|
|
|
2020-04-02 16:48:23 +00:00
|
|
|
cResetEvent::cResetEvent() : state(false)
|
|
|
|
{
|
2019-04-27 12:08:43 +00:00
|
|
|
|
|
|
|
}
|
2020-04-02 16:48:23 +00:00
|
|
|
|
2019-04-27 12:08:43 +00:00
|
|
|
cResetEvent::~cResetEvent()
|
|
|
|
{
|
2020-04-02 16:48:23 +00:00
|
|
|
|
2019-04-27 12:08:43 +00:00
|
|
|
}
|
2020-04-02 16:48:23 +00:00
|
|
|
|
2019-04-27 12:08:43 +00:00
|
|
|
void cResetEvent::Set()//Signal
|
|
|
|
{
|
2020-04-02 16:48:23 +00:00
|
|
|
std::lock_guard<std::mutex> lock(mutx);
|
|
|
|
|
|
|
|
state = true;
|
|
|
|
cond.notify_one();
|
2019-04-27 12:08:43 +00:00
|
|
|
}
|
2020-04-02 16:48:23 +00:00
|
|
|
|
|
|
|
void cResetEvent::Reset()
|
2019-04-27 12:08:43 +00:00
|
|
|
{
|
2020-04-02 16:48:23 +00:00
|
|
|
std::lock_guard<std::mutex> lock(mutx);
|
|
|
|
|
|
|
|
state = false;
|
2019-04-27 12:08:43 +00:00
|
|
|
}
|
2020-04-02 16:48:23 +00:00
|
|
|
|
|
|
|
bool cResetEvent::Wait(u32 msec)
|
2019-04-27 12:08:43 +00:00
|
|
|
{
|
2020-05-01 11:06:07 +00:00
|
|
|
std::unique_lock<std::mutex> lock(mutx);
|
2019-04-27 12:08:43 +00:00
|
|
|
|
2020-05-01 11:06:07 +00:00
|
|
|
if (!state)
|
|
|
|
cond.wait_for(lock, std::chrono::milliseconds(msec));
|
2020-04-02 16:48:23 +00:00
|
|
|
|
2020-05-01 11:06:07 +00:00
|
|
|
bool rc = state;
|
2020-04-02 16:48:23 +00:00
|
|
|
state = false;
|
|
|
|
|
|
|
|
return rc;
|
2019-04-27 12:08:43 +00:00
|
|
|
}
|
2020-04-02 16:48:23 +00:00
|
|
|
|
|
|
|
void cResetEvent::Wait()
|
2019-04-27 12:08:43 +00:00
|
|
|
{
|
2020-04-02 16:48:23 +00:00
|
|
|
std::unique_lock<std::mutex> lock(mutx);
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2020-04-02 16:48:23 +00:00
|
|
|
if (!state) {
|
|
|
|
cond.wait(lock);
|
|
|
|
}
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2020-04-02 16:48:23 +00:00
|
|
|
state = false;
|
|
|
|
}
|