1 #include "core/dispatch.hpp"
2 #include "core/instance.hpp"
3 #include "core/moviedata.hpp"
4 #include "core/rom.hpp"
5 #include "core/romloader.hpp"
6 #include "core/romguess.hpp"
7 #include "core/settings.hpp"
8 #include "core/project.hpp"
9 #include "core/window.hpp"
10 #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
] = "";
32 void load_new_rom_inner(const romload_request
& req
)
34 if(req
.packfile
!= "") {
35 messages
<< "Loading ROM " << req
.packfile
<< std::endl
;
36 loaded_rom
newrom(req
.packfile
);
39 } else if(req
.singlefile
!= "") {
40 messages
<< "Loading ROM " << req
.singlefile
<< std::endl
;
41 loaded_rom
newrom(req
.singlefile
, req
.core
, req
.system
, req
.region
);
45 messages
<< "Loading multi-file ROM." << std::endl
;
46 loaded_rom
newrom(req
.files
, req
.core
, req
.system
, req
.region
);
52 std::string
call_rom(unsigned i
, bool bios
)
61 return std::string("ROM ") + j
;
64 void print_missing(core_type
& t
, unsigned present
)
66 bool has_bios
= (t
.get_biosname() != "");
68 for(unsigned i
= 0; i
< t
.get_image_count(); i
++)
69 total
|= t
.get_image_info(i
).mandatory
;
71 std::string need
= "";
75 if((total
& bit
) && !(present
& bit
)) {
76 if(need
!= "") need
+= ", ";
77 for(unsigned i
= 0; i
< t
.get_image_count(); i
++) {
78 if(t
.get_image_info(i
).mandatory
& bit
) {
79 if(!first
) need
+= "/";
80 need
+= call_rom(i
, has_bios
);
87 (stringfmt() << "Slots " << need
<< " are required.").throwex();
91 bool _load_new_rom(const romload_request
& req
)
93 if(CORE().project
->get()) {
94 std::cerr
<< "Can't switch ROM with project active." << std::endl
;
98 load_new_rom_inner(req
);
100 for(size_t i
= 0; i
< ROM_SLOT_COUNT
; i
++) {
101 CORE().mlogic
->get_mfile().romimg_sha256
[i
] = our_rom
.romimg
[i
].sha_256
.read();
102 CORE().mlogic
->get_mfile().romxml_sha256
[i
] = our_rom
.romxml
[i
].sha_256
.read();
103 CORE().mlogic
->get_mfile().namehint
[i
] = our_rom
.romimg
[i
].namehint
;
105 } catch(std::exception
& e
) {
106 platform::error_message(std::string("Can't load ROM: ") + e
.what());
107 messages
<< "Can't reload ROM: " << e
.what() << std::endl
;
110 messages
<< "Using core: " << our_rom
.rtype
->get_core_identifier() << std::endl
;
111 notify_core_change();
116 bool reload_active_rom()
119 if(our_rom
.rtype
->isnull()) {
120 platform::error_message("Can't reload ROM: No existing ROM");
121 messages
<< "No ROM loaded" << std::endl
;
124 if(our_rom
.load_filename
!= "") {
125 req
.packfile
= our_rom
.load_filename
;
126 return _load_new_rom(req
);
128 //This is composite ROM.
129 req
.core
= our_rom
.rtype
->get_core_identifier();
130 req
.system
= our_rom
.rtype
->get_iname();
131 req
.region
= our_rom
.orig_region
->get_iname();
132 for(unsigned i
= 0; i
< ROM_SLOT_COUNT
; i
++)
133 req
.files
[i
] = our_rom
.romimg
[i
].filename
;
134 return _load_new_rom(req
);
137 regex_results
get_argument(const std::vector
<std::string
>& cmdline
, const std::string
& regexp
)
139 for(auto i
: cmdline
) {
141 if(r
= regex(regexp
, i
))
144 return regex_results();
147 std::string
get_requested_core(const std::vector
<std::string
>& cmdline
)
150 if(r
= get_argument(cmdline
, "--core=(.+)"))
155 loaded_rom
construct_rom_multifile(core_type
* ctype
, const moviefile::brief_info
& info
,
156 const std::vector
<std::string
>& cmdline
, bool have_movie
)
158 std::string roms
[ROM_SLOT_COUNT
];
159 std::string realcore
= ctype
->get_core_identifier();
160 std::string realtype
= ctype
->get_iname();
161 std::string bios
= ctype
->get_biosname();
162 uint32_t pmand
= 0, tmand
= 0;
163 for(unsigned i
= 0; i
< ROM_SLOT_COUNT
; i
++) {
164 std::string optregex
;
166 std::string psetting
;
168 if(bios
!= "" && i
== 0) {
169 optregex
= "--bios=(.*)";
171 psetting
= "firmwarepath";
175 j
[0] = i
- ((bios
!= "") ? 1 : 0) + 'a';
178 optregex
= std::string("--rom-") + j
+ "=(.*)";
179 psetting
= "rompath";
180 j
[0] = i
- ((bios
!= "") ? 1 : 0) + 'A';
183 romid
= std::string("ROM ") + j
;
185 regex_results r
= get_argument(cmdline
, optregex
);
186 if(i
>= ctype
->get_image_count()) {
188 throw std::runtime_error("This ROM type has no " + romid
);
192 if(info
.hash
[i
] == "" && have_movie
&& r
)
193 throw std::runtime_error("This movie has no " + romid
);
195 auto img
= ctype
->get_image_info(i
);
196 tmand
|= img
.mandatory
;
198 //Explicitly specified, use that.
200 } else if(info
.hint
[i
] != "") {
202 std::set
<std::string
> exts
= img
.extensions
;
204 std::string candidate
= CORE().setcache
->get(psetting
) + "/" + info
.hint
[i
] +
206 if(zip::file_exists(candidate
)) {
212 if(isbios
&& roms
[i
] == "" && i
== 0) {
214 roms
[0] = CORE().setcache
->get("firmwarepath") + "/" + bios
;
216 if(roms
[i
] == "" && info
.hash
[i
] != "")
217 roms
[i
] = try_to_guess_rom(info
.hint
[i
], info
.hash
[i
], info
.hashxml
[i
], *ctype
, i
);
218 if(roms
[i
] == "" && info
.hash
[i
] != "")
219 throw std::runtime_error("Can't find " + romid
+ " (specify explicitly)");
221 pmand
|= img
.mandatory
;
222 if(roms
[i
] != "" && !zip::file_exists(roms
[i
]))
223 throw std::runtime_error(romid
+ " points to nonexistent file (" + roms
[i
] + ")");
226 print_missing(*ctype
, pmand
);
227 return loaded_rom(roms
, realcore
, realtype
, "");
230 loaded_rom
construct_rom_nofile(const std::vector
<std::string
>& cmdline
)
232 std::string requested_core
= get_requested_core(cmdline
);
233 //Handle bundle / single-file ROMs.
234 for(auto i
: cmdline
) {
236 if(r
= regex("--rom=(.*)", i
)) {
237 //Okay, load as ROM bundle and check validity.
238 loaded_rom
cr(r
[1], requested_core
);
243 for(auto i
: core_core::all_cores())
244 if(i
->get_core_shortname() == requested_core
|| requested_core
== "")
246 throw std::runtime_error("Specified unsupported core");
250 regex_results _type
= get_argument(cmdline
, "--rom-type=(.*)");
252 return loaded_rom(); //NULL rom.
253 core_type
* ctype
= NULL
;
254 for(auto i
: core_type::get_core_types()) {
255 if(i
->get_iname() != _type
[1])
257 if(i
->get_core_shortname() != requested_core
&& requested_core
!= "")
262 throw std::runtime_error("Specified impossible core/type combination");
264 moviefile::brief_info info
;
265 return construct_rom_multifile(ctype
, info
, cmdline
, false);
269 loaded_rom
construct_rom(const std::string
& movie_filename
, const std::vector
<std::string
>& cmdline
)
271 if(movie_filename
== "")
272 return construct_rom_nofile(cmdline
);
273 moviefile::brief_info
info(movie_filename
);
274 std::string requested_core
= get_requested_core(cmdline
);
275 auto sysregs
= core_sysregion::find_matching(info
.sysregion
);
277 throw std::runtime_error("No core supports '" + info
.sysregion
+ "'");
279 //Default to correct core.
280 if(requested_core
== "") {
281 for(auto i
: core_core::all_cores())
282 if(i
->get_core_identifier() == info
.corename
)
283 requested_core
= i
->get_core_shortname();
286 //Handle bundle / single-file ROMs.
287 for(auto i
: cmdline
) {
289 if(r
= regex("--rom=(.*)", i
)) {
290 //Okay, load as ROM bundle and check validity.
291 loaded_rom
cr(r
[1], requested_core
);
292 for(auto j
: sysregs
) {
293 if(&j
->get_type() != cr
.rtype
)
295 for(auto k
: cr
.rtype
->get_regions())
296 if(k
== &j
->get_region())
299 throw std::runtime_error("Specified ROM is of wrong type ('" +
300 cr
.rtype
->get_hname() + "') for movie ('" + info
.sysregion
+ ")");
307 core_type
* ctype
= NULL
;
308 for(auto i
: sysregs
) {
309 ctype
= &i
->get_type();
310 if(ctype
->get_core_shortname() == requested_core
)
313 if(requested_core
!= "" && ctype
->get_core_shortname() != requested_core
)
314 throw std::runtime_error("Specified incomplatible or unsupported core");
315 if(requested_core
== "")
316 messages
<< "Will use '" << ctype
->get_core_identifier() << "'" << std::endl
;
317 return construct_rom_multifile(ctype
, info
, cmdline
, true);