1 // license:BSD-3-Clause
2 // copyright-holders:Nicola Salmoria,Aaron Giles,Vas Crabb
3 /*********************************************************************
4 
5     romload.h
6 
7     ROM loading functions.
8 
9 *********************************************************************/
10 
11 #ifndef MAME_EMU_ROMLOAD_H
12 #define MAME_EMU_ROMLOAD_H
13 
14 #pragma once
15 
16 #include "chd.h"
17 
18 #include <functional>
19 #include <initializer_list>
20 #include <string>
21 #include <type_traits>
22 #include <vector>
23 
24 
25 /***************************************************************************
26     TYPE DEFINITIONS
27 ***************************************************************************/
28 
29 
30 /***************************************************************************
31     MACROS
32 ***************************************************************************/
33 
ROMENTRY_UNWRAP(T const & r)34 template <typename T> inline std::enable_if_t<!std::is_pointer<T>::value, T const &> ROMENTRY_UNWRAP(T const &r) { return r; }
ROMENTRY_UNWRAP(T const * r)35 template <typename T> inline T const &ROMENTRY_UNWRAP(T const *r) { return *r; }
36 
37 /* ----- per-entry macros ----- */
ROMENTRY_GETTYPE(T const & r)38 template <typename T> inline u32  ROMENTRY_GETTYPE(T const &r)         { return ROMENTRY_UNWRAP(r).get_flags() & ROMENTRY_TYPEMASK; }
ROMENTRY_ISSPECIAL(T const & r)39 template <typename T> inline bool ROMENTRY_ISSPECIAL(T const &r)       { return ROMENTRY_GETTYPE(r) != ROMENTRYTYPE_ROM; }
ROMENTRY_ISFILE(T const & r)40 template <typename T> inline bool ROMENTRY_ISFILE(T const &r)          { return ROMENTRY_GETTYPE(r) == ROMENTRYTYPE_ROM; }
ROMENTRY_ISREGION(T const & r)41 template <typename T> inline bool ROMENTRY_ISREGION(T const &r)        { return ROMENTRY_GETTYPE(r) == ROMENTRYTYPE_REGION; }
ROMENTRY_ISEND(T const & r)42 template <typename T> inline bool ROMENTRY_ISEND(T const &r)           { return ROMENTRY_GETTYPE(r) == ROMENTRYTYPE_END; }
ROMENTRY_ISRELOAD(T const & r)43 template <typename T> inline bool ROMENTRY_ISRELOAD(T const &r)        { return ROMENTRY_GETTYPE(r) == ROMENTRYTYPE_RELOAD; }
ROMENTRY_ISCONTINUE(T const & r)44 template <typename T> inline bool ROMENTRY_ISCONTINUE(T const &r)      { return ROMENTRY_GETTYPE(r) == ROMENTRYTYPE_CONTINUE; }
ROMENTRY_ISFILL(T const & r)45 template <typename T> inline bool ROMENTRY_ISFILL(T const &r)          { return ROMENTRY_GETTYPE(r) == ROMENTRYTYPE_FILL; }
ROMENTRY_ISCOPY(T const & r)46 template <typename T> inline bool ROMENTRY_ISCOPY(T const &r)          { return ROMENTRY_GETTYPE(r) == ROMENTRYTYPE_COPY; }
ROMENTRY_ISIGNORE(T const & r)47 template <typename T> inline bool ROMENTRY_ISIGNORE(T const &r)        { return ROMENTRY_GETTYPE(r) == ROMENTRYTYPE_IGNORE; }
ROMENTRY_ISSYSTEM_BIOS(T const & r)48 template <typename T> inline bool ROMENTRY_ISSYSTEM_BIOS(T const &r)   { return ROMENTRY_GETTYPE(r) == ROMENTRYTYPE_SYSTEM_BIOS; }
ROMENTRY_ISDEFAULT_BIOS(T const & r)49 template <typename T> inline bool ROMENTRY_ISDEFAULT_BIOS(T const &r)  { return ROMENTRY_GETTYPE(r) == ROMENTRYTYPE_DEFAULT_BIOS; }
ROMENTRY_ISPARAMETER(T const & r)50 template <typename T> inline bool ROMENTRY_ISPARAMETER(T const &r)     { return ROMENTRY_GETTYPE(r) == ROMENTRYTYPE_PARAMETER; }
ROMENTRY_ISREGIONEND(T const & r)51 template <typename T> inline bool ROMENTRY_ISREGIONEND(T const &r)     { return ROMENTRY_ISREGION(r) || ROMENTRY_ISPARAMETER(r) || ROMENTRY_ISEND(r); }
52 
53 /* ----- per-region macros ----- */
54 #define ROMREGION_GETTAG(r)         ((r)->name().c_str())
ROMREGION_GETLENGTH(T const & r)55 template <typename T> inline u32  ROMREGION_GETLENGTH(T const &r)      { return ROMENTRY_UNWRAP(r).get_length(); }
ROMREGION_GETFLAGS(T const & r)56 template <typename T> inline u32  ROMREGION_GETFLAGS(T const &r)       { return ROMENTRY_UNWRAP(r).get_flags(); }
ROMREGION_GETWIDTH(T const & r)57 template <typename T> inline u32  ROMREGION_GETWIDTH(T const &r)       { return 8 << ((ROMREGION_GETFLAGS(r) & ROMREGION_WIDTHMASK) >> 8); }
ROMREGION_ISLITTLEENDIAN(T const & r)58 template <typename T> inline bool ROMREGION_ISLITTLEENDIAN(T const &r) { return (ROMREGION_GETFLAGS(r) & ROMREGION_ENDIANMASK) == ROMREGION_LE; }
ROMREGION_ISBIGENDIAN(T const & r)59 template <typename T> inline bool ROMREGION_ISBIGENDIAN(T const &r)    { return (ROMREGION_GETFLAGS(r) & ROMREGION_ENDIANMASK) == ROMREGION_BE; }
ROMREGION_ISINVERTED(T const & r)60 template <typename T> inline bool ROMREGION_ISINVERTED(T const &r)     { return (ROMREGION_GETFLAGS(r) & ROMREGION_INVERTMASK) == ROMREGION_INVERT; }
ROMREGION_ISERASE(T const & r)61 template <typename T> inline bool ROMREGION_ISERASE(T const &r)        { return (ROMREGION_GETFLAGS(r) & ROMREGION_ERASEMASK) == ROMREGION_ERASE; }
ROMREGION_GETERASEVAL(T const & r)62 template <typename T> inline u32  ROMREGION_GETERASEVAL(T const &r)    { return (ROMREGION_GETFLAGS(r) & ROMREGION_ERASEVALMASK) >> 16; }
ROMREGION_GETDATATYPE(T const & r)63 template <typename T> inline u32  ROMREGION_GETDATATYPE(T const &r)    { return ROMREGION_GETFLAGS(r) & ROMREGION_DATATYPEMASK; }
ROMREGION_ISROMDATA(T const & r)64 template <typename T> inline bool ROMREGION_ISROMDATA(T const &r)      { return ROMREGION_GETDATATYPE(r) == ROMREGION_DATATYPEROM; }
ROMREGION_ISDISKDATA(T const & r)65 template <typename T> inline bool ROMREGION_ISDISKDATA(T const &r)     { return ROMREGION_GETDATATYPE(r) == ROMREGION_DATATYPEDISK; }
66 
67 
68 /* ----- per-ROM macros ----- */
69 #define ROM_GETNAME(r)              ((r)->name().c_str())
70 #define ROM_SAFEGETNAME(r)          (ROMENTRY_ISFILL(r) ? "fill" : ROMENTRY_ISCOPY(r) ? "copy" : ROM_GETNAME(r))
ROM_GETOFFSET(T const & r)71 template <typename T> inline u32  ROM_GETOFFSET(T const &r)            { return ROMENTRY_UNWRAP(r).get_offset(); }
ROM_GETLENGTH(T const & r)72 template <typename T> inline u32  ROM_GETLENGTH(T const &r)            { return ROMENTRY_UNWRAP(r).get_length(); }
ROM_GETFLAGS(T const & r)73 template <typename T> inline u32  ROM_GETFLAGS(T const &r)             { return ROMENTRY_UNWRAP(r).get_flags(); }
74 #define ROM_GETHASHDATA(r)          ((r)->hashdata().c_str())
ROM_ISOPTIONAL(T const & r)75 template <typename T> inline bool ROM_ISOPTIONAL(T const &r)           { return (ROM_GETFLAGS(r) & ROM_OPTIONALMASK) == ROM_OPTIONAL; }
ROM_GETGROUPSIZE(T const & r)76 template <typename T> inline u32  ROM_GETGROUPSIZE(T const &r)         { return ((ROM_GETFLAGS(r) & ROM_GROUPMASK) >> 8) + 1; }
ROM_GETSKIPCOUNT(T const & r)77 template <typename T> inline u32  ROM_GETSKIPCOUNT(T const &r)         { return (ROM_GETFLAGS(r) & ROM_SKIPMASK) >> 12; }
ROM_ISREVERSED(T const & r)78 template <typename T> inline bool ROM_ISREVERSED(T const &r)           { return (ROM_GETFLAGS(r) & ROM_REVERSEMASK) == ROM_REVERSE; }
ROM_GETBITWIDTH(T const & r)79 template <typename T> inline u32  ROM_GETBITWIDTH(T const &r)          { return (ROM_GETFLAGS(r) & ROM_BITWIDTHMASK) ? ((ROM_GETFLAGS(r) & ROM_BITWIDTHMASK) >> 16) : 8; }
ROM_GETBITSHIFT(T const & r)80 template <typename T> inline u32  ROM_GETBITSHIFT(T const &r)          { return (ROM_GETFLAGS(r) & ROM_BITSHIFTMASK) >> 20; }
ROM_INHERITSFLAGS(T const & r)81 template <typename T> inline bool ROM_INHERITSFLAGS(T const &r)        { return (ROM_GETFLAGS(r) & ROM_INHERITFLAGSMASK) == ROM_INHERITFLAGS; }
ROM_GETBIOSFLAGS(T const & r)82 template <typename T> inline u32  ROM_GETBIOSFLAGS(T const &r)         { return (ROM_GETFLAGS(r) & ROM_BIOSFLAGSMASK) >> 24; }
83 
84 
85 /* ----- per-disk macros ----- */
DISK_GETINDEX(T const & r)86 template <typename T> inline u32  DISK_GETINDEX(T const &r)            { return ROMENTRY_UNWRAP(r).get_offset(); }
DISK_ISREADONLY(T const & r)87 template <typename T> inline bool DISK_ISREADONLY(T const &r)          { return (ROM_GETFLAGS(r) & DISK_READONLYMASK) == DISK_READONLY; }
88 
89 
90 namespace romload {
91 
92 template <typename T>
93 class const_entry_iterator
94 {
95 protected:
96 	tiny_rom_entry const *m_data;
97 
const_entry_iterator()98 	constexpr const_entry_iterator() noexcept : m_data(nullptr) { }
const_entry_iterator(tiny_rom_entry const * data)99 	constexpr const_entry_iterator(tiny_rom_entry const *data) noexcept : m_data(data) { }
100 	constexpr const_entry_iterator(const_entry_iterator const &) noexcept = default;
101 	const_entry_iterator(const_entry_iterator &&) noexcept = default;
102 	const_entry_iterator &operator=(const_entry_iterator const &) noexcept = default;
103 	const_entry_iterator &operator=(const_entry_iterator &&) noexcept = default;
104 
105 public:
106 	typedef T value_type;
107 	typedef value_type const *pointer;
108 	typedef value_type const &reference;
109 	typedef std::ptrdiff_t difference_type;
110 	typedef std::forward_iterator_tag iterator_category;
111 
112 	reference operator*() const noexcept { return reinterpret_cast<reference>(*m_data); }
113 	pointer operator->() const noexcept { return reinterpret_cast<pointer>(m_data); }
114 };
115 
116 
117 class file final : tiny_rom_entry
118 {
119 private:
120 	file() = default;
121 	file(file const &) = delete;
122 	file &operator=(file const &) = delete;
123 
124 public:
125 	// ROM
get_name()126 	constexpr char const *get_name()       const { return name; }
get_offset()127 	constexpr u32         get_offset()     const { return offset; }
get_length()128 	constexpr u32         get_length()     const { return length; }
get_flags()129 	constexpr u32         get_flags()      const { return flags; }
get_hashdata()130 	constexpr char const *get_hashdata()   const { return hashdata; }
is_optional()131 	constexpr bool        is_optional()    const { return (flags & ROM_OPTIONALMASK) == ROM_OPTIONAL; }
get_groupsize()132 	constexpr u32         get_groupsize()  const { return ((flags & ROM_GROUPMASK) >> 8) + 1; }
get_skipcount()133 	constexpr u32         get_skipcount()  const { return (flags & ROM_SKIPMASK) >> 12; }
is_reversed()134 	constexpr bool        is_reversed()    const { return (flags & ROM_REVERSEMASK) == ROM_REVERSE; }
get_bitwidth()135 	constexpr u32         get_bitwidth()   const { return (flags & ROM_BITWIDTHMASK) ? ((flags & ROM_BITWIDTHMASK) >> 16) : 8; }
get_bitshift()136 	constexpr u32         get_bitshift()   const { return (flags & ROM_BITSHIFTMASK) >> 20; }
inherits_flags()137 	constexpr bool        inherits_flags() const { return (flags & ROM_INHERITFLAGSMASK) == ROM_INHERITFLAGS; }
get_bios_flags()138 	constexpr u32         get_bios_flags() const { return (flags & ROM_BIOSFLAGSMASK) >> 24; }
139 
140 	// disk
get_index()141 	constexpr u32         get_index()      const { return offset; }
is_readonly()142 	constexpr bool        is_readonly()    const { return (flags & DISK_READONLYMASK) == DISK_READONLY; }
143 };
144 
145 class files
146 {
147 private:
148 	tiny_rom_entry const *m_data;
149 
150 public:
151 	class const_iterator : public const_entry_iterator<file>
152 	{
153 	private:
154 		friend class files;
155 
const_iterator(tiny_rom_entry const * data)156 		constexpr const_iterator(tiny_rom_entry const *data) noexcept : const_entry_iterator<file>(data) { }
157 
158 	public:
159 		constexpr const_iterator() noexcept = default;
160 		constexpr const_iterator(const_iterator const &) noexcept = default;
161 		const_iterator(const_iterator &&) noexcept = default;
162 		const_iterator &operator=(const_iterator const &) noexcept = default;
163 		const_iterator &operator=(const_iterator &&) noexcept = default;
164 
165 		const_iterator &operator++() noexcept
166 		{
167 			while (m_data)
168 			{
169 				++m_data;
170 				if (ROMENTRY_ISFILE(m_data))
171 					break;
172 				else if (ROMENTRY_ISREGIONEND(m_data))
173 					m_data = nullptr;
174 			}
175 			return *this;
176 		}
177 
178 		const_iterator operator++(int) noexcept { const_iterator result(*this); operator++(); return result; }
179 
180 		constexpr bool operator==(const_iterator const &rhs) const noexcept { return m_data == rhs.m_data; }
181 		constexpr bool operator!=(const_iterator const &rhs) const noexcept { return m_data != rhs.m_data; }
182 	};
183 
files(tiny_rom_entry const * data)184 	files(tiny_rom_entry const *data) : m_data(data)
185 	{
186 		while (m_data && !ROMENTRY_ISFILE(m_data))
187 		{
188 			if (ROMENTRY_ISREGIONEND(m_data))
189 				m_data = nullptr;
190 			else
191 				++m_data;
192 		}
193 	}
194 
begin()195 	const_iterator begin() const { return const_iterator(m_data); }
cbegin()196 	const_iterator cbegin() const { return const_iterator(m_data); }
end()197 	const_iterator end() const { return const_iterator(nullptr); }
cend()198 	const_iterator cend() const { return const_iterator(nullptr); }
199 };
200 
201 
202 class region final : tiny_rom_entry
203 {
204 private:
205 	region() = default;
206 	region(region const &) = delete;
207 	region &operator=(region const &) = delete;
208 
209 public:
get_tag()210 	constexpr char const *get_tag()         const { return name; }
get_length()211 	constexpr u32         get_length()      const { return length; }
get_width()212 	constexpr u32         get_width()       const { return 8 << ((flags & ROMREGION_WIDTHMASK) >> 8); }
is_littleendian()213 	constexpr bool        is_littleendian() const { return (flags & ROMREGION_ENDIANMASK) == ROMREGION_LE; }
is_bigendian()214 	constexpr bool        is_bigendian()    const { return (flags & ROMREGION_ENDIANMASK) == ROMREGION_BE; }
is_inverted()215 	constexpr bool        is_inverted()     const { return (flags & ROMREGION_INVERTMASK) == ROMREGION_INVERT; }
is_erase()216 	constexpr bool        is_erase()        const { return (flags & ROMREGION_ERASEMASK) == ROMREGION_ERASE; }
get_eraseval()217 	constexpr u32         get_eraseval()    const { return (flags & ROMREGION_ERASEVALMASK) >> 16; }
get_datatype()218 	constexpr u32         get_datatype()    const { return flags & ROMREGION_DATATYPEMASK; }
is_romdata()219 	constexpr bool        is_romdata()      const { return get_datatype() == ROMREGION_DATATYPEROM; }
is_diskdata()220 	constexpr bool        is_diskdata()     const { return get_datatype() == ROMREGION_DATATYPEDISK; }
221 
get_files()222 	files get_files() const { return files(static_cast<tiny_rom_entry const *>(this) + 1); }
223 };
224 
225 class regions
226 {
227 private:
228 	tiny_rom_entry const *m_data;
229 
230 public:
231 	class const_iterator : public const_entry_iterator<region>
232 	{
233 	private:
234 		friend class regions;
235 
const_iterator(tiny_rom_entry const * data)236 		constexpr const_iterator(tiny_rom_entry const *data) noexcept : const_entry_iterator<region>(data) { }
237 
238 	public:
239 		constexpr const_iterator() noexcept = default;
240 		constexpr const_iterator(const_iterator const &) noexcept = default;
241 		const_iterator(const_iterator &&) noexcept = default;
242 		const_iterator &operator=(const_iterator const &) noexcept = default;
243 		const_iterator &operator=(const_iterator &&) noexcept = default;
244 
245 		const_iterator &operator++() noexcept
246 		{
247 			while (m_data)
248 			{
249 				++m_data;
250 				if (ROMENTRY_ISREGION(m_data))
251 					break;
252 				else if (ROMENTRY_ISEND(m_data))
253 					m_data = nullptr;
254 			}
255 			return *this;
256 		}
257 
258 		const_iterator operator++(int) noexcept { const_iterator result(*this); operator++(); return result; }
259 
260 		constexpr bool operator==(const_iterator const &rhs) const noexcept { return m_data == rhs.m_data; }
261 		constexpr bool operator!=(const_iterator const &rhs) const noexcept { return m_data != rhs.m_data; }
262 	};
263 
regions(tiny_rom_entry const * data)264 	regions(tiny_rom_entry const *data) : m_data(data)
265 	{
266 		while (m_data && !ROMENTRY_ISREGION(m_data))
267 		{
268 			if (ROMENTRY_ISEND(m_data))
269 				m_data = nullptr;
270 			else
271 				++m_data;
272 		}
273 	}
274 
begin()275 	const_iterator begin() const { return const_iterator(m_data); }
cbegin()276 	const_iterator cbegin() const { return const_iterator(m_data); }
end()277 	const_iterator end() const { return const_iterator(nullptr); }
cend()278 	const_iterator cend() const { return const_iterator(nullptr); }
279 };
280 
281 
282 class system_bios final : tiny_rom_entry
283 {
284 private:
285 	system_bios() = default;
286 	system_bios(system_bios const &) = delete;
287 	system_bios &operator=(system_bios const &) = delete;
288 
289 public:
get_value()290 	constexpr u32         get_value()       const { return (flags & ROM_BIOSFLAGSMASK) >> 24; }
get_name()291 	constexpr char const *get_name()        const { return name; }
get_description()292 	constexpr char const *get_description() const { return hashdata; }
293 };
294 
295 class system_bioses
296 {
297 private:
298 	tiny_rom_entry const *m_data;
299 
300 public:
301 	class const_iterator : public const_entry_iterator<system_bios>
302 	{
303 	private:
304 		friend class system_bioses;
305 
const_iterator(tiny_rom_entry const * data)306 		constexpr const_iterator(tiny_rom_entry const *data) noexcept : const_entry_iterator<system_bios>(data) { }
307 
308 	public:
309 		constexpr const_iterator() noexcept = default;
310 		constexpr const_iterator(const_iterator const &) noexcept = default;
311 		const_iterator(const_iterator &&) noexcept = default;
312 		const_iterator &operator=(const_iterator const &) noexcept = default;
313 		const_iterator &operator=(const_iterator &&) noexcept = default;
314 
315 		const_iterator &operator++() noexcept
316 		{
317 			while (m_data)
318 			{
319 				++m_data;
320 				if (ROMENTRY_ISSYSTEM_BIOS(m_data))
321 					break;
322 				else if (ROMENTRY_ISEND(m_data))
323 					m_data = nullptr;
324 			}
325 			return *this;
326 		}
327 
328 		const_iterator operator++(int) noexcept { const_iterator result(*this); operator++(); return result; }
329 
330 		constexpr bool operator==(const_iterator const &rhs) const noexcept { return m_data == rhs.m_data; }
331 		constexpr bool operator!=(const_iterator const &rhs) const noexcept { return m_data != rhs.m_data; }
332 	};
333 
system_bioses(tiny_rom_entry const * data)334 	system_bioses(tiny_rom_entry const *data) : m_data(data)
335 	{
336 		while (m_data && !ROMENTRY_ISSYSTEM_BIOS(m_data))
337 		{
338 			if (ROMENTRY_ISEND(m_data))
339 				m_data = nullptr;
340 			else
341 				++m_data;
342 		}
343 	}
344 
begin()345 	const_iterator begin() const { return const_iterator(m_data); }
cbegin()346 	const_iterator cbegin() const { return const_iterator(m_data); }
end()347 	const_iterator end() const { return const_iterator(nullptr); }
cend()348 	const_iterator cend() const { return const_iterator(nullptr); }
349 };
350 
351 
352 class default_bios final : tiny_rom_entry
353 {
354 private:
355 	default_bios() = default;
356 	default_bios(default_bios const &) = delete;
357 	default_bios &operator=(default_bios const &) = delete;
358 
359 public:
get_name()360 	constexpr char const *get_name() const { return name; }
361 };
362 
363 
364 class entries
365 {
366 private:
367 	tiny_rom_entry const *m_data;
368 
369 public:
entries(tiny_rom_entry const * data)370 	constexpr entries(tiny_rom_entry const *data) : m_data(data) { }
371 
get_regions()372 	regions get_regions() const { return regions(m_data); }
get_system_bioses()373 	system_bioses get_system_bioses() const { return system_bioses(m_data); }
374 };
375 
376 } // namespace romload
377 
378 
379 /***************************************************************************
380 TYPE DEFINITIONS
381 ***************************************************************************/
382 
383 // ======================> rom_load_manager
384 
385 class rom_load_manager
386 {
387 	class open_chd
388 	{
389 	public:
open_chd(const char * region)390 		open_chd(const char *region) : m_region(region) { }
391 
region()392 		const char *region() const { return m_region.c_str(); }
chd()393 		chd_file &chd() { return m_diffchd.opened() ? m_diffchd : m_origchd; }
orig_chd()394 		chd_file &orig_chd() { return m_origchd; }
diff_chd()395 		chd_file &diff_chd() { return m_diffchd; }
396 
397 	private:
398 		std::string         m_region;               /* disk region we came from */
399 		chd_file            m_origchd;              /* handle to the original CHD */
400 		chd_file            m_diffchd;              /* handle to the diff CHD */
401 	};
402 
403 public:
404 	// construction/destruction
405 	rom_load_manager(running_machine &machine);
406 
407 	// getters
machine()408 	running_machine &machine() const { return m_machine; }
409 
410 	/* return the number of warnings we generated */
warnings()411 	int warnings() const { return m_warnings; }
412 
software_load_warnings_message()413 	std::string& software_load_warnings_message() { return m_softwarningstring; }
414 
415 	/* return the number of BAD_DUMP/NO_DUMP warnings we generated */
knownbad()416 	int knownbad() const { return m_knownbad; }
417 
418 	/* ----- disk handling ----- */
419 
420 	/* return a pointer to the CHD file associated with the given region */
421 	chd_file *get_disk_handle(const char *region);
422 
423 	/* set a pointer to the CHD file associated with the given region */
424 	int set_disk_handle(const char *region, const char *fullpath);
425 
426 	void load_software_part_region(device_t &device, software_list_device &swlist, const char *swname, const rom_entry *start_region);
427 
428 	/* get search path for a software item */
429 	static std::vector<std::string> get_software_searchpath(software_list_device &swlist, const software_info &swinfo);
430 
431 	/* open a disk image, searching up the parent and loading by checksum */
432 	static chd_error open_disk_image(const emu_options &options, const device_t &device, const rom_entry *romp, chd_file &image_chd);
433 	static chd_error open_disk_image(const emu_options &options, software_list_device &swlist, const software_info &swinfo, const rom_entry *romp, chd_file &image_chd);
434 
435 private:
436 	void determine_bios_rom(device_t &device, const char *specbios);
437 	void count_roms();
438 	void fill_random(u8 *base, u32 length);
439 	void handle_missing_file(const rom_entry *romp, const std::vector<std::string> &tried_file_names, chd_error chderr);
440 	void dump_wrong_and_correct_checksums(const util::hash_collection &hashes, const util::hash_collection &acthashes);
441 	void verify_length_and_hash(emu_file *file, const char *name, u32 explength, const util::hash_collection &hashes);
442 	void display_loading_rom_message(const char *name, bool from_list);
443 	void display_rom_load_results(bool from_list);
444 	void region_post_process(memory_region *region, bool invert);
445 	std::unique_ptr<emu_file> open_rom_file(std::initializer_list<std::reference_wrapper<const std::vector<std::string> > > searchpath, const rom_entry *romp, std::vector<std::string> &tried_file_names, bool from_list);
446 	std::unique_ptr<emu_file> open_rom_file(const std::vector<std::string> &paths, std::vector<std::string> &tried, bool has_crc, u32 crc, const std::string &name, osd_file::error &filerr);
447 	int rom_fread(emu_file *file, u8 *buffer, int length, const rom_entry *parent_region);
448 	int read_rom_data(emu_file *file, const rom_entry *parent_region, const rom_entry *romp);
449 	void fill_rom_data(const rom_entry *romp);
450 	void copy_rom_data(const rom_entry *romp);
451 	void process_rom_entries(std::initializer_list<std::reference_wrapper<const std::vector<std::string> > > searchpath, u8 bios, const rom_entry *parent_region, const rom_entry *romp, bool from_list);
452 	chd_error open_disk_diff(emu_options &options, const rom_entry *romp, chd_file &source, chd_file &diff_chd);
453 	void process_disk_entries(std::initializer_list<std::reference_wrapper<const std::vector<std::string> > > searchpath, const char *regiontag, const rom_entry *romp, std::function<const rom_entry * ()> next_parent);
454 	void normalize_flags_for_device(const char *rgntag, u8 &width, endianness_t &endian);
455 	void process_region_list();
456 
457 	// internal state
458 	running_machine &   m_machine;            // reference to our machine
459 
460 	int                 m_warnings;           // warning count during processing
461 	int                 m_knownbad;           // BAD_DUMP/NO_DUMP count during processing
462 	int                 m_errors;             // error count during processing
463 
464 	int                 m_romsloaded;         // current ROMs loaded count
465 	int                 m_romstotal;          // total number of ROMs to read
466 	u64                 m_romsloadedsize;     // total size of ROMs loaded so far
467 	u64                 m_romstotalsize;      // total size of ROMs to read
468 
469 	std::vector<std::unique_ptr<open_chd>> m_chd_list;     /* disks */
470 
471 	memory_region *     m_region;             // info about current region
472 
473 	std::string         m_errorstring;        // error string
474 	std::string         m_softwarningstring;  // software warning string
475 };
476 
477 
478 /* ----- Helpers ----- */
479 
480 /* return pointer to the first ROM region within a source */
481 const rom_entry *rom_first_region(const device_t &device);
482 const rom_entry *rom_first_region(const rom_entry *romp);
483 
484 /* return pointer to the next ROM region within a source */
485 const rom_entry *rom_next_region(const rom_entry *romp);
486 
487 /* return pointer to the first ROM file within a region */
488 const rom_entry *rom_first_file(const rom_entry *romp);
489 
490 /* return pointer to the next ROM file within a region */
491 const rom_entry *rom_next_file(const rom_entry *romp);
492 
493 /* return the expected size of a file given the ROM description */
494 u32 rom_file_size(const rom_entry *romp);
495 
496 /* return pointer to the first per-game parameter */
497 const rom_entry *rom_first_parameter(const device_t &device);
498 
499 /* return pointer to the next per-game parameter */
500 const rom_entry *rom_next_parameter(const rom_entry *romp);
501 
502 // builds a rom_entry vector from a tiny_rom_entry array
503 std::vector<rom_entry> rom_build_entries(const tiny_rom_entry *tinyentries);
504 
505 #endif  // MAME_EMU_ROMLOAD_H
506