3 #include "core/memorymanip.hpp"
4 #include "core/misc.hpp"
5 #include "core/rom.hpp"
6 #include "core/threaddebug.hpp"
7 #include "core/window.hpp"
8 #include "library/sha256.hpp"
20 #include <boost/filesystem.hpp>
25 uint64_t rcounter
= 0;
26 bool reached_main_flag
;
28 std::string
get_random_hexstring_64(size_t index
)
30 std::ostringstream str
;
31 str
<< rseed
<< " " << time(NULL
) << " " << (rcounter
++) << " " << index
;
32 std::string s
= str
.str();
35 std::copy(s
.begin(), s
.end(), x
.begin());
36 return sha256::hash(reinterpret_cast<uint8_t*>(&x
[0]), x
.size());
39 std::string
collect_identifying_information()
41 //TODO: Collect as much identifying information as possible.
42 std::ostringstream str
;
43 time_t told
= time(NULL
);
53 str
<< (loops
- base
) << " ";
62 std::string
get_random_hexstring(size_t length
) throw(std::bad_alloc
)
65 for(size_t i
= 0; i
< length
; i
+= 64)
66 out
= out
+ get_random_hexstring_64(i
);
67 return out
.substr(0, length
);
70 void set_random_seed(const std::string
& seed
) throw(std::bad_alloc
)
72 std::ostringstream str
;
73 str
<< seed
.length() << " " << seed
;
77 void set_random_seed() throw(std::bad_alloc
)
79 //Try /dev/urandom first.
81 std::ifstream
r("/dev/urandom", std::ios::binary
);
85 std::string
s(buf
, 64);
91 std::ostringstream str
;
92 str
<< collect_identifying_information() << " " << time(NULL
);
93 set_random_seed(str
.str());
97 struct loaded_rom
load_rom_from_commandline(std::vector
<std::string
> cmdline
) throw(std::bad_alloc
,
102 f
= rom_files(cmdline
);
103 f
.resolve_relative();
104 } catch(std::bad_alloc
& e
) {
106 } catch(std::exception
& e
) {
107 throw std::runtime_error(std::string("Can't resolve ROM files: ") + e
.what());
109 messages
<< "ROM type: " << gtype::tostring(f
.rtype
, f
.region
) << std::endl
;
110 if(f
.rom
!= "") messages
<< name_subrom(f
.rtype
, 0) << " file: '" << f
.rom
<< "'" << std::endl
;
111 if(f
.rom_xml
!= "") messages
<< name_subrom(f
.rtype
, 1) << " file: '" << f
.rom_xml
<< "'"
113 if(f
.slota
!= "") messages
<< name_subrom(f
.rtype
, 2) << " file: '" << f
.slota
<< "'" << std::endl
;
114 if(f
.slota_xml
!= "") messages
<< name_subrom(f
.rtype
, 3) << " file: '" << f
.slota_xml
<< "'"
116 if(f
.slotb
!= "") messages
<< name_subrom(f
.rtype
, 4) << " file: '" << f
.slotb
<< "'" << std::endl
;
117 if(f
.slotb_xml
!= "") messages
<< name_subrom(f
.rtype
, 5) << " file: '" << f
.slotb_xml
<< "'"
124 } catch(std::bad_alloc
& e
) {
126 } catch(std::exception
& e
) {
127 throw std::runtime_error(std::string("Can't load ROM: ") + e
.what());
130 std::string not_present
= "N/A";
131 if(r
.rom
.valid
) messages
<< name_subrom(f
.rtype
, 0) << " hash: " << r
.rom
.sha256
<< std::endl
;
132 if(r
.rom_xml
.valid
) messages
<< name_subrom(f
.rtype
, 1) << " hash: " << r
.rom_xml
.sha256
<< std::endl
;
133 if(r
.slota
.valid
) messages
<< name_subrom(f
.rtype
, 2) << " hash: " << r
.slota
.sha256
<< std::endl
;
134 if(r
.slota_xml
.valid
) messages
<< name_subrom(f
.rtype
, 3) << " hash: " << r
.slota_xml
.sha256
136 if(r
.slotb
.valid
) messages
<< name_subrom(f
.rtype
, 4) << " hash: " << r
.slotb
.sha256
<< std::endl
;
137 if(r
.slotb_xml
.valid
) messages
<< name_subrom(f
.rtype
, 5) << " hash: " << r
.slotb_xml
.sha256
142 void dump_region_map() throw(std::bad_alloc
)
144 std::vector
<struct memory_region
> regions
= get_regions();
145 for(auto i
: regions
) {
146 std::ostringstream x
;
147 x
<< std::setfill('0') << std::setw(16) << std::hex
<< i
.baseaddr
<< "-";
148 x
<< std::setfill('0') << std::setw(16) << std::hex
<< i
.lastaddr
<< " ";
149 x
<< std::setfill('0') << std::setw(16) << std::hex
<< i
.size
<< " ";
150 messages
<< x
.str() << (i
.readonly
? "R-" : "RW") << (i
.native_endian
? 'N' : 'L')
151 << (i
.iospace
? 'I' : 'M') << " " << i
.region_name
<< std::endl
;
155 void fatal_error() throw()
157 platform::fatal_error();
158 std::cout
<< "PANIC: Fatal error, can't continue." << std::endl
;
162 std::string
get_config_path() throw(std::bad_alloc
)
166 if((tmp
= getenv("APPDATA"))) {
167 //If $APPDATA exists, it is the base directory
169 } else if((tmp
= getenv("XDG_CONFIG_HOME"))) {
170 //If $XDG_CONFIG_HOME exists, it is the base directory
172 } else if((tmp
= getenv("HOME"))) {
173 //If $HOME exists, the base directory is '.config' there.
174 basedir
= std::string(tmp
) + "/.config";
176 //Last chance: Return current directory.
179 //Try to create 'lsnes'. If it exists (or is created) and is directory, great. Otherwise error out.
180 std::string lsnes_path
= basedir
+ "/lsnes";
181 boost::filesystem::path
p(lsnes_path
);
182 if(!boost::filesystem::create_directories(p
) && !boost::filesystem::is_directory(p
)) {
183 messages
<< "FATAL: Can't create configuration directory '" << lsnes_path
<< "'" << std::endl
;
186 //Yes, this is racy, but portability is more important than being absolutely correct...
187 std::string tfile
= lsnes_path
+ "/test";
188 remove(tfile
.c_str());
190 if(!(x
= fopen(tfile
.c_str(), "w+"))) {
191 messages
<< "FATAL: Configuration directory '" << lsnes_path
<< "' is not writable" << std::endl
;
195 remove(tfile
.c_str());
199 extern const char* lsnesrc_file
;
201 void create_lsnesrc()
203 std::string rcfile
= get_config_path() + "/lsnes.rc";
204 std::ifstream
x(rcfile
.c_str());
209 std::ofstream
y(rcfile
.c_str());
211 messages
<< "FATAL: lsnes.rc (" << rcfile
<< ") doesn't exist nor it can be created" << std::endl
;
214 y
.write(lsnesrc_file
, strlen(lsnesrc_file
));
221 messages
<< "FATAL: Out of memory!" << std::endl
;
225 std::ostream
& _messages()
227 return platform::out();
230 uint32_t gcd(uint32_t a
, uint32_t b
) throw()
235 return gcd(b
, a
% b
);
238 std::string
format_address(void* addr
)
240 unsigned long x
= (unsigned long)addr
;
241 std::ostringstream y
;
242 y
<< "0x" << std::hex
<< std::setfill('0') << std::setw(2 * sizeof(unsigned long)) << x
;
246 bool in_global_ctors()
248 return !reached_main_flag
;
253 reached_main_flag
= true;
254 init_threaded_malloc();
257 std::string bsnes_core_version
;