1 // license:BSD-3-Clause
2 // copyright-holders:Miodrag Milanovic
3 /***************************************************************************
4
5 diimage.cpp
6
7 Device image interfaces.
8
9 ***************************************************************************/
10
11 #include "emu.h"
12
13 #include "emuopts.h"
14 #include "drivenum.h"
15 #include "romload.h"
16 #include "ui/uimain.h"
17 #include "zippath.h"
18 #include "softlist.h"
19 #include "softlist_dev.h"
20 #include "formats/ioprocs.h"
21
22 #include <cstring>
23 #include <regex>
24
25
26 //**************************************************************************
27 // DEVICE CONFIG IMAGE INTERFACE
28 //**************************************************************************
29 const image_device_type_info device_image_interface::m_device_info_array[] =
30 {
31 { IO_UNKNOWN, "unknown", "unkn" }, /* 0 */
32 { IO_CARTSLOT, "cartridge", "cart" }, /* 1 */
33 { IO_FLOPPY, "floppydisk", "flop" }, /* 2 */
34 { IO_HARDDISK, "harddisk", "hard" }, /* 3 */
35 { IO_CYLINDER, "cylinder", "cyln" }, /* 4 */
36 { IO_CASSETTE, "cassette", "cass" }, /* 5 */
37 { IO_PUNCHCARD, "punchcard", "pcrd" }, /* 6 */
38 { IO_PUNCHTAPE, "punchtape", "ptap" }, /* 7 */
39 { IO_PRINTER, "printout", "prin" }, /* 8 */
40 { IO_SERIAL, "serial", "serl" }, /* 9 */
41 { IO_PARALLEL, "parallel", "parl" }, /* 10 */
42 { IO_SNAPSHOT, "snapshot", "dump" }, /* 11 */
43 { IO_QUICKLOAD, "quickload", "quik" }, /* 12 */
44 { IO_MEMCARD, "memcard", "memc" }, /* 13 */
45 { IO_CDROM, "cdrom", "cdrm" }, /* 14 */
46 { IO_MAGTAPE, "magtape", "magt" }, /* 15 */
47 { IO_ROM, "romimage", "rom" }, /* 16 */
48 { IO_MIDIIN, "midiin", "min" }, /* 17 */
49 { IO_MIDIOUT, "midiout", "mout" }, /* 18 */
50 { IO_PICTURE, "picture", "pic" }, /* 19 */
51 { IO_VIDEO, "vidfile", "vid" } /* 20 */
52 };
53
54
55 //**************************************************************************
56 // IMAGE DEVICE FORMAT
57 //**************************************************************************
58
59 //-------------------------------------------------
60 // ctor
61 //-------------------------------------------------
62
image_device_format(const std::string & name,const std::string & description,const std::string & extensions,const std::string & optspec)63 image_device_format::image_device_format(const std::string &name, const std::string &description, const std::string &extensions, const std::string &optspec)
64 : m_name(name), m_description(description), m_optspec(optspec)
65 {
66 std::regex comma_regex("\\,");
67 std::copy(
68 std::sregex_token_iterator(extensions.begin(), extensions.end(), comma_regex, -1),
69 std::sregex_token_iterator(),
70 std::back_inserter(m_extensions));
71 }
72
73
74 //-------------------------------------------------
75 // dtor
76 //-------------------------------------------------
77
~image_device_format()78 image_device_format::~image_device_format()
79 {
80 }
81
82
83 //**************************************************************************
84 // DEVICE IMAGE INTERFACE
85 //**************************************************************************
86
87 //-------------------------------------------------
88 // device_image_interface - constructor
89 //-------------------------------------------------
90
device_image_interface(const machine_config & mconfig,device_t & device)91 device_image_interface::device_image_interface(const machine_config &mconfig, device_t &device)
92 : device_interface(device, "image")
93 , m_err()
94 , m_file()
95 , m_mame_file()
96 , m_software_part_ptr(nullptr)
97 , m_supported(0)
98 , m_readonly(false)
99 , m_created(false)
100 , m_create_format(0)
101 , m_create_args(nullptr)
102 , m_user_loadable(true)
103 , m_is_loading(false)
104 , m_is_reset_and_loading(false)
105 {
106 }
107
108
109 //-------------------------------------------------
110 // ~device_image_interface - destructor
111 //-------------------------------------------------
112
~device_image_interface()113 device_image_interface::~device_image_interface()
114 {
115 }
116
117
118 //-------------------------------------------------
119 // interface_config_complete - perform any
120 // operations now that the configuration is
121 // complete
122 //-------------------------------------------------
123
interface_config_complete()124 void device_image_interface::interface_config_complete()
125 {
126 // set brief and instance name
127 update_names();
128 }
129
130
131 //-------------------------------------------------
132 // find_device_type - search trough list of
133 // device types to extract data
134 //-------------------------------------------------
135
find_device_type(iodevice_t type)136 const image_device_type_info *device_image_interface::find_device_type(iodevice_t type)
137 {
138 int i;
139 for (i = 0; i < ARRAY_LENGTH(device_image_interface::m_device_info_array); i++)
140 {
141 if (m_device_info_array[i].m_type == type)
142 return &m_device_info_array[i];
143 }
144 return nullptr;
145 }
146
147 //-------------------------------------------------
148 // device_typename - retrieves device type name
149 //-------------------------------------------------
150
device_typename(iodevice_t type)151 const char *device_image_interface::device_typename(iodevice_t type)
152 {
153 const image_device_type_info *info = find_device_type(type);
154 return (info != nullptr) ? info->m_name : "unknown";
155 }
156
157 //-------------------------------------------------
158 // device_brieftypename - retrieves device
159 // brief type name
160 //-------------------------------------------------
161
device_brieftypename(iodevice_t type)162 const char *device_image_interface::device_brieftypename(iodevice_t type)
163 {
164 const image_device_type_info *info = find_device_type(type);
165 return (info != nullptr) ? info->m_shortname : "unk";
166 }
167
168 //-------------------------------------------------
169 // device_typeid - retrieves device type id
170 //-------------------------------------------------
171
device_typeid(const char * name)172 iodevice_t device_image_interface::device_typeid(const char *name)
173 {
174 int i;
175 for (i = 0; i < ARRAY_LENGTH(device_image_interface::m_device_info_array); i++)
176 {
177 if (!core_stricmp(name, m_device_info_array[i].m_name) || !core_stricmp(name, m_device_info_array[i].m_shortname))
178 return m_device_info_array[i].m_type;
179 }
180 return (iodevice_t)-1;
181 }
182
183 //-------------------------------------------------
184 // set_image_filename - specifies the filename of
185 // an image
186 //-------------------------------------------------
187
set_image_filename(const std::string & filename)188 void device_image_interface::set_image_filename(const std::string &filename)
189 {
190 m_image_name = filename;
191 util::zippath_parent(m_working_directory, filename);
192 m_basename.assign(m_image_name);
193
194 // find the last "path separator"
195 auto iter = std::find_if(
196 m_image_name.rbegin(),
197 m_image_name.rend(),
198 [](char c) { return (c == '\\') || (c == '/') || (c == ':'); });
199
200 if (iter != m_image_name.rend())
201 m_basename.assign(iter.base(), m_image_name.end());
202
203 m_basename_noext = m_basename;
204 auto loc = m_basename_noext.find_last_of('.');
205 if (loc != std::string::npos)
206 m_basename_noext = m_basename_noext.substr(0, loc);
207
208 m_filetype = core_filename_extract_extension(m_basename, true);
209 }
210
211
212 /****************************************************************************
213 CREATION FORMATS
214 ****************************************************************************/
215
216 //-------------------------------------------------
217 // device_get_named_creatable_format -
218 // accesses a specific image format available for
219 // image creation by name
220 //-------------------------------------------------
221
device_get_named_creatable_format(const std::string & format_name)222 const image_device_format *device_image_interface::device_get_named_creatable_format(const std::string &format_name) noexcept
223 {
224 for (auto &format : m_formatlist)
225 if (format->name() == format_name)
226 return format.get();
227 return nullptr;
228 }
229
230
231 //-------------------------------------------------
232 // add_format
233 //-------------------------------------------------
234
add_format(std::unique_ptr<image_device_format> && format)235 void device_image_interface::add_format(std::unique_ptr<image_device_format> &&format)
236 {
237 m_formatlist.push_back(std::move(format));
238 }
239
240
241 //-------------------------------------------------
242 // add_format
243 //-------------------------------------------------
244
add_format(std::string && name,std::string && description,std::string && extensions,std::string && optspec)245 void device_image_interface::add_format(std::string &&name, std::string &&description, std::string &&extensions, std::string &&optspec)
246 {
247 auto format = std::make_unique<image_device_format>(std::move(name), std::move(description), std::move(extensions), std::move(optspec));
248 add_format(std::move(format));
249 }
250
251
252 /****************************************************************************
253 ERROR HANDLING
254 ****************************************************************************/
255
256 //-------------------------------------------------
257 // image_clear_error - clear out any specified
258 // error
259 //-------------------------------------------------
260
clear_error()261 void device_image_interface::clear_error()
262 {
263 m_err = IMAGE_ERROR_SUCCESS;
264 if (!m_err_message.empty())
265 {
266 m_err_message.clear();
267 }
268 }
269
270
271
272 //-------------------------------------------------
273 // error - returns the error text for an image
274 // error
275 //-------------------------------------------------
276
277 static const char *const messages[] =
278 {
279 "",
280 "Internal error",
281 "Unsupported operation",
282 "Out of memory",
283 "File not found",
284 "Invalid image",
285 "File already open",
286 "Unspecified error"
287 };
288
error()289 const char *device_image_interface::error()
290 {
291 return (!m_err_message.empty()) ? m_err_message.c_str() : messages[m_err];
292 }
293
294
295
296 //-------------------------------------------------
297 // seterror - specifies an error on an image
298 //-------------------------------------------------
299
seterror(image_error_t err,const char * message)300 void device_image_interface::seterror(image_error_t err, const char *message)
301 {
302 clear_error();
303 m_err = err;
304 if (message != nullptr)
305 {
306 m_err_message = message;
307 }
308 }
309
310
311
312 //-------------------------------------------------
313 // message - used to display a message while
314 // loading
315 //-------------------------------------------------
316
message(const char * format,...)317 void device_image_interface::message(const char *format, ...)
318 {
319 va_list args;
320 char buffer[256];
321
322 /* format the message */
323 va_start(args, format);
324 vsnprintf(buffer, ARRAY_LENGTH(buffer), format, args);
325 va_end(args);
326
327 /* display the popup for a standard amount of time */
328 device().machine().ui().popup_time(5, "%s: %s",
329 basename(),
330 buffer);
331 }
332
333
334 /***************************************************************************
335 WORKING DIRECTORIES
336 ***************************************************************************/
337
338 //-------------------------------------------------
339 // try_change_working_directory - tries to change
340 // the working directory, but only if the directory
341 // actually exists
342 //-------------------------------------------------
343
try_change_working_directory(const std::string & subdir)344 bool device_image_interface::try_change_working_directory(const std::string &subdir)
345 {
346 const osd::directory::entry *entry;
347 bool success = false;
348 bool done = false;
349
350 auto directory = osd::directory::open(m_working_directory);
351 if (directory)
352 {
353 while (!done && (entry = directory->read()) != nullptr)
354 {
355 if (!core_stricmp(subdir.c_str(), entry->name))
356 {
357 done = true;
358 success = entry->type == osd::directory::entry::entry_type::DIR;
359 }
360 }
361
362 directory.reset();
363 }
364
365 // did we successfully identify the directory?
366 if (success)
367 m_working_directory = util::zippath_combine(m_working_directory, subdir);
368
369 return success;
370 }
371
372
373 //-------------------------------------------------
374 // setup_working_directory - sets up the working
375 // directory according to a few defaults
376 //-------------------------------------------------
377
setup_working_directory()378 void device_image_interface::setup_working_directory()
379 {
380 bool success = false;
381 // get user-specified directory and make sure it exists
382 m_working_directory = device().mconfig().options().sw_path();
383 // if multipath, get first
384 size_t i = m_working_directory.find_first_of(';');
385 if (i != std::string::npos)
386 m_working_directory.resize(i);
387 // validate directory
388 if (!m_working_directory.empty())
389 if (osd::directory::open(m_working_directory))
390 success = true;
391
392 // if not exist, use previous method
393 if (!success)
394 {
395 // first set up the working directory to be the starting directory
396 osd_get_full_path(m_working_directory, ".");
397 // now try browsing down to "software"
398 if (try_change_working_directory("software"))
399 success = true;
400 }
401
402 if (success)
403 {
404 // now down to a directory for this computer
405 int gamedrv = driver_list::find(device().machine().system());
406 while(gamedrv != -1 && !try_change_working_directory(driver_list::driver(gamedrv).name))
407 {
408 gamedrv = driver_list::compatible_with(gamedrv);
409 }
410 }
411 }
412
413
414 //-------------------------------------------------
415 // working_directory - returns the working
416 // directory to use for this image; this is
417 // valid even if not mounted
418 //-------------------------------------------------
419
working_directory()420 const std::string &device_image_interface::working_directory()
421 {
422 // check to see if we've never initialized the working directory
423 if (m_working_directory.empty())
424 setup_working_directory();
425
426 return m_working_directory;
427 }
428
429
430 //-------------------------------------------------
431 // software_entry - return a pointer to the
432 // software_info structure from the softlist
433 //-------------------------------------------------
434
software_entry() const435 const software_info *device_image_interface::software_entry() const noexcept
436 {
437 return !m_software_part_ptr ? nullptr : &m_software_part_ptr->info();
438 }
439
440
441 //-------------------------------------------------
442 // get_software_region
443 //-------------------------------------------------
444
get_software_region(const char * tag)445 u8 *device_image_interface::get_software_region(const char *tag)
446 {
447 if (!loaded_through_softlist())
448 return nullptr;
449
450 std::string full_tag = util::string_format("%s:%s", device().tag(), tag);
451 memory_region *region = device().machine().root_device().memregion(full_tag);
452 return region != nullptr ? region->base() : nullptr;
453 }
454
455
456 //-------------------------------------------------
457 // image_get_software_region_length
458 //-------------------------------------------------
459
get_software_region_length(const char * tag)460 u32 device_image_interface::get_software_region_length(const char *tag)
461 {
462 std::string full_tag = util::string_format("%s:%s", device().tag(), tag);
463 memory_region *region = device().machine().root_device().memregion(full_tag);
464 return region != nullptr ? region->bytes() : 0;
465 }
466
467
468 //-------------------------------------------------
469 // image_get_feature
470 //-------------------------------------------------
471
get_feature(const char * feature_name) const472 const char *device_image_interface::get_feature(const char *feature_name) const
473 {
474 return !m_software_part_ptr ? nullptr : m_software_part_ptr->feature(feature_name);
475 }
476
477
478 //-------------------------------------------------
479 // load_software_region -
480 //-------------------------------------------------
481
load_software_region(const char * tag,optional_shared_ptr<u8> & ptr)482 bool device_image_interface::load_software_region(const char *tag, optional_shared_ptr<u8> &ptr)
483 {
484 size_t size = get_software_region_length(tag);
485
486 if (size)
487 {
488 ptr.allocate(size);
489
490 memcpy(ptr, get_software_region(tag), size);
491 }
492
493 return size > 0;
494 }
495
496
497 // ****************************************************************************
498 // Hash info loading
499 //
500 // If the hash is not checked and the relevant info not loaded, force that info
501 // to be loaded
502 // ****************************************************************************
503
run_hash(util::core_file & file,u32 skip_bytes,util::hash_collection & hashes,const char * types)504 bool device_image_interface::run_hash(util::core_file &file, u32 skip_bytes, util::hash_collection &hashes, const char *types)
505 {
506 // reset the hash; we want to override existing data
507 hashes.reset();
508
509 // figure out the size, and "cap" the skip bytes
510 u64 size = file.size();
511 skip_bytes = (u32) std::min((u64) skip_bytes, size);
512
513 // seek to the beginning
514 file.seek(skip_bytes, SEEK_SET);
515 u64 position = skip_bytes;
516
517 // keep on reading hashes
518 hashes.begin(types);
519 while (position < size)
520 {
521 uint8_t buffer[8192];
522
523 // read bytes
524 const u32 count = (u32) std::min(size - position, (u64) sizeof(buffer));
525 const u32 actual_count = file.read(buffer, count);
526 if (actual_count == 0)
527 return false;
528 position += actual_count;
529
530 // and compute the hashes
531 hashes.buffer(buffer, actual_count);
532 }
533 hashes.end();
534
535 // cleanup
536 file.seek(0, SEEK_SET);
537 return true;
538 }
539
540
541
image_checkhash()542 bool device_image_interface::image_checkhash()
543 {
544 // only calculate CRC if it hasn't been calculated, and the open_mode is read only
545 u32 crcval;
546 if (!m_hash.crc(crcval) && is_readonly() && !m_created)
547 {
548 // do not cause a linear read of 600 megs please
549 // TODO: use SHA1 in the CHD header as the hash
550 if (image_type() == IO_CDROM)
551 return true;
552
553 // Skip calculating the hash when we have an image mounted through a software list
554 if (loaded_through_softlist())
555 return true;
556
557 // run the hash
558 if (!run_hash(*m_file, unhashed_header_length(), m_hash, util::hash_collection::HASH_TYPES_ALL))
559 return false;
560 }
561 return true;
562 }
563
564
calculate_hash_on_file(util::core_file & file) const565 util::hash_collection device_image_interface::calculate_hash_on_file(util::core_file &file) const
566 {
567 // calculate the hash
568 util::hash_collection hash;
569 if (!run_hash(file, unhashed_header_length(), hash, util::hash_collection::HASH_TYPES_ALL))
570 hash.reset();
571 return hash;
572 }
573
574
crc()575 u32 device_image_interface::crc()
576 {
577 u32 crc = 0;
578
579 image_checkhash();
580 m_hash.crc(crc);
581
582 return crc;
583 }
584
585
586 //-------------------------------------------------
587 // support_command_line_image_creation - do we
588 // want to support image creation from the front
589 // end command line?
590 //-------------------------------------------------
591
support_command_line_image_creation() const592 bool device_image_interface::support_command_line_image_creation() const noexcept
593 {
594 bool result;
595 switch (image_type())
596 {
597 case IO_PRINTER:
598 case IO_SERIAL:
599 case IO_PARALLEL:
600 // going by the assumption that these device image types should support this
601 // behavior; ideally we'd get rid of IO_* and just push this to the specific
602 // devices
603 result = true;
604 break;
605 default:
606 result = false;
607 break;
608 }
609 return result;
610 }
611
612
613 // ****************************************************************************
614 // Battery functions
615 //
616 // These functions provide transparent access to battery-backed RAM on an
617 // image; typically for cartridges.
618 // ****************************************************************************
619
620
621 //-------------------------------------------------
622 // battery_load - retrieves the battery
623 // backed RAM for an image. The file name is
624 // created from the machine driver name and the
625 // image name.
626 //-------------------------------------------------
627
battery_load(void * buffer,int length,int fill)628 void device_image_interface::battery_load(void *buffer, int length, int fill)
629 {
630 if (!buffer || (length <= 0))
631 throw emu_fatalerror("device_image_interface::battery_load: Must specify sensical buffer/length");
632
633 osd_file::error filerr;
634 int bytes_read = 0;
635 std::string fname = std::string(device().machine().system().name).append(PATH_SEPARATOR).append(m_basename_noext).append(".nv");
636
637 /* try to open the battery file and read it in, if possible */
638 emu_file file(device().machine().options().nvram_directory(), OPEN_FLAG_READ);
639 filerr = file.open(fname);
640 if (filerr == osd_file::error::NONE)
641 bytes_read = file.read(buffer, length);
642
643 // fill remaining bytes (if necessary)
644 memset(((char *)buffer) + bytes_read, fill, length - bytes_read);
645 }
646
battery_load(void * buffer,int length,const void * def_buffer)647 void device_image_interface::battery_load(void *buffer, int length, const void *def_buffer)
648 {
649 if (!buffer || (length <= 0))
650 throw emu_fatalerror("device_image_interface::battery_load: Must specify sensical buffer/length");
651
652 osd_file::error filerr;
653 int bytes_read = 0;
654 std::string fname = std::string(device().machine().system().name).append(PATH_SEPARATOR).append(m_basename_noext).append(".nv");
655
656 // try to open the battery file and read it in, if possible
657 emu_file file(device().machine().options().nvram_directory(), OPEN_FLAG_READ);
658 filerr = file.open(fname);
659 if (filerr == osd_file::error::NONE)
660 bytes_read = file.read(buffer, length);
661
662 // if no file was present, copy the default contents
663 if (!bytes_read && def_buffer)
664 std::memcpy(buffer, def_buffer, length);
665 }
666
667
668 //-------------------------------------------------
669 // battery_save - stores the battery
670 // backed RAM for an image. The file name is
671 // created from the machine driver name and the
672 // image name.
673 //-------------------------------------------------
674
battery_save(const void * buffer,int length)675 void device_image_interface::battery_save(const void *buffer, int length)
676 {
677 if (!buffer || (length <= 0))
678 throw emu_fatalerror("device_image_interface::battery_save: Must specify sensical buffer/length");
679
680 if (!device().machine().options().nvram_save())
681 return;
682
683 std::string fname = std::string(device().machine().system().name).append(PATH_SEPARATOR).append(m_basename_noext).append(".nv");
684
685 // try to open the battery file and write it out, if possible
686 emu_file file(device().machine().options().nvram_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
687 osd_file::error filerr = file.open(fname);
688 if (filerr == osd_file::error::NONE)
689 file.write(buffer, length);
690 }
691
692
693 //-------------------------------------------------
694 // uses_file_extension - update configuration
695 // based on completed device setup
696 //-------------------------------------------------
697
uses_file_extension(const char * file_extension) const698 bool device_image_interface::uses_file_extension(const char *file_extension) const
699 {
700 bool result = false;
701
702 if (file_extension[0] == '.')
703 file_extension++;
704
705 /* find the extensions */
706 std::string extensions(file_extensions());
707 char *ext = strtok((char*)extensions.c_str(),",");
708 while (ext != nullptr)
709 {
710 if (!core_stricmp(ext, file_extension))
711 {
712 result = true;
713 break;
714 }
715 ext = strtok (nullptr, ",");
716 }
717 return result;
718 }
719
720
721 // ***************************************************************************
722 // IMAGE LOADING
723 // ***************************************************************************
724
725 //-------------------------------------------------
726 // is_loaded - quick check to determine whether an
727 // image is loaded
728 //-------------------------------------------------
729
is_loaded()730 bool device_image_interface::is_loaded()
731 {
732 return (m_file != nullptr);
733 }
734
735 //-------------------------------------------------
736 // image_error_from_file_error - converts an image
737 // error to a file error
738 //-------------------------------------------------
739
image_error_from_file_error(osd_file::error filerr)740 image_error_t device_image_interface::image_error_from_file_error(osd_file::error filerr)
741 {
742 switch (filerr)
743 {
744 case osd_file::error::NONE:
745 return IMAGE_ERROR_SUCCESS;
746
747 case osd_file::error::NOT_FOUND:
748 case osd_file::error::ACCESS_DENIED:
749 // file not found (or otherwise cannot open)
750 return IMAGE_ERROR_FILENOTFOUND;
751
752 case osd_file::error::OUT_OF_MEMORY:
753 // out of memory
754 return IMAGE_ERROR_OUTOFMEMORY;
755
756 case osd_file::error::ALREADY_OPEN:
757 // this shouldn't happen
758 return IMAGE_ERROR_ALREADYOPEN;
759
760 case osd_file::error::FAILURE:
761 case osd_file::error::TOO_MANY_FILES:
762 case osd_file::error::INVALID_DATA:
763 default:
764 // other errors
765 return IMAGE_ERROR_INTERNAL;
766 }
767 }
768
769
770 //-------------------------------------------------
771 // load_image_by_path - loads an image with a
772 // specific path
773 //-------------------------------------------------
774
load_image_by_path(u32 open_flags,const std::string & path)775 image_error_t device_image_interface::load_image_by_path(u32 open_flags, const std::string &path)
776 {
777 std::string revised_path;
778
779 // attempt to read the file
780 auto const filerr = util::zippath_fopen(path, open_flags, m_file, revised_path);
781 if (filerr != osd_file::error::NONE)
782 return image_error_from_file_error(filerr);
783
784 m_readonly = (open_flags & OPEN_FLAG_WRITE) ? 0 : 1;
785 m_created = (open_flags & OPEN_FLAG_CREATE) ? 1 : 0;
786 set_image_filename(revised_path);
787 return IMAGE_ERROR_SUCCESS;
788 }
789
790
791 //-------------------------------------------------
792 // reopen_for_write
793 //-------------------------------------------------
794
reopen_for_write(const std::string & path)795 int device_image_interface::reopen_for_write(const std::string &path)
796 {
797 m_file.reset();
798
799 std::string revised_path;
800
801 // attempt to open the file for writing
802 auto const filerr = util::zippath_fopen(path, OPEN_FLAG_READ|OPEN_FLAG_WRITE|OPEN_FLAG_CREATE, m_file, revised_path);
803 if (filerr != osd_file::error::NONE)
804 return image_error_from_file_error(filerr);
805
806 // success!
807 m_readonly = 0;
808 m_created = 1;
809 set_image_filename(revised_path);
810
811 return IMAGE_ERROR_SUCCESS;
812 }
813
814
815 //-------------------------------------------------
816 // determine_open_plan - determines which open
817 // flags to use, and in what order
818 //-------------------------------------------------
819
determine_open_plan(bool is_create)820 std::vector<u32> device_image_interface::determine_open_plan(bool is_create)
821 {
822 std::vector<u32> open_plan;
823
824 // emit flags into a vector
825 if (!is_create && is_readable() && is_writeable())
826 open_plan.push_back(OPEN_FLAG_READ | OPEN_FLAG_WRITE);
827 if (!is_create && !is_readable() && is_writeable())
828 open_plan.push_back(OPEN_FLAG_WRITE);
829 if (!is_create && is_readable())
830 open_plan.push_back(OPEN_FLAG_READ);
831 if (is_create && is_writeable() && is_creatable())
832 open_plan.push_back(OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE);
833
834 return open_plan;
835 }
836
837
838 //-------------------------------------------------
839 // verify_length_and_hash - verify the length
840 // and hash signatures of a file
841 //-------------------------------------------------
842
verify_length_and_hash(emu_file * file,const char * name,u32 explength,const util::hash_collection & hashes)843 static int verify_length_and_hash(emu_file *file, const char *name, u32 explength, const util::hash_collection &hashes)
844 {
845 int retval = 0;
846 if (!file)
847 return 0;
848
849 // verify length
850 u32 actlength = file->size();
851 if (explength != actlength)
852 {
853 osd_printf_error("%s WRONG LENGTH (expected: %d found: %d)\n", name, explength, actlength);
854 retval++;
855 }
856
857 util::hash_collection &acthashes = file->hashes(hashes.hash_types().c_str());
858 if (hashes.flag(util::hash_collection::FLAG_NO_DUMP))
859 {
860 // If there is no good dump known, write it
861 osd_printf_error("%s NO GOOD DUMP KNOWN\n", name);
862 }
863 else if (hashes != acthashes)
864 {
865 // otherwise, it's just bad
866 osd_printf_error("%s WRONG CHECKSUMS:\n", name);
867 osd_printf_error(" EXPECTED: %s\n", hashes.macro_string());
868 osd_printf_error(" FOUND: %s\n", acthashes.macro_string());
869 retval++;
870 }
871 else if (hashes.flag(util::hash_collection::FLAG_BAD_DUMP))
872 {
873 // If it matches, but it is actually a bad dump, write it
874 osd_printf_error("%s NEEDS REDUMP\n",name);
875 }
876 return retval;
877 }
878
879
880 //-------------------------------------------------
881 // load_software - software image loading
882 //-------------------------------------------------
883
load_software(software_list_device & swlist,const char * swname,const rom_entry * start)884 bool device_image_interface::load_software(software_list_device &swlist, const char *swname, const rom_entry *start)
885 {
886 bool retval = false;
887 int warningcount = 0;
888 for (const rom_entry *region = start; region; region = rom_next_region(region))
889 {
890 // loop until we hit the end of this region
891 for (const rom_entry *romp = region + 1; !ROMENTRY_ISREGIONEND(romp); romp++)
892 {
893 // handle files
894 if (ROMENTRY_ISFILE(romp))
895 {
896 const software_info *const swinfo = swlist.find(swname);
897 if (!swinfo)
898 return false;
899
900 const u32 supported = swinfo->supported();
901 if (supported == SOFTWARE_SUPPORTED_PARTIAL)
902 osd_printf_error("WARNING: support for software %s (in list %s) is only partial\n", swname, swlist.list_name());
903 if (supported == SOFTWARE_SUPPORTED_NO)
904 osd_printf_error("WARNING: support for software %s (in list %s) is only preliminary\n", swname, swlist.list_name());
905
906 u32 crc = 0;
907 const bool has_crc = util::hash_collection(ROM_GETHASHDATA(romp)).crc(crc);
908 std::vector<const software_info *> parents;
909 std::vector<std::string> searchpath = rom_load_manager::get_software_searchpath(swlist, *swinfo);
910
911 // for historical reasons, add the search path for the software list device's owner
912 const device_t *const listowner = swlist.owner();
913 if (listowner)
914 {
915 std::vector<std::string> devsearch = listowner->searchpath();
916 for (std::string &path : devsearch)
917 searchpath.emplace_back(std::move(path));
918 }
919
920 // try to load the file
921 m_mame_file.reset(new emu_file(device().machine().options().media_path(), searchpath, OPEN_FLAG_READ));
922 m_mame_file->set_restrict_to_mediapath(1);
923 osd_file::error filerr;
924 if (has_crc)
925 filerr = m_mame_file->open(ROM_GETNAME(romp), crc);
926 else
927 filerr = m_mame_file->open(ROM_GETNAME(romp));
928 if (filerr != osd_file::error::NONE)
929 m_mame_file.reset();
930
931 warningcount += verify_length_and_hash(m_mame_file.get(), ROM_GETNAME(romp), ROM_GETLENGTH(romp), util::hash_collection(ROM_GETHASHDATA(romp)));
932
933 if (filerr == osd_file::error::NONE)
934 filerr = util::core_file::open_proxy(*m_mame_file, m_file);
935 if (filerr == osd_file::error::NONE)
936 retval = true;
937
938 break; // load first item for start
939 }
940 }
941 }
942
943 if (warningcount > 0)
944 osd_printf_error("WARNING: the software item might not run correctly.\n");
945
946 return retval;
947 }
948
949
950 //-------------------------------------------------
951 // load_internal - core image loading
952 //-------------------------------------------------
953
load_internal(const std::string & path,bool is_create,int create_format,util::option_resolution * create_args)954 image_init_result device_image_interface::load_internal(const std::string &path, bool is_create, int create_format, util::option_resolution *create_args)
955 {
956 // first unload the image
957 unload();
958
959 // clear any possible error messages
960 clear_error();
961
962 // we are now loading
963 m_is_loading = true;
964
965 // record the filename
966 set_image_filename(path);
967
968 if (core_opens_image_file())
969 {
970 // determine open plan
971 std::vector<u32> open_plan = determine_open_plan(is_create);
972
973 // attempt to open the file in various ways
974 for (auto iter = open_plan.cbegin(); !m_file && iter != open_plan.cend(); iter++)
975 {
976 // open the file
977 m_err = load_image_by_path(*iter, path);
978 if (m_err && (m_err != IMAGE_ERROR_FILENOTFOUND))
979 goto done;
980 }
981
982 // did we fail to find the file?
983 if (!is_loaded())
984 {
985 m_err = IMAGE_ERROR_FILENOTFOUND;
986 goto done;
987 }
988 }
989
990 // call device load or create
991 m_create_format = create_format;
992 m_create_args = create_args;
993
994 if (init_phase()==false) {
995 m_err = (finish_load() == image_init_result::PASS) ? IMAGE_ERROR_SUCCESS : IMAGE_ERROR_INTERNAL;
996 if (m_err)
997 goto done;
998 }
999 // success!
1000
1001 done:
1002 if (m_err!=0) {
1003 if (!init_phase())
1004 {
1005 if (device().machine().phase() == machine_phase::RUNNING)
1006 device().popmessage("Error: Unable to %s image '%s': %s", is_create ? "create" : "load", path, error());
1007 else
1008 osd_printf_error("Error: Unable to %s image '%s': %s\n", is_create ? "create" : "load", path, error());
1009 }
1010 clear();
1011 }
1012 return m_err ? image_init_result::FAIL : image_init_result::PASS;
1013 }
1014
1015
1016 //-------------------------------------------------
1017 // load - load an image into MAME
1018 //-------------------------------------------------
1019
load(const std::string & path)1020 image_init_result device_image_interface::load(const std::string &path)
1021 {
1022 // is this a reset on load item?
1023 if (is_reset_on_load() && !init_phase())
1024 {
1025 reset_and_load(path);
1026 return image_init_result::PASS;
1027 }
1028
1029 return load_internal(path, false, 0, nullptr);
1030 }
1031
1032
1033 //-------------------------------------------------
1034 // load_software - loads a softlist item by name
1035 //-------------------------------------------------
1036
load_software(const std::string & software_identifier)1037 image_init_result device_image_interface::load_software(const std::string &software_identifier)
1038 {
1039 // Is this a software part that forces a reset and we're at runtime? If so, get this loaded through reset_and_load
1040 if (is_reset_on_load() && !init_phase())
1041 {
1042 reset_and_load(software_identifier);
1043 return image_init_result::PASS;
1044 }
1045
1046 // Prepare to load
1047 unload();
1048 clear_error();
1049 m_is_loading = true;
1050
1051 // Check if there's a software list defined for this device and use that if we're not creating an image
1052 bool softload = load_software_part(software_identifier);
1053 if (!softload)
1054 {
1055 m_is_loading = false;
1056 return image_init_result::FAIL;
1057 }
1058
1059 // set up softlist stuff
1060 m_full_software_name = m_software_part_ptr->info().shortname();
1061
1062 // specify image name with softlist-derived names
1063 m_image_name = m_full_software_name;
1064 m_basename = m_full_software_name;
1065 m_basename_noext = m_full_software_name;
1066 m_filetype = use_software_list_file_extension_for_filetype() && m_mame_file != nullptr
1067 ? core_filename_extract_extension(m_mame_file->filename(), true)
1068 : "";
1069
1070 // Copy some image information when we have been loaded through a software list
1071 software_info &swinfo = m_software_part_ptr->info();
1072
1073 // sanitize
1074 if (swinfo.longname().empty() || swinfo.publisher().empty() || swinfo.year().empty())
1075 fatalerror("Each entry in an XML list must have all of the following fields: description, publisher, year!\n");
1076
1077 // store
1078 m_longname = swinfo.longname();
1079 m_manufacturer = swinfo.publisher();
1080 m_year = swinfo.year();
1081
1082 // set file type
1083 std::string filename = (m_mame_file != nullptr) && (m_mame_file->filename() != nullptr)
1084 ? m_mame_file->filename()
1085 : "";
1086 m_filetype = core_filename_extract_extension(filename, true);
1087
1088 // call finish_load if necessary
1089 if (init_phase() == false && (finish_load() != image_init_result::PASS))
1090 return image_init_result::FAIL;
1091
1092 return image_init_result::PASS;
1093 }
1094
1095
1096 //-------------------------------------------------
1097 // image_finish_load - special call - only use
1098 // from core
1099 //-------------------------------------------------
1100
finish_load()1101 image_init_result device_image_interface::finish_load()
1102 {
1103 image_init_result err = image_init_result::PASS;
1104
1105 if (m_is_loading)
1106 {
1107 if (!image_checkhash())
1108 {
1109 m_err = IMAGE_ERROR_INVALIDIMAGE;
1110 err = image_init_result::FAIL;
1111 }
1112
1113 if (err == image_init_result::PASS)
1114 {
1115 if (m_created)
1116 {
1117 err = call_create(m_create_format, m_create_args);
1118 if (err != image_init_result::PASS)
1119 {
1120 if (!m_err)
1121 m_err = IMAGE_ERROR_UNSPECIFIED;
1122 }
1123 }
1124 else
1125 {
1126 // using device load
1127 err = call_load();
1128 if (err != image_init_result::PASS)
1129 {
1130 if (!m_err)
1131 m_err = IMAGE_ERROR_UNSPECIFIED;
1132 }
1133 }
1134 }
1135 }
1136 m_is_loading = false;
1137 m_create_format = 0;
1138 m_create_args = nullptr;
1139 return err;
1140 }
1141
1142
1143 //-------------------------------------------------
1144 // create - create a image
1145 //-------------------------------------------------
1146
create(const std::string & path)1147 image_init_result device_image_interface::create(const std::string &path)
1148 {
1149 return create(path, nullptr, nullptr);
1150 }
1151
1152
1153 //-------------------------------------------------
1154 // create - create a image
1155 //-------------------------------------------------
1156
create(const std::string & path,const image_device_format * create_format,util::option_resolution * create_args)1157 image_init_result device_image_interface::create(const std::string &path, const image_device_format *create_format, util::option_resolution *create_args)
1158 {
1159 int format_index = 0;
1160 int cnt = 0;
1161 for (auto &format : m_formatlist)
1162 {
1163 if (create_format == format.get()) {
1164 format_index = cnt;
1165 break;
1166 }
1167 cnt++;
1168 }
1169 return load_internal(path, true, format_index, create_args);
1170 }
1171
1172
1173 //-------------------------------------------------
1174 // reset_and_load - called internally when we try
1175 // to load an is_reset_on_load() item; will reset
1176 // the emulation and record this image to be loaded
1177 //-------------------------------------------------
1178
reset_and_load(const std::string & path)1179 void device_image_interface::reset_and_load(const std::string &path)
1180 {
1181 // first make sure the reset is scheduled
1182 device().machine().schedule_hard_reset();
1183
1184 // and record the new load
1185 device().machine().options().image_option(instance_name()).specify(path);
1186
1187 // record that we're reset and loading
1188 m_is_reset_and_loading = true;
1189 }
1190
1191
1192 //-------------------------------------------------
1193 // clear - clear all internal data pertaining
1194 // to an image
1195 //-------------------------------------------------
1196
clear()1197 void device_image_interface::clear()
1198 {
1199 m_mame_file.reset();
1200 m_file.reset();
1201
1202 m_image_name.clear();
1203 m_readonly = false;
1204 m_created = false;
1205 m_create_format = 0;
1206 m_create_args = nullptr;
1207
1208 m_longname.clear();
1209 m_manufacturer.clear();
1210 m_year.clear();
1211 m_basename.clear();
1212 m_basename_noext.clear();
1213 m_filetype.clear();
1214
1215 m_full_software_name.clear();
1216 m_software_part_ptr = nullptr;
1217 m_software_list_name.clear();
1218 }
1219
1220
1221 //-------------------------------------------------
1222 // unload - main call to unload an image
1223 //-------------------------------------------------
1224
unload()1225 void device_image_interface::unload()
1226 {
1227 if (is_loaded() || loaded_through_softlist())
1228 {
1229 call_unload();
1230 }
1231 clear();
1232 clear_error();
1233 }
1234
1235
1236 //-------------------------------------------------
1237 // create_option_guide
1238 //-------------------------------------------------
1239
OPTION_GUIDE_START(null_option_guide)1240 OPTION_GUIDE_START(null_option_guide)
1241 OPTION_GUIDE_END
1242
1243 const util::option_guide &device_image_interface::create_option_guide() const
1244 {
1245 return null_option_guide;
1246 }
1247
1248 //-------------------------------------------------
1249 // update_names - update brief and instance names
1250 //-------------------------------------------------
1251
update_names()1252 void device_image_interface::update_names()
1253 {
1254 const char *inst_name = custom_instance_name();
1255 const char *brief_name = custom_brief_instance_name();
1256 if (inst_name == nullptr)
1257 inst_name = device_typename(image_type());
1258 if (brief_name == nullptr)
1259 brief_name = device_brieftypename(image_type());
1260
1261 // count instances of the general image type, or device type if custom
1262 int count = 0;
1263 int index = -1;
1264 for (const device_image_interface &image : image_interface_iterator(device().mconfig().root_device()))
1265 {
1266 if (this == &image)
1267 index = count;
1268 const char *other_name = image.custom_instance_name();
1269 if (!other_name)
1270 other_name = device_typename(image.image_type());
1271
1272 if (other_name == inst_name || !strcmp(other_name, inst_name))
1273 count++;
1274 }
1275
1276 m_canonical_instance_name = string_format("%s%d", inst_name, index + 1);
1277 if (count > 1)
1278 {
1279 m_instance_name = m_canonical_instance_name;
1280 m_brief_instance_name = string_format("%s%d", brief_name, index + 1);
1281 }
1282 else
1283 {
1284 m_instance_name = inst_name;
1285 m_brief_instance_name = brief_name;
1286 }
1287 }
1288
1289 //-------------------------------------------------
1290 // find_software_item
1291 //-------------------------------------------------
1292
find_software_item(const std::string & identifier,bool restrict_to_interface,software_list_device ** dev) const1293 const software_part *device_image_interface::find_software_item(const std::string &identifier, bool restrict_to_interface, software_list_device **dev) const
1294 {
1295 // split full software name into software list name and short software name
1296 std::string list_name, software_name, part_name;
1297 if (!software_name_parse(identifier, &list_name, &software_name, &part_name))
1298 return nullptr;
1299
1300 // determine interface
1301 const char *interface = restrict_to_interface
1302 ? image_interface()
1303 : nullptr;
1304
1305 // find the software list if explicitly specified
1306 for (software_list_device &swlistdev : software_list_device_iterator(device().mconfig().root_device()))
1307 {
1308 if (list_name.empty() || (list_name == swlistdev.list_name()))
1309 {
1310 const software_info *info = swlistdev.find(software_name);
1311 if (info != nullptr)
1312 {
1313 const software_part *part = info->find_part(part_name, interface);
1314 if (part != nullptr)
1315 {
1316 if (dev != nullptr)
1317 *dev = &swlistdev;
1318 return part;
1319 }
1320 }
1321 }
1322
1323 if (software_name == swlistdev.list_name())
1324 {
1325 // ad hoc handling for the case path = swlist_name:swinfo_name (e.g.
1326 // gameboy:sml) which is not handled properly by software_name_split
1327 // since the function cannot distinguish between this and the case
1328 // path = swinfo_name:swpart_name
1329 const software_info *info = swlistdev.find(part_name);
1330 if (info != nullptr)
1331 {
1332 const software_part *part = info->find_part("", interface);
1333 if (part != nullptr)
1334 {
1335 if (dev != nullptr)
1336 *dev = &swlistdev;
1337 return part;
1338 }
1339 }
1340 }
1341 }
1342
1343 // if explicitly specified and not found, just error here
1344 if (dev != nullptr)
1345 *dev = nullptr;
1346 return nullptr;
1347 }
1348
1349
1350 //-------------------------------------------------
1351 // get_software_list_loader
1352 //-------------------------------------------------
1353
get_software_list_loader() const1354 const software_list_loader &device_image_interface::get_software_list_loader() const
1355 {
1356 return false_software_list_loader::instance();
1357 }
1358
1359
1360 //-------------------------------------------------
1361 // load_software_part
1362 //
1363 // Load a software part for a device. The part to
1364 // load is determined by the "path", software lists
1365 // configured for a driver, and the interface
1366 // supported by the device.
1367 //
1368 // returns true if the software could be loaded,
1369 // false otherwise. If the software could be loaded
1370 // sw_info and sw_part are also set.
1371 //-------------------------------------------------
1372
load_software_part(const std::string & identifier)1373 bool device_image_interface::load_software_part(const std::string &identifier)
1374 {
1375 // if no match has been found, we suggest similar shortnames
1376 software_list_device *swlist;
1377 m_software_part_ptr = find_software_item(identifier, true, &swlist);
1378 if (m_software_part_ptr == nullptr)
1379 {
1380 software_list_device::display_matches(device().machine().config(), image_interface(), identifier);
1381 return false;
1382 }
1383
1384 // Load the software part
1385 const char *swname = m_software_part_ptr->info().shortname().c_str();
1386 const rom_entry *start_entry = m_software_part_ptr->romdata().data();
1387 const software_list_loader &loader = get_software_list_loader();
1388 bool result = loader.load_software(*this, *swlist, swname, start_entry);
1389
1390 // check compatibility
1391 switch (swlist->is_compatible(*m_software_part_ptr))
1392 {
1393 case SOFTWARE_IS_COMPATIBLE:
1394 break;
1395
1396 case SOFTWARE_IS_INCOMPATIBLE:
1397 swlist->popmessage("WARNING! the set %s might not work on this system due to incompatible filter(s) '%s'\n", m_software_part_ptr->info().shortname(), swlist->filter());
1398 break;
1399
1400 case SOFTWARE_NOT_COMPATIBLE:
1401 swlist->popmessage("WARNING! the set %s might not work on this system due to missing filter(s) '%s'\n", m_software_part_ptr->info().shortname(), swlist->filter());
1402 break;
1403 }
1404
1405 // check requirements and load those images
1406 const char *requirement = m_software_part_ptr->feature("requirement");
1407 if (requirement != nullptr)
1408 {
1409 const software_part *req_swpart = find_software_item(requirement, false);
1410 if (req_swpart != nullptr)
1411 {
1412 device_image_interface *req_image = software_list_device::find_mountable_image(device().mconfig(), *req_swpart);
1413 if (req_image != nullptr)
1414 req_image->load_software(requirement);
1415 }
1416 }
1417
1418 m_software_list_name = swlist->list_name();
1419 return result;
1420 }
1421
1422 //-------------------------------------------------
1423 // software_get_default_slot
1424 //-------------------------------------------------
1425
software_get_default_slot(const char * default_card_slot) const1426 std::string device_image_interface::software_get_default_slot(const char *default_card_slot) const
1427 {
1428 std::string result;
1429
1430 const std::string &image_name(device().mconfig().options().image_option(instance_name()).value());
1431 if (!image_name.empty())
1432 {
1433 result.assign(default_card_slot);
1434 const software_part *swpart = find_software_item(image_name, true);
1435 if (swpart != nullptr)
1436 {
1437 const char *slot = swpart->feature("slot");
1438 if (slot != nullptr)
1439 result.assign(slot);
1440 }
1441 }
1442 return result;
1443 }
1444
1445
1446 //-------------------------------------------------
1447 // init_phase
1448 //-------------------------------------------------
1449
init_phase() const1450 bool device_image_interface::init_phase() const
1451 {
1452 // diimage.cpp has quite a bit of logic that randomly decides to behave
1453 // differently at startup; this is an enc[r]apsulation of the "logic"
1454 // that switches these behaviors
1455 return !device().has_running_machine()
1456 || device().machine().phase() == machine_phase::INIT;
1457 }
1458
1459
1460 //----------------------------------------------------------------------------
1461
image_fseek_thunk(void * file,s64 offset,int whence)1462 static int image_fseek_thunk(void *file, s64 offset, int whence)
1463 {
1464 device_image_interface *image = (device_image_interface *) file;
1465 return image->fseek(offset, whence);
1466 }
1467
image_fread_thunk(void * file,void * buffer,size_t length)1468 static size_t image_fread_thunk(void *file, void *buffer, size_t length)
1469 {
1470 device_image_interface *image = (device_image_interface *) file;
1471 return image->fread(buffer, length);
1472 }
1473
image_fwrite_thunk(void * file,const void * buffer,size_t length)1474 static size_t image_fwrite_thunk(void *file, const void *buffer, size_t length)
1475 {
1476 device_image_interface *image = (device_image_interface *) file;
1477 return image->fwrite(buffer, length);
1478 }
1479
image_fsize_thunk(void * file)1480 static u64 image_fsize_thunk(void *file)
1481 {
1482 device_image_interface *image = (device_image_interface *) file;
1483 return image->length();
1484 }
1485
1486 //----------------------------------------------------------------------------
1487
1488 struct io_procs image_ioprocs =
1489 {
1490 nullptr,
1491 image_fseek_thunk,
1492 image_fread_thunk,
1493 image_fwrite_thunk,
1494 image_fsize_thunk
1495 };
1496