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
;
43 bool crashing
= false;
45 void fatal_signal_handler(int sig
)
48 write(2, "Double fault, exiting!\n", 23);
53 write(2, "Caught fatal signal!\n", 21);
54 if(lsnes_instance
.mlogic
) emerg_save_movie(lsnes_instance
.mlogic
->get_mfile(),
55 lsnes_instance
.mlogic
->get_rrdata());
60 void terminate_handler()
63 write(2, "Double fault, exiting!\n", 23);
67 write(2, "Terminating abnormally!\n", 24);
68 if(lsnes_instance
.mlogic
) emerg_save_movie(lsnes_instance
.mlogic
->get_mfile(),
69 lsnes_instance
.mlogic
->get_rrdata());
70 std::cerr
<< "Exiting on fatal error" << std::endl
;
74 //% is intentionally missing.
75 const char* allowed_filename_chars
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
76 "^&'@{}[],$?!-#().+~_";
79 std::string
safe_filename(const std::string
& str
)
82 for(size_t i
= 0; i
< str
.length(); i
++) {
83 unsigned char ch
= static_cast<unsigned char>(str
[i
]);
84 if(strchr(allowed_filename_chars
, ch
))
87 o
<< "%" << hex::to8(ch
);
92 void fatal_error() throw()
94 platform::fatal_error();
95 std::cout
<< "PANIC: Fatal error, can't continue." << std::endl
;
99 std::string
get_config_path() throw(std::bad_alloc
)
103 if((tmp
= getenv("APPDATA"))) {
104 //If $APPDATA exists, it is the base directory
106 } else if((tmp
= getenv("XDG_CONFIG_HOME"))) {
107 //If $XDG_CONFIG_HOME exists, it is the base directory
109 } else if((tmp
= getenv("HOME"))) {
110 //If $HOME exists, the base directory is '.config' there.
111 basedir
= std::string(tmp
) + "/.config";
113 //Last chance: Return current directory.
116 //Try to create 'lsnes'. If it exists (or is created) and is directory, great. Otherwise error out.
117 std::string lsnes_path
= basedir
+ "/lsnes";
118 if(!directory::ensure_exists(lsnes_path
)) {
119 messages
<< "FATAL: Can't create configuration directory '" << lsnes_path
<< "'" << std::endl
;
122 //Yes, this is racy, but portability is more important than being absolutely correct...
123 std::string tfile
= lsnes_path
+ "/test";
124 remove(tfile
.c_str());
126 if(!(x
= fopen(tfile
.c_str(), "w+"))) {
127 messages
<< "FATAL: Configuration directory '" << lsnes_path
<< "' is not writable" << std::endl
;
131 remove(tfile
.c_str());
137 if(lsnes_instance
.mlogic
) emerg_save_movie(lsnes_instance
.mlogic
->get_mfile(),
138 lsnes_instance
.mlogic
->get_rrdata());
139 messages
<< "FATAL: Out of memory!" << std::endl
;
143 uint32_t gcd(uint32_t a
, uint32_t b
) throw()
148 return gcd(b
, a
% b
);
151 std::string
format_address(void* addr
)
153 return hex::to((uint64_t)addr
);
156 bool in_global_ctors()
158 return !reached_main_flag
;
163 notify_new_core
.errors_to(&messages
.getstream());
165 new_core_flag
= false; //We'll process the static cores anyway.
166 reached_main_flag
= true;
167 lsnes_instance
.command
->set_oom_panic(OOM_panic
);
168 lsnes_instance
.command
->set_output(platform::out());
169 loadlib::module::run_initializers();
170 std::set_terminate(terminate_handler
);
172 signal(SIGHUP
, fatal_signal_handler
);
175 signal(SIGINT
, fatal_signal_handler
);
178 signal(SIGQUIT
, fatal_signal_handler
);
181 signal(SIGILL
, fatal_signal_handler
);
184 signal(SIGABRT
, fatal_signal_handler
);
187 signal(SIGSEGV
, fatal_signal_handler
);
190 signal(SIGFPE
, fatal_signal_handler
);
193 signal(SIGPIPE
, fatal_signal_handler
);
196 signal(SIGBUS
, fatal_signal_handler
);
199 signal(SIGTRAP
, fatal_signal_handler
);
202 signal(SIGTERM
, fatal_signal_handler
);
206 std::string
mangle_name(const std::string
& orig
)
208 std::ostringstream out
;
215 out
<< "\xE2\x8F\xBF";
217 out
<< "\xE2\x8B\xBF";
224 std::string
get_temp_file()
226 #if !defined(_WIN32) && !defined(_WIN64)
228 strcpy(tname
, "/tmp/lsnestmp_XXXXXX");
229 int h
= mkstemp(tname
);
231 throw std::runtime_error("Failed to get new tempfile name");
237 if(!GetTempPathA(512, tpath
))
238 throw std::runtime_error("Failed to get new tempfile name");
239 if(!GetTempFileNameA(tpath
, "lsn", 0, tname
))
240 throw std::runtime_error("Failed to get new tempfile name");