1 #include "core/dispatch.hpp"
2 #include "core/moviedata.hpp"
3 #include "core/rom.hpp"
4 #include "core/romloader.hpp"
5 #include "core/romguess.hpp"
6 #include "core/settings.hpp"
7 #include "core/project.hpp"
8 #include "core/window.hpp"
9 #include "library/zip.hpp"
14 std::cerr
<< "Can't switch ROM with project active." << std::endl
;
20 for(size_t i
= 0; i
< ROM_SLOT_COUNT
; i
++) {
21 movb
.get_mfile().romimg_sha256
[i
] = "";
22 movb
.get_mfile().romxml_sha256
[i
] = "";
23 movb
.get_mfile().namehint
[i
] = "";
31 void load_new_rom_inner(const romload_request
& req
)
33 if(req
.packfile
!= "") {
34 messages
<< "Loading ROM " << req
.packfile
<< std::endl
;
35 loaded_rom
newrom(req
.packfile
);
38 } else if(req
.singlefile
!= "") {
39 messages
<< "Loading ROM " << req
.singlefile
<< std::endl
;
40 loaded_rom
newrom(req
.singlefile
, req
.core
, req
.system
, req
.region
);
44 messages
<< "Loading multi-file ROM." << std::endl
;
45 loaded_rom
newrom(req
.files
, req
.core
, req
.system
, req
.region
);
51 std::string
call_rom(unsigned i
, bool bios
)
60 return std::string("ROM ") + j
;
63 void print_missing(core_type
& t
, unsigned present
)
65 bool has_bios
= (t
.get_biosname() != "");
67 for(unsigned i
= 0; i
< t
.get_image_count(); i
++)
68 total
|= t
.get_image_info(i
).mandatory
;
70 std::string need
= "";
74 if((total
& bit
) && !(present
& bit
)) {
75 if(need
!= "") need
+= ", ";
76 for(unsigned i
= 0; i
< t
.get_image_count(); i
++) {
77 if(t
.get_image_info(i
).mandatory
& bit
) {
78 if(!first
) need
+= "/";
79 need
+= call_rom(i
, has_bios
);
86 (stringfmt() << "Slots " << need
<< " are required.").throwex();
90 bool _load_new_rom(const romload_request
& req
)
93 std::cerr
<< "Can't switch ROM with project active." << std::endl
;
97 load_new_rom_inner(req
);
99 for(size_t i
= 0; i
< ROM_SLOT_COUNT
; i
++) {
100 movb
.get_mfile().romimg_sha256
[i
] = our_rom
.romimg
[i
].sha_256
.read();
101 movb
.get_mfile().romxml_sha256
[i
] = our_rom
.romxml
[i
].sha_256
.read();
102 movb
.get_mfile().namehint
[i
] = our_rom
.romimg
[i
].namehint
;
104 } catch(std::exception
& e
) {
105 platform::error_message(std::string("Can't load ROM: ") + e
.what());
106 messages
<< "Can't reload ROM: " << e
.what() << std::endl
;
109 messages
<< "Using core: " << our_rom
.rtype
->get_core_identifier() << std::endl
;
110 notify_core_change();
115 bool reload_active_rom()
118 if(our_rom
.rtype
->isnull()) {
119 platform::error_message("Can't reload ROM: No existing ROM");
120 messages
<< "No ROM loaded" << std::endl
;
123 if(our_rom
.load_filename
!= "") {
124 req
.packfile
= our_rom
.load_filename
;
125 return _load_new_rom(req
);
127 //This is composite ROM.
128 req
.core
= our_rom
.rtype
->get_core_identifier();
129 req
.system
= our_rom
.rtype
->get_iname();
130 req
.region
= our_rom
.orig_region
->get_iname();
131 for(unsigned i
= 0; i
< ROM_SLOT_COUNT
; i
++)
132 req
.files
[i
] = our_rom
.romimg
[i
].filename
;
133 return _load_new_rom(req
);
136 regex_results
get_argument(const std::vector
<std::string
>& cmdline
, const std::string
& regexp
)
138 for(auto i
: cmdline
) {
140 if(r
= regex(regexp
, i
))
143 return regex_results();
146 std::string
get_requested_core(const std::vector
<std::string
>& cmdline
)
149 if(r
= get_argument(cmdline
, "--core=(.+)"))
154 loaded_rom
construct_rom_multifile(core_type
* ctype
, const moviefile::brief_info
& info
,
155 const std::vector
<std::string
>& cmdline
, bool have_movie
)
157 std::string roms
[ROM_SLOT_COUNT
];
158 std::string realcore
= ctype
->get_core_identifier();
159 std::string realtype
= ctype
->get_iname();
160 std::string bios
= ctype
->get_biosname();
161 uint32_t pmand
= 0, tmand
= 0;
162 for(unsigned i
= 0; i
< ROM_SLOT_COUNT
; i
++) {
163 std::string optregex
;
165 std::string psetting
;
167 if(bios
!= "" && i
== 0) {
168 optregex
= "--bios=(.*)";
170 psetting
= "firmwarepath";
174 j
[0] = i
- ((bios
!= "") ? 1 : 0) + 'a';
177 optregex
= std::string("--rom-") + j
+ "=(.*)";
178 psetting
= "rompath";
179 j
[0] = i
- ((bios
!= "") ? 1 : 0) + 'A';
182 romid
= std::string("ROM ") + j
;
184 regex_results r
= get_argument(cmdline
, optregex
);
185 if(i
>= ctype
->get_image_count()) {
187 throw std::runtime_error("This ROM type has no " + romid
);
191 if(info
.hash
[i
] == "" && have_movie
&& r
)
192 throw std::runtime_error("This movie has no " + romid
);
194 auto img
= ctype
->get_image_info(i
);
195 tmand
|= img
.mandatory
;
197 //Explicitly specified, use that.
199 } else if(info
.hint
[i
] != "") {
201 std::set
<std::string
> exts
= img
.extensions
;
203 std::string candidate
= lsnes_vset
[psetting
].str() + "/" + info
.hint
[i
] +
205 if(zip::file_exists(candidate
)) {
211 if(isbios
&& roms
[i
] == "" && i
== 0) {
213 roms
[0] = lsnes_vset
["firmwarepath"].str() + "/" + bios
;
215 if(roms
[i
] == "" && info
.hash
[i
] != "")
216 roms
[i
] = try_to_guess_rom(info
.hint
[i
], info
.hash
[i
], info
.hashxml
[i
], *ctype
, i
);
217 if(roms
[i
] == "" && info
.hash
[i
] != "")
218 throw std::runtime_error("Can't find " + romid
+ " (specify explicitly)");
220 pmand
|= img
.mandatory
;
221 if(roms
[i
] != "" && !zip::file_exists(roms
[i
]))
222 throw std::runtime_error(romid
+ " points to nonexistent file (" + roms
[i
] + ")");
225 print_missing(*ctype
, pmand
);
226 return loaded_rom(roms
, realcore
, realtype
, "");
229 loaded_rom
construct_rom_nofile(const std::vector
<std::string
>& cmdline
)
231 std::string requested_core
= get_requested_core(cmdline
);
232 //Handle bundle / single-file ROMs.
233 for(auto i
: cmdline
) {
235 if(r
= regex("--rom=(.*)", i
)) {
236 //Okay, load as ROM bundle and check validity.
237 loaded_rom
cr(r
[1], requested_core
);
242 for(auto i
: core_core::all_cores())
243 if(i
->get_core_shortname() == requested_core
|| requested_core
== "")
245 throw std::runtime_error("Specified unsupported core");
249 regex_results _type
= get_argument(cmdline
, "--rom-type=(.*)");
251 return loaded_rom(); //NULL rom.
252 core_type
* ctype
= NULL
;
253 for(auto i
: core_type::get_core_types()) {
254 if(i
->get_iname() != _type
[1])
256 if(i
->get_core_shortname() != requested_core
&& requested_core
!= "")
261 throw std::runtime_error("Specified impossible core/type combination");
263 moviefile::brief_info info
;
264 return construct_rom_multifile(ctype
, info
, cmdline
, false);
268 loaded_rom
construct_rom(const std::string
& movie_filename
, const std::vector
<std::string
>& cmdline
)
270 if(movie_filename
== "")
271 return construct_rom_nofile(cmdline
);
272 moviefile::brief_info
info(movie_filename
);
273 std::string requested_core
= get_requested_core(cmdline
);
274 auto sysregs
= core_sysregion::find_matching(info
.sysregion
);
276 throw std::runtime_error("No core supports '" + info
.sysregion
+ "'");
278 //Default to correct core.
279 if(requested_core
== "") {
280 for(auto i
: core_core::all_cores())
281 if(i
->get_core_identifier() == info
.corename
)
282 requested_core
= i
->get_core_shortname();
285 //Handle bundle / single-file ROMs.
286 for(auto i
: cmdline
) {
288 if(r
= regex("--rom=(.*)", i
)) {
289 //Okay, load as ROM bundle and check validity.
290 loaded_rom
cr(r
[1], requested_core
);
291 for(auto j
: sysregs
) {
292 if(&j
->get_type() != cr
.rtype
)
294 for(auto k
: cr
.rtype
->get_regions())
295 if(k
== &j
->get_region())
298 throw std::runtime_error("Specified ROM is of wrong type ('" +
299 cr
.rtype
->get_hname() + "') for movie ('" + info
.sysregion
+ ")");
306 core_type
* ctype
= NULL
;
307 for(auto i
: sysregs
) {
308 ctype
= &i
->get_type();
309 if(ctype
->get_core_shortname() == requested_core
)
312 if(requested_core
!= "" && ctype
->get_core_shortname() != requested_core
)
313 throw std::runtime_error("Specified incomplatible or unsupported core");
314 if(requested_core
== "")
315 messages
<< "Will use '" << ctype
->get_core_identifier() << "'" << std::endl
;
316 return construct_rom_multifile(ctype
, info
, cmdline
, true);