3 #include "core/command.hpp"
4 #include "core/controllerframe.hpp"
5 #include "core/dispatch.hpp"
6 #include "core/instance.hpp"
7 #include "core/messages.hpp"
8 #include "core/misc.hpp"
9 #include "core/movie.hpp"
10 #include "core/window.hpp"
11 #include "library/crandom.hpp"
12 #include "library/directory.hpp"
13 #include "library/hex.hpp"
14 #include "library/loadlib.hpp"
15 #include "library/string.hpp"
31 #include <boost/filesystem.hpp>
32 #if defined(_WIN32) || defined(_WIN64)
36 #ifdef USE_LIBGCRYPT_SHA256
42 bool reached_main_flag
;
44 void fatal_signal_handler(int sig
)
46 write(2, "Caught fatal signal!\n", 21);
47 if(lsnes_instance
.mlogic
) emerg_save_movie(lsnes_instance
.mlogic
->get_mfile(),
48 lsnes_instance
.mlogic
->get_rrdata());
53 void terminate_handler()
55 write(2, "Terminating abnormally!\n", 24);
56 if(lsnes_instance
.mlogic
) emerg_save_movie(lsnes_instance
.mlogic
->get_mfile(),
57 lsnes_instance
.mlogic
->get_rrdata());
58 std::cerr
<< "Exiting on fatal error" << std::endl
;
62 //% is intentionally missing.
63 const char* allowed_filename_chars
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
64 "^&'@{}[],$?!-#().+~_";
67 std::string
safe_filename(const std::string
& str
)
70 for(size_t i
= 0; i
< str
.length(); i
++) {
71 unsigned char ch
= static_cast<unsigned char>(str
[i
]);
72 if(strchr(allowed_filename_chars
, ch
))
75 o
<< "%" << hex::to8(ch
);
80 void fatal_error() throw()
82 platform::fatal_error();
83 std::cout
<< "PANIC: Fatal error, can't continue." << std::endl
;
87 std::string
get_config_path() throw(std::bad_alloc
)
91 if((tmp
= getenv("APPDATA"))) {
92 //If $APPDATA exists, it is the base directory
94 } else if((tmp
= getenv("XDG_CONFIG_HOME"))) {
95 //If $XDG_CONFIG_HOME exists, it is the base directory
97 } else if((tmp
= getenv("HOME"))) {
98 //If $HOME exists, the base directory is '.config' there.
99 basedir
= std::string(tmp
) + "/.config";
101 //Last chance: Return current directory.
104 //Try to create 'lsnes'. If it exists (or is created) and is directory, great. Otherwise error out.
105 std::string lsnes_path
= basedir
+ "/lsnes";
106 if(!directory::ensure_exists(lsnes_path
)) {
107 messages
<< "FATAL: Can't create configuration directory '" << lsnes_path
<< "'" << std::endl
;
110 //Yes, this is racy, but portability is more important than being absolutely correct...
111 std::string tfile
= lsnes_path
+ "/test";
112 remove(tfile
.c_str());
114 if(!(x
= fopen(tfile
.c_str(), "w+"))) {
115 messages
<< "FATAL: Configuration directory '" << lsnes_path
<< "' is not writable" << std::endl
;
119 remove(tfile
.c_str());
125 if(lsnes_instance
.mlogic
) emerg_save_movie(lsnes_instance
.mlogic
->get_mfile(),
126 lsnes_instance
.mlogic
->get_rrdata());
127 messages
<< "FATAL: Out of memory!" << std::endl
;
131 uint32_t gcd(uint32_t a
, uint32_t b
) throw()
136 return gcd(b
, a
% b
);
139 std::string
format_address(void* addr
)
141 return hex::to((uint64_t)addr
);
144 bool in_global_ctors()
146 return !reached_main_flag
;
151 notify_new_core
.errors_to(&messages
.getstream());
153 new_core_flag
= false; //We'll process the static cores anyway.
154 reached_main_flag
= true;
155 lsnes_instance
.command
->set_oom_panic(OOM_panic
);
156 lsnes_instance
.command
->set_output(platform::out());
157 loadlib::module::run_initializers();
158 std::set_terminate(terminate_handler
);
160 signal(SIGHUP
, fatal_signal_handler
);
163 signal(SIGINT
, fatal_signal_handler
);
166 signal(SIGQUIT
, fatal_signal_handler
);
169 signal(SIGILL
, fatal_signal_handler
);
172 signal(SIGABRT
, fatal_signal_handler
);
175 signal(SIGSEGV
, fatal_signal_handler
);
178 signal(SIGFPE
, fatal_signal_handler
);
181 signal(SIGPIPE
, fatal_signal_handler
);
184 signal(SIGBUS
, fatal_signal_handler
);
187 signal(SIGTRAP
, fatal_signal_handler
);
190 signal(SIGTERM
, fatal_signal_handler
);
194 std::string
mangle_name(const std::string
& orig
)
196 std::ostringstream out
;
203 out
<< "\xE2\x8F\xBF";
205 out
<< "\xE2\x8B\xBF";
212 std::string
get_temp_file()
214 #if !defined(_WIN32) && !defined(_WIN64)
216 strcpy(tname
, "/tmp/lsnestmp_XXXXXX");
217 int h
= mkstemp(tname
);
219 throw std::runtime_error("Failed to get new tempfile name");
225 if(!GetTempPathA(512, tpath
))
226 throw std::runtime_error("Failed to get new tempfile name");
227 if(!GetTempFileNameA(tpath
, "lsn", 0, tname
))
228 throw std::runtime_error("Failed to get new tempfile name");