1 #include "core/dispatch.hpp"
2 #include "core/instance.hpp"
3 #include "core/messages.hpp"
4 #include "core/moviedata.hpp"
5 #include "core/project.hpp"
6 #include "core/rom.hpp"
7 #include "core/settings.hpp"
8 #include "core/window.hpp"
9 #include "library/zip.hpp"
14 if(core
.project
->get()) {
15 std::cerr
<< "Can't switch ROM with project active." << std::endl
;
21 for(size_t i
= 0; i
< ROM_SLOT_COUNT
; i
++) {
22 core
.mlogic
->get_mfile().romimg_sha256
[i
] = "";
23 core
.mlogic
->get_mfile().romxml_sha256
[i
] = "";
24 core
.mlogic
->get_mfile().namehint
[i
] = "";
26 core
.dispatch
->core_change();
32 void load_new_rom_inner(const romload_request
& req
)
35 if(req
.packfile
!= "") {
36 messages
<< "Loading ROM " << req
.packfile
<< std::endl
;
37 loaded_rom
newrom(new rom_image(req
.packfile
));
40 } else if(req
.singlefile
!= "") {
41 messages
<< "Loading ROM " << req
.singlefile
<< std::endl
;
42 loaded_rom
newrom(new rom_image(req
.singlefile
, req
.core
, req
.system
, req
.region
));
46 messages
<< "Loading multi-file ROM." << std::endl
;
47 loaded_rom
newrom(new rom_image(req
.files
, req
.core
, req
.system
, req
.region
));
53 std::string
call_rom(unsigned i
, bool bios
)
62 return std::string("ROM ") + j
;
65 void print_missing(core_type
& t
, unsigned present
)
67 bool has_bios
= (t
.get_biosname() != "");
69 for(unsigned i
= 0; i
< t
.get_image_count(); i
++)
70 total
|= t
.get_image_info(i
).mandatory
;
72 std::string need
= "";
76 if((total
& bit
) && !(present
& bit
)) {
77 if(need
!= "") need
+= ", ";
78 for(unsigned i
= 0; i
< t
.get_image_count(); i
++) {
79 if(t
.get_image_info(i
).mandatory
& bit
) {
80 if(!first
) need
+= "/";
81 need
+= call_rom(i
, has_bios
);
88 (stringfmt() << "Slots " << need
<< " are required.").throwex();
92 bool _load_new_rom(const romload_request
& req
)
95 if(core
.project
->get()) {
96 std::string msg
= "Can't switch ROM with project active.";
97 platform::error_message(msg
);
98 messages
<< msg
<< std::endl
;
102 load_new_rom_inner(req
);
104 for(size_t i
= 0; i
< ROM_SLOT_COUNT
; i
++) {
105 auto& img
= core
.rom
->get_rom(i
);
106 auto& xml
= core
.rom
->get_markup(i
);
107 core
.mlogic
->get_mfile().romimg_sha256
[i
] = img
.sha_256
.read();
108 core
.mlogic
->get_mfile().romxml_sha256
[i
] = xml
.sha_256
.read();
109 core
.mlogic
->get_mfile().namehint
[i
] = img
.namehint
;
111 } catch(std::exception
& e
) {
112 platform::error_message(std::string("Can't load ROM: ") + e
.what());
113 messages
<< "Can't reload ROM: " << e
.what() << std::endl
;
116 messages
<< "Using core: " << core
.rom
->get_core_identifier() << std::endl
;
117 core
.dispatch
->core_change();
122 bool reload_active_rom()
126 if(core
.rom
->isnull()) {
127 platform::error_message("Can't reload ROM: No existing ROM");
128 messages
<< "No ROM loaded" << std::endl
;
132 std::string loadfile
= core
.rom
->get_pack_filename();
134 req
.packfile
= loadfile
;
135 return _load_new_rom(req
);
137 //This is composite ROM.
138 req
.core
= core
.rom
->get_core_identifier();
139 req
.system
= core
.rom
->get_iname();
140 req
.region
= core
.rom
->orig_region_get_iname();
141 for(unsigned i
= 0; i
< ROM_SLOT_COUNT
; i
++)
142 req
.files
[i
] = core
.rom
->get_rom(i
).filename
;
143 return _load_new_rom(req
);
146 regex_results
get_argument(const std::vector
<std::string
>& cmdline
, const std::string
& regexp
)
148 for(auto i
: cmdline
) {
150 if(r
= regex(regexp
, i
))
153 return regex_results();
156 std::string
get_requested_core(const std::vector
<std::string
>& cmdline
)
159 if(r
= get_argument(cmdline
, "--core=(.+)"))
164 rom_image_handle
construct_rom_multifile(core_type
* ctype
, const moviefile::brief_info
& info
,
165 const std::vector
<std::string
>& cmdline
, bool have_movie
)
168 std::string roms
[ROM_SLOT_COUNT
];
169 std::string realcore
= ctype
->get_core_identifier();
170 std::string realtype
= ctype
->get_iname();
171 std::string bios
= ctype
->get_biosname();
172 uint32_t pmand
= 0, tmand
= 0;
173 for(unsigned i
= 0; i
< ROM_SLOT_COUNT
; i
++) {
174 std::string optregex
;
176 auto psetting
= &SET_firmwarepath
;
178 if(bios
!= "" && i
== 0) {
179 optregex
= "--bios=(.*)";
181 psetting
= &SET_firmwarepath
;
185 j
[0] = i
- ((bios
!= "") ? 1 : 0) + 'a';
188 optregex
= std::string("--rom-") + j
+ "=(.*)";
189 psetting
= &SET_rompath
;
190 j
[0] = i
- ((bios
!= "") ? 1 : 0) + 'A';
193 romid
= std::string("ROM ") + j
;
195 regex_results r
= get_argument(cmdline
, optregex
);
196 if(i
>= ctype
->get_image_count()) {
198 throw std::runtime_error("This ROM type has no " + romid
);
202 if(info
.hash
[i
] == "" && have_movie
&& r
)
203 throw std::runtime_error("This movie has no " + romid
);
205 auto img
= ctype
->get_image_info(i
);
206 tmand
|= img
.mandatory
;
208 //Explicitly specified, use that.
210 } else if(info
.hint
[i
] != "") {
212 std::set
<std::string
> exts
= img
.extensions
;
214 std::string candidate
= (*psetting
)(*core
.settings
) + "/" + info
.hint
[i
] +
216 if(zip::file_exists(candidate
)) {
222 if(isbios
&& roms
[i
] == "" && i
== 0) {
224 roms
[0] = SET_firmwarepath(*core
.settings
) + "/" + bios
;
226 if(roms
[i
] == "" && info
.hash
[i
] != "")
227 roms
[i
] = try_to_guess_rom(info
.hint
[i
], info
.hash
[i
], info
.hashxml
[i
], *ctype
, i
);
228 if(roms
[i
] == "" && info
.hash
[i
] != "")
229 throw std::runtime_error("Can't find " + romid
+ " (specify explicitly)");
231 pmand
|= img
.mandatory
;
232 if(roms
[i
] != "" && !zip::file_exists(roms
[i
]))
233 throw std::runtime_error(romid
+ " points to nonexistent file (" + roms
[i
] + ")");
236 print_missing(*ctype
, pmand
);
237 return new rom_image(roms
, realcore
, realtype
, "");
240 rom_image_handle
construct_rom_nofile(const std::vector
<std::string
>& cmdline
)
242 std::string requested_core
= get_requested_core(cmdline
);
243 //Handle bundle / single-file ROMs.
244 for(auto i
: cmdline
) {
246 if(r
= regex("--rom=(.*)", i
)) {
247 //Okay, load as ROM bundle and check validity.
248 return new rom_image(r
[1], requested_core
);
252 for(auto i
: core_core::all_cores())
253 if(i
->get_core_shortname() == requested_core
|| requested_core
== "")
255 throw std::runtime_error("Specified unsupported core");
259 regex_results _type
= get_argument(cmdline
, "--rom-type=(.*)");
261 return rom_image_handle(); //NULL rom.
262 core_type
* ctype
= NULL
;
263 for(auto i
: core_type::get_core_types()) {
264 if(i
->get_iname() != _type
[1])
266 if(i
->get_core_shortname() != requested_core
&& requested_core
!= "")
271 throw std::runtime_error("Specified impossible core/type combination");
273 moviefile::brief_info info
;
274 return construct_rom_multifile(ctype
, info
, cmdline
, false);
278 rom_image_handle
construct_rom(const std::string
& movie_filename
, const std::vector
<std::string
>& cmdline
)
280 if(movie_filename
== "")
281 return construct_rom_nofile(cmdline
);
282 moviefile::brief_info
info(movie_filename
);
283 std::string requested_core
= get_requested_core(cmdline
);
284 auto sysregs
= core_sysregion::find_matching(info
.sysregion
);
286 throw std::runtime_error("No core supports '" + info
.sysregion
+ "'");
288 //Default to correct core.
289 if(requested_core
== "") {
290 for(auto i
: core_core::all_cores())
291 if(i
->get_core_identifier() == info
.corename
)
292 requested_core
= i
->get_core_shortname();
295 //Handle bundle / single-file ROMs.
296 for(auto i
: cmdline
) {
298 if(r
= regex("--rom=(.*)", i
)) {
299 //Okay, load as ROM bundle and check validity.
300 auto cr
= new rom_image(r
[1], requested_core
);
301 for(auto j
: sysregs
) {
302 if(!cr
->is_of_type(j
->get_type()))
304 for(auto k
: cr
->get_regions())
305 if(k
== &j
->get_region())
308 throw std::runtime_error("Specified ROM is of wrong type ('" +
309 cr
->get_hname() + "') for movie ('" + info
.sysregion
+ ")");
316 core_type
* ctype
= NULL
;
317 for(auto i
: sysregs
) {
318 ctype
= &i
->get_type();
319 if(ctype
->get_core_shortname() == requested_core
)
322 if(requested_core
!= "" && ctype
->get_core_shortname() != requested_core
)
323 throw std::runtime_error("Specified incomplatible or unsupported core");
324 if(requested_core
== "")
325 messages
<< "Will use '" << ctype
->get_core_identifier() << "'" << std::endl
;
326 return construct_rom_multifile(ctype
, info
, cmdline
, true);