2 #include "memorymanip.hpp"
15 #include <boost/filesystem.hpp>
20 uint64_t rcounter
= 0;
22 std::string
get_random_hexstring_64(size_t index
)
24 std::ostringstream str
;
25 str
<< rseed
<< " " << time(NULL
) << " " << (rcounter
++) << " " << index
;
26 std::string s
= str
.str();
29 std::copy(s
.begin(), s
.end(), x
.begin());
30 return sha256::hash(reinterpret_cast<uint8_t*>(&x
[0]), x
.size());
33 std::string
collect_identifying_information()
35 //TODO: Collect as much identifying information as possible.
36 std::ostringstream str
;
37 time_t told
= time(NULL
);
47 str
<< (loops
- base
) << " ";
56 bool is_cmd_prefix(const std::string
& haystack
, const std::string
& needle
) throw()
58 size_t hlen
= haystack
.length();
59 size_t nlen
= needle
.length();
62 for(size_t i
= 0; i
< nlen
; i
++)
63 if(haystack
[i
] != needle
[i
])
67 return (haystack
[nlen
] == ' ' || haystack
[nlen
] == '\t');
70 std::string
get_random_hexstring(size_t length
) throw(std::bad_alloc
)
73 for(size_t i
= 0; i
< length
; i
+= 64)
74 out
= out
+ get_random_hexstring_64(i
);
75 return out
.substr(0, length
);
78 void set_random_seed(const std::string
& seed
) throw(std::bad_alloc
)
80 std::ostringstream str
;
81 str
<< seed
.length() << " " << seed
;
85 void set_random_seed() throw(std::bad_alloc
)
87 //Try /dev/urandom first.
89 std::ifstream
r("/dev/urandom", std::ios::binary
);
93 std::string
s(buf
, 64);
99 std::ostringstream str
;
100 str
<< collect_identifying_information() << " " << time(NULL
);
101 set_random_seed(str
.str());
107 #include <nall/sha256.hpp>
109 using foobar::nall::sha256_ctx
;
110 using foobar::nall::sha256_init
;
111 using foobar::nall::sha256_final
;
112 using foobar::nall::sha256_hash
;
113 using foobar::nall::sha256_chunk
;
116 * \brief Opaque internal state of SHA256
121 * \brief Opaque internal state structure of SHA256
126 sha256::sha256() throw(std::bad_alloc
)
128 opaque
= new sha256_opaque();
130 sha256_init(&opaque
->shactx
);
133 sha256::~sha256() throw()
138 void sha256::write(const uint8_t* data
, size_t datalen
) throw()
140 sha256_chunk(&opaque
->shactx
, data
, datalen
);
143 void sha256::read(uint8_t* hashout
) throw()
146 sha256_final(&opaque
->shactx
);
148 sha256_hash(&opaque
->shactx
, hashout
);
151 std::string
sha256::read() throw(std::bad_alloc
)
155 return sha256::tostring(b
);
158 void sha256::hash(uint8_t* hashout
, const uint8_t* data
, size_t datalen
) throw()
161 s
.write(data
, datalen
);
165 std::string
sha256::tostring(const uint8_t* hashout
) throw(std::bad_alloc
)
167 std::ostringstream str
;
168 for(unsigned i
= 0; i
< 32; i
++)
169 str
<< std::hex
<< std::setw(2) << std::setfill('0') << (unsigned)hashout
[i
];
173 struct loaded_rom
load_rom_from_commandline(std::vector
<std::string
> cmdline
, window
* win
) throw(std::bad_alloc
,
178 f
= rom_files(cmdline
, win
);
179 f
.resolve_relative();
180 } catch(std::bad_alloc
& e
) {
182 } catch(std::exception
& e
) {
183 throw std::runtime_error(std::string("Can't resolve ROM files: ") + e
.what());
185 out(win
) << "ROM type: " << gtype::tostring(f
.rtype
, f
.region
) << std::endl
;
186 if(f
.rom
!= "") out(win
) << name_subrom(f
.rtype
, 0) << " file: '" << f
.rom
<< "'" << std::endl
;
187 if(f
.rom_xml
!= "") out(win
) << name_subrom(f
.rtype
, 1) << " file: '" << f
.rom_xml
<< "'" << std::endl
;
188 if(f
.slota
!= "") out(win
) << name_subrom(f
.rtype
, 2) << " file: '" << f
.slota
<< "'" << std::endl
;
189 if(f
.slota_xml
!= "") out(win
) << name_subrom(f
.rtype
, 3) << " file: '" << f
.slota_xml
<< "'" << std::endl
;
190 if(f
.slotb
!= "") out(win
) << name_subrom(f
.rtype
, 4) << " file: '" << f
.slotb
<< "'" << std::endl
;
191 if(f
.slotb_xml
!= "") out(win
) << name_subrom(f
.rtype
, 5) << " file: '" << f
.slotb_xml
<< "'" << std::endl
;
195 r
= loaded_rom(f
, win
);
196 r
.do_patch(cmdline
, win
);
197 } catch(std::bad_alloc
& e
) {
199 } catch(std::exception
& e
) {
200 throw std::runtime_error(std::string("Can't load ROM: ") + e
.what());
203 std::string not_present
= "N/A";
204 if(r
.rom
.valid
) out(win
) << name_subrom(f
.rtype
, 0) << " hash: " << r
.rom
.sha256
<< std::endl
;
205 if(r
.rom_xml
.valid
) out(win
) << name_subrom(f
.rtype
, 1) << " hash: " << r
.rom_xml
.sha256
<< std::endl
;
206 if(r
.slota
.valid
) out(win
) << name_subrom(f
.rtype
, 2) << " hash: " << r
.slota
.sha256
<< std::endl
;
207 if(r
.slota_xml
.valid
) out(win
) << name_subrom(f
.rtype
, 3) << " hash: " << r
.slota_xml
.sha256
<< std::endl
;
208 if(r
.slotb
.valid
) out(win
) << name_subrom(f
.rtype
, 4) << " hash: " << r
.slotb
.sha256
<< std::endl
;
209 if(r
.slotb_xml
.valid
) out(win
) << name_subrom(f
.rtype
, 5) << " hash: " << r
.slotb_xml
.sha256
<< std::endl
;
213 void dump_region_map(window
* win
) throw(std::bad_alloc
)
215 std::vector
<struct memory_region
> regions
= get_regions();
216 for(auto i
= regions
.begin(); i
!= regions
.end(); ++i
) {
218 sprintf(buf
, "Region: %08X-%08X %08X %s%c %s", i
->baseaddr
, i
->lastaddr
, i
->size
,
219 i
->readonly
? "R-" : "RW", i
->native_endian
? 'N' : 'B', i
->region_name
.c_str());
220 out(win
) << buf
<< std::endl
;
224 std::ostream
& out(window
* win
) throw(std::bad_alloc
)
232 void fatal_error(window
* win
) throw()
236 std::cout
<< "PANIC: Fatal error, can't continue." << std::endl
;
240 std::string
get_config_path(window
* win
) throw(std::bad_alloc
)
244 if((tmp
= getenv("APPDATA"))) {
245 //If $APPDATA exists, it is the base directory
247 } else if((tmp
= getenv("XDG_CONFIG_HOME"))) {
248 //If $XDG_CONFIG_HOME exists, it is the base directory
250 } else if((tmp
= getenv("HOME"))) {
251 //If $HOME exists, the base directory is '.config' there.
252 basedir
= std::string(tmp
) + "/.config";
254 //Last chance: Return current directory.
257 //Try to create 'lsnes'. If it exists (or is created) and is directory, great. Otherwise error out.
258 std::string lsnes_path
= basedir
+ "/lsnes";
259 boost::filesystem::path
p(lsnes_path
);
260 if(!boost::filesystem::create_directories(p
) && !boost::filesystem::is_directory(p
)) {
261 out(win
) << "FATAL: Can't create configuration directory '" << lsnes_path
<< "'" << std::endl
;
264 //Yes, this is racy, but portability is more important than being absolutely correct...
265 std::string tfile
= lsnes_path
+ "/test";
266 remove(tfile
.c_str());
268 if(!(x
= fopen(tfile
.c_str(), "w+"))) {
269 out(win
) << "FATAL: Configuration directory '" << lsnes_path
<< "' is not writable" << std::endl
;
273 remove(tfile
.c_str());
277 extern const char* lsnesrc_file
;
279 void create_lsnesrc(window
* win
)
281 std::string rcfile
= get_config_path(win
) + "/lsnes.rc";
282 std::ifstream
x(rcfile
.c_str());
287 std::ofstream
y(rcfile
.c_str());
289 out(win
) << "FATAL: lsnes.rc (" << rcfile
<< ") doesn't exist nor it can be created" << std::endl
;
292 y
.write(lsnesrc_file
, strlen(lsnesrc_file
));
297 void OOM_panic(window
* win
)
299 out(win
) << "FATAL: Out of memory!" << std::endl
;
303 std::string bsnes_core_version
;
304 std::string lsnes_version
= "0-β1";