summaryrefslogtreecommitdiffstatshomepage
path: root/src/frontend/mame
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend/mame')
-rw-r--r--src/frontend/mame/audit.cpp604
-rw-r--r--src/frontend/mame/audit.h168
-rw-r--r--src/frontend/mame/cheat.cpp1446
-rw-r--r--src/frontend/mame/cheat.h337
-rw-r--r--src/frontend/mame/clifront.cpp2051
-rw-r--r--src/frontend/mame/clifront.h75
-rw-r--r--src/frontend/mame/info.cpp1601
-rw-r--r--src/frontend/mame/info.h68
-rw-r--r--src/frontend/mame/language.cpp79
-rw-r--r--src/frontend/mame/language.h31
-rw-r--r--src/frontend/mame/luaengine.cpp2623
-rw-r--r--src/frontend/mame/luaengine.h252
-rw-r--r--src/frontend/mame/mame.cpp393
-rw-r--r--src/frontend/mame/mame.h92
-rw-r--r--src/frontend/mame/mameopts.cpp426
-rw-r--r--src/frontend/mame/mameopts.h78
-rw-r--r--src/frontend/mame/pluginopts.cpp97
-rw-r--r--src/frontend/mame/pluginopts.h29
-rw-r--r--src/frontend/mame/ui/auditmenu.cpp204
-rw-r--r--src/frontend/mame/ui/auditmenu.h41
-rw-r--r--src/frontend/mame/ui/barcode.cpp154
-rw-r--r--src/frontend/mame/ui/barcode.h31
-rw-r--r--src/frontend/mame/ui/cheatopt.cpp320
-rw-r--r--src/frontend/mame/ui/cheatopt.h49
-rw-r--r--src/frontend/mame/ui/custmenu.cpp583
-rw-r--r--src/frontend/mame/ui/custmenu.h131
-rw-r--r--src/frontend/mame/ui/custui.cpp1068
-rw-r--r--src/frontend/mame/ui/custui.h178
-rw-r--r--src/frontend/mame/ui/datfile.cpp680
-rw-r--r--src/frontend/mame/ui/datfile.h96
-rw-r--r--src/frontend/mame/ui/datmenu.cpp296
-rw-r--r--src/frontend/mame/ui/datmenu.h52
-rw-r--r--src/frontend/mame/ui/defimg.h262
-rw-r--r--src/frontend/mame/ui/devctrl.h153
-rw-r--r--src/frontend/mame/ui/devopt.cpp279
-rw-r--r--src/frontend/mame/ui/devopt.h30
-rw-r--r--src/frontend/mame/ui/dirmenu.cpp665
-rw-r--r--src/frontend/mame/ui/dirmenu.h97
-rw-r--r--src/frontend/mame/ui/filemngr.cpp218
-rw-r--r--src/frontend/mame/ui/filemngr.h37
-rw-r--r--src/frontend/mame/ui/filesel.cpp888
-rw-r--r--src/frontend/mame/ui/filesel.h148
-rw-r--r--src/frontend/mame/ui/floppycntrl.cpp170
-rw-r--r--src/frontend/mame/ui/floppycntrl.h36
-rw-r--r--src/frontend/mame/ui/icorender.h233
-rw-r--r--src/frontend/mame/ui/imgcntrl.cpp343
-rw-r--r--src/frontend/mame/ui/imgcntrl.h62
-rw-r--r--src/frontend/mame/ui/info.cpp110
-rw-r--r--src/frontend/mame/ui/info.h37
-rw-r--r--src/frontend/mame/ui/info_pty.cpp43
-rw-r--r--src/frontend/mame/ui/info_pty.h24
-rw-r--r--src/frontend/mame/ui/inifile.cpp454
-rw-r--r--src/frontend/mame/ui/inifile.h117
-rw-r--r--src/frontend/mame/ui/inputmap.cpp930
-rw-r--r--src/frontend/mame/ui/inputmap.h155
-rw-r--r--src/frontend/mame/ui/mainmenu.cpp284
-rw-r--r--src/frontend/mame/ui/mainmenu.h59
-rw-r--r--src/frontend/mame/ui/menu.cpp2965
-rw-r--r--src/frontend/mame/ui/menu.h284
-rw-r--r--src/frontend/mame/ui/miscmenu.cpp983
-rw-r--r--src/frontend/mame/ui/miscmenu.h154
-rw-r--r--src/frontend/mame/ui/moptions.cpp90
-rw-r--r--src/frontend/mame/ui/moptions.h139
-rw-r--r--src/frontend/mame/ui/optsmenu.cpp390
-rw-r--r--src/frontend/mame/ui/optsmenu.h53
-rw-r--r--src/frontend/mame/ui/pluginopt.cpp113
-rw-r--r--src/frontend/mame/ui/pluginopt.h38
-rw-r--r--src/frontend/mame/ui/selector.cpp257
-rw-r--r--src/frontend/mame/ui/selector.h52
-rw-r--r--src/frontend/mame/ui/selgame.cpp2493
-rw-r--r--src/frontend/mame/ui/selgame.h85
-rw-r--r--src/frontend/mame/ui/selsoft.cpp2148
-rw-r--r--src/frontend/mame/ui/selsoft.h110
-rw-r--r--src/frontend/mame/ui/simpleselgame.cpp446
-rw-r--r--src/frontend/mame/ui/simpleselgame.h48
-rw-r--r--src/frontend/mame/ui/sliders.cpp283
-rw-r--r--src/frontend/mame/ui/sliders.h39
-rw-r--r--src/frontend/mame/ui/slotopt.cpp210
-rw-r--r--src/frontend/mame/ui/slotopt.h35
-rw-r--r--src/frontend/mame/ui/sndmenu.cpp171
-rw-r--r--src/frontend/mame/ui/sndmenu.h42
-rw-r--r--src/frontend/mame/ui/starimg.h38
-rw-r--r--src/frontend/mame/ui/submenu.cpp368
-rw-r--r--src/frontend/mame/ui/submenu.h160
-rw-r--r--src/frontend/mame/ui/swlist.cpp458
-rw-r--r--src/frontend/mame/ui/swlist.h84
-rw-r--r--src/frontend/mame/ui/tapectrl.cpp182
-rw-r--r--src/frontend/mame/ui/tapectrl.h30
-rw-r--r--src/frontend/mame/ui/toolbar.h110
-rw-r--r--src/frontend/mame/ui/ui.cpp2738
-rw-r--r--src/frontend/mame/ui/ui.h223
-rw-r--r--src/frontend/mame/ui/uicmd14.pngbin0 -> 3254 bytes
-rw-r--r--src/frontend/mame/ui/utils.cpp181
-rw-r--r--src/frontend/mame/ui/utils.h256
-rw-r--r--src/frontend/mame/ui/videoopt.cpp232
-rw-r--r--src/frontend/mame/ui/videoopt.h48
-rw-r--r--src/frontend/mame/ui/viewgfx.cpp1162
-rw-r--r--src/frontend/mame/ui/viewgfx.h32
98 files changed, 38097 insertions, 0 deletions
diff --git a/src/frontend/mame/audit.cpp b/src/frontend/mame/audit.cpp
new file mode 100644
index 00000000000..60781ae7710
--- /dev/null
+++ b/src/frontend/mame/audit.cpp
@@ -0,0 +1,604 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+/***************************************************************************
+
+ audit.c
+
+ ROM set auditing functions.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "emuopts.h"
+#include "audit.h"
+#include "chd.h"
+#include "sound/samples.h"
+#include "softlist.h"
+
+//**************************************************************************
+// CORE FUNCTIONS
+//**************************************************************************
+
+//-------------------------------------------------
+// media_auditor - constructor
+//-------------------------------------------------
+
+media_auditor::media_auditor(const driver_enumerator &enumerator)
+ : m_enumerator(enumerator),
+ m_validation(AUDIT_VALIDATE_FULL),
+ m_searchpath(nullptr)
+{
+}
+
+
+//-------------------------------------------------
+// audit_media - audit the media described by the
+// currently-enumerated driver
+//-------------------------------------------------
+
+media_auditor::summary media_auditor::audit_media(const char *validation)
+{
+ // start fresh
+ m_record_list.reset();
+
+ // store validation for later
+ m_validation = validation;
+
+// temporary hack until romload is update: get the driver path and support it for
+// all searches
+const char *driverpath = m_enumerator.config().root_device().searchpath();
+
+ int found = 0;
+ int required = 0;
+ int shared_found = 0;
+ int shared_required = 0;
+
+ // iterate over devices and regions
+ for (device_t &device : device_iterator(m_enumerator.config().root_device()))
+ {
+ // determine the search path for this source and iterate through the regions
+ m_searchpath = device.searchpath();
+
+ // now iterate over regions and ROMs within
+ for (const rom_entry *region = rom_first_region(device); region != nullptr; region = rom_next_region(region))
+ {
+// temporary hack: add the driver path & region name
+std::string combinedpath = std::string(device.searchpath()).append(";").append(driverpath);
+if (device.shortname())
+ combinedpath.append(";").append(device.shortname());
+m_searchpath = combinedpath.c_str();
+
+ for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom))
+ {
+ const char *name = ROM_GETNAME(rom);
+ hash_collection hashes(ROM_GETHASHDATA(rom));
+ device_t *shared_device = find_shared_device(device, name, hashes, ROM_GETLENGTH(rom));
+
+ // count the number of files with hashes
+ if (!hashes.flag(hash_collection::FLAG_NO_DUMP) && !ROM_ISOPTIONAL(rom))
+ {
+ required++;
+ if (shared_device != nullptr)
+ shared_required++;
+ }
+
+ // audit a file
+ audit_record *record = nullptr;
+ if (ROMREGION_ISROMDATA(region))
+ record = audit_one_rom(rom);
+
+ // audit a disk
+ else if (ROMREGION_ISDISKDATA(region))
+ record = audit_one_disk(rom);
+
+ if (record != nullptr)
+ {
+ // count the number of files that are found.
+ if (record->status() == audit_record::STATUS_GOOD || (record->status() == audit_record::STATUS_FOUND_INVALID && find_shared_device(device, name, record->actual_hashes(), record->actual_length()) == nullptr))
+ {
+ found++;
+ if (shared_device != nullptr)
+ shared_found++;
+ }
+
+ record->set_shared_device(shared_device);
+ }
+ }
+ }
+ }
+
+ // if we only find files that are in the parent & either the set has no unique files or the parent is not found, then assume we don't have the set at all
+ if (found == shared_found && required > 0 && (required != shared_required || shared_found == 0))
+ {
+ m_record_list.reset();
+ return NOTFOUND;
+ }
+
+ // return a summary
+ return summarize(m_enumerator.driver().name);
+}
+
+
+//-------------------------------------------------
+// audit_device - audit the device
+//-------------------------------------------------
+
+media_auditor::summary media_auditor::audit_device(device_t &device, const char *validation)
+{
+ // start fresh
+ m_record_list.reset();
+
+ // store validation for later
+ m_validation = validation;
+ m_searchpath = device.shortname();
+
+ int found = 0;
+ int required = 0;
+
+ // now iterate over regions and ROMs within
+ for (const rom_entry *region = rom_first_region(device); region != nullptr; region = rom_next_region(region))
+ {
+ for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom))
+ {
+ hash_collection hashes(ROM_GETHASHDATA(rom));
+
+ // count the number of files with hashes
+ if (!hashes.flag(hash_collection::FLAG_NO_DUMP) && !ROM_ISOPTIONAL(rom))
+ {
+ required++;
+ }
+
+ // audit a file
+ audit_record *record = nullptr;
+ if (ROMREGION_ISROMDATA(region))
+ record = audit_one_rom(rom);
+
+ // audit a disk
+ else if (ROMREGION_ISDISKDATA(region))
+ record = audit_one_disk(rom);
+
+ // count the number of files that are found.
+ if (record != nullptr && (record->status() == audit_record::STATUS_GOOD || record->status() == audit_record::STATUS_FOUND_INVALID))
+ {
+ found++;
+ }
+ }
+ }
+
+ if (found == 0 && required > 0)
+ {
+ m_record_list.reset();
+ return NOTFOUND;
+ }
+
+ // return a summary
+ return summarize(device.shortname());
+}
+
+
+//-------------------------------------------------
+// audit_software
+//-------------------------------------------------
+media_auditor::summary media_auditor::audit_software(const char *list_name, software_info *swinfo, const char *validation)
+{
+ // start fresh
+ m_record_list.reset();
+
+ // store validation for later
+ m_validation = validation;
+
+ std::string combinedpath(swinfo->shortname());
+ combinedpath.append(";");
+ combinedpath.append(list_name);
+ combinedpath.append(PATH_SEPARATOR);
+ combinedpath.append(swinfo->shortname());
+ std::string locationtag(list_name);
+ locationtag.append("%");
+ locationtag.append(swinfo->shortname());
+ locationtag.append("%");
+ if (swinfo->parentname() != nullptr)
+ {
+ locationtag.append(swinfo->parentname());
+ combinedpath.append(";").append(swinfo->parentname()).append(";").append(list_name).append(PATH_SEPARATOR).append(swinfo->parentname());
+ }
+ m_searchpath = combinedpath.c_str();
+
+ int found = 0;
+ int required = 0;
+
+ // now iterate over software parts
+ for (software_part &part : swinfo->parts())
+ {
+ // now iterate over regions
+ for ( const rom_entry *region = part.romdata(); region; region = rom_next_region( region ) )
+ {
+ // now iterate over rom definitions
+ for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom))
+ {
+ hash_collection hashes(ROM_GETHASHDATA(rom));
+
+ // count the number of files with hashes
+ if (!hashes.flag(hash_collection::FLAG_NO_DUMP) && !ROM_ISOPTIONAL(rom))
+ {
+ required++;
+ }
+
+ // audit a file
+ audit_record *record = nullptr;
+ if (ROMREGION_ISROMDATA(region))
+ {
+ record = audit_one_rom(rom);
+ }
+ // audit a disk
+ else if (ROMREGION_ISDISKDATA(region))
+ {
+ record = audit_one_disk(rom, locationtag.c_str());
+ }
+
+ // count the number of files that are found.
+ if (record != nullptr && (record->status() == audit_record::STATUS_GOOD || record->status() == audit_record::STATUS_FOUND_INVALID))
+ {
+ found++;
+ }
+ }
+ }
+ }
+
+ if (found == 0 && required > 0)
+ {
+ m_record_list.reset();
+ return NOTFOUND;
+ }
+
+ // return a summary
+ return summarize(list_name);
+}
+
+
+//-------------------------------------------------
+// audit_samples - validate the samples for the
+// currently-enumerated driver
+//-------------------------------------------------
+
+media_auditor::summary media_auditor::audit_samples()
+{
+ // start fresh
+ m_record_list.reset();
+
+ int required = 0;
+ int found = 0;
+
+ // iterate over sample entries
+ for (samples_device &device : samples_device_iterator(m_enumerator.config().root_device()))
+ {
+ // by default we just search using the driver name
+ std::string searchpath(m_enumerator.driver().name);
+
+ // add the alternate path if present
+ samples_iterator iter(device);
+ if (iter.altbasename() != nullptr)
+ searchpath.append(";").append(iter.altbasename());
+
+ // iterate over samples in this entry
+ for (const char *samplename = iter.first(); samplename != nullptr; samplename = iter.next())
+ {
+ required++;
+
+ // create a new record
+ audit_record &record = m_record_list.append(*global_alloc(audit_record(samplename, audit_record::MEDIA_SAMPLE)));
+
+ // look for the files
+ emu_file file(m_enumerator.options().sample_path(), OPEN_FLAG_READ | OPEN_FLAG_NO_PRELOAD);
+ path_iterator path(searchpath.c_str());
+ std::string curpath;
+ while (path.next(curpath, samplename))
+ {
+ // attempt to access the file (.flac) or (.wav)
+ osd_file::error filerr = file.open(curpath.c_str(), ".flac");
+ if (filerr != osd_file::error::NONE)
+ filerr = file.open(curpath.c_str(), ".wav");
+
+ if (filerr == osd_file::error::NONE)
+ {
+ record.set_status(audit_record::STATUS_GOOD, audit_record::SUBSTATUS_GOOD);
+ found++;
+ }
+ else
+ record.set_status(audit_record::STATUS_NOT_FOUND, audit_record::SUBSTATUS_NOT_FOUND);
+ }
+ }
+ }
+
+ if (found == 0 && required > 0)
+ {
+ m_record_list.reset();
+ return NOTFOUND;
+ }
+
+ // return a summary
+ return summarize(m_enumerator.driver().name);
+}
+
+
+//-------------------------------------------------
+// summary - generate a summary, with an optional
+// string format
+//-------------------------------------------------
+
+media_auditor::summary media_auditor::summarize(const char *name, std::string *output)
+{
+ if (m_record_list.count() == 0)
+ {
+ return NONE_NEEDED;
+ }
+
+ // loop over records
+ summary overall_status = CORRECT;
+ for (audit_record &record : m_record_list)
+ {
+ summary best_new_status = INCORRECT;
+
+ // skip anything that's fine
+ if (record.substatus() == audit_record::SUBSTATUS_GOOD)
+ continue;
+
+ // output the game name, file name, and length (if applicable)
+ if (output != nullptr)
+ {
+ output->append(string_format("%-12s: %s", name, record.name()));
+ if (record.expected_length() > 0)
+ output->append(string_format(" (%d bytes)", record.expected_length()));
+ output->append(" - ");
+ }
+
+ // use the substatus for finer details
+ switch (record.substatus())
+ {
+ case audit_record::SUBSTATUS_GOOD_NEEDS_REDUMP:
+ if (output != nullptr) output->append("NEEDS REDUMP\n");
+ best_new_status = BEST_AVAILABLE;
+ break;
+
+ case audit_record::SUBSTATUS_FOUND_NODUMP:
+ if (output != nullptr) output->append("NO GOOD DUMP KNOWN\n");
+ best_new_status = BEST_AVAILABLE;
+ break;
+
+ case audit_record::SUBSTATUS_FOUND_BAD_CHECKSUM:
+ if (output != nullptr)
+ {
+ output->append("INCORRECT CHECKSUM:\n");
+ output->append(string_format("EXPECTED: %s\n", record.expected_hashes().macro_string().c_str()));
+ output->append(string_format(" FOUND: %s\n", record.actual_hashes().macro_string().c_str()));
+ }
+ break;
+
+ case audit_record::SUBSTATUS_FOUND_WRONG_LENGTH:
+ if (output != nullptr) output->append(string_format("INCORRECT LENGTH: %d bytes\n", record.actual_length()));
+ break;
+
+ case audit_record::SUBSTATUS_NOT_FOUND:
+ if (output != nullptr)
+ {
+ device_t *shared_device = record.shared_device();
+ if (shared_device == nullptr)
+ output->append("NOT FOUND\n");
+ else
+ output->append(string_format("NOT FOUND (%s)\n", shared_device->shortname()));
+ }
+ break;
+
+ case audit_record::SUBSTATUS_NOT_FOUND_NODUMP:
+ if (output != nullptr) output->append("NOT FOUND - NO GOOD DUMP KNOWN\n");
+ best_new_status = BEST_AVAILABLE;
+ break;
+
+ case audit_record::SUBSTATUS_NOT_FOUND_OPTIONAL:
+ if (output != nullptr) output->append("NOT FOUND BUT OPTIONAL\n");
+ best_new_status = BEST_AVAILABLE;
+ break;
+
+ default:
+ assert(false);
+ }
+
+ // downgrade the overall status if necessary
+ overall_status = MAX(overall_status, best_new_status);
+ }
+ return overall_status;
+}
+
+
+//-------------------------------------------------
+// audit_one_rom - validate a single ROM entry
+//-------------------------------------------------
+
+audit_record *media_auditor::audit_one_rom(const rom_entry *rom)
+{
+ // allocate and append a new record
+ audit_record &record = m_record_list.append(*global_alloc(audit_record(*rom, audit_record::MEDIA_ROM)));
+
+ // see if we have a CRC and extract it if so
+ UINT32 crc = 0;
+ bool has_crc = record.expected_hashes().crc(crc);
+
+ // find the file and checksum it, getting the file length along the way
+ emu_file file(m_enumerator.options().media_path(), OPEN_FLAG_READ | OPEN_FLAG_NO_PRELOAD);
+ file.set_restrict_to_mediapath(true);
+ path_iterator path(m_searchpath);
+ std::string curpath;
+ while (path.next(curpath, record.name()))
+ {
+ // open the file if we can
+ osd_file::error filerr;
+ if (has_crc)
+ filerr = file.open(curpath.c_str(), crc);
+ else
+ filerr = file.open(curpath.c_str());
+
+ // if it worked, get the actual length and hashes, then stop
+ if (filerr == osd_file::error::NONE)
+ {
+ record.set_actual(file.hashes(m_validation), file.size());
+ break;
+ }
+ }
+
+ // compute the final status
+ compute_status(record, rom, record.actual_length() != 0);
+ return &record;
+}
+
+
+//-------------------------------------------------
+// audit_one_disk - validate a single disk entry
+//-------------------------------------------------
+
+audit_record *media_auditor::audit_one_disk(const rom_entry *rom, const char *locationtag)
+{
+ // allocate and append a new record
+ audit_record &record = m_record_list.append(*global_alloc(audit_record(*rom, audit_record::MEDIA_DISK)));
+
+ // open the disk
+ chd_file source;
+ chd_error err = chd_error(open_disk_image(m_enumerator.options(), &m_enumerator.driver(), rom, source, locationtag));
+
+ // if we succeeded, get the hashes
+ if (err == CHDERR_NONE)
+ {
+ hash_collection hashes;
+
+ // if there's a SHA1 hash, add them to the output hash
+ if (source.sha1() != sha1_t::null)
+ hashes.add_sha1(source.sha1());
+
+ // update the actual values
+ record.set_actual(hashes);
+ }
+
+ // compute the final status
+ compute_status(record, rom, err == CHDERR_NONE);
+ return &record;
+}
+
+
+//-------------------------------------------------
+// compute_status - compute a detailed status
+// based on the information we have
+//-------------------------------------------------
+
+void media_auditor::compute_status(audit_record &record, const rom_entry *rom, bool found)
+{
+ // if not found, provide more details
+ if (!found)
+ {
+ // no good dump
+ if (record.expected_hashes().flag(hash_collection::FLAG_NO_DUMP))
+ record.set_status(audit_record::STATUS_NOT_FOUND, audit_record::SUBSTATUS_NOT_FOUND_NODUMP);
+
+ // optional ROM
+ else if (ROM_ISOPTIONAL(rom))
+ record.set_status(audit_record::STATUS_NOT_FOUND, audit_record::SUBSTATUS_NOT_FOUND_OPTIONAL);
+
+ // just plain old not found
+ else
+ record.set_status(audit_record::STATUS_NOT_FOUND, audit_record::SUBSTATUS_NOT_FOUND);
+ }
+
+ // if found, provide more details
+ else
+ {
+ // length mismatch
+ if (record.expected_length() != record.actual_length())
+ record.set_status(audit_record::STATUS_FOUND_INVALID, audit_record::SUBSTATUS_FOUND_WRONG_LENGTH);
+
+ // found but needs a dump
+ else if (record.expected_hashes().flag(hash_collection::FLAG_NO_DUMP))
+ record.set_status(audit_record::STATUS_GOOD, audit_record::SUBSTATUS_FOUND_NODUMP);
+
+ // incorrect hash
+ else if (record.expected_hashes() != record.actual_hashes())
+ record.set_status(audit_record::STATUS_FOUND_INVALID, audit_record::SUBSTATUS_FOUND_BAD_CHECKSUM);
+
+ // correct hash but needs a redump
+ else if (record.expected_hashes().flag(hash_collection::FLAG_BAD_DUMP))
+ record.set_status(audit_record::STATUS_GOOD, audit_record::SUBSTATUS_GOOD_NEEDS_REDUMP);
+
+ // just plain old good
+ else
+ record.set_status(audit_record::STATUS_GOOD, audit_record::SUBSTATUS_GOOD);
+ }
+}
+
+
+//-------------------------------------------------
+// find_shared_device - return the source that
+// shares a media entry with the same hashes
+//-------------------------------------------------
+
+device_t *media_auditor::find_shared_device(device_t &device, const char *name, const hash_collection &romhashes, UINT64 romlength)
+{
+ bool dumped = !romhashes.flag(hash_collection::FLAG_NO_DUMP);
+
+ // special case for non-root devices
+ device_t *highest_device = nullptr;
+ if (device.owner() != nullptr)
+ {
+ for (const rom_entry *region = rom_first_region(device); region != nullptr; region = rom_next_region(region))
+ for (const rom_entry *rom = rom_first_file(region); rom != nullptr; rom = rom_next_file(rom))
+ if (ROM_GETLENGTH(rom) == romlength)
+ {
+ hash_collection hashes(ROM_GETHASHDATA(rom));
+ if ((dumped && hashes == romhashes) || (!dumped && ROM_GETNAME(rom) == name))
+ highest_device = &device;
+ }
+ }
+ else
+ {
+ // iterate up the parent chain
+ for (int drvindex = m_enumerator.find(m_enumerator.driver().parent); drvindex != -1; drvindex = m_enumerator.find(m_enumerator.driver(drvindex).parent))
+ {
+ for (device_t &scandevice : device_iterator(m_enumerator.config(drvindex).root_device()))
+ for (const rom_entry *region = rom_first_region(scandevice); region; region = rom_next_region(region))
+ for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom))
+ if (ROM_GETLENGTH(rom) == romlength)
+ {
+ hash_collection hashes(ROM_GETHASHDATA(rom));
+ if ((dumped && hashes == romhashes) || (!dumped && ROM_GETNAME(rom) == name))
+ highest_device = &scandevice;
+ }
+ }
+ }
+
+ return highest_device;
+}
+
+
+//-------------------------------------------------
+// audit_record - constructor
+//-------------------------------------------------
+
+audit_record::audit_record(const rom_entry &media, media_type type)
+ : m_next(nullptr),
+ m_type(type),
+ m_status(STATUS_ERROR),
+ m_substatus(SUBSTATUS_ERROR),
+ m_name(ROM_GETNAME(&media)),
+ m_explength(rom_file_size(&media)),
+ m_length(0),
+ m_shared_device(nullptr)
+{
+ m_exphashes.from_internal_string(ROM_GETHASHDATA(&media));
+}
+
+audit_record::audit_record(const char *name, media_type type)
+ : m_next(nullptr),
+ m_type(type),
+ m_status(STATUS_ERROR),
+ m_substatus(SUBSTATUS_ERROR),
+ m_name(name),
+ m_explength(0),
+ m_length(0),
+ m_shared_device(nullptr)
+{
+}
diff --git a/src/frontend/mame/audit.h b/src/frontend/mame/audit.h
new file mode 100644
index 00000000000..83421f8cc6e
--- /dev/null
+++ b/src/frontend/mame/audit.h
@@ -0,0 +1,168 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+/***************************************************************************
+
+ audit.h
+
+ ROM, disk, and sample auditing functions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __AUDIT_H__
+#define __AUDIT_H__
+
+#include "drivenum.h"
+#include "hash.h"
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// hashes to use for validation
+#define AUDIT_VALIDATE_FAST "R" /* CRC only */
+#define AUDIT_VALIDATE_FULL "RS" /* CRC + SHA1 */
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> audit_record
+
+// holds the result of auditing a single item
+class audit_record
+{
+ friend class simple_list<audit_record>;
+
+public:
+ // media types
+ enum media_type
+ {
+ MEDIA_ROM = 0,
+ MEDIA_DISK,
+ MEDIA_SAMPLE
+ };
+
+ // status values
+ enum audit_status
+ {
+ STATUS_GOOD = 0,
+ STATUS_FOUND_INVALID,
+ STATUS_NOT_FOUND,
+ STATUS_ERROR
+ };
+
+ // substatus values
+ enum audit_substatus
+ {
+ SUBSTATUS_GOOD = 0,
+ SUBSTATUS_GOOD_NEEDS_REDUMP,
+ SUBSTATUS_FOUND_NODUMP,
+ SUBSTATUS_FOUND_BAD_CHECKSUM,
+ SUBSTATUS_FOUND_WRONG_LENGTH,
+ SUBSTATUS_NOT_FOUND,
+ SUBSTATUS_NOT_FOUND_NODUMP,
+ SUBSTATUS_NOT_FOUND_OPTIONAL,
+ SUBSTATUS_ERROR = 100
+ };
+
+ // construction/destruction
+ audit_record(const rom_entry &media, media_type type);
+ audit_record(const char *name, media_type type);
+
+ // getters
+ audit_record *next() const { return m_next; }
+ media_type type() const { return m_type; }
+ audit_status status() const { return m_status; }
+ audit_substatus substatus() const { return m_substatus; }
+ const char *name() const { return m_name; }
+ UINT64 expected_length() const { return m_explength; }
+ UINT64 actual_length() const { return m_length; }
+ const hash_collection &expected_hashes() const { return m_exphashes; }
+ const hash_collection &actual_hashes() const { return m_hashes; }
+ device_t *shared_device() const { return m_shared_device; }
+
+ // setters
+ void set_status(audit_status status, audit_substatus substatus)
+ {
+ m_status = status;
+ m_substatus = substatus;
+ }
+
+ void set_actual(const hash_collection &hashes, UINT64 length = 0)
+ {
+ m_hashes = hashes;
+ m_length = length;
+ }
+
+ void set_shared_device(device_t *shared_device)
+ {
+ m_shared_device = shared_device;
+ }
+
+private:
+ // internal state
+ audit_record * m_next;
+ media_type m_type; /* type of item that was audited */
+ audit_status m_status; /* status of audit on this item */
+ audit_substatus m_substatus; /* finer-detail status */
+ const char * m_name; /* name of item */
+ UINT64 m_explength; /* expected length of item */
+ UINT64 m_length; /* actual length of item */
+ hash_collection m_exphashes; /* expected hash data */
+ hash_collection m_hashes; /* actual hash information */
+ device_t * m_shared_device; /* device that shares the rom */
+};
+
+
+// ======================> media_auditor
+
+// class which manages auditing of items
+class media_auditor
+{
+public:
+ // summary values
+ enum summary
+ {
+ CORRECT = 0,
+ NONE_NEEDED,
+ BEST_AVAILABLE,
+ INCORRECT,
+ NOTFOUND
+ };
+
+ // construction/destruction
+ media_auditor(const driver_enumerator &enumerator);
+
+ // getters
+ const simple_list<audit_record> &records() const { return m_record_list; }
+
+ // audit operations
+ summary audit_media(const char *validation = AUDIT_VALIDATE_FULL);
+ summary audit_device(device_t &device, const char *validation = AUDIT_VALIDATE_FULL);
+ summary audit_software(const char *list_name, software_info *swinfo, const char *validation = AUDIT_VALIDATE_FULL);
+ summary audit_samples();
+ summary summarize(const char *name,std::string *output = nullptr);
+
+private:
+ // internal helpers
+ audit_record *audit_one_rom(const rom_entry *rom);
+ audit_record *audit_one_disk(const rom_entry *rom, const char *locationtag = nullptr);
+ void compute_status(audit_record &record, const rom_entry *rom, bool found);
+ device_t *find_shared_device(device_t &device, const char *name, const hash_collection &romhashes, UINT64 romlength);
+
+ // internal state
+ simple_list<audit_record> m_record_list;
+ const driver_enumerator & m_enumerator;
+ const char * m_validation;
+ const char * m_searchpath;
+};
+
+
+#endif /* __AUDIT_H__ */
diff --git a/src/frontend/mame/cheat.cpp b/src/frontend/mame/cheat.cpp
new file mode 100644
index 00000000000..099e6344d59
--- /dev/null
+++ b/src/frontend/mame/cheat.cpp
@@ -0,0 +1,1446 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+/***************************************************************************
+
+ cheat.c
+
+ MAME cheat system.
+
+****************************************************************************
+
+ Cheat XML format:
+
+ <mamecheat version="1">
+ <cheat desc="blah">
+ <parameter min="minval(0)" max="maxval(numitems)" step="stepval(1)">
+ <item value="itemval(previtemval|minval+stepval)">text</item>
+ ...
+ </parameter>
+ <script state="on|off|run|change(run)">
+ <action condition="condexpr(1)">expression</action>
+ ...
+ <output condition="condexpr(1)" format="format(required)" line="line(0)" align="left|center|right(left)">
+ <argument count="count(1)">expression</argument>
+ </output>
+ ...
+ </script>
+ ...
+ <comment>
+ ... text ...
+ </comment>
+ </cheat>
+ ...
+ </mamecheat>
+
+****************************************************************************
+
+ Expressions are standard debugger expressions. Note that & and
+ < must be escaped per XML rules. Within attributes you must use
+ &amp; and &lt;. For tags, you can also use <![CDATA[ ... ]]>.
+
+ Each cheat has its own context-specific variables:
+
+ temp0-temp9 -- 10 temporary variables for any use
+ param -- the current value of the cheat parameter
+ frame -- the current frame index
+ argindex -- for arguments with multiple iterations, this is the index
+
+ By default, each cheat has 10 temporary variables that are
+ persistent while executing its scripts. Additional temporary
+ variables may be requested via the 'tempvariables' attribute
+ on the cheat.
+
+****************************************************************************
+
+ Cheats are generally broken down into categories based on
+ which actions are defined and whether or not there is a
+ parameter present:
+
+ ---- Actions -----
+ On Off Run Chg Param? Type
+ === === === === ====== =================================
+ N N N ? None Text-only (displays text in menu)
+ Y N N ? None Oneshot (select to activate)
+ Y Y N ? None On/Off (select to toggle)
+ ? ? Y ? None On/Off (select to toggle)
+
+ ? N N Y Any Oneshot parameter (select to alter)
+ ? Y ? ? Value Value parameter (off or a live value)
+ ? ? Y ? Value Value parameter (off or a live value)
+ ? Y ? ? List Item list parameter (off or a live value)
+ ? ? Y ? List Item list parameter (off or a live value)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "emuopts.h"
+#include "xmlfile.h"
+#include "ui/ui.h"
+#include "ui/menu.h"
+#include "cheat.h"
+#include "debug/debugcpu.h"
+
+#include <ctype.h>
+
+
+
+//**************************************************************************
+// PARAMETERS
+//**************************************************************************
+
+// turn this on to enable removing duplicate cheats; not sure if we should
+#define REMOVE_DUPLICATE_CHEATS 0
+
+
+
+//**************************************************************************
+// NUMBER AND FORMAT
+//**************************************************************************
+
+//-------------------------------------------------
+// format - format an integer according to
+// the format
+//-------------------------------------------------
+
+inline std::string number_and_format::format() const
+{
+ switch (m_format)
+ {
+ default:
+ case XML_INT_FORMAT_DECIMAL:
+ return string_format("%d", (UINT32)m_value);
+
+ case XML_INT_FORMAT_DECIMAL_POUND:
+ return string_format("#%d", (UINT32)m_value);
+
+ case XML_INT_FORMAT_HEX_DOLLAR:
+ return string_format("$%X", (UINT32)m_value);
+
+ case XML_INT_FORMAT_HEX_C:
+ return string_format("0x%X", (UINT32)m_value);
+ }
+}
+
+
+
+//**************************************************************************
+// CHEAT PARAMETER
+//**************************************************************************
+
+//-------------------------------------------------
+// cheat_parameter - constructor
+//-------------------------------------------------
+
+cheat_parameter::cheat_parameter(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node &paramnode)
+ : m_value(0)
+{
+ // read the core attributes
+ m_minval = number_and_format(xml_get_attribute_int(&paramnode, "min", 0), xml_get_attribute_int_format(&paramnode, "min"));
+ m_maxval = number_and_format(xml_get_attribute_int(&paramnode, "max", 0), xml_get_attribute_int_format(&paramnode, "max"));
+ m_stepval = number_and_format(xml_get_attribute_int(&paramnode, "step", 1), xml_get_attribute_int_format(&paramnode, "step"));
+
+ // iterate over items
+ for (xml_data_node *itemnode = xml_get_sibling(paramnode.child, "item"); itemnode != nullptr; itemnode = xml_get_sibling(itemnode->next, "item"))
+ {
+ // check for NULL text
+ if (itemnode->value == nullptr || itemnode->value[0] == 0)
+ throw emu_fatalerror("%s.xml(%d): item is missing text\n", filename, itemnode->line);
+
+ // check for non-existant value
+ if (xml_get_attribute(itemnode, "value") == nullptr)
+ throw emu_fatalerror("%s.xml(%d): item is value\n", filename, itemnode->line);
+
+ // extract the parameters
+ UINT64 value = xml_get_attribute_int(itemnode, "value", 0);
+ int format = xml_get_attribute_int_format(itemnode, "value");
+
+ // allocate and append a new item
+ item &curitem = m_itemlist.append(*global_alloc(item(itemnode->value, value, format)));
+
+ // ensure the maximum expands to suit
+ m_maxval = MAX(m_maxval, curitem.value());
+ }
+
+ // add a variable to the symbol table for our value
+ symbols.add("param", symbol_table::READ_ONLY, &m_value);
+}
+
+
+//-------------------------------------------------
+// text - return the current text for a parameter
+//-------------------------------------------------
+
+const char *cheat_parameter::text()
+{
+ // are we a value cheat?
+ if (!has_itemlist())
+ {
+ m_curtext = string_format("%d (0x%X)", UINT32(m_value), UINT32(m_value));
+ }
+ else
+ {
+ // if not, we're an item cheat
+ m_curtext = string_format("??? (%d)", UINT32(m_value));
+ for (item &curitem : m_itemlist)
+ if (curitem.value() == m_value)
+ {
+ m_curtext.assign(curitem.text());
+ break;
+ }
+ }
+ return m_curtext.c_str();
+}
+
+
+//-------------------------------------------------
+// save - save a single cheat parameter
+//-------------------------------------------------
+
+void cheat_parameter::save(emu_file &cheatfile) const
+{
+ // output the parameter tag
+ cheatfile.printf("\t\t<parameter");
+
+ // if no items, just output min/max/step
+ if (!has_itemlist())
+ {
+ if (m_minval != 0)
+ cheatfile.printf(" min=\"%s\"", m_minval.format().c_str());
+ if (m_maxval != 0)
+ cheatfile.printf(" max=\"%s\"", m_maxval.format().c_str());
+ if (m_stepval != 1)
+ cheatfile.printf(" step=\"%s\"", m_stepval.format().c_str());
+ cheatfile.printf("/>\n");
+ }
+
+ // iterate over items
+ else
+ {
+ for (const item &curitem : m_itemlist)
+ cheatfile.printf("\t\t\t<item value=\"%s\">%s</item>\n", curitem.value().format().c_str(), curitem.text());
+ cheatfile.printf("\t\t</parameter>\n");
+ }
+}
+
+
+//-------------------------------------------------
+// set_minimum_state - set the minimum state
+//-------------------------------------------------
+
+bool cheat_parameter::set_minimum_state()
+{
+ UINT64 origvalue = m_value;
+
+ // set based on whether we have an item list
+ m_value = (!has_itemlist()) ? m_minval : m_itemlist.first()->value();
+
+ return (m_value != origvalue);
+}
+
+
+//-------------------------------------------------
+// set_minimum_state - set the previous state
+//-------------------------------------------------
+
+bool cheat_parameter::set_prev_state()
+{
+ UINT64 origvalue = m_value;
+
+ // are we a value cheat?
+ if (!has_itemlist())
+ {
+ if (m_value < m_minval + m_stepval)
+ m_value = m_minval;
+ else
+ m_value -= m_stepval;
+ }
+
+ // if not, we're an item cheat
+ else
+ {
+ item *curitem, *previtem = nullptr;
+ for (curitem = m_itemlist.first(); curitem != nullptr; previtem = curitem, curitem = curitem->next())
+ if (curitem->value() == m_value)
+ break;
+ if (previtem != nullptr)
+ m_value = previtem->value();
+ }
+
+ return (m_value != origvalue);
+}
+
+
+//-------------------------------------------------
+// set_next_state - advance to the next state
+//-------------------------------------------------
+
+bool cheat_parameter::set_next_state()
+{
+ UINT64 origvalue = m_value;
+
+ // are we a value cheat?
+ if (!has_itemlist())
+ {
+ if (m_value > m_maxval - m_stepval)
+ m_value = m_maxval;
+ else
+ m_value += m_stepval;
+ }
+
+ // if not, we're an item cheat
+ else
+ {
+ item *curitem;
+ for (curitem = m_itemlist.first(); curitem != nullptr; curitem = curitem->next())
+ if (curitem->value() == m_value)
+ break;
+ if (curitem != nullptr && curitem->next() != nullptr)
+ m_value = curitem->next()->value();
+ }
+
+ return (m_value != origvalue);
+}
+
+
+
+//**************************************************************************
+// CHEAT SCRIPT
+//**************************************************************************
+
+//-------------------------------------------------
+// cheat_script - constructor
+//-------------------------------------------------
+
+cheat_script::cheat_script(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node &scriptnode)
+ : m_state(SCRIPT_STATE_RUN)
+{
+ // read the core attributes
+ const char *state = xml_get_attribute_string(&scriptnode, "state", "run");
+ if (strcmp(state, "on") == 0)
+ m_state = SCRIPT_STATE_ON;
+ else if (strcmp(state, "off") == 0)
+ m_state = SCRIPT_STATE_OFF;
+ else if (strcmp(state, "change") == 0)
+ m_state = SCRIPT_STATE_CHANGE;
+ else if (strcmp(state, "run") != 0)
+ throw emu_fatalerror("%s.xml(%d): invalid script state '%s'\n", filename, scriptnode.line, state);
+
+ // iterate over nodes within the script
+ for (xml_data_node *entrynode = scriptnode.child; entrynode != nullptr; entrynode = entrynode->next)
+ {
+ // handle action nodes
+ if (strcmp(entrynode->name, "action") == 0)
+ m_entrylist.append(*global_alloc(script_entry(manager, symbols, filename, *entrynode, true)));
+
+ // handle output nodes
+ else if (strcmp(entrynode->name, "output") == 0)
+ m_entrylist.append(*global_alloc(script_entry(manager, symbols, filename, *entrynode, false)));
+
+ // anything else is ignored
+ else
+ {
+ osd_printf_warning("%s.xml(%d): unknown script item '%s' will be lost if saved\n", filename, entrynode->line, entrynode->name);
+ continue;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// execute - execute ourself
+//-------------------------------------------------
+
+void cheat_script::execute(cheat_manager &manager, UINT64 &argindex)
+{
+ // do nothing if disabled
+ if (!manager.enabled())
+ return;
+
+ // iterate over entries
+ for (script_entry &entry : m_entrylist)
+ entry.execute(manager, argindex);
+}
+
+
+//-------------------------------------------------
+// save - save a single cheat script
+//-------------------------------------------------
+
+void cheat_script::save(emu_file &cheatfile) const
+{
+ // output the script tag
+ cheatfile.printf("\t\t<script");
+ switch (m_state)
+ {
+ case SCRIPT_STATE_OFF: cheatfile.printf(" state=\"off\""); break;
+ case SCRIPT_STATE_ON: cheatfile.printf(" state=\"on\""); break;
+ default:
+ case SCRIPT_STATE_RUN: cheatfile.printf(" state=\"run\""); break;
+ case SCRIPT_STATE_CHANGE: cheatfile.printf(" state=\"change\""); break;
+ }
+ cheatfile.printf(">\n");
+
+ // output entries
+ for (const script_entry &entry : m_entrylist)
+ entry.save(cheatfile);
+
+ // close the tag
+ cheatfile.printf("\t\t</script>\n");
+}
+
+
+//-------------------------------------------------
+// script_entry - constructor
+//-------------------------------------------------
+
+cheat_script::script_entry::script_entry(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node &entrynode, bool isaction)
+ : m_next(nullptr),
+ m_condition(&symbols),
+ m_expression(&symbols)
+{
+ const char *expression = nullptr;
+ try
+ {
+ // read the condition if present
+ expression = xml_get_attribute_string(&entrynode, "condition", nullptr);
+ if (expression != nullptr)
+ m_condition.parse(expression);
+
+ // if this is an action, parse the expression
+ if (isaction)
+ {
+ expression = entrynode.value;
+ if (expression == nullptr || expression[0] == 0)
+ throw emu_fatalerror("%s.xml(%d): missing expression in action tag\n", filename, entrynode.line);
+ m_expression.parse(expression);
+ }
+
+ // otherwise, parse the attributes and arguments
+ else
+ {
+ // extract format
+ const char *format = xml_get_attribute_string(&entrynode, "format", nullptr);
+ if (format == nullptr || format[0] == 0)
+ throw emu_fatalerror("%s.xml(%d): missing format in output tag\n", filename, entrynode.line);
+ m_format.assign(format);
+
+ // extract other attributes
+ m_line = xml_get_attribute_int(&entrynode, "line", 0);
+ m_justify = JUSTIFY_LEFT;
+ const char *align = xml_get_attribute_string(&entrynode, "align", "left");
+ if (strcmp(align, "center") == 0)
+ m_justify = JUSTIFY_CENTER;
+ else if (strcmp(align, "right") == 0)
+ m_justify = JUSTIFY_RIGHT;
+ else if (strcmp(align, "left") != 0)
+ throw emu_fatalerror("%s.xml(%d): invalid alignment '%s' specified\n", filename, entrynode.line, align);
+
+ // then parse arguments
+ int totalargs = 0;
+ for (xml_data_node *argnode = xml_get_sibling(entrynode.child, "argument"); argnode != nullptr; argnode = xml_get_sibling(argnode->next, "argument"))
+ {
+ output_argument &curarg = m_arglist.append(*global_alloc(output_argument(manager, symbols, filename, *argnode)));
+
+ // verify we didn't overrun the argument count
+ totalargs += curarg.count();
+ if (totalargs > MAX_ARGUMENTS)
+ throw emu_fatalerror("%s.xml(%d): too many arguments (found %d, max is %d)\n", filename, argnode->line, totalargs, MAX_ARGUMENTS);
+ }
+
+ // validate the format against the arguments
+ validate_format(filename, entrynode.line);
+ }
+ }
+ catch (expression_error &err)
+ {
+ throw emu_fatalerror("%s.xml(%d): error parsing cheat expression \"%s\" (%s)\n", filename, entrynode.line, expression, err.code_string());
+ }
+}
+
+
+//-------------------------------------------------
+// execute - execute a single script entry
+//-------------------------------------------------
+
+void cheat_script::script_entry::execute(cheat_manager &manager, UINT64 &argindex)
+{
+ // evaluate the condition
+ if (!m_condition.is_empty())
+ {
+ try
+ {
+ UINT64 result = m_condition.execute();
+ if (result == 0)
+ return;
+ }
+ catch (expression_error &err)
+ {
+ osd_printf_warning("Error executing conditional expression \"%s\": %s\n", m_condition.original_string(), err.code_string());
+ return;
+ }
+ }
+
+ // if there is an action, execute it
+ if (!m_expression.is_empty())
+ {
+ try
+ {
+ m_expression.execute();
+ }
+ catch (expression_error &err)
+ {
+ osd_printf_warning("Error executing expression \"%s\": %s\n", m_expression.original_string(), err.code_string());
+ }
+ }
+
+ // if there is a string to display, compute it
+ if (!m_format.empty())
+ {
+ // iterate over arguments and evaluate them
+ UINT64 params[MAX_ARGUMENTS];
+ int curarg = 0;
+ for (output_argument &arg : m_arglist)
+ curarg += arg.values(argindex, &params[curarg]);
+
+ // generate the astring
+ manager.get_output_astring(m_line, m_justify) = string_format(m_format,
+ (UINT32)params[0], (UINT32)params[1], (UINT32)params[2], (UINT32)params[3],
+ (UINT32)params[4], (UINT32)params[5], (UINT32)params[6], (UINT32)params[7],
+ (UINT32)params[8], (UINT32)params[9], (UINT32)params[10], (UINT32)params[11],
+ (UINT32)params[12], (UINT32)params[13], (UINT32)params[14], (UINT32)params[15],
+ (UINT32)params[16], (UINT32)params[17], (UINT32)params[18], (UINT32)params[19],
+ (UINT32)params[20], (UINT32)params[21], (UINT32)params[22], (UINT32)params[23],
+ (UINT32)params[24], (UINT32)params[25], (UINT32)params[26], (UINT32)params[27],
+ (UINT32)params[28], (UINT32)params[29], (UINT32)params[30], (UINT32)params[31]);
+ }
+}
+
+
+//-------------------------------------------------
+// save - save a single action or output
+//-------------------------------------------------
+
+void cheat_script::script_entry::save(emu_file &cheatfile) const
+{
+ // output an action
+ if (m_format.empty())
+ {
+ cheatfile.printf("\t\t\t<action");
+ if (!m_condition.is_empty())
+ cheatfile.printf(" condition=\"%s\"", cheat_manager::quote_expression(m_condition).c_str());
+ cheatfile.printf(">%s</action>\n", cheat_manager::quote_expression(m_expression).c_str());
+ }
+
+ // output an output
+ else
+ {
+ cheatfile.printf("\t\t\t<output format=\"%s\"", m_format.c_str());
+ if (!m_condition.is_empty())
+ cheatfile.printf(" condition=\"%s\"", cheat_manager::quote_expression(m_condition).c_str());
+ if (m_line != 0)
+ cheatfile.printf(" line=\"%d\"", m_line);
+ if (m_justify == JUSTIFY_CENTER)
+ cheatfile.printf(" align=\"center\"");
+ else if (m_justify == JUSTIFY_RIGHT)
+ cheatfile.printf(" align=\"right\"");
+ if (m_arglist.count() == 0)
+ cheatfile.printf(" />\n");
+
+ // output arguments
+ else
+ {
+ cheatfile.printf(">\n");
+ for (const output_argument &curarg : m_arglist)
+ curarg.save(cheatfile);
+ cheatfile.printf("\t\t\t</output>\n");
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// validate_format - check that a format string
+// has the correct number and type of arguments
+//-------------------------------------------------
+
+void cheat_script::script_entry::validate_format(const char *filename, int line)
+{
+ // first count arguments
+ int argsprovided = 0;
+ for (const output_argument &curarg : m_arglist)
+ argsprovided += curarg.count();
+
+ // now scan the string for valid argument usage
+ const char *p = strchr(m_format.c_str(), '%');
+ int argscounted = 0;
+ while (p != nullptr)
+ {
+ // skip past any valid attributes
+ p++;
+ while (strchr("lh0123456789.-+ #", *p) != nullptr)
+ p++;
+
+ // look for a valid type
+ if (strchr("cdiouxX", *p) == nullptr)
+ throw emu_fatalerror("%s.xml(%d): invalid format specification \"%s\"\n", filename, line, m_format.c_str());
+ argscounted++;
+
+ // look for the next one
+ p = strchr(p, '%');
+ }
+
+ // did we match?
+ if (argscounted < argsprovided)
+ throw emu_fatalerror("%s.xml(%d): too many arguments provided (%d) for format \"%s\"\n", filename, line, argsprovided, m_format.c_str());
+ if (argscounted > argsprovided)
+ throw emu_fatalerror("%s.xml(%d): not enough arguments provided (%d) for format \"%s\"\n", filename, line, argsprovided, m_format.c_str());
+}
+
+
+//-------------------------------------------------
+// output_argument - constructor
+//-------------------------------------------------
+
+cheat_script::script_entry::output_argument::output_argument(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node &argnode)
+ : m_next(nullptr),
+ m_expression(&symbols),
+ m_count(0)
+{
+ // first extract attributes
+ m_count = xml_get_attribute_int(&argnode, "count", 1);
+
+ // read the expression
+ const char *expression = argnode.value;
+ if (expression == nullptr || expression[0] == 0)
+ throw emu_fatalerror("%s.xml(%d): missing expression in argument tag\n", filename, argnode.line);
+
+ // parse it
+ try
+ {
+ m_expression.parse(expression);
+ }
+ catch (expression_error &err)
+ {
+ throw emu_fatalerror("%s.xml(%d): error parsing cheat expression \"%s\" (%s)\n", filename, argnode.line, expression, err.code_string());
+ }
+}
+
+
+//-------------------------------------------------
+// value - return the evaluated value of the
+// given output argument
+//-------------------------------------------------
+
+int cheat_script::script_entry::output_argument::values(UINT64 &argindex, UINT64 *result)
+{
+ for (argindex = 0; argindex < m_count; argindex++)
+ {
+ try
+ {
+ result[argindex] = m_expression.execute();
+ }
+ catch (expression_error &err)
+ {
+ osd_printf_warning("Error executing argument expression \"%s\": %s\n", m_expression.original_string(), err.code_string());
+ }
+ }
+ return m_count;
+}
+
+
+//-------------------------------------------------
+// save - save a single output argument
+//-------------------------------------------------
+
+void cheat_script::script_entry::output_argument::save(emu_file &cheatfile) const
+{
+ cheatfile.printf("\t\t\t\t<argument");
+ if (m_count != 1)
+ cheatfile.printf(" count=\"%d\"", (int)m_count);
+ cheatfile.printf(">%s</argument>\n", cheat_manager::quote_expression(m_expression).c_str());
+}
+
+
+
+//**************************************************************************
+// CHEAT ENTRY
+//**************************************************************************
+
+//-------------------------------------------------
+// cheat_entry - constructor
+//-------------------------------------------------
+
+cheat_entry::cheat_entry(cheat_manager &manager, symbol_table &globaltable, const char *filename, xml_data_node &cheatnode)
+ : m_manager(manager),
+ m_next(nullptr),
+ m_symbols(&manager.machine(), &globaltable),
+ m_state(SCRIPT_STATE_OFF),
+ m_numtemp(DEFAULT_TEMP_VARIABLES),
+ m_argindex(0)
+{
+ // reset scripts
+ try
+ {
+ // pull the variable count out ahead of things
+ int tempcount = xml_get_attribute_int(&cheatnode, "tempvariables", DEFAULT_TEMP_VARIABLES);
+ if (tempcount < 1)
+ throw emu_fatalerror("%s.xml(%d): invalid tempvariables attribute (%d)\n", filename, cheatnode.line, tempcount);
+
+ // allocate memory for the cheat
+ m_numtemp = tempcount;
+
+ // get the description
+ const char *description = xml_get_attribute_string(&cheatnode, "desc", nullptr);
+ if (description == nullptr || description[0] == 0)
+ throw emu_fatalerror("%s.xml(%d): empty or missing desc attribute on cheat\n", filename, cheatnode.line);
+ m_description = description;
+
+ // create the symbol table
+ m_symbols.add("argindex", symbol_table::READ_ONLY, &m_argindex);
+ for (int curtemp = 0; curtemp < tempcount; curtemp++) {
+ m_symbols.add(string_format("temp%d", curtemp).c_str(), symbol_table::READ_WRITE);
+ }
+
+ // read the first comment node
+ xml_data_node *commentnode = xml_get_sibling(cheatnode.child, "comment");
+ if (commentnode != nullptr)
+ {
+ // set the value if not NULL
+ if (commentnode->value != nullptr && commentnode->value[0] != 0)
+ m_comment.assign(commentnode->value);
+
+ // only one comment is kept
+ commentnode = xml_get_sibling(commentnode->next, "comment");
+ if (commentnode != nullptr)
+ osd_printf_warning("%s.xml(%d): only one comment node is retained; ignoring additional nodes\n", filename, commentnode->line);
+ }
+
+ // read the first parameter node
+ xml_data_node *paramnode = xml_get_sibling(cheatnode.child, "parameter");
+ if (paramnode != nullptr)
+ {
+ // load this parameter
+ m_parameter.reset(global_alloc(cheat_parameter(manager, m_symbols, filename, *paramnode)));
+
+ // only one parameter allowed
+ paramnode = xml_get_sibling(paramnode->next, "parameter");
+ if (paramnode != nullptr)
+ osd_printf_warning("%s.xml(%d): only one parameter node allowed; ignoring additional nodes\n", filename, paramnode->line);
+ }
+
+ // read the script nodes
+ for (xml_data_node *scriptnode = xml_get_sibling(cheatnode.child, "script"); scriptnode != nullptr; scriptnode = xml_get_sibling(scriptnode->next, "script"))
+ {
+ // load this entry
+ auto curscript = global_alloc(cheat_script(manager, m_symbols, filename, *scriptnode));
+
+ // if we have a script already for this slot, it is an error
+ std::unique_ptr<cheat_script> &slot = script_for_state(curscript->state());
+ if (slot != nullptr)
+ osd_printf_warning("%s.xml(%d): only one on script allowed; ignoring additional scripts\n", filename, scriptnode->line);
+ else
+ slot.reset(curscript);
+ }
+ }
+ catch (emu_fatalerror &)
+ {
+ // call our destructor to clean up and re-throw
+ this->~cheat_entry();
+ throw;
+ }
+}
+
+
+//-------------------------------------------------
+// ~cheat_entry - destructor
+//-------------------------------------------------
+
+cheat_entry::~cheat_entry()
+{
+}
+
+
+//-------------------------------------------------
+// save - save a single cheat entry
+//-------------------------------------------------
+
+void cheat_entry::save(emu_file &cheatfile) const
+{
+ // determine if we have scripts
+ bool has_scripts = (m_off_script != nullptr || m_on_script != nullptr || m_run_script != nullptr || m_change_script != nullptr);
+
+ // output the cheat tag
+ cheatfile.printf("\t<cheat desc=\"%s\"", m_description.c_str());
+ if (m_numtemp != DEFAULT_TEMP_VARIABLES)
+ cheatfile.printf(" tempvariables=\"%d\"", m_numtemp);
+ if (m_comment.empty() && m_parameter == nullptr && !has_scripts)
+ cheatfile.printf(" />\n");
+ else
+ {
+ cheatfile.printf(">\n");
+
+ // save the comment
+ if (!m_comment.empty())
+ cheatfile.printf("\t\t<comment><![CDATA[\n%s\n\t\t]]></comment>\n", m_comment.c_str());
+
+ // output the parameter, if present
+ if (m_parameter != nullptr)
+ m_parameter->save(cheatfile);
+
+ // output the script nodes
+ if (m_on_script != nullptr)
+ m_on_script->save(cheatfile);
+ if (m_off_script != nullptr)
+ m_off_script->save(cheatfile);
+ if (m_change_script != nullptr)
+ m_change_script->save(cheatfile);
+ if (m_run_script != nullptr)
+ m_run_script->save(cheatfile);
+
+ // close the cheat tag
+ cheatfile.printf("\t</cheat>\n");
+ }
+}
+
+
+//-------------------------------------------------
+// activate - activate a oneshot cheat
+//-------------------------------------------------
+
+bool cheat_entry::activate()
+{
+ bool changed = false;
+
+ // if cheats have been toggled off no point in even trying to do anything
+ if (!m_manager.enabled())
+ return changed;
+
+ // if we're a oneshot cheat, execute the "on" script and indicate change
+ if (is_oneshot())
+ {
+ execute_on_script();
+ changed = true;
+ m_manager.machine().popmessage("Activated %s", m_description.c_str());
+ }
+
+ // if we're a oneshot parameter cheat and we're active, execute the "state change" script and indicate change
+ else if (is_oneshot_parameter() && m_state != SCRIPT_STATE_OFF)
+ {
+ execute_change_script();
+ changed = true;
+ m_manager.machine().popmessage("Activated\n %s = %s", m_description.c_str(), m_parameter->text());
+ }
+
+ return changed;
+}
+
+
+//-------------------------------------------------
+// select_default_state - select the default
+// state for a cheat, or activate a oneshot cheat
+//-------------------------------------------------
+
+bool cheat_entry::select_default_state()
+{
+ bool changed = false;
+
+ // if we're a oneshot cheat, there is no default state
+ if (is_oneshot())
+ ;
+
+ // all other types switch to the "off" state
+ else
+ changed = set_state(SCRIPT_STATE_OFF);
+
+ return changed;
+}
+
+
+//-------------------------------------------------
+// select_previous_state - select the previous
+// state for a cheat
+//-------------------------------------------------
+
+bool cheat_entry::select_previous_state()
+{
+ bool changed = false;
+
+ // if we're a oneshot, there is no previous state
+ if (is_oneshot())
+ ;
+
+ // if we're on/off, toggle to off
+ else if (is_onoff())
+ changed = set_state(SCRIPT_STATE_OFF);
+
+ // if we have a parameter, set the previous state
+ else if (m_parameter != nullptr)
+ {
+ // if we're at our minimum, turn off
+ if (m_parameter->is_minimum())
+ changed = set_state(SCRIPT_STATE_OFF);
+ else
+ {
+ // if we changed, ensure we are in the running state and signal state change
+ changed = m_parameter->set_prev_state();
+ if (changed)
+ {
+ set_state(SCRIPT_STATE_RUN);
+ if (!is_oneshot_parameter())
+ execute_change_script();
+ }
+ }
+ }
+ return changed;
+}
+
+
+//-------------------------------------------------
+// select_next_state - select the next state for
+// a cheat
+//-------------------------------------------------
+
+bool cheat_entry::select_next_state()
+{
+ bool changed = false;
+
+ // if we're a oneshot, there is no next state
+ if (is_oneshot())
+ ;
+
+ // if we're on/off, toggle to running state
+ else if (is_onoff())
+ changed = set_state(SCRIPT_STATE_RUN);
+
+ // if we have a parameter, set the next state
+ else if (m_parameter != nullptr)
+ {
+ // if we're off, switch on to the minimum state
+ if (m_state == SCRIPT_STATE_OFF)
+ {
+ changed = set_state(SCRIPT_STATE_RUN);
+ m_parameter->set_minimum_state();
+ }
+
+ // otherwise, switch to the next state
+ else
+ changed = m_parameter->set_next_state();
+
+ // if we changed, signal a state change
+ if (changed && !is_oneshot_parameter())
+ execute_change_script();
+ }
+ return changed;
+}
+
+
+//-------------------------------------------------
+// menu_text - return the text needed to display
+// this cheat in a menu item
+//-------------------------------------------------
+
+void cheat_entry::menu_text(std::string &description, std::string &state, UINT32 &flags)
+{
+ // description is standard
+ description.assign(m_description);
+ state.clear();
+ flags = 0;
+
+ // some cheat entries are just text for display
+ if (is_text_only())
+ {
+ if (!description.empty())
+ {
+ strtrimspace(description);
+ if (description.empty())
+ description.assign(MENU_SEPARATOR_ITEM);
+ }
+ flags = MENU_FLAG_DISABLE;
+ }
+
+ // if we have no parameter and no run or off script, it's a oneshot cheat
+ else if (is_oneshot())
+ state.assign("Set");
+
+ // if we have no parameter, it's just on/off
+ else if (is_onoff())
+ {
+ state.assign((m_state == SCRIPT_STATE_RUN) ? "On" : "Off");
+ flags = (m_state != 0) ? MENU_FLAG_LEFT_ARROW : MENU_FLAG_RIGHT_ARROW;
+ }
+
+ // if we have a value parameter, compute it
+ else if (m_parameter != nullptr)
+ {
+ if (m_state == SCRIPT_STATE_OFF)
+ {
+ state.assign(is_oneshot_parameter() ? "Set" : "Off");
+ flags = MENU_FLAG_RIGHT_ARROW;
+ }
+ else
+ {
+ state.assign(m_parameter->text());
+ flags = MENU_FLAG_LEFT_ARROW;
+ if (!m_parameter->is_maximum())
+ flags |= MENU_FLAG_RIGHT_ARROW;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// set_state - switch to the given state
+//-------------------------------------------------
+
+bool cheat_entry::set_state(script_state newstate)
+{
+ // if we're already in the state, indicate no change
+ if (m_state == newstate)
+ return false;
+
+ // change to the state and run the appropriate script
+ m_state = newstate;
+ if (newstate == SCRIPT_STATE_OFF)
+ execute_off_script();
+ else if (newstate == SCRIPT_STATE_ON || newstate == SCRIPT_STATE_RUN)
+ execute_on_script();
+ return true;
+}
+
+
+//-------------------------------------------------
+// script_for_state - get a reference to the
+// given script pointer
+//-------------------------------------------------
+
+std::unique_ptr<cheat_script> &cheat_entry::script_for_state(script_state state)
+{
+ switch (state)
+ {
+ case SCRIPT_STATE_ON: return m_on_script;
+ case SCRIPT_STATE_OFF: return m_off_script;
+ case SCRIPT_STATE_CHANGE: return m_change_script;
+ default:
+ case SCRIPT_STATE_RUN: return m_run_script;
+ }
+}
+
+
+//-------------------------------------------------
+// is_duplicate - determine if a new cheat entry
+// is already included in the list
+//-------------------------------------------------
+
+bool cheat_entry::is_duplicate() const
+{
+ for (cheat_entry &scannode : manager().entries())
+ if (strcmp(scannode.description(), description()) == 0)
+ return true;
+ return false;
+}
+
+
+//**************************************************************************
+// CHEAT MANAGER
+//**************************************************************************
+
+const int cheat_manager::CHEAT_VERSION;
+
+
+//-------------------------------------------------
+// cheat_manager - constructor
+//-------------------------------------------------
+
+cheat_manager::cheat_manager(running_machine &machine)
+ : m_machine(machine),
+ m_disabled(true),
+ m_symtable(&machine)
+{
+ // if the cheat engine is disabled, we're done
+ if (!machine.options().cheat())
+ return;
+
+ m_output.resize(UI_TARGET_FONT_ROWS*2);
+ m_justify.resize(UI_TARGET_FONT_ROWS*2);
+
+ // request a callback
+ machine.add_notifier(MACHINE_NOTIFY_FRAME, machine_notify_delegate(FUNC(cheat_manager::frame_update), this));
+
+ // create a global symbol table
+ m_symtable.add("frame", symbol_table::READ_ONLY, &m_framecount);
+ m_symtable.add("frombcd", nullptr, 1, 1, execute_frombcd);
+ m_symtable.add("tobcd", nullptr, 1, 1, execute_tobcd);
+
+ // we rely on the debugger expression callbacks; if the debugger isn't
+ // enabled, we must jumpstart them manually
+ if ((machine.debug_flags & DEBUG_FLAG_ENABLED) == 0)
+ debug_cpu_init(machine);
+
+ // configure for memory access (shared with debugger)
+ debug_cpu_configure_memory(machine, m_symtable);
+
+ // load the cheats
+ reload();
+}
+
+
+//-------------------------------------------------
+// set_enable - globally enable or disable the
+// cheat engine
+//-------------------------------------------------
+
+void cheat_manager::set_enable(bool enable)
+{
+ // if the cheat engine is disabled, we're done
+ if (!machine().options().cheat())
+ return;
+
+ // if we're enabled currently and we don't want to be, turn things off
+ if (!m_disabled && !enable)
+ {
+ // iterate over running cheats and execute any OFF Scripts
+ for (cheat_entry &cheat : m_cheatlist)
+ if (cheat.state() == SCRIPT_STATE_RUN)
+ cheat.execute_off_script();
+ machine().popmessage("Cheats Disabled");
+ m_disabled = true;
+ }
+
+ // if we're disabled currently and we want to be enabled, turn things on
+ else if (m_disabled && enable)
+ {
+ // iterate over running cheats and execute any ON Scripts
+ m_disabled = false;
+ for (cheat_entry &cheat : m_cheatlist)
+ if (cheat.state() == SCRIPT_STATE_RUN)
+ cheat.execute_on_script();
+ machine().popmessage("Cheats Enabled");
+ }
+}
+
+
+//-------------------------------------------------
+// reload - re-initialize the cheat engine, and
+// and reload the cheat file(s)
+//-------------------------------------------------
+
+void cheat_manager::reload()
+{
+ // if the cheat engine is disabled, we're done
+ if (!machine().options().cheat())
+ return;
+
+ // free everything
+ m_cheatlist.reset();
+
+ // reset state
+ m_framecount = 0;
+ m_numlines = 0;
+ m_lastline = 0;
+ m_disabled = false;
+
+ // load the cheat file, if it's a system that has a software list then try softlist_name/shortname.xml first,
+ // if it fails to load then try to load via crc32 - basename/crc32.xml ( eg. 01234567.xml )
+ for (device_image_interface &image : image_interface_iterator(machine().root_device()))
+ if (image.exists())
+ {
+ // if we are loading through a software list, try to load softlist_name/shortname.xml
+ // this allows the coexistence of arcade cheats with cheats for home conversions which
+ // have the same shortname
+ if (image.software_entry() != nullptr)
+ {
+ load_cheats(string_format("%s%s%s", image.software_list_name(), PATH_SEPARATOR, image.basename()).c_str());
+ break;
+ }
+ // else we are loading outside the software list, try to load machine_basename/crc32.xml
+ else
+ {
+ UINT32 crc = image.crc();
+ if (crc != 0)
+ {
+ load_cheats(string_format("%s%s%08X", machine().basename(), PATH_SEPARATOR, crc).c_str());
+ break;
+ }
+ }
+ }
+
+ // if we haven't found the cheats yet, load by basename
+ if (m_cheatlist.count() == 0)
+ load_cheats(machine().basename());
+
+ // temporary: save the file back out as output.xml for comparison
+ if (m_cheatlist.count() != 0)
+ save_all("output");
+}
+
+
+//-------------------------------------------------
+// cheat_list_save - save a cheat file from
+// memory to the given filename
+//-------------------------------------------------
+
+bool cheat_manager::save_all(const char *filename)
+{
+ // open the file with the proper name
+ emu_file cheatfile(machine().options().cheat_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ osd_file::error filerr = cheatfile.open(filename, ".xml");
+
+ // if that failed, return nothing
+ if (filerr != osd_file::error::NONE)
+ return false;
+
+ // wrap the rest of catch errors
+ try
+ {
+ // output the outer layers
+ cheatfile.printf("<?xml version=\"1.0\"?>\n");
+ cheatfile.printf("<!-- This file is autogenerated; comments and unknown tags will be stripped -->\n");
+ cheatfile.printf("<mamecheat version=\"%d\">\n", CHEAT_VERSION);
+
+ // iterate over cheats in the list and save them
+ for (cheat_entry &cheat : m_cheatlist)
+ cheat.save(cheatfile);
+
+ // close out the file
+ cheatfile.printf("</mamecheat>\n");
+ return true;
+ }
+
+ // catch errors and cleanup
+ catch (emu_fatalerror &err)
+ {
+ osd_printf_error("%s\n", err.string());
+ cheatfile.remove_on_close();
+ }
+ return false;
+}
+
+
+//-------------------------------------------------
+// render_text - called by the UI system to
+// render text
+//-------------------------------------------------
+
+void cheat_manager::render_text(render_container &container)
+{
+ // render any text and free it along the way
+ for (int linenum = 0; linenum < m_output.size(); linenum++)
+ if (!m_output[linenum].empty())
+ {
+ // output the text
+ mame_machine_manager::instance()->ui().draw_text_full(&container, m_output[linenum].c_str(),
+ 0.0f, (float)linenum * mame_machine_manager::instance()->ui().get_line_height(), 1.0f,
+ m_justify[linenum], WRAP_NEVER, DRAW_OPAQUE,
+ ARGB_WHITE, ARGB_BLACK, nullptr, nullptr);
+ }
+}
+
+
+//-------------------------------------------------
+// get_output_astring - return a reference to
+// the given row's string, and set the
+// justification
+//-------------------------------------------------
+
+std::string &cheat_manager::get_output_astring(int row, int justify)
+{
+ // if the row is not specified, grab the next one
+ if (row == 0)
+ row = (m_lastline >= 0) ? m_lastline + 1 : m_lastline - 1;
+
+ // remember the last request
+ m_lastline = row;
+
+ // invert if negative
+ row = (row < 0) ? m_numlines + row : row - 1;
+
+ // clamp within range
+ row = MAX(row, 0);
+ row = MIN(row, m_numlines - 1);
+
+ // return the appropriate string
+ m_justify[row] = justify;
+ return m_output[row];
+}
+
+
+//-------------------------------------------------
+// quote_expression - quote an expression
+// string so that it is valid to embed in an XML
+// document
+//-------------------------------------------------
+
+std::string cheat_manager::quote_expression(const parsed_expression &expression)
+{
+ std::string str = expression.original_string();
+
+ strreplace(str, " && ", " and ");
+ strreplace(str, " &&", " and ");
+ strreplace(str, "&& ", " and ");
+ strreplace(str, "&&", " and ");
+
+ strreplace(str, " & ", " band ");
+ strreplace(str, " &", " band ");
+ strreplace(str, "& ", " band ");
+ strreplace(str, "&", " band ");
+
+ strreplace(str, " <= ", " le ");
+ strreplace(str, " <=", " le ");
+ strreplace(str, "<= ", " le ");
+ strreplace(str, "<=", " le ");
+
+ strreplace(str, " < ", " lt ");
+ strreplace(str, " <", " lt ");
+ strreplace(str, "< ", " lt ");
+ strreplace(str, "<", " lt ");
+
+ strreplace(str, " << ", " lshift ");
+ strreplace(str, " <<", " lshift ");
+ strreplace(str, "<< ", " lshift ");
+ strreplace(str, "<<", " lshift ");
+
+ return str;
+}
+
+
+//-------------------------------------------------
+// execute_frombcd - convert a value from BCD
+//-------------------------------------------------
+
+UINT64 cheat_manager::execute_frombcd(symbol_table &table, void *ref, int params, const UINT64 *param)
+{
+ UINT64 value = param[0];
+ UINT64 multiplier = 1;
+ UINT64 result = 0;
+
+ while (value != 0)
+ {
+ result += (value & 0x0f) * multiplier;
+ value >>= 4;
+ multiplier *= 10;
+ }
+ return result;
+}
+
+
+//-------------------------------------------------
+// execute_tobcd - convert a value to BCD
+//-------------------------------------------------
+
+UINT64 cheat_manager::execute_tobcd(symbol_table &table, void *ref, int params, const UINT64 *param)
+{
+ UINT64 value = param[0];
+ UINT64 result = 0;
+ UINT8 shift = 0;
+
+ while (value != 0)
+ {
+ result += (value % 10) << shift;
+ value /= 10;
+ shift += 4;
+ }
+ return result;
+}
+
+
+//-------------------------------------------------
+// frame_update - per-frame callback
+//-------------------------------------------------
+
+void cheat_manager::frame_update()
+{
+ // set up for accumulating output
+ m_lastline = 0;
+ m_numlines = floor(1.0f / mame_machine_manager::instance()->ui().get_line_height());
+ m_numlines = MIN(m_numlines, m_output.size());
+ for (auto & elem : m_output)
+ elem.clear();
+
+ // iterate over running cheats and execute them
+ for (cheat_entry &cheat : m_cheatlist)
+ cheat.frame_update();
+
+ // increment the frame counter
+ m_framecount++;
+}
+
+
+//-------------------------------------------------
+// load_cheats - load a cheat file into memory
+// and create the cheat entry list
+//-------------------------------------------------
+
+void cheat_manager::load_cheats(const char *filename)
+{
+ xml_data_node *rootnode = nullptr;
+ std::string searchstr(machine().options().cheat_path());
+ path_iterator path(searchstr.c_str());
+ std::string curpath;
+ while (path.next(curpath))
+ {
+ searchstr.append(";").append(curpath).append(PATH_SEPARATOR).append("cheat");
+ }
+ emu_file cheatfile(searchstr.c_str(), OPEN_FLAG_READ);
+ try
+ {
+ // open the file with the proper name
+ osd_file::error filerr = cheatfile.open(filename, ".xml");
+
+ // loop over all instrances of the files found in our search paths
+ while (filerr == osd_file::error::NONE)
+ {
+ osd_printf_verbose("Loading cheats file from %s\n", cheatfile.fullpath());
+
+ // read the XML file into internal data structures
+ xml_parse_options options = { nullptr };
+ xml_parse_error error;
+ options.error = &error;
+ rootnode = xml_file_read(cheatfile, &options);
+
+ // if unable to parse the file, just bail
+ if (rootnode == nullptr)
+ throw emu_fatalerror("%s.xml(%d): error parsing XML (%s)\n", filename, error.error_line, error.error_message);
+
+ // find the layout node
+ xml_data_node *mamecheatnode = xml_get_sibling(rootnode->child, "mamecheat");
+ if (mamecheatnode == nullptr)
+ throw emu_fatalerror("%s.xml: missing mamecheatnode node", filename);
+
+ // validate the config data version
+ int version = xml_get_attribute_int(mamecheatnode, "version", 0);
+ if (version != CHEAT_VERSION)
+ throw emu_fatalerror("%s.xml(%d): Invalid cheat XML file: unsupported version", filename, mamecheatnode->line);
+
+ // parse all the elements
+ for (xml_data_node *cheatnode = xml_get_sibling(mamecheatnode->child, "cheat"); cheatnode != nullptr; cheatnode = xml_get_sibling(cheatnode->next, "cheat"))
+ {
+ // load this entry
+ cheat_entry *curcheat = global_alloc(cheat_entry(*this, m_symtable, filename, *cheatnode));
+
+ // make sure we're not a duplicate
+ if (REMOVE_DUPLICATE_CHEATS && curcheat->is_duplicate())
+ {
+ osd_printf_verbose("Ignoring duplicate cheat '%s' from file %s\n", curcheat->description(), cheatfile.fullpath());
+ global_free(curcheat);
+ }
+ else // add to the end of the list
+ m_cheatlist.append(*curcheat);
+ }
+
+ // free the file and loop for the next one
+ xml_file_free(rootnode);
+
+ // open the next file in sequence
+ filerr = cheatfile.open_next();
+ }
+ }
+
+ // handle errors cleanly
+ catch (emu_fatalerror &err)
+ {
+ osd_printf_error("%s\n", err.string());
+ m_cheatlist.reset();
+ if (rootnode != nullptr)
+ xml_file_free(rootnode);
+ }
+}
diff --git a/src/frontend/mame/cheat.h b/src/frontend/mame/cheat.h
new file mode 100644
index 00000000000..dac90e17286
--- /dev/null
+++ b/src/frontend/mame/cheat.h
@@ -0,0 +1,337 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+/***************************************************************************
+
+ cheat.h
+
+ Cheat system.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __CHEAT_H__
+#define __CHEAT_H__
+
+#include "debug/express.h"
+#include "ui/ui.h"
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+enum script_state
+{
+ SCRIPT_STATE_OFF = 0,
+ SCRIPT_STATE_ON,
+ SCRIPT_STATE_RUN,
+ SCRIPT_STATE_CHANGE,
+ SCRIPT_STATE_COUNT
+};
+DECLARE_ENUM_OPERATORS(script_state)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class cheat_manager;
+
+
+// ======================> number_and_format
+
+// helper class to remember a format along with a number
+class number_and_format
+{
+public:
+ // construction/destruction
+ number_and_format(UINT64 value = 0, int format = 0)
+ : m_value(value),
+ m_format(format) { }
+
+ // pass-through to look like a regular number
+ operator UINT64 &() { return m_value; }
+ operator const UINT64 &() const { return m_value; }
+
+ // format the number according to its format
+ std::string format() const;
+
+private:
+ // internal state
+ UINT64 m_value;
+ int m_format;
+};
+
+
+// ======================> cheat_parameter
+
+// a parameter for a cheat, which can be set in the UI
+class cheat_parameter
+{
+public:
+ // construction/destruction
+ cheat_parameter(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node &paramnode);
+
+ // queries
+ const char *text();
+ bool has_itemlist() const { return (m_itemlist.count() != 0); }
+ bool is_minimum() const { return (m_value == ((m_itemlist.count() == 0) ? m_minval : m_itemlist.first()->value())); }
+ bool is_maximum() const { return (m_value == ((m_itemlist.count() == 0) ? m_maxval : m_itemlist.last()->value())); }
+
+ // state setters
+ bool set_minimum_state();
+ bool set_prev_state();
+ bool set_next_state();
+
+ // actions
+ void save(emu_file &cheatfile) const;
+
+private:
+ // a single item in a parameter item list
+ class item
+ {
+ friend class simple_list<item>;
+
+ public:
+ // construction/destruction
+ item(const char *text, UINT64 value, int valformat)
+ : m_next(nullptr),
+ m_text(text),
+ m_value(value, valformat) { }
+
+ // getters
+ item *next() const { return m_next; }
+ const number_and_format &value() const { return m_value; }
+ const char *text() const { return m_text.c_str(); }
+
+ private:
+ // internal state
+ item * m_next; // next item in list
+ std::string m_text; // name of the item
+ number_and_format m_value; // value of the item
+ };
+
+ // internal state
+ number_and_format m_minval; // minimum value
+ number_and_format m_maxval; // maximum value
+ number_and_format m_stepval; // step value
+ UINT64 m_value; // live value of the parameter
+ std::string m_curtext; // holding for a value string
+ simple_list<item> m_itemlist; // list of items
+};
+
+
+// ======================> cheat_script
+
+// a script entry, specifying which state to execute under
+class cheat_script
+{
+ friend class simple_list<cheat_script>;
+
+public:
+ // construction/destruction
+ cheat_script(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node &scriptnode);
+
+ // getters
+ script_state state() const { return m_state; }
+
+ // actions
+ void execute(cheat_manager &manager, UINT64 &argindex);
+ void save(emu_file &cheatfile) const;
+
+private:
+ // an entry within the script
+ class script_entry
+ {
+ friend class simple_list<script_entry>;
+
+ public:
+ // construction/destruction
+ script_entry(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node &entrynode, bool isaction);
+
+ // getters
+ script_entry *next() const { return m_next; }
+
+ // actions
+ void execute(cheat_manager &manager, UINT64 &argindex);
+ void save(emu_file &cheatfile) const;
+
+ private:
+ // an argument for output
+ class output_argument
+ {
+ friend class simple_list<output_argument>;
+
+ public:
+ // construction/destruction
+ output_argument(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node &argnode);
+
+ // getters
+ output_argument *next() const { return m_next; }
+ int count() const { return m_count; }
+ int values(UINT64 &argindex, UINT64 *result);
+
+ // actions
+ void save(emu_file &cheatfile) const;
+
+ private:
+ // internal state
+ output_argument * m_next; // link to next argument
+ parsed_expression m_expression; // expression for argument
+ UINT64 m_count; // number of repetitions
+ };
+
+ // internal helpers
+ void validate_format(const char *filename, int line);
+
+ // internal state
+ script_entry * m_next; // link to next entry
+ parsed_expression m_condition; // condition under which this is executed
+ parsed_expression m_expression; // expression to execute
+ std::string m_format; // string format to print
+ simple_list<output_argument> m_arglist; // list of arguments
+ INT8 m_line; // which line to print on
+ UINT8 m_justify; // justification when printing
+
+ // constants
+ static const int MAX_ARGUMENTS = 32;
+ };
+
+ // internal state
+ simple_list<script_entry> m_entrylist; // list of actions to perform
+ script_state m_state; // which state this script is for
+};
+
+
+// ======================> cheat_entry
+
+// a single cheat
+class cheat_entry
+{
+ friend class simple_list<cheat_entry>;
+
+public:
+ // construction/destruction
+ cheat_entry(cheat_manager &manager, symbol_table &globaltable, const char *filename, xml_data_node &cheatnode);
+ ~cheat_entry();
+
+ // getters
+ cheat_manager &manager() const { return m_manager; }
+ cheat_entry *next() const { return m_next; }
+ script_state state() const { return m_state; }
+ const char *description() const { return m_description.c_str(); }
+ const char *comment() const { return m_comment.c_str(); }
+
+ // script detection
+ bool has_run_script() const { return (m_run_script != nullptr); }
+ bool has_on_script() const { return (m_on_script != nullptr); }
+ bool has_off_script() const { return (m_off_script != nullptr); }
+ bool has_change_script() const { return (m_change_script != nullptr); }
+
+ // script execution
+ void execute_off_script() { if (has_off_script()) m_off_script->execute(m_manager, m_argindex); }
+ void execute_on_script() { if (has_on_script()) m_on_script->execute(m_manager, m_argindex); }
+ void execute_run_script() { if (has_run_script()) m_run_script->execute(m_manager, m_argindex); }
+ void execute_change_script() { if (has_change_script()) m_change_script->execute(m_manager, m_argindex); }
+
+ // cheat classification
+ bool is_text_only() const { return (m_parameter == nullptr && !has_run_script() && !has_off_script() && !has_on_script()); }
+ bool is_oneshot() const { return (m_parameter == nullptr && !has_run_script() && !has_off_script() && has_on_script()); }
+ bool is_onoff() const { return (m_parameter == nullptr && (has_run_script() || (has_off_script() && has_on_script()))); }
+ bool is_value_parameter() const { return (m_parameter != nullptr && !m_parameter->has_itemlist()); }
+ bool is_itemlist_parameter() const { return (m_parameter != nullptr && m_parameter->has_itemlist()); }
+ bool is_oneshot_parameter() const { return (m_parameter != nullptr && !has_run_script() && !has_off_script() && has_change_script()); }
+ bool is_duplicate() const;
+
+ // actions
+ bool activate();
+ bool select_default_state();
+ bool select_previous_state();
+ bool select_next_state();
+ void save(emu_file &cheatfile) const;
+
+ // UI helpers
+ void menu_text(std::string &description, std::string &state, UINT32 &flags);
+
+ // per-frame update
+ void frame_update() { if (m_state == SCRIPT_STATE_RUN) execute_run_script(); }
+
+private:
+ // internal helpers
+ bool set_state(script_state newstate);
+ std::unique_ptr<cheat_script> &script_for_state(script_state state);
+
+ // internal state
+ cheat_manager & m_manager; // reference to our manager
+ cheat_entry * m_next; // next cheat entry
+ std::string m_description; // string description/menu title
+ std::string m_comment; // comment data
+ std::unique_ptr<cheat_parameter> m_parameter; // parameter
+ std::unique_ptr<cheat_script> m_on_script; // script to run when turning on
+ std::unique_ptr<cheat_script> m_off_script; // script to run when turning off
+ std::unique_ptr<cheat_script> m_change_script; // script to run when value changes
+ std::unique_ptr<cheat_script> m_run_script; // script to run each frame when on
+ symbol_table m_symbols; // symbol table for this cheat
+ script_state m_state; // current cheat state
+ UINT32 m_numtemp; // number of temporary variables
+ UINT64 m_argindex; // argument index variable
+
+ // constants
+ static const int DEFAULT_TEMP_VARIABLES = 10;
+};
+
+
+// ======================> cheat_manager
+
+// private machine-global data
+class cheat_manager
+{
+public:
+ // construction/destruction
+ cheat_manager(running_machine &machine);
+
+ // getters
+ running_machine &machine() const { return m_machine; }
+ bool enabled() const { return !m_disabled; }
+ const simple_list<cheat_entry> &entries() const { return m_cheatlist; }
+
+ // setters
+ void set_enable(bool enable = true);
+
+ // actions
+ void reload();
+ bool save_all(const char *filename);
+ void render_text(render_container &container);
+
+ // output helpers
+ std::string &get_output_astring(int row, int justify);
+
+ // global helpers
+ static std::string quote_expression(const parsed_expression &expression);
+ static UINT64 execute_frombcd(symbol_table &table, void *ref, int params, const UINT64 *param);
+ static UINT64 execute_tobcd(symbol_table &table, void *ref, int params, const UINT64 *param);
+
+private:
+ // internal helpers
+ void frame_update();
+ void load_cheats(const char *filename);
+
+ // internal state
+ running_machine & m_machine; // reference to our machine
+ simple_list<cheat_entry> m_cheatlist; // cheat list
+ UINT64 m_framecount; // frame count
+ std::vector<std::string> m_output; // array of output strings
+ std::vector<UINT8> m_justify; // justification for each string
+ UINT8 m_numlines; // number of lines available for output
+ INT8 m_lastline; // last line used for output
+ bool m_disabled; // true if the cheat engine is disabled
+ symbol_table m_symtable; // global symbol table
+
+ // constants
+ static constexpr int CHEAT_VERSION = 1;
+};
+
+
+#endif /* __CHEAT_H__ */
diff --git a/src/frontend/mame/clifront.cpp b/src/frontend/mame/clifront.cpp
new file mode 100644
index 00000000000..9d81306aa60
--- /dev/null
+++ b/src/frontend/mame/clifront.cpp
@@ -0,0 +1,2051 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+/***************************************************************************
+
+ clifront.c
+
+ Command-line interface frontend for MAME.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "mame.h"
+#include "chd.h"
+#include "emuopts.h"
+#include "mameopts.h"
+#include "jedparse.h"
+#include "audit.h"
+#include "info.h"
+#include "unzip.h"
+#include "validity.h"
+#include "sound/samples.h"
+#include "clifront.h"
+#include "xmlfile.h"
+
+#include "drivenum.h"
+
+#include "osdepend.h"
+#include "softlist.h"
+
+#include "ui/moptions.h"
+
+#include <new>
+#include <ctype.h>
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// core commands
+#define CLICOMMAND_HELP "help"
+#define CLICOMMAND_VALIDATE "validate"
+
+// configuration commands
+#define CLICOMMAND_CREATECONFIG "createconfig"
+#define CLICOMMAND_SHOWCONFIG "showconfig"
+#define CLICOMMAND_SHOWUSAGE "showusage"
+
+// frontend commands
+#define CLICOMMAND_LISTXML "listxml"
+#define CLICOMMAND_LISTFULL "listfull"
+#define CLICOMMAND_LISTSOURCE "listsource"
+#define CLICOMMAND_LISTCLONES "listclones"
+#define CLICOMMAND_LISTBROTHERS "listbrothers"
+#define CLICOMMAND_LISTCRC "listcrc"
+#define CLICOMMAND_LISTROMS "listroms"
+#define CLICOMMAND_LISTSAMPLES "listsamples"
+#define CLICOMMAND_VERIFYROMS "verifyroms"
+#define CLICOMMAND_VERIFYSAMPLES "verifysamples"
+#define CLICOMMAND_ROMIDENT "romident"
+#define CLICOMMAND_LISTDEVICES "listdevices"
+#define CLICOMMAND_LISTSLOTS "listslots"
+#define CLICOMMAND_LISTMEDIA "listmedia" // needed by MESS
+#define CLICOMMAND_LISTSOFTWARE "listsoftware"
+#define CLICOMMAND_VERIFYSOFTWARE "verifysoftware"
+#define CLICOMMAND_GETSOFTLIST "getsoftlist"
+#define CLICOMMAND_VERIFYSOFTLIST "verifysoftlist"
+
+
+//**************************************************************************
+// COMMAND-LINE OPTIONS
+//**************************************************************************
+
+static const options_entry cli_option_entries[] =
+{
+ /* core commands */
+ { nullptr, nullptr, OPTION_HEADER, "CORE COMMANDS" },
+ { CLICOMMAND_HELP ";h;?", "0", OPTION_COMMAND, "show help message" },
+ { CLICOMMAND_VALIDATE ";valid", "0", OPTION_COMMAND, "perform driver validation on all game drivers" },
+
+ /* configuration commands */
+ { nullptr, nullptr, OPTION_HEADER, "CONFIGURATION COMMANDS" },
+ { CLICOMMAND_CREATECONFIG ";cc", "0", OPTION_COMMAND, "create the default configuration file" },
+ { CLICOMMAND_SHOWCONFIG ";sc", "0", OPTION_COMMAND, "display running parameters" },
+ { CLICOMMAND_SHOWUSAGE ";su", "0", OPTION_COMMAND, "show this help" },
+
+ /* frontend commands */
+ { nullptr, nullptr, OPTION_HEADER, "FRONTEND COMMANDS" },
+ { CLICOMMAND_LISTXML ";lx", "0", OPTION_COMMAND, "all available info on driver in XML format" },
+ { CLICOMMAND_LISTFULL ";ll", "0", OPTION_COMMAND, "short name, full name" },
+ { CLICOMMAND_LISTSOURCE ";ls", "0", OPTION_COMMAND, "driver sourcefile" },
+ { CLICOMMAND_LISTCLONES ";lc", "0", OPTION_COMMAND, "show clones" },
+ { CLICOMMAND_LISTBROTHERS ";lb", "0", OPTION_COMMAND, "show \"brothers\", or other drivers from same sourcefile" },
+ { CLICOMMAND_LISTCRC, "0", OPTION_COMMAND, "CRC-32s" },
+ { CLICOMMAND_LISTROMS ";lr", "0", OPTION_COMMAND, "list required roms for a driver" },
+ { CLICOMMAND_LISTSAMPLES, "0", OPTION_COMMAND, "list optional samples for a driver" },
+ { CLICOMMAND_VERIFYROMS, "0", OPTION_COMMAND, "report romsets that have problems" },
+ { CLICOMMAND_VERIFYSAMPLES, "0", OPTION_COMMAND, "report samplesets that have problems" },
+ { CLICOMMAND_ROMIDENT, "0", OPTION_COMMAND, "compare files with known MAME roms" },
+ { CLICOMMAND_LISTDEVICES ";ld", "0", OPTION_COMMAND, "list available devices" },
+ { CLICOMMAND_LISTSLOTS ";lslot", "0", OPTION_COMMAND, "list available slots and slot devices" },
+ { CLICOMMAND_LISTMEDIA ";lm", "0", OPTION_COMMAND, "list available media for the system" },
+ { CLICOMMAND_LISTSOFTWARE ";lsoft", "0", OPTION_COMMAND, "list known software for the system" },
+ { CLICOMMAND_VERIFYSOFTWARE ";vsoft", "0", OPTION_COMMAND, "verify known software for the system" },
+ { CLICOMMAND_GETSOFTLIST ";glist", "0", OPTION_COMMAND, "retrieve software list by name" },
+ { CLICOMMAND_VERIFYSOFTLIST ";vlist", "0", OPTION_COMMAND, "verify software list by name" },
+ { nullptr }
+};
+
+
+// media_identifier class identifies media by hash via a search in
+// the driver database
+class media_identifier
+{
+public:
+ // construction/destruction
+ media_identifier(emu_options &options);
+
+ // getters
+ int total() const { return m_total; }
+ int matches() const { return m_matches; }
+ int nonroms() const { return m_nonroms; }
+
+ // operations
+ void reset() { m_total = m_matches = m_nonroms = 0; }
+ void identify(const char *name);
+ void identify_file(const char *name);
+ void identify_data(const char *name, const UINT8 *data, int length);
+ int find_by_hash(const hash_collection &hashes, int length);
+
+private:
+ // internal state
+ driver_enumerator m_drivlist;
+ int m_total;
+ int m_matches;
+ int m_nonroms;
+};
+
+
+//**************************************************************************
+// CLI FRONTEND
+//**************************************************************************
+
+//-------------------------------------------------
+// cli_frontend - constructor
+//-------------------------------------------------
+
+cli_frontend::cli_frontend(emu_options &options, osd_interface &osd)
+ : m_options(options),
+ m_osd(osd),
+ m_result(EMU_ERR_NONE)
+{
+ m_options.add_entries(cli_option_entries);
+}
+
+
+//-------------------------------------------------
+// ~cli_frontend - destructor
+//-------------------------------------------------
+
+cli_frontend::~cli_frontend()
+{
+ // nuke any device options since they will leak memory
+ mame_options::remove_device_options(m_options);
+}
+
+//-------------------------------------------------
+// execute - execute a game via the standard
+// command line interface
+//-------------------------------------------------
+
+int cli_frontend::execute(int argc, char **argv)
+{
+ // wrap the core execution in a try/catch to field all fatal errors
+ m_result = EMU_ERR_NONE;
+ mame_machine_manager *manager = mame_machine_manager::instance(m_options, m_osd);
+
+ try
+ {
+ // first parse options to be able to get software from it
+ std::string option_errors;
+ mame_options::parse_command_line(m_options,argc, argv, option_errors);
+
+ mame_options::parse_standard_inis(m_options,option_errors);
+
+ load_translation(m_options);
+
+ manager->start_luaengine();
+
+ if (*(m_options.software_name()) != 0)
+ {
+ const game_driver *system = m_options.system();
+ if (system == nullptr && *(m_options.system_name()) != 0)
+ throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "Unknown system '%s'", m_options.system_name());
+
+ machine_config config(*system, m_options);
+ software_list_device_iterator iter(config.root_device());
+ if (iter.count() == 0)
+ throw emu_fatalerror(EMU_ERR_FATALERROR, "Error: unknown option: %s\n", m_options.software_name());
+
+ bool found = false;
+ for (software_list_device &swlistdev : iter)
+ {
+ software_info *swinfo = swlistdev.find(m_options.software_name());
+ if (swinfo != nullptr)
+ {
+ // loop through all parts
+ for (software_part &swpart : swinfo->parts())
+ {
+ const char *mount = swpart.feature("automount");
+ if (swpart.is_compatible(swlistdev))
+ {
+ if (mount == nullptr || strcmp(mount,"no") != 0)
+ {
+ // search for an image device with the right interface
+ for (device_image_interface &image : image_interface_iterator(config.root_device()))
+ {
+ const char *interface = image.image_interface();
+ if (interface != nullptr)
+ {
+ if (swpart.matches_interface(interface))
+ {
+ const char *option = m_options.value(image.brief_instance_name());
+
+ // mount only if not already mounted
+ if (*option == 0)
+ {
+ std::string val = string_format("%s:%s:%s", swlistdev.list_name(), m_options.software_name(), swpart.name());
+
+ // call this in order to set slot devices according to mounting
+ mame_options::parse_slot_devices(m_options, argc, argv, option_errors, image.instance_name(), val.c_str(), &swpart);
+ break;
+ }
+ }
+ }
+ }
+ }
+ found = true;
+ }
+ }
+ }
+
+ if (found)
+ break;
+ }
+ if (!found)
+ {
+ software_list_device::display_matches(config, nullptr, m_options.software_name());
+ throw emu_fatalerror(EMU_ERR_FATALERROR, nullptr);
+ }
+ }
+
+ // parse the command line, adding any system-specific options
+ if (!mame_options::parse_command_line(m_options,argc, argv, option_errors))
+ {
+ // if we failed, check for no command and a system name first; in that case error on the name
+ if (*(m_options.command()) == 0 && m_options.system() == nullptr && *(m_options.system_name()) != 0)
+ throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "Unknown system '%s'", m_options.system_name());
+
+ // otherwise, error on the options
+ throw emu_fatalerror(EMU_ERR_INVALID_CONFIG, "%s", strtrimspace(option_errors).c_str());
+ }
+ if (!option_errors.empty())
+ osd_printf_error("Error in command line:\n%s\n", strtrimspace(option_errors).c_str());
+
+ // determine the base name of the EXE
+ std::string exename = core_filename_extract_base(argv[0], true);
+
+ // if we have a command, execute that
+ if (*(m_options.command()) != 0)
+ execute_commands(exename.c_str());
+
+ // otherwise, check for a valid system
+ else
+ {
+ // We need to preprocess the config files once to determine the web server's configuration
+ // and file locations
+ if (m_options.read_config())
+ {
+ m_options.revert(OPTION_PRIORITY_INI);
+ mame_options::parse_standard_inis(m_options,option_errors);
+ }
+ if (!option_errors.empty())
+ osd_printf_error("Error in command line:\n%s\n", strtrimspace(option_errors).c_str());
+
+ // if we can't find it, give an appropriate error
+ const game_driver *system = m_options.system();
+ if (system == nullptr && *(m_options.system_name()) != 0)
+ throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "Unknown system '%s'", m_options.system_name());
+
+ // otherwise just run the game
+ m_result = manager->execute();
+ }
+ }
+
+ // handle exceptions of various types
+ catch (emu_fatalerror &fatal)
+ {
+ std::string str(fatal.string());
+ strtrimspace(str);
+ osd_printf_error("%s\n", str.c_str());
+ m_result = (fatal.exitcode() != 0) ? fatal.exitcode() : EMU_ERR_FATALERROR;
+
+ // if a game was specified, wasn't a wildcard, and our error indicates this was the
+ // reason for failure, offer some suggestions
+ if (m_result == EMU_ERR_NO_SUCH_GAME && *(m_options.system_name()) != 0 && strchr(m_options.system_name(), '*') == nullptr && m_options.system() == nullptr)
+ {
+ // get the top 16 approximate matches
+ driver_enumerator drivlist(m_options);
+ int matches[16];
+ drivlist.find_approximate_matches(m_options.system_name(), ARRAY_LENGTH(matches), matches);
+
+ // print them out
+ osd_printf_error("\n\"%s\" approximately matches the following\n"
+ "supported machines (best match first):\n\n", m_options.system_name());
+ for (auto & matche : matches)
+ if (matche != -1)
+ osd_printf_error("%-18s%s\n", drivlist.driver(matche).name, drivlist.driver(matche).description);
+ }
+ }
+ catch (emu_exception &)
+ {
+ osd_printf_error("Caught unhandled emulator exception\n");
+ m_result = EMU_ERR_FATALERROR;
+ }
+ catch (add_exception &aex)
+ {
+ osd_printf_error("Tag '%s' already exists in tagged_list\n", aex.tag());
+ m_result = EMU_ERR_FATALERROR;
+ }
+ catch (std::exception &ex)
+ {
+ osd_printf_error("Caught unhandled %s exception: %s\n", typeid(ex).name(), ex.what());
+ m_result = EMU_ERR_FATALERROR;
+ }
+ catch (...)
+ {
+ osd_printf_error("Caught unhandled exception\n");
+ m_result = EMU_ERR_FATALERROR;
+ }
+
+ util::archive_file::cache_clear();
+ global_free(manager);
+
+ return m_result;
+}
+
+
+//-------------------------------------------------
+// listxml - output the XML data for one or more
+// games
+//-------------------------------------------------
+
+void cli_frontend::listxml(const char *gamename)
+{
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // create the XML and print it to stdout
+ info_xml_creator creator(drivlist);
+ creator.output(stdout);
+}
+
+
+//-------------------------------------------------
+// listfull - output the name and description of
+// one or more games
+//-------------------------------------------------
+
+void cli_frontend::listfull(const char *gamename)
+{
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // print the header
+ osd_printf_info("Name: Description:\n");
+
+ // iterate through drivers and output the info
+ while (drivlist.next())
+ if ((drivlist.driver().flags & MACHINE_NO_STANDALONE) == 0)
+ osd_printf_info("%-18s\"%s\"\n", drivlist.driver().name, drivlist.driver().description);
+}
+
+
+//-------------------------------------------------
+// listsource - output the name and source
+// filename of one or more games
+//-------------------------------------------------
+
+void cli_frontend::listsource(const char *gamename)
+{
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // iterate through drivers and output the info
+ while (drivlist.next())
+ osd_printf_info("%-16s %s\n", drivlist.driver().name, core_filename_extract_base(drivlist.driver().source_file).c_str());
+}
+
+
+//-------------------------------------------------
+// listclones - output the name and parent of all
+// clones matching the given pattern
+//-------------------------------------------------
+
+void cli_frontend::listclones(const char *gamename)
+{
+ // start with a filtered list of drivers
+ driver_enumerator drivlist(m_options, gamename);
+ int original_count = drivlist.count();
+
+ // iterate through the remaining ones to see if their parent matches
+ while (drivlist.next_excluded())
+ {
+ // if we have a non-bios clone and it matches, keep it
+ int clone_of = drivlist.clone();
+ if (clone_of != -1 && (drivlist.driver(clone_of).flags & MACHINE_IS_BIOS_ROOT) == 0)
+ if (drivlist.matches(gamename, drivlist.driver(clone_of).name))
+ drivlist.include();
+ }
+
+ // return an error if none found
+ if (drivlist.count() == 0)
+ {
+ // see if we match but just weren't a clone
+ if (original_count == 0)
+ throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+ else
+ osd_printf_info("Found %d matches for '%s' but none were clones\n", drivlist.count(), gamename);
+ return;
+ }
+
+ // print the header
+ osd_printf_info("Name: Clone of:\n");
+
+ // iterate through drivers and output the info
+ drivlist.reset();
+ while (drivlist.next())
+ {
+ int clone_of = drivlist.clone();
+ if (clone_of != -1 && (drivlist.driver(clone_of).flags & MACHINE_IS_BIOS_ROOT) == 0)
+ osd_printf_info("%-16s %-8s\n", drivlist.driver().name, drivlist.driver(clone_of).name);
+ }
+}
+
+
+//-------------------------------------------------
+// listbrothers - for each matching game, output
+// the list of other games that share the same
+// source file
+//-------------------------------------------------
+
+void cli_frontend::listbrothers(const char *gamename)
+{
+ // start with a filtered list of drivers; return an error if none found
+ driver_enumerator initial_drivlist(m_options, gamename);
+ if (initial_drivlist.count() == 0)
+ throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // for the final list, start with an empty driver list
+ driver_enumerator drivlist(m_options);
+ drivlist.exclude_all();
+
+ // scan through the initially-selected drivers
+ while (initial_drivlist.next())
+ {
+ // if we are already marked in the final list, we don't need to do anything
+ if (drivlist.included(initial_drivlist.current()))
+ continue;
+
+ // otherwise, walk excluded items in the final list and mark any that match
+ drivlist.reset();
+ while (drivlist.next_excluded())
+ if (strcmp(drivlist.driver().source_file, initial_drivlist.driver().source_file) == 0)
+ drivlist.include();
+ }
+
+ // print the header
+ osd_printf_info("Source file: Name: Parent:\n");
+
+ // output the entries found
+ drivlist.reset();
+ while (drivlist.next())
+ {
+ int clone_of = drivlist.clone();
+ osd_printf_info("%-16s %-16s %-16s\n", core_filename_extract_base(drivlist.driver().source_file).c_str(), drivlist.driver().name, (clone_of == -1 ? "" : drivlist.driver(clone_of).name));
+ }
+}
+
+
+//-------------------------------------------------
+// listcrc - output the CRC and name of all ROMs
+// referenced by the emulator
+//-------------------------------------------------
+
+void cli_frontend::listcrc(const char *gamename)
+{
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // iterate through matches, and then through ROMs
+ while (drivlist.next())
+ {
+ for (device_t &device : device_iterator(drivlist.config().root_device()))
+ for (const rom_entry *region = rom_first_region(device); region; region = rom_next_region(region))
+ for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom))
+ {
+ // if we have a CRC, display it
+ UINT32 crc;
+ if (hash_collection(ROM_GETHASHDATA(rom)).crc(crc))
+ osd_printf_info("%08x %-16s \t %-8s \t %s\n", crc, ROM_GETNAME(rom), device.shortname(), device.name());
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// listroms - output the list of ROMs referenced
+// by a given game or set of games
+//-------------------------------------------------
+
+void cli_frontend::listroms(const char *gamename)
+{
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // iterate through matches
+ bool first = true;
+ while (drivlist.next())
+ {
+ // print a header
+ if (!first)
+ osd_printf_info("\n");
+ first = false;
+ osd_printf_info("ROMs required for driver \"%s\".\n"
+ "Name Size Checksum\n", drivlist.driver().name);
+
+ // iterate through roms
+ for (device_t &device : device_iterator(drivlist.config().root_device()))
+ for (const rom_entry *region = rom_first_region(device); region; region = rom_next_region(region))
+ for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom))
+ {
+ // accumulate the total length of all chunks
+ int length = -1;
+ if (ROMREGION_ISROMDATA(region))
+ length = rom_file_size(rom);
+
+ // start with the name
+ const char *name = ROM_GETNAME(rom);
+ osd_printf_info("%-20s ", name);
+
+ // output the length next
+ if (length >= 0)
+ osd_printf_info("%7d", length);
+ else
+ osd_printf_info(" ");
+
+ // output the hash data
+ hash_collection hashes(ROM_GETHASHDATA(rom));
+ if (!hashes.flag(hash_collection::FLAG_NO_DUMP))
+ {
+ if (hashes.flag(hash_collection::FLAG_BAD_DUMP))
+ osd_printf_info(" BAD");
+ osd_printf_info(" %s", hashes.macro_string().c_str());
+ }
+ else
+ osd_printf_info(" NO GOOD DUMP KNOWN");
+
+ // end with a CR
+ osd_printf_info("\n");
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// listsamples - output the list of samples
+// referenced by a given game or set of games
+//-------------------------------------------------
+
+void cli_frontend::listsamples(const char *gamename)
+{
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // iterate over drivers, looking for SAMPLES devices
+ bool first = true;
+ while (drivlist.next())
+ {
+ // see if we have samples
+ samples_device_iterator iter(drivlist.config().root_device());
+ if (iter.count() == 0)
+ continue;
+
+ // print a header
+ if (!first)
+ osd_printf_info("\n");
+ first = false;
+ osd_printf_info("Samples required for driver \"%s\".\n", drivlist.driver().name);
+
+ // iterate over samples devices and print the samples from each one
+ for (samples_device &device : iter)
+ {
+ samples_iterator sampiter(device);
+ for (const char *samplename = sampiter.first(); samplename != nullptr; samplename = sampiter.next())
+ osd_printf_info("%s\n", samplename);
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// listdevices - output the list of devices
+// referenced by a given game or set of games
+//-------------------------------------------------
+
+int cli_frontend::compare_devices(const void *i1, const void *i2)
+{
+ device_t *dev1 = *(device_t **)i1;
+ device_t *dev2 = *(device_t **)i2;
+ return strcmp(dev1->tag(), dev2->tag());
+}
+
+void cli_frontend::listdevices(const char *gamename)
+{
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // iterate over drivers, looking for SAMPLES devices
+ bool first = true;
+ while (drivlist.next())
+ {
+ // print a header
+ if (!first)
+ printf("\n");
+ first = false;
+ printf("Driver %s (%s):\n", drivlist.driver().name, drivlist.driver().description);
+
+ // build a list of devices
+ std::vector<device_t *> device_list;
+ for (device_t &device : device_iterator(drivlist.config().root_device()))
+ device_list.push_back(&device);
+
+ // sort them by tag
+ qsort(&device_list[0], device_list.size(), sizeof(device_list[0]), compare_devices);
+
+ // dump the results
+ for (auto device : device_list)
+ {
+ // extract the tag, stripping the leading colon
+ const char *tag = device->tag();
+ if (*tag == ':')
+ tag++;
+
+ // determine the depth
+ int depth = 1;
+ if (*tag == 0)
+ {
+ tag = "<root>";
+ depth = 0;
+ }
+ else
+ {
+ for (const char *c = tag; *c != 0; c++)
+ if (*c == ':')
+ {
+ tag = c + 1;
+ depth++;
+ }
+ }
+ printf(" %*s%-*s %s", depth * 2, "", 30 - depth * 2, tag, device->name());
+
+ // add more information
+ UINT32 clock = device->clock();
+ if (clock >= 1000000000)
+ printf(" @ %d.%02d GHz\n", clock / 1000000000, (clock / 10000000) % 100);
+ else if (clock >= 1000000)
+ printf(" @ %d.%02d MHz\n", clock / 1000000, (clock / 10000) % 100);
+ else if (clock >= 1000)
+ printf(" @ %d.%02d kHz\n", clock / 1000, (clock / 10) % 100);
+ else if (clock > 0)
+ printf(" @ %d Hz\n", clock);
+ else
+ printf("\n");
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// listslots - output the list of slot devices
+// referenced by a given game or set of games
+//-------------------------------------------------
+
+void cli_frontend::listslots(const char *gamename)
+{
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // print header
+ printf(" SYSTEM SLOT NAME SLOT OPTIONS SLOT DEVICE NAME \n");
+ printf("---------- ----------- -------------- ----------------------\n");
+
+ // iterate over drivers
+ while (drivlist.next())
+ {
+ // iterate
+ bool first = true;
+ for (const device_slot_interface &slot : slot_interface_iterator(drivlist.config().root_device()))
+ {
+ if (slot.fixed()) continue;
+ // output the line, up to the list of extensions
+ printf("%-13s%-10s ", first ? drivlist.driver().name : "", slot.device().tag()+1);
+
+ bool first_option = true;
+
+ // get the options and print them
+ for (const device_slot_option &option : slot.option_list())
+ {
+ if (option.selectable())
+ {
+ device_t *dev = (*option.devtype())(drivlist.config(), "dummy", &drivlist.config().root_device(), 0);
+ dev->config_complete();
+ if (first_option) {
+ printf("%-15s %s\n", option.name(),dev->name());
+ } else {
+ printf("%-23s %-15s %s\n", "",option.name(),dev->name());
+ }
+ global_free(dev);
+
+ first_option = false;
+ }
+ }
+ if (first_option)
+ printf("%-15s %s\n", "[none]","No options available");
+ // end the line
+ printf("\n");
+ first = false;
+ }
+
+ // if we didn't get any at all, just print a none line
+ if (first)
+ printf("%-13s(none)\n", drivlist.driver().name);
+ }
+}
+
+
+//-------------------------------------------------
+// listmedia - output the list of image devices
+// referenced by a given game or set of games
+//-------------------------------------------------
+
+void cli_frontend::listmedia(const char *gamename)
+{
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // print header
+ printf(" SYSTEM MEDIA NAME (brief) IMAGE FILE EXTENSIONS SUPPORTED \n");
+ printf("---------- -------------------- ------------------------------------\n");
+
+ // iterate over drivers
+ while (drivlist.next())
+ {
+ // iterate
+ bool first = true;
+ for (const device_image_interface &imagedev : image_interface_iterator(drivlist.config().root_device()))
+ {
+ if (!imagedev.user_loadable())
+ continue;
+
+ // extract the shortname with parentheses
+ std::string paren_shortname = string_format("(%s)", imagedev.brief_instance_name());
+
+ // output the line, up to the list of extensions
+ printf("%-13s%-12s%-8s ", first ? drivlist.driver().name : "", imagedev.instance_name(), paren_shortname.c_str());
+
+ // get the extensions and print them
+ std::string extensions(imagedev.file_extensions());
+ for (int start = 0, end = extensions.find_first_of(',');; start = end + 1, end = extensions.find_first_of(',', start))
+ {
+ std::string curext(extensions, start, (end == -1) ? extensions.length() - start : end - start);
+ printf(".%-5s", curext.c_str());
+ if (end == -1)
+ break;
+ }
+
+ // end the line
+ printf("\n");
+ first = false;
+ }
+
+ // if we didn't get any at all, just print a none line
+ if (first)
+ printf("%-13s(none)\n", drivlist.driver().name);
+ }
+}
+
+//-------------------------------------------------
+// verifyroms - verify the ROM sets of one or
+// more games
+//-------------------------------------------------
+void cli_frontend::verifyroms(const char *gamename)
+{
+ // determine which drivers to output;
+ driver_enumerator drivlist(m_options, gamename);
+
+ int correct = 0;
+ int incorrect = 0;
+ int notfound = 0;
+ int matched = 0;
+
+ // iterate over drivers
+ media_auditor auditor(drivlist);
+ while (drivlist.next())
+ {
+ matched++;
+
+ // audit the ROMs in this set
+ media_auditor::summary summary = auditor.audit_media(AUDIT_VALIDATE_FAST);
+
+ // if not found, count that and leave it at that
+ if (summary == media_auditor::NOTFOUND)
+ notfound++;
+
+ // else display information about what we discovered
+ else
+ {
+ // output the summary of the audit
+ std::string summary_string;
+ auditor.summarize(drivlist.driver().name,&summary_string);
+ osd_printf_info("%s", summary_string.c_str());
+
+ // output the name of the driver and its clone
+ osd_printf_info("romset %s ", drivlist.driver().name);
+ int clone_of = drivlist.clone();
+ if (clone_of != -1)
+ osd_printf_info("[%s] ", drivlist.driver(clone_of).name);
+
+ // switch off of the result
+ switch (summary)
+ {
+ case media_auditor::INCORRECT:
+ osd_printf_info("is bad\n");
+ incorrect++;
+ break;
+
+ case media_auditor::CORRECT:
+ osd_printf_info("is good\n");
+ correct++;
+ break;
+
+ case media_auditor::BEST_AVAILABLE:
+ case media_auditor::NONE_NEEDED:
+ osd_printf_info("is best available\n");
+ correct++;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ if (!matched || strchr(gamename, '*') || strchr(gamename, '?'))
+ {
+ driver_enumerator dummy_drivlist(m_options);
+ std::unordered_set<std::string> device_map;
+ while (dummy_drivlist.next())
+ {
+ machine_config &config = dummy_drivlist.config();
+ for (device_t &dev : device_iterator(config.root_device()))
+ {
+ if (dev.owner() != nullptr && (*(dev.shortname()) != 0) && dev.rom_region() != nullptr && (device_map.insert(dev.shortname()).second)) {
+ if (core_strwildcmp(gamename, dev.shortname()) == 0)
+ {
+ matched++;
+
+ // audit the ROMs in this set
+ media_auditor::summary summary = auditor.audit_device(dev, AUDIT_VALIDATE_FAST);
+
+ // if not found, count that and leave it at that
+ if (summary == media_auditor::NOTFOUND)
+ notfound++;
+ // else display information about what we discovered
+ else if (summary != media_auditor::NONE_NEEDED)
+ {
+ // output the summary of the audit
+ std::string summary_string;
+ auditor.summarize(dev.shortname(),&summary_string);
+ osd_printf_info("%s", summary_string.c_str());
+
+ // display information about what we discovered
+ osd_printf_info("romset %s ", dev.shortname());
+
+ // switch off of the result
+ switch (summary)
+ {
+ case media_auditor::INCORRECT:
+ osd_printf_info("is bad\n");
+ incorrect++;
+ break;
+
+ case media_auditor::CORRECT:
+ osd_printf_info("is good\n");
+ correct++;
+ break;
+
+ case media_auditor::BEST_AVAILABLE:
+ osd_printf_info("is best available\n");
+ correct++;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ for (const device_slot_interface &slot : slot_interface_iterator(config.root_device()))
+ {
+ for (const device_slot_option &option : slot.option_list())
+ {
+ std::string temptag("_");
+ temptag.append(option.name());
+ device_t *dev = const_cast<machine_config &>(config).device_add(&config.root_device(), temptag.c_str(), option.devtype(), 0);
+
+ // notify this device and all its subdevices that they are now configured
+ for (device_t &device : device_iterator(*dev))
+ if (!device.configured())
+ device.config_complete();
+
+ if (device_map.insert(dev->shortname()).second) {
+ if (core_strwildcmp(gamename, dev->shortname()) == 0)
+ {
+ matched++;
+ if (dev->rom_region() != nullptr)
+ {
+ // audit the ROMs in this set
+ media_auditor::summary summary = auditor.audit_device(*dev, AUDIT_VALIDATE_FAST);
+
+ // if not found, count that and leave it at that
+ if (summary == media_auditor::NOTFOUND)
+ notfound++;
+
+ // else display information about what we discovered
+ else if(summary != media_auditor::NONE_NEEDED)
+ {
+ // output the summary of the audit
+ std::string summary_string;
+ auditor.summarize(dev->shortname(),&summary_string);
+ osd_printf_info("%s", summary_string.c_str());
+
+ // display information about what we discovered
+ osd_printf_info("romset %s ", dev->shortname());
+
+ // switch off of the result
+ switch (summary)
+ {
+ case media_auditor::INCORRECT:
+ osd_printf_info("is bad\n");
+ incorrect++;
+ break;
+
+ case media_auditor::CORRECT:
+ osd_printf_info("is good\n");
+ correct++;
+ break;
+
+ case media_auditor::BEST_AVAILABLE:
+ osd_printf_info("is best available\n");
+ correct++;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+ } else {
+ // check for subdevices with ROMs (a few devices are missed otherwise, e.g. MPU401)
+ for (device_t &device : device_iterator(*dev))
+ {
+ for (device_t &subdev : device_iterator(device))
+ {
+ if (subdev.owner() == &device && subdev.rom_region() != nullptr && subdev.shortname() != nullptr && subdev.shortname()[0] != '\0')
+ {
+ if (device_map.insert(subdev.shortname()).second)
+ {
+ if (core_strwildcmp(gamename, subdev.shortname()) == 0)
+ {
+ matched++;
+
+ // audit the ROMs in this set
+ media_auditor::summary summary = auditor.audit_device(subdev, AUDIT_VALIDATE_FAST);
+
+ // if not found, count that and leave it at that
+ if (summary == media_auditor::NOTFOUND)
+ notfound++;
+
+ // else display information about what we discovered
+ else if (summary != media_auditor::NONE_NEEDED)
+ {
+ // output the summary of the audit
+ std::string summary_string;
+ auditor.summarize(subdev.shortname(),&summary_string);
+ osd_printf_info("%s", summary_string.c_str());
+
+ // display information about what we discovered
+ osd_printf_info("romset %s ", subdev.shortname());
+
+ // switch off of the result
+ switch (summary)
+ {
+ case media_auditor::INCORRECT:
+ osd_printf_info("is bad\n");
+ incorrect++;
+ break;
+
+ case media_auditor::CORRECT:
+ osd_printf_info("is good\n");
+ correct++;
+ break;
+
+ case media_auditor::BEST_AVAILABLE:
+ osd_printf_info("is best available\n");
+ correct++;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ const_cast<machine_config &>(config).device_remove(&config.root_device(), temptag.c_str());
+ }
+ }
+ }
+ }
+
+ // clear out any cached files
+ util::archive_file::cache_clear();
+
+ // return an error if none found
+ if (matched == 0)
+ throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // if we didn't get anything at all, display a generic end message
+ if (matched > 0 && correct == 0 && incorrect == 0)
+ {
+ if (notfound > 0)
+ throw emu_fatalerror(EMU_ERR_MISSING_FILES, "romset \"%s\" not found!\n", gamename);
+ else
+ throw emu_fatalerror(EMU_ERR_MISSING_FILES, "romset \"%s\" has no roms!\n", gamename);
+ }
+
+ // otherwise, print a summary
+ else
+ {
+ if (incorrect > 0)
+ throw emu_fatalerror(EMU_ERR_MISSING_FILES, "%d romsets found, %d were OK.\n", correct + incorrect, correct);
+ osd_printf_info("%d romsets found, %d were OK.\n", correct, correct);
+ }
+}
+
+
+//-------------------------------------------------
+// info_verifysamples - verify the sample sets of
+// one or more games
+//-------------------------------------------------
+
+void cli_frontend::verifysamples(const char *gamename)
+{
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+
+ int correct = 0;
+ int incorrect = 0;
+ int notfound = 0;
+ int matched = 0;
+
+ // iterate over drivers
+ media_auditor auditor(drivlist);
+ while (drivlist.next())
+ {
+ matched++;
+
+ // audit the samples in this set
+ media_auditor::summary summary = auditor.audit_samples();
+
+ // if not found, count that and leave it at that
+ if (summary == media_auditor::NOTFOUND)
+ notfound++;
+
+ // else display information about what we discovered
+ else if (summary != media_auditor::NONE_NEEDED)
+ {
+ // output the summary of the audit
+ std::string summary_string;
+ auditor.summarize(drivlist.driver().name,&summary_string);
+ osd_printf_info("%s", summary_string.c_str());
+
+ // output the name of the driver and its clone
+ osd_printf_info("sampleset %s ", drivlist.driver().name);
+ int clone_of = drivlist.clone();
+ if (clone_of != -1)
+ osd_printf_info("[%s] ", drivlist.driver(clone_of).name);
+
+ // switch off of the result
+ switch (summary)
+ {
+ case media_auditor::INCORRECT:
+ osd_printf_info("is bad\n");
+ incorrect++;
+ break;
+
+ case media_auditor::CORRECT:
+ osd_printf_info("is good\n");
+ correct++;
+ break;
+
+ case media_auditor::BEST_AVAILABLE:
+ osd_printf_info("is best available\n");
+ correct++;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ // clear out any cached files
+ util::archive_file::cache_clear();
+
+ // return an error if none found
+ if (matched == 0)
+ throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // if we didn't get anything at all, display a generic end message
+ if (matched > 0 && correct == 0 && incorrect == 0)
+ {
+ if (notfound > 0)
+ throw emu_fatalerror(EMU_ERR_MISSING_FILES, "sampleset \"%s\" not found!\n", gamename);
+ else
+ throw emu_fatalerror(EMU_ERR_MISSING_FILES, "sampleset \"%s\" not required!\n", gamename);
+ }
+
+ // otherwise, print a summary
+ else
+ {
+ if (incorrect > 0)
+ throw emu_fatalerror(EMU_ERR_MISSING_FILES, "%d samplesets found, %d were OK.\n", correct + incorrect, correct);
+ osd_printf_info("%d samplesets found, %d were OK.\n", correct, correct);
+ }
+}
+#define SOFTLIST_XML_BEGIN "<?xml version=\"1.0\"?>\n" \
+ "<!DOCTYPE softwarelists [\n" \
+ "<!ELEMENT softwarelists (softwarelist*)>\n" \
+ "\t<!ELEMENT softwarelist (software+)>\n" \
+ "\t\t<!ATTLIST softwarelist name CDATA #REQUIRED>\n" \
+ "\t\t<!ATTLIST softwarelist description CDATA #IMPLIED>\n" \
+ "\t\t<!ELEMENT software (description, year, publisher, info*, sharedfeat*, part*)>\n" \
+ "\t\t\t<!ATTLIST software name CDATA #REQUIRED>\n" \
+ "\t\t\t<!ATTLIST software cloneof CDATA #IMPLIED>\n" \
+ "\t\t\t<!ATTLIST software supported (yes|partial|no) \"yes\">\n" \
+ "\t\t\t<!ELEMENT description (#PCDATA)>\n" \
+ "\t\t\t<!ELEMENT year (#PCDATA)>\n" \
+ "\t\t\t<!ELEMENT publisher (#PCDATA)>\n" \
+ "\t\t\t<!ELEMENT info EMPTY>\n" \
+ "\t\t\t\t<!ATTLIST info name CDATA #REQUIRED>\n" \
+ "\t\t\t\t<!ATTLIST info value CDATA #IMPLIED>\n" \
+ "\t\t\t<!ELEMENT sharedfeat EMPTY>\n" \
+ "\t\t\t\t<!ATTLIST sharedfeat name CDATA #REQUIRED>\n" \
+ "\t\t\t\t<!ATTLIST sharedfeat value CDATA #IMPLIED>\n" \
+ "\t\t\t<!ELEMENT part (feature*, dataarea*, diskarea*, dipswitch*)>\n" \
+ "\t\t\t\t<!ATTLIST part name CDATA #REQUIRED>\n" \
+ "\t\t\t\t<!ATTLIST part interface CDATA #REQUIRED>\n" \
+ "\t\t\t\t<!ELEMENT feature EMPTY>\n" \
+ "\t\t\t\t\t<!ATTLIST feature name CDATA #REQUIRED>\n" \
+ "\t\t\t\t\t<!ATTLIST feature value CDATA #IMPLIED>\n" \
+ "\t\t\t\t<!ELEMENT dataarea (rom*)>\n" \
+ "\t\t\t\t\t<!ATTLIST dataarea name CDATA #REQUIRED>\n" \
+ "\t\t\t\t\t<!ATTLIST dataarea size CDATA #REQUIRED>\n" \
+ "\t\t\t\t\t<!ATTLIST dataarea databits (8|16|32|64) \"8\">\n" \
+ "\t\t\t\t\t<!ATTLIST dataarea endian (big|little) \"little\">\n" \
+ "\t\t\t\t\t<!ELEMENT rom EMPTY>\n" \
+ "\t\t\t\t\t\t<!ATTLIST rom name CDATA #IMPLIED>\n" \
+ "\t\t\t\t\t\t<!ATTLIST rom size CDATA #IMPLIED>\n" \
+ "\t\t\t\t\t\t<!ATTLIST rom length CDATA #IMPLIED>\n" \
+ "\t\t\t\t\t\t<!ATTLIST rom crc CDATA #IMPLIED>\n" \
+ "\t\t\t\t\t\t<!ATTLIST rom sha1 CDATA #IMPLIED>\n" \
+ "\t\t\t\t\t\t<!ATTLIST rom offset CDATA #IMPLIED>\n" \
+ "\t\t\t\t\t\t<!ATTLIST rom value CDATA #IMPLIED>\n" \
+ "\t\t\t\t\t\t<!ATTLIST rom status (baddump|nodump|good) \"good\">\n" \
+ "\t\t\t\t\t\t<!ATTLIST rom loadflag (load16_byte|load16_word|load16_word_swap|load32_byte|load32_word|load32_word_swap|load32_dword|load64_word|load64_word_swap|reload|fill|continue|reload_plain) #IMPLIED>\n" \
+ "\t\t\t\t<!ELEMENT diskarea (disk*)>\n" \
+ "\t\t\t\t\t<!ATTLIST diskarea name CDATA #REQUIRED>\n" \
+ "\t\t\t\t\t<!ELEMENT disk EMPTY>\n" \
+ "\t\t\t\t\t\t<!ATTLIST disk name CDATA #REQUIRED>\n" \
+ "\t\t\t\t\t\t<!ATTLIST disk sha1 CDATA #IMPLIED>\n" \
+ "\t\t\t\t\t\t<!ATTLIST disk status (baddump|nodump|good) \"good\">\n" \
+ "\t\t\t\t\t\t<!ATTLIST disk writeable (yes|no) \"no\">\n" \
+ "\t\t\t\t<!ELEMENT dipswitch (dipvalue*)>\n" \
+ "\t\t\t\t\t<!ATTLIST dipswitch name CDATA #REQUIRED>\n" \
+ "\t\t\t\t\t<!ATTLIST dipswitch tag CDATA #REQUIRED>\n" \
+ "\t\t\t\t\t<!ATTLIST dipswitch mask CDATA #REQUIRED>\n" \
+ "\t\t\t\t\t<!ELEMENT dipvalue EMPTY>\n" \
+ "\t\t\t\t\t\t<!ATTLIST dipvalue name CDATA #REQUIRED>\n" \
+ "\t\t\t\t\t\t<!ATTLIST dipvalue value CDATA #REQUIRED>\n" \
+ "\t\t\t\t\t\t<!ATTLIST dipvalue default (yes|no) \"no\">\n" \
+ "]>\n\n" \
+ "<softwarelists>\n"
+
+void cli_frontend::output_single_softlist(FILE *out, software_list_device &swlistdev)
+{
+ fprintf(out, "\t<softwarelist name=\"%s\" description=\"%s\">\n", swlistdev.list_name(), xml_normalize_string(swlistdev.description()));
+ for (software_info &swinfo : swlistdev.get_info())
+ {
+ fprintf(out, "\t\t<software name=\"%s\"", swinfo.shortname());
+ if (swinfo.parentname() != nullptr)
+ fprintf(out, " cloneof=\"%s\"", swinfo.parentname());
+ if (swinfo.supported() == SOFTWARE_SUPPORTED_PARTIAL)
+ fprintf(out, " supported=\"partial\"");
+ if (swinfo.supported() == SOFTWARE_SUPPORTED_NO)
+ fprintf(out, " supported=\"no\"");
+ fprintf(out, ">\n" );
+ fprintf(out, "\t\t\t<description>%s</description>\n", xml_normalize_string(swinfo.longname()));
+ fprintf(out, "\t\t\t<year>%s</year>\n", xml_normalize_string(swinfo.year()));
+ fprintf(out, "\t\t\t<publisher>%s</publisher>\n", xml_normalize_string(swinfo.publisher()));
+
+ for (feature_list_item &flist : swinfo.other_info())
+ fprintf( out, "\t\t\t<info name=\"%s\" value=\"%s\"/>\n", flist.name(), xml_normalize_string( flist.value() ) );
+
+ for (software_part &part : swinfo.parts())
+ {
+ fprintf(out, "\t\t\t<part name=\"%s\"", part.name());
+ if (part.interface() != nullptr)
+ fprintf(out, " interface=\"%s\"", part.interface());
+
+ fprintf(out, ">\n");
+
+ for (feature_list_item &flist : part.featurelist())
+ fprintf(out, "\t\t\t\t<feature name=\"%s\" value=\"%s\" />\n", flist.name(), xml_normalize_string(flist.value()));
+
+ /* TODO: display rom region information */
+ for (const rom_entry *region = part.romdata(); region; region = rom_next_region(region))
+ {
+ int is_disk = ROMREGION_ISDISKDATA(region);
+
+ if (!is_disk)
+ fprintf( out, "\t\t\t\t<dataarea name=\"%s\" size=\"%d\">\n", ROMREGION_GETTAG(region), ROMREGION_GETLENGTH(region) );
+ else
+ fprintf( out, "\t\t\t\t<diskarea name=\"%s\">\n", ROMREGION_GETTAG(region) );
+
+ for ( const rom_entry *rom = rom_first_file( region ); rom && !ROMENTRY_ISREGIONEND(rom); rom++ )
+ {
+ if ( ROMENTRY_ISFILE(rom) )
+ {
+ if (!is_disk)
+ fprintf( out, "\t\t\t\t\t<rom name=\"%s\" size=\"%d\"", xml_normalize_string(ROM_GETNAME(rom)), rom_file_size(rom) );
+ else
+ fprintf( out, "\t\t\t\t\t<disk name=\"%s\"", xml_normalize_string(ROM_GETNAME(rom)) );
+
+ /* dump checksum information only if there is a known dump */
+ hash_collection hashes(ROM_GETHASHDATA(rom));
+ if ( !hashes.flag(hash_collection::FLAG_NO_DUMP) )
+ fprintf( out, " %s", hashes.attribute_string().c_str() );
+ else
+ fprintf( out, " status=\"nodump\"" );
+
+ if (is_disk)
+ fprintf( out, " writeable=\"%s\"", (ROM_GETFLAGS(rom) & DISK_READONLYMASK) ? "no" : "yes");
+
+ if ((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_SKIP(1))
+ fprintf( out, " loadflag=\"load16_byte\"" );
+
+ if ((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_SKIP(3))
+ fprintf( out, " loadflag=\"load32_byte\"" );
+
+ if (((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_SKIP(2)) && ((ROM_GETFLAGS(rom) & ROM_GROUPMASK) == ROM_GROUPWORD))
+ {
+ if (!(ROM_GETFLAGS(rom) & ROM_REVERSEMASK))
+ fprintf( out, " loadflag=\"load32_word\"" );
+ else
+ fprintf( out, " loadflag=\"load32_word_swap\"" );
+ }
+
+ if (((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_SKIP(6)) && ((ROM_GETFLAGS(rom) & ROM_GROUPMASK) == ROM_GROUPWORD))
+ {
+ if (!(ROM_GETFLAGS(rom) & ROM_REVERSEMASK))
+ fprintf( out, " loadflag=\"load64_word\"" );
+ else
+ fprintf( out, " loadflag=\"load64_word_swap\"" );
+ }
+
+ if (((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_NOSKIP) && ((ROM_GETFLAGS(rom) & ROM_GROUPMASK) == ROM_GROUPWORD))
+ {
+ if (!(ROM_GETFLAGS(rom) & ROM_REVERSEMASK))
+ fprintf( out, " loadflag=\"load32_dword\"" );
+ else
+ fprintf( out, " loadflag=\"load16_word_swap\"" );
+ }
+
+ fprintf( out, "/>\n" );
+ }
+ else if ( ROMENTRY_ISRELOAD(rom) )
+ {
+ fprintf( out, "\t\t\t\t\t<rom size=\"%d\" offset=\"0x%x\" loadflag=\"reload\" />\n", ROM_GETLENGTH(rom), ROM_GETOFFSET(rom) );
+ }
+ else if ( ROMENTRY_ISFILL(rom) )
+ {
+ fprintf( out, "\t\t\t\t\t<rom size=\"%d\" offset=\"0x%x\" loadflag=\"fill\" />\n", ROM_GETLENGTH(rom), ROM_GETOFFSET(rom) );
+ }
+ }
+
+ if (!is_disk)
+ fprintf( out, "\t\t\t\t</dataarea>\n" );
+ else
+ fprintf( out, "\t\t\t\t</diskarea>\n" );
+ }
+
+ fprintf( out, "\t\t\t</part>\n" );
+ }
+
+ fprintf( out, "\t\t</software>\n" );
+ }
+ fprintf(out, "\t</softwarelist>\n" );
+}
+/*-------------------------------------------------
+ info_listsoftware - output the list of
+ software supported by a given game or set of
+ games
+ TODO: Add all information read from the source files
+ Possible improvement: use a sorted list for
+ identifying duplicate lists.
+-------------------------------------------------*/
+
+void cli_frontend::listsoftware(const char *gamename)
+{
+ FILE *out = stdout;
+ std::unordered_set<std::string> list_map;
+ bool isfirst = true;
+
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ while (drivlist.next())
+ {
+ for (software_list_device &swlistdev : software_list_device_iterator(drivlist.config().root_device()))
+ if (list_map.insert(swlistdev.list_name()).second)
+ if (!swlistdev.get_info().empty())
+ {
+ if (isfirst) { fprintf(out, SOFTLIST_XML_BEGIN); isfirst = false; }
+ output_single_softlist(out, swlistdev);
+ }
+ }
+
+ if (!isfirst)
+ fprintf( out, "</softwarelists>\n" );
+ else
+ fprintf( out, "No software lists found for this system\n" );
+}
+
+
+/*-------------------------------------------------
+ verifysoftware - verify roms from the software
+ list of the specified driver(s)
+-------------------------------------------------*/
+void cli_frontend::verifysoftware(const char *gamename)
+{
+ std::unordered_set<std::string> list_map;
+
+ int correct = 0;
+ int incorrect = 0;
+ int notfound = 0;
+ int matched = 0;
+ int nrlists = 0;
+
+ // determine which drivers to process; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ {
+ throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+ }
+
+ media_auditor auditor(drivlist);
+ while (drivlist.next())
+ {
+ matched++;
+
+ for (software_list_device &swlistdev : software_list_device_iterator(drivlist.config().root_device()))
+ if (swlistdev.list_type() == SOFTWARE_LIST_ORIGINAL_SYSTEM)
+ if (list_map.insert(swlistdev.list_name()).second)
+ if (!swlistdev.get_info().empty())
+ {
+ nrlists++;
+ for (software_info &swinfo : swlistdev.get_info())
+ {
+ media_auditor::summary summary = auditor.audit_software(swlistdev.list_name(), &swinfo, AUDIT_VALIDATE_FAST);
+
+ // if not found, count that and leave it at that
+ if (summary == media_auditor::NOTFOUND)
+ {
+ notfound++;
+ }
+ // else display information about what we discovered
+ else if(summary != media_auditor::NONE_NEEDED)
+ {
+ // output the summary of the audit
+ std::string summary_string;
+ auditor.summarize(swinfo.shortname(), &summary_string);
+ osd_printf_info("%s", summary_string.c_str());
+
+ // display information about what we discovered
+ osd_printf_info("romset %s:%s ", swlistdev.list_name(), swinfo.shortname());
+
+ // switch off of the result
+ switch (summary)
+ {
+ case media_auditor::INCORRECT:
+ osd_printf_info("is bad\n");
+ incorrect++;
+ break;
+
+ case media_auditor::CORRECT:
+ osd_printf_info("is good\n");
+ correct++;
+ break;
+
+ case media_auditor::BEST_AVAILABLE:
+ osd_printf_info("is best available\n");
+ correct++;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // clear out any cached files
+ util::archive_file::cache_clear();
+
+ // return an error if none found
+ if (matched == 0)
+ throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // if we didn't get anything at all, display a generic end message
+ if (matched > 0 && correct == 0 && incorrect == 0)
+ {
+ throw emu_fatalerror(EMU_ERR_MISSING_FILES, "romset \"%s\" has no software entries defined!\n", gamename);
+ }
+ // otherwise, print a summary
+ else
+ {
+ if (incorrect > 0)
+ throw emu_fatalerror(EMU_ERR_MISSING_FILES, "%d romsets found in %d software lists, %d were OK.\n", correct + incorrect, nrlists, correct);
+ osd_printf_info("%d romsets found in %d software lists, %d romsets were OK.\n", correct, nrlists, correct);
+ }
+
+}
+
+/*-------------------------------------------------
+ getsoftlist - retrieve software list by name
+-------------------------------------------------*/
+
+void cli_frontend::getsoftlist(const char *gamename)
+{
+ FILE *out = stdout;
+ std::unordered_set<std::string> list_map;
+ bool isfirst = TRUE;
+
+ driver_enumerator drivlist(m_options);
+ while (drivlist.next())
+ {
+ for (software_list_device &swlistdev : software_list_device_iterator(drivlist.config().root_device()))
+ if (core_strwildcmp(gamename, swlistdev.list_name()) == 0 && list_map.insert(swlistdev.list_name()).second)
+ if (!swlistdev.get_info().empty())
+ {
+ if (isfirst) { fprintf( out, SOFTLIST_XML_BEGIN); isfirst = FALSE; }
+ output_single_softlist(out, swlistdev);
+ }
+ }
+
+ if (!isfirst)
+ fprintf( out, "</softwarelists>\n" );
+ else
+ fprintf( out, "No such software lists found\n" );
+}
+
+
+/*-------------------------------------------------
+ verifysoftlist - verify software list by name
+-------------------------------------------------*/
+void cli_frontend::verifysoftlist(const char *gamename)
+{
+ std::unordered_set<std::string> list_map;
+ int correct = 0;
+ int incorrect = 0;
+ int notfound = 0;
+ int matched = 0;
+
+ driver_enumerator drivlist(m_options);
+ media_auditor auditor(drivlist);
+
+ while (drivlist.next())
+ {
+ for (software_list_device &swlistdev : software_list_device_iterator(drivlist.config().root_device()))
+ if (core_strwildcmp(gamename, swlistdev.list_name()) == 0 && list_map.insert(swlistdev.list_name()).second)
+ if (!swlistdev.get_info().empty())
+ {
+ matched++;
+
+ // Get the actual software list contents
+ for (software_info &swinfo : swlistdev.get_info())
+ {
+ media_auditor::summary summary = auditor.audit_software(swlistdev.list_name(), &swinfo, AUDIT_VALIDATE_FAST);
+
+ // if not found, count that and leave it at that
+ if (summary == media_auditor::NOTFOUND)
+ {
+ notfound++;
+ }
+ // else display information about what we discovered
+ else if (summary != media_auditor::NONE_NEEDED)
+ {
+ // output the summary of the audit
+ std::string summary_string;
+ auditor.summarize(swinfo.shortname(), &summary_string);
+ osd_printf_info("%s", summary_string.c_str());
+
+ // display information about what we discovered
+ osd_printf_info("romset %s:%s ", swlistdev.list_name(), swinfo.shortname());
+
+ // switch off of the result
+ switch (summary)
+ {
+ case media_auditor::INCORRECT:
+ osd_printf_info("is bad\n");
+ incorrect++;
+ break;
+
+ case media_auditor::CORRECT:
+ osd_printf_info("is good\n");
+ correct++;
+ break;
+
+ case media_auditor::BEST_AVAILABLE:
+ osd_printf_info("is best available\n");
+ correct++;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // clear out any cached files
+ util::archive_file::cache_clear();
+
+ // return an error if none found
+ if (matched == 0)
+ throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "No matching software lists found for '%s'", gamename);
+
+ // if we didn't get anything at all, display a generic end message
+ if (matched > 0 && correct == 0 && incorrect == 0)
+ {
+ throw emu_fatalerror(EMU_ERR_MISSING_FILES, "no romsets found for software list \"%s\"!\n", gamename);
+ }
+ // otherwise, print a summary
+ else
+ {
+ if (incorrect > 0)
+ throw emu_fatalerror(EMU_ERR_MISSING_FILES, "%d romsets found in %d software lists, %d were OK.\n", correct + incorrect, matched, correct);
+ osd_printf_info("%d romsets found in %d software lists, %d romsets were OK.\n", correct, matched, correct);
+ }
+}
+
+//-------------------------------------------------
+// romident - identify ROMs by looking for
+// matches in our internal database
+//-------------------------------------------------
+
+void cli_frontend::romident(const char *filename)
+{
+ media_identifier ident(m_options);
+
+ // identify the file, then output results
+ osd_printf_info("Identifying %s....\n", filename);
+ ident.identify(filename);
+
+ // return the appropriate error code
+ if (ident.matches() == ident.total())
+ return;
+ else if (ident.matches() == ident.total() - ident.nonroms())
+ throw emu_fatalerror(EMU_ERR_IDENT_NONROMS, "Out of %d files, %d matched, %d are not roms.\n",ident.total(),ident.matches(),ident.nonroms());
+ else if (ident.matches() > 0)
+ throw emu_fatalerror(EMU_ERR_IDENT_PARTIAL, "Out of %d files, %d matched, %d did not match.\n",ident.total(),ident.matches(),ident.total()-ident.matches());
+ else
+ throw emu_fatalerror(EMU_ERR_IDENT_NONE, "No roms matched.\n");
+}
+
+
+//-------------------------------------------------
+// execute_commands - execute various frontend
+// commands
+//-------------------------------------------------
+
+void cli_frontend::execute_commands(const char *exename)
+{
+ // help?
+ if (strcmp(m_options.command(), CLICOMMAND_HELP) == 0)
+ {
+ display_help(exename);
+ return;
+ }
+
+ // showusage?
+ if (strcmp(m_options.command(), CLICOMMAND_SHOWUSAGE) == 0)
+ {
+ osd_printf_info("Usage: %s [machine] [media] [software] [options]",exename);
+ osd_printf_info("\n\nOptions:\n%s", m_options.output_help().c_str());
+ return;
+ }
+
+ // validate?
+ if (strcmp(m_options.command(), CLICOMMAND_VALIDATE) == 0)
+ {
+ validity_checker valid(m_options);
+ valid.set_validate_all(true);
+ const char *sysname = m_options.system_name();
+ bool result = valid.check_all_matching((sysname[0] == 0) ? "*" : sysname);
+ if (!result)
+ throw emu_fatalerror(EMU_ERR_FAILED_VALIDITY, "Validity check failed (%d errors, %d warnings in total)\n", valid.errors(), valid.warnings());
+ return;
+ }
+
+ // other commands need the INIs parsed
+ std::string option_errors;
+ mame_options::parse_standard_inis(m_options,option_errors);
+ if (!option_errors.empty())
+ osd_printf_error("%s\n", option_errors.c_str());
+
+ // createconfig?
+ if (strcmp(m_options.command(), CLICOMMAND_CREATECONFIG) == 0)
+ {
+ // attempt to open the output file
+ emu_file file(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ if (file.open(emulator_info::get_configname(), ".ini") != osd_file::error::NONE)
+ throw emu_fatalerror("Unable to create file %s.ini\n",emulator_info::get_configname());
+
+ // generate the updated INI
+ file.puts(m_options.output_ini().c_str());
+
+ ui_options ui_opts;
+ emu_file file_ui(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ if (file_ui.open("ui.ini") != osd_file::error::NONE)
+ throw emu_fatalerror("Unable to create file ui.ini\n");
+
+ // generate the updated INI
+ file_ui.puts(ui_opts.output_ini().c_str());
+
+ plugin_options plugin_opts;
+ path_iterator iter(m_options.plugins_path());
+ std::string pluginpath;
+ while (iter.next(pluginpath))
+ {
+ plugin_opts.parse_json(pluginpath);
+ }
+ emu_file file_plugin(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ if (file_plugin.open("plugin.ini") != osd_file::error::NONE)
+ throw emu_fatalerror("Unable to create file plugin.ini\n");
+
+ // generate the updated INI
+ file_plugin.puts(plugin_opts.output_ini().c_str());
+
+ return;
+ }
+
+ // showconfig?
+ if (strcmp(m_options.command(), CLICOMMAND_SHOWCONFIG) == 0)
+ {
+ // print the INI text
+ printf("%s\n", m_options.output_ini().c_str());
+ return;
+ }
+
+ // all other commands call out to one of these helpers
+ static const struct
+ {
+ const char *option;
+ void (cli_frontend::*function)(const char *gamename);
+ } info_commands[] =
+ {
+ { CLICOMMAND_LISTXML, &cli_frontend::listxml },
+ { CLICOMMAND_LISTFULL, &cli_frontend::listfull },
+ { CLICOMMAND_LISTSOURCE, &cli_frontend::listsource },
+ { CLICOMMAND_LISTCLONES, &cli_frontend::listclones },
+ { CLICOMMAND_LISTBROTHERS, &cli_frontend::listbrothers },
+ { CLICOMMAND_LISTCRC, &cli_frontend::listcrc },
+ { CLICOMMAND_LISTDEVICES, &cli_frontend::listdevices },
+ { CLICOMMAND_LISTSLOTS, &cli_frontend::listslots },
+ { CLICOMMAND_LISTROMS, &cli_frontend::listroms },
+ { CLICOMMAND_LISTSAMPLES, &cli_frontend::listsamples },
+ { CLICOMMAND_VERIFYROMS, &cli_frontend::verifyroms },
+ { CLICOMMAND_VERIFYSAMPLES, &cli_frontend::verifysamples },
+ { CLICOMMAND_LISTMEDIA, &cli_frontend::listmedia },
+ { CLICOMMAND_LISTSOFTWARE, &cli_frontend::listsoftware },
+ { CLICOMMAND_VERIFYSOFTWARE,&cli_frontend::verifysoftware },
+ { CLICOMMAND_ROMIDENT, &cli_frontend::romident },
+ { CLICOMMAND_GETSOFTLIST, &cli_frontend::getsoftlist },
+ { CLICOMMAND_VERIFYSOFTLIST,&cli_frontend::verifysoftlist },
+ };
+
+ // find the command
+ for (auto & info_command : info_commands)
+ if (strcmp(m_options.command(), info_command.option) == 0)
+ {
+ // parse any relevant INI files before proceeding
+ const char *sysname = m_options.system_name();
+ (this->*info_command.function)((sysname[0] == 0) ? "*" : sysname);
+ return;
+ }
+
+ if (!m_osd.execute_command(m_options.command()))
+ // if we get here, we don't know what has been requested
+ throw emu_fatalerror(EMU_ERR_INVALID_CONFIG, "Unknown command '%s' specified", m_options.command());
+}
+
+
+//-------------------------------------------------
+// display_help - display help to standard
+// output
+//-------------------------------------------------
+
+void cli_frontend::display_help(const char *exename)
+{
+ osd_printf_info("%s v%s\n%s\n\n", emulator_info::get_appname(),build_version,emulator_info::get_copyright_info());
+ osd_printf_info("This software reproduces, more or less faithfully, the behaviour of a wide range\n"
+ "of machines. But hardware is useless without software, so images of the ROMs and\n"
+ "other media which run on that hardware are also required.\n\n");
+ osd_printf_info("Usage: %s [machine] [media] [software] [options]",exename);
+ osd_printf_info("\n\n"
+ " %s -showusage for a brief list of options\n"
+ " %s -showconfig for a list of configuration options\n"
+ " %s -listmedia for a full list of supported media\n"
+ " %s -createconfig to create a %s.ini\n\n"
+ "For usage instructions, please consult the files config.txt and windows.txt.\n",exename,
+ exename,exename,exename,emulator_info::get_configname());
+}
+
+
+//-------------------------------------------------
+// display_suggestions - display 10 possible
+// matches for a given invalid gamename
+//-------------------------------------------------
+
+void cli_frontend::display_suggestions(const char *gamename)
+{
+}
+
+
+//**************************************************************************
+// MEDIA IDENTIFIER
+//**************************************************************************
+
+//-------------------------------------------------
+// media_identifier - constructor
+//-------------------------------------------------
+
+media_identifier::media_identifier(emu_options &options)
+ : m_drivlist(options),
+ m_total(0),
+ m_matches(0),
+ m_nonroms(0)
+{
+}
+
+
+//-------------------------------------------------
+// identify - identify a directory, ZIP file,
+// or raw file
+//-------------------------------------------------
+
+void media_identifier::identify(const char *filename)
+{
+ // first try to open as a directory
+ osd_directory *directory = osd_opendir(filename);
+ if (directory != nullptr)
+ {
+ // iterate over all files in the directory
+ for (const osd_directory_entry *entry = osd_readdir(directory); entry != nullptr; entry = osd_readdir(directory))
+ if (entry->type == ENTTYPE_FILE)
+ {
+ std::string curfile = std::string(filename).append(PATH_SEPARATOR).append(entry->name);
+ identify(curfile.c_str());
+ }
+
+ // close the directory and be done
+ osd_closedir(directory);
+ }
+
+ // if that failed, and the filename ends with .zip, identify as a ZIP file
+ if (core_filename_ends_with(filename, ".7z") || core_filename_ends_with(filename, ".zip"))
+ {
+ // first attempt to examine it as a valid _7Z file
+ util::archive_file::ptr archive;
+ util::archive_file::error err;
+ if (core_filename_ends_with(filename, ".7z"))
+ err = util::archive_file::open_7z(filename, archive);
+ else
+ err = util::archive_file::open_zip(filename, archive);
+ if ((err == util::archive_file::error::NONE) && archive)
+ {
+ std::vector<std::uint8_t> data;
+
+ // loop over entries in the .7z, skipping empty files and directories
+ for (int i = archive->first_file(); i >= 0; i = archive->next_file())
+ {
+ const std::uint64_t length(archive->current_uncompressed_length());
+ if (!archive->current_is_directory() && (length != 0) && (std::uint32_t(length) == length))
+ {
+ // decompress data into RAM and identify it
+ try
+ {
+ data.resize(std::size_t(length));
+ err = archive->decompress(&data[0], std::uint32_t(length));
+ if (err == util::archive_file::error::NONE)
+ identify_data(archive->current_name().c_str(), &data[0], length);
+ }
+ catch (...)
+ {
+ // resizing the buffer could cause a bad_alloc if archive contains large files
+ }
+ data.clear();
+ }
+ }
+ }
+
+ // clear out any cached files
+ archive.reset();
+ util::archive_file::cache_clear();
+ }
+
+ // otherwise, identify as a raw file
+ else
+ identify_file(filename);
+}
+
+
+//-------------------------------------------------
+// identify_file - identify a file
+//-------------------------------------------------
+
+void media_identifier::identify_file(const char *name)
+{
+ // CHD files need to be parsed and their hashes extracted from the header
+ if (core_filename_ends_with(name, ".chd"))
+ {
+ // output the name
+ osd_printf_info("%-20s", core_filename_extract_base(name).c_str());
+ m_total++;
+
+ // attempt to open as a CHD; fail if not
+ chd_file chd;
+ chd_error err = chd.open(name);
+ if (err != CHDERR_NONE)
+ {
+ osd_printf_info("NOT A CHD\n");
+ m_nonroms++;
+ return;
+ }
+
+ // error on writable CHDs
+ if (!chd.compressed())
+ {
+ osd_printf_info("is a writeable CHD\n");
+ return;
+ }
+
+ // otherwise, get the hash collection for this CHD
+ hash_collection hashes;
+ if (chd.sha1() != sha1_t::null)
+ hashes.add_sha1(chd.sha1());
+
+ // determine whether this file exists
+ int found = find_by_hash(hashes, chd.logical_bytes());
+ if (found == 0)
+ osd_printf_info("NO MATCH\n");
+ else
+ m_matches++;
+ }
+
+ // all other files have their hashes computed directly
+ else
+ {
+ // load the file and process if it opens and has a valid length
+ UINT32 length;
+ void *data;
+ const osd_file::error filerr = util::core_file::load(name, &data, length);
+ if (filerr == osd_file::error::NONE && length > 0)
+ {
+ identify_data(name, reinterpret_cast<UINT8 *>(data), length);
+ osd_free(data);
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// identify_data - identify a buffer full of
+// data; if it comes from a .JED file, parse the
+// fusemap into raw data first
+//-------------------------------------------------
+
+void media_identifier::identify_data(const char *name, const UINT8 *data, int length)
+{
+ // if this is a '.jed' file, process it into raw bits first
+ dynamic_buffer tempjed;
+ jed_data jed;
+ if (core_filename_ends_with(name, ".jed") && jed_parse(data, length, &jed) == JEDERR_NONE)
+ {
+ // now determine the new data length and allocate temporary memory for it
+ length = jedbin_output(&jed, nullptr, 0);
+ tempjed.resize(length);
+ jedbin_output(&jed, &tempjed[0], length);
+ data = &tempjed[0];
+ }
+
+ // compute the hash of the data
+ hash_collection hashes;
+ hashes.compute(data, length, hash_collection::HASH_TYPES_CRC_SHA1);
+
+ // output the name
+ m_total++;
+ osd_printf_info("%-20s", core_filename_extract_base(name).c_str());
+
+ // see if we can find a match in the ROMs
+ int found = find_by_hash(hashes, length);
+
+ // if we didn't find it, try to guess what it might be
+ if (found == 0)
+ osd_printf_info("NO MATCH\n");
+
+ // if we did find it, count it as a match
+ else
+ m_matches++;
+}
+
+
+//-------------------------------------------------
+// find_by_hash - scan for a file in the list
+// of drivers by hash
+//-------------------------------------------------
+
+int media_identifier::find_by_hash(const hash_collection &hashes, int length)
+{
+ int found = 0;
+ std::unordered_set<std::string> listnames;
+ std::unordered_set<std::string> shortnames;
+
+ // iterate over drivers
+ m_drivlist.reset();
+ while (m_drivlist.next())
+ {
+ // iterate over devices, regions and files within the region
+ for (device_t &device : device_iterator(m_drivlist.config().root_device()))
+ {
+ if (shortnames.insert(device.shortname()).second)
+ {
+ for (const rom_entry *region = rom_first_region(device); region != nullptr; region = rom_next_region(region))
+ for (const rom_entry *rom = rom_first_file(region); rom != nullptr; rom = rom_next_file(rom))
+ {
+ hash_collection romhashes(ROM_GETHASHDATA(rom));
+ if (!romhashes.flag(hash_collection::FLAG_NO_DUMP) && hashes == romhashes)
+ {
+ bool baddump = romhashes.flag(hash_collection::FLAG_BAD_DUMP);
+
+ // output information about the match
+ if (found)
+ osd_printf_info(" ");
+ osd_printf_info("= %s%-20s %-10s %s\n", baddump ? "(BAD) " : "", ROM_GETNAME(rom), m_drivlist.driver().name, m_drivlist.driver().description);
+ found++;
+ }
+ }
+ }
+ }
+
+ // next iterate over softlists
+ for (software_list_device &swlistdev : software_list_device_iterator(m_drivlist.config().root_device()))
+ {
+ if (listnames.insert(swlistdev.list_name()).second)
+ {
+ for (software_info &swinfo : swlistdev.get_info())
+ for (software_part &part : swinfo.parts())
+ for (const rom_entry *region = part.romdata(); region != nullptr; region = rom_next_region(region))
+ for (const rom_entry *rom = rom_first_file(region); rom != nullptr; rom = rom_next_file(rom))
+ {
+ hash_collection romhashes(ROM_GETHASHDATA(rom));
+ if (hashes == romhashes)
+ {
+ bool baddump = romhashes.flag(hash_collection::FLAG_BAD_DUMP);
+
+ // output information about the match
+ if (found)
+ osd_printf_info(" ");
+ osd_printf_info("= %s%-20s %s:%s %s\n", baddump ? "(BAD) " : "", ROM_GETNAME(rom), swlistdev.list_name(), swinfo.shortname(), swinfo.longname());
+ found++;
+ }
+ }
+ }
+ }
+ }
+
+ return found;
+}
diff --git a/src/frontend/mame/clifront.h b/src/frontend/mame/clifront.h
new file mode 100644
index 00000000000..2a7da7fcb78
--- /dev/null
+++ b/src/frontend/mame/clifront.h
@@ -0,0 +1,75 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+/***************************************************************************
+
+ clifront.h
+
+ Command-line interface frontend for MAME.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __CLIFRONT_H__
+#define __CLIFRONT_H__
+
+#include "emu.h"
+#include "emuopts.h"
+
+// don't include osd_interface in header files
+class osd_interface;
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// cli_frontend handles command-line processing and emulator execution
+class cli_frontend
+{
+public:
+ // construction/destruction
+ cli_frontend(emu_options &options, osd_interface &osd);
+ ~cli_frontend();
+
+ // execute based on the incoming argc/argv
+ int execute(int argc, char **argv);
+
+ // direct access to the command operations
+ void listxml(const char *gamename = "*");
+ void listfull(const char *gamename = "*");
+ void listsource(const char *gamename = "*");
+ void listclones(const char *gamename = "*");
+ void listbrothers(const char *gamename = "*");
+ void listcrc(const char *gamename = "*");
+ void listroms(const char *gamename = "*");
+ void listsamples(const char *gamename = "*");
+ static int compare_devices(const void *i1, const void *i2);
+ void listdevices(const char *gamename = "*");
+ void listslots(const char *gamename = "*");
+ void listmedia(const char *gamename = "*");
+ void listsoftware(const char *gamename = "*");
+ void verifysoftware(const char *gamename = "*");
+ void verifyroms(const char *gamename = "*");
+ void verifysamples(const char *gamename = "*");
+ void romident(const char *filename);
+ void getsoftlist(const char *gamename = "*");
+ void verifysoftlist(const char *gamename = "*");
+
+private:
+ // internal helpers
+ void execute_commands(const char *exename);
+ void display_help(const char *exename);
+ void display_suggestions(const char *gamename);
+ void output_single_softlist(FILE *out, software_list_device &swlist);
+
+ // internal state
+ emu_options & m_options;
+ osd_interface & m_osd;
+ int m_result;
+};
+
+
+
+
+#endif /* __CLIFRONT_H__ */
diff --git a/src/frontend/mame/info.cpp b/src/frontend/mame/info.cpp
new file mode 100644
index 00000000000..ee77890d63b
--- /dev/null
+++ b/src/frontend/mame/info.cpp
@@ -0,0 +1,1601 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles,Paul Priest
+/***************************************************************************
+
+ info.c
+
+ Dumps the MAME internal data as an XML file.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "mame.h"
+#include "emuopts.h"
+#include "mameopts.h"
+#include "machine/ram.h"
+#include "sound/samples.h"
+#include "info.h"
+#include "xmlfile.h"
+#include "config.h"
+#include "softlist.h"
+
+#include <ctype.h>
+
+#define XML_ROOT "mame"
+#define XML_TOP "machine"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// DTD string describing the data
+const char info_xml_creator::s_dtd_string[] =
+"<!DOCTYPE __XML_ROOT__ [\n"
+"<!ELEMENT __XML_ROOT__ (__XML_TOP__+)>\n"
+"\t<!ATTLIST __XML_ROOT__ build CDATA #IMPLIED>\n"
+"\t<!ATTLIST __XML_ROOT__ debug (yes|no) \"no\">\n"
+"\t<!ATTLIST __XML_ROOT__ mameconfig CDATA #REQUIRED>\n"
+"\t<!ELEMENT __XML_TOP__ (description, year?, manufacturer?, biosset*, rom*, disk*, device_ref*, sample*, chip*, display*, sound?, input?, dipswitch*, configuration*, port*, adjuster*, driver?, device*, slot*, softwarelist*, ramoption*)>\n"
+"\t\t<!ATTLIST __XML_TOP__ name CDATA #REQUIRED>\n"
+"\t\t<!ATTLIST __XML_TOP__ sourcefile CDATA #IMPLIED>\n"
+"\t\t<!ATTLIST __XML_TOP__ isbios (yes|no) \"no\">\n"
+"\t\t<!ATTLIST __XML_TOP__ isdevice (yes|no) \"no\">\n"
+"\t\t<!ATTLIST __XML_TOP__ ismechanical (yes|no) \"no\">\n"
+"\t\t<!ATTLIST __XML_TOP__ runnable (yes|no) \"yes\">\n"
+"\t\t<!ATTLIST __XML_TOP__ cloneof CDATA #IMPLIED>\n"
+"\t\t<!ATTLIST __XML_TOP__ romof CDATA #IMPLIED>\n"
+"\t\t<!ATTLIST __XML_TOP__ sampleof CDATA #IMPLIED>\n"
+"\t\t<!ELEMENT description (#PCDATA)>\n"
+"\t\t<!ELEMENT year (#PCDATA)>\n"
+"\t\t<!ELEMENT manufacturer (#PCDATA)>\n"
+"\t\t<!ELEMENT biosset EMPTY>\n"
+"\t\t\t<!ATTLIST biosset name CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST biosset description CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST biosset default (yes|no) \"no\">\n"
+"\t\t<!ELEMENT rom EMPTY>\n"
+"\t\t\t<!ATTLIST rom name CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST rom bios CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST rom size CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST rom crc CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST rom sha1 CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST rom merge CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST rom region CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST rom offset CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST rom status (baddump|nodump|good) \"good\">\n"
+"\t\t\t<!ATTLIST rom optional (yes|no) \"no\">\n"
+"\t\t<!ELEMENT disk EMPTY>\n"
+"\t\t\t<!ATTLIST disk name CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST disk sha1 CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST disk merge CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST disk region CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST disk index CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST disk writable (yes|no) \"no\">\n"
+"\t\t\t<!ATTLIST disk status (baddump|nodump|good) \"good\">\n"
+"\t\t\t<!ATTLIST disk optional (yes|no) \"no\">\n"
+"\t\t<!ELEMENT device_ref EMPTY>\n"
+"\t\t\t<!ATTLIST device_ref name CDATA #REQUIRED>\n"
+"\t\t<!ELEMENT sample EMPTY>\n"
+"\t\t\t<!ATTLIST sample name CDATA #REQUIRED>\n"
+"\t\t<!ELEMENT chip EMPTY>\n"
+"\t\t\t<!ATTLIST chip name CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST chip tag CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST chip type (cpu|audio) #REQUIRED>\n"
+"\t\t\t<!ATTLIST chip clock CDATA #IMPLIED>\n"
+"\t\t<!ELEMENT display EMPTY>\n"
+"\t\t\t<!ATTLIST display tag CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST display type (raster|vector|lcd|unknown) #REQUIRED>\n"
+"\t\t\t<!ATTLIST display rotate (0|90|180|270) #REQUIRED>\n"
+"\t\t\t<!ATTLIST display flipx (yes|no) \"no\">\n"
+"\t\t\t<!ATTLIST display width CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST display height CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST display refresh CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST display pixclock CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST display htotal CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST display hbend CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST display hbstart CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST display vtotal CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST display vbend CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST display vbstart CDATA #IMPLIED>\n"
+"\t\t<!ELEMENT sound EMPTY>\n"
+"\t\t\t<!ATTLIST sound channels CDATA #REQUIRED>\n"
+"\t\t<!ELEMENT input (control*)>\n"
+"\t\t\t<!ATTLIST input service (yes|no) \"no\">\n"
+"\t\t\t<!ATTLIST input tilt (yes|no) \"no\">\n"
+"\t\t\t<!ATTLIST input players CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST input coins CDATA #IMPLIED>\n"
+"\t\t\t<!ELEMENT control EMPTY>\n"
+"\t\t\t\t<!ATTLIST control type CDATA #REQUIRED>\n"
+"\t\t\t\t<!ATTLIST control player CDATA #IMPLIED>\n"
+"\t\t\t\t<!ATTLIST control buttons CDATA #IMPLIED>\n"
+"\t\t\t\t<!ATTLIST control minimum CDATA #IMPLIED>\n"
+"\t\t\t\t<!ATTLIST control maximum CDATA #IMPLIED>\n"
+"\t\t\t\t<!ATTLIST control sensitivity CDATA #IMPLIED>\n"
+"\t\t\t\t<!ATTLIST control keydelta CDATA #IMPLIED>\n"
+"\t\t\t\t<!ATTLIST control reverse (yes|no) \"no\">\n"
+"\t\t\t\t<!ATTLIST control ways CDATA #IMPLIED>\n"
+"\t\t\t\t<!ATTLIST control ways2 CDATA #IMPLIED>\n"
+"\t\t\t\t<!ATTLIST control ways3 CDATA #IMPLIED>\n"
+"\t\t<!ELEMENT dipswitch (dipvalue*)>\n"
+"\t\t\t<!ATTLIST dipswitch name CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST dipswitch tag CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST dipswitch mask CDATA #REQUIRED>\n"
+"\t\t\t<!ELEMENT dipvalue EMPTY>\n"
+"\t\t\t\t<!ATTLIST dipvalue name CDATA #REQUIRED>\n"
+"\t\t\t\t<!ATTLIST dipvalue value CDATA #REQUIRED>\n"
+"\t\t\t\t<!ATTLIST dipvalue default (yes|no) \"no\">\n"
+"\t\t<!ELEMENT configuration (confsetting*)>\n"
+"\t\t\t<!ATTLIST configuration name CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST configuration tag CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST configuration mask CDATA #REQUIRED>\n"
+"\t\t\t<!ELEMENT confsetting EMPTY>\n"
+"\t\t\t\t<!ATTLIST confsetting name CDATA #REQUIRED>\n"
+"\t\t\t\t<!ATTLIST confsetting value CDATA #REQUIRED>\n"
+"\t\t\t\t<!ATTLIST confsetting default (yes|no) \"no\">\n"
+"\t\t<!ELEMENT port (analog*)>\n"
+"\t\t\t<!ATTLIST port tag CDATA #REQUIRED>\n"
+"\t\t\t<!ELEMENT analog EMPTY>\n"
+"\t\t\t\t<!ATTLIST analog mask CDATA #REQUIRED>\n"
+"\t\t<!ELEMENT adjuster EMPTY>\n"
+"\t\t\t<!ATTLIST adjuster name CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST adjuster default CDATA #REQUIRED>\n"
+"\t\t<!ELEMENT driver EMPTY>\n"
+"\t\t\t<!ATTLIST driver status (good|imperfect|preliminary) #REQUIRED>\n"
+"\t\t\t<!ATTLIST driver emulation (good|imperfect|preliminary) #REQUIRED>\n"
+"\t\t\t<!ATTLIST driver color (good|imperfect|preliminary) #REQUIRED>\n"
+"\t\t\t<!ATTLIST driver sound (good|imperfect|preliminary) #REQUIRED>\n"
+"\t\t\t<!ATTLIST driver graphic (good|imperfect|preliminary) #REQUIRED>\n"
+"\t\t\t<!ATTLIST driver cocktail (good|imperfect|preliminary) #IMPLIED>\n"
+"\t\t\t<!ATTLIST driver protection (good|imperfect|preliminary) #IMPLIED>\n"
+"\t\t\t<!ATTLIST driver savestate (supported|unsupported) #REQUIRED>\n"
+"\t\t<!ELEMENT device (instance*, extension*)>\n"
+"\t\t\t<!ATTLIST device type CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST device tag CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST device fixed_image CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST device mandatory CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST device interface CDATA #IMPLIED>\n"
+"\t\t\t<!ELEMENT instance EMPTY>\n"
+"\t\t\t\t<!ATTLIST instance name CDATA #REQUIRED>\n"
+"\t\t\t\t<!ATTLIST instance briefname CDATA #REQUIRED>\n"
+"\t\t\t<!ELEMENT extension EMPTY>\n"
+"\t\t\t\t<!ATTLIST extension name CDATA #REQUIRED>\n"
+"\t\t<!ELEMENT slot (slotoption*)>\n"
+"\t\t\t<!ATTLIST slot name CDATA #REQUIRED>\n"
+"\t\t\t<!ELEMENT slotoption EMPTY>\n"
+"\t\t\t\t<!ATTLIST slotoption name CDATA #REQUIRED>\n"
+"\t\t\t\t<!ATTLIST slotoption devname CDATA #REQUIRED>\n"
+"\t\t\t\t<!ATTLIST slotoption default (yes|no) \"no\">\n"
+"\t\t<!ELEMENT softwarelist EMPTY>\n"
+"\t\t\t<!ATTLIST softwarelist name CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST softwarelist status (original|compatible) #REQUIRED>\n"
+"\t\t\t<!ATTLIST softwarelist filter CDATA #IMPLIED>\n"
+"\t\t<!ELEMENT ramoption (#PCDATA)>\n"
+"\t\t\t<!ATTLIST ramoption default CDATA #IMPLIED>\n"
+"]>";
+
+
+//**************************************************************************
+// INFO XML CREATOR
+//**************************************************************************
+
+//-------------------------------------------------
+// info_xml_creator - constructor
+//-------------------------------------------------
+
+info_xml_creator::info_xml_creator(driver_enumerator &drivlist)
+ : m_output(nullptr),
+ m_drivlist(drivlist),
+ m_lookup_options(m_drivlist.options())
+{
+ mame_options::remove_device_options(m_lookup_options);
+}
+
+
+//-------------------------------------------------
+// output_mame_xml - print the XML information
+// for all known games
+//-------------------------------------------------
+
+void info_xml_creator::output(FILE *out, bool nodevices)
+{
+ m_output = out;
+
+ // output the DTD
+ fprintf(m_output, "<?xml version=\"1.0\"?>\n");
+ std::string dtd(s_dtd_string);
+ strreplace(dtd, "__XML_ROOT__", XML_ROOT);
+ strreplace(dtd, "__XML_TOP__", XML_TOP);
+
+ fprintf(m_output, "%s\n\n", dtd.c_str());
+
+ // top-level tag
+ fprintf(m_output, "<%s build=\"%s\" debug=\""
+#ifdef MAME_DEBUG
+ "yes"
+#else
+ "no"
+#endif
+ "\" mameconfig=\"%d\">\n",
+ XML_ROOT,
+ xml_normalize_string(build_version),
+ CONFIG_VERSION
+ );
+
+ // iterate through the drivers, outputting one at a time
+ while (m_drivlist.next())
+ output_one();
+
+ // output devices (both devices with roms and slot devices)
+ if (!nodevices)
+ output_devices();
+
+ // close the top level tag
+ fprintf(m_output, "</%s>\n",XML_ROOT);
+}
+
+
+//-------------------------------------------------
+// output_one - print the XML information
+// for one particular game driver
+//-------------------------------------------------
+
+void info_xml_creator::output_one()
+{
+ // no action if not a game
+ const game_driver &driver = m_drivlist.driver();
+ if (driver.flags & MACHINE_NO_STANDALONE)
+ return;
+
+ // allocate input ports
+ machine_config &config = m_drivlist.config();
+ ioport_list portlist;
+ std::string errors;
+ device_iterator iter(config.root_device());
+ for (device_t &device : iter)
+ portlist.append(device, errors);
+
+ // renumber player numbers for controller ports
+ int player_offset = 0;
+ // but treat keyboard count separately from players' number
+ int kbd_offset = 0;
+ for (device_t &device : iter)
+ {
+ int nplayers = 0;
+ bool new_kbd = false;
+ for (ioport_port &port : portlist)
+ if (&port.device() == &device)
+ for (ioport_field &field : port.fields())
+ if (field.type() >= IPT_START && field.type() < IPT_ANALOG_LAST)
+ {
+ if (field.type() == IPT_KEYBOARD)
+ {
+ if (!new_kbd) new_kbd = TRUE;
+ field.set_player(field.player() + kbd_offset);
+ }
+ else
+ {
+ nplayers = MAX(nplayers, field.player() + 1);
+ field.set_player(field.player() + player_offset);
+ }
+ }
+ player_offset += nplayers;
+ if (new_kbd) kbd_offset++;
+ }
+
+ // print the header and the game name
+ fprintf(m_output, "\t<%s",XML_TOP);
+ fprintf(m_output, " name=\"%s\"", xml_normalize_string(driver.name));
+
+ // strip away any path information from the source_file and output it
+ const char *start = strrchr(driver.source_file, '/');
+ if (start == nullptr)
+ start = strrchr(driver.source_file, '\\');
+ if (start == nullptr)
+ start = driver.source_file - 1;
+ fprintf(m_output, " sourcefile=\"%s\"", xml_normalize_string(start + 1));
+
+ // append bios and runnable flags
+ if (driver.flags & MACHINE_IS_BIOS_ROOT)
+ fprintf(m_output, " isbios=\"yes\"");
+ if (driver.flags & MACHINE_NO_STANDALONE)
+ fprintf(m_output, " runnable=\"no\"");
+ if (driver.flags & MACHINE_MECHANICAL)
+ fprintf(m_output, " ismechanical=\"yes\"");
+
+ // display clone information
+ int clone_of = m_drivlist.find(driver.parent);
+ if (clone_of != -1 && !(m_drivlist.driver(clone_of).flags & MACHINE_IS_BIOS_ROOT))
+ fprintf(m_output, " cloneof=\"%s\"", xml_normalize_string(m_drivlist.driver(clone_of).name));
+ if (clone_of != -1)
+ fprintf(m_output, " romof=\"%s\"", xml_normalize_string(m_drivlist.driver(clone_of).name));
+
+ // display sample information and close the game tag
+ output_sampleof();
+ fprintf(m_output, ">\n");
+
+ // output game description
+ if (driver.description != nullptr)
+ fprintf(m_output, "\t\t<description>%s</description>\n", xml_normalize_string(driver.description));
+
+ // print the year only if is a number or another allowed character (? or +)
+ if (driver.year != nullptr && strspn(driver.year, "0123456789?+") == strlen(driver.year))
+ fprintf(m_output, "\t\t<year>%s</year>\n", xml_normalize_string(driver.year));
+
+ // print the manufacturer information
+ if (driver.manufacturer != nullptr)
+ fprintf(m_output, "\t\t<manufacturer>%s</manufacturer>\n", xml_normalize_string(driver.manufacturer));
+
+ // now print various additional information
+ output_bios();
+ output_rom(m_drivlist.config().root_device());
+ output_device_roms();
+ output_sample(m_drivlist.config().root_device());
+ output_chips(m_drivlist.config().root_device(), "");
+ output_display(m_drivlist.config().root_device(), "");
+ output_sound(m_drivlist.config().root_device());
+ output_input(portlist);
+ output_switches(portlist, "", IPT_DIPSWITCH, "dipswitch", "dipvalue");
+ output_switches(portlist, "", IPT_CONFIG, "configuration", "confsetting");
+ output_ports(portlist);
+ output_adjusters(portlist);
+ output_driver();
+ output_images(m_drivlist.config().root_device(), "");
+ output_slots(m_drivlist.config().root_device(), "");
+ output_software_list();
+ output_ramoptions();
+
+ // close the topmost tag
+ fprintf(m_output, "\t</%s>\n",XML_TOP);
+}
+
+
+//-------------------------------------------------
+// output_one_device - print the XML info for
+// a single device
+//-------------------------------------------------
+
+void info_xml_creator::output_one_device(device_t &device, const char *devtag)
+{
+ bool has_speaker = FALSE, has_input = FALSE;
+ // check if the device adds speakers to the system
+ sound_interface_iterator snditer(device);
+ if (snditer.first() != nullptr)
+ has_speaker = TRUE;
+ // generate input list
+ ioport_list portlist;
+ std::string errors;
+ for (device_t &dev : device_iterator(device))
+ portlist.append(dev, errors);
+ // check if the device adds player inputs (other than dsw and configs) to the system
+ for (ioport_port &port : portlist)
+ for (ioport_field &field : port.fields())
+ if (field.type() >= IPT_START1 && field.type() < IPT_UI_FIRST)
+ {
+ has_input = TRUE;
+ break;
+ }
+
+ // start to output info
+ fprintf(m_output, "\t<%s", XML_TOP);
+ fprintf(m_output, " name=\"%s\"", xml_normalize_string(device.shortname()));
+ std::string src(device.source());
+ strreplace(src,"../", "");
+ fprintf(m_output, " sourcefile=\"%s\"", xml_normalize_string(src.c_str()));
+ fprintf(m_output, " isdevice=\"yes\"");
+ fprintf(m_output, " runnable=\"no\"");
+ output_sampleof();
+ fprintf(m_output, ">\n");
+ fprintf(m_output, "\t\t<description>%s</description>\n", xml_normalize_string(device.name()));
+
+ output_rom(device);
+
+ samples_device *samples = dynamic_cast<samples_device*>(&device);
+ if (samples==nullptr) output_sample(device); // ignore samples_device itself
+
+ output_chips(device, devtag);
+ output_display(device, devtag);
+ if (has_speaker)
+ output_sound(device);
+ if (has_input)
+ output_input(portlist);
+ output_switches(portlist, devtag, IPT_DIPSWITCH, "dipswitch", "dipvalue");
+ output_switches(portlist, devtag, IPT_CONFIG, "configuration", "confsetting");
+ output_adjusters(portlist);
+ output_images(device, devtag);
+ output_slots(device, devtag);
+ fprintf(m_output, "\t</%s>\n", XML_TOP);
+}
+
+
+//-------------------------------------------------
+// output_devices - print the XML info for devices
+// with roms and for devices that can be mounted
+// in slots
+// The current solution works to some extent, but
+// it is limited by the fact that devices are only
+// acknowledged when attached to a driver (so that
+// for instance sub-sub-devices could never appear
+// in the xml input if they are not also attached
+// directly to a driver as device or sub-device)
+//-------------------------------------------------
+
+void info_xml_creator::output_devices()
+{
+ m_drivlist.reset();
+ std::unordered_set<std::string> shortnames;
+
+ while (m_drivlist.next())
+ {
+ // first, run through devices with roms which belongs to the default configuration
+ for (device_t &device : device_iterator(m_drivlist.config().root_device()))
+ {
+ if (device.owner() != nullptr && device.shortname() != nullptr && device.shortname()[0]!='\0')
+ {
+ if (shortnames.insert(device.shortname()).second)
+ output_one_device(device, device.tag());
+ }
+ }
+
+ // then, run through slot devices
+ for (const device_slot_interface &slot : slot_interface_iterator(m_drivlist.config().root_device()))
+ {
+ for (const device_slot_option &option : slot.option_list())
+ {
+ std::string temptag("_");
+ temptag.append(option.name());
+ device_t *dev = const_cast<machine_config &>(m_drivlist.config()).device_add(&m_drivlist.config().root_device(), temptag.c_str(), option.devtype(), 0);
+
+ // notify this device and all its subdevices that they are now configured
+ for (device_t &device : device_iterator(*dev))
+ if (!device.configured())
+ device.config_complete();
+
+ if (shortnames.insert(dev->shortname()).second)
+ output_one_device(*dev, temptag.c_str());
+
+ // also, check for subdevices with ROMs (a few devices are missed otherwise, e.g. MPU401)
+ for (device_t &device : device_iterator(*dev))
+ {
+ if (device.owner() == dev && device.shortname() != nullptr && device.shortname()[0]!='\0')
+ {
+ if (shortnames.insert(device.shortname()).second)
+ output_one_device(device, device.tag());
+ }
+ }
+
+ const_cast<machine_config &>(m_drivlist.config()).device_remove(&m_drivlist.config().root_device(), temptag.c_str());
+ }
+ }
+ }
+}
+
+
+//------------------------------------------------
+// output_device_roms - when a driver uses roms
+// included in a device set, print a reference
+//-------------------------------------------------
+
+void info_xml_creator::output_device_roms()
+{
+ for (device_t &device : device_iterator(m_drivlist.config().root_device()))
+ if (device.owner() != nullptr && device.shortname() != nullptr && device.shortname()[0] != '\0')
+ fprintf(m_output, "\t\t<device_ref name=\"%s\"/>\n", xml_normalize_string(device.shortname()));
+}
+
+
+//------------------------------------------------
+// output_sampleof - print the 'sampleof'
+// attribute, if appropriate
+//-------------------------------------------------
+
+void info_xml_creator::output_sampleof()
+{
+ // iterate over sample devices
+ for (samples_device &device : samples_device_iterator(m_drivlist.config().root_device()))
+ {
+ samples_iterator sampiter(device);
+ if (sampiter.altbasename() != nullptr)
+ {
+ fprintf(m_output, " sampleof=\"%s\"", xml_normalize_string(sampiter.altbasename()));
+
+ // must stop here, as there can only be one attribute of the same name
+ return;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// output_bios - print the BIOS set for a
+// game
+//-------------------------------------------------
+
+void info_xml_creator::output_bios()
+{
+ // skip if no ROMs
+ if (m_drivlist.driver().rom == nullptr)
+ return;
+
+ // first determine the default BIOS name
+ std::string defaultname;
+ for (const rom_entry *rom = m_drivlist.driver().rom; !ROMENTRY_ISEND(rom); rom++)
+ if (ROMENTRY_ISDEFAULT_BIOS(rom))
+ defaultname = ROM_GETNAME(rom);
+
+ // iterate over ROM entries and look for BIOSes
+ for (const rom_entry *rom = m_drivlist.driver().rom; !ROMENTRY_ISEND(rom); rom++)
+ if (ROMENTRY_ISSYSTEM_BIOS(rom))
+ {
+ // output extracted name and descriptions
+ fprintf(m_output, "\t\t<biosset");
+ fprintf(m_output, " name=\"%s\"", xml_normalize_string(ROM_GETNAME(rom)));
+ fprintf(m_output, " description=\"%s\"", xml_normalize_string(ROM_GETHASHDATA(rom)));
+ if (defaultname == ROM_GETNAME(rom))
+ fprintf(m_output, " default=\"yes\"");
+ fprintf(m_output, "/>\n");
+ }
+}
+
+
+//-------------------------------------------------
+// output_rom - print the roms section of
+// the XML output
+//-------------------------------------------------
+
+void info_xml_creator::output_rom(device_t &device)
+{
+ // iterate over 3 different ROM "types": BIOS, ROMs, DISKs
+ for (int rom_type = 0; rom_type < 3; rom_type++)
+ for (const rom_entry *region = rom_first_region(device); region != nullptr; region = rom_next_region(region))
+ {
+ bool is_disk = ROMREGION_ISDISKDATA(region);
+
+ // disk regions only work for disks
+ if ((is_disk && rom_type != 2) || (!is_disk && rom_type == 2))
+ continue;
+
+ // iterate through ROM entries
+ for (const rom_entry *rom = rom_first_file(region); rom != nullptr; rom = rom_next_file(rom))
+ {
+ bool is_bios = ROM_GETBIOSFLAGS(rom);
+ const char *name = ROM_GETNAME(rom);
+ int offset = ROM_GETOFFSET(rom);
+ const char *merge_name = nullptr;
+ char bios_name[100];
+
+ // BIOS ROMs only apply to bioses
+ if ((is_bios && rom_type != 0) || (!is_bios && rom_type == 0))
+ continue;
+
+ // if we have a valid ROM and we are a clone, see if we can find the parent ROM
+ hash_collection hashes(ROM_GETHASHDATA(rom));
+ if (!hashes.flag(hash_collection::FLAG_NO_DUMP))
+ merge_name = get_merge_name(hashes);
+ if (&device != &m_drivlist.config().root_device())
+ merge_name = nullptr;
+ // scan for a BIOS name
+ bios_name[0] = 0;
+ if (!is_disk && is_bios)
+ {
+ // scan backwards through the ROM entries
+ for (const rom_entry *brom = rom - 1; brom != m_drivlist.driver().rom; brom--)
+ if (ROMENTRY_ISSYSTEM_BIOS(brom))
+ {
+ strcpy(bios_name, ROM_GETNAME(brom));
+ break;
+ }
+ }
+
+ std::ostringstream output;
+
+ // opening tag
+ if (!is_disk)
+ output << "\t\t<rom";
+ else
+ output << "\t\t<disk";
+
+ // add name, merge, bios, and size tags */
+ if (name != nullptr && name[0] != 0)
+ util::stream_format(output, " name=\"%s\"", xml_normalize_string(name));
+ if (merge_name != nullptr)
+ util::stream_format(output, " merge=\"%s\"", xml_normalize_string(merge_name));
+ if (bios_name[0] != 0)
+ util::stream_format(output, " bios=\"%s\"", xml_normalize_string(bios_name));
+ if (!is_disk)
+ util::stream_format(output, " size=\"%d\"", rom_file_size(rom));
+
+ // dump checksum information only if there is a known dump
+ if (!hashes.flag(hash_collection::FLAG_NO_DUMP))
+ {
+ // iterate over hash function types and print m_output their values
+ output << " " << hashes.attribute_string();
+ }
+ else
+ output << " status=\"nodump\"";
+
+ // append a region name
+ util::stream_format(output, " region=\"%s\"", ROMREGION_GETTAG(region));
+
+ // for non-disk entries, print offset
+ if (!is_disk)
+ util::stream_format(output, " offset=\"%x\"", offset);
+
+ // for disk entries, add the disk index
+ else
+ {
+ util::stream_format(output, " index=\"%x\"", DISK_GETINDEX(rom));
+ util::stream_format(output, " writable=\"%s\"", DISK_ISREADONLY(rom) ? "no" : "yes");
+ }
+
+ // add optional flag
+ if (ROM_ISOPTIONAL(rom))
+ output << " optional=\"yes\"";
+
+ output << "/>\n";
+
+ fprintf(m_output, "%s", output.str().c_str());
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// output_sample - print a list of all
+// samples referenced by a game_driver
+//-------------------------------------------------
+
+void info_xml_creator::output_sample(device_t &device)
+{
+ // iterate over sample devices
+ for (samples_device &samples : samples_device_iterator(device))
+ {
+ samples_iterator iter(samples);
+ std::unordered_set<std::string> already_printed;
+ for (const char *samplename = iter.first(); samplename != nullptr; samplename = iter.next())
+ {
+ // filter out duplicates
+ if (!already_printed.insert(samplename).second)
+ continue;
+
+ // output the sample name
+ fprintf(m_output, "\t\t<sample name=\"%s\"/>\n", xml_normalize_string(samplename));
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ output_chips - print a list of CPU and
+ sound chips used by a game
+-------------------------------------------------*/
+
+void info_xml_creator::output_chips(device_t &device, const char *root_tag)
+{
+ // iterate over executable devices
+ for (device_execute_interface &exec : execute_interface_iterator(device))
+ {
+ if (strcmp(exec.device().tag(), device.tag()))
+ {
+ std::string newtag(exec.device().tag()), oldtag(":");
+ newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length());
+
+ fprintf(m_output, "\t\t<chip");
+ fprintf(m_output, " type=\"cpu\"");
+ fprintf(m_output, " tag=\"%s\"", xml_normalize_string(newtag.c_str()));
+ fprintf(m_output, " name=\"%s\"", xml_normalize_string(exec.device().name()));
+ fprintf(m_output, " clock=\"%d\"", exec.device().clock());
+ fprintf(m_output, "/>\n");
+ }
+ }
+
+ // iterate over sound devices
+ for (device_sound_interface &sound : sound_interface_iterator(device))
+ {
+ if (strcmp(sound.device().tag(), device.tag()))
+ {
+ std::string newtag(sound.device().tag()), oldtag(":");
+ newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length());
+
+ fprintf(m_output, "\t\t<chip");
+ fprintf(m_output, " type=\"audio\"");
+ fprintf(m_output, " tag=\"%s\"", xml_normalize_string(newtag.c_str()));
+ fprintf(m_output, " name=\"%s\"", xml_normalize_string(sound.device().name()));
+ if (sound.device().clock() != 0)
+ fprintf(m_output, " clock=\"%d\"", sound.device().clock());
+ fprintf(m_output, "/>\n");
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// output_display - print a list of all the
+// displays
+//-------------------------------------------------
+
+void info_xml_creator::output_display(device_t &device, const char *root_tag)
+{
+ // iterate over screens
+ for (const screen_device &screendev : screen_device_iterator(device))
+ {
+ if (strcmp(screendev.tag(), device.tag()))
+ {
+ std::string newtag(screendev.tag()), oldtag(":");
+ newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length());
+
+ fprintf(m_output, "\t\t<display");
+ fprintf(m_output, " tag=\"%s\"", xml_normalize_string(newtag.c_str()));
+
+ switch (screendev.screen_type())
+ {
+ case SCREEN_TYPE_RASTER: fprintf(m_output, " type=\"raster\""); break;
+ case SCREEN_TYPE_VECTOR: fprintf(m_output, " type=\"vector\""); break;
+ case SCREEN_TYPE_LCD: fprintf(m_output, " type=\"lcd\""); break;
+ default: fprintf(m_output, " type=\"unknown\""); break;
+ }
+
+ // output the orientation as a string
+ switch (m_drivlist.driver().flags & ORIENTATION_MASK)
+ {
+ case ORIENTATION_FLIP_X:
+ fprintf(m_output, " rotate=\"0\" flipx=\"yes\"");
+ break;
+ case ORIENTATION_FLIP_Y:
+ fprintf(m_output, " rotate=\"180\" flipx=\"yes\"");
+ break;
+ case ORIENTATION_FLIP_X|ORIENTATION_FLIP_Y:
+ fprintf(m_output, " rotate=\"180\"");
+ break;
+ case ORIENTATION_SWAP_XY:
+ fprintf(m_output, " rotate=\"90\" flipx=\"yes\"");
+ break;
+ case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_X:
+ fprintf(m_output, " rotate=\"90\"");
+ break;
+ case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_Y:
+ fprintf(m_output, " rotate=\"270\"");
+ break;
+ case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_X|ORIENTATION_FLIP_Y:
+ fprintf(m_output, " rotate=\"270\" flipx=\"yes\"");
+ break;
+ default:
+ fprintf(m_output, " rotate=\"0\"");
+ break;
+ }
+
+ // output width and height only for games that are not vector
+ if (screendev.screen_type() != SCREEN_TYPE_VECTOR)
+ {
+ const rectangle &visarea = screendev.visible_area();
+ fprintf(m_output, " width=\"%d\"", visarea.width());
+ fprintf(m_output, " height=\"%d\"", visarea.height());
+ }
+
+ // output refresh rate
+ fprintf(m_output, " refresh=\"%f\"", ATTOSECONDS_TO_HZ(screendev.refresh_attoseconds()));
+
+ // output raw video parameters only for games that are not vector
+ // and had raw parameters specified
+ if (screendev.screen_type() != SCREEN_TYPE_VECTOR && !screendev.oldstyle_vblank_supplied())
+ {
+ int pixclock = screendev.width() * screendev.height() * ATTOSECONDS_TO_HZ(screendev.refresh_attoseconds());
+
+ fprintf(m_output, " pixclock=\"%d\"", pixclock);
+ fprintf(m_output, " htotal=\"%d\"", screendev.width());
+ fprintf(m_output, " hbend=\"%d\"", screendev.visible_area().min_x);
+ fprintf(m_output, " hbstart=\"%d\"", screendev.visible_area().max_x+1);
+ fprintf(m_output, " vtotal=\"%d\"", screendev.height());
+ fprintf(m_output, " vbend=\"%d\"", screendev.visible_area().min_y);
+ fprintf(m_output, " vbstart=\"%d\"", screendev.visible_area().max_y+1);
+ }
+ fprintf(m_output, " />\n");
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// output_sound - print a list of all the
+// speakers
+//------------------------------------------------
+
+void info_xml_creator::output_sound(device_t &device)
+{
+ speaker_device_iterator spkiter(device);
+ int speakers = spkiter.count();
+
+ // if we have no sound, zero m_output the speaker count
+ sound_interface_iterator snditer(device);
+ if (snditer.first() == nullptr)
+ speakers = 0;
+
+ fprintf(m_output, "\t\t<sound channels=\"%d\"/>\n", speakers);
+}
+
+
+//-------------------------------------------------
+// output_input - print a summary of a game's
+// input
+//-------------------------------------------------
+
+void info_xml_creator::output_input(const ioport_list &portlist)
+{
+ // enumerated list of control types
+ // NOTE: the order is chosen so that 'spare' button inputs are assigned to the
+ // most-likely-correct input device when info is output (you can think of it as
+ // a sort of likelihood order of having buttons)
+ enum
+ {
+ CTRL_DIGITAL_BUTTONS,
+ CTRL_DIGITAL_JOYSTICK,
+ CTRL_ANALOG_JOYSTICK,
+ CTRL_ANALOG_LIGHTGUN,
+ CTRL_ANALOG_DIAL,
+ CTRL_ANALOG_POSITIONAL,
+ CTRL_ANALOG_TRACKBALL,
+ CTRL_ANALOG_MOUSE,
+ CTRL_ANALOG_PADDLE,
+ CTRL_ANALOG_PEDAL,
+ CTRL_DIGITAL_KEYPAD,
+ CTRL_DIGITAL_KEYBOARD,
+ CTRL_DIGITAL_MAHJONG,
+ CTRL_DIGITAL_HANAFUDA,
+ CTRL_DIGITAL_GAMBLING,
+ CTRL_COUNT
+ };
+
+ enum
+ {
+ CTRL_P1,
+ CTRL_P2,
+ CTRL_P3,
+ CTRL_P4,
+ CTRL_P5,
+ CTRL_P6,
+ CTRL_P7,
+ CTRL_P8,
+ CTRL_PCOUNT
+ };
+
+ // directions
+ const UINT8 DIR_UP = 0x01;
+ const UINT8 DIR_DOWN = 0x02;
+ const UINT8 DIR_LEFT = 0x04;
+ const UINT8 DIR_RIGHT = 0x08;
+
+ // initialize the list of control types
+ struct
+ {
+ const char * type; // general type of input
+ int player; // player which the input belongs to
+ int nbuttons; // total number of buttons
+ int maxbuttons; // max index of buttons (using IPT_BUTTONn) [probably to be removed soonish]
+ int ways; // directions for joystick
+ bool analog; // is analog input?
+ UINT8 helper[3]; // for dual joysticks [possibly to be removed soonish]
+ INT32 min; // analog minimum value
+ INT32 max; // analog maximum value
+ INT32 sensitivity; // default analog sensitivity
+ INT32 keydelta; // default analog keydelta
+ bool reverse; // default analog reverse setting
+ } control_info[CTRL_COUNT * CTRL_PCOUNT];
+
+ memset(&control_info, 0, sizeof(control_info));
+
+ // tracking info as we iterate
+ int nplayer = 0;
+ int ncoin = 0;
+ bool service = false;
+ bool tilt = false;
+
+ // iterate over the ports
+ for (ioport_port &port : portlist)
+ {
+ int ctrl_type = CTRL_DIGITAL_BUTTONS;
+ bool ctrl_analog = FALSE;
+ for (ioport_field &field : port.fields())
+ {
+
+ // track the highest player number
+ if (nplayer < field.player() + 1)
+ nplayer = field.player() + 1;
+
+ // switch off of the type
+ switch (field.type())
+ {
+ // map joysticks
+ case IPT_JOYSTICK_UP:
+ ctrl_type = CTRL_DIGITAL_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
+ control_info[field.player() * CTRL_COUNT + ctrl_type].helper[0] |= DIR_UP;
+ break;
+ case IPT_JOYSTICK_DOWN:
+ ctrl_type = CTRL_DIGITAL_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
+ control_info[field.player() * CTRL_COUNT + ctrl_type].helper[0] |= DIR_DOWN;
+ break;
+ case IPT_JOYSTICK_LEFT:
+ ctrl_type = CTRL_DIGITAL_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
+ control_info[field.player() * CTRL_COUNT + ctrl_type].helper[0] |= DIR_LEFT;
+ break;
+ case IPT_JOYSTICK_RIGHT:
+ ctrl_type = CTRL_DIGITAL_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
+ control_info[field.player() * CTRL_COUNT + ctrl_type].helper[0] |= DIR_RIGHT;
+ break;
+
+ case IPT_JOYSTICKLEFT_UP:
+ ctrl_type = CTRL_DIGITAL_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
+ control_info[field.player() * CTRL_COUNT + ctrl_type].helper[1] |= DIR_UP;
+ break;
+ case IPT_JOYSTICKLEFT_DOWN:
+ ctrl_type = CTRL_DIGITAL_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
+ control_info[field.player() * CTRL_COUNT + ctrl_type].helper[1] |= DIR_DOWN;
+ break;
+ case IPT_JOYSTICKLEFT_LEFT:
+ ctrl_type = CTRL_DIGITAL_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
+ control_info[field.player() * CTRL_COUNT + ctrl_type].helper[1] |= DIR_LEFT;
+ break;
+ case IPT_JOYSTICKLEFT_RIGHT:
+ ctrl_type = CTRL_DIGITAL_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
+ control_info[field.player() * CTRL_COUNT + ctrl_type].helper[1] |= DIR_RIGHT;
+ break;
+
+ case IPT_JOYSTICKRIGHT_UP:
+ ctrl_type = CTRL_DIGITAL_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
+ control_info[field.player() * CTRL_COUNT + ctrl_type].helper[2] |= DIR_UP;
+ break;
+ case IPT_JOYSTICKRIGHT_DOWN:
+ ctrl_type = CTRL_DIGITAL_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
+ control_info[field.player() * CTRL_COUNT + ctrl_type].helper[2] |= DIR_DOWN;
+ break;
+ case IPT_JOYSTICKRIGHT_LEFT:
+ ctrl_type = CTRL_DIGITAL_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
+ control_info[field.player() * CTRL_COUNT + ctrl_type].helper[2] |= DIR_LEFT;
+ break;
+ case IPT_JOYSTICKRIGHT_RIGHT:
+ ctrl_type = CTRL_DIGITAL_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
+ control_info[field.player() * CTRL_COUNT + ctrl_type].helper[2] |= DIR_RIGHT;
+ break;
+
+ // map analog inputs
+ case IPT_AD_STICK_X:
+ case IPT_AD_STICK_Y:
+ case IPT_AD_STICK_Z:
+ ctrl_analog = TRUE;
+ ctrl_type = CTRL_ANALOG_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "stick";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].analog = TRUE;
+ break;
+
+ case IPT_PADDLE:
+ case IPT_PADDLE_V:
+ ctrl_analog = TRUE;
+ ctrl_type = CTRL_ANALOG_PADDLE;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "paddle";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].analog = TRUE;
+ break;
+
+ case IPT_PEDAL:
+ case IPT_PEDAL2:
+ case IPT_PEDAL3:
+ ctrl_analog = TRUE;
+ ctrl_type = CTRL_ANALOG_PEDAL;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "pedal";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].analog = TRUE;
+ break;
+
+ case IPT_LIGHTGUN_X:
+ case IPT_LIGHTGUN_Y:
+ ctrl_analog = TRUE;
+ ctrl_type = CTRL_ANALOG_LIGHTGUN;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "lightgun";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].analog = TRUE;
+ break;
+
+ case IPT_POSITIONAL:
+ case IPT_POSITIONAL_V:
+ ctrl_analog = TRUE;
+ ctrl_type = CTRL_ANALOG_POSITIONAL;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "positional";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].analog = TRUE;
+ break;
+
+ case IPT_DIAL:
+ case IPT_DIAL_V:
+ ctrl_analog = TRUE;
+ ctrl_type = CTRL_ANALOG_DIAL;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "dial";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].analog = TRUE;
+ break;
+
+ case IPT_TRACKBALL_X:
+ case IPT_TRACKBALL_Y:
+ ctrl_analog = TRUE;
+ ctrl_type = CTRL_ANALOG_TRACKBALL;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "trackball";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].analog = TRUE;
+ break;
+
+ case IPT_MOUSE_X:
+ case IPT_MOUSE_Y:
+ ctrl_analog = TRUE;
+ ctrl_type = CTRL_ANALOG_MOUSE;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "mouse";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].analog = TRUE;
+ break;
+
+ // map buttons
+ case IPT_BUTTON1:
+ case IPT_BUTTON2:
+ case IPT_BUTTON3:
+ case IPT_BUTTON4:
+ case IPT_BUTTON5:
+ case IPT_BUTTON6:
+ case IPT_BUTTON7:
+ case IPT_BUTTON8:
+ case IPT_BUTTON9:
+ case IPT_BUTTON10:
+ case IPT_BUTTON11:
+ case IPT_BUTTON12:
+ case IPT_BUTTON13:
+ case IPT_BUTTON14:
+ case IPT_BUTTON15:
+ case IPT_BUTTON16:
+ ctrl_analog = FALSE;
+ if (control_info[field.player() * CTRL_COUNT + ctrl_type].type == nullptr)
+ {
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "only_buttons";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].analog = FALSE;
+ }
+ control_info[field.player() * CTRL_COUNT + ctrl_type].maxbuttons = MAX(control_info[field.player() * CTRL_COUNT + ctrl_type].maxbuttons, field.type() - IPT_BUTTON1 + 1);
+ control_info[field.player() * CTRL_COUNT + ctrl_type].nbuttons++;
+ break;
+
+ // track maximum coin index
+ case IPT_COIN1:
+ case IPT_COIN2:
+ case IPT_COIN3:
+ case IPT_COIN4:
+ case IPT_COIN5:
+ case IPT_COIN6:
+ case IPT_COIN7:
+ case IPT_COIN8:
+ ncoin = MAX(ncoin, field.type() - IPT_COIN1 + 1);
+ break;
+
+ // track presence of keypads and keyboards
+ case IPT_KEYPAD:
+ ctrl_type = CTRL_DIGITAL_KEYPAD;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "keypad";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].nbuttons++;
+ break;
+
+ case IPT_KEYBOARD:
+ ctrl_type = CTRL_DIGITAL_KEYBOARD;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "keyboard";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].nbuttons++;
+ break;
+
+ // additional types
+ case IPT_SERVICE:
+ service = true;
+ break;
+
+ case IPT_TILT:
+ tilt = true;
+ break;
+
+ default:
+ if (field.type() > IPT_MAHJONG_FIRST && field.type() < IPT_MAHJONG_LAST)
+ {
+ ctrl_type = CTRL_DIGITAL_MAHJONG;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "mahjong";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].nbuttons++;
+ }
+ else if (field.type() > IPT_HANAFUDA_FIRST && field.type() < IPT_HANAFUDA_LAST)
+ {
+ ctrl_type = CTRL_DIGITAL_HANAFUDA;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "hanafuda";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].nbuttons++;
+ }
+ else if (field.type() > IPT_GAMBLING_FIRST && field.type() < IPT_GAMBLING_LAST)
+ {
+ ctrl_type = CTRL_DIGITAL_GAMBLING;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "gambling";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].nbuttons++;
+ }
+ break;
+ }
+
+ if (ctrl_analog)
+ {
+ // get the analog stats
+ if (field.minval() != 0)
+ control_info[field.player() * CTRL_COUNT + ctrl_type].min = field.minval();
+ if (field.maxval() != 0)
+ control_info[field.player() * CTRL_COUNT + ctrl_type].max = field.maxval();
+ if (field.sensitivity() != 0)
+ control_info[field.player() * CTRL_COUNT + ctrl_type].sensitivity = field.sensitivity();
+ if (field.delta() != 0)
+ control_info[field.player() * CTRL_COUNT + ctrl_type].keydelta = field.delta();
+ if (field.analog_reverse() != 0)
+ control_info[field.player() * CTRL_COUNT + ctrl_type].reverse = TRUE;
+ }
+ }
+ }
+
+ // Clean-up those entries, if any, where buttons were defined in a separate port than the actual controller they belong to.
+ // This is quite often the case, especially for arcades where controls can be easily mapped to separate input ports on PCB.
+ // If such situation would only happen for joystick, it would be possible to work it around by initializing differently
+ // ctrl_type above, but it is quite common among analog inputs as well (for instance, this is the tipical situation
+ // for lightguns) and therefore we really need this separate loop.
+ for (int i = 0; i < CTRL_PCOUNT; i++)
+ {
+ bool fix_done = FALSE;
+ for (int j = 1; j < CTRL_COUNT; j++)
+ if (control_info[i * CTRL_COUNT].type != nullptr && control_info[i * CTRL_COUNT + j].type != nullptr && !fix_done)
+ {
+ control_info[i * CTRL_COUNT + j].nbuttons += control_info[i * CTRL_COUNT].nbuttons;
+ control_info[i * CTRL_COUNT + j].maxbuttons = MAX(control_info[i * CTRL_COUNT + j].maxbuttons, control_info[i * CTRL_COUNT].maxbuttons);
+
+ memset(&control_info[i * CTRL_COUNT], 0, sizeof(control_info[0]));
+ fix_done = TRUE;
+ }
+ }
+
+ // Output the input info
+ // First basic info
+ fprintf(m_output, "\t\t<input");
+ fprintf(m_output, " players=\"%d\"", nplayer);
+ if (ncoin != 0)
+ fprintf(m_output, " coins=\"%d\"", ncoin);
+ if (service)
+ fprintf(m_output, " service=\"yes\"");
+ if (tilt)
+ fprintf(m_output, " tilt=\"yes\"");
+ fprintf(m_output, ">\n");
+
+ // Then controller specific ones
+ for (auto & elem : control_info)
+ if (elem.type != nullptr)
+ {
+ //printf("type %s - player %d - buttons %d\n", elem.type, elem.player, elem.nbuttons);
+ if (elem.analog)
+ {
+ fprintf(m_output, "\t\t\t<control type=\"%s\"", xml_normalize_string(elem.type));
+ if (nplayer > 1)
+ fprintf(m_output, " player=\"%d\"", elem.player);
+ if (elem.nbuttons > 0)
+ fprintf(m_output, " buttons=\"%d\"", strcmp(elem.type, "stick") ? elem.nbuttons : elem.maxbuttons);
+ if (elem.min != 0 || elem.max != 0)
+ {
+ fprintf(m_output, " minimum=\"%d\"", elem.min);
+ fprintf(m_output, " maximum=\"%d\"", elem.max);
+ }
+ if (elem.sensitivity != 0)
+ fprintf(m_output, " sensitivity=\"%d\"", elem.sensitivity);
+ if (elem.keydelta != 0)
+ fprintf(m_output, " keydelta=\"%d\"", elem.keydelta);
+ if (elem.reverse)
+ fprintf(m_output, " reverse=\"yes\"");
+
+ fprintf(m_output, "/>\n");
+ }
+ else
+ {
+ if (elem.helper[1] == 0 && elem.helper[2] != 0) { elem.helper[1] = elem.helper[2]; elem.helper[2] = 0; }
+ if (elem.helper[0] == 0 && elem.helper[1] != 0) { elem.helper[0] = elem.helper[1]; elem.helper[1] = 0; }
+ if (elem.helper[1] == 0 && elem.helper[2] != 0) { elem.helper[1] = elem.helper[2]; elem.helper[2] = 0; }
+ const char *joys = (elem.helper[2] != 0) ? "triple" : (elem.helper[1] != 0) ? "double" : "";
+ fprintf(m_output, "\t\t\t<control type=\"%s%s\"", joys, xml_normalize_string(elem.type));
+ if (nplayer > 1)
+ fprintf(m_output, " player=\"%d\"", elem.player);
+ if (elem.nbuttons > 0)
+ fprintf(m_output, " buttons=\"%d\"", strcmp(elem.type, "joy") ? elem.nbuttons : elem.maxbuttons);
+ for (int lp = 0; lp < 3 && elem.helper[lp] != 0; lp++)
+ {
+ const char *plural = (lp==2) ? "3" : (lp==1) ? "2" : "";
+ const char *ways;
+ std::string helper;
+ switch (elem.helper[lp] & (DIR_UP | DIR_DOWN | DIR_LEFT | DIR_RIGHT))
+ {
+ case DIR_UP | DIR_DOWN | DIR_LEFT | DIR_RIGHT:
+ helper = string_format("%d", (elem.ways == 0) ? 8 : elem.ways);
+ ways = helper.c_str();
+ break;
+ case DIR_LEFT | DIR_RIGHT:
+ ways = "2";
+ break;
+ case DIR_UP | DIR_DOWN:
+ ways = "vertical2";
+ break;
+ case DIR_UP:
+ case DIR_DOWN:
+ case DIR_LEFT:
+ case DIR_RIGHT:
+ ways = "1";
+ break;
+ case DIR_UP | DIR_DOWN | DIR_LEFT:
+ case DIR_UP | DIR_DOWN | DIR_RIGHT:
+ case DIR_UP | DIR_LEFT | DIR_RIGHT:
+ case DIR_DOWN | DIR_LEFT | DIR_RIGHT:
+ ways = (elem.ways == 4) ? "3 (half4)" : "5 (half8)";
+ break;
+ default:
+ ways = "strange2";
+ break;
+ }
+ fprintf(m_output, " ways%s=\"%s\"", plural, ways);
+ }
+ fprintf(m_output, "/>\n");
+ }
+ }
+
+ fprintf(m_output, "\t\t</input>\n");
+}
+
+
+//-------------------------------------------------
+// output_switches - print the configurations or
+// DIP switch settings
+//-------------------------------------------------
+
+void info_xml_creator::output_switches(const ioport_list &portlist, const char *root_tag, int type, const char *outertag, const char *innertag)
+{
+ // iterate looking for DIP switches
+ for (ioport_port &port : portlist)
+ for (ioport_field &field : port.fields())
+ if (field.type() == type)
+ {
+ std::ostringstream output;
+
+ std::string newtag(port.tag()), oldtag(":");
+ newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length());
+
+ // output the switch name information
+ std::string normalized_field_name(xml_normalize_string(field.name()));
+ std::string normalized_newtag(xml_normalize_string(newtag.c_str()));
+ util::stream_format(output,"\t\t<%s name=\"%s\" tag=\"%s\" mask=\"%u\">\n", outertag, normalized_field_name.c_str(), normalized_newtag.c_str(), field.mask());
+
+ // loop over settings
+ for (ioport_setting &setting : field.settings())
+ {
+ util::stream_format(output,"\t\t\t<%s name=\"%s\" value=\"%u\"%s/>\n", innertag, xml_normalize_string(setting.name()), setting.value(), setting.value() == field.defvalue() ? " default=\"yes\"" : "");
+ }
+
+ // terminate the switch entry
+ util::stream_format(output,"\t\t</%s>\n", outertag);
+
+ fprintf(m_output, "%s", output.str().c_str());
+ }
+}
+
+//-------------------------------------------------
+// output_ports - print the structure of input
+// ports in the driver
+//-------------------------------------------------
+void info_xml_creator::output_ports(const ioport_list &portlist)
+{
+ // cycle through ports
+ for (ioport_port &port : portlist)
+ {
+ fprintf(m_output,"\t\t<port tag=\"%s\">\n", xml_normalize_string(port.tag()));
+ for (ioport_field &field : port.fields())
+ {
+ if(field.is_analog())
+ fprintf(m_output,"\t\t\t<analog mask=\"%u\"/>\n", field.mask());
+ }
+ // close element
+ fprintf(m_output,"\t\t</port>\n");
+ }
+
+}
+
+//-------------------------------------------------
+// output_adjusters - print the Analog
+// Adjusters for a game
+//-------------------------------------------------
+
+void info_xml_creator::output_adjusters(const ioport_list &portlist)
+{
+ // iterate looking for Adjusters
+ for (ioport_port &port : portlist)
+ for (ioport_field &field : port.fields())
+ if (field.type() == IPT_ADJUSTER)
+ fprintf(m_output, "\t\t<adjuster name=\"%s\" default=\"%d\"/>\n", xml_normalize_string(field.name()), field.defvalue());
+}
+
+
+//-------------------------------------------------
+// output_driver - print driver status
+//-------------------------------------------------
+
+void info_xml_creator::output_driver()
+{
+ fprintf(m_output, "\t\t<driver");
+
+ /* The status entry is an hint for frontend authors */
+ /* to select working and not working games without */
+ /* the need to know all the other status entries. */
+ /* Games marked as status=good are perfectly emulated, games */
+ /* marked as status=imperfect are emulated with only */
+ /* some minor issues, games marked as status=preliminary */
+ /* don't work or have major emulation problems. */
+
+ if (m_drivlist.driver().flags & (MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION | MACHINE_NO_SOUND | MACHINE_WRONG_COLORS | MACHINE_MECHANICAL))
+ fprintf(m_output, " status=\"preliminary\"");
+ else if (m_drivlist.driver().flags & (MACHINE_IMPERFECT_COLORS | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS))
+ fprintf(m_output, " status=\"imperfect\"");
+ else
+ fprintf(m_output, " status=\"good\"");
+
+ if (m_drivlist.driver().flags & MACHINE_NOT_WORKING)
+ fprintf(m_output, " emulation=\"preliminary\"");
+ else
+ fprintf(m_output, " emulation=\"good\"");
+
+ if (m_drivlist.driver().flags & MACHINE_WRONG_COLORS)
+ fprintf(m_output, " color=\"preliminary\"");
+ else if (m_drivlist.driver().flags & MACHINE_IMPERFECT_COLORS)
+ fprintf(m_output, " color=\"imperfect\"");
+ else
+ fprintf(m_output, " color=\"good\"");
+
+ if (m_drivlist.driver().flags & MACHINE_NO_SOUND)
+ fprintf(m_output, " sound=\"preliminary\"");
+ else if (m_drivlist.driver().flags & MACHINE_IMPERFECT_SOUND)
+ fprintf(m_output, " sound=\"imperfect\"");
+ else
+ fprintf(m_output, " sound=\"good\"");
+
+ if (m_drivlist.driver().flags & MACHINE_IMPERFECT_GRAPHICS)
+ fprintf(m_output, " graphic=\"imperfect\"");
+ else
+ fprintf(m_output, " graphic=\"good\"");
+
+ if (m_drivlist.driver().flags & MACHINE_NO_COCKTAIL)
+ fprintf(m_output, " cocktail=\"preliminary\"");
+
+ if (m_drivlist.driver().flags & MACHINE_UNEMULATED_PROTECTION)
+ fprintf(m_output, " protection=\"preliminary\"");
+
+ if (m_drivlist.driver().flags & MACHINE_SUPPORTS_SAVE)
+ fprintf(m_output, " savestate=\"supported\"");
+ else
+ fprintf(m_output, " savestate=\"unsupported\"");
+
+ fprintf(m_output, "/>\n");
+}
+
+
+//-------------------------------------------------
+// output_images - prints m_output all info on
+// image devices
+//-------------------------------------------------
+
+void info_xml_creator::output_images(device_t &device, const char *root_tag)
+{
+ for (const device_image_interface &imagedev : image_interface_iterator(device))
+ {
+ if (strcmp(imagedev.device().tag(), device.tag()))
+ {
+ bool loadable = imagedev.user_loadable();
+ std::string newtag(imagedev.device().tag()), oldtag(":");
+ newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length());
+
+ // print m_output device type
+ fprintf(m_output, "\t\t<device type=\"%s\"", xml_normalize_string(imagedev.image_type_name()));
+
+ // does this device have a tag?
+ if (imagedev.device().tag())
+ fprintf(m_output, " tag=\"%s\"", xml_normalize_string(newtag.c_str()));
+
+ // is this device available as media switch?
+ if (!loadable)
+ fprintf(m_output, " fixed_image=\"1\"");
+
+ // is this device mandatory?
+ if (imagedev.must_be_loaded())
+ fprintf(m_output, " mandatory=\"1\"");
+
+ if (imagedev.image_interface() && imagedev.image_interface()[0])
+ fprintf(m_output, " interface=\"%s\"", xml_normalize_string(imagedev.image_interface()));
+
+ // close the XML tag
+ fprintf(m_output, ">\n");
+
+ if (loadable)
+ {
+ const char *name = imagedev.instance_name();
+ const char *shortname = imagedev.brief_instance_name();
+
+ fprintf(m_output, "\t\t\t<instance");
+ fprintf(m_output, " name=\"%s\"", xml_normalize_string(name));
+ fprintf(m_output, " briefname=\"%s\"", xml_normalize_string(shortname));
+ fprintf(m_output, "/>\n");
+
+ std::string extensions(imagedev.file_extensions());
+
+ char *ext = strtok((char *)extensions.c_str(), ",");
+ while (ext != nullptr)
+ {
+ fprintf(m_output, "\t\t\t<extension");
+ fprintf(m_output, " name=\"%s\"", xml_normalize_string(ext));
+ fprintf(m_output, "/>\n");
+ ext = strtok(nullptr, ",");
+ }
+ }
+ fprintf(m_output, "\t\t</device>\n");
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// output_images - prints all info about slots
+//-------------------------------------------------
+
+void info_xml_creator::output_slots(device_t &device, const char *root_tag)
+{
+ for (const device_slot_interface &slot : slot_interface_iterator(device))
+ {
+ if (slot.fixed()) continue; // or shall we list these as non-configurable?
+
+ if (strcmp(slot.device().tag(), device.tag()))
+ {
+ std::string newtag(slot.device().tag()), oldtag(":");
+ newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length());
+
+ // print m_output device type
+ fprintf(m_output, "\t\t<slot name=\"%s\">\n", xml_normalize_string(newtag.c_str()));
+
+ /*
+ if (slot.slot_interface()[0])
+ fprintf(m_output, " interface=\"%s\"", xml_normalize_string(slot.slot_interface()));
+ */
+
+ for (const device_slot_option &option : slot.option_list())
+ {
+ if (option.selectable())
+ {
+ device_t *dev = const_cast<machine_config &>(m_drivlist.config()).device_add(&m_drivlist.config().root_device(), "dummy", option.devtype(), 0);
+ if (!dev->configured())
+ dev->config_complete();
+
+ fprintf(m_output, "\t\t\t<slotoption");
+ fprintf(m_output, " name=\"%s\"", xml_normalize_string(option.name()));
+ fprintf(m_output, " devname=\"%s\"", xml_normalize_string(dev->shortname()));
+ if (slot.default_option() != nullptr && strcmp(slot.default_option(),option.name())==0)
+ fprintf(m_output, " default=\"yes\"");
+ fprintf(m_output, "/>\n");
+ const_cast<machine_config &>(m_drivlist.config()).device_remove(&m_drivlist.config().root_device(), "dummy");
+ }
+ }
+
+ fprintf(m_output, "\t\t</slot>\n");
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// output_software_list - print the information
+// for all known software lists for this system
+//-------------------------------------------------
+
+void info_xml_creator::output_software_list()
+{
+ for (const software_list_device &swlist : software_list_device_iterator(m_drivlist.config().root_device()))
+ {
+ fprintf(m_output, "\t\t<softwarelist name=\"%s\" ", swlist.list_name());
+ fprintf(m_output, "status=\"%s\" ", (swlist.list_type() == SOFTWARE_LIST_ORIGINAL_SYSTEM) ? "original" : "compatible");
+ if (swlist.filter())
+ fprintf(m_output, "filter=\"%s\" ", swlist.filter());
+ fprintf(m_output, "/>\n");
+ }
+}
+
+
+
+//-------------------------------------------------
+// output_ramoptions - prints m_output all RAM
+// options for this system
+//-------------------------------------------------
+
+void info_xml_creator::output_ramoptions()
+{
+ for (const ram_device &ram : ram_device_iterator(m_drivlist.config().root_device()))
+ {
+ fprintf(m_output, "\t\t<ramoption default=\"1\">%u</ramoption>\n", ram.default_size());
+
+ if (ram.extra_options() != nullptr)
+ {
+ std::string options(ram.extra_options());
+ for (int start = 0, end = options.find_first_of(',');; start = end + 1, end = options.find_first_of(',', start))
+ {
+ std::string option;
+ option.assign(options.substr(start, (end == -1) ? -1 : end - start));
+ fprintf(m_output, "\t\t<ramoption>%u</ramoption>\n", ram_device::parse_string(option.c_str()));
+ if (end == -1)
+ break;
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// get_merge_name - get the rom name from a
+// parent set
+//-------------------------------------------------
+
+const char *info_xml_creator::get_merge_name(const hash_collection &romhashes)
+{
+ // walk the parent chain
+ const char *merge_name = nullptr;
+ for (int clone_of = m_drivlist.find(m_drivlist.driver().parent); clone_of != -1; clone_of = m_drivlist.find(m_drivlist.driver(clone_of).parent))
+ {
+ // look in the parent's ROMs
+ device_t *device = &m_drivlist.config(clone_of, m_lookup_options).root_device();
+ for (const rom_entry *pregion = rom_first_region(*device); pregion != nullptr; pregion = rom_next_region(pregion))
+ for (const rom_entry *prom = rom_first_file(pregion); prom != nullptr; prom = rom_next_file(prom))
+ {
+ hash_collection phashes(ROM_GETHASHDATA(prom));
+ if (!phashes.flag(hash_collection::FLAG_NO_DUMP) && romhashes == phashes)
+ {
+ // stop when we find a match
+ merge_name = ROM_GETNAME(prom);
+ break;
+ }
+ }
+ }
+
+ return merge_name;
+}
diff --git a/src/frontend/mame/info.h b/src/frontend/mame/info.h
new file mode 100644
index 00000000000..78082ec033b
--- /dev/null
+++ b/src/frontend/mame/info.h
@@ -0,0 +1,68 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+/***************************************************************************
+
+ info.h
+
+ Dumps the MAME internal data as an XML file.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __INFO_H__
+#define __INFO_H__
+
+#include "drivenum.h"
+
+
+//**************************************************************************
+// FUNCTION PROTOTYPES
+//**************************************************************************
+
+// helper class to putput
+class info_xml_creator
+{
+public:
+ // construction/destruction
+ info_xml_creator(driver_enumerator &drivlist);
+
+ // output
+ void output(FILE *out, bool nodevices = false);
+
+private:
+ // internal helper
+ void output_one();
+ void output_sampleof();
+ void output_bios();
+ void output_rom(device_t &device);
+ void output_device_roms();
+ void output_sample(device_t &device);
+ void output_chips(device_t &device, const char *root_tag);
+ void output_display(device_t &device, const char *root_tag);
+ void output_sound(device_t &device);
+ void output_input(const ioport_list &portlist);
+ void output_switches(const ioport_list &portlist, const char *root_tag, int type, const char *outertag, const char *innertag);
+ void output_ports(const ioport_list &portlist);
+ void output_adjusters(const ioport_list &portlist);
+ void output_driver();
+ void output_images(device_t &device, const char *root_tag);
+ void output_slots(device_t &device, const char *root_tag);
+ void output_software_list();
+ void output_ramoptions();
+
+ void output_one_device(device_t &device, const char *devtag);
+ void output_devices();
+
+ const char *get_merge_name(const hash_collection &romhashes);
+
+ // internal state
+ FILE * m_output;
+ driver_enumerator & m_drivlist;
+ emu_options m_lookup_options;
+
+ static const char s_dtd_string[];
+};
+
+
+#endif /* __INFO_H__ */
diff --git a/src/frontend/mame/language.cpp b/src/frontend/mame/language.cpp
new file mode 100644
index 00000000000..5c9686a646e
--- /dev/null
+++ b/src/frontend/mame/language.cpp
@@ -0,0 +1,79 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/***************************************************************************
+
+ language.cpp
+
+ Multi-language support.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "emuopts.h"
+
+static std::unordered_map<std::string, std::string> g_translation;
+
+const char *lang_translate(const char *word)
+{
+ if (g_translation.find(word) == g_translation.end())
+ {
+ return word;
+ }
+ return g_translation[word].c_str();
+}
+
+const UINT32 MO_MAGIC = 0x950412de;
+const UINT32 MO_MAGIC_REVERSED = 0xde120495;
+
+inline UINT32 endianchange(UINT32 value) {
+ UINT32 b0 = (value >> 0) & 0xff;
+ UINT32 b1 = (value >> 8) & 0xff;
+ UINT32 b2 = (value >> 16) & 0xff;
+ UINT32 b3 = (value >> 24) & 0xff;
+
+ return (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
+}
+
+void load_translation(emu_options &m_options)
+{
+ g_translation.clear();
+ emu_file file(m_options.language_path(), OPEN_FLAG_READ);
+ auto name = std::string(m_options.language());
+ strreplace(name, " ", "_");
+ strreplace(name, "(", "");
+ strreplace(name, ")", "");
+ if (file.open(name.c_str(), PATH_SEPARATOR "strings.mo") == osd_file::error::NONE)
+ {
+ UINT64 size = file.size();
+ UINT32 *buffer = global_alloc_array(UINT32, size / 4 + 1);
+ file.read(buffer, size);
+ file.close();
+
+ if (buffer[0] != MO_MAGIC && buffer[0] != MO_MAGIC_REVERSED)
+ {
+ global_free_array(buffer);
+ return;
+ }
+ if (buffer[0] == MO_MAGIC_REVERSED)
+ {
+ for (auto i = 0; i < (size / 4) + 1; ++i)
+ {
+ buffer[i] = endianchange(buffer[i]);
+ }
+ }
+
+ UINT32 number_of_strings = buffer[2];
+ UINT32 original_table_offset = buffer[3] >> 2;
+ UINT32 translation_table_offset = buffer[4] >> 2;
+
+ const char *data = reinterpret_cast<const char*>(buffer);
+
+ for (auto i = 1; i < number_of_strings; ++i)
+ {
+ std::string original = (const char *)data + buffer[original_table_offset + 2 * i + 1];
+ std::string translation = (const char *)data + buffer[translation_table_offset + 2 * i + 1];
+ g_translation.insert(std::pair<std::string, std::string>(original, translation));
+ }
+ global_free_array(buffer);
+ }
+}
diff --git a/src/frontend/mame/language.h b/src/frontend/mame/language.h
new file mode 100644
index 00000000000..2a9d934576b
--- /dev/null
+++ b/src/frontend/mame/language.h
@@ -0,0 +1,31 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/***************************************************************************
+
+ language.h
+
+ Multi-language support.
+
+***************************************************************************/
+#pragma once
+
+#ifndef __EMU_H__
+#error Dont include this file directly; include emu.h instead.
+#endif
+
+#ifndef __LANGUAGE_H__
+#define __LANGUAGE_H__
+
+//**************************************************************************
+// LOCALIZATION SUPPORT
+//**************************************************************************
+
+#define _(param) lang_translate(param)
+// Fake one to make possible using it in static text definitions, on those
+// lang_translate must be called afterwards
+#define __(param) param
+
+void load_translation(emu_options &option);
+const char *lang_translate(const char *word);
+
+#endif /*__LANGUAGE_H__*/
diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp
new file mode 100644
index 00000000000..b8d8644218a
--- /dev/null
+++ b/src/frontend/mame/luaengine.cpp
@@ -0,0 +1,2623 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic,Luca Bruno
+/***************************************************************************
+
+ luaengine.c
+
+ Controls execution of the core MAME system.
+
+***************************************************************************/
+
+#include <limits>
+#include <thread>
+#include <lua.hpp>
+#include "luabridge/Source/LuaBridge/LuaBridge.h"
+#include <signal.h>
+#include "emu.h"
+#include "mame.h"
+#include "cheat.h"
+#include "drivenum.h"
+#include "emuopts.h"
+#include "ui/ui.h"
+#include "luaengine.h"
+#include <mutex>
+
+#ifdef __clang__
+#pragma clang diagnostic ignored "-Wshift-count-overflow"
+#endif
+//**************************************************************************
+// LUA ENGINE
+//**************************************************************************
+
+#if !defined(LUA_PROMPT)
+#define LUA_PROMPT "> "
+#define LUA_PROMPT2 ">> "
+#endif
+
+#if !defined(LUA_MAXINPUT)
+#define LUA_MAXINPUT 512
+#endif
+
+#define lua_readline(b,p) \
+ (fputs(p, stdout), fflush(stdout), /* show prompt */ \
+ fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */
+
+static lua_State *globalL = nullptr;
+
+#define luai_writestring(s,l) fwrite((s), sizeof(char), (l), stdout)
+#define luai_writeline() (luai_writestring("\n", 1), fflush(stdout))
+
+const char *const lua_engine::tname_ioport = "lua.ioport";
+lua_engine* lua_engine::luaThis = nullptr;
+
+extern "C" {
+ int luaopen_lsqlite3(lua_State *L);
+ int luaopen_zlib(lua_State *L);
+ int luaopen_lfs(lua_State *L);
+}
+
+static void lstop(lua_State *L, lua_Debug *ar)
+{
+ (void)ar; /* unused arg. */
+ lua_sethook(L, nullptr, 0, 0);
+ luaL_error(L, "interrupted!");
+}
+
+
+static void laction(int i)
+{
+ signal(i, SIG_DFL); /* if another SIGINT happens before lstop,
+ terminate process (default action) */
+ lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
+}
+
+int lua_engine::report(int status) {
+ if (status != LUA_OK && !lua_isnil(m_lua_state, -1))
+ {
+ const char *msg = lua_tostring(m_lua_state, -1);
+ if (msg == nullptr) msg = "(error object is not a string)";
+ lua_writestringerror("%s\n", msg);
+ lua_pop(m_lua_state, 1);
+ /* force a complete garbage collection in case of errors */
+ lua_gc(m_lua_state, LUA_GCCOLLECT, 0);
+ }
+ return status;
+}
+
+
+static int traceback (lua_State *L)
+{
+ const char *msg = lua_tostring(L, 1);
+ if (msg)
+ luaL_traceback(L, L, msg, 1);
+ else if (!lua_isnoneornil(L, 1))
+ { /* is there an error object? */
+ if (!luaL_callmeta(L, 1, "__tostring")) /* try its 'tostring' metamethod */
+ lua_pushliteral(L, "(no error message)");
+ }
+ return 1;
+}
+
+
+int lua_engine::docall(int narg, int nres)
+{
+ int status;
+ int base = lua_gettop(m_lua_state) - narg; /* function index */
+ lua_pushcfunction(m_lua_state, traceback); /* push traceback function */
+ lua_insert(m_lua_state, base); /* put it under chunk and args */
+ globalL = m_lua_state; /* to be available to 'laction' */
+ signal(SIGINT, laction);
+ status = lua_pcall(m_lua_state, narg, nres, base);
+ signal(SIGINT, SIG_DFL);
+ lua_remove(m_lua_state, base); /* remove traceback function */
+ return status;
+}
+
+namespace luabridge
+{
+template <>
+struct Stack <osd_file::error>
+{
+ static void push(lua_State *L, osd_file::error error)
+ {
+ std::string strerror;
+ switch(error)
+ {
+ case osd_file::error::NONE:
+ lua_pushboolean(L, false);
+ return;
+ case osd_file::error::FAILURE:
+ strerror = "failure";
+ break;
+ case osd_file::error::OUT_OF_MEMORY:
+ strerror = "out_of_memory";
+ break;
+ case osd_file::error::NOT_FOUND:
+ strerror = "not_found";
+ break;
+ case osd_file::error::ACCESS_DENIED:
+ strerror = "access_denied";
+ break;
+ case osd_file::error::ALREADY_OPEN:
+ strerror = "already_open";
+ break;
+ case osd_file::error::TOO_MANY_FILES:
+ strerror = "too_many_files";
+ break;
+ case osd_file::error::INVALID_DATA:
+ strerror = "invalid_data";
+ break;
+ case osd_file::error::INVALID_ACCESS:
+ strerror = "invalid_access";
+ break;
+ default:
+ strerror = "unknown_error";
+ break;
+ }
+ lua_pushstring(L, strerror.c_str());
+ }
+};
+template <>
+struct Stack <map_handler_type>
+{
+ static void push(lua_State *L, map_handler_type error)
+ {
+ std::string type;
+ switch(error)
+ {
+ case AMH_NONE:
+ type = "none";
+ break;
+ case AMH_RAM:
+ type = "ram";
+ break;
+ case AMH_ROM:
+ type = "rom";
+ break;
+ case AMH_NOP:
+ type = "nop";
+ break;
+ case AMH_UNMAP:
+ type = "unmap";
+ break;
+ case AMH_DEVICE_DELEGATE:
+ type = "delegate";
+ break;
+ case AMH_PORT:
+ type = "port";
+ break;
+ case AMH_BANK:
+ type = "bank";
+ break;
+ case AMH_DEVICE_SUBMAP:
+ type = "submap";
+ break;
+ default:
+ type = "unknown";
+ break;
+ }
+ lua_pushstring(L, type.c_str());
+ }
+};
+}
+/* mark in error messages for incomplete statements */
+#define EOFMARK "<eof>"
+#define marklen (sizeof(EOFMARK)/sizeof(char) - 1)
+
+int lua_engine::incomplete(int status)
+{
+ if (status == LUA_ERRSYNTAX)
+ {
+ size_t lmsg;
+ const char *msg = lua_tolstring(m_lua_state, -1, &lmsg);
+ if (lmsg >= marklen && strcmp(msg + lmsg - marklen, EOFMARK) == 0)
+ {
+ lua_pop(m_lua_state, 1);
+ return 1;
+ }
+ }
+ return 0; /* else... */
+}
+
+lua_engine::hook::hook()
+{
+ L = nullptr;
+ cb = -1;
+}
+
+void lua_engine::hook::set(lua_State *lua, int idx)
+{
+ if (L)
+ luaL_unref(L, LUA_REGISTRYINDEX, cb);
+
+ if (lua_isnil(lua, idx)) {
+ L = nullptr;
+ cb = -1;
+
+ } else {
+ L = lua;
+ lua_pushvalue(lua, idx);
+ cb = luaL_ref(lua, LUA_REGISTRYINDEX);
+ }
+}
+
+lua_State *lua_engine::hook::precall()
+{
+ lua_State *T = lua_newthread(L);
+ lua_rawgeti(T, LUA_REGISTRYINDEX, cb);
+ return T;
+}
+
+void lua_engine::hook::call(lua_engine *engine, lua_State *T, int nparam)
+{
+ engine->resume(T, nparam, L);
+}
+
+void lua_engine::resume(lua_State *L, int nparam, lua_State *root)
+{
+ int s = lua_resume(L, nullptr, nparam);
+ switch(s) {
+ case LUA_OK:
+ if(!root) {
+ std::map<lua_State *, std::pair<lua_State *, int> >::iterator i = thread_registry.find(L);
+ if(i != thread_registry.end()) {
+ luaL_unref(i->second.first, LUA_REGISTRYINDEX, i->second.second);
+ thread_registry.erase(i);
+ }
+ } else
+ lua_pop(root, 1);
+ break;
+
+ case LUA_YIELD:
+ if(root) {
+ int id = luaL_ref(root, LUA_REGISTRYINDEX);
+ thread_registry[L] = std::pair<lua_State *, int>(root, id);
+ }
+ break;
+
+ default:
+ osd_printf_error("[LUA ERROR] %s\n", lua_tostring(L, -1));
+ lua_pop(L, 1);
+ break;
+ }
+}
+
+void lua_engine::resume(void *lua, INT32 param)
+{
+ resume(static_cast<lua_State *>(lua));
+}
+
+int lua_engine::l_ioport_write(lua_State *L)
+{
+ ioport_field *field = static_cast<ioport_field *>(getparam(L, 1, tname_ioport));
+ luaL_argcheck(L, lua_isnumber(L, 2), 2, "value expected");
+ field->set_value(lua_tointeger(L, 2));
+ return 0;
+}
+
+//-------------------------------------------------
+// emu_app_name - return application name
+//-------------------------------------------------
+
+int lua_engine::l_emu_app_name(lua_State *L)
+{
+ lua_pushstring(L, emulator_info::get_appname_lower());
+ return 1;
+}
+
+//-------------------------------------------------
+// emu_app_version - return application version
+//-------------------------------------------------
+
+int lua_engine::l_emu_app_version(lua_State *L)
+{
+ lua_pushstring(L, bare_build_version);
+ return 1;
+}
+
+
+//-------------------------------------------------
+// emu_gamename - returns game full name
+//-------------------------------------------------
+
+int lua_engine::l_emu_gamename(lua_State *L)
+{
+ lua_pushstring(L, luaThis->machine().system().description);
+ return 1;
+}
+
+//-------------------------------------------------
+// emu_romname - returns rom base name
+//-------------------------------------------------
+
+int lua_engine::l_emu_romname(lua_State *L)
+{
+ lua_pushstring(L, luaThis->machine().basename());
+ return 1;
+}
+
+//-------------------------------------------------
+// emu_softname - returns softlist name
+//-------------------------------------------------
+
+int lua_engine::l_emu_softname(lua_State *L)
+{
+ lua_pushstring(L, luaThis->machine().options().software_name());
+ return 1;
+}
+
+//-------------------------------------------------
+// emu_pause/emu_unpause - pause/unpause game
+//-------------------------------------------------
+
+int lua_engine::l_emu_pause(lua_State *L)
+{
+ luaThis->machine().pause();
+ return 0;
+}
+
+int lua_engine::l_emu_unpause(lua_State *L)
+{
+ luaThis->machine().resume();
+ return 0;
+}
+
+//-------------------------------------------------
+// emu_keypost - post keys to natural keyboard
+//-------------------------------------------------
+
+int lua_engine::l_emu_keypost(lua_State *L)
+{
+ const char *keys = luaL_checkstring(L,1);
+ luaThis->machine().ioport().natkeyboard().post_utf8(keys);
+ return 1;
+}
+
+int lua_engine::l_emu_time(lua_State *L)
+{
+ lua_pushnumber(L, luaThis->machine().time().as_double());
+ return 1;
+}
+
+void lua_engine::emu_after_done(void *_h, INT32 param)
+{
+ hook *h = static_cast<hook *>(_h);
+ h->call(this, h->precall(), 0);
+ delete h;
+}
+
+int lua_engine::emu_after(lua_State *L)
+{
+ luaL_argcheck(L, lua_isnumber(L, 1), 1, "waiting duration expected");
+ struct hook *h = new hook;
+ h->set(L, 2);
+ machine().scheduler().timer_set(attotime::from_double(lua_tonumber(L, 1)), timer_expired_delegate(FUNC(lua_engine::emu_after_done), this), 0, h);
+ return 0;
+}
+
+int lua_engine::l_emu_after(lua_State *L)
+{
+ return luaThis->emu_after(L);
+}
+
+int lua_engine::emu_wait(lua_State *L)
+{
+ luaL_argcheck(L, lua_isnumber(L, 1), 1, "waiting duration expected");
+ machine().scheduler().timer_set(attotime::from_double(lua_tonumber(L, 1)), timer_expired_delegate(FUNC(lua_engine::resume), this), 0, L);
+ return lua_yieldk(L, 0, 0, nullptr);
+}
+
+int lua_engine::l_emu_wait(lua_State *L)
+{
+ return luaThis->emu_wait(L);
+}
+
+void lua_engine::output_notifier(const char *outname, INT32 value)
+{
+ if (hook_output_cb.active()) {
+ lua_State *L = hook_output_cb.precall();
+ lua_pushstring(L, outname);
+ lua_pushnumber(L, value);
+ hook_output_cb.call(this, L, 2);
+ }
+}
+
+void lua_engine::s_output_notifier(const char *outname, INT32 value, void *param)
+{
+ static_cast<lua_engine *>(param)->output_notifier(outname, value);
+}
+
+void lua_engine::emu_hook_output(lua_State *L)
+{
+ luaL_argcheck(L, lua_isfunction(L, 1), 1, "callback function expected");
+ hook_output_cb.set(L, 1);
+
+ if (!output_notifier_set) {
+ machine().output().set_notifier(nullptr, s_output_notifier, this);
+ output_notifier_set = true;
+ }
+}
+
+int lua_engine::l_emu_hook_output(lua_State *L)
+{
+ luaThis->emu_hook_output(L);
+ return 0;
+}
+
+int lua_engine::l_emu_set_hook(lua_State *L)
+{
+ luaThis->emu_set_hook(L);
+ return 0;
+}
+
+void lua_engine::emu_set_hook(lua_State *L)
+{
+ luaL_argcheck(L, lua_isfunction(L, 1) || lua_isnil(L, 1), 1, "callback function expected");
+ luaL_argcheck(L, lua_isstring(L, 2), 2, "message (string) expected");
+ const char *hookname = luaL_checkstring(L,2);
+
+ if (strcmp(hookname, "output") == 0) {
+ hook_output_cb.set(L, 1);
+ if (!output_notifier_set) {
+ machine().output().set_notifier(nullptr, s_output_notifier, this);
+ output_notifier_set = true;
+ }
+ } else if (strcmp(hookname, "frame") == 0) {
+ hook_frame_cb.set(L, 1);
+ } else {
+ lua_writestringerror("%s", "Unknown hook name, aborting.\n");
+ }
+}
+
+//-------------------------------------------------
+// options_entry - return table of option entries
+// -> manager:options().entries
+// -> manager:machine():options().entries
+// -> manager:machine():ui():options().entries
+//-------------------------------------------------
+
+template <typename T>
+luabridge::LuaRef lua_engine::l_options_get_entries(const T *o)
+{
+ T *options = const_cast<T *>(o);
+ lua_State *L = luaThis->m_lua_state;
+ luabridge::LuaRef entries_table = luabridge::LuaRef::newTable(L);
+
+ int unadorned_index = 0;
+ for (typename T::entry &curentry : *options)
+ {
+ const char *name = curentry.name();
+ bool is_unadorned = false;
+ // check if it's unadorned
+ if (name && strlen(name) && !strcmp(name, options->unadorned(unadorned_index)))
+ {
+ unadorned_index++;
+ is_unadorned = true;
+ }
+ if (!curentry.is_header() && !curentry.is_command() && !curentry.is_internal() && !is_unadorned)
+ entries_table[name] = &curentry;
+ }
+
+ return entries_table;
+}
+
+//-------------------------------------------------
+// machine_get_screens - return table of available screens userdata
+// -> manager:machine().screens[":screen"]
+//-------------------------------------------------
+
+luabridge::LuaRef lua_engine::l_machine_get_screens(const running_machine *r)
+{
+ lua_State *L = luaThis->m_lua_state;
+ luabridge::LuaRef screens_table = luabridge::LuaRef::newTable(L);
+
+ for (device_t *dev = r->first_screen(); dev != nullptr; dev = dev->next()) {
+ screen_device *sc = dynamic_cast<screen_device *>(dev);
+ if (sc && sc->configured() && sc->started() && sc->type()) {
+ screens_table[sc->tag()] = sc;
+ }
+ }
+
+ return screens_table;
+}
+
+//-------------------------------------------------
+// machine_get_devices - return table of available devices userdata
+// -> manager:machine().devices[":maincpu"]
+//-------------------------------------------------
+
+luabridge::LuaRef lua_engine::l_machine_get_devices(const running_machine *r)
+{
+ running_machine *m = const_cast<running_machine *>(r);
+ lua_State *L = luaThis->m_lua_state;
+ luabridge::LuaRef devs_table = luabridge::LuaRef::newTable(L);
+
+ device_t *root = &(m->root_device());
+ devs_table = devtree_dfs(root, devs_table);
+
+ return devs_table;
+}
+
+//-------------------------------------------------
+// machine_get_images - return table of available image devices userdata
+// -> manager:machine().images["flop1"]
+//-------------------------------------------------
+
+luabridge::LuaRef lua_engine::l_machine_get_images(const running_machine *r)
+{
+ lua_State *L = luaThis->m_lua_state;
+ luabridge::LuaRef image_table = luabridge::LuaRef::newTable(L);
+
+ for (device_image_interface &image : image_interface_iterator(r->root_device()))
+ {
+ image_table[image.brief_instance_name()] = &image;
+ image_table[image.instance_name()] = &image;
+ }
+
+ return image_table;
+}
+
+//-------------------------------------------------
+// memory_banks - return memory_banks
+// -> manager:machine():memory().banks["maincpu"]
+//-------------------------------------------------
+
+luabridge::LuaRef lua_engine::l_memory_get_banks(const memory_manager *m)
+{
+ memory_manager *mm = const_cast<memory_manager *>(m);
+ lua_State *L = luaThis->m_lua_state;
+ luabridge::LuaRef table = luabridge::LuaRef::newTable(L);
+
+ for (memory_bank &bank : mm->banks()) {
+ table[bank.tag()] = &bank;
+ }
+
+ return table;
+}
+
+//-------------------------------------------------
+// memory_regions - return memory_regions
+// -> manager:machine():memory().region[":maincpu"]
+//-------------------------------------------------
+
+luabridge::LuaRef lua_engine::l_memory_get_regions(const memory_manager *m)
+{
+ memory_manager *mm = const_cast<memory_manager *>(m);
+ lua_State *L = luaThis->m_lua_state;
+ luabridge::LuaRef table = luabridge::LuaRef::newTable(L);
+
+ for (memory_region &region: mm->regions()) {
+ table[region.name()] = &region;
+ }
+
+ return table;
+}
+
+//-------------------------------------------------
+// machine_cheat_entries - return cheat entries
+// -> manager:machine():cheat().entries[0]
+//-------------------------------------------------
+
+luabridge::LuaRef lua_engine::l_cheat_get_entries(const cheat_manager *c)
+{
+ cheat_manager *cm = const_cast<cheat_manager *>(c);
+ lua_State *L = luaThis->m_lua_state;
+ luabridge::LuaRef entry_table = luabridge::LuaRef::newTable(L);
+
+ int cheatnum = 0;
+ for (cheat_entry &entry : cm->entries()) {
+ entry_table[cheatnum++] = &entry;
+ }
+
+ return entry_table;
+}
+
+//-------------------------------------------------
+// cheat_entry_state - return cheat entry state
+// -> manager:machine():cheat().entries[0]:state()
+//-------------------------------------------------
+
+int lua_engine::lua_cheat_entry::l_get_state(lua_State *L)
+{
+ cheat_entry *ce = luabridge::Stack<cheat_entry *>::get(L, 1);
+
+ switch (ce->state())
+ {
+ case SCRIPT_STATE_ON: lua_pushliteral(L, "on"); break;
+ case SCRIPT_STATE_RUN: lua_pushliteral(L, "run"); break;
+ case SCRIPT_STATE_CHANGE: lua_pushliteral(L, "change"); break;
+ case SCRIPT_STATE_COUNT: lua_pushliteral(L, "count"); break;
+ default: lua_pushliteral(L, "off"); break;
+ }
+
+ return 1;
+}
+
+//-------------------------------------------------
+// machine_ioports - return table of ioports
+// -> manager:machine():ioport().ports[':P1']
+//-------------------------------------------------
+
+luabridge::LuaRef lua_engine::l_ioport_get_ports(const ioport_manager *m)
+{
+ ioport_manager *im = const_cast<ioport_manager *>(m);
+ lua_State *L = luaThis->m_lua_state;
+ luabridge::LuaRef port_table = luabridge::LuaRef::newTable(L);
+
+ for (ioport_port &port : im->ports()) {
+ port_table[port.tag()] = &port;
+ }
+
+ return port_table;
+}
+
+//-------------------------------------------------
+// ioport_fields - return table of ioport fields
+// -> manager:machine().ioport().ports[':P1'].fields[':']
+//-------------------------------------------------
+
+luabridge::LuaRef lua_engine::l_ioports_port_get_fields(const ioport_port *i)
+{
+ ioport_port *p = const_cast<ioport_port *>(i);
+ lua_State *L = luaThis->m_lua_state;
+ luabridge::LuaRef f_table = luabridge::LuaRef::newTable(L);
+
+ for (ioport_field &field : p->fields()) {
+ f_table[field.name()] = &field;
+ }
+
+ return f_table;
+}
+
+//-------------------------------------------------
+// render_get_targets - return table of render targets
+// -> manager:machine():render().targets[0]
+//-------------------------------------------------
+
+luabridge::LuaRef lua_engine::l_render_get_targets(const render_manager *r)
+{
+ lua_State *L = luaThis->m_lua_state;
+ luabridge::LuaRef target_table = luabridge::LuaRef::newTable(L);
+
+ int tc = 0;
+ for (render_target &curr_rt : r->targets())
+ {
+ target_table[tc++] = &curr_rt;
+ }
+
+ return target_table;
+}
+
+// private helper for get_devices - DFS visit all devices in a running machine
+luabridge::LuaRef lua_engine::devtree_dfs(device_t *root, luabridge::LuaRef devs_table)
+{
+ if (root) {
+ for (device_t &dev : root->subdevices()) {
+ if (dev.configured() && dev.started()) {
+ devs_table[dev.tag()] = &dev;
+ devtree_dfs(&dev, devs_table);
+ }
+ }
+ }
+ return devs_table;
+}
+
+//-------------------------------------------------
+// device_get_memspaces - return table of available address spaces userdata
+// -> manager:machine().devices[":maincpu"].spaces["program"]
+//-------------------------------------------------
+
+luabridge::LuaRef lua_engine::l_dev_get_memspaces(const device_t *d)
+{
+ device_t *dev = const_cast<device_t *>(d);
+ lua_State *L = luaThis->m_lua_state;
+ luabridge::LuaRef sp_table = luabridge::LuaRef::newTable(L);
+
+ if(!dynamic_cast<device_memory_interface *>(dev))
+ return sp_table;
+
+ for (address_spacenum sp = AS_0; sp < ADDRESS_SPACES; ++sp) {
+ if (dev->memory().has_space(sp)) {
+ sp_table[dev->memory().space(sp).name()] = &(dev->memory().space(sp));
+ }
+ }
+
+ return sp_table;
+}
+
+//-------------------------------------------------
+// device_get_state - return table of available state userdata
+// -> manager:machine().devices[":maincpu"].state
+//-------------------------------------------------
+
+luabridge::LuaRef lua_engine::l_dev_get_states(const device_t *d)
+{
+ device_t *dev = const_cast<device_t *>(d);
+ lua_State *L = luaThis->m_lua_state;
+ luabridge::LuaRef st_table = luabridge::LuaRef::newTable(L);
+
+ if(!dynamic_cast<device_state_interface *>(dev))
+ return st_table;
+
+ for (device_state_entry &s : dev->state().state_entries())
+ {
+ // XXX: refrain from exporting non-visible entries?
+ st_table[s.symbol()] = &s;
+ }
+
+ return st_table;
+}
+
+//-------------------------------------------------
+// device_get_item - return table of indexed items owned by this device
+// -> manager:machine().devices[":maincpu"].items
+//-------------------------------------------------
+
+luabridge::LuaRef lua_engine::l_dev_get_items(const device_t *d)
+{
+ device_t *dev = const_cast<device_t *>(d);
+ lua_State *L = luaThis->m_lua_state;
+ luabridge::LuaRef table = luabridge::LuaRef::newTable(L);
+ std::string tag = dev->tag();
+
+ // 10000 is enough?
+ for(int i = 0; i < 10000; i++)
+ {
+ std::string name;
+ const char *item;
+ unsigned int size, count;
+ void *base;
+ item = dev->machine().save().indexed_item(i, base, size, count);
+ if(!item)
+ break;
+ name = &(strchr(item, '/')[1]);
+ if(name.substr(0, name.find("/")) == tag)
+ {
+ name = name.substr(name.find("/") + 1, std::string::npos);
+ table[name] = i;
+ }
+ }
+ return table;
+}
+
+lua_engine::lua_item::lua_item(int index)
+{
+ std::string name;
+ const char *item;
+ item = luaThis->machine().save().indexed_item(index, l_item_base, l_item_size, l_item_count);
+ if(!item)
+ {
+ l_item_base = nullptr;
+ l_item_size = 0;
+ l_item_count= 0;
+ }
+}
+
+int lua_engine::lua_item::l_item_read(lua_State *L)
+{
+ luaL_argcheck(L, lua_isnumber(L, 2), 2, "offset (integer) expected");
+ int offset = lua_tounsigned(L, 2);
+ int ret = 0;
+ if(!l_item_base || (offset > l_item_count))
+ {
+ lua_pushnil(L);
+ return 1;
+ }
+ switch(l_item_size)
+ {
+ case 1:
+ default:
+ ret = ((UINT8 *)l_item_base)[offset];
+ break;
+ case 2:
+ ret = ((UINT16 *)l_item_base)[offset];
+ break;
+ case 4:
+ ret = ((UINT32 *)l_item_base)[offset];
+ break;
+ case 8:
+ ret = ((UINT64 *)l_item_base)[offset];
+ break;
+ }
+ lua_pushunsigned(L, ret);
+ return 1;
+}
+
+int lua_engine::lua_item::l_item_write(lua_State *L)
+{
+ luaL_argcheck(L, lua_isnumber(L, 2), 2, "offset (integer) expected");
+ luaL_argcheck(L, lua_isnumber(L, 3), 3, "value (integer) expected");
+ int offset = lua_tounsigned(L, 2);
+ UINT64 value = lua_tounsigned(L, 3);
+ if(!l_item_base || (offset > l_item_count))
+ return 1;
+ switch(l_item_size)
+ {
+ case 1:
+ default:
+ ((UINT8 *)l_item_base)[offset] = (UINT8)value;
+ break;
+ case 2:
+ ((UINT16 *)l_item_base)[offset] = (UINT16)value;
+ break;
+ case 4:
+ ((UINT32 *)l_item_base)[offset] = (UINT32)value;
+ break;
+ case 8:
+ ((UINT64 *)l_item_base)[offset] = (UINT64)value;
+ break;
+ }
+ return 1;
+}
+
+int lua_engine::lua_item::l_item_read_block(lua_State *L)
+{
+ luaL_argcheck(L, lua_isnumber(L, 2), 2, "offset (integer) expected");
+ luaL_argcheck(L, lua_isnumber(L, 3), 3, "length (integer) expected");
+ int offset = lua_tounsigned(L, 2);
+ int len = lua_tonumber(L, 3);
+ if(!l_item_base || ((offset + len) > (l_item_size * l_item_count)))
+ {
+ lua_pushnil(L);
+ return 1;
+ }
+ luaL_Buffer buff;
+ char *ptr = luaL_buffinitsize(L, &buff, len);
+ memcpy(ptr, l_item_base, len);
+ luaL_pushresultsize(&buff, len);
+ return 1;
+}
+
+//-------------------------------------------------
+// state_get_value - return value of a device state entry
+// -> manager:machine().devices[":maincpu"].state["PC"].value
+//-------------------------------------------------
+
+UINT64 lua_engine::l_state_get_value(const device_state_entry *d)
+{
+ device_state_interface *state = d->parent_state();
+ if(state) {
+ luaThis->machine().save().dispatch_presave();
+ return state->state_int(d->index());
+ } else {
+ return 0;
+ }
+}
+
+//-------------------------------------------------
+// state_set_value - set value of a device state entry
+// -> manager:machine().devices[":maincpu"].state["D0"].value = 0x0c00
+//-------------------------------------------------
+
+void lua_engine::l_state_set_value(device_state_entry *d, UINT64 val)
+{
+ device_state_interface *state = d->parent_state();
+ if(state) {
+ state->set_state_int(d->index(), val);
+ luaThis->machine().save().dispatch_presave();
+ }
+}
+
+//-------------------------------------------------
+// mem_read - templated memory readers for <sign>,<size>
+// -> manager:machine().devices[":maincpu"].spaces["program"]:read_i8(0xC000)
+//-------------------------------------------------
+
+template <typename T>
+int lua_engine::lua_addr_space::l_mem_read(lua_State *L)
+{
+ address_space &sp = luabridge::Stack<address_space &>::get(L, 1);
+ luaL_argcheck(L, lua_isnumber(L, 2), 2, "address (integer) expected");
+ offs_t address = lua_tounsigned(L, 2);
+ T mem_content = 0;
+ switch(sizeof(mem_content) * 8) {
+ case 8:
+ mem_content = sp.read_byte(address);
+ break;
+ case 16:
+ if (WORD_ALIGNED(address)) {
+ mem_content = sp.read_word(address);
+ } else {
+ mem_content = sp.read_word_unaligned(address);
+ }
+ break;
+ case 32:
+ if (DWORD_ALIGNED(address)) {
+ mem_content = sp.read_dword(address);
+ } else {
+ mem_content = sp.read_dword_unaligned(address);
+ }
+ break;
+ case 64:
+ if (QWORD_ALIGNED(address)) {
+ mem_content = sp.read_qword(address);
+ } else {
+ mem_content = sp.read_qword_unaligned(address);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (std::numeric_limits<T>::is_signed) {
+ lua_pushinteger(L, mem_content);
+ } else {
+ lua_pushunsigned(L, mem_content);
+ }
+
+ return 1;
+
+}
+
+//-------------------------------------------------
+// mem_write - templated memory writer for <sign>,<size>
+// -> manager:machine().devices[":maincpu"].spaces["program"]:write_u16(0xC000, 0xF00D)
+//-------------------------------------------------
+
+template <typename T>
+int lua_engine::lua_addr_space::l_mem_write(lua_State *L)
+{
+ address_space &sp = luabridge::Stack<address_space &>::get(L, 1);
+ luaL_argcheck(L, lua_isnumber(L, 2), 2, "address (integer) expected");
+ luaL_argcheck(L, lua_isnumber(L, 3), 3, "value (integer) expected");
+ offs_t address = lua_tounsigned(L, 2);
+ T val = lua_tounsigned(L, 3);
+
+ switch(sizeof(val) * 8) {
+ case 8:
+ sp.write_byte(address, val);
+ break;
+ case 16:
+ if (WORD_ALIGNED(address)) {
+ sp.write_word(address, val);
+ } else {
+ sp.write_word_unaligned(address, val);
+ }
+ break;
+ case 32:
+ if (DWORD_ALIGNED(address)) {
+ sp.write_dword(address, val);
+ } else {
+ sp.write_dword_unaligned(address, val);
+ }
+ break;
+ case 64:
+ if (QWORD_ALIGNED(address)) {
+ sp.write_qword(address, val);
+ } else {
+ sp.write_qword_unaligned(address, val);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+//-------------------------------------------------
+// mem_direct_read - templated direct memory readers for <sign>,<size>
+// -> manager:machine().devices[":maincpu"].spaces["program"]:read_direct_i8(0xC000)
+//-------------------------------------------------
+
+template <typename T>
+int lua_engine::lua_addr_space::l_direct_mem_read(lua_State *L)
+{
+ address_space &sp = luabridge::Stack<address_space &>::get(L, 1);
+ luaL_argcheck(L, lua_isnumber(L, 2), 2, "address (integer) expected");
+ offs_t address = lua_tounsigned(L, 2);
+ T mem_content = 0;
+ offs_t lowmask = sp.data_width() / 8 - 1;
+ for(int i = 0; i < sizeof(T); i++)
+ {
+ int addr = sp.endianness() == ENDIANNESS_LITTLE ? address + sizeof(T) - 1 - i : address + i;
+ UINT8 *base = (UINT8 *)sp.get_read_ptr(sp.address_to_byte(addr & ~lowmask));
+ if(!base)
+ continue;
+ mem_content <<= 8;
+ if(sp.endianness() == ENDIANNESS_BIG)
+ mem_content |= base[BYTE8_XOR_BE(addr) & lowmask];
+ else
+ mem_content |= base[BYTE8_XOR_LE(addr) & lowmask];
+ }
+
+ if (std::numeric_limits<T>::is_signed) {
+ lua_pushinteger(L, mem_content);
+ } else {
+ lua_pushunsigned(L, mem_content);
+ }
+
+ return 1;
+}
+
+//-------------------------------------------------
+// mem_direct_write - templated memory writer for <sign>,<size>
+// -> manager:machine().devices[":maincpu"].spaces["program"]:write_direct_u16(0xC000, 0xF00D)
+//-------------------------------------------------
+
+template <typename T>
+int lua_engine::lua_addr_space::l_direct_mem_write(lua_State *L)
+{
+ address_space &sp = luabridge::Stack<address_space &>::get(L, 1);
+ luaL_argcheck(L, lua_isnumber(L, 2), 2, "address (integer) expected");
+ luaL_argcheck(L, lua_isnumber(L, 3), 3, "value (integer) expected");
+ offs_t address = lua_tounsigned(L, 2);
+ T val = lua_tounsigned(L, 3);
+ offs_t lowmask = sp.data_width() / 8 - 1;
+ for(int i = 0; i < sizeof(T); i++)
+ {
+ int addr = sp.endianness() == ENDIANNESS_BIG ? address + sizeof(T) - 1 - i : address + i;
+ UINT8 *base = (UINT8 *)sp.get_read_ptr(sp.address_to_byte(addr & ~lowmask));
+ if(!base)
+ continue;
+ if(sp.endianness() == ENDIANNESS_BIG)
+ base[BYTE8_XOR_BE(addr) & lowmask] = val & 0xff;
+ else
+ base[BYTE8_XOR_LE(addr) & lowmask] = val & 0xff;
+ val >>= 8;
+ }
+
+ return 0;
+}
+
+//-------------------------------------------------
+// region_read - templated region readers for <sign>,<size>
+// -> manager:machine():memory().region[":maincpu"]:read_i8(0xC000)
+//-------------------------------------------------
+
+template <typename T>
+int lua_engine::lua_memory_region::l_region_read(lua_State *L)
+{
+ memory_region &region = luabridge::Stack<memory_region &>::get(L, 1);
+ luaL_argcheck(L, lua_isnumber(L, 2), 2, "address (integer) expected");
+ offs_t address = lua_tounsigned(L, 2);
+ T mem_content = 0;
+ offs_t lowmask = region.bytewidth() - 1;
+ for(int i = 0; i < sizeof(T); i++)
+ {
+ int addr = region.endianness() == ENDIANNESS_LITTLE ? address + sizeof(T) - 1 - i : address + i;
+ if(addr >= region.bytes())
+ continue;
+ mem_content <<= 8;
+ if(region.endianness() == ENDIANNESS_BIG)
+ mem_content |= region.u8((BYTE8_XOR_BE(addr) & lowmask) | (addr & ~lowmask));
+ else
+ mem_content |= region.u8((BYTE8_XOR_LE(addr) & lowmask) | (addr & ~lowmask));
+ }
+
+ if (std::numeric_limits<T>::is_signed) {
+ lua_pushinteger(L, mem_content);
+ } else {
+ lua_pushunsigned(L, mem_content);
+ }
+
+ return 1;
+}
+
+//-------------------------------------------------
+// region_write - templated region writer for <sign>,<size>
+// -> manager:machine():memory().region[":maincpu"]:write_u16(0xC000, 0xF00D)
+//-------------------------------------------------
+
+template <typename T>
+int lua_engine::lua_memory_region::l_region_write(lua_State *L)
+{
+ memory_region &region = luabridge::Stack<memory_region &>::get(L, 1);
+ luaL_argcheck(L, lua_isnumber(L, 2), 2, "address (integer) expected");
+ luaL_argcheck(L, lua_isnumber(L, 3), 3, "value (integer) expected");
+ offs_t address = lua_tounsigned(L, 2);
+ T val = lua_tounsigned(L, 3);
+ offs_t lowmask = region.bytewidth() - 1;
+ for(int i = 0; i < sizeof(T); i++)
+ {
+ int addr = region.endianness() == ENDIANNESS_BIG ? address + sizeof(T) - 1 - i : address + i;
+ if(addr >= region.bytes())
+ continue;
+ if(region.endianness() == ENDIANNESS_BIG)
+ region.base()[(BYTE8_XOR_BE(addr) & lowmask) | (addr & ~lowmask)] = val & 0xff;
+ else
+ region.base()[(BYTE8_XOR_BE(addr) & lowmask) | (addr & ~lowmask)] = val & 0xff;
+ val >>= 8;
+ }
+
+ return 0;
+}
+
+luabridge::LuaRef lua_engine::l_addr_space_map(const address_space *space)
+{
+ lua_State *L = luaThis->m_lua_state;
+ luabridge::LuaRef map = luabridge::LuaRef::newTable(L);
+
+ int i = 1;
+ for (address_map_entry &entry : space->map()->m_entrylist)
+ {
+ luabridge::LuaRef mapentry = luabridge::LuaRef::newTable(L);
+ mapentry["offset"] = space->address_to_byte(entry.m_addrstart) & space->bytemask();
+ mapentry["endoff"] = space->address_to_byte(entry.m_addrend) & space->bytemask();
+ mapentry["readtype"] = entry.m_read.m_type;
+ mapentry["writetype"] = entry.m_write.m_type;
+ map[i++] = mapentry;
+ }
+ return map;
+}
+
+int lua_engine::lua_options_entry::l_entry_value(lua_State *L)
+{
+ core_options::entry *e = luabridge::Stack<core_options::entry *>::get(L, 1);
+ if(!e) {
+ return 0;
+ }
+
+ luaL_argcheck(L, !lua_isfunction(L, 2), 2, "optional argument: unsupported value");
+
+ if (!lua_isnone(L, 2))
+ {
+ std::string error;
+ // FIXME: not working with ui_options::entry
+ // TODO: optional arg for priority
+ luaThis->machine().options().set_value(e->name(),
+ lua_isboolean(L, 2) ? (lua_toboolean(L, 2) ? "1" : "0") : lua_tostring(L, 2),
+ OPTION_PRIORITY_CMDLINE, error);
+
+ if (!error.empty())
+ {
+ luaL_error(L, "%s", error.c_str());
+ }
+ }
+
+ switch (e->type())
+ {
+ case OPTION_BOOLEAN:
+ lua_pushboolean(L, (atoi(e->value()) != 0));
+ break;
+ case OPTION_INTEGER:
+ lua_pushnumber(L, atoi(e->value()));
+ break;
+ case OPTION_FLOAT:
+ lua_pushnumber(L, atof(e->value()));
+ break;
+ default:
+ lua_pushstring(L, e->value());
+ break;
+ }
+
+ return 1;
+}
+
+//-------------------------------------------------
+// begin_recording - start avi
+// -> manager:machine():video():begin_recording()
+//-------------------------------------------------
+
+int lua_engine::lua_video::l_begin_recording(lua_State *L)
+{
+ video_manager *vm = luabridge::Stack<video_manager *>::get(L, 1);
+ if (!vm) {
+ return 0;
+ }
+
+ luaL_argcheck(L, lua_isstring(L, 2) || lua_isnone(L, 2), 2, "optional argument: filename, string expected");
+
+ const char *filename = lua_tostring(L, 2);
+ if (!lua_isnone(L, 2)) {
+ std::string vidname(filename);
+ strreplace(vidname, "/", PATH_SEPARATOR);
+ strreplace(vidname, "%g", luaThis->machine().basename());
+ filename = vidname.c_str();
+ } else {
+ filename = nullptr;
+ }
+ vm->begin_recording(filename, video_manager::MF_AVI);
+
+ return 1;
+}
+
+//-------------------------------------------------
+// end_recording - start saving avi
+// -> manager:machine():video():end_recording()
+//-------------------------------------------------
+
+int lua_engine::lua_video::l_end_recording(lua_State *L)
+{
+ video_manager *vm = luabridge::Stack<video_manager *>::get(L, 1);
+ if (!vm) {
+ return 0;
+ }
+
+ if (!vm->is_recording()) {
+ lua_writestringerror("%s", "No active recording to stop");
+ return 0;
+ }
+
+ vm->end_recording(video_manager::MF_AVI);
+ return 1;
+}
+
+//-------------------------------------------------
+// screen_height - return screen visible height
+// -> manager:machine().screens[":screen"]:height()
+//-------------------------------------------------
+
+int lua_engine::lua_screen::l_height(lua_State *L)
+{
+ screen_device *sc = luabridge::Stack<screen_device *>::get(L, 1);
+ if(!sc) {
+ return 0;
+ }
+
+ lua_pushunsigned(L, sc->visible_area().height());
+ return 1;
+}
+
+//-------------------------------------------------
+// screen_width - return screen visible width
+// -> manager:machine().screens[":screen"]:width()
+//-------------------------------------------------
+
+int lua_engine::lua_screen::l_width(lua_State *L)
+{
+ screen_device *sc = luabridge::Stack<screen_device *>::get(L, 1);
+ if(!sc) {
+ return 0;
+ }
+
+ lua_pushunsigned(L, sc->visible_area().width());
+ return 1;
+}
+
+
+//-------------------------------------------------
+// screen_orientation - return screen orientation
+// -> manager:machine().screens[":screen"]:orientation()
+// -> rotation_angle (0, 90, 180, 270)
+// -> flipx (true, false)
+// -> flipy (true, false)
+//-------------------------------------------------
+
+int lua_engine::lua_screen::l_orientation(lua_State *L)
+{
+ UINT32 flags = (luaThis->machine().system().flags & ORIENTATION_MASK);
+
+ int rotation_angle = 0;
+ switch (flags)
+ {
+ case ORIENTATION_FLIP_X:
+ rotation_angle = 0;
+ break;
+ case ORIENTATION_SWAP_XY:
+ case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_X:
+ rotation_angle = 90;
+ break;
+ case ORIENTATION_FLIP_Y:
+ case ORIENTATION_FLIP_X|ORIENTATION_FLIP_Y:
+ rotation_angle = 180;
+ break;
+ case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_Y:
+ case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_X|ORIENTATION_FLIP_Y:
+ rotation_angle = 270;
+ break;
+ }
+
+ lua_createtable(L, 2, 2);
+ lua_pushliteral(L, "rotation_angle");
+ lua_pushinteger(L, rotation_angle);
+
+ lua_settable(L, -3);
+ lua_pushliteral(L, "flipx");
+ lua_pushboolean(L, (flags & ORIENTATION_FLIP_X));
+
+ lua_settable(L, -3);
+ lua_pushliteral(L, "flipy");
+ lua_pushboolean(L, (flags & ORIENTATION_FLIP_Y));
+ lua_settable(L, -3);
+ return 1;
+}
+
+//-------------------------------------------------
+// screen_refresh - return screen refresh rate
+// -> manager:machine().screens[":screen"]:refresh()
+//-------------------------------------------------
+
+int lua_engine::lua_screen::l_refresh(lua_State *L)
+{
+ screen_device *sc = luabridge::Stack<screen_device *>::get(L, 1);
+ if(!sc) {
+ return 0;
+ }
+
+ lua_pushnumber(L, ATTOSECONDS_TO_HZ(sc->refresh_attoseconds()));
+ return 1;
+}
+
+//-------------------------------------------------
+// screen_snapshot - save png bitmap of screen to snapshots folder
+// -> manager:machine().screens[":screen"]:snapshot("filename.png")
+//-------------------------------------------------
+
+int lua_engine::lua_screen::l_snapshot(lua_State *L)
+{
+ screen_device *sc = luabridge::Stack<screen_device *>::get(L, 1);
+ if(!sc || !sc->machine().render().is_live(*sc))
+ {
+ return 0;
+ }
+
+ luaL_argcheck(L, lua_isstring(L, 2) || lua_isnone(L, 2), 2, "optional argument: filename, string expected");
+
+ emu_file file(sc->machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ osd_file::error filerr;
+
+ if (!lua_isnone(L, 2)) {
+ const char *filename = lua_tostring(L, 2);
+ std::string snapstr(filename);
+ strreplace(snapstr, "/", PATH_SEPARATOR);
+ strreplace(snapstr, "%g", sc->machine().basename());
+ filerr = file.open(snapstr.c_str());
+ }
+ else
+ {
+ filerr = sc->machine().video().open_next(file, "png");
+ }
+
+ if (filerr != osd_file::error::NONE)
+ {
+ luaL_error(L, "osd_file::error=%d", filerr);
+ return 0;
+ }
+
+ sc->machine().video().save_snapshot(sc, file);
+ lua_writestringerror("saved %s", file.fullpath());
+ file.close();
+ return 1;
+}
+
+//-------------------------------------------------
+// screen_type - return human readable screen type
+// -> manager:machine().screens[":screen"]:type()
+//-------------------------------------------------
+
+int lua_engine::lua_screen::l_type(lua_State *L)
+{
+ screen_device *sc = luabridge::Stack<screen_device *>::get(L, 1);
+ if(!sc) {
+ return 0;
+ }
+
+ switch (sc->screen_type())
+ {
+ case SCREEN_TYPE_RASTER: lua_pushliteral(L, "raster"); break;
+ case SCREEN_TYPE_VECTOR: lua_pushliteral(L, "vector"); break;
+ case SCREEN_TYPE_LCD: lua_pushliteral(L, "lcd"); break;
+ case SCREEN_TYPE_SVG: lua_pushliteral(L, "svg"); break;
+ default: lua_pushliteral(L, "unknown"); break;
+ }
+
+ return 1;
+}
+
+//-------------------------------------------------
+// draw_box - draw a box on a screen container
+// -> manager:machine().screens[":screen"]:draw_box(x1, y1, x2, y2, bgcolor, linecolor)
+//-------------------------------------------------
+
+int lua_engine::lua_screen::l_draw_box(lua_State *L)
+{
+ screen_device *sc = luabridge::Stack<screen_device *>::get(L, 1);
+ if(!sc) {
+ return 0;
+ }
+
+ // ensure that we got 6 numerical parameters
+ luaL_argcheck(L, lua_isnumber(L, 2), 2, "x1 (integer) expected");
+ luaL_argcheck(L, lua_isnumber(L, 3), 3, "y1 (integer) expected");
+ luaL_argcheck(L, lua_isnumber(L, 4), 4, "x2 (integer) expected");
+ luaL_argcheck(L, lua_isnumber(L, 5), 5, "y2 (integer) expected");
+ luaL_argcheck(L, lua_isnumber(L, 6), 6, "background color (integer) expected");
+ luaL_argcheck(L, lua_isnumber(L, 7), 7, "outline color (integer) expected");
+
+ // retrieve all parameters
+ int sc_width = sc->visible_area().width();
+ int sc_height = sc->visible_area().height();
+ float x1, y1, x2, y2;
+ x1 = MIN(MAX(0, (float) lua_tonumber(L, 2)), sc_width-1) / static_cast<float>(sc_width);
+ y1 = MIN(MAX(0, (float) lua_tonumber(L, 3)), sc_height-1) / static_cast<float>(sc_height);
+ x2 = MIN(MAX(0, (float) lua_tonumber(L, 4)), sc_width-1) / static_cast<float>(sc_width);
+ y2 = MIN(MAX(0, (float) lua_tonumber(L, 5)), sc_height-1) / static_cast<float>(sc_height);
+ UINT32 bgcolor = lua_tounsigned(L, 6);
+ UINT32 fgcolor = lua_tounsigned(L, 7);
+
+ // draw the box
+ render_container &rc = sc->container();
+ mame_machine_manager::instance()->ui().draw_outlined_box(&rc, x1, y1, x2, y2, fgcolor, bgcolor);
+
+ return 0;
+}
+
+//-------------------------------------------------
+// draw_line - draw a line on a screen container
+// -> manager:machine().screens[":screen"]:draw_line(x1, y1, x2, y2, linecolor)
+//-------------------------------------------------
+
+int lua_engine::lua_screen::l_draw_line(lua_State *L)
+{
+ screen_device *sc = luabridge::Stack<screen_device *>::get(L, 1);
+ if(!sc) {
+ return 0;
+ }
+
+ // ensure that we got 5 numerical parameters
+ luaL_argcheck(L, lua_isnumber(L, 2), 2, "x1 (integer) expected");
+ luaL_argcheck(L, lua_isnumber(L, 3), 3, "y1 (integer) expected");
+ luaL_argcheck(L, lua_isnumber(L, 4), 4, "x2 (integer) expected");
+ luaL_argcheck(L, lua_isnumber(L, 5), 5, "y2 (integer) expected");
+ luaL_argcheck(L, lua_isnumber(L, 6), 6, "color (integer) expected");
+
+ // retrieve all parameters
+ int sc_width = sc->visible_area().width();
+ int sc_height = sc->visible_area().height();
+ float x1, y1, x2, y2;
+ x1 = MIN(MAX(0, (float) lua_tonumber(L, 2)), sc_width-1) / static_cast<float>(sc_width);
+ y1 = MIN(MAX(0, (float) lua_tonumber(L, 3)), sc_height-1) / static_cast<float>(sc_height);
+ x2 = MIN(MAX(0, (float) lua_tonumber(L, 4)), sc_width-1) / static_cast<float>(sc_width);
+ y2 = MIN(MAX(0, (float) lua_tonumber(L, 5)), sc_height-1) / static_cast<float>(sc_height);
+ UINT32 color = lua_tounsigned(L, 6);
+
+ // draw the line
+ sc->container().add_line(x1, y1, x2, y2, UI_LINE_WIDTH, rgb_t(color), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ return 0;
+}
+
+//-------------------------------------------------
+// draw_text - draw text on a screen container
+// if x is a position, then y is a pixel position, otherwise x and y are screen size relative
+// -> manager:machine().screens[":screen"]:draw_text(x, y, message)
+//-------------------------------------------------
+
+int lua_engine::lua_screen::l_draw_text(lua_State *L)
+{
+ screen_device *sc = luabridge::Stack<screen_device *>::get(L, 1);
+ if(!sc) {
+ return 0;
+ }
+
+ // ensure that we got proper parameters
+ luaL_argcheck(L, lua_isnumber(L, 2) || lua_isstring(L, 2), 2, "x (integer or string) expected");
+ luaL_argcheck(L, lua_isnumber(L, 3), 3, "y (integer) expected");
+ luaL_argcheck(L, lua_isstring(L, 4), 4, "message (string) expected");
+ luaL_argcheck(L, lua_isinteger(L, 5) || lua_isnone(L, 5), 5, "optional argument: text color, integer expected (default: 0xffffffff)");
+
+ // retrieve all parameters
+ int sc_width = sc->visible_area().width();
+ int sc_height = sc->visible_area().height();
+ int justify = JUSTIFY_LEFT;
+ float y, x = 0;
+ if(lua_isnumber(L, 2))
+ {
+ x = MIN(MAX(0, (float) lua_tonumber(L, 2)), sc_width-1) / static_cast<float>(sc_width);
+ y = MIN(MAX(0, (float) lua_tonumber(L, 3)), sc_height-1) / static_cast<float>(sc_height);
+ }
+ else
+ {
+ std::string just_str = lua_tostring(L, 2);
+ if(just_str == "right")
+ justify = JUSTIFY_RIGHT;
+ else if(just_str == "center")
+ justify = JUSTIFY_CENTER;
+ y = lua_tonumber(L, 3);
+ }
+ const char *msg = luaL_checkstring(L,4);
+ rgb_t textcolor = UI_TEXT_COLOR;
+ if (!lua_isnone(L, 5)) {
+ textcolor = rgb_t(lua_tounsigned(L, 5));
+ }
+
+ // draw the text
+ render_container &rc = sc->container();
+ mame_machine_manager::instance()->ui().draw_text_full(&rc, msg, x, y, (1.0f - x),
+ justify, WRAP_WORD, DRAW_NORMAL, textcolor,
+ UI_TEXT_BG_COLOR, nullptr, nullptr);
+ return 0;
+}
+
+int lua_engine::lua_emu_file::l_emu_file_read(lua_State *L)
+{
+ lua_emu_file *file = luabridge::Stack<lua_emu_file *>::get(L, 1);
+ luaL_argcheck(L, lua_isnumber(L, 2), 2, "length (integer) expected");
+ int ret, len = lua_tonumber(L, 2);
+ luaL_Buffer buff;
+ char *ptr = luaL_buffinitsize(L, &buff, len);
+ ret = file->file.read(ptr, len);
+ luaL_pushresultsize(&buff, ret);
+ return 1;
+}
+
+void *lua_engine::checkparam(lua_State *L, int idx, const char *tname)
+{
+ const char *name;
+
+ if(!lua_getmetatable(L, idx))
+ return nullptr;
+
+ lua_rawget(L, LUA_REGISTRYINDEX);
+ name = lua_tostring(L, -1);
+ if(!name || strcmp(name, tname)) {
+ lua_pop(L, 1);
+ return nullptr;
+ }
+ lua_pop(L, 1);
+
+ return *static_cast<void **>(lua_touserdata(L, idx));
+}
+
+void *lua_engine::getparam(lua_State *L, int idx, const char *tname)
+{
+ void *p = checkparam(L, idx, tname);
+ char msg[256];
+ sprintf(msg, "%s expected", tname);
+ luaL_argcheck(L, p, idx, msg);
+ return p;
+}
+
+void lua_engine::push(lua_State *L, void *p, const char *tname)
+{
+ void **pp = static_cast<void **>(lua_newuserdata(L, sizeof(void *)));
+ *pp = p;
+ luaL_getmetatable(L, tname);
+ lua_setmetatable(L, -2);
+}
+
+int lua_engine::l_emu_exit(lua_State *L)
+{
+ luaThis->machine().schedule_exit();
+ return 1;
+}
+
+int lua_engine::l_emu_start(lua_State *L)
+{
+ const char *system_name = luaL_checkstring(L,1);
+
+ int index = driver_list::find(system_name);
+ if (index != -1) {
+ mame_machine_manager::instance()->schedule_new_driver(driver_list::driver(index));
+ luaThis->machine().schedule_hard_reset();
+ }
+ return 1;
+}
+
+int lua_engine::luaopen_ioport(lua_State *L)
+{
+ static const struct luaL_Reg ioport_funcs [] = {
+ { "write", l_ioport_write },
+ { nullptr, nullptr } /* sentinel */
+ };
+
+ luaL_newmetatable(L, tname_ioport);
+ lua_pushvalue(L, -1);
+ lua_pushstring(L, tname_ioport);
+ lua_rawset(L, LUA_REGISTRYINDEX);
+ lua_pushstring(L, "__index");
+ lua_pushvalue(L, -2);
+ lua_settable(L, -3);
+ luaL_setfuncs(L, ioport_funcs, 0);
+ return 1;
+}
+
+struct msg {
+ std::string text;
+ int ready;
+ std::string response;
+ int status;
+ int done;
+} msg;
+
+static std::mutex g_mutex;
+
+void lua_engine::serve_lua()
+{
+ osd_sleep(osd_ticks_per_second() / 1000 * 50);
+ printf("%s v%s\n%s\n%s\n\n", emulator_info::get_appname(),build_version,emulator_info::get_copyright_info(),LUA_COPYRIGHT);
+ fflush(stdout);
+ char buff[LUA_MAXINPUT];
+ std::string oldbuff;
+
+ const char *b = LUA_PROMPT;
+
+ do {
+ // Wait for input
+ fputs(b, stdout); fflush(stdout); /* show prompt */
+ fgets(buff, LUA_MAXINPUT, stdin);
+
+ // Create message
+ {
+ std::lock_guard<std::mutex> lock(g_mutex);
+ if (msg.ready == 0) {
+ msg.text = oldbuff;
+ if (oldbuff.length() != 0) msg.text.append("\n");
+ msg.text.append(buff);
+ msg.ready = 1;
+ msg.done = 0;
+ }
+ }
+
+ // Wait for response
+ int done;
+ do {
+ osd_sleep(osd_ticks_per_second() / 1000);
+ std::lock_guard<std::mutex> lock(g_mutex);
+ done = msg.done;
+ } while (done==0);
+
+ // Do action on client side
+ {
+ std::lock_guard<std::mutex> lock(g_mutex);
+
+ if (msg.status == -1) {
+ b = LUA_PROMPT2;
+ oldbuff = msg.response;
+ }
+ else {
+ b = LUA_PROMPT;
+ oldbuff = "";
+ }
+ msg.done = 0;
+ }
+
+ } while (1);
+}
+
+static void *serve_lua(void *param)
+{
+ lua_engine *engine = (lua_engine *)param;
+ engine->serve_lua();
+ return NULL;
+}
+
+//-------------------------------------------------
+// lua_engine - constructor
+//-------------------------------------------------
+
+lua_engine::lua_engine()
+{
+ m_machine = nullptr;
+ luaThis = this;
+ m_lua_state = luaL_newstate(); /* create state */
+ output_notifier_set = false;
+
+ luaL_checkversion(m_lua_state);
+ lua_gc(m_lua_state, LUA_GCSTOP, 0); /* stop collector during initialization */
+ luaL_openlibs(m_lua_state); /* open libraries */
+
+ // Get package.preload so we can store builtins in it.
+ lua_getglobal(m_lua_state, "package");
+ lua_getfield(m_lua_state, -1, "preload");
+ lua_remove(m_lua_state, -2); // Remove package
+
+ lua_pushcfunction(m_lua_state, luaopen_zlib);
+ lua_setfield(m_lua_state, -2, "zlib");
+
+ lua_pushcfunction(m_lua_state, luaopen_lsqlite3);
+ lua_setfield(m_lua_state, -2, "lsqlite3");
+
+ lua_pushcfunction(m_lua_state, luaopen_lfs);
+ lua_setfield(m_lua_state, -2, "lfs");
+
+ luaopen_ioport(m_lua_state);
+
+ lua_gc(m_lua_state, LUA_GCRESTART, 0);
+ msg.ready = 0;
+ msg.status = 0;
+ msg.done = 0;
+}
+
+//-------------------------------------------------
+// ~lua_engine - destructor
+//-------------------------------------------------
+
+lua_engine::~lua_engine()
+{
+ close();
+}
+
+int lua_engine::compile_with_env(const char *envname, const char *script, const char *env)
+{
+ std::string field = std::string("env_").append(envname);
+ int error;
+ lua_settop(m_lua_state, 0);
+ lua_getfield(m_lua_state, LUA_REGISTRYINDEX, field.c_str());
+
+ if(!lua_istable(m_lua_state, -1))
+ {
+ lua_newtable(m_lua_state);
+ lua_setfield(m_lua_state, LUA_REGISTRYINDEX, field.c_str());
+ lua_getfield(m_lua_state, LUA_REGISTRYINDEX, field.c_str());
+ }
+
+ // optionally load a string to prepare the environment
+ if(env)
+ {
+ error = luaL_loadstring(m_lua_state, env);
+ if(error == LUA_OK)
+ lua_pushvalue(m_lua_state, -2);
+ if((error != LUA_OK) || ((error = lua_pcall(m_lua_state, 1, 0, 0)) != LUA_OK))
+ {
+ if((error == LUA_ERRSYNTAX) || (error == LUA_ERRRUN))
+ printf("%s\n", lua_tostring(m_lua_state, -1));
+ lua_pop(m_lua_state, 1);
+ }
+ lua_getfield(m_lua_state, LUA_REGISTRYINDEX, field.c_str());
+ }
+
+ if((error = luaL_loadstring(m_lua_state, script)) != LUA_OK)
+ {
+ if(error == LUA_ERRSYNTAX)
+ printf("%s\n", lua_tostring(m_lua_state, -1));
+ lua_tostring(m_lua_state, -1);
+ lua_pop(m_lua_state, 2);
+ return -1;
+ }
+ lua_pushvalue(m_lua_state, -2);
+ lua_setupvalue(m_lua_state, -2, 1);
+ int ref = luaL_ref(m_lua_state, -2);
+ lua_pop(m_lua_state, 1);
+ return ref;
+}
+
+template <typename Tout, typename Tin>
+Tout lua_engine::run(const char *env, int ref, Tin in)
+{
+ Tout ret;
+ lua_settop(m_lua_state, 0);
+ luabridge::Stack<Tin>::push(m_lua_state, in);
+ run_internal(env, ref);
+ if(lua_isnil(m_lua_state, 1))
+ ret = Tout(0);
+ else
+ ret = luabridge::Stack<Tout>::get(m_lua_state, 1);
+ lua_pop(m_lua_state, 1);
+ return ret;
+}
+
+template <typename Tout>
+Tout lua_engine::run(const char *env, int ref)
+{
+ Tout ret;
+ lua_settop(m_lua_state, 0);
+ lua_pushnil(m_lua_state);
+ run_internal(env, ref);
+ if(lua_isnil(m_lua_state, 1))
+ ret = Tout(0);
+ else
+ ret = luabridge::Stack<Tout>::get(m_lua_state, 1);
+ lua_pop(m_lua_state, 1);
+ return ret;
+}
+
+template <typename Tin>
+void lua_engine::run(const char *env, int ref, Tin in)
+{
+ lua_settop(m_lua_state, 0);
+ luabridge::Stack<Tin>::push(m_lua_state, in);
+ run_internal(env, ref);
+ lua_pop(m_lua_state, 1);
+}
+
+void lua_engine::run(const char *env, int ref)
+{
+ lua_settop(m_lua_state, 0);
+ lua_pushnil(m_lua_state);
+ run_internal(env, ref);
+ lua_pop(m_lua_state, 1);
+}
+// create specialization so luabridge doesn't have to be included everywhere
+template int lua_engine::run<int>(const char *env, int ref);
+
+void lua_engine::run_internal(const char *env, int ref)
+{
+ std::string field = std::string("env_").append(env);
+ lua_getfield(m_lua_state, LUA_REGISTRYINDEX, field.c_str());
+ if(lua_istable(m_lua_state, -1))
+ {
+ lua_rawgeti(m_lua_state, -1, ref);
+ if(lua_isfunction(m_lua_state, -1))
+ {
+ lua_pushvalue(m_lua_state, -3);
+ int error;
+ if((error = lua_pcall(m_lua_state, 1, 1, 0)) != LUA_OK)
+ {
+ if(error == LUA_ERRRUN)
+ printf("%s\n", lua_tostring(m_lua_state, -1));
+ lua_pop(m_lua_state, 1);
+ lua_pushnil(m_lua_state);
+ }
+ }
+ }
+ lua_replace(m_lua_state, 1);
+ lua_pop(m_lua_state, 1);
+}
+
+void lua_engine::menu_populate(std::string &menu, std::vector<menu_item> &menu_list)
+{
+ std::string field = "menu_pop_" + menu;
+ lua_settop(m_lua_state, 0);
+ lua_getfield(m_lua_state, LUA_REGISTRYINDEX, field.c_str());
+
+ if(!lua_isfunction(m_lua_state, -1))
+ {
+ lua_pop(m_lua_state, 1);
+ return;
+ }
+ int error;
+ if((error = lua_pcall(m_lua_state, 0, 1, 0)) != LUA_OK)
+ {
+ if(error == LUA_ERRRUN)
+ printf("%s\n", lua_tostring(m_lua_state, -1));
+ lua_pop(m_lua_state, 1);
+ return;
+ }
+ if(!lua_istable(m_lua_state, -1))
+ {
+ lua_pop(m_lua_state, 1);
+ return;
+ }
+
+ lua_pushnil(m_lua_state);
+ while(lua_next(m_lua_state, -2))
+ {
+ if(lua_istable(m_lua_state, -1))
+ {
+ menu_item item;
+ lua_rawgeti(m_lua_state, -1, 1);
+ item.text = lua_tostring(m_lua_state, -1);
+ lua_pop(m_lua_state, 1);
+ lua_rawgeti(m_lua_state, -1, 2);
+ item.subtext = lua_tostring(m_lua_state, -1);
+ lua_pop(m_lua_state, 1);
+ lua_rawgeti(m_lua_state, -1, 3);
+ item.flags = lua_tostring(m_lua_state, -1);
+ lua_pop(m_lua_state, 1);
+ menu_list.push_back(item);
+ }
+ lua_pop(m_lua_state, 1);
+ }
+ lua_pop(m_lua_state, 1);
+}
+
+bool lua_engine::menu_callback(std::string &menu, int index, std::string event)
+{
+ std::string field = "menu_cb_" + menu;
+ bool ret = false;
+ lua_settop(m_lua_state, 0);
+ lua_getfield(m_lua_state, LUA_REGISTRYINDEX, field.c_str());
+
+ if(lua_isfunction(m_lua_state, -1))
+ {
+ lua_pushinteger(m_lua_state, index);
+ lua_pushstring(m_lua_state, event.c_str());
+ int error;
+ if((error = lua_pcall(m_lua_state, 2, 1, 0)) != LUA_OK)
+ {
+ if(error == 2)
+ printf("%s\n", lua_tostring(m_lua_state, -1));
+ lua_pop(m_lua_state, 1);
+ return false;
+ }
+ ret = lua_toboolean(m_lua_state, -1);
+ lua_pop(m_lua_state, 1);
+ }
+ return ret;
+}
+
+int lua_engine::l_emu_register_menu(lua_State *L)
+{
+ luaL_argcheck(L, lua_isfunction(L, 1), 1, "callback function expected");
+ luaL_argcheck(L, lua_isfunction(L, 2), 2, "callback function expected");
+ luaL_argcheck(L, lua_isstring(L, 3), 3, "name (string) expected");
+ std::string name = luaL_checkstring(L, 3);
+ std::string cbfield = "menu_cb_" + name;
+ std::string popfield = "menu_pop_" + name;
+ luaThis->m_menu.push_back(std::string(name));
+ lua_pushvalue(L, 1);
+ lua_setfield(L, LUA_REGISTRYINDEX, cbfield.c_str());
+ lua_pushvalue(L, 2);
+ lua_setfield(L, LUA_REGISTRYINDEX, popfield.c_str());
+ return 1;
+}
+
+void lua_engine::execute_function(const char *id)
+{
+ lua_settop(m_lua_state, 0);
+ lua_getfield(m_lua_state, LUA_REGISTRYINDEX, id);
+
+ if (lua_istable(m_lua_state, -1))
+ {
+ lua_pushnil(m_lua_state);
+ while (lua_next(m_lua_state, -2) != 0)
+ {
+ if (lua_isfunction(m_lua_state, -1))
+ {
+ int error;
+ if((error = lua_pcall(m_lua_state, 0, 0, 0)) != LUA_OK)
+ {
+ if(error == 2)
+ printf("%s\n", lua_tostring(m_lua_state, -1));
+ lua_pop(m_lua_state, 1);
+ }
+ }
+ else
+ {
+ lua_pop(m_lua_state, 1);
+ }
+ }
+ }
+}
+
+int lua_engine::register_function(lua_State *L, const char *id)
+{
+ if (!lua_isnil(L, 1))
+ luaL_checktype(L, 1, LUA_TFUNCTION);
+ lua_settop(L, 1);
+ lua_getfield(L, LUA_REGISTRYINDEX, id);
+ if (lua_isnil(L, -1))
+ {
+ lua_newtable(L);
+ }
+ luaL_checktype(L, -1, LUA_TTABLE);
+ int len = lua_rawlen(L, -1);
+ lua_pushnumber(L, len + 1);
+ lua_pushvalue(L, 1);
+ lua_rawset(L, -3); /* Stores the pair in the table */
+
+ lua_pushvalue(L, -1);
+ lua_setfield(L, LUA_REGISTRYINDEX, id);
+ return 1;
+}
+
+int lua_engine::l_emu_register_prestart(lua_State *L)
+{
+ return register_function(L, "LUA_ON_PRESTART");
+}
+
+int lua_engine::l_emu_register_start(lua_State *L)
+{
+ return register_function(L, "LUA_ON_START");
+}
+
+int lua_engine::l_emu_register_stop(lua_State *L)
+{
+ return register_function(L, "LUA_ON_STOP");
+}
+
+int lua_engine::l_emu_register_pause(lua_State *L)
+{
+ return register_function(L, "LUA_ON_PAUSE");
+}
+
+int lua_engine::l_emu_register_resume(lua_State *L)
+{
+ return register_function(L, "LUA_ON_RESUME");
+}
+
+int lua_engine::l_emu_register_frame(lua_State *L)
+{
+ return register_function(L, "LUA_ON_FRAME");
+}
+
+int lua_engine::l_emu_register_frame_done(lua_State *L)
+{
+ return register_function(L, "LUA_ON_FRAME_DONE");
+}
+
+void lua_engine::on_machine_prestart()
+{
+ execute_function("LUA_ON_PRESTART");
+}
+
+void lua_engine::on_machine_start()
+{
+ execute_function("LUA_ON_START");
+}
+
+void lua_engine::on_machine_stop()
+{
+ execute_function("LUA_ON_STOP");
+}
+
+void lua_engine::on_machine_pause()
+{
+ execute_function("LUA_ON_PAUSE");
+}
+
+void lua_engine::on_machine_resume()
+{
+ execute_function("LUA_ON_RESUME");
+}
+
+void lua_engine::on_machine_frame()
+{
+ execute_function("LUA_ON_FRAME");
+}
+
+void lua_engine::on_frame_done()
+{
+ execute_function("LUA_ON_FRAME_DONE");
+}
+
+void lua_engine::update_machine()
+{
+ lua_newtable(m_lua_state);
+ if (m_machine!=nullptr)
+ {
+ // Create the ioport array
+ for (ioport_port &port : machine().ioport().ports())
+ {
+ for (ioport_field &field : port.fields())
+ {
+ if (field.name())
+ {
+ push(m_lua_state, &field, tname_ioport);
+ lua_setfield(m_lua_state, -2, field.name());
+ }
+ }
+ }
+ }
+ lua_setglobal(m_lua_state, "ioport");
+}
+
+void lua_engine::attach_notifiers()
+{
+ machine().add_notifier(MACHINE_NOTIFY_RESET, machine_notify_delegate(FUNC(lua_engine::on_machine_prestart), this), true);
+ machine().add_notifier(MACHINE_NOTIFY_RESET, machine_notify_delegate(FUNC(lua_engine::on_machine_start), this));
+ machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(lua_engine::on_machine_stop), this));
+ machine().add_notifier(MACHINE_NOTIFY_PAUSE, machine_notify_delegate(FUNC(lua_engine::on_machine_pause), this));
+ machine().add_notifier(MACHINE_NOTIFY_RESUME, machine_notify_delegate(FUNC(lua_engine::on_machine_resume), this));
+ machine().add_notifier(MACHINE_NOTIFY_FRAME, machine_notify_delegate(FUNC(lua_engine::on_machine_frame), this));
+}
+
+int lua_engine::lua_machine::l_popmessage(lua_State *L)
+{
+ running_machine *m = luabridge::Stack<running_machine *>::get(L, 1);
+ if(!lua_isstring(L, 2))
+ m->popmessage();
+ else
+ m->popmessage("%s", luaL_checkstring(L, 2));
+ return 0;
+}
+
+int lua_engine::lua_machine::l_logerror(lua_State *L)
+{
+ running_machine *m = luabridge::Stack<running_machine *>::get(L, 1);
+ luaL_argcheck(L, lua_isstring(L, 2), 2, "message (string) expected");
+ m->logerror("[luaengine] %s\n", luaL_checkstring(L, 2));
+ return 0;
+}
+
+std::string lua_engine::get_print_buffer(lua_State *L)
+{
+ int nargs = lua_gettop(L);
+
+ const std::string sep = " ";
+
+ std::ostringstream ss;
+ bool first = true;
+
+ for (int i = 1; i <= nargs; i++) {
+ const char* c = lua_tostring(L, i);
+ const std::string str = c ? c : "<nil>";
+ if (first) first = false;
+ else ss << sep;
+ ss << str;
+ }
+
+ return ss.str();
+}
+int lua_engine::l_osd_printf_verbose(lua_State *L)
+{
+ osd_printf_verbose("%s\n",get_print_buffer(L).c_str());
+ return 0;
+}
+
+int lua_engine::l_osd_printf_error(lua_State *L)
+{
+ osd_printf_error("%s\n",get_print_buffer(L).c_str());
+ return 0;
+}
+
+int lua_engine::l_osd_printf_info(lua_State *L)
+{
+ osd_printf_info("%s\n",get_print_buffer(L).c_str());
+ return 0;
+}
+
+int lua_engine::l_osd_printf_debug(lua_State *L)
+{
+ osd_printf_debug("%s\n",get_print_buffer(L).c_str());
+ return 0;
+}
+
+//-------------------------------------------------
+// initialize - initialize lua hookup to emu engine
+//-------------------------------------------------
+
+void lua_engine::initialize()
+{
+ luabridge::getGlobalNamespace (m_lua_state)
+ .beginNamespace ("emu")
+ .addCFunction ("app_name", l_emu_app_name )
+ .addCFunction ("app_version", l_emu_app_version )
+ .addCFunction ("gamename", l_emu_gamename )
+ .addCFunction ("romname", l_emu_romname )
+ .addCFunction ("softname", l_emu_softname )
+ .addCFunction ("keypost", l_emu_keypost )
+ .addCFunction ("hook_output", l_emu_hook_output )
+ .addCFunction ("sethook", l_emu_set_hook )
+ .addCFunction ("time", l_emu_time )
+ .addCFunction ("wait", l_emu_wait )
+ .addCFunction ("after", l_emu_after )
+ .addCFunction ("exit", l_emu_exit )
+ .addCFunction ("start", l_emu_start )
+ .addCFunction ("pause", l_emu_pause )
+ .addCFunction ("unpause", l_emu_unpause )
+ .addCFunction ("register_prestart", l_emu_register_prestart )
+ .addCFunction ("register_start", l_emu_register_start )
+ .addCFunction ("register_stop", l_emu_register_stop )
+ .addCFunction ("register_pause", l_emu_register_pause )
+ .addCFunction ("register_resume",l_emu_register_resume )
+ .addCFunction ("register_frame", l_emu_register_frame )
+ .addCFunction ("register_frame_done", l_emu_register_frame_done )
+ .addCFunction ("register_menu", l_emu_register_menu )
+ .addCFunction ("print_verbose", l_osd_printf_verbose )
+ .addCFunction ("print_error", l_osd_printf_error )
+ .addCFunction ("print_info", l_osd_printf_info )
+ .addCFunction ("print_debug", l_osd_printf_debug )
+ .beginClass <mame_machine_manager> ("manager")
+ .addFunction ("machine", &machine_manager::machine)
+ .addFunction ("options", &machine_manager::options)
+ .addFunction ("plugins", &mame_machine_manager::plugins)
+ .endClass ()
+ .beginClass <lua_machine> ("lua_machine")
+ .addCFunction ("popmessage", &lua_machine::l_popmessage)
+ .addCFunction ("logerror", &lua_machine::l_logerror)
+ .endClass ()
+ .deriveClass <running_machine, lua_machine> ("machine")
+ .addFunction ("exit", &running_machine::schedule_exit)
+ .addFunction ("hard_reset", &running_machine::schedule_hard_reset)
+ .addFunction ("soft_reset", &running_machine::schedule_soft_reset)
+ .addFunction ("save", &running_machine::schedule_save)
+ .addFunction ("load", &running_machine::schedule_load)
+ .addFunction ("system", &running_machine::system)
+ .addFunction ("video", &running_machine::video)
+ .addFunction ("ui", &running_machine::ui)
+ .addFunction ("render", &running_machine::render)
+ .addFunction ("ioport", &running_machine::ioport)
+ .addFunction ("parameters", &running_machine::parameters)
+ .addFunction ("cheat", &mame_machine_manager::cheat)
+ .addFunction ("memory", &running_machine::memory)
+ .addFunction ("options", &running_machine::options)
+ .addFunction ("outputs", &running_machine::output)
+ .addProperty <luabridge::LuaRef, void> ("devices", &lua_engine::l_machine_get_devices)
+ .addProperty <luabridge::LuaRef, void> ("screens", &lua_engine::l_machine_get_screens)
+ .addProperty <luabridge::LuaRef, void> ("images", &lua_engine::l_machine_get_images)
+ .endClass ()
+ .beginClass <game_driver> ("game_driver")
+ .addData ("source_file", &game_driver::source_file)
+ .addData ("parent", &game_driver::parent)
+ .addData ("name", &game_driver::name)
+ .addData ("description", &game_driver::description)
+ .addData ("year", &game_driver::year)
+ .addData ("manufacturer", &game_driver::manufacturer)
+ .addData ("compatible_with", &game_driver::compatible_with)
+ .addData ("default_layout", &game_driver::default_layout)
+ .endClass ()
+ .beginClass <device_t> ("device")
+ .addFunction ("name", &device_t::name)
+ .addFunction ("shortname", &device_t::shortname)
+ .addFunction ("tag", &device_t::tag)
+ .addFunction ("owner", &device_t::owner)
+ .addProperty <luabridge::LuaRef, void> ("spaces", &lua_engine::l_dev_get_memspaces)
+ .addProperty <luabridge::LuaRef, void> ("state", &lua_engine::l_dev_get_states)
+ .addProperty <luabridge::LuaRef, void> ("items", &lua_engine::l_dev_get_items)
+ .endClass()
+ .beginClass <cheat_manager> ("cheat")
+ .addProperty <bool, bool> ("enabled", &cheat_manager::enabled, &cheat_manager::set_enable)
+ .addFunction ("reload", &cheat_manager::reload)
+ .addFunction ("save_all", &cheat_manager::save_all)
+ .addProperty <luabridge::LuaRef, void> ("entries", &lua_engine::l_cheat_get_entries)
+ .endClass()
+ .beginClass <lua_cheat_entry> ("lua_cheat_entry")
+ .addCFunction ("state", &lua_cheat_entry::l_get_state)
+ .endClass()
+ .deriveClass <cheat_entry, lua_cheat_entry> ("cheat_entry")
+ .addFunction ("description", &cheat_entry::description)
+ .addFunction ("comment", &cheat_entry::comment)
+ .addFunction ("has_run_script", &cheat_entry::has_run_script)
+ .addFunction ("has_on_script", &cheat_entry::has_on_script)
+ .addFunction ("has_off_script", &cheat_entry::has_off_script)
+ .addFunction ("has_change_script", &cheat_entry::has_change_script)
+ .addFunction ("execute_off_script", &cheat_entry::execute_off_script)
+ .addFunction ("execute_on_script", &cheat_entry::execute_on_script)
+ .addFunction ("execute_run_script", &cheat_entry::execute_run_script)
+ .addFunction ("execute_change_script", &cheat_entry::execute_change_script)
+ .addFunction ("is_text_only", &cheat_entry::is_text_only)
+ .addFunction ("is_oneshot", &cheat_entry::is_oneshot)
+ .addFunction ("is_onoff", &cheat_entry::is_onoff)
+ .addFunction ("is_value_parameter", &cheat_entry::is_value_parameter)
+ .addFunction ("is_itemlist_parameter", &cheat_entry::is_itemlist_parameter)
+ .addFunction ("is_oneshot_parameter", &cheat_entry::is_oneshot_parameter)
+ .addFunction ("activate", &cheat_entry::activate)
+ .addFunction ("select_default_state", &cheat_entry::select_default_state)
+ .addFunction ("select_previous_state", &cheat_entry::select_previous_state)
+ .addFunction ("select_next_state", &cheat_entry::select_next_state)
+ .endClass()
+ .beginClass <ioport_manager> ("ioport")
+ .addFunction ("has_configs", &ioport_manager::has_configs)
+ .addFunction ("has_analog", &ioport_manager::has_analog)
+ .addFunction ("has_dips", &ioport_manager::has_dips)
+ .addFunction ("has_bioses", &ioport_manager::has_bioses)
+ .addFunction ("has_keyboard", &ioport_manager::has_keyboard)
+ .addFunction ("count_players", &ioport_manager::count_players)
+ .addProperty <luabridge::LuaRef, void> ("ports", &lua_engine::l_ioport_get_ports)
+ .endClass()
+ .beginClass <ioport_port> ("ioport_port")
+ .addFunction ("tag", &ioport_port::tag)
+ .addFunction ("active", &ioport_port::active)
+ .addFunction ("live", &ioport_port::live)
+ .addFunction ("read", &ioport_port::read)
+ .addFunction ("write", &ioport_port::write)
+ .addFunction ("field", &ioport_port::field)
+ .addProperty <luabridge::LuaRef, void> ("fields", &lua_engine::l_ioports_port_get_fields)
+ .endClass()
+ .beginClass <ioport_field> ("ioport_field")
+ .addFunction ("set_value", &ioport_field::set_value)
+ .addProperty ("device", &ioport_field::device)
+ .addProperty ("name", &ioport_field::name)
+ .addProperty <UINT8, UINT8> ("player", &ioport_field::player, &ioport_field::set_player)
+ .addProperty ("mask", &ioport_field::mask)
+ .addProperty ("defvalue", &ioport_field::defvalue)
+ .addProperty ("sensitivity", &ioport_field::sensitivity)
+ .addProperty ("way", &ioport_field::way)
+ .addProperty ("is_analog", &ioport_field::is_analog)
+ .addProperty ("is_digitial_joystick", &ioport_field::is_digital_joystick)
+ .addProperty ("enabled", &ioport_field::enabled)
+ .addProperty ("unused", &ioport_field::unused)
+ .addProperty ("cocktail", &ioport_field::cocktail)
+ .addProperty ("toggle", &ioport_field::toggle)
+ .addProperty ("rotated", &ioport_field::rotated)
+ .addProperty ("analog_reverse", &ioport_field::analog_reverse)
+ .addProperty ("analog_reset", &ioport_field::analog_reset)
+ .addProperty ("analog_wraps", &ioport_field::analog_wraps)
+ .addProperty ("analog_invert", &ioport_field::analog_invert)
+ .addProperty ("impulse", &ioport_field::impulse)
+ .addProperty <double, double> ("crosshair_scale", &ioport_field::crosshair_scale, &ioport_field::set_crosshair_scale)
+ .addProperty <double, double> ("crosshair_offset", &ioport_field::crosshair_offset, &ioport_field::set_crosshair_offset)
+ .endClass()
+ .beginClass <core_options> ("core_options")
+ .addFunction ("help", &core_options::output_help)
+ .addFunction ("command", &core_options::command)
+ .addProperty <luabridge::LuaRef, void> ("entries", &lua_engine::l_options_get_entries)
+ .endClass()
+ .beginClass <lua_options_entry> ("lua_options_entry")
+ .addCFunction ("value", &lua_options_entry::l_entry_value)
+ .endClass()
+ .deriveClass <core_options::entry, lua_options_entry> ("core_options_entry")
+ .addFunction ("description", &core_options::entry::description)
+ .addFunction ("default_value", &core_options::entry::default_value)
+ .addFunction ("minimum", &core_options::entry::minimum)
+ .addFunction ("maximum", &core_options::entry::maximum)
+ .addFunction ("has_range", &core_options::entry::has_range)
+ .endClass()
+ .deriveClass <emu_options, core_options> ("emu_options")
+ .endClass()
+ .deriveClass <ui_options, core_options> ("ui_options")
+ .endClass()
+ .deriveClass <plugin_options, core_options> ("plugin_options")
+ .endClass()
+ .beginClass <parameters_manager> ("parameters")
+ .addFunction ("add", &parameters_manager::add)
+ .addFunction ("lookup", &parameters_manager::lookup)
+ .endClass()
+ .beginClass <lua_video> ("lua_video_manager")
+ .addCFunction ("begin_recording", &lua_video::l_begin_recording)
+ .addCFunction ("end_recording", &lua_video::l_end_recording)
+ .endClass()
+ .deriveClass <video_manager, lua_video> ("video")
+ .addFunction ("snapshot", &video_manager::save_active_screen_snapshots)
+ .addFunction ("is_recording", &video_manager::is_recording)
+ .addFunction ("skip_this_frame", &video_manager::skip_this_frame)
+ .addFunction ("speed_factor", &video_manager::speed_factor)
+ .addFunction ("speed_percent", &video_manager::speed_percent)
+ .addProperty <int, int> ("frameskip", &video_manager::frameskip, &video_manager::set_frameskip)
+ .addProperty <bool, bool> ("throttled", &video_manager::throttled, &video_manager::set_throttled)
+ .addProperty <float, float> ("throttle_rate", &video_manager::throttle_rate, &video_manager::set_throttle_rate)
+ .endClass()
+ .beginClass <lua_addr_space> ("lua_addr_space")
+ .addCFunction ("read_i8", &lua_addr_space::l_mem_read<INT8>)
+ .addCFunction ("read_u8", &lua_addr_space::l_mem_read<UINT8>)
+ .addCFunction ("read_i16", &lua_addr_space::l_mem_read<INT16>)
+ .addCFunction ("read_u16", &lua_addr_space::l_mem_read<UINT16>)
+ .addCFunction ("read_i32", &lua_addr_space::l_mem_read<INT32>)
+ .addCFunction ("read_u32", &lua_addr_space::l_mem_read<UINT32>)
+ .addCFunction ("read_i64", &lua_addr_space::l_mem_read<INT64>)
+ .addCFunction ("read_u64", &lua_addr_space::l_mem_read<UINT64>)
+ .addCFunction ("write_i8", &lua_addr_space::l_mem_write<INT8>)
+ .addCFunction ("write_u8", &lua_addr_space::l_mem_write<UINT8>)
+ .addCFunction ("write_i16", &lua_addr_space::l_mem_write<INT16>)
+ .addCFunction ("write_u16", &lua_addr_space::l_mem_write<UINT16>)
+ .addCFunction ("write_i32", &lua_addr_space::l_mem_write<INT32>)
+ .addCFunction ("write_u32", &lua_addr_space::l_mem_write<UINT32>)
+ .addCFunction ("write_i64", &lua_addr_space::l_mem_write<INT64>)
+ .addCFunction ("write_u64", &lua_addr_space::l_mem_write<UINT64>)
+ .addCFunction ("read_direct_i8", &lua_addr_space::l_direct_mem_read<INT8>)
+ .addCFunction ("read_direct_u8", &lua_addr_space::l_direct_mem_read<UINT8>)
+ .addCFunction ("read_direct_i16", &lua_addr_space::l_direct_mem_read<INT16>)
+ .addCFunction ("read_direct_u16", &lua_addr_space::l_direct_mem_read<UINT16>)
+ .addCFunction ("read_direct_i32", &lua_addr_space::l_direct_mem_read<INT32>)
+ .addCFunction ("read_direct_u32", &lua_addr_space::l_direct_mem_read<UINT32>)
+ .addCFunction ("read_direct_i64", &lua_addr_space::l_direct_mem_read<INT64>)
+ .addCFunction ("read_direct_u64", &lua_addr_space::l_direct_mem_read<UINT64>)
+ .addCFunction ("write_direct_i8", &lua_addr_space::l_direct_mem_write<INT8>)
+ .addCFunction ("write_direct_u8", &lua_addr_space::l_direct_mem_write<UINT8>)
+ .addCFunction ("write_direct_i16", &lua_addr_space::l_direct_mem_write<INT16>)
+ .addCFunction ("write_direct_u16", &lua_addr_space::l_direct_mem_write<UINT16>)
+ .addCFunction ("write_direct_i32", &lua_addr_space::l_direct_mem_write<INT32>)
+ .addCFunction ("write_direct_u32", &lua_addr_space::l_direct_mem_write<UINT32>)
+ .addCFunction ("write_direct_i64", &lua_addr_space::l_direct_mem_write<INT64>)
+ .addCFunction ("write_direct_u64", &lua_addr_space::l_direct_mem_write<UINT64>)
+ .endClass()
+ .deriveClass <address_space, lua_addr_space> ("addr_space")
+ .addFunction("name", &address_space::name)
+ .addProperty <luabridge::LuaRef, void> ("map", &lua_engine::l_addr_space_map)
+ .endClass()
+ .beginClass <render_target> ("target")
+ .addFunction ("width", &render_target::width)
+ .addFunction ("height", &render_target::height)
+ .addFunction ("pixel_aspect", &render_target::pixel_aspect)
+ .addFunction ("hidden", &render_target::hidden)
+ .addFunction ("is_ui_target", &render_target::is_ui_target)
+ .addFunction ("index", &render_target::index)
+ .addProperty <float, float> ("max_update_rate", &render_target::max_update_rate, &render_target::set_max_update_rate)
+ .addProperty <int, int> ("view", &render_target::view, &render_target::set_view)
+ .addProperty <int, int> ("orientation", &render_target::orientation, &render_target::set_orientation)
+ .addProperty <bool, bool> ("backdrops", &render_target::backdrops_enabled, &render_target::set_backdrops_enabled)
+ .addProperty <bool, bool> ("overlays", &render_target::overlays_enabled, &render_target::set_overlays_enabled)
+ .addProperty <bool, bool> ("bezels", &render_target::bezels_enabled, &render_target::set_bezels_enabled)
+ .addProperty <bool, bool> ("marquees", &render_target::marquees_enabled, &render_target::set_marquees_enabled)
+ .addProperty <bool, bool> ("screen_overlay", &render_target::screen_overlay_enabled, &render_target::set_screen_overlay_enabled)
+ .addProperty <bool, bool> ("zoom", &render_target::zoom_to_screen, &render_target::set_zoom_to_screen)
+ .endClass()
+ .beginClass <render_container> ("render_container")
+ .addFunction ("orientation", &render_container::orientation)
+ .addFunction ("xscale", &render_container::xscale)
+ .addFunction ("yscale", &render_container::yscale)
+ .addFunction ("xoffset", &render_container::xoffset)
+ .addFunction ("yoffset", &render_container::yoffset)
+ .addFunction ("is_empty", &render_container::is_empty)
+ .endClass()
+ .beginClass <render_manager> ("render")
+ .addFunction ("max_update_rate", &render_manager::max_update_rate)
+ .addFunction ("ui_target", &render_manager::ui_target)
+ .addFunction ("ui_container", &render_manager::ui_container)
+ .addProperty <luabridge::LuaRef, void> ("targets", &lua_engine::l_render_get_targets)
+ .endClass()
+ .beginClass <mame_ui_manager> ("ui")
+ .addFunction ("is_menu_active", &mame_ui_manager::is_menu_active)
+ .addFunction ("options", &mame_ui_manager::options)
+ .addProperty <bool, bool> ("show_fps", &mame_ui_manager::show_fps, &mame_ui_manager::set_show_fps)
+ .addProperty <bool, bool> ("show_profiler", &mame_ui_manager::show_profiler, &mame_ui_manager::set_show_profiler)
+ .addProperty <bool, bool> ("single_step", &mame_ui_manager::single_step, &mame_ui_manager::set_single_step)
+ .addFunction ("get_line_height", &mame_ui_manager::get_line_height)
+ .endClass()
+ .beginClass <lua_screen> ("lua_screen_dev")
+ .addCFunction ("draw_box", &lua_screen::l_draw_box)
+ .addCFunction ("draw_line", &lua_screen::l_draw_line)
+ .addCFunction ("draw_text", &lua_screen::l_draw_text)
+ .addCFunction ("height", &lua_screen::l_height)
+ .addCFunction ("width", &lua_screen::l_width)
+ .addCFunction ("orientation", &lua_screen::l_orientation)
+ .addCFunction ("refresh", &lua_screen::l_refresh)
+ .addCFunction ("snapshot", &lua_screen::l_snapshot)
+ .addCFunction ("type", &lua_screen::l_type)
+ .endClass()
+ .deriveClass <screen_device, lua_screen> ("screen_dev")
+ .addFunction ("frame_number", &screen_device::frame_number)
+ .addFunction ("name", &screen_device::name)
+ .addFunction ("shortname", &screen_device::shortname)
+ .addFunction ("tag", &screen_device::tag)
+ .addFunction ("xscale", &screen_device::xscale)
+ .addFunction ("yscale", &screen_device::yscale)
+ .endClass()
+ .beginClass <device_state_entry> ("dev_space")
+ .addFunction ("name", &device_state_entry::symbol)
+ .addProperty <UINT64, UINT64> ("value", &lua_engine::l_state_get_value, &lua_engine::l_state_set_value)
+ .addFunction ("is_visible", &device_state_entry::visible)
+ .addFunction ("is_divider", &device_state_entry::divider)
+ .endClass()
+ .beginClass <memory_manager> ("memory")
+ .addProperty <luabridge::LuaRef, void> ("banks", &lua_engine::l_memory_get_banks)
+ .addProperty <luabridge::LuaRef, void> ("regions", &lua_engine::l_memory_get_regions)
+ .endClass()
+ .beginClass <lua_memory_region> ("lua_region")
+ .addCFunction ("read_i8", &lua_memory_region::l_region_read<INT8>)
+ .addCFunction ("read_u8", &lua_memory_region::l_region_read<UINT8>)
+ .addCFunction ("read_i16", &lua_memory_region::l_region_read<INT16>)
+ .addCFunction ("read_u16", &lua_memory_region::l_region_read<UINT16>)
+ .addCFunction ("read_i32", &lua_memory_region::l_region_read<INT32>)
+ .addCFunction ("read_u32", &lua_memory_region::l_region_read<UINT32>)
+ .addCFunction ("read_i64", &lua_memory_region::l_region_read<INT64>)
+ .addCFunction ("read_u64", &lua_memory_region::l_region_read<UINT64>)
+ .addCFunction ("write_i8", &lua_memory_region::l_region_write<INT8>)
+ .addCFunction ("write_u8", &lua_memory_region::l_region_write<UINT8>)
+ .addCFunction ("write_i16", &lua_memory_region::l_region_write<INT16>)
+ .addCFunction ("write_u16", &lua_memory_region::l_region_write<UINT16>)
+ .addCFunction ("write_i32", &lua_memory_region::l_region_write<INT32>)
+ .addCFunction ("write_u32", &lua_memory_region::l_region_write<UINT32>)
+ .addCFunction ("write_i64", &lua_memory_region::l_region_write<INT64>)
+ .addCFunction ("write_u64", &lua_memory_region::l_region_write<UINT64>)
+ .endClass()
+ .beginClass <output_manager> ("output")
+ .addFunction ("set_value", &output_manager::set_value)
+ .addFunction ("set_indexed_value", &output_manager::set_indexed_value)
+ .addFunction ("get_value", &output_manager::get_value)
+ .addFunction ("get_indexed_value", &output_manager::get_indexed_value)
+ .addFunction ("name_to_id", &output_manager::name_to_id)
+ .addFunction ("id_to_name", &output_manager::id_to_name)
+ .endClass()
+ .deriveClass <memory_region, lua_memory_region> ("region")
+ .addProperty <UINT32> ("size", &memory_region::bytes)
+ .endClass()
+ .beginClass <device_image_interface> ("image")
+ .addFunction ("exists", &device_image_interface::exists)
+ .addFunction ("filename", &device_image_interface::filename)
+ .addFunction ("longname", &device_image_interface::longname)
+ .addFunction ("manufacturer", &device_image_interface::manufacturer)
+ .addFunction ("year", &device_image_interface::year)
+ .addFunction ("software_list_name", &device_image_interface::software_list_name)
+ .addFunction ("image_type_name", &device_image_interface::image_type_name)
+ .addFunction ("load", &device_image_interface::load)
+ .addFunction ("unload", &device_image_interface::unload)
+ .addFunction ("crc", &device_image_interface::crc)
+ .addProperty <const device_t &> ("device", static_cast<const device_t &(device_image_interface::*)() const>(&device_image_interface::device))
+ .addProperty <bool> ("is_readable", &device_image_interface::is_readable)
+ .addProperty <bool> ("is_writeable", &device_image_interface::is_writeable)
+ .addProperty <bool> ("is_creatable", &device_image_interface::is_creatable)
+ .addProperty <bool> ("is_reset_on_load", &device_image_interface::is_reset_on_load)
+ .endClass()
+ .beginClass <lua_emu_file> ("file")
+ .addConstructor <void (*)(const char *, UINT32)> ()
+ .addCFunction ("read", &lua_emu_file::l_emu_file_read)
+ .addFunction ("open", &lua_emu_file::open)
+ .addFunction ("open_next", &lua_emu_file::open_next)
+ .addFunction ("seek", &lua_emu_file::seek)
+ .addFunction ("size", &lua_emu_file::size)
+ .addFunction ("filename", &lua_emu_file::filename)
+ .addFunction ("fullpath", &lua_emu_file::fullpath)
+ .endClass()
+ .beginClass <lua_item> ("item")
+ .addConstructor <void (*)(int)> ()
+ .addData ("size", &lua_item::l_item_size, false)
+ .addData ("count", &lua_item::l_item_count, false)
+ .addCFunction ("read", &lua_item::l_item_read)
+ .addCFunction ("read_block", &lua_item::l_item_read_block)
+ .addCFunction ("write", &lua_item::l_item_write)
+ .endClass()
+ .endNamespace();
+
+ luabridge::push (m_lua_state, mame_machine_manager::instance());
+ lua_setglobal(m_lua_state, "manager");
+}
+
+void lua_engine::start_console()
+{
+ std::thread th(::serve_lua, this);
+ th.detach();
+}
+
+//-------------------------------------------------
+// frame_hook - called at each frame refresh, used to draw a HUD
+//-------------------------------------------------
+bool lua_engine::frame_hook()
+{
+ bool is_cb_hooked = false;
+ if (m_machine != nullptr) {
+ // invoke registered callback (if any)
+ is_cb_hooked = hook_frame_cb.active();
+ if (is_cb_hooked) {
+ lua_State *L = hook_frame_cb.precall();
+ hook_frame_cb.call(this, L, 0);
+ }
+ }
+ return is_cb_hooked;
+}
+
+void lua_engine::periodic_check()
+{
+ std::lock_guard<std::mutex> lock(g_mutex);
+ if (msg.ready == 1) {
+ lua_settop(m_lua_state, 0);
+ int status = luaL_loadbuffer(m_lua_state, msg.text.c_str(), msg.text.length(), "=stdin");
+ if (incomplete(status)==0) /* cannot try to add lines? */
+ {
+ if (status == LUA_OK) status = docall(0, LUA_MULTRET);
+ report(status);
+ if (status == LUA_OK && lua_gettop(m_lua_state) > 0) /* any result to print? */
+ {
+ luaL_checkstack(m_lua_state, LUA_MINSTACK, "too many results to print");
+ lua_getglobal(m_lua_state, "print");
+ lua_insert(m_lua_state, 1);
+ if (lua_pcall(m_lua_state, lua_gettop(m_lua_state) - 1, 0, 0) != LUA_OK)
+ lua_writestringerror("%s\n", lua_pushfstring(m_lua_state,
+ "error calling " LUA_QL("print") " (%s)",
+ lua_tostring(m_lua_state, -1)));
+ }
+ }
+ else
+ {
+ status = -1;
+ }
+ msg.status = status;
+ msg.response = msg.text;
+ msg.text = "";
+ msg.ready = 0;
+ msg.done = 1;
+ }
+}
+
+//-------------------------------------------------
+// close - close and cleanup of lua engine
+//-------------------------------------------------
+
+void lua_engine::close()
+{
+ lua_settop(m_lua_state, 0); /* clear stack */
+ lua_close(m_lua_state);
+}
+
+//-------------------------------------------------
+// execute - load and execute script
+//-------------------------------------------------
+
+void lua_engine::load_script(const char *filename)
+{
+ int s = luaL_loadfile(m_lua_state, filename);
+ report(s);
+ update_machine();
+ start();
+}
+
+//-------------------------------------------------
+// execute_string - execute script from string
+//-------------------------------------------------
+
+void lua_engine::load_string(const char *value)
+{
+ int s = luaL_loadstring(m_lua_state, value);
+ report(s);
+ update_machine();
+ start();
+}
+
+//-------------------------------------------------
+// start - execute the loaded script
+//-------------------------------------------------
+
+void lua_engine::start()
+{
+ resume(m_lua_state);
+}
+
+
+//**************************************************************************
+// LuaBridge Stack specializations
+//**************************************************************************
+
+namespace luabridge {
+ template <>
+ struct Stack <unsigned long long> {
+ static inline void push (lua_State* L, unsigned long long value) {
+ lua_pushunsigned(L, static_cast <lua_Unsigned> (value));
+ }
+
+ static inline unsigned long long get (lua_State* L, int index) {
+ return static_cast <unsigned long long> (luaL_checkunsigned (L, index));
+ }
+ };
+}
diff --git a/src/frontend/mame/luaengine.h b/src/frontend/mame/luaengine.h
new file mode 100644
index 00000000000..0f18cb995b1
--- /dev/null
+++ b/src/frontend/mame/luaengine.h
@@ -0,0 +1,252 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/***************************************************************************
+
+ luaengine.h
+
+ Controls execution of the core MAME system.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __EMU_H__
+#error Dont include this file directly; include emu.h instead.
+#endif
+
+#ifndef __LUA_ENGINE_H__
+#define __LUA_ENGINE_H__
+
+#include <map>
+
+// None is typedef'd already in SDL/X11 libs
+#ifdef None
+#undef None
+#endif
+
+class cheat_manager;
+
+struct lua_State;
+namespace luabridge
+{
+ class LuaRef;
+}
+
+class lua_engine
+{
+public:
+ // construction/destruction
+ lua_engine();
+ ~lua_engine();
+
+ void initialize();
+ void start_console();
+ void load_script(const char *filename);
+ void load_string(const char *value);
+
+ void serve_lua();
+ void periodic_check();
+ bool frame_hook();
+ void execute_function(const char *id);
+
+ struct menu_item {
+ std::string text;
+ std::string subtext;
+ std::string flags;
+ };
+ void menu_populate(std::string &menu, std::vector<menu_item> &menu_list);
+ bool menu_callback(std::string &menu, int index, std::string event);
+
+ void resume(lua_State *L, int nparam = 0, lua_State *root = nullptr);
+ void set_machine(running_machine *machine) { m_machine = machine; update_machine(); }
+ std::vector<std::string> &get_menu() { return m_menu; }
+ void attach_notifiers();
+ void on_frame_done();
+
+ int compile_with_env(const char *envname, const char *script, const char *env = nullptr);
+ template <typename Tout, typename Tin> Tout run(const char *envname, int ref, Tin in);
+ template <typename Tout> Tout run(const char *envname, int ref);
+ template <typename Tin> void run(const char *envname, int ref, Tin in);
+ void run(const char *envname, int ref);
+private:
+ struct hook {
+ lua_State *L;
+ int cb;
+
+ hook();
+ void set(lua_State *L, int idx);
+ lua_State *precall();
+ void call(lua_engine *engine, lua_State *T, int nparam);
+ bool active() const { return L != nullptr; }
+ };
+
+ static const char *const tname_ioport;
+
+ // internal state
+ lua_State *m_lua_state;
+ running_machine * m_machine;
+
+ std::vector<std::string> m_menu;
+
+ hook hook_output_cb;
+ bool output_notifier_set;
+
+ hook hook_frame_cb;
+
+ static lua_engine* luaThis;
+
+ std::map<lua_State *, std::pair<lua_State *, int> > thread_registry;
+
+ running_machine &machine() const { return *m_machine; }
+
+ void update_machine();
+
+ void on_machine_prestart();
+ void on_machine_start();
+ void on_machine_stop();
+ void on_machine_pause();
+ void on_machine_resume();
+ void on_machine_frame();
+
+ void output_notifier(const char *outname, INT32 value);
+ static void s_output_notifier(const char *outname, INT32 value, void *param);
+
+ void emu_after_done(void *_h, INT32 param);
+ int emu_after(lua_State *L);
+ int emu_wait(lua_State *L);
+ void emu_hook_output(lua_State *L);
+ void emu_set_hook(lua_State *L);
+
+ static int l_ioport_write(lua_State *L);
+ static int l_emu_after(lua_State *L);
+ static int l_emu_app_name(lua_State *L);
+ static int l_emu_app_version(lua_State *L);
+ static int l_emu_wait(lua_State *L);
+ static int l_emu_time(lua_State *L);
+ static int l_emu_gamename(lua_State *L);
+ static int l_emu_romname(lua_State *L);
+ static int l_emu_softname(lua_State *L);
+ static int l_emu_keypost(lua_State *L);
+ static int l_emu_hook_output(lua_State *L);
+ static int l_emu_exit(lua_State *L);
+ static int l_emu_start(lua_State *L);
+ static int l_emu_pause(lua_State *L);
+ static int l_emu_unpause(lua_State *L);
+ static int l_emu_set_hook(lua_State *L);
+ static int l_emu_register_prestart(lua_State *L);
+ static int l_emu_register_start(lua_State *L);
+ static int l_emu_register_stop(lua_State *L);
+ static int l_emu_register_pause(lua_State *L);
+ static int l_emu_register_resume(lua_State *L);
+ static int l_emu_register_frame(lua_State *L);
+ static int l_emu_register_frame_done(lua_State *L);
+ static int l_emu_register_menu(lua_State *L);
+ static std::string get_print_buffer(lua_State *L);
+ static int l_osd_printf_verbose(lua_State *L);
+ static int l_osd_printf_error(lua_State *L);
+ static int l_osd_printf_info(lua_State *L);
+ static int l_osd_printf_debug(lua_State *L);
+ static int register_function(lua_State *L, const char *id);
+
+ // "emu.machine" namespace
+ static luabridge::LuaRef l_machine_get_devices(const running_machine *r);
+ static luabridge::LuaRef l_machine_get_images(const running_machine *r);
+ static luabridge::LuaRef l_ioport_get_ports(const ioport_manager *i);
+ static luabridge::LuaRef l_render_get_targets(const render_manager *r);
+ static luabridge::LuaRef l_ioports_port_get_fields(const ioport_port *i);
+ static luabridge::LuaRef devtree_dfs(device_t *root, luabridge::LuaRef dev_table);
+ static luabridge::LuaRef l_dev_get_states(const device_t *d);
+ static UINT64 l_state_get_value(const device_state_entry *d);
+ static void l_state_set_value(device_state_entry *d, UINT64 v);
+ static luabridge::LuaRef l_dev_get_memspaces(const device_t *d);
+ struct lua_machine {
+ int l_popmessage(lua_State *L);
+ int l_logerror(lua_State *L);
+ };
+ struct lua_addr_space {
+ template<typename T> int l_mem_read(lua_State *L);
+ template<typename T> int l_mem_write(lua_State *L);
+ template<typename T> int l_direct_mem_read(lua_State *L);
+ template<typename T> int l_direct_mem_write(lua_State *L);
+ };
+ static luabridge::LuaRef l_addr_space_map(const address_space *as);
+
+ static luabridge::LuaRef l_machine_get_screens(const running_machine *r);
+ struct lua_screen {
+ int l_height(lua_State *L);
+ int l_width(lua_State *L);
+ int l_orientation(lua_State *L);
+ int l_refresh(lua_State *L);
+ int l_type(lua_State *L);
+ int l_snapshot(lua_State *L);
+ int l_draw_box(lua_State *L);
+ int l_draw_line(lua_State *L);
+ int l_draw_text(lua_State *L);
+ };
+ static luabridge::LuaRef l_dev_get_items(const device_t *d);
+
+ struct lua_video {
+ int l_begin_recording(lua_State *L);
+ int l_end_recording(lua_State *L);
+ };
+
+ static luabridge::LuaRef l_cheat_get_entries(const cheat_manager *c);
+ struct lua_cheat_entry {
+ int l_get_state(lua_State *L);
+ };
+
+ template<typename T> static luabridge::LuaRef l_options_get_entries(const T *o);
+ struct lua_options_entry {
+ int l_entry_value(lua_State *L);
+ };
+
+ static luabridge::LuaRef l_memory_get_banks(const memory_manager *m);
+ static luabridge::LuaRef l_memory_get_regions(const memory_manager *m);
+ struct lua_memory_region {
+ template<typename T> int l_region_read(lua_State *L);
+ template<typename T> int l_region_write(lua_State *L);
+ };
+
+ struct lua_emu_file {
+ lua_emu_file(const char *searchpath, UINT32 openflags) :
+ path(searchpath),
+ file(path.c_str(), openflags) {}
+
+ int l_emu_file_read(lua_State *L);
+ osd_file::error open(const char *name) {return file.open(name);}
+ osd_file::error open_next() {return file.open_next();}
+ int seek(INT64 offset, int whence) {return file.seek(offset, whence);}
+ UINT64 size() {return file.size();}
+ const char *filename() {return file.filename();}
+ const char *fullpath() {return file.fullpath();}
+
+ std::string path;
+ emu_file file;
+ };
+
+ struct lua_item {
+ lua_item(int index);
+ void *l_item_base;
+ unsigned int l_item_size;
+ unsigned int l_item_count;
+ int l_item_read(lua_State *L);
+ int l_item_read_block(lua_State *L);
+ int l_item_write(lua_State *L);
+ };
+ void run_internal(const char *env, int ref);
+
+ void resume(void *L, INT32 param);
+ void start();
+ static int luaopen_ioport(lua_State *L);
+ void close();
+
+ static void *checkparam(lua_State *L, int idx, const char *tname);
+ static void *getparam(lua_State *L, int idx, const char *tname);
+ static void push(lua_State *L, void *p, const char *tname);
+
+ int report(int status);
+ int docall(int narg, int nres);
+ int incomplete(int status) ;
+};
+
+#endif /* __LUA_ENGINE_H__ */
diff --git a/src/frontend/mame/mame.cpp b/src/frontend/mame/mame.cpp
new file mode 100644
index 00000000000..2be1ea0f615
--- /dev/null
+++ b/src/frontend/mame/mame.cpp
@@ -0,0 +1,393 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles
+/***************************************************************************
+
+ mame.c
+
+ Controls execution of the core MAME system.
+****************************************************************************
+
+ Since there has been confusion in the past over the order of
+ initialization and other such things, here it is, all spelled out
+ as of January, 2008:
+
+ main()
+ - does platform-specific init
+ - calls mame_execute() [mame.c]
+
+ mame_execute() [mame.c]
+ - calls mame_validitychecks() [validity.c] to perform validity checks on all compiled drivers
+ - begins resource tracking (level 1)
+ - calls create_machine [mame.c] to initialize the running_machine structure
+ - calls init_machine() [mame.c]
+
+ init_machine() [mame.c]
+ - calls fileio_init() [fileio.c] to initialize file I/O info
+ - calls config_init() [config.c] to initialize configuration system
+ - calls input_init() [input.c] to initialize the input system
+ - calls output_init() [output.c] to initialize the output system
+ - calls state_init() [state.c] to initialize save state system
+ - calls state_save_allow_registration() [state.c] to allow registrations
+ - calls palette_init() [palette.c] to initialize palette system
+ - calls render_init() [render.c] to initialize the rendering system
+ - calls ui_init() [ui.c] to initialize the user interface
+ - calls generic_machine_init() [machine/generic.c] to initialize generic machine structures
+ - calls generic_video_init() [video/generic.c] to initialize generic video structures
+ - calls generic_sound_init() [audio/generic.c] to initialize generic sound structures
+ - calls timer_init() [timer.c] to reset the timer system
+ - calls osd_init() [osdepend.h] to do platform-specific initialization
+ - calls input_port_init() [inptport.c] to set up the input ports
+ - calls rom_init() [romload.c] to load the game's ROMs
+ - calls memory_init() [memory.c] to process the game's memory maps
+ - calls watchdog_init() [watchdog.c] to initialize the watchdog system
+ - calls the driver's DRIVER_INIT callback
+ - calls device_list_start() [devintrf.c] to start any devices
+ - calls video_init() [video.c] to start the video system
+ - calls tilemap_init() [tilemap.c] to start the tilemap system
+ - calls crosshair_init() [crsshair.c] to configure the crosshairs
+ - calls sound_init() [sound.c] to start the audio system
+ - calls debugger_init() [debugger.c] to set up the debugger
+ - calls the driver's MACHINE_START, SOUND_START, and VIDEO_START callbacks
+ - calls cheat_init() [cheat.c] to initialize the cheat system
+ - calls image_init() [image.c] to initialize the image system
+
+ - calls config_load_settings() [config.c] to load the configuration file
+ - calls nvram_load [machine/generic.c] to load NVRAM
+ - calls ui_display_startup_screens() [ui.c] to display the startup screens
+ - begins resource tracking (level 2)
+ - calls soft_reset() [mame.c] to reset all systems
+
+ -------------------( at this point, we're up and running )----------------------
+
+ - calls scheduler->timeslice() [schedule.c] over and over until we exit
+ - ends resource tracking (level 2), freeing all auto_mallocs and timers
+ - calls the nvram_save() [machine/generic.c] to save NVRAM
+ - calls config_save_settings() [config.c] to save the game's configuration
+ - calls all registered exit routines [mame.c]
+ - ends resource tracking (level 1), freeing all auto_mallocs and timers
+
+ - exits the program
+
+***************************************************************************/
+
+#include "emu.h"
+#include "mame.h"
+#include "emuopts.h"
+#include "mameopts.h"
+#include "osdepend.h"
+#include "validity.h"
+#include "clifront.h"
+#include "luaengine.h"
+#include <time.h>
+#include "ui/selgame.h"
+#include "ui/simpleselgame.h"
+#include "cheat.h"
+#include "ui/datfile.h"
+#include "ui/inifile.h"
+
+//**************************************************************************
+// MACHINE MANAGER
+//**************************************************************************
+
+mame_machine_manager* mame_machine_manager::m_manager = nullptr;
+
+mame_machine_manager* mame_machine_manager::instance(emu_options &options,osd_interface &osd)
+{
+ if(!m_manager)
+ {
+ m_manager = global_alloc(mame_machine_manager(options,osd));
+ }
+ return m_manager;
+}
+
+mame_machine_manager* mame_machine_manager::instance()
+{
+ return m_manager;
+}
+
+//-------------------------------------------------
+// mame_machine_manager - constructor
+//-------------------------------------------------
+
+mame_machine_manager::mame_machine_manager(emu_options &options,osd_interface &osd)
+ : machine_manager(options, osd),
+ m_plugins(std::make_unique<plugin_options>()),
+ m_lua(global_alloc(lua_engine)),
+ m_new_driver_pending(nullptr)
+{
+}
+
+
+//-------------------------------------------------
+// ~mame_machine_manager - destructor
+//-------------------------------------------------
+
+mame_machine_manager::~mame_machine_manager()
+{
+ global_free(m_lua);
+ m_manager = nullptr;
+}
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+//-------------------------------------------------
+// mame_schedule_new_driver - schedule a new game to
+// be loaded
+//-------------------------------------------------
+
+void mame_machine_manager::schedule_new_driver(const game_driver &driver)
+{
+ m_new_driver_pending = &driver;
+}
+
+
+/***************************************************************************
+ CORE IMPLEMENTATION
+***************************************************************************/
+void mame_machine_manager::update_machine()
+{
+ m_lua->set_machine(m_machine);
+ m_lua->attach_notifiers();
+}
+
+
+std::vector<std::string> split(const std::string &text, char sep)
+{
+ std::vector<std::string> tokens;
+ std::size_t start = 0, end = 0;
+ while ((end = text.find(sep, start)) != std::string::npos) {
+ std::string temp = text.substr(start, end - start);
+ if (temp != "") tokens.push_back(temp);
+ start = end + 1;
+ }
+ std::string temp = text.substr(start);
+ if (temp != "") tokens.push_back(temp);
+ return tokens;
+}
+
+void mame_machine_manager::start_luaengine()
+{
+ if (options().plugins())
+ {
+ path_iterator iter(options().plugins_path());
+ std::string pluginpath;
+ while (iter.next(pluginpath))
+ {
+ m_plugins->parse_json(pluginpath);
+ }
+ std::vector<std::string> include = split(options().plugin(),',');
+ std::vector<std::string> exclude = split(options().no_plugin(),',');
+ {
+ // parse the file
+ std::string error;
+ // attempt to open the output file
+ emu_file file(options().ini_path(), OPEN_FLAG_READ);
+ if (file.open("plugin.ini") == osd_file::error::NONE)
+ {
+ bool result = m_plugins->parse_ini_file((util::core_file&)file, OPTION_PRIORITY_MAME_INI, OPTION_PRIORITY_DRIVER_INI, error);
+ if (!result)
+ osd_printf_error("**Error loading plugin.ini**");
+ }
+ }
+ for (auto &curentry : *m_plugins)
+ {
+ if (!curentry.is_header())
+ {
+ if (std::find(include.begin(), include.end(), curentry.name()) != include.end())
+ {
+ std::string error_string;
+ m_plugins->set_value(curentry.name(), "1", OPTION_PRIORITY_CMDLINE, error_string);
+ }
+ if (std::find(exclude.begin(), exclude.end(), curentry.name()) != exclude.end())
+ {
+ std::string error_string;
+ m_plugins->set_value(curentry.name(), "0", OPTION_PRIORITY_CMDLINE, error_string);
+ }
+ }
+ }
+ }
+ m_lua->initialize();
+
+ {
+ emu_file file(options().plugins_path(), OPEN_FLAG_READ);
+ osd_file::error filerr = file.open("boot.lua");
+ if (filerr == osd_file::error::NONE)
+ {
+ m_lua->load_script(file.fullpath());
+ }
+ }
+}
+
+/*-------------------------------------------------
+ execute - run the core emulation
+-------------------------------------------------*/
+
+int mame_machine_manager::execute()
+{
+ bool started_empty = false;
+
+ bool firstgame = true;
+ bool firstrun = true;
+
+ // loop across multiple hard resets
+ bool exit_pending = false;
+ int error = EMU_ERR_NONE;
+
+ if (m_options.console()) {
+ m_lua->start_console();
+ }
+ while (error == EMU_ERR_NONE && !exit_pending)
+ {
+ m_new_driver_pending = nullptr;
+
+ // if no driver, use the internal empty driver
+ const game_driver *system = m_options.system();
+ if (system == nullptr)
+ {
+ system = &GAME_NAME(___empty);
+ if (firstgame)
+ started_empty = true;
+ }
+
+ firstgame = false;
+
+ // parse any INI files as the first thing
+ if (m_options.read_config())
+ {
+ m_options.revert(OPTION_PRIORITY_INI);
+ std::string errors;
+ mame_options::parse_standard_inis(m_options,errors);
+ }
+
+ // otherwise, perform validity checks before anything else
+ if (system != nullptr)
+ {
+ validity_checker valid(m_options);
+ valid.set_verbose(false);
+ valid.check_shared_source(*system);
+ }
+
+ // create the machine configuration
+ machine_config config(*system, m_options);
+
+ // create the machine structure and driver
+ running_machine machine(config, *this);
+
+ set_machine(&machine);
+
+ // run the machine
+ error = machine.run(firstrun);
+ firstrun = false;
+
+ // check the state of the machine
+ if (m_new_driver_pending)
+ {
+ // set up new system name and adjust device options accordingly
+ mame_options::set_system_name(m_options,m_new_driver_pending->name);
+ firstrun = true;
+ }
+ else
+ {
+ if (machine.exit_pending()) mame_options::set_system_name(m_options,"");
+ }
+
+ if (machine.exit_pending() && (!started_empty || (system == &GAME_NAME(___empty))))
+ exit_pending = true;
+
+ // machine will go away when we exit scope
+ set_machine(nullptr);
+ }
+ // return an error
+ return error;
+}
+
+TIMER_CALLBACK_MEMBER(mame_machine_manager::autoboot_callback)
+{
+ if (strlen(options().autoboot_script())!=0) {
+ mame_machine_manager::instance()->lua()->load_script(options().autoboot_script());
+ }
+ else if (strlen(options().autoboot_command())!=0) {
+ std::string cmd = std::string(options().autoboot_command());
+ strreplace(cmd, "'", "\\'");
+ std::string val = std::string("emu.keypost('").append(cmd).append("')");
+ mame_machine_manager::instance()->lua()->load_string(val.c_str());
+ }
+}
+
+void mame_machine_manager::reset()
+{
+ // setup autoboot if needed
+ m_autoboot_timer->adjust(attotime(options().autoboot_delay(),0),0);
+}
+
+ui_manager* mame_machine_manager::create_ui(running_machine& machine)
+{
+ m_ui = std::make_unique<mame_ui_manager>(machine);
+ m_ui->init();
+
+ machine.add_notifier(MACHINE_NOTIFY_RESET, machine_notify_delegate(FUNC(mame_machine_manager::reset), this));
+
+ // start the inifile manager
+ m_inifile = std::make_unique<inifile_manager>(machine);
+
+ m_ui->set_startup_text("Initializing...", true);
+ // set up the cheat engine
+ m_cheat = std::make_unique<cheat_manager>(machine);
+
+ // allocate autoboot timer
+ m_autoboot_timer = machine.scheduler().timer_alloc(timer_expired_delegate(FUNC(mame_machine_manager::autoboot_callback), this));
+
+ // start datfile manager
+ m_datfile = std::make_unique<datfile_manager>(machine);
+
+ // start favorite manager
+ m_favorite = std::make_unique<favorite_manager>(machine);
+
+ return m_ui.get();
+}
+
+void mame_machine_manager::ui_initialize(running_machine& machine,bool firstrun)
+{
+ m_ui->initialize(machine);
+
+ // display the startup screens
+ m_ui->display_startup_screens(firstrun);
+}
+
+const char * emulator_info::get_bare_build_version() { return bare_build_version; }
+const char * emulator_info::get_build_version() { return build_version; }
+
+void emulator_info::display_ui_chooser(running_machine& machine)
+{
+ // force the UI to show the game select screen
+ if (strcmp(machine.options().ui(), "simple") == 0) {
+ ui_simple_menu_select_game::force_game_select(machine, &machine.render().ui_container());
+ }
+ else {
+ ui_menu_select_game::force_game_select(machine, &machine.render().ui_container());
+ }
+}
+
+int emulator_info::start_frontend(emu_options &options, osd_interface &osd, int argc, char *argv[])
+{
+ cli_frontend frontend(options, osd);
+ return frontend.execute(argc, argv);
+}
+
+void emulator_info::draw_user_interface(running_machine& machine)
+{
+ mame_machine_manager::instance()->ui().update_and_render(&machine.render().ui_container());
+}
+
+void emulator_info::periodic_check()
+{
+ mame_machine_manager::instance()->lua()->periodic_check();
+}
+
+bool emulator_info::frame_hook()
+{
+ return mame_machine_manager::instance()->lua()->frame_hook();
+} \ No newline at end of file
diff --git a/src/frontend/mame/mame.h b/src/frontend/mame/mame.h
new file mode 100644
index 00000000000..33ce991e685
--- /dev/null
+++ b/src/frontend/mame/mame.h
@@ -0,0 +1,92 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles
+/***************************************************************************
+
+ mame.h
+
+ Controls execution of the core MAME system.
+***************************************************************************/
+
+#pragma once
+
+#ifndef __EMU_H__
+#error Dont include this file directly; include emu.h instead.
+#endif
+
+#ifndef __MAME_H__
+#define __MAME_H__
+
+#include "emu.h"
+#include <time.h>
+#include "pluginopts.h"
+#include "ui/ui.h"
+
+class osd_interface;
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+class lua_engine;
+class cheat_manager;
+class datfile_manager;
+class inifile_manager;
+class favorite_manager;
+class mame_ui_manager;
+
+// ======================> machine_manager
+
+class mame_machine_manager : machine_manager
+{
+ DISABLE_COPYING(mame_machine_manager);
+private:
+ // construction/destruction
+ mame_machine_manager(emu_options &options, osd_interface &osd);
+public:
+ static mame_machine_manager *instance(emu_options &options, osd_interface &osd);
+ static mame_machine_manager *instance();
+ ~mame_machine_manager();
+
+ plugin_options &plugins() const { return *m_plugins; }
+ lua_engine *lua() { return m_lua; }
+
+ virtual void update_machine() override;
+
+ void reset();
+ TIMER_CALLBACK_MEMBER(autoboot_callback);
+
+ virtual ui_manager* create_ui(running_machine& machine) override;
+ virtual void ui_initialize(running_machine& machine,bool firstrun) override;
+
+ /* execute as configured by the OPTION_SYSTEMNAME option on the specified options */
+ int execute();
+ void start_luaengine();
+ void schedule_new_driver(const game_driver &driver);
+ mame_ui_manager& ui() const { assert(m_ui != nullptr); return *m_ui; }
+ cheat_manager &cheat() const { assert(m_cheat != nullptr); return *m_cheat; }
+ datfile_manager &datfile() const { assert(m_datfile != nullptr); return *m_datfile; }
+ inifile_manager &inifile() const { assert(m_inifile != nullptr); return *m_inifile; }
+ favorite_manager &favorite() const { assert(m_favorite != nullptr); return *m_favorite; }
+private:
+ std::unique_ptr<plugin_options> m_plugins; // pointer to plugin options
+ lua_engine * m_lua;
+
+ const game_driver * m_new_driver_pending; // pointer to the next pending driver
+
+ static mame_machine_manager* m_manager;
+ emu_timer *m_autoboot_timer; // autoboot timer
+ std::unique_ptr<mame_ui_manager> m_ui; // internal data from ui.cpp
+ std::unique_ptr<cheat_manager> m_cheat; // internal data from cheat.cpp
+ std::unique_ptr<datfile_manager> m_datfile; // internal data from datfile.c
+ std::unique_ptr<inifile_manager> m_inifile; // internal data from inifile.c for INIs
+ std::unique_ptr<favorite_manager> m_favorite; // internal data from inifile.c for favorites
+
+};
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+extern const char build_version[];
+extern const char bare_build_version[];
+
+#endif /* __MAME_H__ */
diff --git a/src/frontend/mame/mameopts.cpp b/src/frontend/mame/mameopts.cpp
new file mode 100644
index 00000000000..a0754f4cfd5
--- /dev/null
+++ b/src/frontend/mame/mameopts.cpp
@@ -0,0 +1,426 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+/***************************************************************************
+
+ mameopts.c
+
+ Options file and command line management.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "mameopts.h"
+#include "drivenum.h"
+#include "softlist.h"
+
+#include <ctype.h>
+
+int mame_options::m_slot_options = 0;
+int mame_options::m_device_options = 0;
+
+//-------------------------------------------------
+// add_slot_options - add all of the slot
+// options for the configured system
+//-------------------------------------------------
+
+bool mame_options::add_slot_options(emu_options &options, const software_part *swpart)
+{
+ // look up the system configured by name; if no match, do nothing
+ const game_driver *cursystem = options.system();
+ if (cursystem == nullptr)
+ return false;
+
+ // create the configuration
+ machine_config config(*cursystem, options);
+
+ // iterate through all slot devices
+ int starting_count = options.options_count();
+ for (const device_slot_interface &slot : slot_interface_iterator(config.root_device()))
+ {
+ // skip fixed slots
+ if (slot.fixed())
+ continue;
+
+ // retrieve info about the device instance
+ const char *name = slot.device().tag() + 1;
+ if (!options.exists(name))
+ {
+ // first device? add the header as to be pretty
+ if (m_slot_options++ == 0)
+ options.add_entry(nullptr, "SLOT DEVICES", OPTION_HEADER | OPTION_FLAG_DEVICE);
+
+ // add the option
+ options.add_entry(name, nullptr, OPTION_STRING | OPTION_FLAG_DEVICE, slot.default_option(), true);
+ }
+
+ // allow software lists to supply their own defaults
+ if (swpart != nullptr)
+ {
+ std::string featurename = std::string(name).append("_default");
+ const char *value = swpart->feature(featurename.c_str());
+ if (value != nullptr && (*value == '\0' || slot.option(value) != nullptr))
+ {
+ // set priority above INIs but below actual command line
+ std::string error;
+ options.set_value(name, value, OPTION_PRIORITY_SUBCMD, error);
+ }
+ }
+ }
+ return (options.options_count() != starting_count);
+}
+
+
+//-------------------------------------------------
+// update_slot_options - update slot values
+// depending of image mounted
+//-------------------------------------------------
+
+void mame_options::update_slot_options(emu_options &options, const software_part *swpart)
+{
+ // look up the system configured by name; if no match, do nothing
+ const game_driver *cursystem = options.system();
+ if (cursystem == nullptr)
+ return;
+ machine_config config(*cursystem, options);
+
+ // iterate through all slot devices
+ for (device_slot_interface &slot : slot_interface_iterator(config.root_device()))
+ {
+ // retrieve info about the device instance
+ const char *name = slot.device().tag() + 1;
+ if (options.exists(name) && !slot.option_list().empty())
+ {
+ std::string defvalue = slot.get_default_card_software();
+ if (defvalue.empty())
+ {
+ // keep any non-default setting
+ if (options.priority(name) > OPTION_PRIORITY_DEFAULT)
+ continue;
+
+ // reinstate the actual default value as configured
+ if (slot.default_option() != nullptr)
+ defvalue.assign(slot.default_option());
+ }
+
+ // set the value and hide the option if not selectable
+ options.set_default_value(name, defvalue.c_str());
+ const device_slot_option *option = slot.option(defvalue.c_str());
+ options.set_flag(name, ~OPTION_FLAG_INTERNAL, (option != nullptr && !option->selectable()) ? OPTION_FLAG_INTERNAL : 0);
+ }
+ }
+ while (add_slot_options(options,swpart)) {}
+ add_device_options(options);
+}
+
+
+//-------------------------------------------------
+// add_device_options - add all of the device
+// options for the configured system
+//-------------------------------------------------
+
+void mame_options::add_device_options(emu_options &options)
+{
+ // look up the system configured by name; if no match, do nothing
+ const game_driver *cursystem = options.system();
+ if (cursystem == nullptr)
+ return;
+ machine_config config(*cursystem, options);
+
+ // iterate through all image devices
+ for (const device_image_interface &image : image_interface_iterator(config.root_device()))
+ {
+ if (!image.user_loadable())
+ continue;
+
+ // retrieve info about the device instance
+ std::ostringstream option_name;
+ util::stream_format(option_name, "%s;%s", image.instance_name(), image.brief_instance_name());
+ if (strcmp(image.device_typename(image.image_type()), image.instance_name()) == 0)
+ util::stream_format(option_name, ";%s1;%s1", image.instance_name(), image.brief_instance_name());
+
+ // add the option
+ if (!options.exists(image.instance_name()))
+ {
+ // first device? add the header as to be pretty
+ if (m_device_options++ == 0)
+ options.add_entry(nullptr, "IMAGE DEVICES", OPTION_HEADER | OPTION_FLAG_DEVICE);
+
+ // add the option
+ options.add_entry(option_name.str().c_str(), nullptr, OPTION_STRING | OPTION_FLAG_DEVICE, nullptr, true);
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// remove_device_options - remove device options
+//-------------------------------------------------
+
+void mame_options::remove_device_options(emu_options &options)
+{
+ // iterate through options and remove interesting ones
+ core_options::entry *nextentry;
+ for (auto *curentry = options.first(); curentry != nullptr; curentry = nextentry)
+ {
+ // pre-fetch the next entry in case we delete this one
+ nextentry = curentry->next();
+
+ // if this is a device option, nuke it
+ if ((curentry->flags() & OPTION_FLAG_DEVICE) != 0)
+ options.remove_entry(*curentry);
+ }
+
+ // take also care of ramsize options
+ options.set_default_value(OPTION_RAMSIZE, "");
+
+ // reset counters
+ m_slot_options = 0;
+ m_device_options = 0;
+}
+
+
+//-------------------------------------------------
+// parse_slot_devices - parse the command line
+// and update slot and image devices
+//-------------------------------------------------
+
+bool mame_options::parse_slot_devices(emu_options &options, int argc, char *argv[], std::string &error_string, const char *name, const char *value, const software_part *swpart)
+{
+ // an initial parse to capture the initial set of values
+ bool result;
+
+ options.parse_command_line(argc, argv, OPTION_PRIORITY_CMDLINE, error_string);
+
+ // keep adding slot options until we stop seeing new stuff
+ while (add_slot_options(options,swpart))
+ options.parse_command_line(argc, argv, OPTION_PRIORITY_CMDLINE, error_string);
+
+ // add device options and reparse
+ add_device_options(options);
+ if (name != nullptr && options.exists(name))
+ options.set_value(name, value, OPTION_PRIORITY_SUBCMD, error_string);
+ options.parse_command_line(argc, argv, OPTION_PRIORITY_CMDLINE, error_string);
+
+ int num;
+ do {
+ num = options.options_count();
+ update_slot_options(options,swpart);
+ result = options.parse_command_line(argc, argv, OPTION_PRIORITY_CMDLINE, error_string);
+ } while (num != options.options_count());
+
+ options.update_cached_options();
+
+ return result;
+}
+
+
+//-------------------------------------------------
+// parse_command_line - parse the command line
+// and update the devices
+//-------------------------------------------------
+
+bool mame_options::parse_command_line(emu_options &options, int argc, char *argv[], std::string &error_string)
+{
+ // parse as normal
+ options.parse_command_line(argc, argv, OPTION_PRIORITY_CMDLINE, error_string);
+ bool result = parse_slot_devices(options,argc, argv, error_string);
+ options.update_cached_options();
+ return result;
+}
+
+
+//-------------------------------------------------
+// parse_standard_inis - parse the standard set
+// of INI files
+//-------------------------------------------------
+
+void mame_options::parse_standard_inis(emu_options &options, std::string &error_string, const game_driver *driver)
+{
+ // start with an empty string
+ error_string.clear();
+
+ // parse the INI file defined by the platform (e.g., "mame.ini")
+ // we do this twice so that the first file can change the INI path
+ parse_one_ini(options,emulator_info::get_configname(), OPTION_PRIORITY_MAME_INI);
+ parse_one_ini(options,emulator_info::get_configname(), OPTION_PRIORITY_MAME_INI, &error_string);
+
+ // debug mode: parse "debug.ini" as well
+ if (options.debug())
+ parse_one_ini(options,"debug", OPTION_PRIORITY_DEBUG_INI, &error_string);
+
+ // if we have a valid system driver, parse system-specific INI files
+ const game_driver *cursystem = (driver == nullptr) ? options.system() : driver;
+ if (cursystem == nullptr)
+ return;
+
+ // parse "vertical.ini" or "horizont.ini"
+ if (cursystem->flags & ORIENTATION_SWAP_XY)
+ parse_one_ini(options,"vertical", OPTION_PRIORITY_ORIENTATION_INI, &error_string);
+ else
+ parse_one_ini(options,"horizont", OPTION_PRIORITY_ORIENTATION_INI, &error_string);
+
+ if (cursystem->flags & MACHINE_TYPE_ARCADE)
+ parse_one_ini(options,"arcade", OPTION_PRIORITY_SYSTYPE_INI, &error_string);
+ else if (cursystem->flags & MACHINE_TYPE_CONSOLE)
+ parse_one_ini(options,"console", OPTION_PRIORITY_SYSTYPE_INI, &error_string);
+ else if (cursystem->flags & MACHINE_TYPE_COMPUTER)
+ parse_one_ini(options,"computer", OPTION_PRIORITY_SYSTYPE_INI, &error_string);
+ else if (cursystem->flags & MACHINE_TYPE_OTHER)
+ parse_one_ini(options,"othersys", OPTION_PRIORITY_SYSTYPE_INI, &error_string);
+
+ machine_config config(*cursystem, options);
+ for (const screen_device &device : screen_device_iterator(config.root_device()))
+ {
+ // parse "raster.ini" for raster games
+ if (device.screen_type() == SCREEN_TYPE_RASTER)
+ {
+ parse_one_ini(options,"raster", OPTION_PRIORITY_SCREEN_INI, &error_string);
+ break;
+ }
+ // parse "vector.ini" for vector games
+ if (device.screen_type() == SCREEN_TYPE_VECTOR)
+ {
+ parse_one_ini(options,"vector", OPTION_PRIORITY_SCREEN_INI, &error_string);
+ break;
+ }
+ // parse "lcd.ini" for lcd games
+ if (device.screen_type() == SCREEN_TYPE_LCD)
+ {
+ parse_one_ini(options,"lcd", OPTION_PRIORITY_SCREEN_INI, &error_string);
+ break;
+ }
+ }
+
+ // next parse "source/<sourcefile>.ini"; if that doesn't exist, try <sourcefile>.ini
+ std::string sourcename = core_filename_extract_base(cursystem->source_file, true).insert(0, "source" PATH_SEPARATOR);
+ if (!parse_one_ini(options,sourcename.c_str(), OPTION_PRIORITY_SOURCE_INI, &error_string))
+ {
+ sourcename = core_filename_extract_base(cursystem->source_file, true);
+ parse_one_ini(options,sourcename.c_str(), OPTION_PRIORITY_SOURCE_INI, &error_string);
+ }
+
+ // then parse the grandparent, parent, and system-specific INIs
+ int parent = driver_list::clone(*cursystem);
+ int gparent = (parent != -1) ? driver_list::clone(parent) : -1;
+ if (gparent != -1)
+ parse_one_ini(options,driver_list::driver(gparent).name, OPTION_PRIORITY_GPARENT_INI, &error_string);
+ if (parent != -1)
+ parse_one_ini(options,driver_list::driver(parent).name, OPTION_PRIORITY_PARENT_INI, &error_string);
+ parse_one_ini(options,cursystem->name, OPTION_PRIORITY_DRIVER_INI, &error_string);
+
+ // Re-evaluate slot options after loading ini files
+ update_slot_options(options);
+
+ options.update_cached_options();
+}
+
+//-------------------------------------------------
+// set_system_name - set a new system name
+//-------------------------------------------------
+
+void mame_options::set_system_name(emu_options &options, const char *name)
+{
+ // remember the original system name
+ std::string old_system_name(options.system_name());
+ bool new_system = old_system_name.compare(name) != 0;
+
+ // if the system name changed, fix up the device options
+ if (new_system)
+ {
+ // first set the new name
+ std::string error;
+ options.set_value(OPTION_SYSTEMNAME, name, OPTION_PRIORITY_CMDLINE, error);
+ assert(error.empty());
+
+ // remove any existing device options
+ remove_device_options(options);
+ }
+ else
+ {
+ // revert device options set for the old software
+ options.revert(OPTION_PRIORITY_SUBCMD, OPTION_PRIORITY_SUBCMD);
+ }
+
+ // get the new system
+ const game_driver *cursystem = options.system();
+ if (cursystem == nullptr)
+ return;
+
+ if (*options.software_name() != 0)
+ {
+ std::string sw_load(options.software_name());
+ std::string sw_list, sw_name, sw_part, sw_instance, error_string;
+ int left = sw_load.find_first_of(':');
+ int middle = sw_load.find_first_of(':', left + 1);
+ int right = sw_load.find_last_of(':');
+
+ sw_list = sw_load.substr(0, left - 1);
+ sw_name = sw_load.substr(left + 1, middle - left - 1);
+ sw_part = sw_load.substr(middle + 1, right - middle - 1);
+ sw_instance = sw_load.substr(right + 1);
+ sw_load.assign(sw_load.substr(0, right));
+
+ // look up the software part
+ machine_config config(*cursystem, options);
+ software_list_device *swlist = software_list_device::find_by_name(config, sw_list.c_str());
+ software_info *swinfo = swlist != nullptr ? swlist->find(sw_name.c_str()) : nullptr;
+ software_part *swpart = swinfo != nullptr ? swinfo->find_part(sw_part.c_str()) : nullptr;
+
+ // then add the options
+ if (new_system)
+ {
+ while (add_slot_options(options,swpart)) {}
+ add_device_options(options);
+ }
+
+ options.set_value(OPTION_SOFTWARENAME, sw_name.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
+ if (options.exists(sw_instance.c_str()))
+ options.set_value(sw_instance.c_str(), sw_load.c_str(), OPTION_PRIORITY_SUBCMD, error_string);
+
+ int num;
+ do {
+ num = options.options_count();
+ update_slot_options(options,swpart);
+ } while (num != options.options_count());
+ }
+ else if (new_system)
+ {
+ // add the options afresh
+ while (add_slot_options(options)) {}
+ add_device_options(options);
+ int num;
+ do {
+ num = options.options_count();
+ update_slot_options(options);
+ } while (num != options.options_count());
+ }
+}
+
+//-------------------------------------------------
+// parse_one_ini - parse a single INI file
+//-------------------------------------------------
+
+bool mame_options::parse_one_ini(emu_options &options, const char *basename, int priority, std::string *error_string)
+{
+ // don't parse if it has been disabled
+ if (!options.read_config())
+ return false;
+
+ // open the file; if we fail, that's ok
+ emu_file file(options.ini_path(), OPEN_FLAG_READ);
+ osd_file::error filerr = file.open(basename, ".ini");
+ if (filerr != osd_file::error::NONE)
+ return false;
+
+ // parse the file
+ osd_printf_verbose("Parsing %s.ini\n", basename);
+ std::string error;
+ bool result = options.parse_ini_file((util::core_file&)file, priority, OPTION_PRIORITY_DRIVER_INI, error);
+
+ // append errors if requested
+ if (!error.empty() && error_string)
+ error_string->append(string_format("While parsing %s:\n%s\n", file.fullpath(), error));
+
+ return result;
+}
+
diff --git a/src/frontend/mame/mameopts.h b/src/frontend/mame/mameopts.h
new file mode 100644
index 00000000000..50b1ae5b776
--- /dev/null
+++ b/src/frontend/mame/mameopts.h
@@ -0,0 +1,78 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+/***************************************************************************
+
+ mameopts.h
+
+ Options file and command line management.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __MAMEOPTS_H__
+#define __MAMEOPTS_H__
+
+#include "emuopts.h"
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+#undef OPTION_PRIORITY_CMDLINE
+
+// option priorities
+enum
+{
+ // command-line options are HIGH priority
+ OPTION_PRIORITY_SUBCMD = OPTION_PRIORITY_HIGH,
+ OPTION_PRIORITY_CMDLINE,
+
+ // INI-based options are NORMAL priority, in increasing order:
+ OPTION_PRIORITY_MAME_INI = OPTION_PRIORITY_NORMAL + 1,
+ OPTION_PRIORITY_DEBUG_INI,
+ OPTION_PRIORITY_ORIENTATION_INI,
+ OPTION_PRIORITY_SYSTYPE_INI,
+ OPTION_PRIORITY_SCREEN_INI,
+ OPTION_PRIORITY_SOURCE_INI,
+ OPTION_PRIORITY_GPARENT_INI,
+ OPTION_PRIORITY_PARENT_INI,
+ OPTION_PRIORITY_DRIVER_INI,
+ OPTION_PRIORITY_INI,
+};
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// forward references
+struct game_driver;
+class software_part;
+
+class mame_options
+{
+ static const UINT32 OPTION_FLAG_DEVICE = 0x80000000;
+
+public:
+ // parsing wrappers
+ static bool parse_command_line(emu_options &options, int argc, char *argv[], std::string &error_string);
+ static void parse_standard_inis(emu_options &options, std::string &error_string, const game_driver *driver = nullptr);
+ static bool parse_slot_devices(emu_options &options, int argc, char *argv[], std::string &error_string, const char *name = nullptr, const char *value = nullptr, const software_part *swpart = nullptr);
+ // FIXME: Couriersud: This should be in image_device_exit
+ static void remove_device_options(emu_options &options);
+
+ static void set_system_name(emu_options &options, const char *name);
+ static bool add_slot_options(emu_options &options, const software_part *swpart = nullptr);
+private:
+ // device-specific option handling
+ static void add_device_options(emu_options &options);
+ static void update_slot_options(emu_options &options, const software_part *swpart = nullptr);
+
+ // INI parsing helper
+ static bool parse_one_ini(emu_options &options, const char *basename, int priority, std::string *error_string = nullptr);
+
+ static int m_slot_options;
+ static int m_device_options;
+
+};
+
+#endif /* __MAMEOPTS_H__ */
diff --git a/src/frontend/mame/pluginopts.cpp b/src/frontend/mame/pluginopts.cpp
new file mode 100644
index 00000000000..90b4b138cab
--- /dev/null
+++ b/src/frontend/mame/pluginopts.cpp
@@ -0,0 +1,97 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/***************************************************************************
+
+ pluginopts.cpp
+
+ Plugin options manager.
+
+***************************************************************************/
+#include <fstream>
+#include "emu.h"
+#include "pluginopts.h"
+
+#include <rapidjson/document.h>
+#include <rapidjson/error/en.h>
+#include <rapidjson/istreamwrapper.h>
+#include <fstream>
+
+//**************************************************************************
+// PLUGIN OPTIONS
+//**************************************************************************
+
+const options_entry plugin_options::s_option_entries[] =
+{
+ { nullptr, nullptr, OPTION_HEADER, "PLUGINS OPTIONS" },
+ { nullptr }
+};
+
+//-------------------------------------------------
+// plugin_options - constructor
+//-------------------------------------------------
+
+plugin_options::plugin_options()
+: core_options()
+{
+ add_entries(plugin_options::s_option_entries);
+}
+
+
+void plugin_options::parse_json(std::string path)
+{
+ // first try to open as a directory
+ osd_directory *directory = osd_opendir(path.c_str());
+ if (directory != nullptr)
+ {
+ // iterate over all files in the directory
+ for (const osd_directory_entry *entry = osd_readdir(directory); entry != nullptr; entry = osd_readdir(directory))
+ {
+ if (entry->type == ENTTYPE_FILE)
+ {
+ std::string name = entry->name;
+ if (name == "plugin.json")
+ {
+ std::string curfile = std::string(path).append(PATH_SEPARATOR).append(entry->name);
+ std::ifstream ifs(curfile);
+ rapidjson::IStreamWrapper isw(ifs);
+ rapidjson::Document document;
+ document.ParseStream<0>(isw);
+
+ if (document.HasParseError()) {
+ std::string error(GetParseError_En(document.GetParseError()));
+ osd_printf_error("Unable to parse plugin definition file %s. Errors returned:\n", curfile.c_str());
+ osd_printf_error("%s\n", error.c_str());
+ return;
+ }
+
+ if (document["plugin"].IsObject())
+ {
+ std::string name = document["plugin"]["name"].GetString();
+ std::string description = document["plugin"]["description"].GetString();
+ std::string type = document["plugin"]["type"].GetString();
+ bool start = false;
+ if (document["plugin"].HasMember("start") && (std::string(document["plugin"]["start"].GetString()) == "true"))
+ start = true;
+
+ if (type=="plugin")
+ {
+ add_entry(core_strdup(name.c_str()),core_strdup(description.c_str()), OPTION_BOOLEAN, start ? "1" : "0");
+ }
+ }
+
+ }
+ }
+ else if (entry->type == ENTTYPE_DIR)
+ {
+ std::string name = entry->name;
+ if (!(name == "." || name == ".."))
+ {
+ parse_json(path + PATH_SEPARATOR + name);
+ }
+ }
+ }
+
+ // close the directory and be done
+ osd_closedir(directory);
+ }
+}
diff --git a/src/frontend/mame/pluginopts.h b/src/frontend/mame/pluginopts.h
new file mode 100644
index 00000000000..91aa68c2208
--- /dev/null
+++ b/src/frontend/mame/pluginopts.h
@@ -0,0 +1,29 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/***************************************************************************
+
+ pluginopts.cpp
+
+ Plugin options manager.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __PLUGIN_OPTS_H__
+#define __PLUGIN_OPTS_H__
+
+#include "options.h"
+
+class plugin_options : public core_options
+{
+public:
+ // construction/destruction
+ plugin_options();
+
+ void parse_json(std::string path);
+private:
+ static const options_entry s_option_entries[];
+};
+
+#endif /* __PLUGIN_OPTS_H__ */
diff --git a/src/frontend/mame/ui/auditmenu.cpp b/src/frontend/mame/ui/auditmenu.cpp
new file mode 100644
index 00000000000..3c1ddace6cf
--- /dev/null
+++ b/src/frontend/mame/ui/auditmenu.cpp
@@ -0,0 +1,204 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/*********************************************************************
+
+ ui/auditmenu.cpp
+
+ Internal UI user interface.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "ui/ui.h"
+#include "ui/menu.h"
+#include "audit.h"
+#include "ui/auditmenu.h"
+
+extern const char UI_VERSION_TAG[];
+
+//-------------------------------------------------
+// sort
+//-------------------------------------------------
+
+inline int cs_stricmp(const char *s1, const char *s2)
+{
+ for (;;)
+ {
+ int c1 = tolower((UINT8)*s1++);
+ int c2 = tolower((UINT8)*s2++);
+ if (c1 == 0 || c1 != c2)
+ return c1 - c2;
+ }
+}
+
+bool sorted_game_list(const game_driver *x, const game_driver *y)
+{
+ bool clonex = strcmp(x->parent, "0");
+ bool cloney = strcmp(y->parent, "0");
+
+ if (!clonex && !cloney)
+ return (cs_stricmp(x->description, y->description) < 0);
+
+ int cx = -1, cy = -1;
+ if (clonex)
+ {
+ cx = driver_list::find(x->parent);
+ if (cx == -1 || (driver_list::driver(cx).flags & MACHINE_IS_BIOS_ROOT) != 0)
+ clonex = false;
+ }
+
+ if (cloney)
+ {
+ cy = driver_list::find(y->parent);
+ if (cy == -1 || (driver_list::driver(cy).flags & MACHINE_IS_BIOS_ROOT) != 0)
+ cloney = false;
+ }
+
+ if (!clonex && !cloney)
+ return (cs_stricmp(x->description, y->description) < 0);
+ else if (clonex && cloney)
+ {
+ if (!cs_stricmp(x->parent, y->parent))
+ return (cs_stricmp(x->description, y->description) < 0);
+ else
+ return (cs_stricmp(driver_list::driver(cx).description, driver_list::driver(cy).description) < 0);
+ }
+ else if (!clonex && cloney)
+ {
+ if (!cs_stricmp(x->name, y->parent))
+ return true;
+ else
+ return (cs_stricmp(x->description, driver_list::driver(cy).description) < 0);
+ }
+ else
+ {
+ if (!cs_stricmp(x->parent, y->name))
+ return false;
+ else
+ return (cs_stricmp(driver_list::driver(cx).description, y->description) < 0);
+ }
+}
+
+//-------------------------------------------------
+// ctor / dtor
+//-------------------------------------------------
+
+ui_menu_audit::ui_menu_audit(running_machine &machine, render_container *container, vptr_game &availablesorted, vptr_game &unavailablesorted, int _audit_mode)
+ : ui_menu(machine, container)
+ , m_availablesorted(availablesorted)
+ , m_unavailablesorted(unavailablesorted)
+ , m_audit_mode(_audit_mode)
+ , m_first(true)
+{
+ if (m_audit_mode == 2)
+ {
+ m_availablesorted.clear();
+ m_unavailablesorted.clear();
+ }
+}
+
+ui_menu_audit::~ui_menu_audit()
+{
+}
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_menu_audit::handle()
+{
+ process(UI_MENU_PROCESS_CUSTOM_ONLY);
+
+ if (m_first)
+ {
+ mame_machine_manager::instance()->ui().draw_text_box(container, _("Audit in progress..."), JUSTIFY_CENTER, 0.5f, 0.5f, UI_GREEN_COLOR);
+ m_first = false;
+ return;
+ }
+
+ if (m_audit_mode == 1)
+ {
+ vptr_game::iterator iter = m_unavailablesorted.begin();
+ while (iter != m_unavailablesorted.end())
+ {
+ driver_enumerator enumerator(machine().options(), (*iter)->name);
+ enumerator.next();
+ media_auditor auditor(enumerator);
+ media_auditor::summary summary = auditor.audit_media(AUDIT_VALIDATE_FAST);
+
+ // if everything looks good, include the driver
+ if (summary == media_auditor::CORRECT || summary == media_auditor::BEST_AVAILABLE || summary == media_auditor::NONE_NEEDED)
+ {
+ m_availablesorted.push_back((*iter));
+ iter = m_unavailablesorted.erase(iter);
+ }
+ else
+ ++iter;
+ }
+ }
+ else
+ {
+ driver_enumerator enumerator(machine().options());
+ media_auditor auditor(enumerator);
+ while (enumerator.next())
+ {
+ media_auditor::summary summary = auditor.audit_media(AUDIT_VALIDATE_FAST);
+
+ // if everything looks good, include the driver
+ if (summary == media_auditor::CORRECT || summary == media_auditor::BEST_AVAILABLE || summary == media_auditor::NONE_NEEDED)
+ m_availablesorted.push_back(&enumerator.driver());
+ else
+ m_unavailablesorted.push_back(&enumerator.driver());
+ }
+ }
+
+ // sort
+ std::stable_sort(m_availablesorted.begin(), m_availablesorted.end(), sorted_game_list);
+ std::stable_sort(m_unavailablesorted.begin(), m_unavailablesorted.end(), sorted_game_list);
+ save_available_machines();
+ ui_menu::menu_stack->parent->reset(UI_MENU_RESET_SELECT_FIRST);
+ ui_menu::stack_pop(machine());
+}
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_audit::populate()
+{
+ item_append("Dummy", nullptr, 0, (void *)(FPTR)1);
+}
+
+//-------------------------------------------------
+// save drivers infos to file
+//-------------------------------------------------
+
+void ui_menu_audit::save_available_machines()
+{
+ // attempt to open the output file
+ emu_file file(mame_machine_manager::instance()->ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ if (file.open(emulator_info::get_configname(), "_avail.ini") == osd_file::error::NONE)
+ {
+ // generate header
+ std::ostringstream buffer;
+ buffer << "#\n" << UI_VERSION_TAG << emulator_info::get_bare_build_version() << "\n#\n\n";
+ util::stream_format(buffer, "%d\n", m_availablesorted.size());
+ util::stream_format(buffer, "%d\n", m_unavailablesorted.size());
+
+ // generate available list
+ for (size_t x = 0; x < m_availablesorted.size(); ++x)
+ {
+ int find = driver_list::find(m_availablesorted[x]->name);
+ util::stream_format(buffer, "%d\n", find);
+ }
+
+ // generate unavailable list
+ for (size_t x = 0; x < m_unavailablesorted.size(); ++x)
+ {
+ int find = driver_list::find(m_unavailablesorted[x]->name);
+ util::stream_format(buffer, "%d\n", find);
+ }
+ file.puts(buffer.str().c_str());
+ file.close();
+ }
+}
diff --git a/src/frontend/mame/ui/auditmenu.h b/src/frontend/mame/ui/auditmenu.h
new file mode 100644
index 00000000000..b63bbb6507b
--- /dev/null
+++ b/src/frontend/mame/ui/auditmenu.h
@@ -0,0 +1,41 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/***************************************************************************
+
+ ui/auditmenu.h
+
+ Internal UI user interface.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_AUDIT_H__
+#define __UI_AUDIT_H__
+
+//-------------------------------------------------
+// class audit menu
+//-------------------------------------------------
+using vptr_game = std::vector<const game_driver *>;
+
+class ui_menu_audit : public ui_menu
+{
+public:
+ ui_menu_audit(running_machine &machine, render_container *container, vptr_game &availablesorted, vptr_game &unavailablesorted, int audit_mode);
+ virtual ~ui_menu_audit();
+ virtual void populate() override;
+ virtual void handle() override;
+
+private:
+ vptr_game &m_availablesorted;
+ vptr_game &m_unavailablesorted;
+
+ int m_audit_mode;
+ void save_available_machines();
+ bool m_first;
+};
+
+inline int cs_stricmp(const char *s1, const char *s2);
+bool sorted_game_list(const game_driver *x, const game_driver *y);
+
+#endif /* __UI_AUDIT_H__ */
diff --git a/src/frontend/mame/ui/barcode.cpp b/src/frontend/mame/ui/barcode.cpp
new file mode 100644
index 00000000000..10dec5bde11
--- /dev/null
+++ b/src/frontend/mame/ui/barcode.cpp
@@ -0,0 +1,154 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli
+/***************************************************************************
+
+ ui/barcode.cpp
+
+ "Barcode Reader" control
+
+***************************************************************************/
+
+#include "emu.h"
+#include "ui/ui.h"
+#include "ui/menu.h"
+#include "ui/barcode.h"
+
+// itemrefs for key menu items
+#define ITEMREF_NEW_BARCODE ((void *) 0x0001)
+#define ITEMREF_ENTER_BARCODE ((void *) 0x0002)
+#define ITEMREF_SELECT_READER ((void *) 0x0003)
+
+
+/**************************************************
+
+ BARCODE READER MENU
+
+ **************************************************/
+
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+ui_menu_barcode_reader::ui_menu_barcode_reader(running_machine &machine, render_container *container, barcode_reader_device *device)
+ : ui_menu_device_control<barcode_reader_device>(machine, container, device)
+{
+}
+
+
+//-------------------------------------------------
+// dtor
+//-------------------------------------------------
+
+ui_menu_barcode_reader::~ui_menu_barcode_reader()
+{
+}
+
+//-------------------------------------------------
+// populate - populates the barcode input menu
+//-------------------------------------------------
+
+void ui_menu_barcode_reader::populate()
+{
+ if (current_device())
+ {
+ std::string buffer;
+ const char *new_barcode;
+
+ // selected device
+ item_append(current_display_name().c_str(), "", current_display_flags(), ITEMREF_SELECT_READER);
+
+ // append the "New Barcode" item
+ if (get_selection() == ITEMREF_NEW_BARCODE)
+ {
+ buffer.append(m_barcode_buffer);
+ new_barcode = buffer.c_str();
+ }
+ else
+ {
+ new_barcode = m_barcode_buffer;
+ }
+
+ item_append(_("New Barcode:"), new_barcode, 0, ITEMREF_NEW_BARCODE);
+
+ // finish up the menu
+ item_append(ui_menu_item_type::SEPARATOR);
+ item_append(_("Enter Code"), nullptr, 0, ITEMREF_ENTER_BARCODE);
+
+ customtop = mame_machine_manager::instance()->ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER;
+ }
+}
+
+
+//-------------------------------------------------
+// handle - manages inputs in the barcode input menu
+//-------------------------------------------------
+
+void ui_menu_barcode_reader::handle()
+{
+ // rebuild the menu (so to update the selected device, if the user has pressed L or R)
+ reset(UI_MENU_RESET_REMEMBER_POSITION);
+ populate();
+
+ // process the menu
+ const ui_menu_event *event = process(UI_MENU_PROCESS_LR_REPEAT);
+
+ // process the event
+ if (event != nullptr)
+ {
+ // handle selections
+ switch (event->iptkey)
+ {
+ case IPT_UI_LEFT:
+ if (event->itemref == ITEMREF_SELECT_READER)
+ previous();
+ break;
+
+ case IPT_UI_RIGHT:
+ if (event->itemref == ITEMREF_SELECT_READER)
+ next();
+ break;
+
+ case IPT_UI_SELECT:
+ if (event->itemref == ITEMREF_ENTER_BARCODE)
+ {
+ std::string tmp_file(m_barcode_buffer);
+ //printf("code %s\n", m_barcode_buffer);
+ if (!current_device()->is_valid(tmp_file.length()))
+ mame_machine_manager::instance()->ui().popup_time(5, "%s", _("Barcode length invalid!"));
+ else
+ {
+ current_device()->write_code(tmp_file.c_str(), tmp_file.length());
+ // if sending was successful, reset char buffer
+ if (m_barcode_buffer[0] != '\0')
+ memset(m_barcode_buffer, '\0', ARRAY_LENGTH(m_barcode_buffer));
+ reset(UI_MENU_RESET_REMEMBER_POSITION);
+ }
+ }
+ break;
+
+ case IPT_SPECIAL:
+ if (get_selection() == ITEMREF_NEW_BARCODE)
+ {
+ int buflen = strlen(m_barcode_buffer);
+
+ // if it's a backspace and we can handle it, do so
+ if ((event->unichar == 8 || event->unichar == 0x7f) && buflen > 0)
+ *(char *)utf8_previous_char(&m_barcode_buffer[buflen]) = 0;
+ else if (event->unichar >= '0' && event->unichar <= '9')
+ {
+ buflen += utf8_from_uchar(&m_barcode_buffer[buflen], ARRAY_LENGTH(m_barcode_buffer) - buflen, event->unichar);
+ m_barcode_buffer[buflen] = 0;
+ }
+ reset(UI_MENU_RESET_REMEMBER_POSITION);
+ }
+ break;
+
+ case IPT_UI_CANCEL:
+ // reset the char buffer also in this case
+ if (m_barcode_buffer[0] != '\0')
+ memset(m_barcode_buffer, '\0', ARRAY_LENGTH(m_barcode_buffer));
+ break;
+ }
+ }
+}
diff --git a/src/frontend/mame/ui/barcode.h b/src/frontend/mame/ui/barcode.h
new file mode 100644
index 00000000000..5a3dbff634e
--- /dev/null
+++ b/src/frontend/mame/ui/barcode.h
@@ -0,0 +1,31 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli
+/***************************************************************************
+
+ ui/barcode.h
+
+ "Barcode Reader" control
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_BARCODE_H__
+#define __UI_BARCODE_H__
+
+#include "machine/bcreader.h"
+#include "ui/devctrl.h"
+
+class ui_menu_barcode_reader : public ui_menu_device_control<barcode_reader_device> {
+public:
+ ui_menu_barcode_reader(running_machine &machine, render_container *container, barcode_reader_device *device);
+ virtual ~ui_menu_barcode_reader();
+ virtual void populate() override;
+ virtual void handle() override;
+
+private:
+ char m_barcode_buffer[20];
+};
+
+
+#endif // __UI_BARCODE_H__
diff --git a/src/frontend/mame/ui/cheatopt.cpp b/src/frontend/mame/ui/cheatopt.cpp
new file mode 100644
index 00000000000..8d84c06d759
--- /dev/null
+++ b/src/frontend/mame/ui/cheatopt.cpp
@@ -0,0 +1,320 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/*********************************************************************
+
+ ui/cheatopt.cpp
+
+ Internal menu for the cheat interface.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "cheat.h"
+
+#include "ui/ui.h"
+#include "ui/menu.h"
+#include "ui/cheatopt.h"
+
+/*-------------------------------------------------
+ menu_cheat - handle the cheat menu
+-------------------------------------------------*/
+
+void ui_menu_cheat::handle()
+{
+ /* process the menu */
+ const ui_menu_event *menu_event = process(UI_MENU_PROCESS_LR_REPEAT);
+
+
+ /* handle events */
+ if (menu_event != nullptr && menu_event->itemref != nullptr)
+ {
+ bool changed = false;
+
+ /* clear cheat comment on any movement or keypress */
+ machine().popmessage();
+
+ /* handle reset all + reset all cheats for reload all option */
+ if ((menu_event->itemref == ITEMREF_CHEATS_RESET_ALL || menu_event->itemref == ITEMREF_CHEATS_RELOAD_ALL) && menu_event->iptkey == IPT_UI_SELECT)
+ {
+ for (cheat_entry &curcheat : mame_machine_manager::instance()->cheat().entries())
+ if (curcheat.select_default_state())
+ changed = true;
+ }
+
+ /* handle individual cheats */
+ else if (menu_event->itemref >= ITEMREF_CHEATS_FIRST_ITEM)
+ {
+ cheat_entry *curcheat = reinterpret_cast<cheat_entry *>(menu_event->itemref);
+ const char *string;
+ switch (menu_event->iptkey)
+ {
+ /* if selected, activate a oneshot */
+ case IPT_UI_SELECT:
+ changed = curcheat->activate();
+ break;
+
+ /* if cleared, reset to default value */
+ case IPT_UI_CLEAR:
+ changed = curcheat->select_default_state();
+ break;
+
+ /* left decrements */
+ case IPT_UI_LEFT:
+ changed = curcheat->select_previous_state();
+ break;
+
+ /* right increments */
+ case IPT_UI_RIGHT:
+ changed = curcheat->select_next_state();
+ break;
+
+ /* bring up display comment if one exists */
+ case IPT_UI_DISPLAY_COMMENT:
+ case IPT_UI_UP:
+ case IPT_UI_DOWN:
+ string = curcheat->comment();
+ if (string != nullptr && string[0] != 0)
+ machine().popmessage(_("Cheat Comment:\n%s"), string);
+ break;
+ }
+ }
+
+ /* handle reload all */
+ if (menu_event->itemref == ITEMREF_CHEATS_RELOAD_ALL && menu_event->iptkey == IPT_UI_SELECT)
+ {
+ /* re-init cheat engine and thus reload cheats/cheats have already been turned off by here */
+ mame_machine_manager::instance()->cheat().reload();
+
+ /* display the reloaded cheats */
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ machine().popmessage(_("All cheats reloaded"));
+ }
+
+ /* handle autofire menu */
+ if (menu_event->itemref == ITEMREF_CHEATS_AUTOFIRE_SETTINGS && menu_event->iptkey == IPT_UI_SELECT)
+ {
+ ui_menu::stack_push(global_alloc_clear<ui_menu_autofire>(machine(), container));
+ }
+
+ /* if things changed, update */
+ if (changed)
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ }
+}
+
+
+/*-------------------------------------------------
+ menu_cheat_populate - populate the cheat menu
+-------------------------------------------------*/
+
+ui_menu_cheat::ui_menu_cheat(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+void ui_menu_cheat::populate()
+{
+ /* iterate over cheats */
+ std::string text;
+ std::string subtext;
+
+ // add the autofire menu
+ item_append(_("Autofire Settings"), nullptr, 0, (void *)ITEMREF_CHEATS_AUTOFIRE_SETTINGS);
+
+ /* add a separator */
+ item_append(ui_menu_item_type::SEPARATOR);
+
+ // add other cheats
+ if (!mame_machine_manager::instance()->cheat().entries().empty()) {
+ for (cheat_entry &curcheat : mame_machine_manager::instance()->cheat().entries())
+ {
+ UINT32 flags;
+ curcheat.menu_text(text, subtext, flags);
+ item_append(text.c_str(), subtext.c_str(), flags, &curcheat);
+ }
+
+ /* add a separator */
+ item_append(ui_menu_item_type::SEPARATOR);
+
+ /* add a reset all option */
+ item_append(_("Reset All"), nullptr, 0, (void *)ITEMREF_CHEATS_RESET_ALL);
+
+ /* add a reload all cheats option */
+ item_append(_("Reload All"), nullptr, 0, (void *)ITEMREF_CHEATS_RELOAD_ALL);
+ }
+}
+
+ui_menu_cheat::~ui_menu_cheat()
+{
+}
+
+
+
+
+
+/*-------------------------------------------------
+ menu_autofire - handle the autofire settings
+ menu
+-------------------------------------------------*/
+
+ui_menu_autofire::ui_menu_autofire(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+ const screen_device *screen = machine.first_screen();
+
+ if (screen == nullptr)
+ {
+ refresh = 60.0;
+ }
+ else
+ {
+ refresh = ATTOSECONDS_TO_HZ(screen->refresh_attoseconds());
+ }
+}
+
+ui_menu_autofire::~ui_menu_autofire()
+{
+}
+
+void ui_menu_autofire::handle()
+{
+ ioport_field *field;
+ bool changed = false;
+
+ /* process the menu */
+ const ui_menu_event *menu_event = process(0);
+
+ /* handle events */
+ if (menu_event != nullptr && menu_event->itemref != nullptr)
+ {
+ // menu item is changed using left/right keys only
+ if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
+ {
+ if (menu_event->itemref == ITEMREF_AUTOFIRE_STATUS)
+ {
+ // toggle autofire status
+ bool autofire_toggle = machine().ioport().get_autofire_toggle(); // (menu_event->iptkey == IPT_UI_LEFT);
+ machine().ioport().set_autofire_toggle(!autofire_toggle);
+ changed = true;
+ }
+ else if (menu_event->itemref == ITEMREF_AUTOFIRE_DELAY)
+ {
+ // change autofire frequency
+ int autofire_delay = machine().ioport().get_autofire_delay();
+ if (menu_event->iptkey == IPT_UI_LEFT)
+ {
+ autofire_delay--;
+ if (autofire_delay < 1)
+ autofire_delay = 1;
+ }
+ else
+ {
+ autofire_delay++;
+ if (autofire_delay > 30)
+ autofire_delay = 30;
+ }
+ machine().ioport().set_autofire_delay(autofire_delay);
+ changed = true;
+ }
+ else
+ {
+ // enable autofire on specific button
+ field = (ioport_field *)menu_event->itemref;
+ ioport_field::user_settings settings;
+ field->get_user_settings(settings);
+ settings.autofire = (menu_event->iptkey == IPT_UI_RIGHT);
+ field->set_user_settings(settings);
+ changed = true;
+ }
+ }
+ }
+
+ // if toggle settings changed, redraw menu to reflect new options
+ if (!changed)
+ {
+ changed = (last_toggle != machine().ioport().get_autofire_toggle());
+ }
+
+ /* if something changed, rebuild the menu */
+ if (changed)
+ {
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ }
+}
+
+
+/*-------------------------------------------------
+ menu_autofire_populate - populate the autofire
+ menu
+-------------------------------------------------*/
+
+void ui_menu_autofire::populate()
+{
+ char temp_text[64];
+
+ /* add autofire toggle item */
+ bool autofire_toggle = machine().ioport().get_autofire_toggle();
+ item_append(_("Autofire Status"), (autofire_toggle ? _("Disabled") : _("Enabled")),
+ (autofire_toggle ? MENU_FLAG_RIGHT_ARROW : MENU_FLAG_LEFT_ARROW), (void *)ITEMREF_AUTOFIRE_STATUS);
+
+ /* iterate over the input ports and add autofire toggle items */
+ int menu_items = 0;
+ for (ioport_port &port : machine().ioport().ports())
+ {
+ bool is_first_button = true;
+ for (ioport_field &field : port.fields())
+ {
+ if ((field.name()) && ((field.type() >= IPT_BUTTON1 && field.type() <= IPT_BUTTON16))) // IPT_BUTTON1 + 15)))
+ {
+ menu_items++;
+ ioport_field::user_settings settings;
+ field.get_user_settings(settings);
+
+ if (is_first_button)
+ {
+ /* add a separator for each player */
+ item_append(ui_menu_item_type::SEPARATOR);
+ is_first_button = false;
+ }
+ /* add an autofire item */
+ if (!autofire_toggle)
+ {
+ // item is enabled and can be switched to values on/off
+ item_append(field.name(), (settings.autofire ? _("On") : _("Off")),
+ (settings.autofire ? MENU_FLAG_LEFT_ARROW : MENU_FLAG_RIGHT_ARROW), (void *)&field);
+ }
+ else
+ {
+ // item is disabled
+ item_append(field.name(), (settings.autofire ? _("On") : _("Off")),
+ MENU_FLAG_DISABLE | MENU_FLAG_INVERT, nullptr);
+ }
+ }
+ }
+ }
+
+ /* add text item if no buttons found */
+ if (menu_items==0)
+ {
+ item_append(ui_menu_item_type::SEPARATOR);
+ item_append(_("No buttons found on this machine!"), nullptr, MENU_FLAG_DISABLE, nullptr);
+ }
+
+ /* add a separator */
+ item_append(ui_menu_item_type::SEPARATOR);
+
+ /* add autofire delay item */
+ int value = machine().ioport().get_autofire_delay();
+ snprintf(temp_text, ARRAY_LENGTH(temp_text), "%d = %.2f Hz", value, (float)refresh/value);
+ if (!autofire_toggle)
+ {
+ item_append(_("Autofire Delay"), temp_text, MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW, (void *)ITEMREF_AUTOFIRE_DELAY);
+ }
+ else
+ {
+ item_append(_("Autofire Delay"), temp_text, MENU_FLAG_DISABLE | MENU_FLAG_INVERT, nullptr);
+ }
+
+ /* add a separator */
+ item_append(ui_menu_item_type::SEPARATOR);
+
+ last_toggle = autofire_toggle;
+}
diff --git a/src/frontend/mame/ui/cheatopt.h b/src/frontend/mame/ui/cheatopt.h
new file mode 100644
index 00000000000..a9321df7304
--- /dev/null
+++ b/src/frontend/mame/ui/cheatopt.h
@@ -0,0 +1,49 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/***************************************************************************
+
+ ui/cheatopt.h
+
+ Internal menu for the cheat interface.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_CHEATOPT_H__
+#define __UI_CHEATOPT_H__
+
+// itemrefs for key menu items
+#define ITEMREF_CHEATS_RESET_ALL ((void *) 0x0001)
+#define ITEMREF_CHEATS_RELOAD_ALL ((void *) 0x0002)
+#define ITEMREF_CHEATS_AUTOFIRE_SETTINGS ((void *) 0x0003)
+#define ITEMREF_CHEATS_FIRST_ITEM ((void *) 0x0004)
+
+class ui_menu_cheat : public ui_menu {
+public:
+ ui_menu_cheat(running_machine &machine, render_container *container);
+ virtual ~ui_menu_cheat();
+ virtual void populate() override;
+ virtual void handle() override;
+};
+
+
+// itemrefs for key menu items
+#define ITEMREF_AUTOFIRE_STATUS ((void *) 0x0001)
+#define ITEMREF_AUTOFIRE_DELAY ((void *) 0x0002)
+#define ITEMREF_AUTOFIRE_FIRST_BUTTON ((void *) 0x0003)
+
+class ui_menu_autofire : public ui_menu {
+public:
+ ui_menu_autofire(running_machine &machine, render_container *container);
+ virtual ~ui_menu_autofire();
+ virtual void populate() override;
+ virtual void handle() override;
+
+private:
+ float refresh;
+ bool last_toggle;
+};
+
+
+#endif /* __UI_CHEATOPT_H__ */
diff --git a/src/frontend/mame/ui/custmenu.cpp b/src/frontend/mame/ui/custmenu.cpp
new file mode 100644
index 00000000000..e1d6ed470ca
--- /dev/null
+++ b/src/frontend/mame/ui/custmenu.cpp
@@ -0,0 +1,583 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/*********************************************************************
+
+ ui/custmenu.cpp
+
+ Internal UI user interface.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "ui/ui.h"
+#include "ui/menu.h"
+#include "ui/custmenu.h"
+#include "ui/selector.h"
+#include "ui/inifile.h"
+#include "rendfont.h"
+
+/**************************************************
+ MENU CUSTOM FILTER
+**************************************************/
+//-------------------------------------------------
+// ctor / dtor
+//-------------------------------------------------
+ui_menu_custom_filter::ui_menu_custom_filter(running_machine &machine, render_container *container, bool _single_menu)
+ : ui_menu(machine, container)
+ , m_single_menu(_single_menu)
+ , m_added(false)
+{
+}
+
+ui_menu_custom_filter::~ui_menu_custom_filter()
+{
+ if (m_single_menu)
+ ui_menu::menu_stack->reset(UI_MENU_RESET_SELECT_FIRST);
+ save_custom_filters();
+}
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+void ui_menu_custom_filter::handle()
+{
+ bool changed = false;
+ m_added = false;
+
+ // process the menu
+ const ui_menu_event *m_event = process(UI_MENU_PROCESS_LR_REPEAT);
+ if (m_event != nullptr && m_event->itemref != nullptr)
+ {
+ switch ((FPTR)m_event->itemref)
+ {
+ case MAIN_FILTER:
+ if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT)
+ {
+ (m_event->iptkey == IPT_UI_RIGHT) ? custfltr::main++ : custfltr::main--;
+ changed = true;
+ }
+ break;
+
+ case ADD_FILTER:
+ if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ custfltr::numother++;
+ custfltr::other[custfltr::numother] = FILTER_UNAVAILABLE + 1;
+ m_added = true;
+ }
+ break;
+
+ case REMOVE_FILTER:
+ if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ custfltr::other[custfltr::numother] = FILTER_UNAVAILABLE + 1;
+ custfltr::numother--;
+ changed = true;
+ }
+ break;
+ }
+
+ if ((FPTR)m_event->itemref >= OTHER_FILTER && (FPTR)m_event->itemref < OTHER_FILTER + MAX_CUST_FILTER)
+ {
+ int pos = (int)((FPTR)m_event->itemref - OTHER_FILTER);
+ if (m_event->iptkey == IPT_UI_LEFT && custfltr::other[pos] > FILTER_UNAVAILABLE + 1)
+ {
+ custfltr::other[pos]--;
+ for ( ; custfltr::other[pos] > FILTER_UNAVAILABLE && (custfltr::other[pos] == FILTER_CATEGORY
+ || custfltr::other[pos] == FILTER_FAVORITE); custfltr::other[pos]--) ;
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_RIGHT && custfltr::other[pos] < FILTER_LAST - 1)
+ {
+ custfltr::other[pos]++;
+ for ( ; custfltr::other[pos] < FILTER_LAST && (custfltr::other[pos] == FILTER_CATEGORY
+ || custfltr::other[pos] == FILTER_FAVORITE); custfltr::other[pos]++) ;
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ size_t total = main_filters::length;
+ std::vector<std::string> s_sel(total);
+ for (size_t index = 0; index < total; ++index)
+ if (index <= FILTER_UNAVAILABLE || index == FILTER_CATEGORY || index == FILTER_FAVORITE || index == FILTER_CUSTOM)
+ s_sel[index] = "_skip_";
+ else
+ s_sel[index] = main_filters::text[index];
+
+ ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, s_sel, custfltr::other[pos]));
+ }
+ }
+ else if ((FPTR)m_event->itemref >= YEAR_FILTER && (FPTR)m_event->itemref < YEAR_FILTER + MAX_CUST_FILTER)
+ {
+ int pos = (int)((FPTR)m_event->itemref - YEAR_FILTER);
+ if (m_event->iptkey == IPT_UI_LEFT && custfltr::year[pos] > 0)
+ {
+ custfltr::year[pos]--;
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_RIGHT && custfltr::year[pos] < c_year::ui.size() - 1)
+ {
+ custfltr::year[pos]++;
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, c_year::ui, custfltr::year[pos]));
+ }
+ else if ((FPTR)m_event->itemref >= MNFCT_FILTER && (FPTR)m_event->itemref < MNFCT_FILTER + MAX_CUST_FILTER)
+ {
+ int pos = (int)((FPTR)m_event->itemref - MNFCT_FILTER);
+ if (m_event->iptkey == IPT_UI_LEFT && custfltr::mnfct[pos] > 0)
+ {
+ custfltr::mnfct[pos]--;
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_RIGHT && custfltr::mnfct[pos] < c_mnfct::ui.size() - 1)
+ {
+ custfltr::mnfct[pos]++;
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, c_mnfct::ui, custfltr::mnfct[pos]));
+ }
+ }
+
+ if (changed)
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ else if (m_added)
+ reset(UI_MENU_RESET_SELECT_FIRST);
+}
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+void ui_menu_custom_filter::populate()
+{
+ // add main filter
+ UINT32 arrow_flags = get_arrow_flags((int)FILTER_ALL, (int)FILTER_UNAVAILABLE, custfltr::main);
+ item_append(_("Main filter"), main_filters::text[custfltr::main], arrow_flags, (void *)(FPTR)MAIN_FILTER);
+
+ // add other filters
+ for (int x = 1; x <= custfltr::numother; x++)
+ {
+ item_append(ui_menu_item_type::SEPARATOR);
+
+ // add filter items
+ arrow_flags = get_arrow_flags((int)FILTER_UNAVAILABLE + 1, (int)FILTER_LAST - 1, custfltr::other[x]);
+ item_append(_("Other filter"), main_filters::text[custfltr::other[x]], arrow_flags, (void *)(FPTR)(OTHER_FILTER + x));
+
+ if (m_added)
+ selected = item.size() - 2;
+
+ // add manufacturer subitem
+ if (custfltr::other[x] == FILTER_MANUFACTURER && c_mnfct::ui.size() > 0)
+ {
+ arrow_flags = get_arrow_flags(0, c_mnfct::ui.size() - 1, custfltr::mnfct[x]);
+ std::string fbuff(_("^!Manufacturer"));
+ convert_command_glyph(fbuff);
+ item_append(fbuff.c_str(), c_mnfct::ui[custfltr::mnfct[x]].c_str(), arrow_flags, (void *)(FPTR)(MNFCT_FILTER + x));
+ }
+
+ // add year subitem
+ else if (custfltr::other[x] == FILTER_YEAR && c_year::ui.size() > 0)
+ {
+ arrow_flags = get_arrow_flags(0, c_year::ui.size() - 1, custfltr::year[x]);
+ std::string fbuff(_("^!Year"));
+ convert_command_glyph(fbuff);
+ item_append(fbuff.c_str(), c_year::ui[custfltr::year[x]].c_str(), arrow_flags, (void *)(FPTR)(YEAR_FILTER + x));
+ }
+ }
+
+ item_append(ui_menu_item_type::SEPARATOR);
+
+ if (custfltr::numother > 0)
+ item_append(_("Remove last filter"), nullptr, 0, (void *)(FPTR)REMOVE_FILTER);
+
+ if (custfltr::numother < MAX_CUST_FILTER - 2)
+ item_append(_("Add filter"), nullptr, 0, (void *)(FPTR)ADD_FILTER);
+
+ item_append(ui_menu_item_type::SEPARATOR);
+ customtop = mame_machine_manager::instance()->ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER;
+}
+
+//-------------------------------------------------
+// perform our special rendering
+//-------------------------------------------------
+void ui_menu_custom_filter::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ float width;
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+
+ // get the size of the text
+ mui.draw_text_full(container, _("Select custom filters:"), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += (2.0f * UI_BOX_LR_BORDER) + 0.01f;
+ float maxwidth = MAX(width, origx2 - origx1);
+
+ // compute our bounds
+ float x1 = 0.5f - 0.5f * maxwidth;
+ float x2 = x1 + maxwidth;
+ float y1 = origy1 - top;
+ float y2 = origy1 - UI_BOX_TB_BORDER;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ mui.draw_text_full(container, _("Select custom filters:"), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+}
+
+//-------------------------------------------------
+// save custom filters info to file
+//-------------------------------------------------
+
+void ui_menu_custom_filter::save_custom_filters()
+{
+ // attempt to open the output file
+ emu_file file(mame_machine_manager::instance()->ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ if (file.open("custom_", emulator_info::get_configname(), "_filter.ini") == osd_file::error::NONE)
+ {
+ // generate custom filters info
+ std::ostringstream cinfo;
+ util::stream_format(cinfo, "Total filters = %d\n", (custfltr::numother + 1));
+ util::stream_format(cinfo, "Main filter = %s\n", main_filters::text[custfltr::main]);
+
+ for (int x = 1; x <= custfltr::numother; x++)
+ {
+ util::stream_format(cinfo, "Other filter = %s\n", main_filters::text[custfltr::other[x]]);
+ if (custfltr::other[x] == FILTER_MANUFACTURER)
+ util::stream_format(cinfo, " Manufacturer filter = %s\n", c_mnfct::ui[custfltr::mnfct[x]]);
+ else if (custfltr::other[x] == FILTER_YEAR)
+ util::stream_format(cinfo, " Year filter = %s\n", c_year::ui[custfltr::year[x]]);
+ }
+ file.puts(cinfo.str().c_str());
+ file.close();
+ }
+}
+
+/**************************************************
+ MENU CUSTOM SOFTWARE FILTER
+**************************************************/
+//-------------------------------------------------
+// ctor / dtor
+//-------------------------------------------------
+ui_menu_swcustom_filter::ui_menu_swcustom_filter(running_machine &machine, render_container *container, const game_driver *_driver, s_filter &_filter) :
+ ui_menu(machine, container)
+ , m_added(false)
+ , m_filter(_filter)
+ , m_driver(_driver)
+{
+}
+
+ui_menu_swcustom_filter::~ui_menu_swcustom_filter()
+{
+ ui_menu::menu_stack->reset(UI_MENU_RESET_SELECT_FIRST);
+ save_sw_custom_filters();
+}
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+void ui_menu_swcustom_filter::handle()
+{
+ bool changed = false;
+ m_added = false;
+
+ // process the menu
+ const ui_menu_event *m_event = process(UI_MENU_PROCESS_LR_REPEAT);
+ if (m_event != nullptr && m_event->itemref != nullptr)
+ {
+ switch ((FPTR)m_event->itemref)
+ {
+ case MAIN_FILTER:
+ if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT)
+ {
+ (m_event->iptkey == IPT_UI_RIGHT) ? sw_custfltr::main++ : sw_custfltr::main--;
+ changed = true;
+ }
+ break;
+
+ case ADD_FILTER:
+ if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ sw_custfltr::numother++;
+ sw_custfltr::other[sw_custfltr::numother] = UI_SW_UNAVAILABLE + 1;
+ m_added = true;
+ }
+ break;
+
+ case REMOVE_FILTER:
+ if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ sw_custfltr::other[sw_custfltr::numother] = UI_SW_UNAVAILABLE + 1;
+ sw_custfltr::numother--;
+ changed = true;
+ }
+ break;
+ }
+
+ if ((FPTR)m_event->itemref >= OTHER_FILTER && (FPTR)m_event->itemref < OTHER_FILTER + MAX_CUST_FILTER)
+ {
+ int pos = (int)((FPTR)m_event->itemref - OTHER_FILTER);
+ if (m_event->iptkey == IPT_UI_LEFT && sw_custfltr::other[pos] > UI_SW_UNAVAILABLE + 1)
+ {
+ sw_custfltr::other[pos]--;
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_RIGHT && sw_custfltr::other[pos] < UI_SW_LAST - 1)
+ {
+ sw_custfltr::other[pos]++;
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ size_t total = sw_filters::length;
+ std::vector<std::string> s_sel(total);
+ for (size_t index = 0; index < total; ++index)
+ if (index <= UI_SW_UNAVAILABLE|| index == UI_SW_CUSTOM)
+ s_sel[index] = "_skip_";
+ else
+ s_sel[index] = sw_filters::text[index];
+
+ ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, s_sel, sw_custfltr::other[pos]));
+ }
+ }
+ else if ((FPTR)m_event->itemref >= YEAR_FILTER && (FPTR)m_event->itemref < YEAR_FILTER + MAX_CUST_FILTER)
+ {
+ int pos = (int)((FPTR)m_event->itemref - YEAR_FILTER);
+ if (m_event->iptkey == IPT_UI_LEFT && sw_custfltr::year[pos] > 0)
+ {
+ sw_custfltr::year[pos]--;
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_RIGHT && sw_custfltr::year[pos] < m_filter.year.ui.size() - 1)
+ {
+ sw_custfltr::year[pos]++;
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, m_filter.year.ui, sw_custfltr::year[pos]));
+ }
+ else if ((FPTR)m_event->itemref >= TYPE_FILTER && (FPTR)m_event->itemref < TYPE_FILTER + MAX_CUST_FILTER)
+ {
+ int pos = (int)((FPTR)m_event->itemref - TYPE_FILTER);
+ if (m_event->iptkey == IPT_UI_LEFT && sw_custfltr::type[pos] > 0)
+ {
+ sw_custfltr::type[pos]--;
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_RIGHT && sw_custfltr::type[pos] < m_filter.type.ui.size() - 1)
+ {
+ sw_custfltr::type[pos]++;
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, m_filter.type.ui, sw_custfltr::type[pos]));
+ }
+ else if ((FPTR)m_event->itemref >= MNFCT_FILTER && (FPTR)m_event->itemref < MNFCT_FILTER + MAX_CUST_FILTER)
+ {
+ int pos = (int)((FPTR)m_event->itemref - MNFCT_FILTER);
+ if (m_event->iptkey == IPT_UI_LEFT && sw_custfltr::mnfct[pos] > 0)
+ {
+ sw_custfltr::mnfct[pos]--;
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_RIGHT && sw_custfltr::mnfct[pos] < m_filter.publisher.ui.size() - 1)
+ {
+ sw_custfltr::mnfct[pos]++;
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, m_filter.publisher.ui, sw_custfltr::mnfct[pos]));
+ }
+ else if ((FPTR)m_event->itemref >= REGION_FILTER && (FPTR)m_event->itemref < REGION_FILTER + MAX_CUST_FILTER)
+ {
+ int pos = (int)((FPTR)m_event->itemref - REGION_FILTER);
+ if (m_event->iptkey == IPT_UI_LEFT && sw_custfltr::region[pos] > 0)
+ {
+ sw_custfltr::region[pos]--;
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_RIGHT && sw_custfltr::region[pos] < m_filter.region.ui.size() - 1)
+ {
+ sw_custfltr::region[pos]++;
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, m_filter.region.ui, sw_custfltr::region[pos]));
+ }
+ else if ((FPTR)m_event->itemref >= LIST_FILTER && (FPTR)m_event->itemref < LIST_FILTER + MAX_CUST_FILTER)
+ {
+ int pos = (int)((FPTR)m_event->itemref - LIST_FILTER);
+ if (m_event->iptkey == IPT_UI_LEFT && sw_custfltr::list[pos] > 0)
+ {
+ sw_custfltr::list[pos]--;
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_RIGHT && sw_custfltr::list[pos] < m_filter.swlist.name.size() - 1)
+ {
+ sw_custfltr::list[pos]++;
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, m_filter.swlist.description, sw_custfltr::list[pos]));
+ }
+ }
+
+ if (changed)
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ else if (m_added)
+ reset(UI_MENU_RESET_SELECT_FIRST);
+}
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+void ui_menu_swcustom_filter::populate()
+{
+ // add main filter
+ UINT32 arrow_flags = get_arrow_flags((int)UI_SW_ALL, (int)UI_SW_UNAVAILABLE, sw_custfltr::main);
+ item_append(_("Main filter"), sw_filters::text[sw_custfltr::main], arrow_flags, (void *)(FPTR)MAIN_FILTER);
+
+ // add other filters
+ for (int x = 1; x <= sw_custfltr::numother; x++)
+ {
+ item_append(ui_menu_item_type::SEPARATOR);
+
+ // add filter items
+ arrow_flags = get_arrow_flags((int)UI_SW_UNAVAILABLE + 1, (int)UI_SW_LAST - 1, sw_custfltr::other[x]);
+ item_append(_("Other filter"), sw_filters::text[sw_custfltr::other[x]], arrow_flags, (void *)(FPTR)(OTHER_FILTER + x));
+
+ if (m_added)
+ selected = item.size() - 2;
+
+ // add publisher subitem
+ if (sw_custfltr::other[x] == UI_SW_PUBLISHERS && m_filter.publisher.ui.size() > 0)
+ {
+ arrow_flags = get_arrow_flags(0, m_filter.publisher.ui.size() - 1, sw_custfltr::mnfct[x]);
+ std::string fbuff(_("^!Publisher"));
+ convert_command_glyph(fbuff);
+ item_append(fbuff.c_str(), m_filter.publisher.ui[sw_custfltr::mnfct[x]].c_str(), arrow_flags, (void *)(FPTR)(MNFCT_FILTER + x));
+ }
+
+ // add year subitem
+ else if (sw_custfltr::other[x] == UI_SW_YEARS && m_filter.year.ui.size() > 0)
+ {
+ arrow_flags = get_arrow_flags(0, m_filter.year.ui.size() - 1, sw_custfltr::year[x]);
+ std::string fbuff(_("^!Year"));
+ convert_command_glyph(fbuff);
+ item_append(fbuff.c_str(), m_filter.year.ui[sw_custfltr::year[x]].c_str(), arrow_flags, (void *)(FPTR)(YEAR_FILTER + x));
+ }
+
+ // add year subitem
+ else if (sw_custfltr::other[x] == UI_SW_LIST && m_filter.swlist.name.size() > 0)
+ {
+ arrow_flags = get_arrow_flags(0, m_filter.swlist.name.size() - 1, sw_custfltr::list[x]);
+ std::string fbuff(_("^!Software List"));
+ convert_command_glyph(fbuff);
+ item_append(fbuff.c_str(), m_filter.swlist.description[sw_custfltr::list[x]].c_str(), arrow_flags, (void *)(FPTR)(LIST_FILTER + x));
+ }
+
+ // add device type subitem
+ else if (sw_custfltr::other[x] == UI_SW_TYPE && m_filter.type.ui.size() > 0)
+ {
+ arrow_flags = get_arrow_flags(0, m_filter.type.ui.size() - 1, sw_custfltr::type[x]);
+ std::string fbuff(_("^!Device type"));
+ convert_command_glyph(fbuff);
+ item_append(fbuff.c_str(), m_filter.type.ui[sw_custfltr::type[x]].c_str(), arrow_flags, (void *)(FPTR)(TYPE_FILTER + x));
+ }
+
+ // add region subitem
+ else if (sw_custfltr::other[x] == UI_SW_REGION && m_filter.region.ui.size() > 0)
+ {
+ arrow_flags = get_arrow_flags(0, m_filter.region.ui.size() - 1, sw_custfltr::region[x]);
+ std::string fbuff(_("^!Region"));
+ convert_command_glyph(fbuff);
+ item_append(fbuff.c_str(), m_filter.region.ui[sw_custfltr::region[x]].c_str(), arrow_flags, (void *)(FPTR)(REGION_FILTER + x));
+ }
+ }
+
+ item_append(ui_menu_item_type::SEPARATOR);
+
+ if (sw_custfltr::numother > 0)
+ item_append(_("Remove last filter"), nullptr, 0, (void *)(FPTR)REMOVE_FILTER);
+
+ if (sw_custfltr::numother < MAX_CUST_FILTER - 2)
+ item_append(_("Add filter"), nullptr, 0, (void *)(FPTR)ADD_FILTER);
+
+ item_append(ui_menu_item_type::SEPARATOR);
+
+ customtop = mame_machine_manager::instance()->ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER;
+}
+
+//-------------------------------------------------
+// perform our special rendering
+//-------------------------------------------------
+void ui_menu_swcustom_filter::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ float width;
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+
+ // get the size of the text
+ mui.draw_text_full(container, _("Select custom filters:"), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += (2.0f * UI_BOX_LR_BORDER) + 0.01f;
+ float maxwidth = MAX(width, origx2 - origx1);
+
+ // compute our bounds
+ float x1 = 0.5f - 0.5f * maxwidth;
+ float x2 = x1 + maxwidth;
+ float y1 = origy1 - top;
+ float y2 = origy1 - UI_BOX_TB_BORDER;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ mui.draw_text_full(container, _("Select custom filters:"), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+}
+
+//-------------------------------------------------
+// save custom filters info to file
+//-------------------------------------------------
+
+void ui_menu_swcustom_filter::save_sw_custom_filters()
+{
+ // attempt to open the output file
+ emu_file file(mame_machine_manager::instance()->ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ if (file.open("custom_", m_driver->name, "_filter.ini") == osd_file::error::NONE)
+ {
+ // generate custom filters info
+ std::ostringstream cinfo;
+ util::stream_format(cinfo, "Total filters = %d\n", (sw_custfltr::numother + 1));
+ util::stream_format(cinfo, "Main filter = %s\n", sw_filters::text[sw_custfltr::main]);
+
+ for (int x = 1; x <= sw_custfltr::numother; x++)
+ {
+ util::stream_format(cinfo, "Other filter = %s\n", sw_filters::text[sw_custfltr::other[x]]);
+ if (sw_custfltr::other[x] == UI_SW_PUBLISHERS)
+ util::stream_format(cinfo, " Manufacturer filter = %s\n", m_filter.publisher.ui[sw_custfltr::mnfct[x]]);
+ else if (sw_custfltr::other[x] == UI_SW_LIST)
+ util::stream_format(cinfo, " Software List filter = %s\n", m_filter.swlist.name[sw_custfltr::list[x]]);
+ else if (sw_custfltr::other[x] == UI_SW_YEARS)
+ util::stream_format(cinfo, " Year filter = %s\n", m_filter.year.ui[sw_custfltr::year[x]]);
+ else if (sw_custfltr::other[x] == UI_SW_TYPE)
+ util::stream_format(cinfo, " Type filter = %s\n", m_filter.type.ui[sw_custfltr::type[x]]);
+ else if (sw_custfltr::other[x] == UI_SW_REGION)
+ util::stream_format(cinfo, " Region filter = %s\n", m_filter.region.ui[sw_custfltr::region[x]]);
+ }
+ file.puts(cinfo.str().c_str());
+ file.close();
+ }
+}
diff --git a/src/frontend/mame/ui/custmenu.h b/src/frontend/mame/ui/custmenu.h
new file mode 100644
index 00000000000..338344dcddd
--- /dev/null
+++ b/src/frontend/mame/ui/custmenu.h
@@ -0,0 +1,131 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/***************************************************************************
+
+ ui/custmenu.h
+
+ Internal UI user interface.
+
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_CUSTMENU_H__
+#define __UI_CUSTMENU_H__
+
+#include "ui/utils.h"
+
+// Software region
+struct c_sw_region
+{
+ std::vector<std::string> ui;
+ UINT16 actual;
+ void set(std::string &str);
+ std::string getname(std::string &str);
+};
+
+// Software publishers
+struct c_sw_publisher
+{
+ std::vector<std::string> ui;
+ UINT16 actual;
+ void set(std::string &str);
+ std::string getname(std::string &str);
+};
+
+// Software device type
+struct c_sw_type
+{
+ std::vector<std::string> ui;
+ UINT16 actual;
+ void set(std::string &str);
+};
+
+// Software list
+struct c_sw_list
+{
+ std::vector<std::string> name;
+ std::vector<std::string> description;
+ UINT16 actual;
+};
+
+// Software years
+struct c_sw_year
+{
+ std::vector<std::string> ui;
+ UINT16 actual;
+ void set(std::string &str);
+};
+
+struct s_filter
+{
+ c_sw_region region;
+ c_sw_publisher publisher;
+ c_sw_year year;
+ c_sw_type type;
+ c_sw_list swlist;
+};
+
+//-------------------------------------------------
+// custom software filter menu class
+//-------------------------------------------------
+class ui_menu_swcustom_filter : public ui_menu
+{
+public:
+ ui_menu_swcustom_filter(running_machine &machine, render_container *container, const game_driver *_driver, s_filter &_filter);
+ virtual ~ui_menu_swcustom_filter();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+private:
+ enum
+ {
+ MAIN_FILTER = 1,
+ ADD_FILTER,
+ REMOVE_FILTER,
+ MNFCT_FILTER,
+ YEAR_FILTER = MNFCT_FILTER + MAX_CUST_FILTER + 1,
+ REGION_FILTER = YEAR_FILTER + MAX_CUST_FILTER + 1,
+ TYPE_FILTER = REGION_FILTER + MAX_CUST_FILTER + 1,
+ LIST_FILTER = TYPE_FILTER + MAX_CUST_FILTER + 1,
+ OTHER_FILTER = LIST_FILTER + MAX_CUST_FILTER + 1
+ };
+
+ bool m_added;
+ s_filter &m_filter;
+ const game_driver *m_driver;
+
+ void save_sw_custom_filters();
+};
+
+//-------------------------------------------------
+// custom filter menu class
+//-------------------------------------------------
+class ui_menu_custom_filter : public ui_menu
+{
+public:
+ ui_menu_custom_filter(running_machine &machine, render_container *container, bool _single_menu = false);
+ virtual ~ui_menu_custom_filter();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+private:
+ enum
+ {
+ MAIN_FILTER = 1,
+ ADD_FILTER,
+ REMOVE_FILTER,
+ MNFCT_FILTER,
+ YEAR_FILTER = MNFCT_FILTER + MAX_CUST_FILTER + 1,
+ SCREEN_FILTER = YEAR_FILTER + MAX_CUST_FILTER + 1,
+ OTHER_FILTER = SCREEN_FILTER + MAX_CUST_FILTER + 1
+ };
+
+ bool m_single_menu, m_added;
+ void save_custom_filters();
+};
+
+#endif /* __UI_CUSTMENU_H__ */
diff --git a/src/frontend/mame/ui/custui.cpp b/src/frontend/mame/ui/custui.cpp
new file mode 100644
index 00000000000..eb0e755d240
--- /dev/null
+++ b/src/frontend/mame/ui/custui.cpp
@@ -0,0 +1,1068 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/*********************************************************************
+
+ ui/custui.cpp
+
+ Internal UI user interface.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "emuopts.h"
+#include "osdepend.h"
+#include "ui/ui.h"
+#include "ui/menu.h"
+#include "ui/selector.h"
+#include "ui/utils.h"
+#include "ui/custui.h"
+
+const char *const ui_menu_custom_ui::hide_status[] = {
+ __("Show All"),
+ __("Hide Filters"),
+ __("Hide Info/Image"),
+ __("Hide Both") };
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+ui_menu_custom_ui::ui_menu_custom_ui(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+ // load languages
+ file_enumerator path(machine.options().language_path());
+ const char *lang = machine.options().language();
+ const osd_directory_entry *dirent;
+ int cnt = 0;
+ while ((dirent = path.next()) != nullptr)
+ if (dirent->type == ENTTYPE_DIR && strcmp(dirent->name, ".") != 0 && strcmp(dirent->name, "..") != 0)
+ {
+ auto name = std::string(dirent->name);
+ int i = strreplace(name, "_", " (");
+ if (i > 0) name = name.append(")");
+ m_lang.push_back(name);
+ if (strcmp(name.c_str(), lang) == 0)
+ m_currlang = cnt;
+ ++cnt;
+ }
+}
+
+//-------------------------------------------------
+// dtor
+//-------------------------------------------------
+
+ui_menu_custom_ui::~ui_menu_custom_ui()
+{
+ std::string error_string;
+ mame_machine_manager::instance()->ui().options().set_value(OPTION_HIDE_PANELS, ui_globals::panels_status, OPTION_PRIORITY_CMDLINE, error_string);
+ if (!m_lang.empty())
+ {
+ machine().options().set_value(OPTION_LANGUAGE, m_lang[m_currlang].c_str(), OPTION_PRIORITY_CMDLINE, error_string);
+ machine().options().mark_changed(OPTION_LANGUAGE);
+ load_translation(machine().options());
+ }
+ ui_globals::reset = true;
+}
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_menu_custom_ui::handle()
+{
+ bool changed = false;
+
+ // process the menu
+ const ui_menu_event *m_event = process(0);
+
+ if (m_event != nullptr && m_event->itemref != nullptr)
+ {
+ switch ((FPTR)m_event->itemref)
+ {
+ case FONT_MENU:
+ if (m_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_font_ui>(machine(), container));
+ break;
+ case COLORS_MENU:
+ if (m_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_colors_ui>(machine(), container));
+ break;
+ case HIDE_MENU:
+ {
+ if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT)
+ {
+ changed = true;
+ (m_event->iptkey == IPT_UI_RIGHT) ? ui_globals::panels_status++ : ui_globals::panels_status--;
+ }
+ else if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ int total = ARRAY_LENGTH(hide_status);
+ std::vector<std::string> s_sel(total);
+ for (int index = 0; index < total; ++index)
+ s_sel[index] = _(hide_status[index]);
+
+ ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, s_sel, ui_globals::panels_status));
+ }
+ break;
+ }
+ case LANGUAGE_MENU:
+ {
+ if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT)
+ {
+ changed = true;
+ (m_event->iptkey == IPT_UI_RIGHT) ? m_currlang++ : m_currlang--;
+ }
+ else if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ int total = m_lang.size();
+ std::vector<std::string> s_sel(total);
+ for (int index = 0; index < total; ++index)
+ s_sel[index] = m_lang[index];
+
+ ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, s_sel, m_currlang));
+ }
+ break;
+ }
+ }
+ }
+
+ if (changed)
+ reset(UI_MENU_RESET_REMEMBER_REF);
+}
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_custom_ui::populate()
+{
+ UINT32 arrow_flags;
+ item_append(_("Fonts"), nullptr, 0, (void *)(FPTR)FONT_MENU);
+ item_append(_("Colors"), nullptr, 0, (void *)(FPTR)COLORS_MENU);
+
+ if (!m_lang.empty())
+ {
+ arrow_flags = get_arrow_flags(0, m_lang.size() - 1, m_currlang);
+ item_append(_("Language"), m_lang[m_currlang].c_str(), arrow_flags, (void *)(FPTR)LANGUAGE_MENU);
+ }
+
+ arrow_flags = get_arrow_flags(0, (int)HIDE_BOTH, ui_globals::panels_status);
+ item_append(_("Show side panels"), _(hide_status[ui_globals::panels_status]), arrow_flags, (void *)(FPTR)HIDE_MENU);
+
+ item_append(ui_menu_item_type::SEPARATOR);
+ customtop = mame_machine_manager::instance()->ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER;
+}
+
+//-------------------------------------------------
+// perform our special rendering
+//-------------------------------------------------
+
+void ui_menu_custom_ui::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ float width;
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+
+ mui.draw_text_full(container, _("Custom UI Settings"), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += 2 * UI_BOX_LR_BORDER;
+ float maxwidth = MAX(origx2 - origx1, width);
+
+ // compute our bounds
+ float x1 = 0.5f - 0.5f * maxwidth;
+ float x2 = x1 + maxwidth;
+ float y1 = origy1 - top;
+ float y2 = origy1 - UI_BOX_TB_BORDER;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ mui.draw_text_full(container, _("Custom UI Settings"), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+}
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+ui_menu_font_ui::ui_menu_font_ui(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+ ui_options &moptions = mame_machine_manager::instance()->ui().options();
+ std::string name(machine.options().ui_font());
+ list();
+
+#ifdef UI_WINDOWS
+ m_bold = (strreplace(name, "[B]", "") + strreplace(name, "[b]", "") > 0);
+ m_italic = (strreplace(name, "[I]", "") + strreplace(name, "[i]", "") > 0);
+#endif
+ m_actual = 0;
+
+ for (size_t index = 0; index < m_fonts.size(); index++)
+ {
+ if (m_fonts[index].first == name)
+ {
+ m_actual = index;
+ break;
+ }
+ }
+
+ m_info_size = moptions.infos_size();
+ m_font_size = moptions.font_rows();
+
+ for (ui_options::entry &f_entry : moptions)
+ {
+ const char *name = f_entry.name();
+ if (name && strlen(name) && !strcmp(OPTION_INFOS_SIZE, f_entry.name()))
+ {
+ m_info_max = atof(f_entry.maximum());
+ m_info_min = atof(f_entry.minimum());
+ }
+ else if (name && strlen(name) && !strcmp(OPTION_FONT_ROWS, f_entry.name()))
+ {
+ m_font_max = atof(f_entry.maximum());
+ m_font_min = atof(f_entry.minimum());
+ }
+ }
+
+}
+
+//-------------------------------------------------
+// create fonts list
+//-------------------------------------------------
+
+void ui_menu_font_ui::list()
+{
+ machine().osd().get_font_families(machine().options().font_path(), m_fonts);
+
+ // add default string to the top of array
+ m_fonts.emplace(m_fonts.begin(), std::string("default"), std::string(_("default")));
+}
+
+//-------------------------------------------------
+// dtor
+//-------------------------------------------------
+
+ui_menu_font_ui::~ui_menu_font_ui()
+{
+ std::string error_string;
+ ui_options &moptions = mame_machine_manager::instance()->ui().options();
+
+ std::string name(m_fonts[m_actual].first);
+#ifdef UI_WINDOWS
+ if (name != "default")
+ {
+ if (m_italic)
+ name.insert(0, "[I]");
+ if (m_bold)
+ name.insert(0, "[B]");
+ }
+#endif
+ machine().options().set_value(OPTION_UI_FONT, name.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
+ machine().options().mark_changed(OPTION_UI_FONT);
+
+ moptions.set_value(OPTION_INFOS_SIZE, m_info_size, OPTION_PRIORITY_CMDLINE, error_string);
+ moptions.set_value(OPTION_FONT_ROWS, m_font_size, OPTION_PRIORITY_CMDLINE, error_string);
+}
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_menu_font_ui::handle()
+{
+ bool changed = false;
+
+ // process the menu
+ const ui_menu_event *m_event = process(UI_MENU_PROCESS_LR_REPEAT);
+
+ if (m_event != nullptr && m_event->itemref != nullptr)
+ switch ((FPTR)m_event->itemref)
+ {
+ case INFOS_SIZE:
+ if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT)
+ {
+ (m_event->iptkey == IPT_UI_RIGHT) ? m_info_size += 0.05f : m_info_size -= 0.05f;
+ changed = true;
+ }
+ break;
+
+ case FONT_SIZE:
+ if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT)
+ {
+ (m_event->iptkey == IPT_UI_RIGHT) ? m_font_size++ : m_font_size--;
+ changed = true;
+ }
+ break;
+
+
+ case MUI_FNT:
+ if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT)
+ {
+ (m_event->iptkey == IPT_UI_RIGHT) ? m_actual++ : m_actual--;
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ std::vector<std::string> display_names;
+ display_names.reserve(m_fonts.size());
+ for (auto const &font : m_fonts) display_names.emplace_back(font.second);
+ ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, std::move(display_names), m_actual));
+ changed = true;
+ }
+ break;
+
+#ifdef UI_WINDOWS
+ case MUI_BOLD:
+ case MUI_ITALIC:
+ if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT || m_event->iptkey == IPT_UI_SELECT)
+ {
+ ((FPTR)m_event->itemref == MUI_BOLD) ? m_bold = !m_bold : m_italic = !m_italic;
+ changed = true;
+ }
+ break;
+#endif
+ }
+
+ if (changed)
+ reset(UI_MENU_RESET_REMEMBER_REF);
+}
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_font_ui::populate()
+{
+ // set filter arrow
+ UINT32 arrow_flags;
+
+ // add fonts option
+ arrow_flags = get_arrow_flags(0, m_fonts.size() - 1, m_actual);
+ item_append(_("UI Font"), m_fonts[m_actual].second.c_str(), arrow_flags, (void *)(FPTR)MUI_FNT);
+
+#ifdef UI_WINDOWS
+ if (m_fonts[m_actual].first != "default")
+ {
+ item_append(_("Bold"), m_bold ? "On" : "Off", m_bold ? MENU_FLAG_RIGHT_ARROW : MENU_FLAG_LEFT_ARROW, (void *)(FPTR)MUI_BOLD);
+ item_append(_("Italic"), m_italic ? "On" : "Off", m_italic ? MENU_FLAG_RIGHT_ARROW : MENU_FLAG_LEFT_ARROW, (void *)(FPTR)MUI_ITALIC);
+ }
+#endif
+
+ arrow_flags = get_arrow_flags(m_font_min, m_font_max, m_font_size);
+ item_append(_("Lines"), string_format("%2d", m_font_size).c_str(), arrow_flags, (void *)(FPTR)FONT_SIZE);
+
+ item_append(ui_menu_item_type::SEPARATOR);
+
+ // add item
+ arrow_flags = get_arrow_flags(m_info_min, m_info_max, m_info_size);
+ item_append(_("Infos text size"), string_format("%3.2f", m_info_size).c_str(), arrow_flags, (void *)(FPTR)INFOS_SIZE);
+
+ item_append(ui_menu_item_type::SEPARATOR);
+
+ custombottom = customtop = mame_machine_manager::instance()->ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER;
+}
+
+//-------------------------------------------------
+// perform our special rendering
+//-------------------------------------------------
+
+void ui_menu_font_ui::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ float width;
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+
+ // top text
+ std::string topbuf(_("UI Fonts Settings"));
+
+ mui.draw_text_full(container, topbuf.c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += 2 * UI_BOX_LR_BORDER;
+ float maxwidth = MAX(origx2 - origx1, width);
+
+ // compute our bounds
+ float x1 = 0.5f - 0.5f * maxwidth;
+ float x2 = x1 + maxwidth;
+ float y1 = origy1 - top;
+ float y2 = origy1 - UI_BOX_TB_BORDER;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ mui.draw_text_full(container, topbuf.c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+
+ if ((FPTR)selectedref == INFOS_SIZE)
+ {
+ topbuf = _("Sample text - Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+
+ mui.draw_text_full(container, topbuf.c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_LEFT, WRAP_NEVER,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr, m_info_size);
+ width += 2 * UI_BOX_LR_BORDER;
+ maxwidth = MAX(origx2 - origx1, width);
+
+ // compute our bounds
+ x1 = 0.5f - 0.5f * maxwidth;
+ x2 = x1 + maxwidth;
+ y1 = origy2 + UI_BOX_TB_BORDER;
+ y2 = origy2 + bottom;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ mui.draw_text_full(container, topbuf.c_str(), x1, y1, x2 - x1, JUSTIFY_LEFT, WRAP_NEVER,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, m_info_size);
+ }
+}
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+#define SET_COLOR_UI(var, opt) var[M##opt].color = opt; var[M##opt].option = OPTION_##opt
+
+ui_menu_colors_ui::ui_menu_colors_ui(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+ SET_COLOR_UI(m_color_table, UI_BACKGROUND_COLOR);
+ SET_COLOR_UI(m_color_table, UI_BORDER_COLOR);
+ SET_COLOR_UI(m_color_table, UI_CLONE_COLOR);
+ SET_COLOR_UI(m_color_table, UI_DIPSW_COLOR);
+ SET_COLOR_UI(m_color_table, UI_GFXVIEWER_BG_COLOR);
+ SET_COLOR_UI(m_color_table, UI_MOUSEDOWN_BG_COLOR);
+ SET_COLOR_UI(m_color_table, UI_MOUSEDOWN_COLOR);
+ SET_COLOR_UI(m_color_table, UI_MOUSEOVER_BG_COLOR);
+ SET_COLOR_UI(m_color_table, UI_MOUSEOVER_COLOR);
+ SET_COLOR_UI(m_color_table, UI_SELECTED_BG_COLOR);
+ SET_COLOR_UI(m_color_table, UI_SELECTED_COLOR);
+ SET_COLOR_UI(m_color_table, UI_SLIDER_COLOR);
+ SET_COLOR_UI(m_color_table, UI_SUBITEM_COLOR);
+ SET_COLOR_UI(m_color_table, UI_TEXT_BG_COLOR);
+ SET_COLOR_UI(m_color_table, UI_TEXT_COLOR);
+ SET_COLOR_UI(m_color_table, UI_UNAVAILABLE_COLOR);
+}
+
+//-------------------------------------------------
+// dtor
+//-------------------------------------------------
+
+ui_menu_colors_ui::~ui_menu_colors_ui()
+{
+ std::string error_string, dec_color;
+ for (int index = 1; index < MUI_RESTORE; index++)
+ {
+ dec_color = string_format("%x", (UINT32)m_color_table[index].color);
+ mame_machine_manager::instance()->ui().options().set_value(m_color_table[index].option, dec_color.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
+ }
+}
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_menu_colors_ui::handle()
+{
+ bool changed = false;
+
+ // process the menu
+ const ui_menu_event *m_event = process(0);
+
+ if (m_event != nullptr && m_event->itemref != nullptr && m_event->iptkey == IPT_UI_SELECT)
+ {
+ if ((FPTR)m_event->itemref != MUI_RESTORE)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_rgb_ui>(machine(), container, &m_color_table[(FPTR)m_event->itemref].color, item[selected].text));
+ else
+ {
+ changed = true;
+ restore_colors();
+ }
+ }
+
+ if (changed)
+ reset(UI_MENU_RESET_REMEMBER_REF);
+}
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_colors_ui::populate()
+{
+ item_append(_("Normal text"), nullptr, 0, (void *)(FPTR)MUI_TEXT_COLOR);
+ item_append(_("Selected color"), nullptr, 0, (void *)(FPTR)MUI_SELECTED_COLOR);
+ item_append(_("Normal text background"), nullptr, 0, (void *)(FPTR)MUI_TEXT_BG_COLOR);
+ item_append(_("Selected background color"), nullptr, 0, (void *)(FPTR)MUI_SELECTED_BG_COLOR);
+ item_append(_("Subitem color"), nullptr, 0, (void *)(FPTR)MUI_SUBITEM_COLOR);
+ item_append(_("Clone"), nullptr, 0, (void *)(FPTR)MUI_CLONE_COLOR);
+ item_append(_("Border"), nullptr, 0, (void *)(FPTR)MUI_BORDER_COLOR);
+ item_append(_("Background"), nullptr, 0, (void *)(FPTR)MUI_BACKGROUND_COLOR);
+ item_append(_("Dipswitch"), nullptr, 0, (void *)(FPTR)MUI_DIPSW_COLOR);
+ item_append(_("Unavailable color"), nullptr, 0, (void *)(FPTR)MUI_UNAVAILABLE_COLOR);
+ item_append(_("Slider color"), nullptr, 0, (void *)(FPTR)MUI_SLIDER_COLOR);
+ item_append(_("Gfx viewer background"), nullptr, 0, (void *)(FPTR)MUI_GFXVIEWER_BG_COLOR);
+ item_append(_("Mouse over color"), nullptr, 0, (void *)(FPTR)MUI_MOUSEOVER_COLOR);
+ item_append(_("Mouse over background color"), nullptr, 0, (void *)(FPTR)MUI_MOUSEOVER_BG_COLOR);
+ item_append(_("Mouse down color"), nullptr, 0, (void *)(FPTR)MUI_MOUSEDOWN_COLOR);
+ item_append(_("Mouse down background color"), nullptr, 0, (void *)(FPTR)MUI_MOUSEDOWN_BG_COLOR);
+
+ item_append(ui_menu_item_type::SEPARATOR);
+ item_append(_("Restore originals colors"), nullptr, 0, (void *)(FPTR)MUI_RESTORE);
+
+ custombottom = customtop = mame_machine_manager::instance()->ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER;
+}
+
+//-------------------------------------------------
+// perform our special rendering
+//-------------------------------------------------
+
+void ui_menu_colors_ui::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ float width, maxwidth = origx2 - origx1;
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+ float line_height = mui.get_line_height();
+
+ // top text
+ std::string topbuf(_("UI Colors Settings"));
+
+ mui.draw_text_full(container, topbuf.c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += 2 * UI_BOX_LR_BORDER;
+ maxwidth = MAX(maxwidth, width);
+
+ // compute our bounds
+ float x1 = 0.5f - 0.5f * maxwidth;
+ float x2 = x1 + maxwidth;
+ float y1 = origy1 - top;
+ float y2 = origy1 - UI_BOX_TB_BORDER;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ mui.draw_text_full(container, topbuf.c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+
+ // bottom text
+ // get the text for 'UI Select'
+ std::string ui_select_text = machine().input().seq_name(machine().ioport().type_seq(IPT_UI_SELECT, 0, SEQ_TYPE_STANDARD));
+ topbuf = string_format(_("Double click or press %1$s to change the color value"), ui_select_text);
+
+ mui.draw_text_full(container, topbuf.c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += 2 * UI_BOX_LR_BORDER;
+ maxwidth = MAX(maxwidth, width);
+
+ // compute our bounds
+ x1 = 0.5f - 0.5f * maxwidth;
+ x2 = x1 + maxwidth;
+ y1 = origy2 + UI_BOX_TB_BORDER;
+ y2 = origy2 + bottom;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_RED_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ mui.draw_text_full(container, topbuf.c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+
+ // compute maxwidth
+ topbuf = _("Menu Preview");
+
+ mui.draw_text_full(container, topbuf.c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ maxwidth = width + 2.0f * UI_BOX_LR_BORDER;
+
+ std::string sampletxt[5];
+
+ sampletxt[0] = _("Normal");
+ sampletxt[1] = _("Subitem");
+ sampletxt[2] = _("Selected");
+ sampletxt[3] = _("Mouse Over");
+ sampletxt[4] = _("Clone");
+
+ for (auto & elem: sampletxt)
+ {
+ mui.draw_text_full(container, elem.c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += 2 * UI_BOX_LR_BORDER;
+ maxwidth = MAX(maxwidth, width);
+ }
+
+ // compute our bounds for header
+ x1 = origx2 + 2.0f * UI_BOX_LR_BORDER;
+ x2 = x1 + maxwidth;
+ y1 = origy1;
+ y2 = y1 + bottom - UI_BOX_TB_BORDER;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+ y2 -= UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ mui.draw_text_full(container, topbuf.c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+
+ // compute our bounds for menu preview
+ x1 -= UI_BOX_LR_BORDER;
+ x2 += UI_BOX_LR_BORDER;
+ y1 = y2 + 2.0f * UI_BOX_TB_BORDER;
+ y2 = y1 + 5.0f * line_height + 2.0f * UI_BOX_TB_BORDER;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, m_color_table[MUI_BACKGROUND_COLOR].color);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw normal text
+ mui.draw_text_full(container, sampletxt[0].c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NORMAL, m_color_table[MUI_TEXT_COLOR].color, m_color_table[MUI_TEXT_BG_COLOR].color, nullptr, nullptr);
+ y1 += line_height;
+
+ // draw subitem text
+ mui.draw_text_full(container, sampletxt[1].c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NORMAL, m_color_table[MUI_SUBITEM_COLOR].color, m_color_table[MUI_TEXT_BG_COLOR].color, nullptr, nullptr);
+ y1 += line_height;
+
+ // draw selected text
+ highlight(container, x1, y1, x2, y1 + line_height, m_color_table[MUI_SELECTED_BG_COLOR].color);
+ mui.draw_text_full(container, sampletxt[2].c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NORMAL, m_color_table[MUI_SELECTED_COLOR].color, m_color_table[MUI_SELECTED_BG_COLOR].color, nullptr, nullptr);
+ y1 += line_height;
+
+ // draw mouse over text
+ highlight(container, x1, y1, x2, y1 + line_height, m_color_table[MUI_MOUSEOVER_BG_COLOR].color);
+ mui.draw_text_full(container, sampletxt[3].c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NORMAL, m_color_table[MUI_MOUSEOVER_COLOR].color, m_color_table[MUI_MOUSEOVER_BG_COLOR].color, nullptr, nullptr);
+ y1 += line_height;
+
+ // draw clone text
+ mui.draw_text_full(container, sampletxt[4].c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NORMAL, m_color_table[MUI_CLONE_COLOR].color, m_color_table[MUI_TEXT_BG_COLOR].color, nullptr, nullptr);
+
+}
+
+//-------------------------------------------------
+// restore original colors
+//-------------------------------------------------
+
+void ui_menu_colors_ui::restore_colors()
+{
+ ui_options options;
+ for (int index = 1; index < MUI_RESTORE; index++)
+ m_color_table[index].color = rgb_t((UINT32)strtoul(options.value(m_color_table[index].option), nullptr, 16));
+}
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+ui_menu_rgb_ui::ui_menu_rgb_ui(running_machine &machine, render_container *container, rgb_t *_color, std::string _title) : ui_menu(machine, container)
+{
+ m_color = _color;
+ m_key_active = false;
+ m_lock_ref = 0;
+ m_title = _title;
+ m_search[0] = '\0';
+}
+
+//-------------------------------------------------
+// dtor
+//-------------------------------------------------
+
+ui_menu_rgb_ui::~ui_menu_rgb_ui()
+{
+}
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_menu_rgb_ui::handle()
+{
+ bool changed = false;
+
+ // process the menu
+ const ui_menu_event *m_event;
+
+ if (!m_key_active)
+ m_event = process(UI_MENU_PROCESS_LR_REPEAT);
+ else
+ m_event = process(UI_MENU_PROCESS_ONLYCHAR);
+
+ if (m_event != nullptr && m_event->itemref != nullptr)
+ {
+ switch ((FPTR)m_event->itemref)
+ {
+ case RGB_ALPHA:
+ if (m_event->iptkey == IPT_UI_LEFT && m_color->a() > 1)
+ {
+ m_color->set_a(m_color->a() - 1);
+ changed = true;
+ }
+
+ else if (m_event->iptkey == IPT_UI_RIGHT && m_color->a() < 255)
+ {
+ m_color->set_a(m_color->a() + 1);
+ changed = true;
+ }
+
+ else if (m_event->iptkey == IPT_UI_SELECT || m_event->iptkey == IPT_SPECIAL)
+ {
+ inkey_special(m_event);
+ changed = true;
+ }
+
+ break;
+
+ case RGB_RED:
+ if (m_event->iptkey == IPT_UI_LEFT && m_color->r() > 1)
+ {
+ m_color->set_r(m_color->r() - 1);
+ changed = true;
+ }
+
+ else if (m_event->iptkey == IPT_UI_RIGHT && m_color->r() < 255)
+ {
+ m_color->set_r(m_color->r() + 1);
+ changed = true;
+ }
+
+ else if (m_event->iptkey == IPT_UI_SELECT || m_event->iptkey == IPT_SPECIAL)
+ {
+ inkey_special(m_event);
+ changed = true;
+ }
+
+ break;
+
+ case RGB_GREEN:
+ if (m_event->iptkey == IPT_UI_LEFT && m_color->g() > 1)
+ {
+ m_color->set_g(m_color->g() - 1);
+ changed = true;
+ }
+
+ else if (m_event->iptkey == IPT_UI_RIGHT && m_color->g() < 255)
+ {
+ m_color->set_g(m_color->g() + 1);
+ changed = true;
+ }
+
+ else if (m_event->iptkey == IPT_UI_SELECT || m_event->iptkey == IPT_SPECIAL)
+ {
+ inkey_special(m_event);
+ changed = true;
+ }
+
+ break;
+
+ case RGB_BLUE:
+ if (m_event->iptkey == IPT_UI_LEFT && m_color->b() > 1)
+ {
+ m_color->set_b(m_color->b() - 1);
+ changed = true;
+ }
+
+ else if (m_event->iptkey == IPT_UI_RIGHT && m_color->b() < 255)
+ {
+ m_color->set_b(m_color->b() + 1);
+ changed = true;
+ }
+
+ else if (m_event->iptkey == IPT_UI_SELECT || m_event->iptkey == IPT_SPECIAL)
+ {
+ inkey_special(m_event);
+ changed = true;
+ }
+
+ break;
+
+ case PALETTE_CHOOSE:
+ if (m_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_palette_sel>(machine(), container, *m_color));
+ break;
+ }
+ }
+
+ if (changed)
+ reset(UI_MENU_RESET_REMEMBER_REF);
+}
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_rgb_ui::populate()
+{
+ // set filter arrow
+ UINT32 arrow_flags = MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW;
+ std::string s_text = std::string(m_search).append("_");
+
+ if (m_lock_ref != RGB_ALPHA)
+ {
+ arrow_flags = get_arrow_flags(0, 255, m_color->a());
+ item_append(_("Alpha"), string_format("%3u", m_color->a()).c_str(), arrow_flags, (void *)(FPTR)RGB_ALPHA);
+ }
+ else
+ item_append(_("Alpha"), s_text.c_str(), 0, (void *)(FPTR)RGB_ALPHA);
+
+ if (m_lock_ref != RGB_RED)
+ {
+ arrow_flags = get_arrow_flags(0, 255, m_color->r());
+ item_append(_("Red"), string_format("%3u", m_color->r()).c_str(), arrow_flags, (void *)(FPTR)RGB_RED);
+ }
+ else
+ item_append(_("Red"), s_text.c_str(), 0, (void *)(FPTR)RGB_RED);
+
+ if (m_lock_ref != RGB_GREEN)
+ {
+ arrow_flags = get_arrow_flags(0, 255, m_color->g());
+ item_append(_("Green"), string_format("%3u", m_color->g()).c_str(), arrow_flags, (void *)(FPTR)RGB_GREEN);
+ }
+ else
+ item_append(_("Green"), s_text.c_str(), 0, (void *)(FPTR)RGB_GREEN);
+
+ if (m_lock_ref != RGB_BLUE)
+ {
+ arrow_flags = get_arrow_flags(0, 255, m_color->b());
+ item_append(_("Blue"), string_format("%3u", m_color->b()).c_str(), arrow_flags, (void *)(FPTR)RGB_BLUE);
+ }
+ else
+ item_append(_("Blue"), s_text.c_str(), 0, (void *)(FPTR)RGB_BLUE);
+
+ item_append(ui_menu_item_type::SEPARATOR);
+ item_append(_("Choose from palette"), nullptr, 0, (void *)(FPTR)PALETTE_CHOOSE);
+ item_append(ui_menu_item_type::SEPARATOR);
+
+ custombottom = customtop = mame_machine_manager::instance()->ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER;
+}
+
+//-------------------------------------------------
+// perform our special rendering
+//-------------------------------------------------
+
+void ui_menu_rgb_ui::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ float width, maxwidth = origx2 - origx1;
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+
+ // top text
+ std::string topbuf = std::string(m_title).append(_(" - ARGB Settings"));
+ mui.draw_text_full(container, topbuf.c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += 2 * UI_BOX_LR_BORDER;
+ maxwidth = MAX(maxwidth, width);
+
+ // compute our bounds
+ float x1 = 0.5f - 0.5f * maxwidth;
+ float x2 = x1 + maxwidth;
+ float y1 = origy1 - top;
+ float y2 = origy1 - UI_BOX_TB_BORDER;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ mui.draw_text_full(container, topbuf.c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+
+ std::string sampletxt(_("Color preview ="));
+ maxwidth = origx2 - origx1;
+ mui.draw_text_full(container, sampletxt.c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += 2 * UI_BOX_LR_BORDER;
+ maxwidth = MAX(maxwidth, width);
+
+ // compute our bounds
+ x1 -= UI_BOX_LR_BORDER;
+ x2 = x1 + width;
+ y1 = origy2 + UI_BOX_TB_BORDER;
+ y2 = origy2 + bottom;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_RED_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the normal text
+ mui.draw_text_full(container, sampletxt.c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NORMAL, ARGB_WHITE, ARGB_BLACK, nullptr, nullptr);
+
+ float t_x2 = x1 - UI_BOX_LR_BORDER + maxwidth;
+ x1 = x2 + 2.0f * UI_BOX_LR_BORDER;
+ x2 = t_x2;
+ y1 -= UI_BOX_TB_BORDER;
+
+ mui.draw_outlined_box(container, x1, y1, x2, y2, *m_color);
+
+}
+
+//-------------------------------------------------
+// handle special key event
+//-------------------------------------------------
+
+void ui_menu_rgb_ui::inkey_special(const ui_menu_event *m_event)
+{
+ if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ m_key_active = !m_key_active;
+ m_lock_ref = (FPTR)m_event->itemref;
+
+ if (!m_key_active)
+ {
+ int val = atoi(m_search);
+ val = m_color->clamp(val);
+
+ switch ((FPTR)m_event->itemref)
+ {
+ case RGB_ALPHA:
+ m_color->set_a(val);
+ break;
+
+ case RGB_RED:
+ m_color->set_r(val);
+ break;
+
+ case RGB_GREEN:
+ m_color->set_g(val);
+ break;
+
+ case RGB_BLUE:
+ m_color->set_b(val);
+ break;
+ }
+
+ m_search[0] = 0;
+ m_lock_ref = 0;
+ return;
+ }
+ }
+
+ if (!m_key_active)
+ {
+ m_search[0] = 0;
+ return;
+ }
+
+ int buflen = strlen(m_search);
+
+ // if it's a backspace and we can handle it, do so
+ if (((m_event->unichar == 8 || m_event->unichar == 0x7f) && buflen > 0))
+ *(char *)utf8_previous_char(&m_search[buflen]) = 0;
+ else if (buflen >= 3)
+ return;
+ // if it's any other key and we're not maxed out, update
+ else if ((m_event->unichar >= '0' && m_event->unichar <= '9'))
+ buflen += utf8_from_uchar(&m_search[buflen], ARRAY_LENGTH(m_search) - buflen, m_event->unichar);
+
+ m_search[buflen] = 0;
+}
+
+ui_menu_palette_sel::palcolor ui_menu_palette_sel::m_palette[] = {
+ { __("White"), "FFFFFFFF" },
+ { __("Silver"), "FFC0C0C0" },
+ { __("Gray"), "FF808080" },
+ { __("Black"), "FF000000" },
+ { __("Red"), "FFFF0000" },
+ { __("Orange"), "FFFFA500" },
+ { __("Yellow"), "FFFFFF00" },
+ { __("Green"), "FF00FF00" },
+ { __("Blue"), "FF0000FF" },
+ { __("Violet"), "FF8F00FF" }
+};
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+ui_menu_palette_sel::ui_menu_palette_sel(running_machine &machine, render_container *container, rgb_t &_color)
+ : ui_menu(machine, container), m_original(_color)
+{
+}
+
+//-------------------------------------------------
+// dtor
+//-------------------------------------------------
+
+ui_menu_palette_sel::~ui_menu_palette_sel()
+{
+}
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_menu_palette_sel::handle()
+{
+ // process the menu
+ const ui_menu_event *m_event = process(MENU_FLAG_UI_PALETTE);
+ if (m_event != nullptr && m_event->itemref != nullptr)
+ {
+ if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ m_original = rgb_t((UINT32)strtoul(item[selected].subtext, nullptr, 16));
+ ui_menu::menu_stack->parent->reset(UI_MENU_RESET_SELECT_FIRST);
+ ui_menu::stack_pop(machine());
+ }
+ }
+}
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_palette_sel::populate()
+{
+ for (int x = 0; x < ARRAY_LENGTH(m_palette); ++x)
+ item_append(_(m_palette[x].name), m_palette[x].argb, MENU_FLAG_UI_PALETTE, (void *)(FPTR)(x + 1));
+
+ item_append(ui_menu_item_type::SEPARATOR);
+}
+
+//-------------------------------------------------
+// perform our special rendering
+//-------------------------------------------------
+
+void ui_menu_palette_sel::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+}
diff --git a/src/frontend/mame/ui/custui.h b/src/frontend/mame/ui/custui.h
new file mode 100644
index 00000000000..0aeffca9c5b
--- /dev/null
+++ b/src/frontend/mame/ui/custui.h
@@ -0,0 +1,178 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/***************************************************************************
+
+ ui/custui.h
+
+ Internal UI user interface.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef MAME_EMU_UI_UI_CUSTUI_H
+#define MAME_EMU_UI_UI_CUSTUI_H
+
+//-------------------------------------------------
+// Custom UI menu
+//-------------------------------------------------
+
+class ui_menu_custom_ui : public ui_menu
+{
+public:
+ ui_menu_custom_ui(running_machine &machine, render_container *container);
+ virtual ~ui_menu_custom_ui();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+private:
+ enum
+ {
+ LANGUAGE_MENU = 1,
+ FONT_MENU,
+ COLORS_MENU,
+ HIDE_MENU
+ };
+ static const char *const hide_status[];
+ std::vector<std::string> m_lang;
+ std::uint16_t m_currlang;
+};
+
+//-------------------------------------------------
+// Font UI menu
+//-------------------------------------------------
+
+class ui_menu_font_ui : public ui_menu
+{
+public:
+ ui_menu_font_ui(running_machine &machine, render_container *container);
+ virtual ~ui_menu_font_ui();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+private:
+ enum
+ {
+ INFOS_SIZE = 1,
+ FONT_SIZE,
+ MUI_FNT,
+ MUI_BOLD,
+ MUI_ITALIC
+ };
+
+ void list();
+
+ std::uint16_t m_actual;
+ std::vector<std::pair<std::string, std::string> > m_fonts;
+#ifdef UI_WINDOWS
+ bool m_bold, m_italic;
+#endif
+
+ float m_info_min, m_info_max, m_info_size;
+ int m_font_min, m_font_max, m_font_size;
+};
+
+//-------------------------------------------------
+// Colors UI menu
+//-------------------------------------------------
+
+class ui_menu_colors_ui : public ui_menu
+{
+public:
+ ui_menu_colors_ui(running_machine &machine, render_container *container);
+ virtual ~ui_menu_colors_ui();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+private:
+ enum
+ {
+ MUI_BACKGROUND_COLOR = 1,
+ MUI_BORDER_COLOR,
+ MUI_CLONE_COLOR,
+ MUI_DIPSW_COLOR,
+ MUI_GFXVIEWER_BG_COLOR,
+ MUI_MOUSEDOWN_BG_COLOR,
+ MUI_MOUSEDOWN_COLOR,
+ MUI_MOUSEOVER_BG_COLOR,
+ MUI_MOUSEOVER_COLOR,
+ MUI_SELECTED_BG_COLOR,
+ MUI_SELECTED_COLOR,
+ MUI_SLIDER_COLOR,
+ MUI_SUBITEM_COLOR,
+ MUI_TEXT_BG_COLOR,
+ MUI_TEXT_COLOR,
+ MUI_UNAVAILABLE_COLOR,
+ MUI_RESTORE
+ };
+
+ struct s_color_table
+ {
+ rgb_t color;
+ const char *option;
+ };
+
+ s_color_table m_color_table[MUI_RESTORE];
+ void restore_colors();
+};
+
+//-------------------------------------------------
+// ARGB UI menu
+//-------------------------------------------------
+
+class ui_menu_rgb_ui : public ui_menu
+{
+public:
+ ui_menu_rgb_ui(running_machine &machine, render_container *container, rgb_t *_color, std::string _title);
+ virtual ~ui_menu_rgb_ui();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+private:
+ rgb_t *m_color;
+ char m_search[4];
+ bool m_key_active;
+ int m_lock_ref;
+ std::string m_title;
+
+ enum
+ {
+ RGB_ALPHA = 1,
+ RGB_RED,
+ RGB_GREEN,
+ RGB_BLUE,
+ PALETTE_CHOOSE
+ };
+
+ void inkey_special(const ui_menu_event *menu_event);
+};
+
+//-------------------------------------------------
+// Palette UI menu
+//-------------------------------------------------
+
+class ui_menu_palette_sel : public ui_menu
+{
+public:
+ ui_menu_palette_sel(running_machine &machine, render_container *container, rgb_t &_color);
+ virtual ~ui_menu_palette_sel();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+private:
+ struct palcolor
+ {
+ const char *name;
+ const char *argb;
+ };
+
+ static palcolor m_palette[];
+ rgb_t &m_original;
+};
+
+#endif // MAME_EMU_UI_UI_CUSTUI_H
diff --git a/src/frontend/mame/ui/datfile.cpp b/src/frontend/mame/ui/datfile.cpp
new file mode 100644
index 00000000000..1e2ca1d6938
--- /dev/null
+++ b/src/frontend/mame/ui/datfile.cpp
@@ -0,0 +1,680 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/***************************************************************************
+
+ ui/datfile.cpp
+
+ UI DATs manager.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "drivenum.h"
+#include "ui/ui.h"
+#include "ui/datfile.h"
+#include "ui/utils.h"
+
+//-------------------------------------------------
+// TAGS
+//-------------------------------------------------
+static std::string DATAFILE_TAG("$");
+static std::string TAG_BIO("$bio");
+static std::string TAG_INFO("$info");
+static std::string TAG_MAME("$mame");
+static std::string TAG_COMMAND("$cmd");
+static std::string TAG_END("$end");
+static std::string TAG_DRIVER("$drv");
+static std::string TAG_STORY("$story");
+static std::string TAG_HISTORY_R("## REVISION:");
+static std::string TAG_MAMEINFO_R("# MAMEINFO.DAT");
+static std::string TAG_MESSINFO_R("# MESSINFO.DAT");
+static std::string TAG_SYSINFO_R("# This file was generated on");
+static std::string TAG_STORY_R("# version");
+static std::string TAG_COMMAND_SEPARATOR("-----------------------------------------------");
+static std::string TAG_GAMEINIT_R("# GAMEINIT.DAT");
+
+//-------------------------------------------------
+// Statics
+//-------------------------------------------------
+datfile_manager::dataindex datfile_manager::m_histidx;
+datfile_manager::dataindex datfile_manager::m_mameidx;
+datfile_manager::dataindex datfile_manager::m_messidx;
+datfile_manager::dataindex datfile_manager::m_cmdidx;
+datfile_manager::dataindex datfile_manager::m_sysidx;
+datfile_manager::dataindex datfile_manager::m_storyidx;
+datfile_manager::dataindex datfile_manager::m_ginitidx;
+datfile_manager::drvindex datfile_manager::m_drvidx;
+datfile_manager::drvindex datfile_manager::m_messdrvidx;
+datfile_manager::drvindex datfile_manager::m_menuidx;
+datfile_manager::swindex datfile_manager::m_swindex;
+std::string datfile_manager::m_history_rev;
+std::string datfile_manager::m_mame_rev;
+std::string datfile_manager::m_mess_rev;
+std::string datfile_manager::m_sysinfo_rev;
+std::string datfile_manager::m_story_rev;
+std::string datfile_manager::m_ginit_rev;
+bool datfile_manager::first_run = true;
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+datfile_manager::datfile_manager(running_machine &machine) : m_machine(machine)
+{
+ if (mame_machine_manager::instance()->ui().options().enabled_dats() && first_run)
+ {
+ first_run = false;
+ if (parseopen("mameinfo.dat"))
+ {
+ init_mameinfo();
+ parseclose();
+ }
+
+ if (parseopen("command.dat"))
+ {
+ init_command();
+ parseclose();
+ }
+
+ if (parseopen("story.dat"))
+ {
+ init_storyinfo();
+ parseclose();
+ }
+
+ if (parseopen("messinfo.dat"))
+ {
+ init_messinfo();
+ parseclose();
+ }
+
+ if (parseopen("sysinfo.dat"))
+ {
+ init_sysinfo();
+ parseclose();
+ }
+
+ if (parseopen("history.dat"))
+ {
+ init_history();
+ parseclose();
+ }
+
+ if (parseopen("gameinit.dat"))
+ {
+ init_gameinit();
+ parseclose();
+ }
+ }
+}
+
+//-------------------------------------------------
+// initialize sysinfo.dat index
+//-------------------------------------------------
+void datfile_manager::init_sysinfo()
+{
+ int swcount = 0;
+ int count = index_datafile(m_sysidx, swcount);
+ osd_printf_verbose("Sysinfo.dat games found = %i\n", count);
+ osd_printf_verbose("Rev = %s\n", m_sysinfo_rev.c_str());
+}
+
+//-------------------------------------------------
+// initialize story.dat index
+//-------------------------------------------------
+void datfile_manager::init_storyinfo()
+{
+ int swcount = 0;
+ int count = index_datafile(m_storyidx, swcount);
+ osd_printf_verbose("Story.dat games found = %i\n", count);
+}
+
+//-------------------------------------------------
+// initialize history.dat index
+//-------------------------------------------------
+void datfile_manager::init_history()
+{
+ int swcount = 0;
+ int count = index_datafile(m_histidx, swcount);
+ osd_printf_verbose("History.dat systems found = %i\n", count);
+ osd_printf_verbose("History.dat software packages found = %i\n", swcount);
+ osd_printf_verbose("Rev = %s\n", m_history_rev.c_str());
+}
+
+//-------------------------------------------------
+// initialize gameinit.dat index
+//-------------------------------------------------
+void datfile_manager::init_gameinit()
+{
+ int swcount = 0;
+ drvindex tmp;
+ int count = index_mame_mess_info(m_ginitidx, tmp, swcount);
+ osd_printf_verbose("Gameinit.dat games found = %i\n", count);
+ osd_printf_verbose("Rev = %s\n", m_ginit_rev.c_str());
+}
+
+//-------------------------------------------------
+// initialize mameinfo.dat index
+//-------------------------------------------------
+void datfile_manager::init_mameinfo()
+{
+ int drvcount = 0;
+ int count = index_mame_mess_info(m_mameidx, m_drvidx, drvcount);
+ osd_printf_verbose("Mameinfo.dat games found = %i\n", count);
+ osd_printf_verbose("Mameinfo.dat drivers found = %d\n", drvcount);
+ osd_printf_verbose("Rev = %s\n", m_mame_rev.c_str());
+}
+
+//-------------------------------------------------
+// initialize messinfo.dat index
+//-------------------------------------------------
+void datfile_manager::init_messinfo()
+{
+ int drvcount = 0;
+ int count = index_mame_mess_info(m_messidx, m_messdrvidx, drvcount);
+ osd_printf_verbose("Messinfo.dat games found = %i\n", count);
+ osd_printf_verbose("Messinfo.dat drivers found = %d\n", drvcount);
+ osd_printf_verbose("Rev = %s\n", m_mess_rev.c_str());
+}
+
+//-------------------------------------------------
+// initialize command.dat index
+//-------------------------------------------------
+void datfile_manager::init_command()
+{
+ int swcount = 0;
+ int count = index_datafile(m_cmdidx, swcount);
+ osd_printf_verbose("Command.dat games found = %i\n", count);
+}
+
+bool datfile_manager::has_software(std::string &softlist, std::string &softname, std::string &parentname)
+{
+ // Find software in software list index
+ if (m_swindex.find(softlist) == m_swindex.end())
+ return false;
+
+ m_itemsiter = m_swindex[softlist].find(softname);
+ if (m_itemsiter == m_swindex[softlist].end() && !parentname.empty())
+ m_itemsiter = m_swindex[softlist].find(parentname);
+
+ if (m_itemsiter == m_swindex[softlist].end())
+ return false;
+
+ return true;
+}
+//-------------------------------------------------
+// load software info
+//-------------------------------------------------
+void datfile_manager::load_software_info(std::string &softlist, std::string &buffer, std::string &softname, std::string &parentname)
+{
+ // Load history text
+ if (!m_swindex.empty() && parseopen("history.dat"))
+ {
+ // Find software in software list index
+ if (!has_software(softlist, softname, parentname))
+ return;
+
+ long s_offset = (*m_itemsiter).second;
+ char rbuf[64 * 1024];
+ fseek(fp, s_offset, SEEK_SET);
+ std::string readbuf;
+ while (fgets(rbuf, 64 * 1024, fp) != nullptr)
+ {
+ readbuf = chartrimcarriage(rbuf);
+
+ // end entry when a end tag is encountered
+ if (readbuf == TAG_END)
+ break;
+
+ // add this string to the buffer
+ buffer.append(readbuf).append("\n");
+ }
+ parseclose();
+ }
+}
+
+//-------------------------------------------------
+// load_data_info
+//-------------------------------------------------
+void datfile_manager::load_data_info(const game_driver *drv, std::string &buffer, int type)
+{
+ dataindex index_idx;
+ drvindex driver_idx;
+ std::string tag;
+ std::string filename;
+
+ switch (type)
+ {
+ case UI_HISTORY_LOAD:
+ filename = "history.dat";
+ tag = TAG_BIO;
+ index_idx = m_histidx;
+ break;
+ case UI_MAMEINFO_LOAD:
+ filename = "mameinfo.dat";
+ tag = TAG_MAME;
+ index_idx = m_mameidx;
+ driver_idx = m_drvidx;
+ break;
+ case UI_SYSINFO_LOAD:
+ filename = "sysinfo.dat";
+ tag = TAG_BIO;
+ index_idx = m_sysidx;
+ break;
+ case UI_MESSINFO_LOAD:
+ filename = "messinfo.dat";
+ tag = TAG_MAME;
+ index_idx = m_messidx;
+ driver_idx = m_messdrvidx;
+ break;
+ case UI_STORY_LOAD:
+ filename = "story.dat";
+ tag = TAG_STORY;
+ index_idx = m_storyidx;
+ break;
+ case UI_GINIT_LOAD:
+ filename = "gameinit.dat";
+ tag = TAG_MAME;
+ index_idx = m_ginitidx;
+ break;
+ }
+
+ if (parseopen(filename.c_str()))
+ {
+ load_data_text(drv, buffer, index_idx, tag);
+
+ // load driver info
+ if (!driver_idx.empty())
+ load_driver_text(drv, buffer, driver_idx, TAG_DRIVER);
+
+ // cleanup mameinfo and sysinfo double line spacing
+ if ((tag == TAG_MAME && type != UI_GINIT_LOAD) || type == UI_SYSINFO_LOAD)
+ strreplace(buffer, "\n\n", "\n");
+
+ parseclose();
+ }
+}
+
+//-------------------------------------------------
+// load a game text into the buffer
+//-------------------------------------------------
+void datfile_manager::load_data_text(const game_driver *drv, std::string &buffer, dataindex &idx, std::string &tag)
+{
+ dataindex::iterator itemsiter = idx.find(drv);
+ if (itemsiter == idx.end())
+ {
+ int cloneof = driver_list::non_bios_clone(*drv);
+ if (cloneof == -1)
+ return;
+ else
+ {
+ const game_driver *c_drv = &driver_list::driver(cloneof);
+ itemsiter = idx.find(c_drv);
+ if (itemsiter == idx.end())
+ return;
+ }
+ }
+
+ long s_offset = (*itemsiter).second;
+ fseek(fp, s_offset, SEEK_SET);
+ char rbuf[64 * 1024];
+ std::string readbuf;
+ while (fgets(rbuf, 64 * 1024, fp) != nullptr)
+ {
+ readbuf = chartrimcarriage(rbuf);
+
+ // end entry when a end tag is encountered
+ if (readbuf == TAG_END)
+ break;
+
+ // continue if a specific tag is encountered
+ if (readbuf == tag)
+ continue;
+
+ // add this string to the buffer
+ buffer.append(readbuf).append("\n");
+ }
+}
+
+//-------------------------------------------------
+// load a driver name and offset into an
+// indexed array
+//-------------------------------------------------
+void datfile_manager::load_driver_text(const game_driver *drv, std::string &buffer, drvindex &idx, std::string &tag)
+{
+ std::string s(core_filename_extract_base(drv->source_file));
+ drvindex::const_iterator index = idx.find(s);
+
+ // if driver not found, return
+ if (index == idx.end())
+ return;
+
+ buffer.append("\n--- DRIVER INFO ---\n").append("Driver: ").append(s).append("\n\n");
+ long s_offset = (*index).second;
+ fseek(fp, s_offset, SEEK_SET);
+ char rbuf[64 * 1024];
+ std::string readbuf;
+ while (fgets(rbuf, 64 * 1024, fp) != nullptr)
+ {
+ readbuf = chartrimcarriage(rbuf);
+
+ // end entry when a end tag is encountered
+ if (readbuf == TAG_END)
+ break;
+
+ // continue if a specific tag is encountered
+ if (readbuf == tag)
+ continue;
+
+ // add this string to the buffer
+ buffer.append(readbuf).append("\n");
+ }
+}
+
+//-------------------------------------------------
+// load a game name and offset into an
+// indexed array (mameinfo)
+//-------------------------------------------------
+int datfile_manager::index_mame_mess_info(dataindex &index, drvindex &index_drv, int &drvcount)
+{
+ std::string name;
+ size_t foundtag;
+ size_t t_mame = TAG_MAMEINFO_R.size();
+ size_t t_mess = TAG_MESSINFO_R.size();
+ size_t t_ginit = TAG_GAMEINIT_R.size();
+ size_t t_info = TAG_INFO.size();
+
+ char rbuf[64 * 1024];
+ std::string readbuf, xid;
+ while (fgets(rbuf, 64 * 1024, fp) != nullptr)
+ {
+ readbuf = chartrimcarriage(rbuf);
+ if (m_mame_rev.empty() && readbuf.compare(0, t_mame, TAG_MAMEINFO_R) == 0)
+ {
+ size_t found = readbuf.find(" ", t_mame + 1);
+ m_mame_rev = readbuf.substr(t_mame + 1, found - t_mame);
+ }
+ else if (m_mess_rev.empty() && (foundtag = readbuf.find(TAG_MESSINFO_R)) != std::string::npos)
+ {
+ size_t found = readbuf.find(" ", foundtag + t_mess + 1);
+ m_mess_rev = readbuf.substr(foundtag + t_mess + 1, found - t_mess - foundtag);
+ }
+ else if (m_ginit_rev.empty() && readbuf.compare(0, t_ginit, TAG_GAMEINIT_R) == 0)
+ {
+ size_t found = readbuf.find(" ", t_ginit + 1);
+ m_ginit_rev = readbuf.substr(t_ginit + 1, found - t_ginit);
+ }
+ else if (readbuf.compare(0, t_info, TAG_INFO) == 0)
+ {
+ // TAG_INFO
+ fgets(rbuf, 64 * 1024, fp);
+ xid = chartrimcarriage(rbuf);
+ name = readbuf.substr(t_info + 1);
+ if (xid == TAG_MAME)
+ {
+ // validate driver
+ int game_index = driver_list::find(name.c_str());
+ if (game_index != -1)
+ index.emplace(&driver_list::driver(game_index), ftell(fp));
+ }
+ else if (xid == TAG_DRIVER)
+ {
+ index_drv.emplace(name, ftell(fp));
+ drvcount++;
+ }
+ }
+ }
+ return index.size();
+}
+
+//-------------------------------------------------
+// load a game name and offset into an
+// indexed array
+//-------------------------------------------------
+int datfile_manager::index_datafile(dataindex &index, int &swcount)
+{
+ std::string readbuf, name;
+ size_t t_hist = TAG_HISTORY_R.size();
+ size_t t_story = TAG_STORY_R.size();
+ size_t t_sysinfo = TAG_SYSINFO_R.size();
+ size_t t_info = TAG_INFO.size();
+ size_t t_bio = TAG_BIO.size();
+ char rbuf[64 * 1024];
+ while (fgets(rbuf, 64 * 1024, fp) != nullptr)
+ {
+ readbuf = chartrimcarriage(rbuf);
+
+ if (m_history_rev.empty() && readbuf.compare(0, t_hist, TAG_HISTORY_R) == 0)
+ {
+ size_t found = readbuf.find(" ", t_hist + 1);
+ m_history_rev = readbuf.substr(t_hist + 1, found - t_hist);
+ }
+ else if (m_sysinfo_rev.empty() && readbuf.compare(0, t_sysinfo, TAG_SYSINFO_R) == 0)
+ {
+ size_t found = readbuf.find(".", t_sysinfo + 1);
+ m_sysinfo_rev = readbuf.substr(t_sysinfo + 1, found - t_sysinfo);
+ }
+ else if (m_story_rev.empty() && readbuf.compare(0, t_story, TAG_STORY_R) == 0)
+ m_story_rev = readbuf.substr(t_story + 1);
+ else if (readbuf.compare(0, t_info, TAG_INFO) == 0)
+ {
+ int curpoint = t_info + 1;
+ int ends = readbuf.size();
+ while (curpoint < ends)
+ {
+ // search for comma
+ size_t found = readbuf.find(",", curpoint);
+
+ // found it
+ if (found != std::string::npos)
+ {
+ // copy data and validate driver
+ name = readbuf.substr(curpoint, found - curpoint);
+
+ // validate driver
+ int game_index = driver_list::find(name.c_str());
+ if (game_index != -1)
+ index.emplace(&driver_list::driver(game_index), ftell(fp));
+
+ // update current point
+ curpoint = ++found;
+ }
+ // if comma not found, copy data while until reach the end of string
+ else if (curpoint < ends)
+ {
+ name = readbuf.substr(curpoint);
+ int game_index = driver_list::find(name.c_str());
+ if (game_index != -1)
+ index.emplace(&driver_list::driver(game_index), ftell(fp));
+
+ // update current point
+ curpoint = ends;
+ }
+ }
+ }
+ // search for software info
+ else if (!readbuf.empty() && readbuf[0] == DATAFILE_TAG[0])
+ {
+ fgets(rbuf, 64 * 1024, fp);
+ std::string readbuf_2(chartrimcarriage(rbuf));
+
+ // TAG_BIO identifies software list
+ if (readbuf_2.compare(0, t_bio, TAG_BIO) == 0)
+ {
+ size_t eq_sign = readbuf.find("=");
+ std::string s_list(readbuf.substr(1, eq_sign - 1));
+ std::string s_roms(readbuf.substr(eq_sign + 1));
+ int ends = s_list.size();
+ int curpoint = 0;
+
+ while (curpoint < ends)
+ {
+ size_t found = s_list.find(",", curpoint);
+
+ // found it
+ if (found != std::string::npos)
+ {
+ name = s_list.substr(curpoint, found - curpoint);
+ curpoint = ++found;
+ }
+ else
+ {
+ name = s_list;
+ curpoint = ends;
+ }
+
+ // search for a software list in the index, if not found then allocates
+ std::string lname(name);
+ int cpoint = 0;
+ int cends = s_roms.size();
+
+ while (cpoint < cends)
+ {
+ // search for comma
+ size_t found = s_roms.find(",", cpoint);
+
+ // found it
+ if (found != std::string::npos)
+ {
+ // copy data
+ name = s_roms.substr(cpoint, found - cpoint);
+
+ // add a SoftwareItem
+ m_swindex[lname].emplace(name, ftell(fp));
+
+ // update current point
+ cpoint = ++found;
+ swcount++;
+ }
+ else
+ {
+ // if reach the end, bail out
+ if (s_roms[cpoint] == '\r' || s_roms[cpoint] == '\n')
+ break;
+
+ // copy data
+ name = s_roms.substr(cpoint);
+
+ // add a SoftwareItem
+ m_swindex[lname].emplace(name, ftell(fp));
+
+ // update current point
+ cpoint = cends;
+ swcount++;
+ }
+ }
+ }
+ }
+ }
+ }
+ return index.size();
+}
+
+//---------------------------------------------------------
+// parseopen - Open up file for reading
+//---------------------------------------------------------
+bool datfile_manager::parseopen(const char *filename)
+{
+ // MAME core file parsing functions fail in recognizing UNICODE chars in UTF-8 without BOM,
+ // so it's better and faster use standard C fileio functions.
+
+ emu_file file(mame_machine_manager::instance()->ui().options().history_path(), OPEN_FLAG_READ);
+ if (file.open(filename) != osd_file::error::NONE)
+ return false;
+
+ m_fullpath = file.fullpath();
+ file.close();
+ fp = fopen(m_fullpath.c_str(), "rb");
+
+ fgetc(fp);
+ fseek(fp, 0, SEEK_SET);
+ return true;
+}
+
+//-------------------------------------------------
+// create the menu index
+//-------------------------------------------------
+void datfile_manager::index_menuidx(const game_driver *drv, dataindex &idx, drvindex &index)
+{
+ dataindex::iterator itemsiter = idx.find(drv);
+ if (itemsiter == idx.end())
+ {
+ int cloneof = driver_list::non_bios_clone(*drv);
+ if (cloneof == -1)
+ return;
+ else
+ {
+ const game_driver *c_drv = &driver_list::driver(cloneof);
+ itemsiter = idx.find(c_drv);
+ if (itemsiter == idx.end())
+ return;
+ }
+ }
+
+ // seek to correct point in datafile
+ long s_offset = (*itemsiter).second;
+ fseek(fp, s_offset, SEEK_SET);
+ size_t tinfo = TAG_INFO.size();
+ char rbuf[64 * 1024];
+ std::string readbuf;
+ while (fgets(rbuf, 64 * 1024, fp) != nullptr)
+ {
+ readbuf = chartrimcarriage(rbuf);
+
+ if (!core_strnicmp(TAG_INFO.c_str(), readbuf.c_str(), tinfo))
+ break;
+
+ // TAG_COMMAND identifies the driver
+ if (readbuf == TAG_COMMAND)
+ {
+ fgets(rbuf, 64 * 1024, fp);
+ chartrimcarriage(rbuf);
+ index.emplace(rbuf, ftell(fp));
+ }
+ }
+}
+
+//-------------------------------------------------
+// load command text into the buffer
+//-------------------------------------------------
+void datfile_manager::load_command_info(std::string &buffer, std::string &sel)
+{
+ if (parseopen("command.dat"))
+ {
+ // open and seek to correct point in datafile
+ long offset = m_menuidx.at(sel);
+ fseek(fp, offset, SEEK_SET);
+ char rbuf[64 * 1024];
+ std::string readbuf;
+ while (fgets(rbuf, 64 * 1024, fp) != nullptr)
+ {
+ readbuf = chartrimcarriage(rbuf);
+
+ // skip separator lines
+ if (readbuf == TAG_COMMAND_SEPARATOR)
+ continue;
+
+ // end entry when a tag is encountered
+ if (readbuf == TAG_END)
+ break;
+
+ // add this string to the buffer
+ buffer.append(readbuf).append("\n");;
+ }
+ parseclose();
+ }
+}
+
+//-------------------------------------------------
+// load submenu item for command.dat
+//-------------------------------------------------
+void datfile_manager::command_sub_menu(const game_driver *drv, std::vector<std::string> &menuitems)
+{
+ if (parseopen("command.dat"))
+ {
+ m_menuidx.clear();
+ index_menuidx(drv, m_cmdidx, m_menuidx);
+ for (auto & elem : m_menuidx)
+ menuitems.push_back(elem.first);
+ parseclose();
+ }
+}
diff --git a/src/frontend/mame/ui/datfile.h b/src/frontend/mame/ui/datfile.h
new file mode 100644
index 00000000000..27bb8094704
--- /dev/null
+++ b/src/frontend/mame/ui/datfile.h
@@ -0,0 +1,96 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/***************************************************************************
+
+ ui/datfile.h
+
+ UI DATs manager.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_DATFILE_H__
+#define __UI_DATFILE_H__
+
+//-------------------------------------------------
+// Datafile Manager
+//-------------------------------------------------
+class datfile_manager
+{
+public:
+ // construction/destruction
+ datfile_manager(running_machine &machine);
+
+ // getters
+ running_machine &machine() const { return m_machine; }
+
+ // actions
+ void load_data_info(const game_driver *drv, std::string &buffer, int type);
+ void load_command_info(std::string &buffer, std::string &sel);
+ void load_software_info(std::string &softlist, std::string &buffer, std::string &softname, std::string &parentname);
+ void command_sub_menu(const game_driver *drv, std::vector<std::string> &menuitems);
+ void reset_run() { first_run = true; }
+
+ std::string rev_history() const { return m_history_rev; }
+ std::string rev_mameinfo() const { return m_mame_rev; }
+ std::string rev_messinfo() const { return m_mess_rev; }
+ std::string rev_sysinfo() const { return m_sysinfo_rev; }
+ std::string rev_storyinfo() const { return m_story_rev; }
+ std::string rev_ginitinfo() const { return m_ginit_rev; }
+
+ bool has_history(const game_driver *driver) { return (m_histidx.find(driver) != m_histidx.end()); }
+ bool has_mameinfo(const game_driver *driver) { return (m_mameidx.find(driver) != m_mameidx.end()); }
+ bool has_messinfo(const game_driver *driver) { return (m_messidx.find(driver) != m_messidx.end()); }
+ bool has_command(const game_driver *driver) { return (m_cmdidx.find(driver) != m_cmdidx.end()); }
+ bool has_sysinfo(const game_driver *driver) { return (m_sysidx.find(driver) != m_sysidx.end()); }
+ bool has_story(const game_driver *driver) { return (m_storyidx.find(driver) != m_storyidx.end()); }
+ bool has_gameinit(const game_driver *driver) { return (m_ginitidx.find(driver) != m_ginitidx.end()); }
+ bool has_software(std::string &softlist, std::string &softname, std::string &parentname);
+
+ bool has_data(const game_driver *a = nullptr)
+ {
+ const game_driver *d = (a != nullptr) ? a : &machine().system();
+ return (has_history(d) || has_mameinfo(d) || has_messinfo(d) || has_command(d) || has_sysinfo(d) || has_story(d) || has_gameinit(d));
+ }
+private:
+ using drvindex = std::unordered_map<std::string, long>;
+ using dataindex = std::unordered_map<const game_driver *, long>;
+ using swindex = std::unordered_map<std::string, drvindex>;
+
+ // global index
+ static dataindex m_histidx, m_mameidx, m_messidx, m_cmdidx, m_sysidx, m_storyidx, m_ginitidx;
+ static drvindex m_drvidx, m_messdrvidx, m_menuidx;
+ static swindex m_swindex;
+
+ // internal helpers
+ void init_history();
+ void init_mameinfo();
+ void init_messinfo();
+ void init_command();
+ void init_sysinfo();
+ void init_storyinfo();
+ void init_gameinit();
+
+ // file open/close/seek
+ bool parseopen(const char *filename);
+ void parseclose() { if (fp != nullptr) fclose(fp); }
+
+ int index_mame_mess_info(dataindex &index, drvindex &index_drv, int &drvcount);
+ int index_datafile(dataindex &index, int &swcount);
+ void index_menuidx(const game_driver *drv, dataindex &idx, drvindex &index);
+ drvindex::iterator m_itemsiter;
+
+ void load_data_text(const game_driver *drv, std::string &buffer, dataindex &idx, std::string &tag);
+ void load_driver_text(const game_driver *drv, std::string &buffer, drvindex &idx, std::string &tag);
+
+ // internal state
+ running_machine &m_machine; // reference to our machine
+ std::string m_fullpath;
+ static std::string m_history_rev, m_mame_rev, m_mess_rev, m_sysinfo_rev, m_story_rev, m_ginit_rev;
+ FILE *fp = nullptr;
+ static bool first_run;
+};
+
+
+#endif /* __UI_DATFILE_H__ */
diff --git a/src/frontend/mame/ui/datmenu.cpp b/src/frontend/mame/ui/datmenu.cpp
new file mode 100644
index 00000000000..7e90e11178d
--- /dev/null
+++ b/src/frontend/mame/ui/datmenu.cpp
@@ -0,0 +1,296 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/*********************************************************************
+
+ ui/datmenu.cpp
+
+ Internal UI user interface.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "ui/ui.h"
+#include "ui/menu.h"
+#include "drivenum.h"
+#include "rendfont.h"
+#include "ui/datfile.h"
+#include "ui/datmenu.h"
+#include "ui/utils.h"
+#include "softlist.h"
+
+//-------------------------------------------------
+// ctor / dtor
+//-------------------------------------------------
+
+ui_menu_dats_view::ui_menu_dats_view(running_machine &machine, render_container *container, const game_driver *driver)
+ : ui_menu(machine, container)
+ , m_actual(0)
+ , m_driver((driver == nullptr) ? &machine.system() : driver)
+ , m_issoft(false)
+
+{
+ for (device_image_interface &image : image_interface_iterator(machine.root_device()))
+ {
+ if (image.filename())
+ {
+ m_list = strensure(image.software_list_name());
+ m_short = strensure(image.software_entry()->shortname());
+ m_long = strensure(image.software_entry()->longname());
+ m_parent = strensure(image.software_entry()->parentname());
+ }
+ }
+
+ init_items();
+}
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+ui_menu_dats_view::ui_menu_dats_view(running_machine &machine, render_container *container, ui_software_info *swinfo, const game_driver *driver)
+ : ui_menu(machine, container)
+ , m_actual(0)
+ , m_driver((driver == nullptr) ? &machine.system() : driver)
+ , m_swinfo(swinfo)
+ , m_list(swinfo->listname)
+ , m_short(swinfo->shortname)
+ , m_long(swinfo->longname)
+ , m_parent(swinfo->parentname)
+ , m_issoft(true)
+
+{
+ if (mame_machine_manager::instance()->datfile().has_software(m_list, m_short, m_parent))
+ m_items_list.emplace_back(_("Software History"), UI_HISTORY_LOAD, mame_machine_manager::instance()->datfile().rev_history());
+ if (swinfo != nullptr && !swinfo->usage.empty())
+ m_items_list.emplace_back(_("Software Usage"), 0, "");
+}
+
+//-------------------------------------------------
+// dtor
+//-------------------------------------------------
+
+ui_menu_dats_view::~ui_menu_dats_view()
+{
+}
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_menu_dats_view::handle()
+{
+ const ui_menu_event *m_event = process(MENU_FLAG_UI_DATS);
+ if (m_event != nullptr)
+ {
+ if (m_event->iptkey == IPT_UI_LEFT && m_actual > 0)
+ {
+ m_actual--;
+ reset(UI_MENU_RESET_SELECT_FIRST);
+ }
+
+ if (m_event->iptkey == IPT_UI_RIGHT && m_actual < m_items_list.size() - 1)
+ {
+ m_actual++;
+ reset(UI_MENU_RESET_SELECT_FIRST);
+ }
+ }
+}
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_dats_view::populate()
+{
+ bool paused = machine().paused();
+ if (!paused)
+ machine().pause();
+
+ (m_issoft == true) ? get_data_sw() : get_data();
+
+ item_append(MENU_SEPARATOR_ITEM, nullptr, (MENU_FLAG_UI_DATS | MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW), nullptr);
+ customtop = 2.0f * mame_machine_manager::instance()->ui().get_line_height() + 4.0f * UI_BOX_TB_BORDER;
+ custombottom = mame_machine_manager::instance()->ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER;
+
+ if (!paused)
+ machine().resume();
+}
+
+//-------------------------------------------------
+// perform our special rendering
+//-------------------------------------------------
+
+void ui_menu_dats_view::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+ float maxwidth = origx2 - origx1;
+ float width;
+ std::string driver = (m_issoft == true) ? m_swinfo->longname : m_driver->description;
+
+ mui.draw_text_full(container, driver.c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += 2 * UI_BOX_LR_BORDER;
+ maxwidth = MAX(maxwidth, width);
+
+ // compute our bounds
+ float x1 = 0.5f - 0.5f * maxwidth;
+ float x2 = x1 + maxwidth;
+ float y1 = origy1 - top;
+ float y2 = origy1 - 2.0f * UI_BOX_TB_BORDER - mui.get_line_height();
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ mui.draw_text_full(container, driver.c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+
+ maxwidth = 0;
+ for (auto & elem : m_items_list)
+ {
+ mui.draw_text_full(container, elem.label.c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ maxwidth += width;
+ }
+
+ float space = (1.0f - maxwidth) / (m_items_list.size() * 2);
+
+ // compute our bounds
+ x1 -= UI_BOX_LR_BORDER;
+ x2 += UI_BOX_LR_BORDER;
+ y1 = y2 + UI_BOX_TB_BORDER;
+ y2 += mui.get_line_height() + 2.0f * UI_BOX_TB_BORDER;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
+
+ // take off the borders
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ int x = 0;
+ for (auto & elem : m_items_list)
+ {
+ x1 += space;
+ rgb_t fcolor = (m_actual == x) ? rgb_t(0xff, 0xff, 0xff, 0x00) : UI_TEXT_COLOR;
+ rgb_t bcolor = (m_actual == x) ? rgb_t(0xff, 0xff, 0xff, 0xff) : UI_TEXT_BG_COLOR;
+ mui.draw_text_full(container, elem.label.c_str(), x1, y1, 1.0f, JUSTIFY_LEFT, WRAP_NEVER, DRAW_NONE, fcolor, bcolor, &width, nullptr);
+
+ if (bcolor != UI_TEXT_BG_COLOR)
+ mui.draw_textured_box(container, x1 - (space / 2), y1, x1 + width + (space / 2), y2, bcolor, rgb_t(255, 43, 43, 43),
+ hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
+
+ mui.draw_text_full(container, elem.label.c_str(), x1, y1, 1.0f, JUSTIFY_LEFT, WRAP_NEVER, DRAW_NORMAL, fcolor, bcolor, &width, nullptr);
+ x1 += width + space;
+ ++x;
+ }
+
+ // bottom
+ std::string revision;
+ revision.assign(_("Revision: ")).append(m_items_list[m_actual].revision);
+ mui.draw_text_full(container, revision.c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE, DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += 2 * UI_BOX_LR_BORDER;
+ maxwidth = MAX(origx2 - origx1, width);
+
+ // compute our bounds
+ x1 = 0.5f - 0.5f * maxwidth;
+ x2 = x1 + maxwidth;
+ y1 = origy2 + UI_BOX_TB_BORDER;
+ y2 = origy2 + bottom;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ mui.draw_text_full(container, revision.c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+}
+
+//-------------------------------------------------
+// load data from DATs
+//-------------------------------------------------
+
+void ui_menu_dats_view::get_data()
+{
+ std::vector<int> xstart;
+ std::vector<int> xend;
+ std::string buffer;
+ std::vector<std::string> m_item;
+ if (m_items_list[m_actual].option == UI_COMMAND_LOAD)
+ {
+ mame_machine_manager::instance()->datfile().command_sub_menu(m_driver, m_item);
+ if (!m_item.empty())
+ {
+ for (size_t x = 0; x < m_item.size(); ++x)
+ {
+ std::string t_buffer;
+ buffer.append(m_item[x]).append("\n");
+ mame_machine_manager::instance()->datfile().load_command_info(t_buffer, m_item[x]);
+ if (!t_buffer.empty())
+ buffer.append(t_buffer).append("\n");
+ }
+ convert_command_glyph(buffer);
+ }
+ }
+ else
+ mame_machine_manager::instance()->datfile().load_data_info(m_driver, buffer, m_items_list[m_actual].option);
+
+ int lines = mame_machine_manager::instance()->ui().wrap_text(container, buffer.c_str(), 0.0f, 0.0f, 1.0f - (4.0f * UI_BOX_LR_BORDER), xstart, xend);
+ for (int x = 0; x < lines; ++x)
+ {
+ std::string tempbuf(buffer.substr(xstart[x], xend[x] - xstart[x]));
+ item_append(tempbuf.c_str(), nullptr, (MENU_FLAG_UI_DATS | MENU_FLAG_DISABLE), (void *)(FPTR)(x + 1));
+ }
+}
+
+void ui_menu_dats_view::get_data_sw()
+{
+ std::vector<int> xstart;
+ std::vector<int> xend;
+ std::string buffer;
+ if (m_items_list[m_actual].option == 0)
+ buffer = m_swinfo->usage;
+ else
+ {
+ if (m_swinfo->startempty == 1)
+ mame_machine_manager::instance()->datfile().load_data_info(m_swinfo->driver, buffer, UI_HISTORY_LOAD);
+ else
+ mame_machine_manager::instance()->datfile().load_software_info(m_swinfo->listname, buffer, m_swinfo->shortname, m_swinfo->parentname);
+ }
+
+ int lines = mame_machine_manager::instance()->ui().wrap_text(container, buffer.c_str(), 0.0f, 0.0f, 1.0f - (4.0f * UI_BOX_LR_BORDER), xstart, xend);
+ for (int x = 0; x < lines; ++x)
+ {
+ std::string tempbuf(buffer.substr(xstart[x], xend[x] - xstart[x]));
+ item_append(tempbuf.c_str(), nullptr, (MENU_FLAG_UI_DATS | MENU_FLAG_DISABLE), (void *)(FPTR)(x + 1));
+ }
+}
+
+void ui_menu_dats_view::init_items()
+{
+ datfile_manager &datfile = mame_machine_manager::instance()->datfile();
+ if (datfile.has_history(m_driver))
+ m_items_list.emplace_back(_("History"), UI_HISTORY_LOAD, datfile.rev_history());
+ if (datfile.has_mameinfo(m_driver))
+ m_items_list.emplace_back(_("Mameinfo"), UI_MAMEINFO_LOAD, datfile.rev_mameinfo());
+ if (datfile.has_messinfo(m_driver))
+ m_items_list.emplace_back(_("Messinfo"), UI_MESSINFO_LOAD, datfile.rev_messinfo());
+ if (datfile.has_sysinfo(m_driver))
+ m_items_list.emplace_back(_("Sysinfo"), UI_SYSINFO_LOAD, datfile.rev_sysinfo());
+ if (datfile.has_story(m_driver))
+ m_items_list.emplace_back(_("Mamescore"), UI_STORY_LOAD, datfile.rev_storyinfo());
+ if (datfile.has_gameinit(m_driver))
+ m_items_list.emplace_back(_("Gameinit"), UI_GINIT_LOAD, datfile.rev_ginitinfo());
+ if (datfile.has_command(m_driver))
+ m_items_list.emplace_back(_("Command"), UI_COMMAND_LOAD, "");
+}
diff --git a/src/frontend/mame/ui/datmenu.h b/src/frontend/mame/ui/datmenu.h
new file mode 100644
index 00000000000..10de3894816
--- /dev/null
+++ b/src/frontend/mame/ui/datmenu.h
@@ -0,0 +1,52 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/***************************************************************************
+
+ ui/datmenu.h
+
+ Internal UI user interface.
+
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_DATMENU_H__
+#define __UI_DATMENU_H__
+
+struct ui_software_info;
+
+//-------------------------------------------------
+// class dats menu
+//-------------------------------------------------
+
+class ui_menu_dats_view : public ui_menu
+{
+public:
+ ui_menu_dats_view(running_machine &machine, render_container *container, ui_software_info *swinfo, const game_driver *driver = nullptr);
+ ui_menu_dats_view(running_machine &machine, render_container *container, const game_driver *driver = nullptr);
+ virtual ~ui_menu_dats_view();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+private:
+ int m_actual;
+ const game_driver *m_driver;
+ ui_software_info *m_swinfo;
+ std::string m_list, m_short, m_long, m_parent;
+ void get_data();
+ void get_data_sw();
+ void init_items();
+ bool m_issoft;
+ struct list_items
+ {
+ list_items(std::string l, int i, std::string rev) { label = l; option = i; revision = rev; }
+ std::string label;
+ int option;
+ std::string revision;
+ };
+ std::vector<list_items> m_items_list;
+};
+
+#endif /* __UI_DATMENU_H__ */
diff --git a/src/frontend/mame/ui/defimg.h b/src/frontend/mame/ui/defimg.h
new file mode 100644
index 00000000000..bce018449d1
--- /dev/null
+++ b/src/frontend/mame/ui/defimg.h
@@ -0,0 +1,262 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+
+static const UINT32 no_avail_bmp[] =
+{
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00231f20, 0x00000000, 0x00000000, 0x00000000, 0x01231f20, 0x04231f20, 0x11231f20, 0x2e231f20, 0x62231f20, 0x8e231f20, 0xb4231f20, 0xd4231f20, 0xe5231f20, 0xf2231f20, 0xfd231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xfd231f20, 0xf2231f20, 0xe5231f20, 0xd4231f20, 0xb4231f20, 0x8e231f20, 0x62231f20, 0x2e231f20, 0x11231f20, 0x04231f20, 0x01231f20, 0x00000000, 0x00000000, 0x00000000, 0x00231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00231f20, 0x00231f20, 0x00000000, 0x00000000, 0x06231f20, 0x1c231f20, 0x49231f20, 0x8c231f20, 0xc4231f20, 0xf0231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xf0231f20, 0xc4231f20, 0x8c231f20, 0x49231f20, 0x1c231f20, 0x06231f20, 0x00000000, 0x00000000, 0x00231f20, 0x00231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00231f20, 0x00000000, 0x00000000, 0x04231f20, 0x32231f20, 0x7b231f20, 0xc2231f20, 0xf3231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xf3231f20, 0xc2231f20, 0x7b231f20, 0x32231f20, 0x04231f20, 0x00000000, 0x00000000, 0x00231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x30231f20, 0x8e231f20, 0xd6231f20, 0xfd231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xfd231f20, 0xd6231f20, 0x8e231f20, 0x30231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00231f20, 0x00000000, 0x0e231f20, 0x73231f20, 0xd8231f20, 0xfb231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xfb231f20, 0xd8231f20, 0x73231f20, 0x0e231f20, 0x00000000, 0x00231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00231f20, 0x00231f20, 0x00000000, 0x29231f20, 0xb6231f20, 0xfb231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xfb231f20, 0xb6231f20, 0x29231f20, 0x00000000, 0x00231f20, 0x00231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00231f20, 0x00000000, 0x00000000, 0x03231f20, 0x4f231f20, 0xdd231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xdd231f20, 0x4f231f20, 0x03231f20, 0x00000000, 0x00000000, 0x00231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00231f20, 0x00000000, 0x00000000, 0x0a231f20, 0x72231f20, 0xf4231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xf4231f20, 0x72231f20, 0x0a231f20, 0x00000000, 0x00000000, 0x00231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x10231f20, 0x84231f20, 0xf5231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1a1b, 0xff1e191a, 0xff1e1a1b, 0xff211c1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xf5231f20, 0x84231f20, 0x10231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00231f20, 0x00000000, 0x0a231f20, 0x84231f20, 0xf5231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff1c1718, 0xff1b1718, 0xff1b1718, 0xff1b1718, 0xff1d191a, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xff1b1718, 0xff1b1718, 0xff1c1819, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff393637, 0xff7c7a7a, 0xff827f80, 0xff7d7b7c, 0xff494647, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xf5231f20, 0x84231f20, 0x0a231f20, 0x00000000, 0x00231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00231f20, 0x03231f20, 0x74231f20, 0xf5231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff3b3839, 0xff585656, 0xff5a5757, 0xff5a5757, 0xff5b5858, 0xff4b4949, 0xff272325, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff464243, 0xff5a5858, 0xff5a5758, 0xff565253, 0xff312d2e, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1c1819, 0xff575355, 0xffececec, 0xfff7f7f7, 0xffededed, 0xff7a7878, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xf5231f20, 0x74231f20, 0x03231f20, 0x00231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00231f20, 0x00000000, 0x51231f20, 0xf4231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff807d7e, 0xfff1f1f1, 0xfff6f6f6, 0xfff6f6f6, 0xfff9f9f9, 0xffe1e0e0, 0xff565354, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xffa9a7a7, 0xfff6f6f6, 0xfff6f6f6, 0xffe6e6e6, 0xff575455, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff585556, 0xfff5f5f5, 0xffffffff, 0xfff5f5f5, 0xff7d7b7c, 0xff201d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xf4231f20, 0x51231f20, 0x00000000, 0x00231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x2a231f20, 0xde231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff848283, 0xfff7f7f7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffa6a4a5, 0xff2c2729, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xffafadad, 0xfffdfdfd, 0xffffffff, 0xffedecec, 0xff5a5758, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff595556, 0xfff6f6f6, 0xffffffff, 0xfff6f6f6, 0xff7e7c7c, 0xff201d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xde231f20, 0x2a231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00231f20, 0x00000000, 0x0e231f20, 0xb5231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231e1f, 0xff1e1b1c, 0xff848282, 0xfff6f6f6, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff0f0f0, 0xff585556, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xffafadad, 0xfffdfdfd, 0xffffffff, 0xffececec, 0xff595658, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1c1819, 0xff524f50, 0xffdbdbdb, 0xffe5e4e5, 0xffdcdbdb, 0xff737071, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xb5231f20, 0x0e231f20, 0x00000000, 0x00231f20, 0x00000000, 0x00000000,
+ 0x00000000, 0x00231f20, 0x00000000, 0x00000000, 0x73231f20, 0xfb231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1b1c, 0xff848282, 0xfff6f6f6, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffb4b3b4, 0xff282425, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xffafadad, 0xfffdfdfd, 0xffffffff, 0xffececec, 0xff595658, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff2e2b2c, 0xff4f4c4d, 0xff524f50, 0xff504d4e, 0xff363334, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xfb231f20, 0x73231f20, 0x00000000, 0x00000000, 0x00231f20, 0x00000000,
+ 0x00000000, 0x00231f20, 0x00000000, 0x30231f20, 0xd8231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1b1c, 0xff848282, 0xfff6f6f6, 0xffffffff, 0xfffdfdfd, 0xffededed, 0xfffdfdfd, 0xffffffff, 0xfff9fafa, 0xff646162, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xffafadad, 0xfffdfdfd, 0xffffffff, 0xffececec, 0xff595658, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1a1b, 0xff1e1a1b, 0xff1e1a1b, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xd8231f20, 0x30231f20, 0x00000000, 0x00231f20, 0x00000000,
+ 0x00231f20, 0x00000000, 0x05231f20, 0x8e231f20, 0xfa231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1b1c, 0xff848282, 0xfff6f6f6, 0xffffffff, 0xfff8f8f8, 0xffadacac, 0xffdbdbdb, 0xffffffff, 0xffffffff, 0xffc8c7c7, 0xff2b2628, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xffafadad, 0xfffdfdfd, 0xffffffff, 0xffececec, 0xff595658, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff1c1718, 0xff1a1617, 0xff1b1718, 0xff1b1718, 0xff1a1617, 0xff1d191a, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff1d191a, 0xff1a1617, 0xff1b1718, 0xff1a1617, 0xff1b1718, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff1c1819, 0xff1a1517, 0xff1b1718, 0xff1a1517, 0xff1c1719, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff1c1819, 0xff191516, 0xff1a1617, 0xff1a1617, 0xff191516, 0xff1b1718, 0xff1f1b1c, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff1c1819, 0xff1a1617, 0xff1b1718, 0xff1a1617, 0xff1a1617, 0xff1f1b1c, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff1d191a, 0xff1a1516, 0xff1a1617, 0xff1b1718, 0xff191516, 0xff1b1718, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xfa231f20, 0x8e231f20, 0x05231f20, 0x00000000, 0x00231f20,
+ 0x00000000, 0x00000000, 0x32231f20, 0xd8231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1b1c, 0xff848282, 0xfff6f6f6, 0xffffffff, 0xfff7f7f7, 0xff858384, 0xff949393, 0xfffdfefd, 0xffffffff, 0xfffdfdfd, 0xff767475, 0xff1c1718, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xffafadad, 0xfffdfdfd, 0xffffffff, 0xffececec, 0xff595658, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff252122, 0xff413e3f, 0xff6e6c6c, 0xff8f8d8d, 0xff9c9b9b, 0xff9b9999, 0xff898787, 0xff646061, 0xff383435, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff292526, 0xff393637, 0xff3b3839, 0xff3a3738, 0xff2c292a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231e1f, 0xff2f2b2c, 0xff3a3738, 0xff3b3839, 0xff393536, 0xff282425, 0xff221e1f, 0xff201c1d, 0xff302d2e, 0xff5f5c5d, 0xff8a8788, 0xff9b9a9a, 0xff989797, 0xff7c7a7a, 0xff454243, 0xff231f20, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xff373334, 0xff666465, 0xff8e8c8c, 0xff9b999a, 0xff918f8f, 0xff716f6f, 0xff3b3839, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff231f20, 0xff302c2d, 0xff4e4a4b, 0xff706e6f, 0xff8b898a, 0xff999797, 0xff999797, 0xff8e8c8d, 0xff767374, 0xff494646, 0xff2b2728, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff201c1d, 0xff332f30, 0xff636061, 0xff8d8b8b, 0xff9c9a9b, 0xff989697, 0xff807f7f, 0xff524f4f, 0xff2a2627, 0xff211d1e, 0xff221e1f, 0xff2e2a2b, 0xff3b3738, 0xff3b3839, 0xff383536, 0xff292526, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff231f20, 0xff393636, 0xff646162, 0xff878485, 0xff989697, 0xff9d9b9b, 0xff908e8e, 0xff716e6e, 0xff423f3f, 0xff252122, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xd8231f20, 0x32231f20, 0x00000000, 0x00000000,
+ 0x00000000, 0x06231f20, 0x7c231f20, 0xfc231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1b1c, 0xff848282, 0xfff6f6f6, 0xffffffff, 0xfff8f8f8, 0xff7b797a, 0xff4a4647, 0xffdedede, 0xffffffff, 0xffffffff, 0xffd1d0d1, 0xff363233, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xffafadad, 0xfffdfdfd, 0xffffffff, 0xffececec, 0xff595658, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff252122, 0xff504e4f, 0xffaaa9a9, 0xffececed, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe1e0e1, 0xff949293, 0xff403c3d, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1c1718, 0xff555253, 0xffe9e9e9, 0xfff4f4f4, 0xffebebeb, 0xff787676, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff8b898a, 0xffeff0f0, 0xfff3f3f3, 0xffdddddd, 0xff4c4a4a, 0xff242021, 0xff716f6f, 0xffd4d2d3, 0xfffefefe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff0f0f0, 0xff9c9b9c, 0xff393536, 0xff201c1d, 0xff231f20, 0xff211d1e, 0xff322f30, 0xff848282, 0xffe0dede, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff838182, 0xff2f2b2c, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff2b2728, 0xff605d5e, 0xffa2a1a1, 0xffd8d7d7, 0xfff7f7f7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff6f5f5, 0xffc4c3c3, 0xff6c696a, 0xff2d292a, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff2f2b2c, 0xff7c797a, 0xffd9d8d8, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff8f7f7, 0xffbdbcbc, 0xff5a5757, 0xff1f1a1b, 0xff817e7f, 0xfff2f1f1, 0xfff3f2f2, 0xffdedede, 0xff524e4f, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff242021, 0xff474344, 0xff9a9899, 0xffe3e2e2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffeeedee, 0xffaaa9a9, 0xff4e4b4b, 0xff231f20, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xfc231f20, 0x7c231f20, 0x06231f20, 0x00000000,
+ 0x00000000, 0x1c231f20, 0xc3231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1b1c, 0xff848282, 0xfff6f6f6, 0xffffffff, 0xfff8f8f8, 0xff7e7c7d, 0xff1d181a, 0xff9a9898, 0xfffbfbfb, 0xffffffff, 0xfff9f9f9, 0xff848182, 0xff1f1b1c, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xffafadad, 0xfffdfdfd, 0xffffffff, 0xffececec, 0xff595658, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff272324, 0xff7d7a7b, 0xffe9e9e9, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffcfcfc, 0xfffdfcfc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffd4d3d4, 0xff605d5e, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff595656, 0xfff7f7f7, 0xffffffff, 0xfff7f7f7, 0xff7e7c7d, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff939191, 0xfffbfbfb, 0xffffffff, 0xffeae9e9, 0xff5d5a5b, 0xff8c8a8a, 0xfff8f7f7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffbab9b9, 0xff3b3738, 0xff1b1718, 0xff3c3939, 0xffb3b2b2, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffefe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffdfdfd, 0xff959293, 0xff2b2728, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff484445, 0xffe6e6e6, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffdfefe, 0xfffafafa, 0xfffcfbfb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff8f8f8, 0xff9d9b9b, 0xff343031, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff383435, 0xffa7a6a6, 0xfffefdfd, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffdfdfd, 0xfff8f8f8, 0xfffcfcfc, 0xffffffff, 0xffffffff, 0xffe7e7e7, 0xff696767, 0xff8b8989, 0xfffcfcfc, 0xffffffff, 0xffeaeaea, 0xff555253, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff262222, 0xff727071, 0xffdedede, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffcfcfc, 0xfffbfbfb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe5e4e4, 0xff757273, 0xff252122, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xc3231f20, 0x1c231f20, 0x00000000,
+ 0x01231f20, 0x49231f20, 0xf4231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1b1c, 0xff848282, 0xfff6f6f6, 0xffffffff, 0xfff8f8f8, 0xff807d7e, 0xff161213, 0xff474444, 0xffdfdedf, 0xffffffff, 0xffffffff, 0xffd1d0d0, 0xff413d3e, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xffafadad, 0xfffdfdfd, 0xffffffff, 0xffececec, 0xff595658, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff211d1e, 0xff828080, 0xfff4f3f3, 0xffffffff, 0xffffffff, 0xfffcfcfc, 0xffcecdcd, 0xff9c9a9a, 0xff868585, 0xff8a8787, 0xffa6a4a4, 0xffdddcdc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe0dfe0, 0xff5f5c5d, 0xff1f1b1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff585556, 0xfff5f5f5, 0xffffffff, 0xfff5f5f5, 0xff7d7b7c, 0xff201d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff929090, 0xfffafafa, 0xffffffff, 0xffececec, 0xffadabac, 0xfff2f2f2, 0xffffffff, 0xffd3d2d2, 0xffa6a4a5, 0xff908e8f, 0xff929191, 0xffb4b3b3, 0xffeeeeee, 0xffffffff, 0xffffffff, 0xfffdfdfd, 0xff959394, 0xff363333, 0xffb0afb0, 0xffffffff, 0xfffafafa, 0xffc9c8c9, 0xffa09e9f, 0xff8f8c8d, 0xff969494, 0xffbdbcbc, 0xfff6f5f6, 0xffffffff, 0xffffffff, 0xfff7f7f7, 0xff686667, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff4b4949, 0xffefeeef, 0xffffffff, 0xffdddddd, 0xffbab9ba, 0xff9e9c9d, 0xff8b898a, 0xff848182, 0xff868484, 0xff999797, 0xffbebdbe, 0xfff0f0ef, 0xffffffff, 0xffffffff, 0xffffffff, 0xff949293, 0xff262223, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff2e2a2b, 0xff9f9d9e, 0xfffdfdfd, 0xffffffff, 0xffffffff, 0xfff1f1f1, 0xffb7b5b6, 0xff8d8b8c, 0xff7f7c7d, 0xff878586, 0xffaaa8a9, 0xffe2e1e2, 0xffffffff, 0xffdbdbdb, 0xffbcbbbb, 0xfffcfcfc, 0xffffffff, 0xffe9e8e8, 0xff555252, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff221e1f, 0xff807e7e, 0xfff0f0f0, 0xffffffff, 0xffffffff, 0xfff7f7f7, 0xffcac9c9, 0xff9e9c9c, 0xff888686, 0xff858282, 0xff959393, 0xffc0bfbf, 0xfff5f5f5, 0xffffffff, 0xffffffff, 0xffecebeb, 0xff726f70, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xf4231f20, 0x49231f20, 0x01231f20,
+ 0x04231f20, 0x8c231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1b1c, 0xff848282, 0xfff6f6f6, 0xffffffff, 0xfff8f8f8, 0xff807d7e, 0xff1b1718, 0xff1e191a, 0xff8f8d8e, 0xffffffff, 0xffffffff, 0xfff9f9f9, 0xff888687, 0xff242021, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xffafadad, 0xfffdfdfd, 0xffffffff, 0xffececec, 0xff595658, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d1a1b, 0xff5c5959, 0xffe6e5e5, 0xffffffff, 0xffffffff, 0xfff6f5f6, 0xff979495, 0xff3f3c3c, 0xff272424, 0xff221f20, 0xff221e1f, 0xff2b2728, 0xff4d494a, 0xffb6b5b5, 0xffffffff, 0xffffffff, 0xffffffff, 0xffc9c8c8, 0xff3f3b3c, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff585556, 0xfff5f5f5, 0xffffffff, 0xfff5f5f5, 0xff7d7b7c, 0xff201d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff929090, 0xfffafafa, 0xffffffff, 0xfffcfcfc, 0xfff9f9f9, 0xfff4f4f4, 0xff918e8f, 0xff413e3f, 0xff2b2728, 0xff242021, 0xff242021, 0xff2d2a2a, 0xff6c6a6a, 0xffeae9e9, 0xffffffff, 0xffffffff, 0xffdcdcdc, 0xffb1afb0, 0xfff7f7f7, 0xffececec, 0xff7b797a, 0xff393536, 0xff292526, 0xff231f20, 0xff262223, 0xff343031, 0xff7f7d7d, 0xfff4f4f4, 0xffffffff, 0xffffffff, 0xffc1c0c0, 0xff292526, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff454243, 0xffb1afb0, 0xff7e7b7c, 0xff494647, 0xff332f30, 0xff292526, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff272224, 0xff343031, 0xff656263, 0xffd1d0d0, 0xffffffff, 0xffffffff, 0xfff2f2f2, 0xff545152, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff6c6a6b, 0xfff1f1f1, 0xffffffff, 0xffffffff, 0xffe4e3e4, 0xff6b6869, 0xff302c2d, 0xff241f20, 0xff221e1f, 0xff221e1f, 0xff2c2829, 0xff565253, 0xffc2c2c2, 0xffffffff, 0xfff8f8f8, 0xffffffff, 0xffffffff, 0xffe9e8e8, 0xff555252, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191b, 0xff666264, 0xffe9e8e9, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff7b7879, 0xff3b3738, 0xff282425, 0xff221e1f, 0xff221e1f, 0xff252122, 0xff353132, 0xff777575, 0xffe9e9e9, 0xffffffff, 0xffffffff, 0xffd5d4d4, 0xff4a4647, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0x8c231f20, 0x04231f20,
+ 0x11231f20, 0xc4231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1b1c, 0xff848282, 0xfff6f6f6, 0xffffffff, 0xfff8f8f8, 0xff7f7d7e, 0xff1c1819, 0xff1f1b1c, 0xff383535, 0xffdcdbdb, 0xffffffff, 0xffffffff, 0xffd3d3d3, 0xff434041, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xffafadad, 0xfffdfdfd, 0xffffffff, 0xffececec, 0xff595658, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff2c2829, 0xffb0afaf, 0xfffefefe, 0xffffffff, 0xfffcfcfc, 0xff9e9d9d, 0xff282525, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff383435, 0xffc7c7c7, 0xffffffff, 0xffffffff, 0xfff8f8f8, 0xff848383, 0xff242021, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff585556, 0xfff5f5f5, 0xffffffff, 0xfff5f5f5, 0xff7d7b7c, 0xff201d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff929090, 0xfffafafa, 0xffffffff, 0xffffffff, 0xfffaf9f9, 0xff918f8f, 0xff2a2627, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1a1b, 0xff8a8889, 0xffffffff, 0xffffffff, 0xfffdfdfd, 0xfffdfdfd, 0xfff6f7f7, 0xff6b6969, 0xff211d1e, 0xff221d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff2a2727, 0xffa3a1a1, 0xffffffff, 0xffffffff, 0xfff6f6f6, 0xff4d4a4b, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff282425, 0xff302c2d, 0xff242021, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231e1f, 0xff221e1f, 0xff221e1f, 0xff524f4f, 0xffdddddd, 0xffffffff, 0xffffffff, 0xffa5a4a4, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff312d2e, 0xffbfbebe, 0xffffffff, 0xffffffff, 0xfff5f4f5, 0xff625f60, 0xff1f1b1c, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff211d1e, 0xff4b4849, 0xffd5d4d4, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe9e8e8, 0xff555252, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff363333, 0xffc1c1c1, 0xffffffff, 0xffffffff, 0xffededed, 0xff666464, 0xff211d1e, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff1f1b1c, 0xff706e6e, 0xfff9f9f9, 0xffffffff, 0xfffdfdfd, 0xff908e8f, 0xff272223, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xc4231f20, 0x11231f20,
+ 0x2e231f20, 0xf0231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1b1c, 0xff848282, 0xfff6f6f6, 0xffffffff, 0xfff8f8f8, 0xff7f7d7e, 0xff1c1819, 0xff231f20, 0xff1c1819, 0xff7d7b7b, 0xffffffff, 0xffffffff, 0xffffffff, 0xff8a8788, 0xff252122, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xffafadad, 0xfffdfdfd, 0xffffffff, 0xffececec, 0xff595658, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff535051, 0xffe2e1e1, 0xffffffff, 0xffffffff, 0xffd9d9d9, 0xff393636, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff5b5859, 0xfff5f5f5, 0xffffffff, 0xffffffff, 0xffc4c3c3, 0xff383435, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff585556, 0xfff5f5f5, 0xffffffff, 0xfff5f5f5, 0xff7d7b7c, 0xff201d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff929090, 0xfffafafa, 0xffffffff, 0xffffffff, 0xffcbcacb, 0xff3b3839, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff3f3b3c, 0xffeeedee, 0xffffffff, 0xffffffff, 0xffffffff, 0xffa6a5a5, 0xff242021, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221f1f, 0xff615e5e, 0xfff2f2f2, 0xffffffff, 0xffffffff, 0xff797677, 0xff1b1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff262223, 0xff939191, 0xffffffff, 0xffffffff, 0xffdedede, 0xff2f2b2c, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff575354, 0xfff5f5f5, 0xffffffff, 0xffffffff, 0xffa1a09f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201d1e, 0xff817f81, 0xfff5f5f5, 0xffffffff, 0xffffffff, 0xffe9e8e8, 0xff555252, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211c1e, 0xff6c696a, 0xffefefef, 0xffffffff, 0xffffffff, 0xff989797, 0xff1d191a, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff211d1e, 0xffb1b0b0, 0xffffffff, 0xffffffff, 0xffcccbcb, 0xff3b3738, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xf0231f20, 0x2e231f20,
+ 0x62231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1b1c, 0xff848282, 0xfff6f6f6, 0xffffffff, 0xfff8f8f8, 0xff7f7d7e, 0xff1c1819, 0xff231f20, 0xff211d1e, 0xff2f2c2d, 0xffcdcdcd, 0xffffffff, 0xffffffff, 0xffdddddd, 0xff423f40, 0xff211d1e, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xffafadad, 0xfffdfdfd, 0xffffffff, 0xffececec, 0xff595658, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff7d7b7b, 0xfff9f9f9, 0xffffffff, 0xffffffff, 0xff8f8e8e, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xffbdbcbd, 0xffffffff, 0xffffffff, 0xffeaeaea, 0xff565353, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff585556, 0xfff5f5f5, 0xffffffff, 0xfff5f5f5, 0xff7d7b7c, 0xff201d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff929090, 0xfffafafa, 0xffffffff, 0xfff9f9f9, 0xff918f90, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff282425, 0xffcdcccc, 0xffffffff, 0xffffffff, 0xfff7f7f7, 0xff5d5b5b, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff474444, 0xffdad9d9, 0xffffffff, 0xffffffff, 0xff999898, 0xff1b1618, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff1f1b1c, 0xff696768, 0xfff0f0ef, 0xffffffff, 0xfff5f5f5, 0xff4c494a, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff8a8989, 0xffffffff, 0xffffffff, 0xfff7f7f7, 0xff565354, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xff454242, 0xffdedede, 0xffffffff, 0xffffffff, 0xffe9e8e8, 0xff555252, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff2a2627, 0xffa19fa0, 0xffffffff, 0xffffffff, 0xffeeeded, 0xff444040, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1c1819, 0xff626060, 0xffffffff, 0xffffffff, 0xffeeeeee, 0xff575354, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0x62231f20,
+ 0x8e231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1b1c, 0xff848282, 0xfff6f6f6, 0xffffffff, 0xfff8f8f8, 0xff7f7d7e, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff6e6b6b, 0xfffbfbfb, 0xffffffff, 0xffffffff, 0xff959394, 0xff211d1e, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xffafadad, 0xfffdfdfd, 0xffffffff, 0xffececec, 0xff595658, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff2a2627, 0xffa09f9f, 0xffffffff, 0xffffffff, 0xfff8f8f8, 0xff535051, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1a1617, 0xff7e7b7c, 0xffffffff, 0xffffffff, 0xfffefefe, 0xff737172, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff585556, 0xfff5f5f5, 0xffffffff, 0xfff5f5f5, 0xff7d7b7c, 0xff201d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff929090, 0xfffafafa, 0xffffffff, 0xfff2f2f1, 0xff686666, 0xff1c1719, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff231f20, 0xffb7b5b5, 0xffffffff, 0xffffffff, 0xffdbdbdb, 0xff423f3f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff3b3738, 0xffcecdcd, 0xffffffff, 0xffffffff, 0xffa7a6a6, 0xff1e1a1b, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff1f1b1c, 0xff2c2729, 0xff3b3839, 0xff4c4849, 0xff575455, 0xff5c595a, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5d5a5b, 0xff8b898a, 0xffefefef, 0xffffffff, 0xfffbfbfb, 0xff646162, 0xff1b1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xffb2b1b2, 0xffffffff, 0xffffffff, 0xffd5d4d4, 0xff373435, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff272324, 0xffbebdbd, 0xfffefefe, 0xffffffff, 0xffe9e8e8, 0xff555252, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff383435, 0xffc7c7c7, 0xffffffff, 0xffffffff, 0xffc3c2c2, 0xff201c1d, 0xff1d191a, 0xff1f1b1c, 0xff1e1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1c1819, 0xff3a3738, 0xffeeeeee, 0xffffffff, 0xffffffff, 0xff706e6e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0x8e231f20,
+ 0xb4231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1b1c, 0xff848282, 0xfff6f6f6, 0xffffffff, 0xfff8f8f8, 0xff7f7d7e, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff312e2e, 0xffbcbbbb, 0xffffffff, 0xffffffff, 0xffebebeb, 0xff4a4748, 0xff1e1a1b, 0xff221e1f, 0xff221e1f, 0xffafadad, 0xfffdfdfd, 0xffffffff, 0xffececec, 0xff595658, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff302d2e, 0xffb9b8b9, 0xffffffff, 0xffffffff, 0xffe6e6e6, 0xff343031, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xff565254, 0xfffbfbfb, 0xffffffff, 0xffffffff, 0xff8f8c8d, 0xff252122, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff585556, 0xfff5f5f5, 0xffffffff, 0xfff5f5f5, 0xff7d7b7c, 0xff201d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff929090, 0xfffafafa, 0xffffffff, 0xffededed, 0xff575454, 0xff1b1718, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201d1e, 0xffafadae, 0xffffffff, 0xffffffff, 0xffcac9ca, 0xff373334, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff383535, 0xffc9c8c8, 0xffffffff, 0xffffffff, 0xffafadae, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1a1b, 0xff393536, 0xff777475, 0xffacaaaa, 0xffcccacb, 0xffdddddc, 0xffe5e5e5, 0xffe9e9e9, 0xffebebeb, 0xffebebeb, 0xffebebeb, 0xffebeaeb, 0xfff0f0f0, 0xfffdfdfd, 0xffffffff, 0xffffffff, 0xff706d6e, 0xff191516, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff2c292a, 0xffcccbcc, 0xffffffff, 0xffffffff, 0xffbab9b9, 0xff2b2829, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xffa2a0a0, 0xfffcfcfc, 0xffffffff, 0xffe9e8e8, 0xff555252, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff484445, 0xffdcdcdc, 0xffffffff, 0xffffffff, 0xffc8c7c8, 0xff716f6f, 0xff747172, 0xff747273, 0xff747273, 0xff757273, 0xff757273, 0xff757273, 0xff767373, 0xff757374, 0xff767374, 0xff757273, 0xff828081, 0xffeeedee, 0xffffffff, 0xffffffff, 0xff858283, 0xff242021, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xb4231f20,
+ 0xd4231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1b1c, 0xff848282, 0xfff6f6f6, 0xffffffff, 0xfff8f8f8, 0xff7f7d7e, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff686566, 0xfff1f1f1, 0xffffffff, 0xffffffff, 0xffabaaaa, 0xff211c1d, 0xff211d1e, 0xff221e1f, 0xffafadad, 0xfffdfdfd, 0xffffffff, 0xffececec, 0xff595658, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff343031, 0xffc6c5c5, 0xffffffff, 0xffffffff, 0xffd4d4d4, 0xff2a2627, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff413e3f, 0xfff6f6f5, 0xffffffff, 0xffffffff, 0xff9f9e9e, 0xff272223, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff585556, 0xfff5f5f5, 0xffffffff, 0xfff5f5f5, 0xff7d7b7c, 0xff201d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff929090, 0xfffafafa, 0xffffffff, 0xffe9e9e9, 0xff524e4f, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xffadabac, 0xffffffff, 0xffffffff, 0xffc4c3c4, 0xff322f30, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff373435, 0xffc8c7c7, 0xffffffff, 0xffffffff, 0xffb0aeaf, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff5d5a5b, 0xffc8c7c8, 0xfff3f3f3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff777475, 0xff181415, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff322e2f, 0xffdbdada, 0xffffffff, 0xffffffff, 0xffaeacac, 0xff282425, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1d191a, 0xff908e8f, 0xfffbfbfb, 0xffffffff, 0xffe9e8e8, 0xff555252, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff545151, 0xffe9e9e9, 0xffffffff, 0xffffffff, 0xfff9f9f9, 0xfff1f1f1, 0xfff2f1f2, 0xfff2f1f2, 0xfff2f1f2, 0xfff2f2f2, 0xfff2f2f2, 0xfff2f2f2, 0xfff2f2f2, 0xfff2f2f2, 0xfff2f2f2, 0xfff2f2f2, 0xfff3f3f3, 0xfffdfdfd, 0xffffffff, 0xffffffff, 0xff8d8c8c, 0xff242021, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xd4231f20,
+ 0xe5231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1b1c, 0xff848282, 0xfff6f6f6, 0xffffffff, 0xfff8f8f8, 0xff7f7d7e, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff322e2f, 0xffb6b5b5, 0xffffffff, 0xffffffff, 0xfff3f3f3, 0xff5a5858, 0xff1a1617, 0xff221f1f, 0xffafadad, 0xfffdfdfd, 0xffffffff, 0xffececec, 0xff595658, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff373434, 0xffcac9c9, 0xffffffff, 0xffffffff, 0xffcbcacb, 0xff282425, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff3b3738, 0xfff2f1f2, 0xffffffff, 0xffffffff, 0xffa5a4a4, 0xff262223, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff585556, 0xfff5f5f5, 0xffffffff, 0xfff5f5f5, 0xff7d7b7c, 0xff201d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff929090, 0xfffafafa, 0xffffffff, 0xffe9e9e9, 0xff514d4f, 0xff1d1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xffadacad, 0xffffffff, 0xffffffff, 0xffc4c3c3, 0xff322e30, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff373435, 0xffc8c7c7, 0xffffffff, 0xffffffff, 0xffb0aeaf, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff565454, 0xffe2e1e1, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff3f3f3, 0xffd1d0d0, 0xffb3b1b1, 0xffa19f9f, 0xff989696, 0xff939191, 0xff929091, 0xff918f90, 0xffafaeaf, 0xfff4f4f4, 0xffffffff, 0xffffffff, 0xff777475, 0xff181415, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff322f30, 0xffdfdede, 0xffffffff, 0xffffffff, 0xffa9a7a8, 0xff282425, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1c1819, 0xff8b8989, 0xfffbfbfb, 0xffffffff, 0xffe9e8e8, 0xff555252, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff595758, 0xfff0efef, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff929091, 0xff242021, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xe5231f20,
+ 0xf2231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1b1c, 0xff848282, 0xfff6f6f6, 0xffffffff, 0xfff8f8f8, 0xff7f7d7e, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff676566, 0xffececec, 0xffffffff, 0xffffffff, 0xffb9b8b8, 0xff262223, 0xff201c1c, 0xffafadad, 0xfffdfdfd, 0xffffffff, 0xffececec, 0xff595658, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff353233, 0xffc7c6c7, 0xffffffff, 0xffffffff, 0xffd2d1d1, 0xff2a2627, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff3f3b3c, 0xfff5f5f5, 0xffffffff, 0xffffffff, 0xffa2a0a1, 0xff262223, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff585556, 0xfff5f5f5, 0xffffffff, 0xfff5f5f5, 0xff7d7b7c, 0xff201d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff929090, 0xfffafafa, 0xffffffff, 0xffe9e9e9, 0xff514d4f, 0xff1d1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xffadacad, 0xffffffff, 0xffffffff, 0xffc4c3c3, 0xff322e30, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff373435, 0xffc8c7c7, 0xffffffff, 0xffffffff, 0xffb0aeaf, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff2e2a2b, 0xffc2c1c1, 0xffffffff, 0xffffffff, 0xfff5f4f4, 0xff9b9a9a, 0xff464344, 0xff2a2627, 0xff221e1f, 0xff1d191a, 0xff1c1819, 0xff1c1819, 0xff1c1819, 0xff1a1516, 0xff5c595a, 0xffe9e8e9, 0xffffffff, 0xffffffff, 0xff777475, 0xff181415, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff302c2d, 0xffd7d7d7, 0xffffffff, 0xffffffff, 0xffb1b0b0, 0xff292526, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e191a, 0xff959393, 0xfffcfcfc, 0xffffffff, 0xffe9e8e8, 0xff555252, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff585556, 0xffeeedee, 0xffffffff, 0xffffffff, 0xffc1c0c0, 0xff848282, 0xff898788, 0xff898788, 0xff898788, 0xff898788, 0xff898788, 0xff898788, 0xff898788, 0xff898788, 0xff898788, 0xff898788, 0xff898788, 0xff898788, 0xff898788, 0xff8b898a, 0xff565253, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xf2231f20,
+ 0xfd231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1b1c, 0xff848282, 0xfff6f6f6, 0xffffffff, 0xfff8f8f8, 0xff7f7d7e, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff2c2829, 0xffb6b5b5, 0xfffefefe, 0xffffffff, 0xfff1f1f1, 0xff666364, 0xff1c1819, 0xffafadad, 0xfffdfdfd, 0xffffffff, 0xffececec, 0xff595658, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff312e2f, 0xffbdbcbd, 0xffffffff, 0xffffffff, 0xffe1e0e1, 0xff302c2d, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xff4f4b4c, 0xfffaf9f9, 0xffffffff, 0xffffffff, 0xff949292, 0xff262223, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff585556, 0xfff5f5f5, 0xffffffff, 0xfff5f5f5, 0xff7d7b7c, 0xff201d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff929090, 0xfffafafa, 0xffffffff, 0xffe9e9e9, 0xff514d4f, 0xff1d1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xffadacad, 0xffffffff, 0xffffffff, 0xffc4c3c3, 0xff322e30, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff373435, 0xffc8c7c7, 0xffffffff, 0xffffffff, 0xffb0aeaf, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xff5d5a5b, 0xfffffefe, 0xffffffff, 0xfffefefe, 0xff8c898a, 0xff201c1d, 0xff1d191a, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff6a6768, 0xffefefef, 0xffffffff, 0xffffffff, 0xff777475, 0xff181415, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff2a2627, 0xffc6c5c5, 0xffffffff, 0xffffffff, 0xffc1c0c0, 0xff2e2a2b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff201c1d, 0xffa9a8a8, 0xfffdfdfd, 0xffffffff, 0xffe9e8e8, 0xff555252, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff4f4c4d, 0xffe4e4e4, 0xffffffff, 0xffffffff, 0xff999797, 0xff100c0d, 0xff181415, 0xff181415, 0xff181415, 0xff181415, 0xff181415, 0xff181415, 0xff181415, 0xff181415, 0xff181415, 0xff181415, 0xff181415, 0xff181415, 0xff181415, 0xff171314, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xfd231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1b1c, 0xff848282, 0xfff6f6f6, 0xffffffff, 0xfff8f8f8, 0xff7f7d7e, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1c1819, 0xff5f5d5d, 0xffeeeeee, 0xffffffff, 0xfffefefe, 0xffb9b7b8, 0xff302d2e, 0xffacabab, 0xfffdfdfd, 0xffffffff, 0xffececec, 0xff595658, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff2c2829, 0xffa8a6a6, 0xffffffff, 0xffffffff, 0xfff4f4f4, 0xff494647, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff726f70, 0xffffffff, 0xffffffff, 0xffffffff, 0xff7a7878, 0xff241f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff585556, 0xfff5f5f5, 0xffffffff, 0xfff5f5f5, 0xff7d7b7c, 0xff201d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff929090, 0xfffafafa, 0xffffffff, 0xffe9e9e9, 0xff514d4f, 0xff1d1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xffadacad, 0xffffffff, 0xffffffff, 0xffc4c3c3, 0xff322e30, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff373435, 0xffc8c7c7, 0xffffffff, 0xffffffff, 0xffb0aeaf, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff908e8e, 0xffffffff, 0xffffffff, 0xffdcdbdb, 0xff434041, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff7f7c7d, 0xfff9f9f9, 0xffffffff, 0xffffffff, 0xff777475, 0xff181415, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xffa8a6a7, 0xffffffff, 0xffffffff, 0xffe0dfdf, 0xff3f3b3c, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff2d2a2b, 0xffc8c8c8, 0xfffefefe, 0xffffffff, 0xffe9e8e8, 0xff555252, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff3f3c3d, 0xffd3d2d2, 0xffffffff, 0xffffffff, 0xffc7c5c6, 0xff262223, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1b1c, 0xff848282, 0xfff6f6f6, 0xffffffff, 0xfff8f8f8, 0xff7f7d7e, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242021, 0xffaeacad, 0xffffffff, 0xffffffff, 0xffeeeeee, 0xff6c6a6a, 0xffadabab, 0xfffdfdfd, 0xffffffff, 0xffececec, 0xff595658, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff242121, 0xff868484, 0xfffcfcfc, 0xffffffff, 0xffffffff, 0xff7e7b7c, 0xff191516, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1a1b, 0xffacaaab, 0xffffffff, 0xffffffff, 0xfff0f0f0, 0xff5d595a, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff585556, 0xfff5f5f5, 0xffffffff, 0xfff5f5f5, 0xff7d7b7c, 0xff201d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff929090, 0xfffafafa, 0xffffffff, 0xffe9e9e9, 0xff514d4f, 0xff1d1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xffadacad, 0xffffffff, 0xffffffff, 0xffc4c3c3, 0xff322e30, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff373435, 0xffc8c7c7, 0xffffffff, 0xffffffff, 0xffb0aeaf, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xffa7a5a6, 0xffffffff, 0xffffffff, 0xffc6c5c5, 0xff343132, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff2b2829, 0xffa9a8a8, 0xffffffff, 0xffffffff, 0xffffffff, 0xff777475, 0xff181415, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff7b7878, 0xffffffff, 0xffffffff, 0xfffefefe, 0xff696667, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff555153, 0xffe6e5e5, 0xffffffff, 0xffffffff, 0xffe9e8e8, 0xff555252, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff2f2b2c, 0xffb2b1b1, 0xffffffff, 0xffffffff, 0xfff1f1f1, 0xff4a4748, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1b1c, 0xff848282, 0xfff6f6f6, 0xffffffff, 0xfff8f8f8, 0xff7f7d7e, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff4e4a4b, 0xffefeeee, 0xffffffff, 0xffffffff, 0xffbcbbbb, 0xffc1c0c1, 0xfffcfcfc, 0xffffffff, 0xffececec, 0xff595658, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff5d5a5b, 0xffe9e8e9, 0xffffffff, 0xffffffff, 0xffc7c6c6, 0xff2b2627, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1c1819, 0xff464243, 0xffebebeb, 0xffffffff, 0xffffffff, 0xffcfcece, 0xff3e3a3b, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff585556, 0xfff5f5f5, 0xffffffff, 0xfff5f5f5, 0xff7d7b7c, 0xff201d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff929090, 0xfffafafa, 0xffffffff, 0xffe9e9e9, 0xff514d4f, 0xff1d1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xffadacad, 0xffffffff, 0xffffffff, 0xffc4c3c3, 0xff322e30, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff373435, 0xffc8c7c7, 0xffffffff, 0xffffffff, 0xffb0aeaf, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xffa8a6a6, 0xffffffff, 0xffffffff, 0xffcbcaca, 0xff383435, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff4e4b4b, 0xffe3e2e2, 0xffffffff, 0xffffffff, 0xffffffff, 0xff777475, 0xff181415, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff484546, 0xffe8e8e8, 0xffffffff, 0xffffffff, 0xffc3c2c2, 0xff292627, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff262223, 0xff9e9c9c, 0xfffbfbfb, 0xffffffff, 0xffffffff, 0xffe9e8e8, 0xff555252, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff7f7c7d, 0xfff8f7f8, 0xffffffff, 0xffffffff, 0xffa3a1a1, 0xff1e1a1c, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1b1c, 0xff848282, 0xfff6f6f6, 0xffffffff, 0xfff8f8f8, 0xff7f7d7e, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff9c9a9a, 0xffffffff, 0xffffffff, 0xfff5f5f5, 0xfff0f0f0, 0xfffefefe, 0xffffffff, 0xffececec, 0xff595658, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff343031, 0xffbfbebe, 0xffffffff, 0xffffffff, 0xfff8f8f8, 0xff807e7f, 0xff1d191a, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff262223, 0xffafadae, 0xffffffff, 0xffffffff, 0xfffdfdfd, 0xff949293, 0xff272324, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff585556, 0xfff5f5f5, 0xffffffff, 0xfff5f5f5, 0xff7d7b7c, 0xff201d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff929090, 0xfffafafa, 0xffffffff, 0xffe9e9e9, 0xff514d4f, 0xff1d1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xffadacad, 0xffffffff, 0xffffffff, 0xffc4c3c3, 0xff322e30, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff373435, 0xffc8c7c7, 0xffffffff, 0xffffffff, 0xffb0aeaf, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff949192, 0xffffffff, 0xffffffff, 0xffecebec, 0xff565354, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff2c2829, 0xffb1afaf, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff777475, 0xff181415, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff2a2627, 0xffa6a4a5, 0xffffffff, 0xffffffff, 0xffffffff, 0xff939192, 0xff201c1d, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff211d1e, 0xff6c6a6a, 0xffebebeb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe9e8e8, 0xff555252, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff444041, 0xffd5d4d4, 0xffffffff, 0xffffffff, 0xfff0f0f0, 0xff716e6f, 0xff1d191a, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff221e1f, 0xff2d292a, 0xff252122, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1b1c, 0xff848282, 0xfff6f6f6, 0xffffffff, 0xfff8f8f8, 0xff7f7d7e, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff403d3e, 0xffe4e4e4, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffececec, 0xff595658, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xff706d6e, 0xfff0eff0, 0xffffffff, 0xffffffff, 0xffe9e9e9, 0xff706e6f, 0xff282425, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff302c2d, 0xff969494, 0xfffafaf9, 0xffffffff, 0xffffffff, 0xffdad9d9, 0xff4d494a, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff585556, 0xfff5f5f5, 0xffffffff, 0xfff5f5f5, 0xff7d7b7c, 0xff201d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff929090, 0xfffafafa, 0xffffffff, 0xffe9e9e9, 0xff514d4f, 0xff1d1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xffadacad, 0xffffffff, 0xffffffff, 0xffc4c3c3, 0xff322e30, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff373435, 0xffc8c7c7, 0xffffffff, 0xffffffff, 0xffb0aeaf, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xfffdfcfc, 0xffffffff, 0xffffffff, 0xffbbb9b9, 0xff3a3738, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff373334, 0xffa5a3a3, 0xffffffff, 0xfffefefe, 0xfffefefe, 0xffffffff, 0xffffffff, 0xff777475, 0xff181415, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff534f50, 0xffe0dfe0, 0xffffffff, 0xffffffff, 0xfffbfbfb, 0xffa2a0a1, 0xff433f40, 0xff2a2627, 0xff252122, 0xff282425, 0xff3a3738, 0xff807d7e, 0xffeaeaea, 0xfffefefe, 0xffeeeded, 0xfffefefe, 0xffffffff, 0xffe9e8e8, 0xff555252, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff201b1c, 0xff7e7b7c, 0xfff3f3f3, 0xffffffff, 0xffffffff, 0xffe9e9e9, 0xff7c7a7a, 0xff302c2d, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff242021, 0xff2e2a2b, 0xff4f4c4d, 0xff9f9e9f, 0xff9c9a9b, 0xff2f2b2c, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231e1f, 0xff1e1b1c, 0xff848282, 0xfff6f6f6, 0xffffffff, 0xfff8f8f8, 0xff7f7d7e, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff8b898a, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffececec, 0xff595658, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff272425, 0xffa3a1a1, 0xfffafafa, 0xffffffff, 0xffffffff, 0xfff3f2f3, 0xffaaa9a9, 0xff6c6a6a, 0xff585556, 0xff5b5859, 0xff797677, 0xffc2c1c1, 0xfffdfdfd, 0xffffffff, 0xffffffff, 0xffefeeee, 0xff7b7979, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff585556, 0xfff5f5f5, 0xffffffff, 0xfff5f5f5, 0xff7d7b7c, 0xff201d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff929090, 0xfffafafa, 0xffffffff, 0xffe9e9e9, 0xff514d4f, 0xff1d1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xffadacad, 0xffffffff, 0xffffffff, 0xffc4c3c3, 0xff322e30, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff373435, 0xffc8c7c7, 0xffffffff, 0xffffffff, 0xffb0aeaf, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff2e2a2b, 0xffc4c3c3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffcccccc, 0xff7b7878, 0xff575354, 0xff524e4f, 0xff5c595a, 0xff848282, 0xffd2d1d1, 0xffffffff, 0xfff5f5f5, 0xffcbcbcb, 0xffeeeeee, 0xffffffff, 0xffffffff, 0xff777475, 0xff181415, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff242021, 0xff7c797a, 0xffedeced, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe9e8e8, 0xffbebdbe, 0xffaeadae, 0xffb8b7b7, 0xffdddcdc, 0xffffffff, 0xffffffff, 0xffbfbebf, 0xffa5a3a4, 0xfffbfbfb, 0xffffffff, 0xffe9e8e8, 0xff545252, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff282325, 0xff9e9d9d, 0xfff7f7f7, 0xffffffff, 0xffffffff, 0xfffcfcfc, 0xffc6c5c5, 0xff888687, 0xff636161, 0xff585556, 0xff575455, 0xff5e5b5c, 0xff726f70, 0xff959293, 0xffc3c2c2, 0xfff4f3f3, 0xffffffff, 0xffb5b4b4, 0xff2f2b2c, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff858383, 0xfff8f7f7, 0xffffffff, 0xfff9f9f9, 0xff807d7e, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff3f3c3c, 0xffd5d4d4, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffededed, 0xff5a5758, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff332f30, 0xffa4a3a3, 0xfff6f6f6, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffdfdfd, 0xfff0f1f1, 0xfff3f3f3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffeae9e9, 0xff858383, 0xff252222, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff585656, 0xfff6f6f6, 0xffffffff, 0xfff6f6f6, 0xff7e7c7c, 0xff201d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff939191, 0xfffbfbfb, 0xffffffff, 0xffeaeaea, 0xff524e4f, 0xff1d1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xffaeacad, 0xffffffff, 0xffffffff, 0xffc5c4c4, 0xff322e30, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff383435, 0xffc9c8c9, 0xffffffff, 0xffffffff, 0xffb1afb0, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff585556, 0xffdedddd, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff0f0f0, 0xffe9e9e9, 0xfff4f4f4, 0xffffffff, 0xffffffff, 0xfffafafa, 0xffa4a3a3, 0xff706d6e, 0xffe6e6e6, 0xffffffff, 0xffffffff, 0xff787576, 0xff181415, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff272324, 0xff7e7b7d, 0xffdfdede, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffdfdfd, 0xffc2c1c1, 0xff494747, 0xff8a8788, 0xfffbfbfb, 0xffffffff, 0xffe7e6e6, 0xff514e4f, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff2c2829, 0xff918f8f, 0xffe9e9e9, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffafafa, 0xfff0f0f0, 0xffefefef, 0xfff7f7f7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffadabac, 0xff2e2a2b, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff828181, 0xfff5f5f5, 0xfffcfcfc, 0xfff7f7f7, 0xff7e7b7c, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff252122, 0xff817f7f, 0xfff8f8f8, 0xfffdfefe, 0xfffcfcfc, 0xfffcfdfc, 0xffebeaeb, 0xff595656, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201b1d, 0xff2e2a2b, 0xff787575, 0xffcccbcc, 0xfffbfafb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff4f4f3, 0xffbab9b9, 0xff625e5f, 0xff252122, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff585555, 0xfff2f2f2, 0xfffefdfd, 0xfff3f4f4, 0xff7c7a7a, 0xff211c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff908e8f, 0xfff9f8f8, 0xfffcfcfc, 0xffe7e6e6, 0xff504d4e, 0xff1d1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211c1d, 0xffacaaaa, 0xffffffff, 0xffffffff, 0xffc3c2c2, 0xff322e2f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff383435, 0xffc7c5c6, 0xffffffff, 0xffffffff, 0xffafadad, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff232020, 0xff5b5959, 0xffc0bfbf, 0xfffafafa, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffdddcdd, 0xff888686, 0xff302c2d, 0xff5a5657, 0xffe7e7e7, 0xfffefefe, 0xfffffffe, 0xff767475, 0xff191415, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242021, 0xff535051, 0xff9d9b9b, 0xffd2d1d2, 0xffeeeeee, 0xfff9fafa, 0xfff7f7f7, 0xffe7e7e7, 0xffc4c3c4, 0xff858384, 0xff3d3a3b, 0xff1b1819, 0xff989797, 0xfffcfcfc, 0xffffffff, 0xffe1e0e1, 0xff4a4647, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff272324, 0xff5e5b5c, 0xffafadae, 0xffeaeaea, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff5f5f5, 0xffd1d1d1, 0xff9f9d9e, 0xff565454, 0xff262223, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff3b3738, 0xff575455, 0xff585556, 0xff575556, 0xff393637, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff312d2e, 0xff545152, 0xff595657, 0xff585556, 0xff585556, 0xff545152, 0xff302c2d, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff242021, 0xff3a3637, 0xff656263, 0xff949292, 0xffb1b0b0, 0xffbdbcbc, 0xffbcbaba, 0xffacabab, 0xff898787, 0xff595656, 0xff322e2f, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff302c2d, 0xff565353, 0xff595556, 0xff565454, 0xff393536, 0xff221f1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff3e3a3b, 0xff585556, 0xff585556, 0xff535051, 0xff2e2b2b, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff454142, 0xff5a5859, 0xff5a5758, 0xff4a4748, 0xff272324, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff282425, 0xff4b4748, 0xff595657, 0xff5a5758, 0xff454243, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff231f20, 0xff363233, 0xff666464, 0xff9a9798, 0xffb4b3b4, 0xffbdbcbc, 0xffb7b6b6, 0xffa09e9e, 0xff737172, 0xff434041, 0xff262223, 0xff211d1e, 0xff312d2e, 0xff535051, 0xff595656, 0xff595556, 0xff383435, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff211d1e, 0xff292526, 0xff3b3738, 0xff4e4b4c, 0xff565454, 0xff555253, 0xff4a4647, 0xff353132, 0xff252122, 0xff1f1b1c, 0xff231e1f, 0xffb5b4b4, 0xfffefefe, 0xffffffff, 0xffd5d4d4, 0xff3a3738, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xff2e2a2b, 0xff4d4a4a, 0xff787676, 0xff9e9c9d, 0xffb5b4b4, 0xffbdbcbd, 0xffbababa, 0xffb1b0b1, 0xff9c9a9b, 0xff7d7b7b, 0xff575455, 0xff3b3838, 0xff292526, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff211d1e, 0xff211d1e, 0xff221f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff211d1e, 0xff252122, 0xff292526, 0xff272425, 0xff231f20, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff211d1e, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211e1f, 0xff211d1e, 0xff221e1f, 0xff221f1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff211d1e, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff211d1e, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221f1f, 0xff221d1f, 0xff221e1f, 0xff252122, 0xff282425, 0xff262223, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff211d1e, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff3c393a, 0xffd5d5d5, 0xffffffff, 0xfffefefe, 0xffbebdbe, 0xff272324, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff211d1e, 0xff211d1e, 0xff262223, 0xff292526, 0xff272425, 0xff242021, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff201c1d, 0xff7b7879, 0xfff4f3f3, 0xffffffff, 0xfffbfbfb, 0xff8e8b8c, 0xff1d191a, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff322e2f, 0xff312d2e, 0xff211d1e, 0xff1f1b1c, 0xff201c1d, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff211d1e, 0xff1f1b1c, 0xff221e1f, 0xff555253, 0xffd6d5d5, 0xffffffff, 0xffffffff, 0xffeaeaea, 0xff4c484a, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff727070, 0xffafadae, 0xff777475, 0xff494647, 0xff302c2d, 0xff231f20, 0xff221e1f, 0xff211e1f, 0xff2a2627, 0xff434040, 0xff7b7879, 0xffd5d4d4, 0xffffffff, 0xffffffff, 0xffffffff, 0xff9b9999, 0xff201d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff838181, 0xfffafafa, 0xfff4f3f4, 0xffdbd9da, 0xffc0bfbf, 0xffacabab, 0xffa3a2a2, 0xffa8a6a6, 0xffb8b6b7, 0xffd5d4d4, 0xfff4f4f4, 0xffffffff, 0xffffffff, 0xffffffff, 0xffbcbbbc, 0xff353133, 0xff201b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff828080, 0xfffcfcfc, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffefefe, 0xfffcfcfc, 0xfffdfdfd, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffdfefe, 0xffacaaab, 0xff3c3839, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff434041, 0xff939191, 0xffcdcccd, 0xffedecec, 0xfff7f7f7, 0xfffefefe, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff9f9f9, 0xffebebeb, 0xffbcbbbc, 0xff696666, 0xff2a2627, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff1d191a, 0xff272324, 0xff3d3a3b, 0xff5a5758, 0xff6e6c6c, 0xff797677, 0xff7b797a, 0xff737172, 0xff605d5e, 0xff3f3b3b, 0xff231f20, 0xff1d191a, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff1e1a1b, 0xff1b1718, 0xff191516, 0xff181415, 0xff181415, 0xff181415, 0xff1b1718, 0xff1f1a1c, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff2d292a, 0xff5e5c5d, 0xff696566, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696666, 0xff696566, 0xff696666, 0xff514e4f, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff201c1d, 0xff787576, 0xffe8e7e7, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff4f4f4, 0xffd1d1d1, 0xff464344, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff4b4849, 0xffd6d6d6, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffcfcfc, 0xffa2a1a1, 0xff292526, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff2e2a2b, 0xffaaa8a9, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffefdfd, 0xfff7f6f7, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfffafafa, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffeaeaea, 0xff656263, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff242021, 0xff737071, 0xfff7f7f7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe4e3e4, 0xff686566, 0xff423e3f, 0xff464243, 0xff464243, 0xff464243, 0xff464243, 0xff464243, 0xff464243, 0xff464243, 0xff464243, 0xff464243, 0xff464243, 0xff464243, 0xff464243, 0xff464243, 0xff454142, 0xff464344, 0xffa19f9f, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff383435, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff464344, 0xffdedddd, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffdedede, 0xff484546, 0xff1a1617, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1e1a1b, 0xff201c1d, 0xff8d8a8b, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffdfdfd, 0xff828080, 0xff252122, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff2b2829, 0xffb4b2b3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffdfdedf, 0xff4c494a, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff242021, 0xff908d8d, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff4b4748, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff2e2a2b, 0xff464243, 0xff464243, 0xff464243, 0xff464243, 0xff464243, 0xff464243, 0xff464243, 0xff464243, 0xff464243, 0xff464243, 0xff464243, 0xff464243, 0xff464243, 0xff464243, 0xff464243, 0xff464243, 0xff464243, 0xff464243, 0xff464244, 0xff423f40, 0xff2b2728, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1d191a, 0xff868485, 0xfffdfdfd, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffdfdedf, 0xff4c494a, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff242021, 0xff8f8d8d, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffb4b3b3, 0xff272425, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1c1819, 0xff838181, 0xffdadada, 0xffd9d8d8, 0xffd9d8d8, 0xffd9d8d8, 0xffd9d8d8, 0xffd9d8d8, 0xffd9d8d8, 0xffd9d8d8, 0xffd9d8d8, 0xffd9d8d8, 0xffd9d8d8, 0xffd9d8d8, 0xffd9d8d8, 0xffd9d8d8, 0xffd9d8d8, 0xffd9d8d8, 0xffd9d8d8, 0xffd9d8d8, 0xffd9d8d9, 0xffcfcecf, 0xff676464, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff1f1a1b, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1e1a1b, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff585556, 0xffeaeaea, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffdfdedf, 0xff4c494a, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff242021, 0xff8f8d8d, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffcfcfc, 0xff787677, 0xff1b1718, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff332f30, 0xffd7d5d6, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffa9a7a8, 0xff2b2728, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff2e2b2b, 0xff413d3e, 0xff403d3e, 0xff403d3e, 0xff403d3e, 0xff403d3e, 0xff403d3e, 0xff403d3e, 0xff403d3e, 0xff403d3e, 0xff403d3e, 0xff403d3e, 0xff403d3e, 0xff403d3e, 0xff423e3f, 0xff383535, 0xff242021, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff343132, 0xffc5c3c3, 0xfffefefe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffdfdedf, 0xff4c494a, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff242021, 0xff8f8d8d, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffdfdfdf, 0xff423e3f, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1c1819, 0xff737072, 0xfff7f7f7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffdcdbdb, 0xff4a4748, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211e1f, 0xff969394, 0xfffaf9f9, 0xfff2f2f2, 0xfff2f2f2, 0xfff2f2f2, 0xfff2f2f2, 0xfff2f2f2, 0xfff2f2f2, 0xfff2f2f2, 0xfff2f2f2, 0xfff2f2f2, 0xfff2f2f2, 0xfff2f2f2, 0xfff2f2f2, 0xfff8f8f8, 0xffcdcccc, 0xff332f30, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff252021, 0xff908e8e, 0xfff9f8f8, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffdfdedf, 0xff4c484a, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff242021, 0xff8f8d8d, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffefefe, 0xffa8a7a7, 0xff262122, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff2b2728, 0xffbbb9b9, 0xfffefefe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffdfdfd, 0xff7d7b7b, 0xff242021, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff312d2e, 0xffd6d5d5, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff8f7f7, 0xff4c494a, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff5d5a5b, 0xffe5e5e5, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffdfdedf, 0xff4c4849, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff242021, 0xff8f8d8e, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffefeeef, 0xff696667, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xff5a5758, 0xffe8e7e8, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffbfbdbe, 0xff302c2d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff5b5858, 0xfffcfcfc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff787676, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff393536, 0xffc0bebf, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffededed, 0xff9b999a, 0xff828080, 0xff848283, 0xff848283, 0xff848283, 0xff848283, 0xff848283, 0xff848283, 0xff848283, 0xff848283, 0xff848283, 0xff848283, 0xff848283, 0xff848283, 0xff848283, 0xff848282, 0xff868383, 0xffc1c0c0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffc5c3c4, 0xff3c3839, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff262323, 0xff9a9999, 0xfffcfcfc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff3f3f3, 0xff565354, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1d191a, 0xff9c9b9a, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffa8a6a6, 0xff1f1b1c, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221f1f, 0xff231f20, 0xff908e8e, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffeffff, 0xfffefefe, 0xfffffefe, 0xfffffefe, 0xfffffefe, 0xfffffefe, 0xfffffefe, 0xfffffefe, 0xfffffefe, 0xfffffefe, 0xfffffefe, 0xfffffefe, 0xfffffefe, 0xfffffefe, 0xfffffefe, 0xfffffefe, 0xfffffefe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffafafa, 0xff8a8889, 0xff252122, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff444142, 0xffd4d3d4, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff9b999a, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff312d2e, 0xffdfdede, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffdad9da, 0xff2c2829, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff676565, 0xfffafafa, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffebeaea, 0xff585555, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff252122, 0xff807e7e, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffeae9e9, 0xff3d393a, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff332f30, 0xff777575, 0xff7d7b7c, 0xff7c7a7a, 0xff7c7a7a, 0xff7c7a7a, 0xff7c7a7a, 0xff7c7a7a, 0xff7c7a7a, 0xff7c7a7a, 0xff7c7a7a, 0xff7c7a7a, 0xff7c7a7a, 0xff7c7a7a, 0xff7c7a7a, 0xff7c7a7a, 0xff7c7a7a, 0xff7e7b7c, 0xff757273, 0xff2b2728, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff242021, 0xff767374, 0xffa19f9f, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xff9c9a9b, 0xffa09e9f, 0xff615f60, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff272223, 0xff605d5e, 0xff8a8888, 0xff878686, 0xff878585, 0xff878585, 0xff878585, 0xff878585, 0xff878585, 0xff878585, 0xff878585, 0xff878585, 0xff878585, 0xff878585, 0xff878585, 0xff878585, 0xff878585, 0xff878585, 0xff878585, 0xff878585, 0xff878585, 0xff878585, 0xff878585, 0xff878585, 0xff878585, 0xff878585, 0xff888686, 0xff878485, 0xff3e3a3b, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff1b1718, 0xff1b1718, 0xff1b1718, 0xff1b1718, 0xff1b1718, 0xff1b1718, 0xff1b1718, 0xff1b1718, 0xff1b1718, 0xff1b1718, 0xff1b1718, 0xff1b1718, 0xff1b1718, 0xff1b1718, 0xff1b1718, 0xff1b1718, 0xff1b1718, 0xff1c1819, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e191a, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1e1a1b, 0xff221f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1d191a, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff1a1617, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff201b1c, 0xff242021, 0xff302c2d, 0xff3e3b3c, 0xff4a4747, 0xff555253, 0xff5e5b5b, 0xff5f5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5f5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5e5c5d, 0xff5f5c5d, 0xff5e5a5b, 0xff555252, 0xff4a4647, 0xff3e3a3b, 0xff2f2b2c, 0xff231f20, 0xff201c1d, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff1d191a, 0xff2d2a2b, 0xff575455, 0xff848283, 0xffb4b3b4, 0xffd2d1d2, 0xffdfdede, 0xffeaeaea, 0xfff4f4f4, 0xfff6f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff4f3f4, 0xffeaeaea, 0xffdeddde, 0xffd0d0d0, 0xffb2b1b1, 0xff818080, 0xff555253, 0xff2b2829, 0xff1d191a, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e191a, 0xff242021, 0xff605d5e, 0xffb5b3b3, 0xffe5e5e5, 0xfffaf9fa, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff9f9f9, 0xffe4e3e4, 0xffb0afb0, 0xff5c5959, 0xff231e20, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff3f3b3c, 0xffaaa9a9, 0xffececec, 0xfffefefe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffdfdfd, 0xffebeaea, 0xffa6a4a6, 0xff3c3839, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff4e4a4b, 0xffcccacb, 0xfffefefe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffdfdfd, 0xffc8c7c7, 0xff4b4848, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff585556, 0xffdbdadb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffd8d7d8, 0xff555253, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1c1c, 0xff484546, 0xffd7d6d6, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffd4d3d3, 0xff474344, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff383434, 0xffc3c2c2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff373333, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1a1b, 0xff9c9a9a, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff9a9898, 0xff1e1a1b, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1c1819, 0xff514e4e, 0xffebebeb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffeaeaea, 0xff504c4d, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff252122, 0xffaaa9aa, 0xfffdfdfd, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffdfdfd, 0xffaaa9a9, 0xff252122, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xff4a4748, 0xffe0dfe0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe0dfdf, 0xff4a4747, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff787676, 0xfff4f3f3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff3f3f3, 0xff777575, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff2a2627, 0xffa8a6a6, 0xfffefefe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffefefe, 0xffa6a5a5, 0xff292526, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff373435, 0xffc5c4c4, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffc3c2c2, 0xff363333, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff3f3c3d, 0xffd2d1d2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffd2d1d1, 0xff3f3b3c, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff4a4748, 0xffdcdbdb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffdcdbdb, 0xff4a4748, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211c1e, 0xff535052, 0xffe3e2e2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e2e2, 0xff535051, 0xff211c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff555252, 0xffe4e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff555253, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffcfcfc, 0xfff5f4f5, 0xffececec, 0xffe4e3e4, 0xffdcdbdb, 0xffdbdada, 0xffe3e3e3, 0xffececec, 0xfff5f4f5, 0xfffcfcfd, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff545152, 0xff211c1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff1f1f1, 0xffd2d1d1, 0xffafaeae, 0xff8a8889, 0xff6f6d6e, 0xff646162, 0xff5c595a, 0xff555253, 0xff4e4a4b, 0xff464344, 0xff454343, 0xff4d4a4b, 0xff555252, 0xff5c595a, 0xff646263, 0xff706e6f, 0xff898787, 0xffaeadad, 0xffd1d0d0, 0xfff1f1f1, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff545152, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e2e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffbfbfb, 0xffd0cfd0, 0xff949293, 0xff696667, 0xff474444, 0xff343031, 0xff272324, 0xff242021, 0xff231f20, 0xff221e1f, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff282324, 0xff343031, 0xff464243, 0xff686566, 0xff929091, 0xffcccbcb, 0xfff9f9f9, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff545152, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545151, 0xffe2e2e2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffefefe, 0xfff8f7f7, 0xffdddcdc, 0xffa09f9f, 0xff5a5757, 0xff2b2829, 0xff1d191a, 0xff1e1a1b, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff211d1e, 0xff1e1a1b, 0xff1d191a, 0xff2a2627, 0xff575454, 0xff9d9b9c, 0xffdcdadb, 0xfff7f7f7, 0xfffefdfd, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff545152, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff535051, 0xffe2e2e2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffefefe, 0xffebebeb, 0xffb6b5b5, 0xff6c696a, 0xff353132, 0xff1d191a, 0xff1c1819, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff1d191a, 0xff1c1819, 0xff333030, 0xff6a6767, 0xffb1b0b0, 0xffe9e9e9, 0xfffdfdfd, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff545152, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211c1e, 0xff525050, 0xffe2e2e2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe7e7e7, 0xffaeacad, 0xff605d5e, 0xff272324, 0xff1a1617, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff1a1617, 0xff252223, 0xff5c595a, 0xffa9a8a8, 0xffe5e5e5, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff545152, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff524f50, 0xffe2e1e2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffefeeef, 0xffa7a6a6, 0xff5d5a5a, 0xff2c2829, 0xff1e1a1b, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff1e1a1b, 0xff2b2728, 0xff5a5757, 0xffa3a1a2, 0xffecebeb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff545152, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff524f50, 0xffe2e1e1, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffcdcccd, 0xff605d5d, 0xff2b2728, 0xff211d1e, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221d1e, 0xff211d1e, 0xff2a2627, 0xff595657, 0xffc3c3c3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff545152, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff524f50, 0xffe2e1e1, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff7f7f7, 0xff999797, 0xff343132, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff332f30, 0xff928f90, 0xfff3f2f3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff545152, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff524f50, 0xffe1e1e1, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffefefe, 0xffd6d5d5, 0xff666464, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff221e1f, 0xff646061, 0xffd3d2d2, 0xfffcfcfc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff545152, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff524e4f, 0xffe1e1e1, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffaf9fa, 0xffb6b4b5, 0xff423f3f, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1c1718, 0xff3e3a3b, 0xffb2b0b1, 0xfff9f9f9, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff545152, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff514e4f, 0xffe1e0e1, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff8f7f8, 0xffa2a0a1, 0xff353233, 0xff1c191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1c1819, 0xff302c2d, 0xff9a9899, 0xfff6f6f6, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff545152, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff504e4e, 0xffe1e0e0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff4f3f3, 0xff888687, 0xff2d292a, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff2a2728, 0xff827f7f, 0xffefefef, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff545152, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff504d4e, 0xffe1e0e0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffecebec, 0xff716e6f, 0xff272324, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff272425, 0xff6f6d6e, 0xffe7e7e7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff545152, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff504d4e, 0xffe0e0e0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff1f0f1, 0xff726f70, 0xff242021, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff716f6f, 0xffeeeeee, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff545152, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff504d4e, 0xffe0dfe0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff4f4f4, 0xff8a8888, 0xff262223, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221d1e, 0xff888686, 0xfff4f4f4, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff545152, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff504d4d, 0xffe0dfdf, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff9f9f9, 0xff9f9d9d, 0xff2b2727, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff201c1d, 0xff201c1d, 0xff211d1e, 0xff252222, 0xff2e2a2b, 0xff333031, 0xff363334, 0xff3a3738, 0xff3b3738, 0xff373334, 0xff343031, 0xff2f2b2c, 0xff262223, 0xff211e1f, 0xff1f1b1c, 0xff201b1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff242122, 0xff999797, 0xfffafafa, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff545152, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff504c4d, 0xffe0dfdf, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffaeacac, 0xff312d2e, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff1d1819, 0xff242021, 0xff3c3839, 0xff5d5b5b, 0xff7b7979, 0xff959393, 0xffafadad, 0xffbebdbd, 0xffc6c5c5, 0xffcdcccc, 0xffcecdcd, 0xffc7c6c6, 0xffbfbebe, 0xffb1afaf, 0xff979595, 0xff7d7a7c, 0xff615d5e, 0xff3e3a3b, 0xff252122, 0xff1d191a, 0xff1f1b1c, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff2a2728, 0xffa4a2a2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff545152, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff504c4d, 0xffe0dfdf, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffcbcaca, 0xff383535, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff1c1819, 0xff343031, 0xff6f6c6d, 0xffa6a5a5, 0xffcecdce, 0xffe8e8e8, 0xfff6f6f6, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff7f7f7, 0xffe9e9e9, 0xffd0d0d0, 0xffa9a8a8, 0xff737070, 0xff363334, 0xff1c1819, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff333031, 0xffbbb9ba, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff545152, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff4f4c4c, 0xffdfdfdf, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffefefef, 0xff555253, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff1b1718, 0xff3b3839, 0xff8b8888, 0xffd2d1d1, 0xfff3f3f3, 0xfffcfcfc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffdfdfd, 0xfff4f4f4, 0xffd6d5d5, 0xff8f8d8e, 0xff403d3d, 0xff1d1819, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221d1e, 0xff4e4b4c, 0xffe2e1e1, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff545152, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff4f4b4c, 0xffdfdedf, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff868384, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff2f2b2c, 0xff807d7d, 0xffe0e0e0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffefefe, 0xffe3e3e3, 0xff858384, 0xff322e2f, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff252122, 0xff7f7c7d, 0xfff8f8f8, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff545152, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff4e4b4c, 0xffdfdede, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffbab9b9, 0xff312d2e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff272324, 0xff5b5858, 0xffc6c5c5, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffcbcbcb, 0xff5f5c5d, 0xff282425, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff332f30, 0xffb5b3b4, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe5e4e4, 0xff555252, 0xff211c1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff423e3f, 0xffaaa8a9, 0xffc2c1c1, 0xffc0bebf, 0xffc0bfbf, 0xffc0bfbf, 0xffc0bfbf, 0xffc0bfbf, 0xffc0bfbf, 0xffc0bfbf, 0xffc0bfbf, 0xffc1bfbf, 0xffc1bfbf, 0xffc1bfbf, 0xffc1bfbf, 0xffc1bfbf, 0xffc1bfbf, 0xffc1bfc0, 0xffc1bfc0, 0xffc1c0c0, 0xffc1c0c0, 0xffc1c0c0, 0xffc1c0c0, 0xffc1c0c0, 0xffc1c0c0, 0xffc1c0c0, 0xffc1c0c0, 0xffc1c0c1, 0xffc1c0c1, 0xffc1c0c1, 0xffc1c0c1, 0xffc1c0c1, 0xffc2c1c1, 0xffc2c1c1, 0xffc2c1c1, 0xffc2c1c1, 0xffc2c1c1, 0xffc2c1c1, 0xffc2c1c1, 0xffc2c1c1, 0xffc3c1c2, 0xffc3c1c2, 0xffc3c2c2, 0xffc3c2c2, 0xffc3c2c2, 0xffc3c2c2, 0xffc3c2c2, 0xffc3c2c2, 0xffc3c2c2, 0xffc3c2c2, 0xffc3c2c3, 0xffc3c2c3, 0xffc3c2c3, 0xffc3c2c3, 0xffc3c2c3, 0xffc3c3c3, 0xffc3c3c3, 0xffc3c3c3, 0xffc4c3c3, 0xffc4c3c3, 0xffc4c3c3, 0xffc4c3c3, 0xffc4c3c3, 0xffc4c3c3, 0xffc5c3c4, 0xffc5c3c4, 0xffc5c4c4, 0xffc5c4c4, 0xffc5c4c4, 0xffc5c4c4, 0xffc5c4c4, 0xffc5c4c4, 0xffc5c4c4, 0xffc5c4c4, 0xffc5c4c4, 0xffc5c4c4, 0xffc5c4c4, 0xffc5c4c4, 0xffc5c4c4, 0xffc5c4c4, 0xffc5c4c4, 0xffc7c6c6, 0xffbab9ba, 0xff524f50, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff343031, 0xff888686, 0xffeaeaea, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff0f0f0, 0xff8f8e8e, 0xff383435, 0xff1f1b1c, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1a1b, 0xff535051, 0xffc0bfc0, 0xffd2d1d1, 0xffd1d1d1, 0xffd1d1d1, 0xffd1d1d1, 0xffd2d1d1, 0xffd2d1d1, 0xffd2d1d1, 0xffd2d1d1, 0xffd2d1d1, 0xffd3d2d2, 0xffd3d2d2, 0xffd3d2d2, 0xffd3d2d2, 0xffd3d2d3, 0xffd3d2d3, 0xffd3d2d3, 0xffd3d3d3, 0xffd3d3d3, 0xffd3d3d3, 0xffd4d3d3, 0xffd4d3d3, 0xffd3d3d3, 0xffd4d4d4, 0xffd5d4d4, 0xffd5d4d4, 0xffd5d4d4, 0xffd5d4d4, 0xffd5d4d4, 0xffd5d4d4, 0xffd5d4d4, 0xffd5d4d4, 0xffd5d4d5, 0xffd5d5d5, 0xffd5d5d5, 0xffd6d5d5, 0xffd6d5d6, 0xffd6d6d6, 0xffd6d6d6, 0xffd6d6d6, 0xffd7d6d6, 0xffd7d6d6, 0xffd7d6d6, 0xffd7d6d6, 0xffdad9d9, 0xffc3c2c2, 0xff4b4849, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff252122, 0xff2d292a, 0xff2e2b2c, 0xff2f2a2c, 0xff2f2b2c, 0xff2f2b2c, 0xff2f2b2c, 0xff2f2b2c, 0xff2f2b2c, 0xff2f2b2c, 0xff2f2b2c, 0xff2f2c2c, 0xff2f2c2c, 0xff2f2c2c, 0xff2f2c2d, 0xff2f2c2d, 0xff2f2c2d, 0xff2f2c2d, 0xff2f2c2d, 0xff302c2d, 0xff302c2d, 0xff302c2d, 0xff302c2d, 0xff302c2d, 0xff302c2d, 0xff302c2d, 0xff302c2d, 0xff302d2e, 0xff302d2e, 0xff302d2e, 0xff302d2e, 0xff302d2e, 0xff312d2e, 0xff312d2e, 0xff312d2e, 0xff312d2e, 0xff312d2e, 0xff312d2e, 0xff312d2e, 0xff312d2e, 0xff312d2e, 0xff312d2e, 0xff312e2f, 0xff312e2f, 0xff312e2f, 0xff312e2f, 0xff312e2f, 0xff322e2f, 0xff322e2f, 0xff322e2f, 0xff322e2f, 0xff322e2f, 0xff322e2f, 0xff322e2f, 0xff322e2f, 0xff322e2f, 0xff322e2f, 0xff322e2f, 0xff322e2f, 0xff322e2f, 0xff322e2f, 0xff322e2f, 0xff322e2f, 0xff322e2f, 0xff322f2f, 0xff322f30, 0xff322f30, 0xff322f30, 0xff322f30, 0xff322f30, 0xff332f30, 0xff332f30, 0xff332f30, 0xff332f30, 0xff332f30, 0xff332f30, 0xff332f30, 0xff332f30, 0xff333030, 0xff333030, 0xff343030, 0xff343031, 0xff2f2c2d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1c1819, 0xff413e3f, 0xffb2b1b2, 0xfffcfcfc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffefffe, 0xffbbbaba, 0xff4b4748, 0xff1d191a, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xff373435, 0xff3e3a3b, 0xff3e3a3b, 0xff3e3a3b, 0xff3e3b3b, 0xff3e3b3b, 0xff3f3b3b, 0xff3f3b3c, 0xff3f3b3c, 0xff3f3c3c, 0xff3f3b3c, 0xff3f3b3d, 0xff3f3c3d, 0xff3f3c3d, 0xff403c3d, 0xff403c3d, 0xff403c3d, 0xff403c3d, 0xff403d3d, 0xff403d3e, 0xff403d3e, 0xff403d3e, 0xff403d3e, 0xff413d3e, 0xff413d3e, 0xff413d3e, 0xff413e3f, 0xff413e3f, 0xff413e3f, 0xff413e3f, 0xff413e3f, 0xff413e3f, 0xff423e3f, 0xff423e3f, 0xff423f3f, 0xff423f40, 0xff423f40, 0xff423f40, 0xff423f40, 0xff423f40, 0xff433f40, 0xff433f40, 0xff433f40, 0xff433f40, 0xff434041, 0xff3f3c3d, 0xff2a2627, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211c1e, 0xff211c1d, 0xff211c1d, 0xff211c1d, 0xff211c1d, 0xff211c1d, 0xff211c1d, 0xff211c1d, 0xff211c1d, 0xff211c1d, 0xff211c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff211c1d, 0xff231e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1c1819, 0xff4f4c4d, 0xffcac8c8, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffcfcece, 0xff585556, 0xff1f1b1c, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xff4f4c4d, 0xffd3d3d3, 0xfffefefe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffd9d8d8, 0xff555152, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff242021, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff252122, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff454242, 0xffcacaca, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffd1d1d1, 0xff464343, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff444041, 0xffa3a1a2, 0xffb6b4b5, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb4b2b3, 0xffb6b4b5, 0xff5b5859, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff373334, 0xffb8b7b7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffc4c3c4, 0xff373334, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff464243, 0xffadabab, 0xffb0afaf, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb0aeae, 0xffb1b0b0, 0xffa2a0a1, 0xff474445, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff575454, 0xffeae9ea, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff1f1f1, 0xff464344, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff262223, 0xff928f90, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffa19fa0, 0xff262223, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff383435, 0xffdedddd, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff0efef, 0xff5e5b5c, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211c1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffa6a5a5, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff696667, 0xfff4f4f4, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff8f8f8, 0xff7a7778, 0xff1d191a, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff8d8b8c, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe9e8e8, 0xff5c5959, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff9f9f9, 0xff585556, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff454143, 0xffdeddde, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e2e2, 0xff535050, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff504c4d, 0xffe9e8e9, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe9e8e8, 0xff5c5959, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffc5c5c5, 0xff2c2829, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff211d1e, 0xffadabab, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffdfdfd, 0xffb3b1b1, 0xff2a2627, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff2f2b2c, 0xffb5b4b4, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe9e8e8, 0xff5c5859, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff8e8b8c, 0xff211e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1c1819, 0xff5a5758, 0xfff0f0f0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffebebeb, 0xff636161, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff242021, 0xff838182, 0xfffdfdfd, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe8e8e8, 0xff5b5859, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff7f7f7, 0xff5b5959, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff2a2627, 0xffb2b1b2, 0xfffdfdfd, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffb2b0b0, 0xff312d2e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff5c5959, 0xffe9e8e8, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe8e8e8, 0xff5b5859, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffd4d4d4, 0xff3c3839, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xff5c5a5b, 0xffe9e9e9, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffecebec, 0xff5d5a5b, 0xff221d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff3d393a, 0xffcccbcb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe8e8e8, 0xff5b5859, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffa9a7a8, 0xff2b2728, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff252122, 0xff989696, 0xfffcfcfc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff979596, 0xff272324, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff282325, 0xffa6a4a4, 0xfffefefe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe8e8e8, 0xff5b5859, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff828080, 0xff242021, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff3d393a, 0xffcccacb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffd3d2d2, 0xff3a3637, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201b1d, 0xff817f80, 0xfff6f6f6, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe8e7e8, 0xff5b5859, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff3f3f3, 0xff6a6767, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff666364, 0xfff1f1f1, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffcfcfc, 0xff666465, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff656263, 0xffeeeded, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe8e7e8, 0xff5b5859, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e2e2, 0xff545152, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff272224, 0xff908e8f, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff9b9999, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff4c494a, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe8e7e8, 0xff5a5859, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffd2d2d2, 0xff413d3e, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff2e292a, 0xffb5b4b4, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffc4c2c3, 0xff292526, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff373334, 0xffd1d0d0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe8e7e8, 0xff5a5859, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffbebdbd, 0xff343031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff3d3a3a, 0xffd7d6d6, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffeae9e9, 0xff3b3838, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff262223, 0xffbdbcbc, 0xfffefefe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe8e7e7, 0xff5a5758, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffb1afb0, 0xff2d292a, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff514d4e, 0xfff3f3f3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffdfcfc, 0xff5a5758, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff211d1e, 0xffadabac, 0xfffdfdfd, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe8e7e7, 0xff5a5758, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffa9a8a8, 0xff292627, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff5f5c5d, 0xfffdfefd, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff706e6f, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff201b1d, 0xffa2a0a0, 0xfffcfcfc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe8e7e7, 0xff5a5758, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffa1a0a0, 0xff252122, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff6c6a6b, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff7e7c7d, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1a1b, 0xff979595, 0xfffcfcfc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe8e7e7, 0xff5a5758, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffdfdfd, 0xff999798, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff7b7879, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff8d8b8b, 0xff191516, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1d1819, 0xff8c8a8b, 0xfffbfbfb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe8e7e7, 0xff5a5757, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffbfbfb, 0xff929191, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff868384, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff989697, 0xff1b1618, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1c1819, 0xff848182, 0xfffbfbfb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe7e7e7, 0xff5a5757, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffcfcfc, 0xff969595, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff827f80, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff949292, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1c1819, 0xff888687, 0xfffbfbfb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe7e7e7, 0xff5a5757, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffefefe, 0xff9e9d9d, 0xff241f21, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff777576, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff8a8788, 0xff191516, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1d191a, 0xff929090, 0xfffbfbfb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe7e7e7, 0xff5a5757, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffa5a3a5, 0xff272324, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff6a6768, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff7c7a7a, 0xff1b1618, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1a1b, 0xff9b9a9a, 0xfffcfcfc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe7e7e7, 0xff5a5757, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffadabab, 0xff2b2728, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545051, 0xfff7f6f6, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffefefe, 0xff615e5e, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff201c1d, 0xffa4a3a4, 0xfffdfdfd, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe7e7e7, 0xff5a5757, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffb9b8b8, 0xff312e2e, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff444243, 0xffe2e2e2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff5f5f5, 0xff444142, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff231f20, 0xffb5b4b4, 0xfffefefe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe7e6e6, 0xff5a5657, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffcecdcd, 0xff3d393a, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff353132, 0xffc9c7c8, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffdbdada, 0xff312e2f, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff2f2b2c, 0xffcbcaca, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe7e6e6, 0xff595657, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffdedddd, 0xff4c494a, 0xff211d1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff292526, 0xffa1a0a0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffadacac, 0xff242021, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xff423f3f, 0xffdbdada, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe7e6e6, 0xff595657, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffececec, 0xff605d5d, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff767374, 0xfffafafa, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff7a7778, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff565354, 0xffe8e8e8, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe7e6e6, 0xff595657, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffafafa, 0xff767475, 0xff221f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff4e4a4b, 0xffdfdede, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe9e9e9, 0xff4a4748, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e191b, 0xff6f6d6d, 0xfff1f0f0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe7e6e6, 0xff595657, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff9c9b9b, 0xff282526, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff2e2a2b, 0xffb2b0b1, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffb5b3b4, 0xff2d292a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff231f20, 0xff969495, 0xfffbfbfb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe7e6e6, 0xff595657, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffc6c5c5, 0xff343031, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff797677, 0xfff3f3f3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffafafa, 0xff777575, 0xff242021, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff312e2f, 0xffbbbaba, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe7e6e6, 0xff595657, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe9e8e9, 0xff4c4849, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff3c393a, 0xffd0cfcf, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffcfcece, 0xff413e3f, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff494646, 0xffdbdada, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe7e6e6, 0xff595657, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff716e6f, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1d1a1b, 0xff878585, 0xfffbfbfb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff9f9f9, 0xff8a8989, 0xff231f20, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff6a6768, 0xfff1f1f1, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe6e6e6, 0xff585656, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffafadae, 0xff252123, 0xff231e20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff373335, 0xffd2d2d2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffd2d2d2, 0xff423e3f, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff282425, 0xff9c9a9a, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe6e6e6, 0xff585556, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffebebeb, 0xff423f3f, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff686566, 0xfffafbfb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff8f8f8, 0xff797677, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff3e3a3b, 0xffd4d3d3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe6e6e6, 0xff585556, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff838081, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff231f20, 0xffa7a5a6, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffbab9b9, 0xff292525, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff6a6768, 0xfffcfcfc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe6e5e6, 0xff585556, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffcbcaca, 0xff292627, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff393536, 0xffcecdce, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffdbdbdb, 0xff434041, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff262223, 0xffaeadad, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe6e5e6, 0xff585556, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffafafa, 0xff656264, 0xff1b1718, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff595657, 0xffe2e2e2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffececec, 0xff636162, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff4d4a4a, 0xffeeeeee, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe6e5e6, 0xff585556, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff292525, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff242021, 0xff71706f, 0xffebeaea, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff1f0f0, 0xff787576, 0xff221f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff201c1d, 0xffa5a4a4, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe6e5e5, 0xff585555, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff2f2f2, 0xff676465, 0xff1c1718, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff262223, 0xff7e7c7c, 0xfff2f2f2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff4f4f4, 0xff827f80, 0xff282425, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1c1819, 0xff4d4a4b, 0xfff0f0f0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe6e5e5, 0xff585555, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffefefe, 0xffb8b7b7, 0xff2b2729, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff242021, 0xff797777, 0xfff2f2f1, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff2f1f2, 0xff807e7f, 0xff282425, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff201b1c, 0xffa9a7a7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe6e5e5, 0xff585555, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffefefef, 0xff6d6b6b, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1a1b, 0xff6c696a, 0xffe7e7e7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffeae9e9, 0xff777475, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1c1819, 0xff5c595a, 0xfff0efef, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe6e5e5, 0xff585455, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffc4c3c4, 0xff3b3839, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1c1819, 0xff4f4c4d, 0xffc4c3c3, 0xfffbfafb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffbfbfb, 0xffcccacb, 0xff585656, 0xff1c1819, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff322e2f, 0xffbebdbd, 0xfffefefe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe6e5e5, 0xff585455, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffbfbfb, 0xff858384, 0xff242021, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xff373435, 0xff929091, 0xffe1e0e0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe4e4e4, 0xff999797, 0xff3b3839, 0xff1c1819, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xff7d7a7a, 0xfff5f5f5, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe5e5e5, 0xff575455, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe1e0e0, 0xff4e4b4c, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201b1c, 0xff252122, 0xff565354, 0xffa9a7a8, 0xffededed, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff0f0f0, 0xffaeacad, 0xff5a5758, 0xff272324, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff484546, 0xffd4d3d3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe5e5e5, 0xff575455, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffc1c0c0, 0xff302d2e, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff211d1e, 0xff2d292a, 0xff575354, 0xffa5a4a4, 0xffebebeb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffefefef, 0xffadabac, 0xff5b5959, 0xff2e2b2c, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff2e2b2b, 0xffaeacad, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe5e5e5, 0xff575455, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff9d9b9c, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff272324, 0xff444142, 0xff838182, 0xffcac9ca, 0xfff2f2f2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff3f3f4, 0xffcdcccd, 0xff888686, 0xff474444, 0xff282425, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff838182, 0xfffdfefe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe5e5e5, 0xff575455, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff9fafa, 0xff747172, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff1e191a, 0xff272425, 0xff454243, 0xff767373, 0xffa3a1a2, 0xffc4c3c3, 0xffdddbdc, 0xffe7e6e6, 0xffebebeb, 0xffefefef, 0xffefefef, 0xffecebeb, 0xffe7e7e7, 0xffdedede, 0xffc5c4c5, 0xffa6a4a5, 0xff7a7777, 0xff494546, 0xff292526, 0xff1e1a1b, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1a1c, 0xff5c595a, 0xfff1f1f1, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe5e4e5, 0xff575455, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe6e5e5, 0xff5f5c5d, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e191a, 0xff1a1517, 0xff1d191a, 0xff242021, 0xff302c2d, 0xff413d3e, 0xff4a4747, 0xff524f50, 0xff535051, 0xff4b4748, 0xff423e3f, 0xff312e2e, 0xff252122, 0xff1e1a1b, 0xff1a1517, 0xff1d191a, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231e20, 0xff1f1b1b, 0xff4e4c4c, 0xffdddcdc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe5e4e5, 0xff575455, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffd7d7d7, 0xff565354, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff1f1b1c, 0xff1e1a1b, 0xff1d191a, 0xff1c1819, 0xff1c1819, 0xff1d1819, 0xff1e1a1b, 0xff1f1b1c, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff4b4849, 0xffd0d0d0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe5e5e5, 0xff575455, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffcccccc, 0xff4a4748, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff444041, 0xffc5c4c4, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe5e5e4, 0xff565354, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffcccbcb, 0xff484546, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff433f40, 0xffc1c0c0, 0xfffefefe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe5e5e4, 0xff565354, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffdad9d9, 0xff504d4e, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff454243, 0xffcccacb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe5e4e4, 0xff565354, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff5e5c5c, 0xff211e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221d1e, 0xff504d4e, 0xffd6d6d6, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe5e4e4, 0xff565354, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe9e9ea, 0xff7d7b7b, 0xff2e2a2b, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff2a2627, 0xff726f6f, 0xffe2e2e2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe5e4e4, 0xff565354, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff6f5f6, 0xffa4a3a4, 0xff423e3f, 0xff1e1a1b, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1d191a, 0xff3c3839, 0xff9b9a9a, 0xfff3f2f2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe5e4e4, 0xff565354, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffefefe, 0xffcac9ca, 0xff666464, 0xff231e1f, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff211d1e, 0xff5d5b5b, 0xffc3c2c2, 0xfffbfbfb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe4e4e4, 0xff565354, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff0efef, 0xffa9a8a9, 0xff433f40, 0xff1c1718, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff1b1718, 0xff393637, 0xff9d9c9c, 0xffececec, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe4e4e4, 0xff565354, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffefefe, 0xffe3e1e1, 0xff7e7b7b, 0xff2f2b2c, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201b1d, 0xff2b2628, 0xff737171, 0xffdcdcdc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe4e4e4, 0xff565354, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffcccbcb, 0xff727070, 0xff363233, 0xff241f20, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff332f30, 0xff6b696a, 0xffc5c4c5, 0xfffdfdfd, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe4e4e4, 0xff565354, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffcac9ca, 0xff7d7a7b, 0xff484445, 0xff2b2728, 0xff201c1d, 0xff1f1b1c, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff1f1b1c, 0xff2a2627, 0xff444142, 0xff767374, 0xffc3c2c2, 0xfffcfbfb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe4e4e4, 0xff565254, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffdfcfd, 0xffdad9d9, 0xffa9a7a8, 0xff716e6f, 0xff413d3e, 0xff252122, 0xff1d191a, 0xff1b1718, 0xff1f1b1c, 0xff221d1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff201c1d, 0xff1c1819, 0xff1d1819, 0xff242021, 0xff3d3a3b, 0xff6c6a6b, 0xffa4a2a3, 0xffd6d5d6, 0xfff9fafa, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe4e4e4, 0xff565254, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff1f1f1, 0xffd5d3d3, 0xffb0aeaf, 0xff838182, 0xff575455, 0xff322e30, 0xff221d1f, 0xff1c1819, 0xff191516, 0xff1b1718, 0xff1e1a1b, 0xff1f1b1c, 0xff201c1d, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211c1d, 0xff201c1d, 0xff1f1b1c, 0xff1e1a1b, 0xff1b1718, 0xff191516, 0xff1b1718, 0xff201c1d, 0xff302d2d, 0xff545253, 0xff7f7d7d, 0xffadabab, 0xffd2d1d1, 0xffefefef, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe4e4e4, 0xff565253, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffdfdfd, 0xfff8f8f8, 0xffeeeeee, 0xffd8d7d7, 0xffb7b6b6, 0xff989697, 0xff7a7778, 0xff5d595a, 0xff444041, 0xff363334, 0xff2f2c2d, 0xff2c2829, 0xff2a2526, 0xff292627, 0xff2c2829, 0xff2f2b2c, 0xff363234, 0xff413e3f, 0xff5b5758, 0xff777576, 0xff959494, 0xffb5b4b4, 0xffd5d5d5, 0xffededed, 0xfff8f7f7, 0xfffdfdfd, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe4e4e3, 0xff565253, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff9f9f9, 0xfff0f0f0, 0xffececec, 0xffe7e7e7, 0xffdedede, 0xffd4d3d3, 0xffd3d2d2, 0xffdddddc, 0xffe7e6e6, 0xffebebeb, 0xffefefef, 0xfff8f8f8, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe4e4e4, 0xff555253, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe4e3e4, 0xff555253, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff545152, 0xffe3e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe4e3e4, 0xff555253, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211c1d, 0xff555252, 0xffe4e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe4e3e4, 0xff565253, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff524f50, 0xffe2e1e2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe2e1e2, 0xff524f50, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff484445, 0xffdad9d9, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffdad9d9, 0xff474445, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff3d3a3b, 0xffd0cfd0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffcfcfcf, 0xff3d3a3a, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff363233, 0xffc1bfc0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffbfbebe, 0xff343132, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff272324, 0xff9e9c9d, 0xfffdfdfd, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffcfcfc, 0xff9d9b9b, 0xff272223, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xff6d6a6b, 0xfff0f0f0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff0f0f0, 0xff6c696a, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff403d3e, 0xffd9d8d8, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffd9d8d8, 0xff403c3d, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff201c1d, 0xff969495, 0xfffcfcfc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffcfcfc, 0xff959394, 0xff201b1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff3e3a3b, 0xffdedddd, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffdddcdd, 0xff3d393a, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff807e7f, 0xfffbfbfb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffbfbfb, 0xff7e7c7c, 0xff1b1718, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff292526, 0xffa5a3a4, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffa2a1a1, 0xff282525, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff363233, 0xffb9b8b8, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffb6b4b5, 0xff343132, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff423e3f, 0xffb8b6b6, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffb3b2b2, 0xff3f3c3c, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff353132, 0xffa4a3a4, 0xfffbfbfb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffaf9fa, 0xffa09e9f, 0xff333031, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff292526, 0xff7c7979, 0xffd9d9d9, 0xfffbfbfb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffbfbfb, 0xffd7d5d6, 0xff777474, 0xff272324, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff1b1617, 0xff3a3636, 0xff8e8c8d, 0xffd1d0d0, 0xffebebeb, 0xfffbfbfb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffafafa, 0xffeaeaea, 0xffcecdce, 0xff8a8888, 0xff373333, 0xff1a1617, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff1f1a1c, 0xff393536, 0xff625f60, 0xff929090, 0xffb2b0b1, 0xffc2c0c1, 0xffcecece, 0xffd7d6d6, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd8d7d7, 0xffd7d6d6, 0xffcecdcd, 0xffc0bfc0, 0xffb1afb0, 0xff908e8e, 0xff605c5d, 0xff373334, 0xff1e1a1b, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff201c1d, 0xff1e1a1b, 0xff242021, 0xff2e2a2b, 0xff363233, 0xff3d393a, 0xff434041, 0xff454242, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454142, 0xff454242, 0xff434041, 0xff3c393a, 0xff363233, 0xff2e2a2b, 0xff231f20, 0xff1e1a1b, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff232021, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff232020, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff232020, 0xff232021, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff232021, 0xff232021, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff252122, 0xff252122, 0xff252122, 0xff262223, 0xff242021, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff393536, 0xffa1a0a0, 0xffb3b2b3, 0xffb1b0b0, 0xff726f70, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff4c4849, 0xffa9a7a7, 0xffb3b2b2, 0xffb2b0b0, 0xff5b5859, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff231f20, 0xff787576, 0xffb4b2b2, 0xffb4b2b3, 0xffa09e9f, 0xff312d2e, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff242021, 0xff8c8a8b, 0xffb5b3b3, 0xffb4b2b3, 0xff898788, 0xff2e2a2b, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff322e2f, 0xff807d7e, 0xff8d8b8c, 0xff8d8b8b, 0xff8e8c8d, 0xff625f60, 0xff262323, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff464343, 0xffebebeb, 0xffffffff, 0xffffffff, 0xffa09e9f, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff646162, 0xfff3f3f3, 0xffffffff, 0xffffffff, 0xff7c7a7b, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa9a7a7, 0xffffffff, 0xffffffff, 0xffe8e8e8, 0xff393536, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff252022, 0xffcac9ca, 0xffffffff, 0xffffffff, 0xffc5c4c5, 0xff343132, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1c1819, 0xff6b6869, 0xfff4f4f4, 0xffffffff, 0xffffffff, 0xffffffff, 0xffcbcaca, 0xff3b3839, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff454142, 0xffe5e5e5, 0xffffffff, 0xfffbfbfb, 0xff9b999a, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xffe2e2e2, 0xff383535, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c2c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff262223, 0xffacabab, 0xfffdfdfd, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff6f5f5, 0xff666364, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff464343, 0xffebebea, 0xffffffff, 0xffffffff, 0xffa09e9e, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xffe2e2e2, 0xff383535, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c3c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff4a4747, 0xffdddcdc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffa6a4a5, 0xff282425, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff393536, 0xffa4a2a3, 0xffb6b4b5, 0xffb4b2b3, 0xff727071, 0xff211e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xffe2e2e2, 0xff383535, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c3c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211e1f, 0xff7e7c7e, 0xfff6f6f6, 0xffffffff, 0xfff8f8f8, 0xffd8d7d7, 0xfffdfdfd, 0xffffffff, 0xffe4e3e3, 0xff413d3e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff242021, 0xff242021, 0xff241f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xffe2e2e2, 0xff383535, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c3c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff322e2f, 0xffb8b7b7, 0xffffffff, 0xffffffff, 0xffd7d7d7, 0xff656263, 0xfff0f0f0, 0xffffffff, 0xffffffff, 0xff7c797a, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xffe2e2e2, 0xff383535, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff211d1e, 0xff211c1d, 0xff211d1e, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c3c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff555353, 0xffe7e7e6, 0xffffffff, 0xffffffff, 0xff939292, 0xff2c2829, 0xffc3c1c2, 0xffffffff, 0xffffffff, 0xffc7c6c6, 0xff292627, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff221e1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff1d191a, 0xff211d1e, 0xff282425, 0xff343031, 0xff3b3738, 0xff3e3a3b, 0xff3a3738, 0xff353132, 0xff282425, 0xff201b1d, 0xff1f1b1c, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff1e1a1b, 0xff1f1a1b, 0xff242021, 0xff2e2a2b, 0xff383435, 0xff3d393a, 0xff3d393a, 0xff383536, 0xff2f2c2d, 0xff221f20, 0xff1e1a1b, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xffe2e2e2, 0xff383535, 0xff1f1a1c, 0xff1f1b1c, 0xff201c1d, 0xff2c282a, 0xff393637, 0xff3e3a3b, 0xff3c3839, 0xff312d2e, 0xff231f20, 0xff1f1b1c, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c3c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff1e1a1b, 0xff211d1e, 0xff2c292a, 0xff383535, 0xff3d3a3a, 0xff3e3a3b, 0xff373435, 0xff2b2728, 0xff201c1d, 0xff1f1b1c, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff252122, 0xff8d8b8c, 0xffffffff, 0xffffffff, 0xfff3f4f4, 0xff4d494b, 0xff201c1d, 0xff868485, 0xfffefefe, 0xffffffff, 0xfff9f8f8, 0xff585556, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff454243, 0xff8a8889, 0xff8b8989, 0xff8b898a, 0xff464344, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff565354, 0xff8d8b8c, 0xff8b8a89, 0xff848283, 0xff363233, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1f, 0xff373334, 0xff5f5c5d, 0xff878586, 0xffa8a7a7, 0xffbebcbd, 0xffcbc9ca, 0xffd0d0d0, 0xffcbcaca, 0xffbfbebe, 0xffa6a4a4, 0xff7b7879, 0xff3f3c3d, 0xff1e1a1b, 0xff221d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211c1d, 0xff332f30, 0xff7d7b7c, 0xff8a8888, 0xff898787, 0xff5b5858, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff282425, 0xff4a4647, 0xff727070, 0xff999797, 0xffb3b1b2, 0xffc5c4c4, 0xffcfcece, 0xffcfcdce, 0xffc6c5c5, 0xffb6b4b5, 0xff939292, 0xff5f5d5d, 0xff2b2728, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xffe2e2e2, 0xff373434, 0xff1a1617, 0xff3c3839, 0xff7d7b7b, 0xffaeadad, 0xffc7c6c7, 0xffd1d0d0, 0xffcccbcb, 0xffb9b8b8, 0xff8f8d8e, 0xff4d494a, 0xff1f1b1c, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c3c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff242021, 0xff514d4e, 0xff8a8788, 0xffb0aeaf, 0xffc5c4c4, 0xffcfcece, 0xffd0cfcf, 0xffc5c4c4, 0xffacabab, 0xff807d7e, 0xff423f40, 0xff1d1a1b, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff363233, 0xffcdcccc, 0xffffffff, 0xffffffff, 0xffbdbcbc, 0xff272324, 0xff201c1d, 0xff524f50, 0xffe3e2e3, 0xffffffff, 0xffffffff, 0xffa4a2a2, 0xff1e191a, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff4e4b4b, 0xffe1e0e0, 0xfffcfcfc, 0xfffefefe, 0xff9d9b9c, 0xff1e1a1b, 0xff231e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff282425, 0xffbab9b9, 0xfffefefe, 0xfffefefe, 0xffcccbcb, 0xff363233, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221d1f, 0xff7e7c7d, 0xffcfcece, 0xffeaeaea, 0xfff7f7f8, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffefefe, 0xfff5f5f5, 0xffd7d7d7, 0xff7c7a7b, 0xff221f20, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e191a, 0xff434041, 0xffdfdedf, 0xfff9f8f8, 0xfff5f5f5, 0xff989697, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff413e3e, 0xffabaaaa, 0xffdfdfdf, 0xfff1f1f1, 0xfffcfcfc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffbfbfb, 0xffebebeb, 0xffb4b3b3, 0xff454142, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xffe2e2e2, 0xff363334, 0xff585556, 0xffcac9c9, 0xfff5f4f5, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffafafa, 0xffdfdede, 0xff858283, 0xff252223, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c3c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xff393536, 0xff9f9d9d, 0xffe3e2e3, 0xfff9f8f9, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff6f5f6, 0xffd7d6d6, 0xff7c7a7a, 0xff252021, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff625f60, 0xfffbfbfb, 0xffffffff, 0xffffffff, 0xff757374, 0xff1f1b1c, 0xff221e1f, 0xff302c2d, 0xffb6b5b5, 0xffffffff, 0xffffffff, 0xffe3e3e3, 0xff3b3738, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff302c2d, 0xffb4b3b3, 0xffffffff, 0xffffffff, 0xffe2e2e2, 0xff363233, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff4d4a4b, 0xfff5f5f5, 0xffffffff, 0xffffffff, 0xff929090, 0xff252223, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff231f20, 0xffb7b7b7, 0xfffefefe, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff8f8f8, 0xfff3f3f4, 0xfff2f2f2, 0xfff6f6f6, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff8f8f8, 0xff949393, 0xff221d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff454142, 0xffe5e5e5, 0xffffffff, 0xfffbfbfb, 0xff9b9a9a, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff585556, 0xffe5e4e4, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffcfcfc, 0xfff5f6f5, 0xfff2f2f3, 0xfff3f3f3, 0xfffbfafb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffd8d7d7, 0xff484445, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xffe2e1e1, 0xff6b6869, 0xffdadada, 0xffffffff, 0xffffffff, 0xfff9faf9, 0xfff1f1f1, 0xfff2f2f2, 0xfffcfcfc, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff5f4f5, 0xff918f90, 0xff262122, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c3c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff444142, 0xffcdcccd, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff9f9f9, 0xfff3f3f3, 0xfff3f3f3, 0xfffcfcfc, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff4f3f4, 0xff929091, 0xff272324, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xffa9a8a9, 0xffffffff, 0xffffffff, 0xffe0dfdf, 0xff403c3d, 0xff221e1f, 0xff231f20, 0xff201c1d, 0xff7e7c7c, 0xfff5f5f5, 0xffffffff, 0xfffcfcfc, 0xff7b787a, 0xff1b1718, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff797878, 0xfff7f7f7, 0xffffffff, 0xffffffff, 0xff747272, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1c1819, 0xff949293, 0xffffffff, 0xffffffff, 0xffebeaeb, 0xff585455, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff231f20, 0xffb8b6b7, 0xfff7f7f7, 0xffd5d5d5, 0xff9c9b9b, 0xff6f6d6d, 0xff514e4f, 0xff413e3f, 0xff3e3a3b, 0xff4b4849, 0xff726f70, 0xffb6b5b5, 0xfff2f2f2, 0xffffffff, 0xffffffff, 0xfff5f5f5, 0xff6f6c6d, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff454142, 0xffe5e5e5, 0xffffffff, 0xfffbfbfb, 0xff9b999a, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff595656, 0xffe4e4e4, 0xffedecec, 0xffbbbaba, 0xff848282, 0xff5f5d5d, 0xff484445, 0xff3e3a3b, 0xff423e3f, 0xff5a5758, 0xff8e8c8d, 0xffd8d8d8, 0xfffdfdfd, 0xffffffff, 0xffffffff, 0xffc5c4c4, 0xff2e2a2b, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xfff0f0f0, 0xffd7d7d7, 0xffffffff, 0xffeeeded, 0xff9e9c9c, 0xff575354, 0xff3a3738, 0xff3d3a3b, 0xff646061, 0xffb7b5b5, 0xfff7f6f6, 0xffffffff, 0xffffffff, 0xfff0f0f0, 0xff716e6f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c3c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff3c3839, 0xffd1d0d1, 0xffffffff, 0xffffffff, 0xfffcfcfc, 0xffd7d6d6, 0xff8d8b8b, 0xff575455, 0xff413e3e, 0xff413e3f, 0xff5d5a5b, 0xffa2a0a0, 0xffedecec, 0xffffffff, 0xffffffff, 0xfff2f2f2, 0xff777575, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff403c3d, 0xffe9e9e9, 0xffffffff, 0xffffffff, 0xffa5a4a4, 0xff292525, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xff484546, 0xffdedddd, 0xffffffff, 0xfffefefe, 0xffbfbebe, 0xff2a2627, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff494546, 0xffd9d8d8, 0xffffffff, 0xffffffff, 0xffbcbbbc, 0xff242122, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff322e2f, 0xffd9dad9, 0xffffffff, 0xffffffff, 0xffbdbcbd, 0xff343132, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff262122, 0xff817f7f, 0xff6a6768, 0xff2d292a, 0xff1b1718, 0xff1a1517, 0xff1d191a, 0xff1f1b1c, 0xff1f1b1c, 0xff1e1a1b, 0xff1a1617, 0xff231f20, 0xff767274, 0xffe8e8e8, 0xffffffff, 0xffffffff, 0xffc7c5c6, 0xff332f31, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff454142, 0xffe5e5e5, 0xffffffff, 0xfffbfbfb, 0xff9b999a, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff494647, 0xff858383, 0xff484546, 0xff231e20, 0xff191516, 0xff1c1819, 0xff1e1a1b, 0xff1f1b1c, 0xff1f1b1c, 0xff1c1819, 0xff1b1718, 0xff3d393a, 0xffb0afaf, 0xfffbfbfb, 0xffffffff, 0xfffdfdfd, 0xff777576, 0xff1b1718, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe2e1e1, 0xff686666, 0xff1f1b1c, 0xff1c1819, 0xff1f1b1c, 0xff1f1b1c, 0xff1a1617, 0xff242021, 0xff8c8a8b, 0xfff6f6f6, 0xffffffff, 0xffffffff, 0xffcdcccc, 0xff3f3c3d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c3c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff282425, 0xffadabab, 0xffffffff, 0xffffffff, 0xfff8f7f8, 0xffa7a6a6, 0xff393637, 0xff1b1618, 0xff1c1819, 0xff1f1b1c, 0xff1f1b1c, 0xff1b1718, 0xff1b1718, 0xff605d5e, 0xffe0dfe0, 0xffffffff, 0xffffffff, 0xffd4d3d3, 0xff434041, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1c1819, 0xff838181, 0xffffffff, 0xffffffff, 0xfff5f5f5, 0xff686566, 0xff221f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff252223, 0xffaeadae, 0xfffdfdfd, 0xffffffff, 0xffe8e8e8, 0xff575455, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff282526, 0xffa9a8a8, 0xfffdfdfd, 0xffffffff, 0xffededed, 0xff4f4b4c, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff6b696a, 0xfffcfcfc, 0xffffffff, 0xfff9f9f9, 0xff858283, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff242021, 0xff221e1f, 0xff1c1819, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff1b1718, 0xff888687, 0xfffbfbfb, 0xffffffff, 0xffecebeb, 0xff625e60, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff454142, 0xffe5e5e5, 0xffffffff, 0xfffbfbfb, 0xff9b999a, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff241f21, 0xff1e1a1b, 0xff1d191a, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1c1819, 0xff3e3a3b, 0xffcfcece, 0xffffffff, 0xffffffff, 0xffbebdbe, 0xff272324, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xffffffff, 0xfff3f3f3, 0xff7e7b7c, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff221e20, 0xffa5a3a3, 0xffffffff, 0xffffffff, 0xfffcfcfc, 0xff7a7878, 0xff242021, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c3c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xff656262, 0xffeeeeee, 0xffffffff, 0xfffefefe, 0xffb6b4b5, 0xff302d2e, 0xff1d1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1a1516, 0xff686566, 0xfff6f6f6, 0xffffffff, 0xffffffff, 0xff807e7f, 0xff242021, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff2a2728, 0xffcecdcd, 0xffffffff, 0xffffffff, 0xffcecdcd, 0xff3e3b3b, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff6d6b6c, 0xfff6f6f6, 0xffffffff, 0xfffafafa, 0xff939292, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff6d6a6b, 0xfff2f2f2, 0xffffffff, 0xfffbfbfb, 0xff918e8f, 0xff1e1a1b, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff221e1f, 0xffb4b2b2, 0xffffffff, 0xffffffff, 0xffe0dfdf, 0xff504c4d, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff3a3637, 0xffe6e5e6, 0xffffffff, 0xfff9f9f9, 0xff898788, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff454142, 0xffe5e5e5, 0xffffffff, 0xfffbfbfb, 0xff9b999a, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1c1819, 0xff8f8c8d, 0xfffafafa, 0xffffffff, 0xffe0dfdf, 0xff423f40, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xfffefefe, 0xffc9c8c9, 0xff343031, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xff423e3f, 0xffe7e7e7, 0xffffffff, 0xffffffff, 0xffb9b8b8, 0xff2e2a2b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c3c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff282526, 0xffa9a7a7, 0xfffdfdfd, 0xffffffff, 0xffededed, 0xff545152, 0xff1b1718, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff252222, 0xffb5b4b3, 0xffffffff, 0xffffffff, 0xffbcbcbc, 0xff2e2a2b, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20,
+ 0xfd231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff5f5d5d, 0xfff8f8f8, 0xffffffff, 0xfffefefe, 0xff999798, 0xff272324, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff343132, 0xffdad9d9, 0xffffffff, 0xffffffff, 0xffcac9c9, 0xff3b3738, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff383435, 0xffd4d3d4, 0xffffffff, 0xffffffff, 0xffcac9c9, 0xff353132, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff484545, 0xffe5e5e5, 0xffffffff, 0xfffefefe, 0xffb4b2b2, 0xff2b2727, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff1d191a, 0xff191516, 0xff191516, 0xff1b1718, 0xff1c1819, 0xff1d191a, 0xff1d191a, 0xff1b1718, 0xff201b1c, 0xffc9c8c9, 0xffffffff, 0xffffffff, 0xffa4a3a3, 0xff292526, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff454142, 0xffe5e5e5, 0xffffffff, 0xfffbfbfb, 0xff9b999a, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff1b1718, 0xff181415, 0xff1a1517, 0xff1c1819, 0xff1d191a, 0xff1d191a, 0xff1d191a, 0xff130f10, 0xff686566, 0xfff6f6f6, 0xffffffff, 0xffededed, 0xff5d5a5a, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xfffbfbfb, 0xff8e8c8d, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xffaba9aa, 0xffffffff, 0xffffffff, 0xffe6e5e5, 0xff413f40, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c3c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff413e3f, 0xffd3d2d3, 0xffffffff, 0xffffffff, 0xffbfbebe, 0xff252122, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff757374, 0xffffffff, 0xffffffff, 0xffe4e4e4, 0xff3f3c3d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xfd231f20,
+ 0xf2231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff201b1c, 0xffa8a7a7, 0xffffffff, 0xffffffff, 0xffeaeaea, 0xff625f60, 0xff201b1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff999898, 0xffffffff, 0xffffffff, 0xffeeeeee, 0xff676466, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1a1b, 0xff999898, 0xfffdfdfd, 0xffffffff, 0xffebebeb, 0xff636161, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1d191b, 0xff858384, 0xfff8f7f7, 0xffffffff, 0xfff5f5f5, 0xff767475, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff2d292a, 0xff504d4e, 0xff767474, 0xff8e8c8d, 0xff989797, 0xffa09e9f, 0xffa1a0a0, 0xffa1a0a0, 0xffa09f9f, 0xffa1a0a0, 0xffe4e4e4, 0xffffffff, 0xffffffff, 0xffb1afb0, 0xff2e2b2c, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff454142, 0xffe5e5e5, 0xffffffff, 0xfffbfbfb, 0xff9b999a, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201b1c, 0xff221f20, 0xff3c3839, 0xff636061, 0xff838182, 0xff949292, 0xff9d9c9c, 0xffa1a0a0, 0xffa1a0a0, 0xffa1a0a0, 0xff9d9c9c, 0xffbdbcbc, 0xfffbfbfb, 0xffffffff, 0xfff1f1f1, 0xff6a6768, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xfff7f7f7, 0xff636060, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff7b7979, 0xffffffff, 0xffffffff, 0xfffcfcfc, 0xff5a5758, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c3c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff5c5959, 0xffe7e7e7, 0xffffffff, 0xffffffff, 0xff908e8f, 0xff171213, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff201c1d, 0xff1e1a1b, 0xff555253, 0xfffbfbfb, 0xffffffff, 0xfffafafa, 0xff514e4f, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xf2231f20,
+ 0xe5231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xff403d3e, 0xffdfdfdf, 0xffffffff, 0xffffffff, 0xffc8c7c7, 0xff353233, 0xff201b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1c1819, 0xff514f4f, 0xfff5f5f5, 0xffffffff, 0xffffffff, 0xffa19f9f, 0xff2a2627, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff555153, 0xfff2f1f1, 0xffffffff, 0xfffdfdfd, 0xff9d9b9b, 0xff272324, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff302c2d, 0xffc0bfbf, 0xffffffff, 0xffffffff, 0xffdcdcdc, 0xff3d3a3b, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff373334, 0xff888586, 0xffd3d2d2, 0xfff9f8f8, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffbab9b9, 0xff332f30, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff454142, 0xffe5e5e5, 0xffffffff, 0xfffbfbfb, 0xff9b999a, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff262223, 0xff5a5757, 0xffb0afaf, 0xffebeaea, 0xfffefefe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff3f3f3, 0xff747172, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xffebebeb, 0xff494647, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff5a5859, 0xfffdfdfd, 0xffffffff, 0xffffffff, 0xff737171, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c3c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff706e6f, 0xfff3f3f3, 0xffffffff, 0xffffffff, 0xffcdcccc, 0xffa6a4a4, 0xffaaa9a9, 0xffaaa8aa, 0xffaaa9a9, 0xffaaa9a9, 0xffaba9a9, 0xffaba9aa, 0xffabaaaa, 0xffababaa, 0xffacabaa, 0xffabaaab, 0xffbdbcbc, 0xfffcfcfc, 0xffffffff, 0xfffefeff, 0xff625e5f, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xe5231f20,
+ 0xd4231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff7d7a7b, 0xfff7f7f7, 0xffffffff, 0xfffafafa, 0xff959393, 0xff242021, 0xff282425, 0xff292526, 0xff292526, 0xff292526, 0xff292526, 0xff292526, 0xff272324, 0xff2b2728, 0xffc7c6c6, 0xffffffff, 0xffffffff, 0xffd9d8d8, 0xff433f40, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff252223, 0xffc5c3c4, 0xffffffff, 0xffffffff, 0xffd0d0d0, 0xff403d3e, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff5a5758, 0xffe8e7e7, 0xffffffff, 0xffffffff, 0xffa3a2a2, 0xff1e1a1b, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff565354, 0xffcfcece, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffefefe, 0xfff7f7f7, 0xfff1f1f1, 0xffeeedee, 0xffececec, 0xffecebeb, 0xffecebeb, 0xffecebeb, 0xfffaf9f9, 0xffffffff, 0xffffffff, 0xffbcbbbc, 0xff343031, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff454142, 0xffe5e5e5, 0xffffffff, 0xfffbfbfb, 0xff9b999a, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff2f2b2c, 0xff8f8d8d, 0xfff3f2f2, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffbfbfb, 0xfff4f4f4, 0xffefefef, 0xffededed, 0xffecebeb, 0xffecebeb, 0xffebeaeb, 0xfff1f1f1, 0xfffefefe, 0xffffffff, 0xfff4f4f4, 0xff787676, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xffe5e5e5, 0xff3e3b3b, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff4f4c4c, 0xfff8f8f8, 0xffffffff, 0xffffffff, 0xff827f80, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c3c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff7c7a7a, 0xfffbfafa, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff686565, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xd4231f20,
+ 0xb4231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff2e2a2b, 0xffbab8b9, 0xfffefefe, 0xffffffff, 0xfffafafa, 0xffbbb9ba, 0xff979696, 0xff9b9a9a, 0xff9b9a9a, 0xff9b9a9a, 0xff9b9a9a, 0xff9b9a9a, 0xff9b9a9a, 0xff9c9a9a, 0xff979696, 0xffcfcfcf, 0xffffffff, 0xffffffff, 0xfffefefe, 0xff757273, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1717, 0xff7a7778, 0xffffffff, 0xffffffff, 0xfff4f4f4, 0xff6d6a6b, 0xff231e1f, 0xff231f20, 0xff221e1f, 0xff252122, 0xff918f8f, 0xfffcfbfb, 0xffffffff, 0xfff7f7f7, 0xff5b5859, 0xff1b1718, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff494647, 0xffd3d2d2, 0xffffffff, 0xffffffff, 0xfff9f9f9, 0xffcccccc, 0xffa1a0a0, 0xff848383, 0xff726f70, 0xff676465, 0xff625f60, 0xff605d5e, 0xff5f5c5d, 0xff625e5f, 0xffd3d2d2, 0xffffffff, 0xffffffff, 0xffbcbbbb, 0xff343031, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff454142, 0xffe5e5e5, 0xffffffff, 0xfffbfbfb, 0xff9b999a, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff272324, 0xff858383, 0xfff8f8f8, 0xffffffff, 0xffffffff, 0xffe8e7e7, 0xffb6b5b5, 0xff929191, 0xff7b7879, 0xff6c6969, 0xff656263, 0xff615e5f, 0xff615e5e, 0xff5a5758, 0xff908e8e, 0xfff8f8f8, 0xffffffff, 0xfff4f4f4, 0xff777576, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xffe3e3e3, 0xff3b3838, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221d1e, 0xff4d4a4b, 0xfff6f6f6, 0xffffffff, 0xffffffff, 0xff848182, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c3c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff807d7e, 0xfffdfdfd, 0xffffffff, 0xffffffff, 0xffe9e8e8, 0xffdfdede, 0xffe0dfdf, 0xffe0dfdf, 0xffe0dfdf, 0xffe0dfdf, 0xffe0dfdf, 0xffe0dfdf, 0xffe0dfdf, 0xffe0dfdf, 0xffe0dfdf, 0xffe0dfdf, 0xffe0dfdf, 0xffe0dfdf, 0xffe1e0e0, 0xffe0e0e0, 0xff5e5b5c, 0xff211c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xb4231f20,
+ 0x8e231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff565354, 0xffe4e3e3, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffb9b8b8, 0xff2a2627, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff3a3738, 0xffe4e3e4, 0xffffffff, 0xffffffff, 0xffa8a6a7, 0xff2b2728, 0xff231f20, 0xff221e1f, 0xff3a3637, 0xffc7c6c6, 0xffffffff, 0xffffffff, 0xffcbcbcb, 0xff292527, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff272324, 0xff9b9999, 0xfffdfdfd, 0xffffffff, 0xfff9f8f8, 0xff949192, 0xff3d393a, 0xff262223, 0xff201c1d, 0xff1e1a1b, 0xff1e1a1b, 0xff1e191a, 0xff1d191a, 0xff1b1718, 0xff1f1b1c, 0xffc6c5c5, 0xffffffff, 0xffffffff, 0xffbcbbbb, 0xff343031, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff454142, 0xffe5e5e5, 0xffffffff, 0xfffbfbfb, 0xff9b999a, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff484445, 0xffdadada, 0xffffffff, 0xffffffff, 0xffd4d2d2, 0xff5c595a, 0xff2f2b2c, 0xff221e1f, 0xff1f1b1c, 0xff1e1a1b, 0xff1e1a1b, 0xff1d191a, 0xff1d191a, 0xff140f10, 0xff656363, 0xfff5f5f5, 0xffffffff, 0xfff4f4f4, 0xff777576, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xffe7e7e7, 0xff423e3f, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff534f50, 0xfffafbfb, 0xffffffff, 0xffffffff, 0xff7c797a, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c3c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff7b7879, 0xfffafafa, 0xffffffff, 0xffffffff, 0xff8c8a8a, 0xff484545, 0xff504d4e, 0xff504d4d, 0xff504d4d, 0xff504d4d, 0xff504d4d, 0xff504d4d, 0xff504d4d, 0xff504d4d, 0xff504d4d, 0xff504d4d, 0xff504d4d, 0xff504d4d, 0xff504d4e, 0xff504d4e, 0xff312e2e, 0xff221f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0x8e231f20,
+ 0x62231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff252122, 0xff8e8b8b, 0xfffcfbfb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff2f1f2, 0xff4d4a4b, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xffa2a1a1, 0xffffffff, 0xffffffff, 0xffe1e0e0, 0xff434041, 0xff221e1f, 0xff221e1f, 0xff625f5f, 0xfff1f1f1, 0xffffffff, 0xffffffff, 0xff818080, 0xff1b1718, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff3f3b3c, 0xffcfcecf, 0xffffffff, 0xffffffff, 0xffbdbcbc, 0xff292526, 0xff1f1b1c, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff292627, 0xffd8d7d7, 0xffffffff, 0xffffffff, 0xffbcbbbb, 0xff343031, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff454142, 0xffe5e5e5, 0xffffffff, 0xfffbfbfb, 0xff9b999a, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff232021, 0xff757273, 0xfffdfdfd, 0xffffffff, 0xfffafafa, 0xff5f5d5d, 0xff1e1a1b, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff787676, 0xfff7f7f7, 0xffffffff, 0xfff4f4f4, 0xff777576, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xfff1f1f1, 0xff545152, 0xff1b1718, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff686566, 0xffffffff, 0xffffffff, 0xffffffff, 0xff676566, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c3c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff6d6a6b, 0xfff1f1f1, 0xffffffff, 0xffffffff, 0xff858384, 0xff171213, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff211d1e, 0xff231e20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0x62231f20,
+ 0x2e231f20, 0xf0231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff393536, 0xffc6c5c5, 0xffffffff, 0xffffffff, 0xfff0f0f0, 0xffa6a4a5, 0xffa2a0a1, 0xffa3a1a1, 0xffa3a1a1, 0xffa3a1a1, 0xffa3a1a1, 0xffa3a1a1, 0xffa3a1a1, 0xffa3a1a1, 0xffa3a1a1, 0xffa3a1a1, 0xffa2a1a2, 0xffb6b4b4, 0xfff7f7f7, 0xffffffff, 0xffffffff, 0xff929192, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff5b5758, 0xfff9fafa, 0xffffffff, 0xffffffff, 0xff7a7878, 0xff211d1e, 0xff272324, 0xff9d9b9c, 0xffffffff, 0xffffffff, 0xffebeaea, 0xff3f3c3d, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff535051, 0xffe2e2e2, 0xffffffff, 0xffffffff, 0xff7f7d7d, 0xff1a1517, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff454142, 0xffededed, 0xffffffff, 0xffffffff, 0xffbcbbbb, 0xff343031, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff454142, 0xffe5e5e5, 0xffffffff, 0xfffbfbfb, 0xff9b999a, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff252122, 0xff979697, 0xffffffff, 0xffffffff, 0xffd5d5d6, 0xff312d2e, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff201b1c, 0xff9c9a9b, 0xfffbfbfb, 0xffffffff, 0xfff4f4f4, 0xff777576, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xfff9f9f9, 0xff747272, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201b1c, 0xff8f8d8e, 0xffffffff, 0xffffffff, 0xfff5f4f4, 0xff4d4a4b, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c3c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff555152, 0xffe3e2e2, 0xffffffff, 0xffffffff, 0xffb7b6b6, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xf0231f20, 0x2e231f20,
+ 0x11231f20, 0xc4231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221f20, 0xff605e5f, 0xfff1f1f1, 0xffffffff, 0xffffffff, 0xffacabab, 0xff1a1718, 0xff1c1819, 0xff1d191a, 0xff1d191a, 0xff1d191a, 0xff1d191a, 0xff1d191a, 0xff1d191a, 0xff1d191a, 0xff1d191a, 0xff1d191a, 0xff1d191a, 0xff353232, 0xffcccccc, 0xffffffff, 0xffffffff, 0xffdad9da, 0xff322e2f, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff312e2f, 0xffc9c8c8, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff292526, 0xff3c3839, 0xffdad9da, 0xffffffff, 0xffffffff, 0xffaba9aa, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff5e5b5c, 0xffeaeaea, 0xffffffff, 0xffffffff, 0xff6d6b6b, 0xff1b1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1b1718, 0xff7e7c7d, 0xfffefdfe, 0xffffffff, 0xffffffff, 0xffbcbbbb, 0xff343031, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff454142, 0xffe5e5e5, 0xffffffff, 0xfffbfbfb, 0xff9b999a, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff252223, 0xffa6a4a5, 0xffffffff, 0xffffffff, 0xffc6c4c4, 0xff2b2829, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff363233, 0xffcacaca, 0xffffffff, 0xffffffff, 0xfff4f4f4, 0xff777576, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xfffdfdfd, 0xffaaa9aa, 0xff231f20, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff2c2829, 0xffc9c7c8, 0xffffffff, 0xffffffff, 0xffd1d1d1, 0xff383435, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c3c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff383536, 0xffc6c5c6, 0xffffffff, 0xffffffff, 0xffe7e7e7, 0xff464344, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xc4231f20, 0x11231f20,
+ 0x04231f20, 0x8c231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff272324, 0xff9f9d9d, 0xffffffff, 0xffffffff, 0xfffefefe, 0xff646262, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff272324, 0xff959393, 0xffffffff, 0xffffffff, 0xffffffff, 0xff6d6a6b, 0xff1b1718, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff878586, 0xffffffff, 0xffffffff, 0xfff6f6f6, 0xff4d4a4a, 0xff6a6869, 0xffffffff, 0xffffffff, 0xfffbfbfb, 0xff656262, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff595657, 0xffe7e7e6, 0xffffffff, 0xffffffff, 0xff858384, 0xff181416, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xff393536, 0xffcdcccc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffbcbbbb, 0xff343031, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff454142, 0xffe5e5e5, 0xffffffff, 0xfffbfbfb, 0xff9b999a, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff252122, 0xffa09e9e, 0xffffffff, 0xffffffff, 0xffdad9d9, 0xff332f30, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff201c1d, 0xff777575, 0xfff2f2f2, 0xffffffff, 0xffffffff, 0xfff4f4f4, 0xff777576, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xffffffff, 0xffe0e0e0, 0xff4f4c4d, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1c1819, 0xff686566, 0xfffbfbfb, 0xffffffff, 0xffffffff, 0xff9c9b9b, 0xff272324, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c3c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xff908f8f, 0xfffafafa, 0xffffffff, 0xfffcfcfc, 0xffa09e9e, 0xff262223, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0x8c231f20, 0x04231f20,
+ 0x01231f20, 0x49231f20, 0xf4231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff3d3a3b, 0xffdddddd, 0xffffffff, 0xffffffff, 0xffd8d7d7, 0xff322e2f, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221d1e, 0xff605d5e, 0xffececec, 0xffffffff, 0xffffffff, 0xffb9b7b8, 0xff221e20, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff504c4d, 0xffe6e5e5, 0xffffffff, 0xffffffff, 0xff9c9a9b, 0xffb4b2b2, 0xffffffff, 0xffffffff, 0xffd0cfcf, 0xff373334, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff474344, 0xffd8d7d7, 0xffffffff, 0xffffffff, 0xffcbcaca, 0xff322e2f, 0xff1b1718, 0xff211d1e, 0xff221e1f, 0xff221e1f, 0xff211d1e, 0xff1c1819, 0xff2f2b2c, 0xffa09e9f, 0xfffbfbfb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffbcbbbb, 0xff343031, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff454142, 0xffe5e5e5, 0xffffffff, 0xfffbfbfb, 0xff9b999a, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff242021, 0xff828081, 0xffffffff, 0xffffffff, 0xfffdfdfd, 0xff737171, 0xff1b1617, 0xff1f1b1c, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff1f1b1c, 0xff1f1b1c, 0xff575555, 0xffd7d6d6, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff4f4f4, 0xff777576, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xffffffff, 0xfffefefe, 0xffafaeaf, 0xff343132, 0xff1d191a, 0xff211d1e, 0xff221e1f, 0xff221e1f, 0xff201c1d, 0xff1a1617, 0xff474344, 0xffd5d4d4, 0xffffffff, 0xffffffff, 0xffebeaea, 0xff5b5858, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c3c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xff454343, 0xffd9d8d9, 0xffffffff, 0xffffffff, 0xffefefef, 0xff828081, 0xff2a2627, 0xff1c1819, 0xff201c1d, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff201c1d, 0xff1e191b, 0xff1c1819, 0xff272424, 0xff524f50, 0xff4b4848, 0xff242021, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xf4231f20, 0x49231f20, 0x01231f20,
+ 0x00000000, 0x1c231f20, 0xc3231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xff757273, 0xffffffff, 0xffffffff, 0xffffffff, 0xff969495, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff393537, 0xffc7c6c6, 0xffffffff, 0xffffffff, 0xffececec, 0xff4c4949, 0xff1c1819, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff302c2d, 0xffb4b3b3, 0xffffffff, 0xffffffff, 0xffeeedee, 0xfff3f3f3, 0xffffffff, 0xffffffff, 0xff918f90, 0xff262223, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff2d292a, 0xffafadae, 0xffffffff, 0xffffffff, 0xfffbfbfb, 0xffacabab, 0xff434041, 0xff211d1e, 0xff1d191a, 0xff1e1a1b, 0xff262223, 0xff504d4e, 0xffadabab, 0xfff7f7f7, 0xfffbfbfb, 0xfff2f2f2, 0xffffffff, 0xffffffff, 0xffbcbbbb, 0xff343031, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff454142, 0xffe5e5e5, 0xffffffff, 0xfffbfbfb, 0xff9b999a, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff555252, 0xffeaeae9, 0xffffffff, 0xffffffff, 0xffe3e2e2, 0xff726f70, 0xff2b2828, 0xff1e1a1b, 0xff1d191a, 0xff201b1c, 0xff332f30, 0xff777475, 0xffd8d7d7, 0xffffffff, 0xfff3f2f2, 0xfffdfdfd, 0xffffffff, 0xfff4f4f4, 0xff777576, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xfffafafa, 0xfff7f8f8, 0xfffbfbfb, 0xffafaeae, 0xff4c494a, 0xff242021, 0xff1d191a, 0xff1e1a1b, 0xff282425, 0xff615e5f, 0xffcbcacb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffa3a1a2, 0xff2c2829, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c3c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1a1b, 0xff726f70, 0xfff5f5f5, 0xffffffff, 0xffffffff, 0xfff0efef, 0xffa9a7a7, 0xff5a5757, 0xff2d2a2b, 0xff211c1d, 0xff1e1a1b, 0xff1f1b1c, 0xff211d1e, 0xff2a2627, 0xff434041, 0xff706d6e, 0xffaba9aa, 0xffe1e1e1, 0xff868384, 0xff252122, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xc3231f20, 0x1c231f20, 0x00000000,
+ 0x00000000, 0x06231f20, 0x7c231f20, 0xfc231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff262223, 0xffc0bebf, 0xffffffff, 0xffffffff, 0xfff5f4f4, 0xff575455, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff231f20, 0xff949293, 0xfffafafa, 0xffffffff, 0xfffbfbfb, 0xff908e8e, 0xff1c1819, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff7a7879, 0xfff6f5f6, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe9e9e9, 0xff595657, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201b1c, 0xff605e5e, 0xffebeaea, 0xffffffff, 0xffffffff, 0xfffbfbfb, 0xffdfdedf, 0xffb4b3b3, 0xff9b9999, 0xffa1a0a0, 0xffc0bfbf, 0xffe6e6e6, 0xfffdfdfd, 0xffffffff, 0xffa5a2a3, 0xffc8c6c7, 0xffffffff, 0xffffffff, 0xffbcbbbb, 0xff343031, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff454142, 0xffe5e5e5, 0xffffffff, 0xfffbfbfb, 0xff9b999a, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f5f, 0xffedecec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff2d292a, 0xffa3a1a1, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff1f1f1, 0xffcbcbcb, 0xffa4a3a3, 0xff9a9999, 0xffadabac, 0xffd4d3d3, 0xfff3f3f3, 0xffffffff, 0xffdfdfdf, 0xff9e9c9d, 0xfff6f6f6, 0xffffffff, 0xfff4f4f4, 0xff777576, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xffe6e5e5, 0xffa09f9e, 0xfffcfcfc, 0xfffdfdfd, 0xffe4e4e4, 0xffbbbaba, 0xff9f9d9d, 0xffa3a0a2, 0xffc5c4c4, 0xffececec, 0xfffefefe, 0xffffffff, 0xffffffff, 0xffcccbcb, 0xff433f40, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242022, 0xffc4c2c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff333031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff242021, 0xff807e7e, 0xfff9f8f8, 0xffffffff, 0xffffffff, 0xfffcfcfc, 0xffececec, 0xffd0d0d0, 0xffb2b0b0, 0xffa4a1a2, 0xffa6a3a5, 0xffb5b3b4, 0xffcdcccd, 0xffe2e1e1, 0xfff3f3f3, 0xfffdfdfd, 0xffffffff, 0xff8b8a8a, 0xff242121, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xfc231f20, 0x7c231f20, 0x06231f20, 0x00000000,
+ 0x00000000, 0x00000000, 0x32231f20, 0xd8231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e191a, 0xff514e4f, 0xfff7f7f7, 0xffffffff, 0xffffffff, 0xffc5c4c5, 0xff332f30, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff5c5a5a, 0xffebebeb, 0xffffffff, 0xffffffff, 0xffcdcdcd, 0xff343032, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff484546, 0xffdbdada, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffbdbcbd, 0xff343132, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xff807e7f, 0xfff2f2f2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffdfdfd, 0xffabaaaa, 0xff363233, 0xffc1bfc0, 0xffffffff, 0xffffffff, 0xffbcbcbb, 0xff343031, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff454142, 0xffe5e5e5, 0xffffffff, 0xfffbfbfb, 0xff9b9a9a, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1d191a, 0xff615f60, 0xffededec, 0xffffffff, 0xfffafafa, 0xff797778, 0xff1a1617, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff3e3b3c, 0xffc0bebf, 0xfffdfdfe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe7e6e6, 0xff666364, 0xff656263, 0xfff5f5f5, 0xffffffff, 0xfff4f4f4, 0xff787576, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff232021, 0xffa5a3a3, 0xfffefefe, 0xffffffff, 0xffe2e2e2, 0xff464244, 0xff9e9d9d, 0xfffbfbfb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffd1cfcf, 0xff4b4849, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242122, 0xffc5c4c4, 0xffffffff, 0xffffffff, 0xffc0bfbf, 0xff343031, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff231f20, 0xff696767, 0xffdddddd, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff9f9f9, 0xff7d7b7c, 0xff252122, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xd8231f20, 0x32231f20, 0x00000000, 0x00000000,
+ 0x00231f20, 0x00000000, 0x05231f20, 0x8e231f20, 0xfa231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1c1819, 0xff7f7d7d, 0xffe1e0e1, 0xffdbdbdb, 0xffdedede, 0xff7f7d7e, 0xff252122, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff302d2e, 0xffb2b1b1, 0xffdcdbdb, 0xffdbdbdb, 0xffcccccc, 0xff555253, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff282425, 0xff9b9999, 0xffdbdbdb, 0xffdbdbdb, 0xffdbdbdb, 0xffd9d8d9, 0xff7b797a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff656263, 0xffc7c6c7, 0xffeeeeee, 0xfff7f6f6, 0xfff8f8f8, 0xfff8f8f8, 0xfff6f6f6, 0xfff0f0f0, 0xffd4d3d3, 0xff838181, 0xff2b2728, 0xff211d1e, 0xffa7a5a6, 0xffe0dfdf, 0xffdedddd, 0xffa3a2a2, 0xff312d2e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xff3f3b3c, 0xffc5c4c4, 0xffdcdcdc, 0xffd9d9d9, 0xff888586, 0xff211d1e, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xff575455, 0xffcfcdcf, 0xffdbdbdb, 0xffdbd9da, 0xff6b696a, 0xff1b1718, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff363333, 0xff999797, 0xffe0dfe0, 0xfff5f4f4, 0xfff8f7f7, 0xfff9f8f8, 0xfff8f8f8, 0xfff5f5f5, 0xffe7e6e7, 0xffb6b5b5, 0xff535052, 0xff181415, 0xff595556, 0xffd4d3d3, 0xffdbdbdb, 0xffd4d4d4, 0xff696668, 0xff1e1a1b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff231f20, 0xff8f8d8e, 0xffdcdbdb, 0xffdddcdc, 0xffc3c2c2, 0xff322f30, 0xff272425, 0xff828080, 0xffd6d6d6, 0xfff1f1f1, 0xfff7f7f7, 0xfff9f9f9, 0xfff8f8f8, 0xfff5f5f5, 0xffe3e3e3, 0xff9e9d9d, 0xff393536, 0xff1d191a, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff242021, 0xffaaa8a9, 0xffdedede, 0xffdddcdc, 0xffa6a4a5, 0xff312d2e, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1e1a1b, 0xff3c3839, 0xff918f8f, 0xffd3d2d3, 0xffededed, 0xfff5f5f5, 0xfff8f8f8, 0xfff9f9f9, 0xfff8f8f8, 0xfff7f6f6, 0xfff4f3f3, 0xffe8e8e8, 0xffd0cece, 0xff9e9c9c, 0xff5c5959, 0xff2b2829, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xfa231f20, 0x8e231f20, 0x05231f20, 0x00000000, 0x00231f20,
+ 0x00000000, 0x00231f20, 0x00000000, 0x30231f20, 0xd8231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff322e2f, 0xff373435, 0xff363334, 0xff363334, 0xff292526, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff302b2c, 0xff373334, 0xff363334, 0xff363334, 0xff2c2829, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff2c2829, 0xff363334, 0xff363334, 0xff363334, 0xff353233, 0xff282526, 0xff231e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1c1819, 0xff2b2829, 0xff585556, 0xff7b7878, 0xff8a8888, 0xff8b8989, 0xff7b797a, 0xff5e5b5b, 0xff343132, 0xff1d191a, 0xff201c1d, 0xff231f20, 0xff302d2e, 0xff373335, 0xff373334, 0xff312d2e, 0xff242021, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff262223, 0xff343132, 0xff373334, 0xff363334, 0xff2d2a2b, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff292526, 0xff353132, 0xff363334, 0xff363334, 0xff2a2728, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff1f1a1b, 0xff403d3e, 0xff6b6869, 0xff848283, 0xff8c8a8a, 0xff868384, 0xff6f6d6d, 0xff4b4748, 0xff242122, 0xff1d191a, 0xff221e1f, 0xff292526, 0xff363233, 0xff373334, 0xff363233, 0xff2a2728, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff2e2a2b, 0xff373334, 0xff373334, 0xff343131, 0xff252122, 0xff201c1d, 0xff1d191a, 0xff373334, 0xff625f60, 0xff807e7e, 0xff8c8a8b, 0xff888686, 0xff6f6c6d, 0xff433f40, 0xff1f1b1c, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff312e2f, 0xff373334, 0xff373334, 0xff312d2e, 0xff242021, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff1d191a, 0xff322e2f, 0xff565354, 0xff737172, 0xff878485, 0xff8d8b8b, 0xff888687, 0xff7d7b7c, 0xff676464, 0xff4d494a, 0xff2d292a, 0xff1d191a, 0xff1c1819, 0xff221d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xd8231f20, 0x30231f20, 0x00000000, 0x00231f20, 0x00000000,
+ 0x00000000, 0x00231f20, 0x00000000, 0x00000000, 0x73231f20, 0xfb231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff1c1819, 0xff1c1819, 0xff1e1a1b, 0xff1e1a1b, 0xff1d181a, 0xff1b1718, 0xff1f1b1c, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff1f1b1c, 0xff1f1b1c, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff221d1e, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1e1a1b, 0xff1b1718, 0xff1d191a, 0xff1e1a1b, 0xff1d191a, 0xff1b1718, 0xff1d191a, 0xff211d1e, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff1f1b1c, 0xff1f1b1c, 0xff1f1b1c, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff211d1e, 0xff1f1b1c, 0xff1f1b1c, 0xff201b1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff1b1718, 0xff1d191a, 0xff1e1a1b, 0xff1e1a1b, 0xff1c1718, 0xff1d191a, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff201c1d, 0xff1f1b1c, 0xff1f1b1c, 0xff201c1d, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff1f1b1c, 0xff1c1718, 0xff1c1819, 0xff1e191a, 0xff1f1a1b, 0xff1e1a1b, 0xff1d1819, 0xff1b1718, 0xff1d191a, 0xff201c1d, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xfb231f20, 0x73231f20, 0x00000000, 0x00000000, 0x00231f20, 0x00000000,
+ 0x00000000, 0x00000000, 0x00231f20, 0x00000000, 0x0e231f20, 0xb5231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff221e1f, 0xff221e1f, 0xff221e1f, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xb5231f20, 0x0e231f20, 0x00000000, 0x00231f20, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x2a231f20, 0xde231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xde231f20, 0x2a231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00231f20, 0x00000000, 0x51231f20, 0xf4231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xf4231f20, 0x51231f20, 0x00000000, 0x00231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00231f20, 0x03231f20, 0x74231f20, 0xf5231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xf5231f20, 0x74231f20, 0x03231f20, 0x00231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00231f20, 0x00000000, 0x0a231f20, 0x84231f20, 0xf5231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xf5231f20, 0x84231f20, 0x0a231f20, 0x00000000, 0x00231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x10231f20, 0x84231f20, 0xf5231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xf5231f20, 0x84231f20, 0x10231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00231f20, 0x00000000, 0x00000000, 0x0a231f20, 0x72231f20, 0xf4231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xf4231f20, 0x72231f20, 0x0a231f20, 0x00000000, 0x00000000, 0x00231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00231f20, 0x00000000, 0x00000000, 0x03231f20, 0x4f231f20, 0xdd231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xdd231f20, 0x4f231f20, 0x03231f20, 0x00000000, 0x00000000, 0x00231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00231f20, 0x00231f20, 0x00000000, 0x29231f20, 0xb6231f20, 0xfb231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xfb231f20, 0xb6231f20, 0x29231f20, 0x00000000, 0x00231f20, 0x00231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00231f20, 0x00000000, 0x0e231f20, 0x73231f20, 0xd8231f20, 0xfb231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xfb231f20, 0xd8231f20, 0x73231f20, 0x0e231f20, 0x00000000, 0x00231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x30231f20, 0x8e231f20, 0xd6231f20, 0xfd231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xfd231f20, 0xd6231f20, 0x8e231f20, 0x30231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00231f20, 0x00000000, 0x00000000, 0x04231f20, 0x32231f20, 0x7b231f20, 0xc2231f20, 0xf3231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xf3231f20, 0xc2231f20, 0x7b231f20, 0x32231f20, 0x04231f20, 0x00000000, 0x00000000, 0x00231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00231f20, 0x00231f20, 0x00000000, 0x00000000, 0x06231f20, 0x1c231f20, 0x49231f20, 0x8c231f20, 0xc4231f20, 0xf0231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xf0231f20, 0xc4231f20, 0x8c231f20, 0x49231f20, 0x1c231f20, 0x06231f20, 0x00000000, 0x00000000, 0x00231f20, 0x00231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00231f20, 0x00000000, 0x00000000, 0x00000000, 0x01231f20, 0x04231f20, 0x11231f20, 0x2e231f20, 0x62231f20, 0x8e231f20, 0xb4231f20, 0xd4231f20, 0xe5231f20, 0xf2231f20, 0xfd231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xff231f20, 0xfd231f20, 0xf2231f20, 0xe5231f20, 0xd4231f20, 0xb4231f20, 0x8e231f20, 0x62231f20, 0x2e231f20, 0x11231f20, 0x04231f20, 0x01231f20, 0x00000000, 0x00000000, 0x00000000, 0x00231f20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
+};
diff --git a/src/frontend/mame/ui/devctrl.h b/src/frontend/mame/ui/devctrl.h
new file mode 100644
index 00000000000..44cdb6d8ede
--- /dev/null
+++ b/src/frontend/mame/ui/devctrl.h
@@ -0,0 +1,153 @@
+// license:BSD-3-Clause
+// copyright-holders:Nathan Woods
+/***************************************************************************
+
+ ui/devctrl.h
+
+ Device specific control menu
+ This source provides a base class for any device which need a specific
+ submenu and which can occur multiple times in the same driver (at the
+ moment, cassette tapes and barcode readers, in future possibly other like
+ printers)
+ The base class contains calls to get the total number of devices of
+ the same kind connected to the driver, and shortcuts to switch current
+ device to next one or previous one attached. This allows, for instance,
+ users to pass from a device to another one by simply pressing left/right
+ and the menu is rebuilt accordingly, without the need of a preliminary
+ submenu listing available devices of the same kind.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_DEVCTRL_H__
+#define __UI_DEVCTRL_H__
+
+template<class _DeviceType>
+class ui_menu_device_control : public ui_menu
+{
+public:
+ ui_menu_device_control(running_machine &machine, render_container *container, _DeviceType *device);
+
+protected:
+ _DeviceType *current_device() { return m_device; }
+ int count() { return m_count; }
+
+ int current_index();
+ void previous();
+ void next();
+ std::string current_display_name();
+ UINT32 current_display_flags();
+
+private:
+ // device iterator
+ typedef device_type_iterator<&device_creator<_DeviceType>, _DeviceType> iterator;
+
+ _DeviceType * m_device;
+ int m_count;
+};
+
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+template<class _DeviceType>
+ui_menu_device_control<_DeviceType>::ui_menu_device_control(running_machine &machine, render_container *container, _DeviceType *device)
+ : ui_menu(machine, container)
+{
+ iterator iter(machine.root_device());
+ m_count = iter.count();
+ m_device = device ? device : iter.first();
+}
+
+
+//-------------------------------------------------
+// current_index
+//-------------------------------------------------
+
+template<class _DeviceType>
+int ui_menu_device_control<_DeviceType>::current_index()
+{
+ iterator iter(machine().root_device());
+ return iter.indexof(*m_device);
+}
+
+
+//-------------------------------------------------
+// previous
+//-------------------------------------------------
+
+template<class _DeviceType>
+void ui_menu_device_control<_DeviceType>::previous()
+{
+ // left arrow - rotate left through cassette devices
+ if (m_device != nullptr)
+ {
+ iterator iter(machine().root_device());
+ int index = iter.indexof(*m_device);
+ if (index > 0)
+ index--;
+ else
+ index = m_count - 1;
+ m_device = iter.byindex(index);
+ }
+}
+
+
+//-------------------------------------------------
+// next
+//-------------------------------------------------
+
+template<class _DeviceType>
+void ui_menu_device_control<_DeviceType>::next()
+{
+ // right arrow - rotate right through cassette devices
+ if (m_device != nullptr)
+ {
+ iterator iter(machine().root_device());
+ int index = iter.indexof(*m_device);
+ if (index < m_count - 1)
+ index++;
+ else
+ index = 0;
+ m_device = iter.byindex(index);
+ }
+}
+
+
+//-------------------------------------------------
+// current_display_name
+//-------------------------------------------------
+
+template<class _DeviceType>
+std::string ui_menu_device_control<_DeviceType>::current_display_name()
+{
+ std::string display_name;
+ display_name.assign(current_device()->name());
+ if (count() > 1)
+ display_name.append(string_format("%d", current_index() + 1));
+ return display_name;
+}
+
+
+//-------------------------------------------------
+// current_display_flags
+//-------------------------------------------------
+
+template<class _DeviceType>
+UINT32 ui_menu_device_control<_DeviceType>::current_display_flags()
+{
+ UINT32 flags = 0;
+ if (count() > 1)
+ {
+ if (current_index() > 0)
+ flags |= MENU_FLAG_LEFT_ARROW;
+ if (current_index() < count() - 1)
+ flags |= MENU_FLAG_RIGHT_ARROW;
+ }
+ return flags;
+}
+
+
+#endif /* __UI_DEVCTRL_H__ */
diff --git a/src/frontend/mame/ui/devopt.cpp b/src/frontend/mame/ui/devopt.cpp
new file mode 100644
index 00000000000..de145a41b4a
--- /dev/null
+++ b/src/frontend/mame/ui/devopt.cpp
@@ -0,0 +1,279 @@
+// license:BSD-3-Clause
+// copyright-holders:Nathan Woods
+/*********************************************************************
+
+ ui/devopt.cpp
+
+ Internal menu for the device configuration.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "ui/ui.h"
+#include "ui/menu.h"
+#include "ui/devopt.h"
+
+/*-------------------------------------------------
+ ui_device_config - handle the game information
+ menu
+ -------------------------------------------------*/
+
+ui_menu_device_config::ui_menu_device_config(running_machine &machine, render_container *container, device_slot_interface *slot, device_slot_option *option) : ui_menu(machine, container)
+{
+ m_option = option;
+ m_owner = slot;
+ m_mounted = slot->device().subdevice(option->name()) != nullptr;
+}
+
+void ui_menu_device_config::populate()
+{
+ std::ostringstream str;
+ device_t *dev;
+
+ util::stream_format(str, "[This option is%s currently mounted in the running system]\n\n", m_mounted ? "" : " NOT");
+ util::stream_format(str, "Option: %s\n", m_option->name());
+
+ dev = const_cast<machine_config &>(machine().config()).device_add(&machine().config().root_device(), m_option->name(), m_option->devtype(), 0);
+
+ util::stream_format(str, "Device: %s\n", dev->name());
+ if (!m_mounted)
+ str << "\nIf you select this option, the following items will be enabled:\n";
+ else
+ str << "\nThe selected option enables the following items:\n";
+
+ // loop over all CPUs
+ execute_interface_iterator execiter(*dev);
+ if (execiter.count() > 0)
+ {
+ str << "* CPU:\n";
+ std::unordered_set<std::string> exectags;
+ for (device_execute_interface &exec : execiter)
+ {
+ if (!exectags.insert(exec.device().tag()).second)
+ continue;
+
+ // get cpu specific clock that takes internal multiplier/dividers into account
+ int clock = exec.device().clock();
+
+ // count how many identical CPUs we have
+ int count = 1;
+ const char *name = exec.device().name();
+ for (device_execute_interface &scan : execiter)
+ {
+ if (exec.device().type() == scan.device().type() && strcmp(name, scan.device().name()) == 0 && exec.device().clock() == scan.device().clock())
+ if (exectags.insert(scan.device().tag()).second)
+ count++;
+ }
+
+ // if more than one, prepend a #x in front of the CPU name
+ if (count > 1)
+ util::stream_format(str, " %d" UTF8_MULTIPLY, count);
+ else
+ str << " ";
+ str << name;
+
+ // display clock in kHz or MHz
+ if (clock >= 1000000)
+ util::stream_format(str, " %d.%06d" UTF8_NBSP "MHz\n", clock / 1000000, clock % 1000000);
+ else
+ util::stream_format(str, " %d.%03d" UTF8_NBSP "kHz\n", clock / 1000, clock % 1000);
+ }
+ }
+
+ // display screen information
+ screen_device_iterator scriter(*dev);
+ if (scriter.count() > 0)
+ {
+ str << "* Video:\n";
+ for (screen_device &screen : scriter)
+ {
+ util::stream_format(str, " Screen '%s': ", screen.tag());
+
+ if (screen.screen_type() == SCREEN_TYPE_VECTOR)
+ str << "Vector\n";
+ else
+ {
+ const rectangle &visarea = screen.visible_area();
+
+ util::stream_format(str, "%d " UTF8_MULTIPLY " %d (%s) %f" UTF8_NBSP "Hz\n",
+ visarea.width(), visarea.height(),
+ (machine().system().flags & ORIENTATION_SWAP_XY) ? "V" : "H",
+ ATTOSECONDS_TO_HZ(screen.frame_period().attoseconds()));
+ }
+ }
+ }
+
+ // loop over all sound chips
+ sound_interface_iterator snditer(*dev);
+ if (snditer.count() > 0)
+ {
+ str << "* Sound:\n";
+ std::unordered_set<std::string> soundtags;
+ for (device_sound_interface &sound : snditer)
+ {
+ if (!soundtags.insert(sound.device().tag()).second)
+ continue;
+
+ // count how many identical sound chips we have
+ int count = 1;
+ for (device_sound_interface &scan : snditer)
+ {
+ if (sound.device().type() == scan.device().type() && sound.device().clock() == scan.device().clock())
+ if (soundtags.insert(scan.device().tag()).second)
+ count++;
+ }
+ // if more than one, prepend a #x in front of the CPU name
+ if (count > 1)
+ util::stream_format(str," %d" UTF8_MULTIPLY, count);
+ else
+ str << " ";
+ str << sound.device().name();
+
+ // display clock in kHz or MHz
+ int clock = sound.device().clock();
+ if (clock >= 1000000)
+ util::stream_format(str," %d.%06d" UTF8_NBSP "MHz\n", clock / 1000000, clock % 1000000);
+ else if (clock != 0)
+ util::stream_format(str," %d.%03d" UTF8_NBSP "kHz\n", clock / 1000, clock % 1000);
+ else
+ str << '\n';
+ }
+ }
+
+ // scan for BIOS settings
+ int bios = 0;
+ if (dev->rom_region())
+ {
+ std::string bios_str;
+ // first loop through roms in search of default bios (shortname)
+ for (const rom_entry *rom = dev->rom_region(); !ROMENTRY_ISEND(rom); rom++)
+ if (ROMENTRY_ISDEFAULT_BIOS(rom))
+ bios_str.assign(ROM_GETNAME(rom));
+
+ // then loop again to count bios options and to get the default bios complete name
+ for (const rom_entry *rom = dev->rom_region(); !ROMENTRY_ISEND(rom); rom++)
+ {
+ if (ROMENTRY_ISSYSTEM_BIOS(rom))
+ {
+ bios++;
+ if (bios_str.compare(ROM_GETNAME(rom))==0)
+ bios_str.assign(ROM_GETHASHDATA(rom));
+ }
+ }
+
+ if (bios)
+ util::stream_format(str, "* BIOS settings:\n %d options [default: %s]\n", bios, bios_str.c_str());
+ }
+
+ int input = 0, input_mj = 0, input_hana = 0, input_gamble = 0, input_analog = 0, input_adjust = 0;
+ int input_keypad = 0, input_keyboard = 0, dips = 0, confs = 0;
+ std::string errors;
+ std::ostringstream dips_opt, confs_opt;
+ ioport_list portlist;
+ for (device_t &iptdev : device_iterator(*dev))
+ portlist.append(iptdev, errors);
+
+ // check if the device adds inputs to the system
+ for (ioport_port &port : portlist)
+ for (ioport_field &field : port.fields())
+ {
+ if (field.type() >= IPT_MAHJONG_FIRST && field.type() < IPT_MAHJONG_LAST)
+ input_mj++;
+ else if (field.type() >= IPT_HANAFUDA_FIRST && field.type() < IPT_HANAFUDA_LAST)
+ input_hana++;
+ else if (field.type() >= IPT_GAMBLING_FIRST && field.type() < IPT_GAMBLING_LAST)
+ input_gamble++;
+ else if (field.type() >= IPT_ANALOG_FIRST && field.type() < IPT_ANALOG_LAST)
+ input_analog++;
+ else if (field.type() == IPT_ADJUSTER)
+ input_adjust++;
+ else if (field.type() == IPT_KEYPAD)
+ input_keypad++;
+ else if (field.type() == IPT_KEYBOARD)
+ input_keyboard++;
+ else if (field.type() >= IPT_START1 && field.type() < IPT_UI_FIRST)
+ input++;
+ else if (field.type() == IPT_DIPSWITCH)
+ {
+ dips++;
+ dips_opt << " " << field.name();
+ for (ioport_setting &setting : field.settings())
+ {
+ if (setting.value() == field.defvalue())
+ {
+ util::stream_format(dips_opt, " [default: %s]\n", setting.name());
+ break;
+ }
+ }
+ }
+ else if (field.type() == IPT_CONFIG)
+ {
+ confs++;
+ confs_opt << " " << field.name();
+ for (ioport_setting &setting : field.settings())
+ {
+ if (setting.value() == field.defvalue())
+ {
+ util::stream_format(confs_opt, " [default: %s]\n", setting.name());
+ break;
+ }
+ }
+ }
+ }
+
+ if (dips)
+ str << "* Dispwitch settings:\n" << dips_opt.str();
+ if (confs)
+ str << "* Configuration settings:\n" << confs_opt.str();
+ if (input + input_mj + input_hana + input_gamble + input_analog + input_adjust + input_keypad + input_keyboard)
+ str << "* Input device(s):\n";
+ if (input)
+ util::stream_format(str, " User inputs [%d inputs]\n", input);
+ if (input_mj)
+ util::stream_format(str, " Mahjong inputs [%d inputs]\n", input_mj);
+ if (input_hana)
+ util::stream_format(str, " Hanafuda inputs [%d inputs]\n", input_hana);
+ if (input_gamble)
+ util::stream_format(str, " Gambling inputs [%d inputs]\n", input_gamble);
+ if (input_analog)
+ util::stream_format(str, " Analog inputs [%d inputs]\n", input_analog);
+ if (input_adjust)
+ util::stream_format(str, " Adjuster inputs [%d inputs]\n", input_adjust);
+ if (input_keypad)
+ util::stream_format(str, " Keypad inputs [%d inputs]\n", input_keypad);
+ if (input_keyboard)
+ util::stream_format(str, " Keyboard inputs [%d inputs]\n", input_keyboard);
+
+ image_interface_iterator imgiter(*dev);
+ if (imgiter.count() > 0)
+ {
+ str << "* Media Options:\n";
+ for (const device_image_interface &imagedev : imgiter)
+ util::stream_format(str, " %s [tag: %s]\n", imagedev.image_type_name(), imagedev.device().tag());
+ }
+
+ slot_interface_iterator slotiter(*dev);
+ if (slotiter.count() > 0)
+ {
+ str << "* Slot Options:\n";
+ for (const device_slot_interface &slot : slotiter)
+ util::stream_format(str, " %s [default: %s]\n", slot.device().tag(), slot.default_option() ? slot.default_option() : "----");
+ }
+
+ if ((execiter.count() + scriter.count() + snditer.count() + imgiter.count() + slotiter.count() + bios + dips + confs
+ + input + input_mj + input_hana + input_gamble + input_analog + input_adjust + input_keypad + input_keyboard) == 0)
+ str << "[None]\n";
+
+ const_cast<machine_config &>(machine().config()).device_remove(&machine().config().root_device(), m_option->name());
+ item_append(str.str().c_str(), nullptr, MENU_FLAG_MULTILINE, nullptr);
+}
+
+void ui_menu_device_config::handle()
+{
+ /* process the menu */
+ process(0);
+}
+
+ui_menu_device_config::~ui_menu_device_config()
+{
+}
diff --git a/src/frontend/mame/ui/devopt.h b/src/frontend/mame/ui/devopt.h
new file mode 100644
index 00000000000..56916aebb54
--- /dev/null
+++ b/src/frontend/mame/ui/devopt.h
@@ -0,0 +1,30 @@
+// license:BSD-3-Clause
+// copyright-holders:Nathan Woods
+/***************************************************************************
+
+ ui/devopt.h
+
+ Internal menu for the device configuration.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_DEVOPT_H__
+#define __UI_DEVOPT_H__
+
+class ui_menu_device_config : public ui_menu {
+public:
+ ui_menu_device_config(running_machine &machine, render_container *container, device_slot_interface *slot, device_slot_option *option);
+ virtual ~ui_menu_device_config();
+ virtual void populate() override;
+ virtual void handle() override;
+
+private:
+ device_slot_interface *m_owner;
+ device_slot_option *m_option;
+ bool m_mounted;
+};
+
+
+#endif /* __UI_DEVOPT_H__ */
diff --git a/src/frontend/mame/ui/dirmenu.cpp b/src/frontend/mame/ui/dirmenu.cpp
new file mode 100644
index 00000000000..9ec3205f134
--- /dev/null
+++ b/src/frontend/mame/ui/dirmenu.cpp
@@ -0,0 +1,665 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/*********************************************************************
+
+ ui/dirmenu.cpp
+
+ Internal UI user interface.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "emuopts.h"
+#include "ui/ui.h"
+#include "ui/menu.h"
+#include "ui/dirmenu.h"
+#include "ui/datfile.h"
+#include "ui/utils.h"
+#include "ui/optsmenu.h"
+
+static int ADDING = 1;
+static int CHANGE = 2;
+
+struct folders_entry
+{
+ const char *name;
+ const char *option;
+ const int action;
+};
+
+static const folders_entry s_folders[] =
+{
+ { __("ROMs"), OPTION_MEDIAPATH, ADDING },
+ { __("UI"), OPTION_UI_PATH, CHANGE },
+ { __("Language"), OPTION_LANGUAGEPATH, CHANGE },
+ { __("Samples"), OPTION_SAMPLEPATH, ADDING },
+ { __("DATs"), OPTION_HISTORY_PATH, ADDING },
+ { __("INIs"), OPTION_INIPATH, ADDING },
+ { __("Extra INIs"), OPTION_EXTRAINI_PATH, CHANGE },
+ { __("Icons"), OPTION_ICONS_PATH, ADDING },
+ { __("Cheats"), OPTION_CHEATPATH, ADDING },
+ { __("Snapshots"), OPTION_SNAPSHOT_DIRECTORY, ADDING },
+ { __("Cabinets"), OPTION_CABINETS_PATH, ADDING },
+ { __("Flyers"), OPTION_FLYERS_PATH, ADDING },
+ { __("Titles"), OPTION_TITLES_PATH, ADDING },
+ { __("Ends"), OPTION_ENDS_PATH, ADDING },
+ { __("PCBs"), OPTION_PCBS_PATH, ADDING },
+ { __("Marquees"), OPTION_MARQUEES_PATH, ADDING },
+ { __("Controls Panels"), OPTION_CPANELS_PATH, ADDING },
+ { __("Crosshairs"), OPTION_CROSSHAIRPATH, ADDING },
+ { __("Artworks"), OPTION_ARTPATH, ADDING },
+ { __("Bosses"), OPTION_BOSSES_PATH, ADDING },
+ { __("Artworks Preview"), OPTION_ARTPREV_PATH, ADDING },
+ { __("Select"), OPTION_SELECT_PATH, ADDING },
+ { __("GameOver"), OPTION_GAMEOVER_PATH, ADDING },
+ { __("HowTo"), OPTION_HOWTO_PATH, ADDING },
+ { __("Logos"), OPTION_LOGOS_PATH, ADDING },
+ { __("Scores"), OPTION_SCORES_PATH, ADDING },
+ { __("Versus"), OPTION_VERSUS_PATH, ADDING },
+ { __("Covers"), OPTION_COVER_PATH, ADDING }
+};
+
+
+/**************************************************
+ MENU DIRECTORY
+**************************************************/
+//-------------------------------------------------
+// ctor / dtor
+//-------------------------------------------------
+
+ui_menu_directory::ui_menu_directory(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+ui_menu_directory::~ui_menu_directory()
+{
+ save_ui_options(machine());
+ ui_globals::reset = true;
+ mame_machine_manager::instance()->datfile().reset_run();
+}
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_menu_directory::handle()
+{
+ // process the menu
+ const ui_menu_event *m_event = process(0);
+
+ if (m_event != nullptr && m_event->itemref != nullptr && m_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_display_actual>(machine(), container, selected));
+}
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_directory::populate()
+{
+ for (auto & elem : s_folders)
+ item_append(_(elem.name), nullptr, 0, (void *)(FPTR)elem.action);
+
+ item_append(ui_menu_item_type::SEPARATOR);
+ customtop = mame_machine_manager::instance()->ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER;
+}
+
+//-------------------------------------------------
+// perform our special rendering
+//-------------------------------------------------
+
+void ui_menu_directory::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ float width;
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+
+ // get the size of the text
+ mui.draw_text_full(container, _("Folders Setup"), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += (2.0f * UI_BOX_LR_BORDER) + 0.01f;
+ float maxwidth = MAX(width, origx2 - origx1);
+
+ // compute our bounds
+ float x1 = 0.5f - 0.5f * maxwidth;
+ float x2 = x1 + maxwidth;
+ float y1 = origy1 - top;
+ float y2 = origy1 - UI_BOX_TB_BORDER;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ mui.draw_text_full(container, _("Folders Setup"), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+}
+
+/**************************************************
+ MENU DISPLAY PATH
+**************************************************/
+//-------------------------------------------------
+// ctor / dtor
+//-------------------------------------------------
+
+ui_menu_display_actual::ui_menu_display_actual(running_machine &machine, render_container *container, int ref)
+ : ui_menu(machine, container), m_ref(ref)
+{
+}
+
+ui_menu_display_actual::~ui_menu_display_actual()
+{
+}
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_menu_display_actual::handle()
+{
+ // process the menu
+ const ui_menu_event *m_event = process(0);
+ if (m_event != nullptr && m_event->itemref != nullptr && m_event->iptkey == IPT_UI_SELECT)
+ switch ((FPTR)m_event->itemref)
+ {
+ case REMOVE:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_remove_folder>(machine(), container, m_ref));
+ break;
+
+ case ADD_CHANGE:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_add_change_folder>(machine(), container, m_ref));
+ break;
+ }
+}
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_display_actual::populate()
+{
+ m_tempbuf = string_format(_("Current %1$s Folders"), _(s_folders[m_ref].name));
+ if (mame_machine_manager::instance()->ui().options().exists(s_folders[m_ref].option))
+ m_searchpath.assign(mame_machine_manager::instance()->ui().options().value(s_folders[m_ref].option));
+ else
+ m_searchpath.assign(machine().options().value(s_folders[m_ref].option));
+
+ path_iterator path(m_searchpath.c_str());
+ std::string curpath;
+ m_folders.clear();
+ while (path.next(curpath, nullptr))
+ m_folders.push_back(curpath);
+
+ item_append((s_folders[m_ref].action == CHANGE) ? _("Change Folder") : _("Add Folder"), nullptr, 0, (void *)ADD_CHANGE);
+
+ if (m_folders.size() > 1)
+ item_append(_("Remove Folder"), nullptr, 0, (void *)REMOVE);
+
+ item_append(ui_menu_item_type::SEPARATOR);
+ customtop = (m_folders.size() + 1) * mame_machine_manager::instance()->ui().get_line_height() + 6.0f * UI_BOX_TB_BORDER;
+}
+
+//-------------------------------------------------
+// perform our special rendering
+//-------------------------------------------------
+
+void ui_menu_display_actual::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ float width, maxwidth = origx2 - origx1;
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+ float lineh = mui.get_line_height();
+
+ for (auto & elem : m_folders)
+ {
+ mui.draw_text_full(container, elem.c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_LEFT, WRAP_TRUNCATE, DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += (2.0f * UI_BOX_LR_BORDER) + 0.01f;
+ maxwidth = MAX(maxwidth, width);
+ }
+
+ // get the size of the text
+ mui.draw_text_full(container, m_tempbuf.c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE, DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += (2.0f * UI_BOX_LR_BORDER) + 0.01f;
+ maxwidth = MAX(width, maxwidth);
+
+ // compute our bounds
+ float x1 = 0.5f - 0.5f * maxwidth;
+ float x2 = x1 + maxwidth;
+ float y1 = origy1 - top;
+ float y2 = y1 + lineh + 2.0f * UI_BOX_TB_BORDER;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ mui.draw_text_full(container, m_tempbuf.c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+
+ // compute our bounds
+ x1 = 0.5f - 0.5f * maxwidth;
+ x2 = x1 + maxwidth;
+ y1 = y2 + 2.0f * UI_BOX_TB_BORDER;
+ y2 = origy1 - UI_BOX_TB_BORDER;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ for (auto & elem : m_folders)
+ {
+ mui.draw_text_full(container, elem.c_str(), x1, y1, x2 - x1, JUSTIFY_LEFT, WRAP_TRUNCATE,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+ y1 += lineh;
+ }
+
+}
+
+/**************************************************
+MENU ADD FOLDER
+**************************************************/
+//-------------------------------------------------
+// ctor / dtor
+//-------------------------------------------------
+
+ui_menu_add_change_folder::ui_menu_add_change_folder(running_machine &machine, render_container *container, int ref) : ui_menu(machine, container)
+{
+ m_ref = ref;
+ m_change = (s_folders[ref].action == CHANGE);
+ m_search[0] = '\0';
+
+ // configure the starting path
+ osd_get_full_path(m_current_path, ".");
+
+ std::string searchpath;
+ if (mame_machine_manager::instance()->ui().options().exists(s_folders[m_ref].option))
+ searchpath = mame_machine_manager::instance()->ui().options().value(s_folders[m_ref].option);
+ else
+ searchpath = machine.options().value(s_folders[m_ref].option);
+
+ path_iterator path(searchpath.c_str());
+ std::string curpath;
+ while (path.next(curpath, nullptr))
+ m_folders.push_back(curpath);
+}
+
+ui_menu_add_change_folder::~ui_menu_add_change_folder()
+{
+}
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_menu_add_change_folder::handle()
+{
+ // process the menu
+ const ui_menu_event *m_event = process(0);
+
+ if (m_event != nullptr && m_event->itemref != nullptr)
+ {
+ if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ int index = (FPTR)m_event->itemref - 1;
+ const ui_menu_item &pitem = item[index];
+
+ // go up to the parent path
+ if (!strcmp(pitem.text, ".."))
+ {
+ size_t first_sep = m_current_path.find_first_of(PATH_SEPARATOR[0]);
+ size_t last_sep = m_current_path.find_last_of(PATH_SEPARATOR[0]);
+ if (first_sep != last_sep)
+ m_current_path.erase(++last_sep);
+ }
+ else
+ {
+ // if isn't a drive, appends the directory
+ if (strcmp(pitem.subtext, "[DRIVE]") != 0)
+ {
+ if (m_current_path[m_current_path.length() - 1] == PATH_SEPARATOR[0])
+ m_current_path.append(pitem.text);
+ else
+ m_current_path.append(PATH_SEPARATOR).append(pitem.text);
+ }
+ else
+ m_current_path = pitem.text;
+ }
+
+ // reset the char buffer also in this case
+ if (m_search[0] != 0)
+ m_search[0] = '\0';
+ reset(UI_MENU_RESET_SELECT_FIRST);
+ }
+ else if (m_event->iptkey == IPT_SPECIAL)
+ {
+ int buflen = strlen(m_search);
+ bool update_selected = FALSE;
+
+ // if it's a backspace and we can handle it, do so
+ if ((m_event->unichar == 8 || m_event->unichar == 0x7f) && buflen > 0)
+ {
+ *(char *)utf8_previous_char(&m_search[buflen]) = 0;
+ update_selected = TRUE;
+ }
+ // if it's any other key and we're not maxed out, update
+ else if (m_event->unichar >= ' ' && m_event->unichar < 0x7f)
+ {
+ buflen += utf8_from_uchar(&m_search[buflen], ARRAY_LENGTH(m_search) - buflen, m_event->unichar);
+ m_search[buflen] = 0;
+ update_selected = TRUE;
+ }
+ // Tab key, save current path
+ else if (m_event->unichar == 0x09)
+ {
+ std::string error_string;
+ if (m_change)
+ {
+ if (mame_machine_manager::instance()->ui().options().exists(s_folders[m_ref].option))
+ mame_machine_manager::instance()->ui().options().set_value(s_folders[m_ref].option, m_current_path.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
+ else if (strcmp(machine().options().value(s_folders[m_ref].option), m_current_path.c_str()) != 0)
+ {
+ machine().options().set_value(s_folders[m_ref].option, m_current_path.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
+ machine().options().mark_changed(s_folders[m_ref].option);
+ }
+ mame_machine_manager::instance()->datfile().reset_run();
+ }
+ else
+ {
+ m_folders.push_back(m_current_path);
+ std::string tmppath;
+ for (int x = 0; x < m_folders.size(); ++x)
+ {
+ tmppath.append(m_folders[x]);
+ if (x != m_folders.size() - 1)
+ tmppath.append(";");
+ }
+
+ if (mame_machine_manager::instance()->ui().options().exists(s_folders[m_ref].option))
+ mame_machine_manager::instance()->ui().options().set_value(s_folders[m_ref].option, tmppath.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
+ else if (strcmp(machine().options().value(s_folders[m_ref].option), tmppath.c_str()) != 0)
+ {
+ machine().options().set_value(s_folders[m_ref].option, tmppath.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
+ machine().options().mark_changed(s_folders[m_ref].option);
+ }
+ }
+
+ ui_menu::menu_stack->parent->reset(UI_MENU_RESET_SELECT_FIRST);
+ ui_menu::stack_pop(machine());
+ }
+
+ // check for entries which matches our search buffer
+ if (update_selected)
+ {
+ const int cur_selected = selected;
+ int entry, bestmatch = 0;
+
+ // from current item to the end
+ for (entry = cur_selected; entry < item.size(); entry++)
+ if (item[entry].ref != nullptr && m_search[0] != 0)
+ {
+ int match = 0;
+ for (int i = 0; i < ARRAY_LENGTH(m_search); i++)
+ {
+ if (core_strnicmp(item[entry].text, m_search, i) == 0)
+ match = i;
+ }
+
+ if (match > bestmatch)
+ {
+ bestmatch = match;
+ selected = entry;
+ }
+ }
+
+ // and from the first item to current one
+ for (entry = 0; entry < cur_selected; entry++)
+ {
+ if (item[entry].ref != nullptr && m_search[0] != 0)
+ {
+ int match = 0;
+ for (int i = 0; i < ARRAY_LENGTH(m_search); i++)
+ {
+ if (core_strnicmp(item[entry].text, m_search, i) == 0)
+ match = i;
+ }
+
+ if (match > bestmatch)
+ {
+ bestmatch = match;
+ selected = entry;
+ }
+ }
+ }
+ top_line = selected - (visible_lines / 2);
+ }
+ }
+ else if (m_event->iptkey == IPT_UI_CANCEL)
+ {
+ // reset the char buffer also in this case
+ if (m_search[0] != 0)
+ m_search[0] = '\0';
+ }
+ }
+}
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_add_change_folder::populate()
+{
+ // open a path
+ const char *volume_name = nullptr;
+ file_enumerator path(m_current_path.c_str());
+ const osd_directory_entry *dirent;
+ int folders_count = 0;
+
+ // add the drives
+ for (int i = 0; (volume_name = osd_get_volume_name(i)) != nullptr; ++i)
+ item_append(volume_name, "[DRIVE]", 0, (void *)(FPTR)++folders_count);
+
+ // add the directories
+ while ((dirent = path.next()) != nullptr)
+ {
+ if (dirent->type == ENTTYPE_DIR && strcmp(dirent->name, ".") != 0)
+ item_append(dirent->name, "[DIR]", 0, (void *)(FPTR)++folders_count);
+ }
+
+ item_append(ui_menu_item_type::SEPARATOR);
+
+ // configure the custom rendering
+ customtop = 2.0f * mame_machine_manager::instance()->ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER;
+ custombottom = 1.0f * mame_machine_manager::instance()->ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER;
+}
+
+//-------------------------------------------------
+// perform our special rendering
+//-------------------------------------------------
+
+void ui_menu_add_change_folder::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ float width, maxwidth = origx2 - origx1;
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+ std::string tempbuf[2];
+ tempbuf[0] = string_format(
+ (m_change)
+ ? _("Change %1$s Folder - Search: %2$s_")
+ : _("Add %1$s Folder - Search: %2$s_"),
+ _(s_folders[m_ref].name),
+ m_search);
+ tempbuf[1] = m_current_path;
+
+ // get the size of the text
+ for (auto & elem : tempbuf)
+ {
+ mui.draw_text_full(container, elem.c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += (2.0f * UI_BOX_LR_BORDER) + 0.01f;
+ maxwidth = MAX(width, maxwidth);
+ }
+
+ // compute our bounds
+ float x1 = 0.5f - 0.5f * maxwidth;
+ float x2 = x1 + maxwidth;
+ float y1 = origy1 - top;
+ float y2 = origy1 - UI_BOX_TB_BORDER;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ for (auto & elem : tempbuf)
+ {
+ mui.draw_text_full(container, elem.c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+ y1 = y1 + mui.get_line_height();
+ }
+
+ // bottom text
+ tempbuf[0] = _("Press TAB to set");
+
+ mui.draw_text_full(container, tempbuf[0].c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += 2 * UI_BOX_LR_BORDER;
+ maxwidth = MAX(maxwidth, width);
+
+ // compute our bounds
+ x1 = 0.5f - 0.5f * maxwidth;
+ x2 = x1 + maxwidth;
+ y1 = origy2 + UI_BOX_TB_BORDER;
+ y2 = origy2 + bottom;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_RED_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ mui.draw_text_full(container, tempbuf[0].c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+
+}
+
+/**************************************************
+ MENU REMOVE FOLDER
+**************************************************/
+//-------------------------------------------------
+// ctor / dtor
+//-------------------------------------------------
+
+ui_menu_remove_folder::ui_menu_remove_folder(running_machine &machine, render_container *container, int ref) : ui_menu(machine, container)
+{
+ m_ref = ref;
+ if (mame_machine_manager::instance()->ui().options().exists(s_folders[m_ref].option))
+ m_searchpath.assign(mame_machine_manager::instance()->ui().options().value(s_folders[m_ref].option));
+ else
+ m_searchpath.assign(machine.options().value(s_folders[m_ref].option));
+
+ path_iterator path(m_searchpath.c_str());
+ std::string curpath;
+ while (path.next(curpath, nullptr))
+ m_folders.push_back(curpath);
+}
+
+ui_menu_remove_folder::~ui_menu_remove_folder()
+{
+}
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_menu_remove_folder::handle()
+{
+ // process the menu
+ const ui_menu_event *m_event = process(0);
+ if (m_event != nullptr && m_event->itemref != nullptr && m_event->iptkey == IPT_UI_SELECT)
+ {
+ std::string tmppath, error_string;
+ m_folders.erase(m_folders.begin() + selected);
+ for (int x = 0; x < m_folders.size(); ++x)
+ {
+ tmppath.append(m_folders[x]);
+ if (x < m_folders.size() - 1)
+ tmppath.append(";");
+ }
+
+ if (mame_machine_manager::instance()->ui().options().exists(s_folders[m_ref].option))
+ mame_machine_manager::instance()->ui().options().set_value(s_folders[m_ref].option, tmppath.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
+ else if (strcmp(machine().options().value(s_folders[m_ref].option),tmppath.c_str())!=0)
+ {
+ machine().options().set_value(s_folders[m_ref].option, tmppath.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
+ machine().options().mark_changed(s_folders[m_ref].option);
+ }
+
+ ui_menu::menu_stack->parent->reset(UI_MENU_RESET_REMEMBER_REF);
+ ui_menu::stack_pop(machine());
+ }
+}
+
+//-------------------------------------------------
+// populate menu
+//-------------------------------------------------
+
+void ui_menu_remove_folder::populate()
+{
+ int folders_count = 0;
+ for (auto & elem : m_folders)
+ item_append(elem.c_str(), nullptr, 0, (void *)(FPTR)++folders_count);
+
+ item_append(ui_menu_item_type::SEPARATOR);
+ customtop = mame_machine_manager::instance()->ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER;
+}
+
+//-------------------------------------------------
+// perform our special rendering
+//-------------------------------------------------
+
+void ui_menu_remove_folder::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ float width;
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+ std::string tempbuf = string_format(_("Remove %1$s Folder"), _(s_folders[m_ref].name));
+
+ // get the size of the text
+ mui.draw_text_full(container, tempbuf.c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_NEVER, DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += (2.0f * UI_BOX_LR_BORDER) + 0.01f;
+ float maxwidth = MAX(width, origx2 - origx1);
+
+ // compute our bounds
+ float x1 = 0.5f - 0.5f * maxwidth;
+ float x2 = x1 + maxwidth;
+ float y1 = origy1 - top;
+ float y2 = origy1 - UI_BOX_TB_BORDER;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ mui.draw_text_full(container, tempbuf.c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER, DRAW_NORMAL,
+ UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+}
diff --git a/src/frontend/mame/ui/dirmenu.h b/src/frontend/mame/ui/dirmenu.h
new file mode 100644
index 00000000000..6b68764b258
--- /dev/null
+++ b/src/frontend/mame/ui/dirmenu.h
@@ -0,0 +1,97 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/***************************************************************************
+
+ ui/dirmenu.h
+
+ Internal UI user interface.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_DIRMENU_H__
+#define __UI_DIRMENU_H__
+
+//-------------------------------------------------
+// class directory menu
+//-------------------------------------------------
+
+class ui_menu_directory : public ui_menu
+{
+public:
+ ui_menu_directory(running_machine &machine, render_container *container);
+ virtual ~ui_menu_directory();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+};
+
+//-------------------------------------------------
+// class directory specific menu
+//-------------------------------------------------
+
+class ui_menu_display_actual : public ui_menu
+{
+public:
+ ui_menu_display_actual(running_machine &machine, render_container *container, int selectedref);
+ virtual ~ui_menu_display_actual();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+private:
+ std::string m_tempbuf, m_searchpath;
+ std::vector<std::string> m_folders;
+ int m_ref;
+
+ enum
+ {
+ ADD_CHANGE = 1,
+ REMOVE,
+ };
+};
+
+//-------------------------------------------------
+// class remove folder menu
+//-------------------------------------------------
+
+class ui_menu_remove_folder : public ui_menu
+{
+public:
+ ui_menu_remove_folder(running_machine &machine, render_container *container, int ref);
+ virtual ~ui_menu_remove_folder();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+private:
+ std::string m_searchpath;
+ int m_ref;
+ std::vector<std::string> m_folders;
+};
+
+//-------------------------------------------------
+// class add / change folder menu
+//-------------------------------------------------
+
+class ui_menu_add_change_folder : public ui_menu
+{
+public:
+ ui_menu_add_change_folder(running_machine &machine, render_container *container, int ref);
+ virtual ~ui_menu_add_change_folder();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+ virtual bool menu_has_search_active() override { return (m_search[0] != 0); }
+
+private:
+ int m_ref;
+ std::string m_current_path;
+ char m_search[40];
+ bool m_change;
+ std::vector<std::string> m_folders;
+};
+
+#endif /* __UI_DIRMENU_H__ */
diff --git a/src/frontend/mame/ui/filemngr.cpp b/src/frontend/mame/ui/filemngr.cpp
new file mode 100644
index 00000000000..a0400e234bb
--- /dev/null
+++ b/src/frontend/mame/ui/filemngr.cpp
@@ -0,0 +1,218 @@
+// license:BSD-3-Clause
+// copyright-holders:Nathan Woods
+/*********************************************************************
+
+ ui/filemngr.cpp
+
+ MESS's clunky built-in file manager
+
+ TODO
+ - Restrict directory listing by file extension
+
+*********************************************************************/
+
+#include "emu.h"
+#include "ui/ui.h"
+#include "ui/menu.h"
+#include "ui/filemngr.h"
+#include "ui/filesel.h"
+#include "ui/miscmenu.h"
+#include "ui/imgcntrl.h"
+#include "ui/floppycntrl.h"
+#include "softlist.h"
+
+
+/***************************************************************************
+ FILE MANAGER
+***************************************************************************/
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+ui_menu_file_manager::ui_menu_file_manager(running_machine &machine, render_container *container, const char *warnings) : ui_menu(machine, container), selected_device(nullptr)
+{
+ // This warning string is used when accessing from the force_file_manager call, i.e.
+ // when the file manager is loaded top front in the case of mandatory image devices
+ if (warnings)
+ m_warnings.assign(warnings);
+ else
+ m_warnings.clear();
+
+ m_curr_selected = FALSE;
+}
+
+
+//-------------------------------------------------
+// dtor
+//-------------------------------------------------
+
+ui_menu_file_manager::~ui_menu_file_manager()
+{
+}
+
+
+//-------------------------------------------------
+// custom_render - perform our special rendering
+//-------------------------------------------------
+
+void ui_menu_file_manager::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ const char *path;
+
+ // access the path
+ path = selected_device ? selected_device->filename() : nullptr;
+ extra_text_render(container, top, bottom,
+ origx1, origy1, origx2, origy2, nullptr, path);
+}
+
+
+void ui_menu_file_manager::fill_image_line(device_image_interface *img, std::string &instance, std::string &filename)
+{
+ // get the image type/id
+ instance = string_format("%s (%s)", img->instance_name(), img->brief_instance_name());
+
+ // get the base name
+ if (img->basename() != nullptr)
+ {
+ filename.assign(img->basename());
+
+ // if the image has been loaded through softlist, also show the loaded part
+ if (img->part_entry() != nullptr)
+ {
+ const software_part *tmp = img->part_entry();
+ if (tmp->name() != nullptr)
+ {
+ filename.append(" (");
+ filename.append(tmp->name());
+ // also check if this part has a specific part_id (e.g. "Map Disc", "Bonus Disc", etc.), and in case display it
+ if (img->get_feature("part_id") != nullptr)
+ {
+ filename.append(": ");
+ filename.append(img->get_feature("part_id"));
+ }
+ filename.append(")");
+ }
+ }
+ }
+ else
+ filename.assign("---");
+}
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_file_manager::populate()
+{
+ std::string tmp_inst, tmp_name;
+ bool first_entry = true;
+
+ if (!m_warnings.empty())
+ {
+ item_append(m_warnings.c_str(), nullptr, MENU_FLAG_DISABLE, nullptr);
+ item_append("", nullptr, MENU_FLAG_DISABLE, nullptr);
+ }
+
+ // cycle through all devices for this system
+ std::unordered_set<std::string> devtags;
+ for (device_t &dev : device_iterator(machine().root_device()))
+ {
+ bool tag_appended = false;
+ if (!devtags.insert(dev.tag()).second)
+ continue;
+
+ // check whether it owns an image interface
+ image_interface_iterator subiter(dev);
+ if (subiter.first() != nullptr)
+ {
+ // if so, cycle through all its image interfaces
+ for (device_image_interface &scan : subiter)
+ {
+ if (!scan.user_loadable())
+ continue;
+
+ // if it is a children device, and not something further down the device tree, we want it in the menu!
+ if (strcmp(scan.device().owner()->tag(), dev.tag()) == 0)
+ if (devtags.insert(scan.device().tag()).second)
+ {
+ // check whether we already had some devices with the same owner: if not, output the owner tag!
+ if (!tag_appended)
+ {
+ if (first_entry)
+ first_entry = false;
+ else
+ item_append(ui_menu_item_type::SEPARATOR);
+ item_append(string_format("[root%s]", dev.tag()).c_str(), nullptr, 0, nullptr);
+ tag_appended = true;
+ }
+ // finally, append the image interface to the menu
+ fill_image_line(&scan, tmp_inst, tmp_name);
+ item_append(tmp_inst.c_str(), tmp_name.c_str(), 0, (void *)&scan);
+ }
+ }
+ }
+ }
+ item_append(ui_menu_item_type::SEPARATOR);
+ item_append("Reset", nullptr, 0, (void *)1);
+
+ custombottom = mame_machine_manager::instance()->ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER;
+}
+
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_menu_file_manager::handle()
+{
+ // process the menu
+ const ui_menu_event *event = process(0);
+ if (event != nullptr && event->itemref != nullptr && event->iptkey == IPT_UI_SELECT)
+ {
+ if ((FPTR)event->itemref == 1)
+ {
+ if (m_curr_selected)
+ machine().schedule_hard_reset();
+ }
+ else
+ {
+ selected_device = (device_image_interface *) event->itemref;
+ if (selected_device != nullptr)
+ {
+
+ m_curr_selected = TRUE;
+ floppy_image_device *floppy_device = dynamic_cast<floppy_image_device *>(selected_device);
+ if (floppy_device != nullptr)
+ {
+ ui_menu::stack_push(global_alloc_clear<ui_menu_control_floppy_image>(machine(), container, floppy_device));
+ }
+ else
+ {
+ ui_menu::stack_push(global_alloc_clear<ui_menu_control_device_image>(machine(), container, selected_device));
+ }
+ // reset the existing menu
+ reset(UI_MENU_RESET_REMEMBER_POSITION);
+ }
+ }
+ }
+}
+
+// force file manager menu
+void ui_menu_file_manager::force_file_manager(running_machine &machine, render_container *container, const char *warnings)
+{
+ // reset the menu stack
+ ui_menu::stack_reset(machine);
+
+ // add the quit entry followed by the game select entry
+ ui_menu *quit = global_alloc_clear<ui_menu_quit_game>(machine, container);
+ quit->set_special_main_menu(true);
+ ui_menu::stack_push(quit);
+ ui_menu::stack_push(global_alloc_clear<ui_menu_file_manager>(machine, container, warnings));
+
+ // force the menus on
+ mame_machine_manager::instance()->ui().show_menu();
+
+ // make sure MAME is paused
+ machine.pause();
+}
diff --git a/src/frontend/mame/ui/filemngr.h b/src/frontend/mame/ui/filemngr.h
new file mode 100644
index 00000000000..38c4e068281
--- /dev/null
+++ b/src/frontend/mame/ui/filemngr.h
@@ -0,0 +1,37 @@
+// license:BSD-3-Clause
+// copyright-holders:Nathan Woods
+/***************************************************************************
+
+ ui/filemngr.h
+
+ MESS's clunky built-in file manager
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_FILEMNGR_H__
+#define __UI_FILEMNGR_H__
+
+class ui_menu_file_manager : public ui_menu {
+public:
+ std::string current_directory;
+ std::string current_file;
+ device_image_interface *selected_device;
+
+ static void force_file_manager(running_machine &machine, render_container *container, const char *warnings);
+
+ ui_menu_file_manager(running_machine &machine, render_container *container, const char *warnings);
+ virtual ~ui_menu_file_manager();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+ void fill_image_line(device_image_interface *img, std::string &instance, std::string &filename);
+
+private:
+ std::string m_warnings;
+ bool m_curr_selected;
+};
+
+#endif /* __UI_FILEMNGR_H__ */
diff --git a/src/frontend/mame/ui/filesel.cpp b/src/frontend/mame/ui/filesel.cpp
new file mode 100644
index 00000000000..24d65757a10
--- /dev/null
+++ b/src/frontend/mame/ui/filesel.cpp
@@ -0,0 +1,888 @@
+// license:BSD-3-Clause
+// copyright-holders:Nathan Woods
+/***************************************************************************
+
+ ui/filesel.cpp
+
+ MESS's clunky built-in file manager
+
+ TODO
+ - Support image creation arguments
+ - Restrict empty slot if image required
+
+***************************************************************************/
+
+#include "emu.h"
+#include "ui/ui.h"
+#include "ui/menu.h"
+#include "zippath.h"
+#include "ui/filesel.h"
+#include "imagedev/floppy.h"
+
+#include <cstring>
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+// conditional compilation to enable chosing of image formats - this is not
+// yet fully implemented
+#define ENABLE_FORMATS 0
+
+// time (in seconds) to display errors
+#define ERROR_MESSAGE_TIME 5
+
+// itemrefs for key menu items
+#define ITEMREF_NEW_IMAGE_NAME ((void *) 0x0001)
+#define ITEMREF_CREATE ((void *) 0x0002)
+#define ITEMREF_FORMAT ((void *) 0x0003)
+#define ITEMREF_NO ((void *) 0x0004)
+#define ITEMREF_YES ((void *) 0x0005)
+
+
+/***************************************************************************
+ MENU HELPERS
+***************************************************************************/
+
+//-------------------------------------------------
+// input_character - inputs a typed character
+// into a buffer
+//-------------------------------------------------
+
+static void input_character(char *buffer, size_t buffer_length, unicode_char unichar, int (*filter)(unicode_char))
+{
+ size_t buflen = strlen(buffer);
+
+ if ((unichar == 8 || unichar == 0x7f) && (buflen > 0))
+ {
+ *(char *)utf8_previous_char(&buffer[buflen]) = 0;
+ }
+ else if ((unichar > ' ') && ((filter == nullptr) || (*filter)(unichar)))
+ {
+ buflen += utf8_from_uchar(&buffer[buflen], buffer_length - buflen, unichar);
+ buffer[buflen] = 0;
+ }
+}
+
+//-------------------------------------------------
+// extra_text_draw_box - generically adds header
+// or footer text
+//-------------------------------------------------
+
+static void extra_text_draw_box(render_container *container, float origx1, float origx2, float origy, float yspan, const char *text, int direction)
+{
+ float text_width, text_height;
+ float width, maxwidth;
+ float x1, y1, x2, y2, temp;
+
+ // get the size of the text
+ mame_machine_manager::instance()->ui().draw_text_full(container,text, 0.0f, 0.0f, 1.0f, JUSTIFY_LEFT, WRAP_WORD,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &text_width, &text_height);
+ width = text_width + (2 * UI_BOX_LR_BORDER);
+ maxwidth = MAX(width, origx2 - origx1);
+
+ // compute our bounds
+ x1 = 0.5f - 0.5f * maxwidth;
+ x2 = x1 + maxwidth;
+ y1 = origy + (yspan * direction);
+ y2 = origy + (UI_BOX_TB_BORDER * direction);
+
+ if (y1 > y2)
+ {
+ temp = y1;
+ y1 = y2;
+ y2 = temp;
+ }
+
+ // draw a box
+ mame_machine_manager::instance()->ui().draw_outlined_box(container,x1, y1, x2, y2, UI_BACKGROUND_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ mame_machine_manager::instance()->ui().draw_text_full(container,text, x1, y1, text_width, JUSTIFY_LEFT, WRAP_WORD,
+ DRAW_NORMAL, ARGB_WHITE, ARGB_BLACK, nullptr, nullptr);
+}
+
+
+//-------------------------------------------------
+// extra_text_render - generically adds header
+// and footer text
+//-------------------------------------------------
+
+void extra_text_render(render_container *container, float top, float bottom,
+ float origx1, float origy1, float origx2, float origy2,
+ const char *header, const char *footer)
+{
+ header = ((header != nullptr) && (header[0] != '\0')) ? header : nullptr;
+ footer = ((footer != nullptr) && (footer[0] != '\0')) ? footer : nullptr;
+
+ if (header != nullptr)
+ extra_text_draw_box(container, origx1, origx2, origy1, top, header, -1);
+ if (footer != nullptr)
+ extra_text_draw_box(container, origx1, origx2, origy2, bottom, footer, +1);
+}
+
+
+/***************************************************************************
+ CONFIRM SAVE AS MENU
+***************************************************************************/
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+ui_menu_confirm_save_as::ui_menu_confirm_save_as(running_machine &machine, render_container *container, bool *yes)
+ : ui_menu(machine, container)
+{
+ m_yes = yes;
+ *m_yes = false;
+}
+
+
+//-------------------------------------------------
+// dtor
+//-------------------------------------------------
+
+ui_menu_confirm_save_as::~ui_menu_confirm_save_as()
+{
+}
+
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_confirm_save_as::populate()
+{
+ item_append(_("File Already Exists - Override?"), nullptr, MENU_FLAG_DISABLE, nullptr);
+ item_append(MENU_SEPARATOR_ITEM, nullptr, MENU_FLAG_DISABLE, nullptr);
+ item_append(_("No"), nullptr, 0, ITEMREF_NO);
+ item_append(_("Yes"), nullptr, 0, ITEMREF_YES);
+}
+
+//-------------------------------------------------
+// handle - confirm save as menu
+//-------------------------------------------------
+
+void ui_menu_confirm_save_as::handle()
+{
+ // process the menu
+ const ui_menu_event *event = process(0);
+
+ // process the event
+ if ((event != nullptr) && (event->iptkey == IPT_UI_SELECT))
+ {
+ if (event->itemref == ITEMREF_YES)
+ *m_yes = true;
+
+ // no matter what, pop out
+ ui_menu::stack_pop(machine());
+ }
+}
+
+
+
+/***************************************************************************
+ FILE CREATE MENU
+***************************************************************************/
+
+//-------------------------------------------------
+// is_valid_filename_char - tests to see if a
+// character is valid in a filename
+//-------------------------------------------------
+
+static int is_valid_filename_char(unicode_char unichar)
+{
+ // this should really be in the OSD layer
+ static const char valid_filename_char[] =
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00-0f
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 10-1f
+ 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, // !"#$%&'()*+,-./
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 0123456789:;<=>?
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // @ABCDEFGHIJKLMNO
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // PQRSTUVWXYZ[\]^_
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // `abcdefghijklmno
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, // pqrstuvwxyz{|}~
+ };
+ return (unichar < ARRAY_LENGTH(valid_filename_char)) && valid_filename_char[unichar];
+}
+
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+ui_menu_file_create::ui_menu_file_create(running_machine &machine, render_container *container, device_image_interface *image, std::string &current_directory, std::string &current_file, bool *ok)
+ : ui_menu(machine, container),
+ m_current_directory(current_directory),
+ m_current_file(current_file),
+ m_current_format(nullptr)
+{
+ m_image = image;
+ m_ok = ok;
+ *m_ok = true;
+ auto const sep = current_file.rfind(PATH_SEPARATOR);
+ std::strncpy(m_filename_buffer, current_file.c_str() + ((std::string::npos == sep) ? 0 : (sep + 1)), sizeof(m_filename_buffer));
+}
+
+
+//-------------------------------------------------
+// dtor
+//-------------------------------------------------
+
+ui_menu_file_create::~ui_menu_file_create()
+{
+}
+
+
+//-------------------------------------------------
+// custom_render - perform our special rendering
+//-------------------------------------------------
+
+void ui_menu_file_create::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ extra_text_render(container, top, bottom, origx1, origy1, origx2, origy2,
+ m_current_directory.c_str(),
+ nullptr);
+}
+
+
+//-------------------------------------------------
+// populate - populates the file creator menu
+//-------------------------------------------------
+
+void ui_menu_file_create::populate()
+{
+ std::string buffer;
+ const image_device_format *format;
+ const char *new_image_name;
+
+ // append the "New Image Name" item
+ if (get_selection() == ITEMREF_NEW_IMAGE_NAME)
+ {
+ buffer.append(m_filename_buffer).append("_");
+ new_image_name = buffer.c_str();
+ }
+ else
+ {
+ new_image_name = m_filename_buffer;
+ }
+ item_append(_("New Image Name:"), new_image_name, 0, ITEMREF_NEW_IMAGE_NAME);
+
+ // do we support multiple formats?
+ if (ENABLE_FORMATS) format = m_image->formatlist().first();
+ if (ENABLE_FORMATS && (format != nullptr))
+ {
+ item_append(_("Image Format:"), m_current_format->description(), 0, ITEMREF_FORMAT);
+ m_current_format = format;
+ }
+
+ // finish up the menu
+ item_append(ui_menu_item_type::SEPARATOR);
+ item_append(_("Create"), nullptr, 0, ITEMREF_CREATE);
+
+ customtop = mame_machine_manager::instance()->ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER;
+}
+
+
+//-------------------------------------------------
+// handle - file creator menu
+//-------------------------------------------------
+
+void ui_menu_file_create::handle()
+{
+ // process the menu
+ const ui_menu_event *event = process(0);
+
+ // process the event
+ if (event != nullptr)
+ {
+ // handle selections
+ switch(event->iptkey)
+ {
+ case IPT_UI_SELECT:
+ if ((event->itemref == ITEMREF_CREATE) || (event->itemref == ITEMREF_NEW_IMAGE_NAME))
+ {
+ std::string tmp_file(m_filename_buffer);
+ if (tmp_file.find(".") != -1 && tmp_file.find(".") < tmp_file.length() - 1)
+ {
+ m_current_file = m_filename_buffer;
+ ui_menu::stack_pop(machine());
+ }
+ else
+ mame_machine_manager::instance()->ui().popup_time(1, "%s", _("Please enter a file extension too"));
+ }
+ break;
+
+ case IPT_SPECIAL:
+ if (get_selection() == ITEMREF_NEW_IMAGE_NAME)
+ {
+ input_character(
+ m_filename_buffer,
+ ARRAY_LENGTH(m_filename_buffer),
+ event->unichar,
+ is_valid_filename_char);
+ reset(UI_MENU_RESET_REMEMBER_POSITION);
+ }
+ break;
+ case IPT_UI_CANCEL:
+ *m_ok = false;
+ break;
+ }
+ }
+}
+
+/***************************************************************************
+ FILE SELECTOR MENU
+***************************************************************************/
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+ui_menu_file_selector::ui_menu_file_selector(running_machine &machine, render_container *container, device_image_interface *image, std::string &current_directory, std::string &current_file, bool has_empty, bool has_softlist, bool has_create, int *result)
+ : ui_menu(machine, container),
+ m_current_directory(current_directory),
+ m_current_file(current_file),
+ m_entrylist(nullptr)
+{
+ m_image = image;
+ m_has_empty = has_empty;
+ m_has_softlist = has_softlist;
+ m_has_create = has_create;
+ m_result = result;
+}
+
+
+//-------------------------------------------------
+// dtor
+//-------------------------------------------------
+
+ui_menu_file_selector::~ui_menu_file_selector()
+{
+}
+
+
+//-------------------------------------------------
+// custom_render - perform our special rendering
+//-------------------------------------------------
+
+void ui_menu_file_selector::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ extra_text_render(container, top, bottom,
+ origx1, origy1, origx2, origy2,
+ m_current_directory.c_str(),
+ nullptr);
+}
+
+
+
+//-------------------------------------------------
+// compare_file_selector_entries - sorting proc
+// for file selector entries
+//-------------------------------------------------
+
+int ui_menu_file_selector::compare_entries(const file_selector_entry *e1, const file_selector_entry *e2)
+{
+ int result;
+ const char *e1_basename = (e1->basename != nullptr) ? e1->basename : "";
+ const char *e2_basename = (e2->basename != nullptr) ? e2->basename : "";
+
+ if (e1->type < e2->type)
+ {
+ result = -1;
+ }
+ else if (e1->type > e2->type)
+ {
+ result = 1;
+ }
+ else
+ {
+ result = core_stricmp(e1_basename, e2_basename);
+ if (result == 0)
+ {
+ result = strcmp(e1_basename, e2_basename);
+ if (result == 0)
+ {
+ if (e1 < e2)
+ result = -1;
+ else if (e1 > e2)
+ result = 1;
+ }
+ }
+ }
+
+ return result;
+}
+
+
+//-------------------------------------------------
+// append_entry - appends a new
+// file selector entry to an entry list
+//-------------------------------------------------
+
+ui_menu_file_selector::file_selector_entry *ui_menu_file_selector::append_entry(
+ file_selector_entry_type entry_type, const char *entry_basename, const char *entry_fullpath)
+{
+ file_selector_entry *entry;
+ file_selector_entry **entryptr;
+
+ // allocate a new entry
+ entry = (file_selector_entry *) m_pool_alloc(sizeof(*entry));
+ memset(entry, 0, sizeof(*entry));
+ entry->type = entry_type;
+ entry->basename = (entry_basename != nullptr) ? pool_strdup(entry_basename) : entry_basename;
+ entry->fullpath = (entry_fullpath != nullptr) ? pool_strdup(entry_fullpath) : entry_fullpath;
+
+ // find the end of the list
+ entryptr = &m_entrylist;
+ while ((*entryptr != nullptr) && (compare_entries(entry, *entryptr) >= 0))
+ entryptr = &(*entryptr)->next;
+
+ // insert the entry
+ entry->next = *entryptr;
+ *entryptr = entry;
+ return entry;
+}
+
+
+//-------------------------------------------------
+// append_entry_menu_item - appends
+// a menu item for a file selector entry
+//-------------------------------------------------
+
+ui_menu_file_selector::file_selector_entry *ui_menu_file_selector::append_dirent_entry(const osd_directory_entry *dirent)
+{
+ std::string buffer;
+ file_selector_entry_type entry_type;
+ file_selector_entry *entry;
+
+ switch(dirent->type)
+ {
+ case ENTTYPE_FILE:
+ entry_type = SELECTOR_ENTRY_TYPE_FILE;
+ break;
+
+ case ENTTYPE_DIR:
+ entry_type = SELECTOR_ENTRY_TYPE_DIRECTORY;
+ break;
+
+ default:
+ // exceptional case; do not add a menu item
+ return nullptr;
+ }
+
+ // determine the full path
+ util::zippath_combine(buffer, m_current_directory.c_str(), dirent->name);
+
+ // create the file selector entry
+ entry = append_entry(
+ entry_type,
+ dirent->name,
+ buffer.c_str());
+
+ return entry;
+}
+
+
+//-------------------------------------------------
+// append_entry_menu_item - appends
+// a menu item for a file selector entry
+//-------------------------------------------------
+
+void ui_menu_file_selector::append_entry_menu_item(const file_selector_entry *entry)
+{
+ const char *text = nullptr;
+ const char *subtext = nullptr;
+
+ switch(entry->type)
+ {
+ case SELECTOR_ENTRY_TYPE_EMPTY:
+ text = _("[empty slot]");
+ break;
+
+ case SELECTOR_ENTRY_TYPE_CREATE:
+ text = _("[create]");
+ break;
+
+ case SELECTOR_ENTRY_TYPE_SOFTWARE_LIST:
+ text = _("[software list]");
+ break;
+
+ case SELECTOR_ENTRY_TYPE_DRIVE:
+ text = entry->basename;
+ subtext = "[DRIVE]";
+ break;
+
+ case SELECTOR_ENTRY_TYPE_DIRECTORY:
+ text = entry->basename;
+ subtext = "[DIR]";
+ break;
+
+ case SELECTOR_ENTRY_TYPE_FILE:
+ text = entry->basename;
+ subtext = "[FILE]";
+ break;
+ }
+ item_append(text, subtext, 0, (void *) entry);
+}
+
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_file_selector::populate()
+{
+ util::zippath_directory *directory = nullptr;
+ osd_file::error err;
+ const osd_directory_entry *dirent;
+ const file_selector_entry *entry;
+ const file_selector_entry *selected_entry = nullptr;
+ int i;
+ const char *volume_name;
+ const char *path = m_current_directory.c_str();
+
+ // open the directory
+ err = util::zippath_opendir(path, &directory);
+
+ // clear out the menu entries
+ m_entrylist = nullptr;
+
+ if (m_has_empty)
+ {
+ // add the "[empty slot]" entry
+ append_entry(SELECTOR_ENTRY_TYPE_EMPTY, nullptr, nullptr);
+ }
+
+ if (m_has_create)
+ {
+ // add the "[create]" entry
+ append_entry(SELECTOR_ENTRY_TYPE_CREATE, nullptr, nullptr);
+ }
+
+ if (m_has_softlist)
+ {
+ // add the "[software list]" entry
+ entry = append_entry(SELECTOR_ENTRY_TYPE_SOFTWARE_LIST, nullptr, nullptr);
+ selected_entry = entry;
+ }
+
+ // add the drives
+ i = 0;
+ while((volume_name = osd_get_volume_name(i))!=nullptr)
+ {
+ append_entry(SELECTOR_ENTRY_TYPE_DRIVE,
+ volume_name, volume_name);
+ i++;
+ }
+
+ // build the menu for each item
+ if (err == osd_file::error::NONE)
+ {
+ while((dirent = util::zippath_readdir(directory)) != nullptr)
+ {
+ // append a dirent entry
+ entry = append_dirent_entry(dirent);
+
+ if (entry != nullptr)
+ {
+ // set the selected item to be the first non-parent directory or file
+ if ((selected_entry == nullptr) && strcmp(dirent->name, ".."))
+ selected_entry = entry;
+
+ // do we have to select this file?
+ if (!core_stricmp(m_current_file.c_str(), dirent->name))
+ selected_entry = entry;
+ }
+ }
+ }
+
+ // append all of the menu entries
+ for (entry = m_entrylist; entry != nullptr; entry = entry->next)
+ append_entry_menu_item(entry);
+
+ // set the selection (if we have one)
+ if (selected_entry != nullptr)
+ set_selection((void *) selected_entry);
+
+ // set up custom render proc
+ customtop = mame_machine_manager::instance()->ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER;
+
+ if (directory != nullptr)
+ util::zippath_closedir(directory);
+}
+
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_menu_file_selector::handle()
+{
+ osd_file::error err;
+ const file_selector_entry *entry;
+ const file_selector_entry *selected_entry = nullptr;
+ int bestmatch = 0;
+
+ // process the menu
+ const ui_menu_event *event = process(0);
+ if (event != nullptr && event->itemref != nullptr)
+ {
+ // handle selections
+ if (event->iptkey == IPT_UI_SELECT)
+ {
+ entry = (const file_selector_entry *) event->itemref;
+ switch(entry->type)
+ {
+ case SELECTOR_ENTRY_TYPE_EMPTY:
+ // empty slot - unload
+ *m_result = R_EMPTY;
+ ui_menu::stack_pop(machine());
+ break;
+
+ case SELECTOR_ENTRY_TYPE_CREATE:
+ // create
+ *m_result = R_CREATE;
+ ui_menu::stack_pop(machine());
+ break;
+
+ case SELECTOR_ENTRY_TYPE_SOFTWARE_LIST:
+ *m_result = R_SOFTLIST;
+ ui_menu::stack_pop(machine());
+ break;
+
+ case SELECTOR_ENTRY_TYPE_DRIVE:
+ case SELECTOR_ENTRY_TYPE_DIRECTORY:
+ // drive/directory - first check the path
+ err = util::zippath_opendir(entry->fullpath, nullptr);
+ if (err != osd_file::error::NONE)
+ {
+ // this path is problematic; present the user with an error and bail
+ mame_machine_manager::instance()->ui().popup_time(1, "Error accessing %s", entry->fullpath);
+ break;
+ }
+ m_current_directory.assign(entry->fullpath);
+ reset((ui_menu_reset_options)0);
+ break;
+
+ case SELECTOR_ENTRY_TYPE_FILE:
+ // file
+ m_current_file.assign(entry->fullpath);
+ *m_result = R_FILE;
+ ui_menu::stack_pop(machine());
+ break;
+ }
+
+ // reset the char buffer when pressing IPT_UI_SELECT
+ if (m_filename_buffer[0] != '\0')
+ memset(m_filename_buffer, '\0', ARRAY_LENGTH(m_filename_buffer));
+ }
+ else if (event->iptkey == IPT_SPECIAL)
+ {
+ int buflen = strlen(m_filename_buffer);
+ bool update_selected = FALSE;
+
+ // if it's a backspace and we can handle it, do so
+ if ((event->unichar == 8 || event->unichar == 0x7f) && buflen > 0)
+ {
+ *(char *)utf8_previous_char(&m_filename_buffer[buflen]) = 0;
+ update_selected = TRUE;
+
+ if (ARRAY_LENGTH(m_filename_buffer) > 0)
+ mame_machine_manager::instance()->ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_filename_buffer);
+ }
+ // if it's any other key and we're not maxed out, update
+ else if (event->unichar >= ' ' && event->unichar < 0x7f)
+ {
+ buflen += utf8_from_uchar(&m_filename_buffer[buflen], ARRAY_LENGTH(m_filename_buffer) - buflen, event->unichar);
+ m_filename_buffer[buflen] = 0;
+ update_selected = TRUE;
+
+ if (ARRAY_LENGTH(m_filename_buffer) > 0)
+ mame_machine_manager::instance()->ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_filename_buffer);
+ }
+
+ if (update_selected)
+ {
+ const file_selector_entry *cur_selected = (const file_selector_entry *)get_selection();
+
+ // check for entries which matches our m_filename_buffer:
+ // from current entry to the end
+ for (entry = cur_selected; entry != nullptr; entry = entry->next)
+ {
+ if (entry->basename != nullptr && m_filename_buffer[0] != '\0')
+ {
+ int match = 0;
+ for (int i = 0; i < ARRAY_LENGTH(m_filename_buffer); i++)
+ {
+ if (core_strnicmp(entry->basename, m_filename_buffer, i) == 0)
+ match = i;
+ }
+
+ if (match > bestmatch)
+ {
+ bestmatch = match;
+ selected_entry = entry;
+ }
+ }
+ }
+ // and from the first entry to current one
+ for (entry = m_entrylist; entry != cur_selected; entry = entry->next)
+ {
+ if (entry->basename != nullptr && m_filename_buffer[0] != '\0')
+ {
+ int match = 0;
+ for (int i = 0; i < ARRAY_LENGTH(m_filename_buffer); i++)
+ {
+ if (core_strnicmp(entry->basename, m_filename_buffer, i) == 0)
+ match = i;
+ }
+
+ if (match > bestmatch)
+ {
+ bestmatch = match;
+ selected_entry = entry;
+ }
+ }
+ }
+
+ if (selected_entry != nullptr && selected_entry != cur_selected)
+ {
+ set_selection((void *)selected_entry);
+ top_line = selected - (visible_lines / 2);
+ }
+ }
+ }
+ else if (event->iptkey == IPT_UI_CANCEL)
+ {
+ // reset the char buffer also in this case
+ if (m_filename_buffer[0] != '\0')
+ memset(m_filename_buffer, '\0', ARRAY_LENGTH(m_filename_buffer));
+ }
+ }
+}
+
+
+
+/***************************************************************************
+ SELECT FORMAT MENU
+***************************************************************************/
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+ui_menu_select_format::ui_menu_select_format(running_machine &machine, render_container *container, floppy_image_format_t **formats, int ext_match, int total_usable, int *result)
+ : ui_menu(machine, container)
+{
+ m_formats = formats;
+ m_ext_match = ext_match;
+ m_total_usable = total_usable;
+ m_result = result;
+}
+
+
+//-------------------------------------------------
+// dtor
+//-------------------------------------------------
+
+ui_menu_select_format::~ui_menu_select_format()
+{
+}
+
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_select_format::populate()
+{
+ item_append(_("Select image format"), nullptr, MENU_FLAG_DISABLE, nullptr);
+ for (int i = 0; i < m_total_usable; i++)
+ {
+ const floppy_image_format_t *fmt = m_formats[i];
+
+ if (i && i == m_ext_match)
+ item_append(ui_menu_item_type::SEPARATOR);
+ item_append(fmt->description(), fmt->name(), 0, (void *)(FPTR)i);
+ }
+}
+
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_menu_select_format::handle()
+{
+ // process the menu
+ const ui_menu_event *event = process(0);
+ if (event != nullptr && event->iptkey == IPT_UI_SELECT)
+ {
+ *m_result = int(FPTR(event->itemref));
+ ui_menu::stack_pop(machine());
+ }
+}
+
+
+/***************************************************************************
+ SELECT RW
+***************************************************************************/
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+ui_menu_select_rw::ui_menu_select_rw(running_machine &machine, render_container *container,
+ bool can_in_place, int *result)
+ : ui_menu(machine, container)
+{
+ m_can_in_place = can_in_place;
+ m_result = result;
+}
+
+
+//-------------------------------------------------
+// dtor
+//-------------------------------------------------
+
+ui_menu_select_rw::~ui_menu_select_rw()
+{
+}
+
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_select_rw::populate()
+{
+ item_append(_("Select access mode"), nullptr, MENU_FLAG_DISABLE, nullptr);
+ item_append(_("Read-only"), nullptr, 0, (void *)READONLY);
+ if (m_can_in_place)
+ item_append(_("Read-write"), nullptr, 0, (void *)READWRITE);
+ item_append(_("Read this image, write to another image"), nullptr, 0, (void *)WRITE_OTHER);
+ item_append(_("Read this image, write to diff"), nullptr, 0, (void *)WRITE_DIFF);
+}
+
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_menu_select_rw::handle()
+{
+ // process the menu
+ const ui_menu_event *event = process(0);
+ if (event != nullptr && event->iptkey == IPT_UI_SELECT)
+ {
+ *m_result = int(FPTR(event->itemref));
+ ui_menu::stack_pop(machine());
+ }
+}
diff --git a/src/frontend/mame/ui/filesel.h b/src/frontend/mame/ui/filesel.h
new file mode 100644
index 00000000000..c7e113e463b
--- /dev/null
+++ b/src/frontend/mame/ui/filesel.h
@@ -0,0 +1,148 @@
+// license:BSD-3-Clause
+// copyright-holders:Nathan Woods
+/***************************************************************************
+
+ ui/filesel.h
+
+ MESS's clunky built-in file manager
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_FILESEL_H__
+#define __UI_FILESEL_H__
+
+// ======================> ui_menu_confirm_save_as
+
+class ui_menu_confirm_save_as : public ui_menu
+{
+public:
+ ui_menu_confirm_save_as(running_machine &machine, render_container *container, bool *yes);
+ virtual ~ui_menu_confirm_save_as();
+ virtual void populate() override;
+ virtual void handle() override;
+
+private:
+ bool *m_yes;
+};
+
+
+// ======================> ui_menu_file_create
+
+class ui_menu_file_create : public ui_menu
+{
+public:
+ ui_menu_file_create(running_machine &machine, render_container *container, device_image_interface *image, std::string &current_directory, std::string &current_file, bool *ok);
+ virtual ~ui_menu_file_create();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+private:
+ device_image_interface * m_image;
+ std::string & m_current_directory;
+ std::string & m_current_file;
+ const image_device_format * m_current_format;
+ char m_filename_buffer[1024];
+
+protected:
+ bool * m_ok;
+};
+
+
+// ======================> ui_menu_file_selector
+
+class ui_menu_file_selector : public ui_menu
+{
+public:
+ enum { R_EMPTY, R_SOFTLIST, R_CREATE, R_FILE };
+ ui_menu_file_selector(running_machine &machine, render_container *container, device_image_interface *image, std::string &current_directory, std::string &current_file, bool has_empty, bool has_softlist, bool has_create, int *result);
+ virtual ~ui_menu_file_selector();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+private:
+ enum file_selector_entry_type
+ {
+ SELECTOR_ENTRY_TYPE_EMPTY,
+ SELECTOR_ENTRY_TYPE_CREATE,
+ SELECTOR_ENTRY_TYPE_SOFTWARE_LIST,
+ SELECTOR_ENTRY_TYPE_DRIVE,
+ SELECTOR_ENTRY_TYPE_DIRECTORY,
+ SELECTOR_ENTRY_TYPE_FILE
+ };
+
+ struct file_selector_entry
+ {
+ file_selector_entry *next;
+
+ file_selector_entry_type type;
+ const char *basename;
+ const char *fullpath;
+ };
+
+ // internal state
+ device_image_interface * m_image;
+ std::string & m_current_directory;
+ std::string & m_current_file;
+ bool m_has_empty;
+ bool m_has_softlist;
+ bool m_has_create;
+ int * m_result;
+ file_selector_entry * m_entrylist;
+ char m_filename_buffer[1024];
+
+ // methods
+ int compare_entries(const file_selector_entry *e1, const file_selector_entry *e2);
+ file_selector_entry *append_entry(file_selector_entry_type entry_type, const char *entry_basename, const char *entry_fullpath);
+ file_selector_entry *append_dirent_entry(const osd_directory_entry *dirent);
+ void append_entry_menu_item(const file_selector_entry *entry);
+};
+
+
+// ======================> ui_menu_select_format
+
+class ui_menu_select_format : public ui_menu
+{
+public:
+ ui_menu_select_format(running_machine &machine, render_container *container,
+ class floppy_image_format_t **formats, int ext_match, int total_usable, int *result);
+ virtual ~ui_menu_select_format();
+ virtual void populate() override;
+ virtual void handle() override;
+
+private:
+ // internal state
+ floppy_image_format_t ** m_formats;
+ int m_ext_match;
+ int m_total_usable;
+ int * m_result;
+};
+
+
+// ======================> ui_menu_select_rw
+
+class ui_menu_select_rw : public ui_menu
+{
+public:
+ enum { READONLY, READWRITE, WRITE_OTHER, WRITE_DIFF };
+ ui_menu_select_rw(running_machine &machine, render_container *container,
+ bool can_in_place, int *result);
+ virtual ~ui_menu_select_rw();
+ virtual void populate() override;
+ virtual void handle() override;
+
+private:
+ // internal state
+ bool m_can_in_place;
+ int * m_result;
+};
+
+// helper
+void extra_text_render(render_container *container, float top, float bottom,
+ float origx1, float origy1, float origx2, float origy2,
+ const char *header, const char *footer);
+
+#endif /* __UI_FILESEL_H__ */
diff --git a/src/frontend/mame/ui/floppycntrl.cpp b/src/frontend/mame/ui/floppycntrl.cpp
new file mode 100644
index 00000000000..05a4e03c825
--- /dev/null
+++ b/src/frontend/mame/ui/floppycntrl.cpp
@@ -0,0 +1,170 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ ui/floppycntrl.cpp
+
+***************************************************************************/
+
+#include "emu.h"
+#include "zippath.h"
+#include "ui/menu.h"
+#include "ui/imgcntrl.h"
+#include "ui/filesel.h"
+#include "ui/floppycntrl.h"
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+ui_menu_control_floppy_image::ui_menu_control_floppy_image(running_machine &machine, render_container *container, device_image_interface *_image) : ui_menu_control_device_image(machine, container, _image)
+{
+ floppy_image_device *fd = static_cast<floppy_image_device *>(image);
+ const floppy_image_format_t *fif_list = fd->get_formats();
+ int fcnt = 0;
+ for(const floppy_image_format_t *i = fif_list; i; i = i->next)
+ fcnt++;
+
+ format_array = global_alloc_array(floppy_image_format_t *, fcnt);
+ input_format = output_format = nullptr;
+ input_filename = output_filename = "";
+}
+
+ui_menu_control_floppy_image::~ui_menu_control_floppy_image()
+{
+ global_free_array(format_array);
+}
+
+void ui_menu_control_floppy_image::do_load_create()
+{
+ floppy_image_device *fd = static_cast<floppy_image_device *>(image);
+ if(input_filename.compare("")==0) {
+ int err = fd->create(output_filename.c_str(), nullptr, nullptr);
+ if (err != 0) {
+ machine().popmessage("Error: %s", fd->error());
+ return;
+ }
+ fd->setup_write(output_format);
+ } else {
+ int err = fd->load(input_filename.c_str());
+ if (!err && output_filename.compare("") != 0)
+ err = fd->reopen_for_write(output_filename.c_str());
+ if(err != 0) {
+ machine().popmessage("Error: %s", fd->error());
+ return;
+ }
+ if(output_format)
+ fd->setup_write(output_format);
+ }
+}
+
+void ui_menu_control_floppy_image::hook_load(std::string filename, bool softlist)
+{
+ if (softlist)
+ {
+ machine().popmessage("When loaded from software list, the disk is Read-only.\n");
+ image->load(filename.c_str());
+ ui_menu::stack_pop(machine());
+ return;
+ }
+
+ input_filename = filename;
+ input_format = static_cast<floppy_image_device *>(image)->identify(filename);
+
+ if (!input_format)
+ {
+ machine().popmessage("Error: %s\n", image->error());
+ ui_menu::stack_pop(machine());
+ return;
+ }
+
+ bool can_in_place = input_format->supports_save();
+ if(can_in_place) {
+ osd_file::error filerr;
+ std::string tmp_path;
+ util::core_file::ptr tmp_file;
+ // attempt to open the file for writing but *without* create
+ filerr = util::zippath_fopen(filename.c_str(), OPEN_FLAG_READ | OPEN_FLAG_WRITE, tmp_file, tmp_path);
+ if(filerr == osd_file::error::NONE)
+ tmp_file.reset();
+ else
+ can_in_place = false;
+ }
+ submenu_result = -1;
+ ui_menu::stack_push(global_alloc_clear<ui_menu_select_rw>(machine(), container, can_in_place, &submenu_result));
+ state = SELECT_RW;
+}
+
+void ui_menu_control_floppy_image::handle()
+{
+ floppy_image_device *fd = static_cast<floppy_image_device *>(image);
+ switch (state) {
+ case DO_CREATE: {
+ floppy_image_format_t *fif_list = fd->get_formats();
+ int ext_match;
+ int total_usable = 0;
+ for(floppy_image_format_t *i = fif_list; i; i = i->next) {
+ if(!i->supports_save())
+ continue;
+ if (i->extension_matches(current_file.c_str()))
+ format_array[total_usable++] = i;
+ }
+ ext_match = total_usable;
+ for(floppy_image_format_t *i = fif_list; i; i = i->next) {
+ if(!i->supports_save())
+ continue;
+ if (!i->extension_matches(current_file.c_str()))
+ format_array[total_usable++] = i;
+ }
+ submenu_result = -1;
+ ui_menu::stack_push(global_alloc_clear<ui_menu_select_format>(machine(), container, format_array, ext_match, total_usable, &submenu_result));
+
+ state = SELECT_FORMAT;
+ break;
+ }
+
+ case SELECT_FORMAT:
+ if(submenu_result == -1) {
+ state = START_FILE;
+ handle();
+ } else {
+ util::zippath_combine(output_filename, current_directory.c_str(), current_file.c_str());
+ output_format = format_array[submenu_result];
+ do_load_create();
+ ui_menu::stack_pop(machine());
+ }
+ break;
+
+ case SELECT_RW:
+ switch(submenu_result) {
+ case ui_menu_select_rw::READONLY:
+ do_load_create();
+ ui_menu::stack_pop(machine());
+ break;
+
+ case ui_menu_select_rw::READWRITE:
+ output_format = input_format;
+ do_load_create();
+ ui_menu::stack_pop(machine());
+ break;
+
+ case ui_menu_select_rw::WRITE_DIFF:
+ machine().popmessage("Sorry, diffs are not supported yet\n");
+ ui_menu::stack_pop(machine());
+ break;
+
+ case ui_menu_select_rw::WRITE_OTHER:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_file_create>(machine(), container, image, current_directory, current_file, &create_ok));
+ state = CHECK_CREATE;
+ break;
+
+ case -1:
+ state = START_FILE;
+ break;
+ }
+ break;
+
+ default:
+ ui_menu_control_device_image::handle();
+ }
+} \ No newline at end of file
diff --git a/src/frontend/mame/ui/floppycntrl.h b/src/frontend/mame/ui/floppycntrl.h
new file mode 100644
index 00000000000..08ac1e85d68
--- /dev/null
+++ b/src/frontend/mame/ui/floppycntrl.h
@@ -0,0 +1,36 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ ui/floppycntrl.h
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_FLOPPY_IMAGE_H__
+#define __UI_FLOPPY_IMAGE_H__
+
+#include "imagedev/floppy.h"
+#include "formats/flopimg.h"
+
+class ui_menu_control_floppy_image : public ui_menu_control_device_image {
+public:
+ ui_menu_control_floppy_image(running_machine &machine, render_container *container, device_image_interface *image);
+ virtual ~ui_menu_control_floppy_image();
+
+ virtual void handle() override;
+
+protected:
+ enum { SELECT_FORMAT = LAST_ID, SELECT_MEDIA, SELECT_RW };
+
+ floppy_image_format_t **format_array;
+ floppy_image_format_t *input_format, *output_format;
+ std::string input_filename, output_filename;
+
+ void do_load_create();
+ virtual void hook_load(std::string filename, bool softlist) override;
+};
+
+
+#endif /* __UI_FLOPPY_IMAGE_H__ */ \ No newline at end of file
diff --git a/src/frontend/mame/ui/icorender.h b/src/frontend/mame/ui/icorender.h
new file mode 100644
index 00000000000..ac942ac922e
--- /dev/null
+++ b/src/frontend/mame/ui/icorender.h
@@ -0,0 +1,233 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota, Victor Laskin
+/***************************************************************************
+
+ ui/icorender.h
+
+ ICOns file loader.
+
+ Original code by Victor Laskin (victor.laskin@gmail.com)
+ http://vitiy.info/Code/ico.cpp
+
+***************************************************************************/
+#pragma once
+
+#ifndef __UI_ICORENDER_H__
+#define __UI_ICORENDER_H__
+
+// These next two structs represent how the icon information is stored
+// in an ICO file.
+typedef struct
+{
+ UINT8 bWidth; // Width of the image
+ UINT8 bHeight; // Height of the image (times 2)
+ UINT8 bColorCount; // Number of colors in image (0 if >=8bpp)
+ UINT8 bReserved; // Reserved
+ UINT16 wPlanes; // Color Planes
+ UINT16 wBitCount; // Bits per pixel
+ UINT32 dwBytesInRes; // how many bytes in this resource?
+ UINT32 dwImageOffset; // where in the file is this image
+} ICONDIRENTRY, *LPICONDIRENTRY;
+
+typedef struct
+{
+ UINT16 idReserved; // Reserved
+ UINT16 idType; // resource type (1 for icons)
+ UINT16 idCount; // how many images?
+ //ICONDIRENTRY idEntries[1]; // the entries for each image
+} ICONDIR, *LPICONDIR;
+
+// size - 40 bytes
+typedef struct {
+ UINT32 biSize;
+ UINT32 biWidth;
+ UINT32 biHeight; // Icon Height (added height of XOR-Bitmap and AND-Bitmap)
+ UINT16 biPlanes;
+ UINT16 biBitCount;
+ UINT32 biCompression;
+ INT32 biSizeImage;
+ UINT32 biXPelsPerMeter;
+ UINT32 biYPelsPerMeter;
+ UINT32 biClrUsed;
+ UINT32 biClrImportant;
+} s_BITMAPINFOHEADER, *s_PBITMAPINFOHEADER;
+
+// 46 bytes
+typedef struct{
+ s_BITMAPINFOHEADER icHeader; // DIB header
+ UINT32 icColors[1]; // Color table (short 4 bytes) //RGBQUAD
+ UINT8 icXOR[1]; // DIB bits for XOR mask
+ UINT8 icAND[1]; // DIB bits for AND mask
+} ICONIMAGE, *LPICONIMAGE;
+
+//-------------------------------------------------
+// load an ICO file into a bitmap
+//-------------------------------------------------
+
+void render_load_ico(bitmap_argb32 &bitmap, emu_file &file, const char *dirname, const char *filename)
+{
+ INT32 width = 0;
+ INT32 height = 0;
+
+ // deallocate previous bitmap
+ bitmap.reset();
+
+ // define file's full name
+ std::string fname;
+
+ if (!dirname)
+ fname = filename;
+ else
+ fname.assign(dirname).append(PATH_SEPARATOR).append(filename);
+
+ osd_file::error filerr = file.open(fname.c_str());
+
+ if (filerr != osd_file::error::NONE)
+ return;
+
+ // allocates a buffer for the image
+ UINT64 size = file.size();
+ UINT8 *buffer = global_alloc_array(UINT8, size + 1);
+
+ // read data from the file and set them in the buffer
+ file.read(buffer, size);
+
+ LPICONDIR icoDir = (LPICONDIR)buffer;
+ int iconsCount = icoDir->idCount;
+
+ if (icoDir->idReserved != 0 || icoDir->idType != 1 || iconsCount == 0 || iconsCount > 20)
+ {
+ file.close();
+ global_free_array(buffer);
+ return;
+ }
+
+ UINT8* cursor = buffer;
+ cursor += 6;
+ ICONDIRENTRY* dirEntry = (ICONDIRENTRY*)(cursor);
+ int maxSize = 0;
+ int offset = 0;
+ int maxBitCount = 0;
+ for (int i = 0; i < iconsCount; i++, ++dirEntry)
+ {
+ int w = dirEntry->bWidth;
+ int h = dirEntry->bHeight;
+ int bitCount = dirEntry->wBitCount;
+ if (w * h > maxSize || bitCount > maxBitCount) // we choose icon with max resolution
+ {
+ width = w;
+ height = h;
+ offset = dirEntry->dwImageOffset;
+ maxSize = w * h;
+ }
+ }
+
+ if (offset == 0) return;
+
+ cursor = buffer;
+ cursor += offset;
+ ICONIMAGE* icon = (ICONIMAGE*)(cursor);
+ int realBitsCount = (int)icon->icHeader.biBitCount;
+ bool hasAndMask = (realBitsCount < 32) && (height != icon->icHeader.biHeight);
+
+ cursor += 40;
+ bitmap.allocate(width, height);
+
+ // rgba + vertical swap
+ if (realBitsCount >= 32)
+ {
+ for (int x = 0; x < width; ++x)
+ for (int y = 0; y < height; ++y)
+ {
+ int shift2 = 4 * (x + (height - y - 1) * width);
+ bitmap.pix32(y, x) = rgb_t(cursor[shift2 + 3], cursor[shift2 + 2], cursor[shift2 + 1], cursor[shift2]);
+ }
+ }
+ else if (realBitsCount == 24)
+ for (int x = 0; x < width; ++x)
+ for (int y = 0; y < height; ++y)
+ {
+ int shift2 = 3 * (x + (height - y - 1) * width);
+ bitmap.pix32(y, x) = rgb_t(255, cursor[shift2 + 2], cursor[shift2 + 1], cursor[shift2]);
+ }
+ else if (realBitsCount == 8) // 256 colors
+ {
+ // 256 color table
+ UINT8 *colors = cursor;
+ cursor += 256 * 4;
+ for (int x = 0; x < width; ++x)
+ for (int y = 0; y < height; ++y)
+ {
+ int shift2 = (x + (height - y - 1) * width);
+ int index = 4 * cursor[shift2];
+ bitmap.pix32(y, x) = rgb_t(255, colors[index + 2], colors[index + 1], colors[index]);
+ }
+ }
+ else if (realBitsCount == 4) // 16 colors
+ {
+ // 16 color table
+ UINT8 *colors = cursor;
+ cursor += 16 * 4;
+ for (int x = 0; x < width; ++x)
+ for (int y = 0; y < height; ++y)
+ {
+ int shift2 = (x + (height - y - 1) * width);
+ UINT8 index = cursor[shift2 / 2];
+ if (shift2 % 2 == 0)
+ index = (index >> 4) & 0xF;
+ else
+ index = index & 0xF;
+ index *= 4;
+ bitmap.pix32(y, x) = rgb_t(255, colors[index + 2], colors[index + 1], colors[index]);
+ }
+ }
+ else if (realBitsCount == 1) // 2 colors
+ {
+ // 2 color table
+ UINT8 *colors = cursor;
+ cursor += 2 * 4;
+ int boundary = width; // !!! 32 bit boundary (http://www.daubnet.com/en/file-format-ico)
+ while (boundary % 32 != 0) boundary++;
+
+ for (int x = 0; x < width; ++x)
+ for (int y = 0; y < height; ++y)
+ {
+ int shift2 = (x + (height - y - 1) * boundary);
+ UINT8 index = cursor[shift2 / 8];
+
+ // select 1 bit only
+ UINT8 bit = 7 - (x % 8);
+ index = (index >> bit) & 0x01;
+ index *= 4;
+ bitmap.pix32(y, x) = rgb_t(255, colors[index + 2], colors[index + 1], colors[index]);
+ }
+ }
+
+ // Read AND mask after base color data - 1 BIT MASK
+ if (hasAndMask)
+ {
+ int boundary = width * realBitsCount; // !!! 32 bit boundary (http://www.daubnet.com/en/file-format-ico)
+ while (boundary % 32 != 0) boundary++;
+ cursor += boundary * height / 8;
+
+ boundary = width;
+ while (boundary % 32 != 0) boundary++;
+
+ for (int y = 0; y < height; ++y)
+ for (int x = 0; x < width; ++x)
+ {
+ UINT8 bit = 7 - (x % 8);
+ int shift2 = (x + (height - y - 1) * boundary) / 8;
+ int mask = (0x01 & ((UINT8)cursor[shift2] >> bit));
+ rgb_t colors = bitmap.pix32(y, x);
+ UINT8 alpha = colors.a();
+ alpha *= 1 - mask;
+ colors.set_a(alpha);
+ bitmap.pix32(y, x) = colors;
+ }
+ }
+ file.close();
+ global_free_array(buffer);
+}
+
+#endif /* __UI_ICORENDER_H__ */
diff --git a/src/frontend/mame/ui/imgcntrl.cpp b/src/frontend/mame/ui/imgcntrl.cpp
new file mode 100644
index 00000000000..78bbf1825a2
--- /dev/null
+++ b/src/frontend/mame/ui/imgcntrl.cpp
@@ -0,0 +1,343 @@
+// license:BSD-3-Clause
+// copyright-holders:Nathan Woods
+/***************************************************************************
+
+ ui/imgcntrl.cpp
+
+ MESS's clunky built-in file manager
+
+***************************************************************************/
+
+#include "emu.h"
+#include "emuopts.h"
+#include "ui/ui.h"
+#include "ui/menu.h"
+#include "ui/imgcntrl.h"
+#include "ui/filesel.h"
+#include "ui/swlist.h"
+#include "zippath.h"
+#include "audit.h"
+#include "softlist.h"
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+ui_menu_control_device_image::ui_menu_control_device_image(running_machine &machine, render_container *container, device_image_interface *_image)
+ : ui_menu(machine, container),
+ submenu_result(0),
+ create_ok(false),
+ create_confirmed(false)
+{
+ image = _image;
+
+ if (image->software_list_name())
+ sld = software_list_device::find_by_name(machine.config(), image->software_list_name());
+ else
+ sld = nullptr;
+ swi = image->software_entry();
+ swp = image->part_entry();
+
+ if(swi)
+ {
+ state = START_OTHER_PART;
+ current_directory.assign(image->working_directory());
+ }
+ else
+ {
+ state = START_FILE;
+
+ /* if the image exists, set the working directory to the parent directory */
+ if (image->exists())
+ {
+ current_file.assign(image->filename());
+ util::zippath_parent(current_directory, current_file.c_str());
+ } else
+ current_directory.assign(image->working_directory());
+
+ /* check to see if the path exists; if not clear it */
+ if (util::zippath_opendir(current_directory.c_str(), nullptr) != osd_file::error::NONE)
+ current_directory.clear();
+ }
+}
+
+
+//-------------------------------------------------
+// dtor
+//-------------------------------------------------
+
+ui_menu_control_device_image::~ui_menu_control_device_image()
+{
+}
+
+
+//-------------------------------------------------
+// test_create - creates a new disk image
+//-------------------------------------------------
+
+void ui_menu_control_device_image::test_create(bool &can_create, bool &need_confirm)
+{
+ std::string path;
+ osd_directory_entry *entry;
+ osd_dir_entry_type file_type;
+
+ /* assemble the full path */
+ util::zippath_combine(path, current_directory.c_str(), current_file.c_str());
+
+ /* does a file or a directory exist at the path */
+ entry = osd_stat(path.c_str());
+ file_type = (entry != nullptr) ? entry->type : ENTTYPE_NONE;
+
+ switch(file_type)
+ {
+ case ENTTYPE_NONE:
+ /* no file/dir here - always create */
+ can_create = true;
+ need_confirm = false;
+ break;
+
+ case ENTTYPE_FILE:
+ /* a file exists here - ask for permission from the user */
+ can_create = true;
+ need_confirm = true;
+ break;
+
+ case ENTTYPE_DIR:
+ /* a directory exists here - we can't save over it */
+ mame_machine_manager::instance()->ui().popup_time(5, "%s", _("Cannot save over directory"));
+ can_create = false;
+ need_confirm = false;
+ break;
+
+ default:
+ fatalerror("Unexpected\n");
+ can_create = false;
+ need_confirm = false;
+ break;
+ }
+
+ if (entry != nullptr)
+ osd_free(entry);
+}
+
+
+//-------------------------------------------------
+// load_software_part
+//-------------------------------------------------
+
+void ui_menu_control_device_image::load_software_part()
+{
+ std::string temp_name = std::string(sld->list_name()).append(":").append(swi->shortname()).append(":").append(swp->name());
+
+ driver_enumerator drivlist(machine().options(), machine().options().system_name());
+ drivlist.next();
+ media_auditor auditor(drivlist);
+ media_auditor::summary summary = auditor.audit_software(sld->list_name(), (software_info *)swi, AUDIT_VALIDATE_FAST);
+ // if everything looks good, load software
+ if (summary == media_auditor::CORRECT || summary == media_auditor::BEST_AVAILABLE || summary == media_auditor::NONE_NEEDED)
+ hook_load(temp_name, true);
+ else
+ {
+ machine().popmessage(_("The software selected is missing one or more required ROM or CHD images. Please select a different one."));
+ state = SELECT_SOFTLIST;
+ }
+}
+
+
+//-------------------------------------------------
+// hook_load
+//-------------------------------------------------
+
+void ui_menu_control_device_image::hook_load(std::string name, bool softlist)
+{
+ if (image->is_reset_on_load()) image->set_init_phase();
+ image->load(name.c_str());
+ ui_menu::stack_pop(machine());
+}
+
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_control_device_image::populate()
+{
+}
+
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_menu_control_device_image::handle()
+{
+ switch(state) {
+ case START_FILE: {
+ bool can_create = false;
+ if(image->is_creatable()) {
+ util::zippath_directory *directory = nullptr;
+ osd_file::error err = util::zippath_opendir(current_directory.c_str(), &directory);
+ can_create = err == osd_file::error::NONE && !util::zippath_is_zip(directory);
+ if(directory)
+ util::zippath_closedir(directory);
+ }
+ submenu_result = -1;
+ ui_menu::stack_push(global_alloc_clear<ui_menu_file_selector>(machine(), container, image, current_directory, current_file, true, image->image_interface()!=nullptr, can_create, &submenu_result));
+ state = SELECT_FILE;
+ break;
+ }
+
+ case START_SOFTLIST:
+ sld = nullptr;
+ ui_menu::stack_push(global_alloc_clear<ui_menu_software>(machine(), container, image->image_interface(), &sld));
+ state = SELECT_SOFTLIST;
+ break;
+
+ case START_OTHER_PART: {
+ submenu_result = -1;
+ ui_menu::stack_push(global_alloc_clear<ui_menu_software_parts>(machine(), container, swi, swp->interface(), &swp, true, &submenu_result));
+ state = SELECT_OTHER_PART;
+ break;
+ }
+
+ case SELECT_SOFTLIST:
+ if(!sld) {
+ ui_menu::stack_pop(machine());
+ break;
+ }
+ software_info_name = "";
+ ui_menu::stack_push(global_alloc_clear<ui_menu_software_list>(machine(), container, sld, image->image_interface(), software_info_name));
+ state = SELECT_PARTLIST;
+ break;
+
+ case SELECT_PARTLIST:
+ swi = sld->find(software_info_name.c_str());
+ if (!swi)
+ state = START_SOFTLIST;
+ else if(swi->has_multiple_parts(image->image_interface()))
+ {
+ submenu_result = -1;
+ swp = nullptr;
+ ui_menu::stack_push(global_alloc_clear<ui_menu_software_parts>(machine(), container, swi, image->image_interface(), &swp, false, &submenu_result));
+ state = SELECT_ONE_PART;
+ }
+ else
+ {
+ swp = swi->first_part();
+ load_software_part();
+ }
+ break;
+
+ case SELECT_ONE_PART:
+ switch(submenu_result) {
+ case ui_menu_software_parts::T_ENTRY: {
+ load_software_part();
+ break;
+ }
+
+ case -1: // return to list
+ state = SELECT_SOFTLIST;
+ break;
+
+ }
+ break;
+
+ case SELECT_OTHER_PART:
+ switch(submenu_result) {
+ case ui_menu_software_parts::T_ENTRY:
+ load_software_part();
+ break;
+
+ case ui_menu_software_parts::T_FMGR:
+ state = START_FILE;
+ handle();
+ break;
+
+ case ui_menu_software_parts::T_EMPTY:
+ image->unload();
+ ui_menu::stack_pop(machine());
+ break;
+
+ case ui_menu_software_parts::T_SWLIST:
+ state = START_SOFTLIST;
+ handle();
+ break;
+
+ case -1: // return to system
+ ui_menu::stack_pop(machine());
+ break;
+
+ }
+ break;
+
+ case SELECT_FILE:
+ switch(submenu_result) {
+ case ui_menu_file_selector::R_EMPTY:
+ image->unload();
+ ui_menu::stack_pop(machine());
+ break;
+
+ case ui_menu_file_selector::R_FILE:
+ hook_load(current_file, false);
+ break;
+
+ case ui_menu_file_selector::R_CREATE:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_file_create>(machine(), container, image, current_directory, current_file, &create_ok));
+ state = CHECK_CREATE;
+ break;
+
+ case ui_menu_file_selector::R_SOFTLIST:
+ state = START_SOFTLIST;
+ handle();
+ break;
+
+ case -1: // return to system
+ ui_menu::stack_pop(machine());
+ break;
+ }
+ break;
+
+ case CREATE_FILE: {
+ bool can_create, need_confirm;
+ test_create(can_create, need_confirm);
+ if(can_create) {
+ if(need_confirm) {
+ ui_menu::stack_push(global_alloc_clear<ui_menu_confirm_save_as>(machine(), container, &create_confirmed));
+ state = CREATE_CONFIRM;
+ } else {
+ state = DO_CREATE;
+ handle();
+ }
+ } else {
+ state = START_FILE;
+ handle();
+ }
+ break;
+ }
+
+ case CREATE_CONFIRM:
+ state = create_confirmed ? DO_CREATE : START_FILE;
+ handle();
+ break;
+
+ case CHECK_CREATE:
+ state = create_ok ? CREATE_FILE : START_FILE;
+ handle();
+ break;
+
+ case DO_CREATE: {
+ std::string path;
+ util::zippath_combine(path, current_directory.c_str(), current_file.c_str());
+ int err = image->create(path.c_str(), nullptr, nullptr);
+ if (err != 0)
+ machine().popmessage("Error: %s", image->error());
+ ui_menu::stack_pop(machine());
+ break;
+ }
+ }
+}
diff --git a/src/frontend/mame/ui/imgcntrl.h b/src/frontend/mame/ui/imgcntrl.h
new file mode 100644
index 00000000000..3d978ed617c
--- /dev/null
+++ b/src/frontend/mame/ui/imgcntrl.h
@@ -0,0 +1,62 @@
+// license:BSD-3-Clause
+// copyright-holders:Nathan Woods
+/***************************************************************************
+
+ ui/imgcntrl.h
+
+ MESS's clunky built-in file manager
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_IMGCNTRL_H__
+#define __UI_IMGCNTRL_H__
+
+#include "drivenum.h"
+
+// ======================> ui_menu_control_device_image
+
+class ui_menu_control_device_image : public ui_menu {
+public:
+ ui_menu_control_device_image(running_machine &machine, render_container *container, device_image_interface *image);
+ virtual ~ui_menu_control_device_image();
+ virtual void populate() override;
+ virtual void handle() override;
+
+protected:
+ enum {
+ START_FILE, START_OTHER_PART, START_SOFTLIST,
+ SELECT_PARTLIST, SELECT_ONE_PART, SELECT_OTHER_PART,
+ SELECT_FILE, CREATE_FILE, CREATE_CONFIRM, CHECK_CREATE, DO_CREATE, SELECT_SOFTLIST,
+ LAST_ID
+ };
+
+ // protected instance variables
+ int state;
+ device_image_interface *image;
+ int submenu_result;
+ std::string current_directory;
+ std::string current_file;
+
+ // methods
+ virtual void hook_load(std::string filename, bool softlist);
+
+ bool create_ok;
+
+private:
+ // instance variables
+ bool create_confirmed;
+ //bool softlist_done;
+ const software_info *swi;
+ const software_part *swp;
+ class software_list_device *sld;
+ std::string software_info_name;
+
+ // methods
+ void test_create(bool &can_create, bool &need_confirm);
+ void load_software_part();
+};
+
+
+#endif /* __UI_IMGCNTRL_H__ */
diff --git a/src/frontend/mame/ui/info.cpp b/src/frontend/mame/ui/info.cpp
new file mode 100644
index 00000000000..966d0ca0a33
--- /dev/null
+++ b/src/frontend/mame/ui/info.cpp
@@ -0,0 +1,110 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/***************************************************************************
+
+ ui/info.cpp
+
+ System and image info screens
+
+***************************************************************************/
+
+#include "emu.h"
+#include "ui/menu.h"
+#include "ui/info.h"
+#include "ui/ui.h"
+#include "softlist.h"
+
+/*-------------------------------------------------
+ menu_game_info - handle the game information
+ menu
+ -------------------------------------------------*/
+
+ui_menu_game_info::ui_menu_game_info(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+ui_menu_game_info::~ui_menu_game_info()
+{
+}
+
+void ui_menu_game_info::populate()
+{
+ std::string tempstring;
+ item_append(mame_machine_manager::instance()->ui().game_info_astring(tempstring).c_str(), nullptr, MENU_FLAG_MULTILINE, nullptr);
+}
+
+void ui_menu_game_info::handle()
+{
+ // process the menu
+ process(0);
+}
+
+
+/*-------------------------------------------------
+ ui_menu_image_info - handle the image information
+ menu
+ -------------------------------------------------*/
+
+ui_menu_image_info::ui_menu_image_info(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+ui_menu_image_info::~ui_menu_image_info()
+{
+}
+
+void ui_menu_image_info::populate()
+{
+ item_append(machine().system().description, nullptr, MENU_FLAG_DISABLE, nullptr);
+ item_append("", nullptr, MENU_FLAG_DISABLE, nullptr);
+
+ for (device_image_interface &image : image_interface_iterator(machine().root_device()))
+ image_info(&image);
+}
+
+void ui_menu_image_info::handle()
+{
+ // process the menu
+ process(0);
+}
+
+
+/*-------------------------------------------------
+ image_info - display image info for a specific
+ image interface device
+-------------------------------------------------*/
+
+void ui_menu_image_info::image_info(device_image_interface *image)
+{
+ if (image->exists())
+ {
+ // display device type and filename
+ item_append(image->brief_instance_name(), image->basename(), 0, nullptr);
+
+ // if image has been loaded through softlist, let's add some more info
+ if (image->software_entry())
+ {
+ // display long filename
+ item_append(image->longname(), "", MENU_FLAG_DISABLE, nullptr);
+
+ // display manufacturer and year
+ item_append(string_format("%s, %s", image->manufacturer(), image->year()).c_str(), "", MENU_FLAG_DISABLE, nullptr);
+
+ // display supported information, if available
+ switch (image->supported())
+ {
+ case SOFTWARE_SUPPORTED_NO:
+ item_append(_("Not supported"), "", MENU_FLAG_DISABLE, nullptr);
+ break;
+ case SOFTWARE_SUPPORTED_PARTIAL:
+ item_append(_("Partially supported"), "", MENU_FLAG_DISABLE, nullptr);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ else
+ item_append(image->brief_instance_name(), _("[empty]"), 0, nullptr);
+ item_append("", nullptr, MENU_FLAG_DISABLE, nullptr);
+}
diff --git a/src/frontend/mame/ui/info.h b/src/frontend/mame/ui/info.h
new file mode 100644
index 00000000000..a9459b25340
--- /dev/null
+++ b/src/frontend/mame/ui/info.h
@@ -0,0 +1,37 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/***************************************************************************
+
+ ui/info.h
+
+ System and image info screens
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_INFO_H__
+#define __UI_INFO_H__
+
+class ui_menu_game_info : public ui_menu {
+public:
+ ui_menu_game_info(running_machine &machine, render_container *container);
+ virtual ~ui_menu_game_info();
+ virtual void populate() override;
+ virtual void handle() override;
+};
+
+
+class ui_menu_image_info : public ui_menu
+{
+public:
+ ui_menu_image_info(running_machine &machine, render_container *container);
+ virtual ~ui_menu_image_info();
+ virtual void populate() override;
+ virtual void handle() override;
+
+private:
+ void image_info(device_image_interface *image);
+};
+
+#endif // __UI_INFO_H__
diff --git a/src/frontend/mame/ui/info_pty.cpp b/src/frontend/mame/ui/info_pty.cpp
new file mode 100644
index 00000000000..267f8b1c5b9
--- /dev/null
+++ b/src/frontend/mame/ui/info_pty.cpp
@@ -0,0 +1,43 @@
+// license:BSD-3-Clause
+// copyright-holders:F.Ulivi
+/***************************************************************************
+
+ ui/info_pty.cpp
+
+ Information screen on pseudo terminals
+
+***************************************************************************/
+
+#include "emu.h"
+#include "ui/menu.h"
+#include "ui/info_pty.h"
+
+ui_menu_pty_info::ui_menu_pty_info(running_machine &machine, render_container *container) :
+ ui_menu(machine, container)
+{
+}
+
+ui_menu_pty_info::~ui_menu_pty_info()
+{
+}
+
+void ui_menu_pty_info::populate()
+{
+ item_append(_("Pseudo terminals"), nullptr, MENU_FLAG_DISABLE, nullptr);
+ item_append("", nullptr, MENU_FLAG_DISABLE, nullptr);
+
+ for (device_pty_interface &pty : pty_interface_iterator(machine().root_device()))
+ {
+ const char *port_name = pty.device().owner()->tag() + 1;
+ if (pty.is_open())
+ item_append(port_name, pty.slave_name(), MENU_FLAG_DISABLE, nullptr);
+ else
+ item_append(port_name, _("[failed]"), MENU_FLAG_DISABLE, nullptr);
+ item_append("", nullptr, MENU_FLAG_DISABLE, nullptr);
+ }
+}
+
+void ui_menu_pty_info::handle()
+{
+ process(0);
+}
diff --git a/src/frontend/mame/ui/info_pty.h b/src/frontend/mame/ui/info_pty.h
new file mode 100644
index 00000000000..584652211a6
--- /dev/null
+++ b/src/frontend/mame/ui/info_pty.h
@@ -0,0 +1,24 @@
+// license:BSD-3-Clause
+// copyright-holders:F.Ulivi
+/***************************************************************************
+
+ ui/info_pty.h
+
+ Information screen on pseudo terminals
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_INFO_PTY_H__
+#define __UI_INFO_PTY_H__
+
+class ui_menu_pty_info : public ui_menu {
+public:
+ ui_menu_pty_info(running_machine &machine, render_container *container);
+ virtual ~ui_menu_pty_info();
+ virtual void populate() override;
+ virtual void handle() override;
+};
+
+#endif // __UI_INFO_PTY_H__
diff --git a/src/frontend/mame/ui/inifile.cpp b/src/frontend/mame/ui/inifile.cpp
new file mode 100644
index 00000000000..5e3871a0137
--- /dev/null
+++ b/src/frontend/mame/ui/inifile.cpp
@@ -0,0 +1,454 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/***************************************************************************
+
+ ui/inifile.cpp
+
+ UI INIs file manager.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "ui/ui.h"
+#include "ui/inifile.h"
+#include "softlist.h"
+#include "drivenum.h"
+
+//-------------------------------------------------
+// GLOBAL VARIABLES
+//-------------------------------------------------
+UINT16 inifile_manager::c_cat = 0;
+UINT16 inifile_manager::c_file = 0;
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+inifile_manager::inifile_manager(running_machine &machine)
+ : m_machine(machine)
+{
+ ini_index.clear();
+ directory_scan();
+}
+
+//-------------------------------------------------
+// scan directories and create index
+//-------------------------------------------------
+
+void inifile_manager::directory_scan()
+{
+ // open extra INIs folder
+ file_enumerator path(mame_machine_manager::instance()->ui().options().extraini_path());
+ const osd_directory_entry *dir;
+
+ // loop into folder's file
+ while ((dir = path.next()) != nullptr)
+ {
+ int length = strlen(dir->name);
+ std::string filename(dir->name);
+
+ // check .ini file ending
+ if ((length > 4) && dir->name[length - 4] == '.' && tolower((UINT8)dir->name[length - 3]) == 'i' &&
+ tolower((UINT8)dir->name[length - 2]) == 'n' && tolower((UINT8)dir->name[length - 1]) == 'i')
+ {
+ // try to open file and indexing
+ if (parseopen(filename.c_str()))
+ {
+ init_category(filename);
+ parseclose();
+ }
+ }
+ }
+
+ // sort
+ std::stable_sort(ini_index.begin(), ini_index.end());
+}
+
+//-------------------------------------------------
+// initialize category
+//-------------------------------------------------
+
+void inifile_manager::init_category(std::string &filename)
+{
+ categoryindex index;
+ char rbuf[MAX_CHAR_INFO];
+ std::string readbuf, name;
+ while (fgets(rbuf, MAX_CHAR_INFO, fp) != nullptr)
+ {
+ readbuf = rbuf;
+ if (readbuf[0] == '[')
+ {
+ size_t found = readbuf.find("]");
+ name = readbuf.substr(1, found - 1);
+ if (name == "FOLDER_SETTINGS" || name == "ROOT_FOLDER")
+ continue;
+ else
+ index.emplace_back(name, ftell(fp));
+ }
+ }
+
+ // sort
+ std::stable_sort(index.begin(), index.end());
+
+ if (!index.empty())
+ ini_index.emplace_back(filename, index);
+}
+
+//-------------------------------------------------
+// load and indexing ini files
+//-------------------------------------------------
+
+void inifile_manager::load_ini_category(std::vector<int> &temp_filter)
+{
+ if (ini_index.empty())
+ return;
+
+ bool search_clones = false;
+ std::string filename(ini_index[c_file].first);
+ long offset = ini_index[c_file].second[c_cat].second;
+
+ if (!core_stricmp(filename.c_str(), "category.ini") || !core_stricmp(filename.c_str(), "alltime.ini"))
+ search_clones = true;
+
+ if (parseopen(filename.c_str()))
+ {
+ fseek(fp, offset, SEEK_SET);
+ int num_game = driver_list::total();
+ char rbuf[MAX_CHAR_INFO];
+ std::string readbuf;
+ while (fgets(rbuf, MAX_CHAR_INFO, fp) != nullptr)
+ {
+ readbuf = chartrimcarriage(rbuf);
+
+ if (readbuf.empty() || readbuf[0] == '[')
+ break;
+
+ int dfind = driver_list::find(readbuf.c_str());
+ if (dfind != -1 && search_clones)
+ {
+ temp_filter.push_back(dfind);
+ int clone_of = driver_list::non_bios_clone(dfind);
+ if (clone_of == -1)
+ {
+ for (int x = 0; x < num_game; x++)
+ if (readbuf == driver_list::driver(x).parent && readbuf != driver_list::driver(x).name)
+ temp_filter.push_back(x);
+ }
+ }
+ else if (dfind != -1)
+ temp_filter.push_back(dfind);
+ }
+ parseclose();
+ }
+}
+
+//---------------------------------------------------------
+// parseopen - Open up file for reading
+//---------------------------------------------------------
+
+bool inifile_manager::parseopen(const char *filename)
+{
+ // MAME core file parsing functions fail in recognizing UNICODE chars in UTF-8 without BOM,
+ // so it's better and faster use standard C fileio functions.
+
+ emu_file file(mame_machine_manager::instance()->ui().options().extraini_path(), OPEN_FLAG_READ);
+ if (file.open(filename) != osd_file::error::NONE)
+ return false;
+
+ m_fullpath = file.fullpath();
+ file.close();
+ fp = fopen(m_fullpath.c_str(), "r");
+
+ fgetc(fp);
+ fseek(fp, 0, SEEK_SET);
+ return true;
+}
+
+/**************************************************************************
+ FAVORITE MANAGER
+**************************************************************************/
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+favorite_manager::favorite_manager(running_machine &machine)
+ : m_machine(machine)
+{
+ m_current = -1;
+ parse_favorite();
+}
+
+//-------------------------------------------------
+// add a game
+//-------------------------------------------------
+
+void favorite_manager::add_favorite_game(const game_driver *driver)
+{
+ m_list.emplace_back(driver->name, driver->description, "", "", "", 0, "", driver, "", "", "", 1, "", "", "", true);
+ save_favorite_games();
+}
+
+//-------------------------------------------------
+// add a system
+//-------------------------------------------------
+
+void favorite_manager::add_favorite_game(ui_software_info &swinfo)
+{
+ m_list.push_back(swinfo);
+ save_favorite_games();
+}
+
+//-------------------------------------------------
+// add a game / system
+//-------------------------------------------------
+
+void favorite_manager::add_favorite_game()
+{
+ if ((machine().system().flags & MACHINE_TYPE_ARCADE) != 0)
+ {
+ add_favorite_game(&machine().system());
+ return;
+ }
+
+ bool software_avail = false;
+ for (device_image_interface &image : image_interface_iterator(machine().root_device()))
+ {
+ if (image.exists() && image.software_entry())
+ {
+ const software_info *swinfo = image.software_entry();
+ const software_part *part = image.part_entry();
+ ui_software_info tmpmatches;
+ tmpmatches.shortname = strensure(swinfo->shortname());
+ tmpmatches.longname = strensure(image.longname());
+ tmpmatches.parentname = strensure(swinfo->parentname());
+ tmpmatches.year = strensure(image.year());
+ tmpmatches.publisher = strensure(image.manufacturer());
+ tmpmatches.supported = image.supported();
+ tmpmatches.part = strensure(part->name());
+ tmpmatches.driver = &machine().system();
+ tmpmatches.listname = strensure(image.software_list_name());
+ tmpmatches.interface = strensure(part->interface());
+ tmpmatches.instance = strensure(image.instance_name());
+ tmpmatches.startempty = 0;
+ tmpmatches.parentlongname.clear();
+ if (swinfo->parentname())
+ {
+ software_list_device *swlist = software_list_device::find_by_name(machine().config(), image.software_list_name());
+ for (software_info &c_swinfo : swlist->get_info())
+ {
+ std::string c_parent(c_swinfo.parentname());
+ if (!c_parent.empty() && c_parent == swinfo->shortname())
+ {
+ tmpmatches.parentlongname = c_swinfo.longname();
+ break;
+ }
+ }
+ }
+
+ tmpmatches.usage.clear();
+ for (feature_list_item &flist : swinfo->other_info())
+ if (!strcmp(flist.name(), "usage"))
+ tmpmatches.usage = flist.value();
+
+ tmpmatches.devicetype = strensure(image.image_type_name());
+ tmpmatches.available = true;
+ software_avail = true;
+ m_list.push_back(tmpmatches);
+ save_favorite_games();
+ }
+ }
+
+ if (!software_avail)
+ add_favorite_game(&machine().system());
+}
+
+//-------------------------------------------------
+// remove a favorite from list
+//-------------------------------------------------
+
+void favorite_manager::remove_favorite_game(ui_software_info &swinfo)
+{
+ m_list.erase(std::remove(m_list.begin(), m_list.end(), swinfo), m_list.end());
+ save_favorite_games();
+}
+
+//-------------------------------------------------
+// remove a favorite from list
+//-------------------------------------------------
+
+void favorite_manager::remove_favorite_game()
+{
+ m_list.erase(m_list.begin() + m_current);
+ save_favorite_games();
+}
+
+//-------------------------------------------------
+// check if game is already in favorite list
+//-------------------------------------------------
+
+bool favorite_manager::isgame_favorite()
+{
+ if ((machine().system().flags & MACHINE_TYPE_ARCADE) != 0)
+ return isgame_favorite(&machine().system());
+
+ bool image_loaded = false;
+
+ for (device_image_interface &image : image_interface_iterator(machine().root_device()))
+ {
+ const software_info *swinfo = image.software_entry();
+ if (image.exists() && swinfo != nullptr)
+ {
+ image_loaded = true;
+ for (size_t current = 0; current < m_list.size(); current++)
+ if (m_list[current].shortname == swinfo->shortname() &&
+ m_list[current].listname == image.software_list_name())
+ {
+ m_current = current;
+ return true;
+ }
+ }
+ }
+
+ if (!image_loaded)
+ return isgame_favorite(&machine().system());
+
+ m_current = -1;
+ return false;
+}
+
+//-------------------------------------------------
+// check if game is already in favorite list
+//-------------------------------------------------
+
+bool favorite_manager::isgame_favorite(const game_driver *driver)
+{
+ for (size_t x = 0; x < m_list.size(); x++)
+ if (m_list[x].driver == driver && m_list[x].shortname == driver->name)
+ {
+ m_current = x;
+ return true;
+ }
+
+ m_current = -1;
+ return false;
+}
+
+//-------------------------------------------------
+// check if game is already in favorite list
+//-------------------------------------------------
+
+bool favorite_manager::isgame_favorite(ui_software_info &swinfo)
+{
+ for (size_t x = 0; x < m_list.size(); x++)
+ if (m_list[x] == swinfo)
+ {
+ m_current = x;
+ return true;
+ }
+
+ m_current = -1;
+ return false;
+}
+
+//-------------------------------------------------
+// parse favorite file
+//-------------------------------------------------
+
+void favorite_manager::parse_favorite()
+{
+ emu_file file(mame_machine_manager::instance()->ui().options().ui_path(), OPEN_FLAG_READ);
+ if (file.open(favorite_filename) == osd_file::error::NONE)
+ {
+ char readbuf[1024];
+ file.gets(readbuf, 1024);
+
+ while (readbuf[0] == '[')
+ file.gets(readbuf, 1024);
+
+ while (file.gets(readbuf, 1024))
+ {
+ ui_software_info tmpmatches;
+ tmpmatches.shortname = chartrimcarriage(readbuf);
+ file.gets(readbuf, 1024);
+ tmpmatches.longname = chartrimcarriage(readbuf);
+ file.gets(readbuf, 1024);
+ tmpmatches.parentname = chartrimcarriage(readbuf);
+ file.gets(readbuf, 1024);
+ tmpmatches.year = chartrimcarriage(readbuf);
+ file.gets(readbuf, 1024);
+ tmpmatches.publisher = chartrimcarriage(readbuf);
+ file.gets(readbuf, 1024);
+ tmpmatches.supported = atoi(readbuf);
+ file.gets(readbuf, 1024);
+ tmpmatches.part = chartrimcarriage(readbuf);
+ file.gets(readbuf, 1024);
+ chartrimcarriage(readbuf);
+ int dx = driver_list::find(readbuf);
+ if (dx == -1) continue;
+ tmpmatches.driver = &driver_list::driver(dx);
+ file.gets(readbuf, 1024);
+ tmpmatches.listname = chartrimcarriage(readbuf);
+ file.gets(readbuf, 1024);
+ tmpmatches.interface = chartrimcarriage(readbuf);
+ file.gets(readbuf, 1024);
+ tmpmatches.instance = chartrimcarriage(readbuf);
+ file.gets(readbuf, 1024);
+ tmpmatches.startempty = atoi(readbuf);
+ file.gets(readbuf, 1024);
+ tmpmatches.parentlongname = chartrimcarriage(readbuf);
+ file.gets(readbuf, 1024);
+ tmpmatches.usage = chartrimcarriage(readbuf);
+ file.gets(readbuf, 1024);
+ tmpmatches.devicetype = chartrimcarriage(readbuf);
+ file.gets(readbuf, 1024);
+ tmpmatches.available = atoi(readbuf);
+ m_list.push_back(tmpmatches);
+ }
+ file.close();
+ }
+}
+
+//-------------------------------------------------
+// save favorite
+//-------------------------------------------------
+
+void favorite_manager::save_favorite_games()
+{
+ // attempt to open the output file
+ emu_file file(mame_machine_manager::instance()->ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ if (file.open(favorite_filename) == osd_file::error::NONE)
+ {
+ if (m_list.empty())
+ {
+ file.remove_on_close();
+ file.close();
+ return;
+ }
+
+ // generate the favorite INI
+ std::ostringstream text;
+ text << "[ROOT_FOLDER]\n[Favorite]\n\n";
+ for (auto & elem : m_list)
+ {
+ text << elem.shortname << '\n';
+ text << elem.longname << '\n';
+ text << elem.parentname << '\n';
+ text << elem.year << '\n';
+ text << elem.publisher << '\n';
+ util::stream_format(text, "%d\n", elem.supported);
+ text << elem.part << '\n';
+ util::stream_format(text, "%s\n", elem.driver->name);
+ text << elem.listname << '\n';
+ text << elem.interface << '\n';
+ text << elem.instance << '\n';
+ util::stream_format(text, "%d\n", elem.startempty);
+ text << elem.parentlongname << '\n';
+ text << elem.usage << '\n';
+ text << elem.devicetype << '\n';
+ util::stream_format(text, "%d\n", elem.available);
+ }
+ file.puts(text.str().c_str());
+ file.close();
+ }
+}
diff --git a/src/frontend/mame/ui/inifile.h b/src/frontend/mame/ui/inifile.h
new file mode 100644
index 00000000000..ecc755290a6
--- /dev/null
+++ b/src/frontend/mame/ui/inifile.h
@@ -0,0 +1,117 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/***************************************************************************
+
+ ui/inifile.h
+
+ UI INIs file manager.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_INIFILE_H__
+#define __UI_INIFILE_H__
+
+#include "../frontend/mame/ui/utils.h"
+
+//-------------------------------------------------
+// INIFILE MANAGER
+//-------------------------------------------------
+
+class inifile_manager
+{
+public:
+ // construction/destruction
+ inifile_manager(running_machine &machine);
+
+ // getters
+ running_machine &machine() const { return m_machine; }
+ std::string get_file(int file = -1) { return ((file == -1) ? ini_index[c_file].first : ini_index[file].first); }
+ std::string get_category(int cat = -1) { return ((cat == -1) ? ini_index[c_file].second[c_cat].first : ini_index[c_file].second[cat].first); }
+ size_t total() { return ini_index.size(); }
+ size_t cat_total(int cat = -1) { return ((cat == -1) ? ini_index[c_file].second.size() : ini_index[cat].second.size()); }
+ UINT16 &cur_file() { return c_file; }
+ UINT16 &cur_cat() { return c_cat; }
+
+ // load games from category
+ void load_ini_category(std::vector<int> &temp_filter);
+
+ // setters
+ void move_file(int d) { c_file += d; c_cat = 0; }
+ void move_cat(int d) { c_cat += d; }
+ void set_cat(int i = -1) { (i == -1) ? c_cat = 0 : c_cat = i; }
+ void set_file(int i = -1) { (i == -1) ? c_file = 0 : c_file = i; }
+
+private:
+
+ // ini file structure
+ using categoryindex = std::vector<std::pair<std::string, long>>;
+
+ // files indices
+ static UINT16 c_file, c_cat;
+ std::vector<std::pair<std::string, categoryindex>> ini_index;
+
+ // init category index
+ void init_category(std::string &filename);
+
+ // init file index
+ void directory_scan();
+
+ // file open/close/seek
+ bool parseopen(const char *filename);
+ void parseclose() { if (fp != nullptr) fclose(fp); }
+
+ // internal state
+ running_machine &m_machine; // reference to our machine
+ std::string m_fullpath;
+ FILE *fp = nullptr;
+};
+
+//-------------------------------------------------
+// FAVORITE MANAGER
+//-------------------------------------------------
+
+class favorite_manager
+{
+public:
+ // construction/destruction
+ favorite_manager(running_machine &machine);
+
+ // favorite indices
+ std::vector<ui_software_info> m_list;
+
+ // getters
+ running_machine &machine() const { return m_machine; }
+
+ // add
+ void add_favorite_game();
+ void add_favorite_game(const game_driver *driver);
+ void add_favorite_game(ui_software_info &swinfo);
+
+ // check
+ bool isgame_favorite();
+ bool isgame_favorite(const game_driver *driver);
+ bool isgame_favorite(ui_software_info &swinfo);
+
+ // save
+ void save_favorite_games();
+
+ // remove
+ void remove_favorite_game();
+ void remove_favorite_game(ui_software_info &swinfo);
+
+private:
+ const char *favorite_filename = "favorites.ini";
+
+ // current
+ int m_current;
+
+ // parse file ui_favorite
+ void parse_favorite();
+
+ // internal state
+ running_machine &m_machine; // reference to our machine
+};
+
+#endif /* __UI_INIFILE_H__ */
diff --git a/src/frontend/mame/ui/inputmap.cpp b/src/frontend/mame/ui/inputmap.cpp
new file mode 100644
index 00000000000..d43725b8eb6
--- /dev/null
+++ b/src/frontend/mame/ui/inputmap.cpp
@@ -0,0 +1,930 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/*********************************************************************
+
+ ui/inputmap.cpp
+
+ Internal menus for input mappings.
+
+*********************************************************************/
+
+#include "emu.h"
+
+#include "uiinput.h"
+#include "ui/ui.h"
+#include "ui/menu.h"
+#include "ui/inputmap.h"
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define MAX_PHYSICAL_DIPS 10
+#define MAX_INPUT_PORTS 32
+#define MAX_BITS_PER_PORT 32
+
+/* DIP switch rendering parameters */
+#define DIP_SWITCH_HEIGHT 0.05f
+#define DIP_SWITCH_SPACING 0.01f
+#define SINGLE_TOGGLE_SWITCH_FIELD_WIDTH 0.025f
+#define SINGLE_TOGGLE_SWITCH_WIDTH 0.020f
+/* make the switch 80% of the width space and 1/2 of the switch height */
+#define PERCENTAGE_OF_HALF_FIELD_USED 0.80f
+#define SINGLE_TOGGLE_SWITCH_HEIGHT ((DIP_SWITCH_HEIGHT / 2) * PERCENTAGE_OF_HALF_FIELD_USED)
+
+
+
+/*-------------------------------------------------
+ menu_input_groups_populate - populate the
+ input groups menu
+-------------------------------------------------*/
+
+ui_menu_input_groups::ui_menu_input_groups(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+void ui_menu_input_groups::populate()
+{
+ int player;
+
+ /* build up the menu */
+ item_append(_("User Interface"), nullptr, 0, (void *)(IPG_UI + 1));
+ for (player = 0; player < MAX_PLAYERS; player++)
+ {
+ char buffer[40];
+ sprintf(buffer, "Player %d Controls", player + 1);
+ item_append(buffer, nullptr, 0, (void *)(FPTR)(IPG_PLAYER1 + player + 1));
+ }
+ item_append(_("Other Controls"), nullptr, 0, (void *)(FPTR)(IPG_OTHER + 1));
+}
+
+ui_menu_input_groups::~ui_menu_input_groups()
+{
+}
+
+/*-------------------------------------------------
+ menu_input_groups - handle the input groups
+ menu
+-------------------------------------------------*/
+
+void ui_menu_input_groups::handle()
+{
+ /* process the menu */
+ const ui_menu_event *menu_event = process(0);
+ if (menu_event != nullptr && menu_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_input_general>(machine(), container, int((long long)(menu_event->itemref)-1)));
+}
+
+
+
+/*-------------------------------------------------
+ menu_input_general - handle the general
+ input menu
+-------------------------------------------------*/
+
+ui_menu_input_general::ui_menu_input_general(running_machine &machine, render_container *container, int _group) : ui_menu_input(machine, container)
+{
+ group = _group;
+}
+
+void ui_menu_input_general::populate()
+{
+ input_item_data *itemlist = nullptr;
+ int suborder[SEQ_TYPE_TOTAL];
+ int sortorder = 1;
+
+ /* create a mini lookup table for sort order based on sequence type */
+ suborder[SEQ_TYPE_STANDARD] = 0;
+ suborder[SEQ_TYPE_DECREMENT] = 1;
+ suborder[SEQ_TYPE_INCREMENT] = 2;
+
+ /* iterate over the input ports and add menu items */
+ for (input_type_entry &entry : machine().ioport().types())
+
+ /* add if we match the group and we have a valid name */
+ if (entry.group() == group && entry.name() != nullptr && entry.name()[0] != 0)
+ {
+ input_seq_type seqtype;
+
+ /* loop over all sequence types */
+ sortorder++;
+ for (seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
+ {
+ /* build an entry for the standard sequence */
+ input_item_data *item = (input_item_data *)m_pool_alloc(sizeof(*item));
+ memset(item, 0, sizeof(*item));
+ item->ref = &entry;
+ if(pollingitem && pollingref == &entry && pollingseq == seqtype)
+ pollingitem = item;
+ item->seqtype = seqtype;
+ item->seq = machine().ioport().type_seq(entry.type(), entry.player(), seqtype);
+ item->defseq = &entry.defseq(seqtype);
+ item->sortorder = sortorder * 4 + suborder[seqtype];
+ item->type = ioport_manager::type_is_analog(entry.type()) ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL;
+ item->name = entry.name();
+ item->owner_name = nullptr;
+ item->next = itemlist;
+ itemlist = item;
+
+ /* stop after one, unless we're analog */
+ if (item->type == INPUT_TYPE_DIGITAL)
+ break;
+ }
+ }
+
+ /* sort and populate the menu in a standard fashion */
+ populate_and_sort(itemlist);
+}
+
+ui_menu_input_general::~ui_menu_input_general()
+{
+}
+
+/*-------------------------------------------------
+ menu_input_specific - handle the game-specific
+ input menu
+-------------------------------------------------*/
+
+ui_menu_input_specific::ui_menu_input_specific(running_machine &machine, render_container *container) : ui_menu_input(machine, container)
+{
+}
+
+void ui_menu_input_specific::populate()
+{
+ input_item_data *itemlist = nullptr;
+ int suborder[SEQ_TYPE_TOTAL];
+ int port_count = 0;
+
+ /* create a mini lookup table for sort order based on sequence type */
+ suborder[SEQ_TYPE_STANDARD] = 0;
+ suborder[SEQ_TYPE_DECREMENT] = 1;
+ suborder[SEQ_TYPE_INCREMENT] = 2;
+
+ /* iterate over the input ports and add menu items */
+ for (ioport_port &port : machine().ioport().ports())
+ {
+ port_count++;
+ for (ioport_field &field : port.fields())
+ {
+ const char *name = field.name();
+
+ /* add if we match the group and we have a valid name */
+ if (name != nullptr && field.enabled() &&
+ ((field.type() == IPT_OTHER && field.name() != nullptr) || machine().ioport().type_group(field.type(), field.player()) != IPG_INVALID))
+ {
+ input_seq_type seqtype;
+ UINT32 sortorder;
+
+ /* determine the sorting order */
+ if (field.type() >= IPT_START1 && field.type() < IPT_ANALOG_LAST)
+ {
+ sortorder = (field.type() << 2) | (field.player() << 12);
+ if (strcmp(field.device().tag(), ":"))
+ sortorder |= (port_count & 0xfff) * 0x10000;
+ }
+ else
+ sortorder = field.type() | 0xf000;
+
+ /* loop over all sequence types */
+ for (seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
+ {
+ /* build an entry for the standard sequence */
+ input_item_data *item = (input_item_data *)m_pool_alloc(sizeof(*item));
+ memset(item, 0, sizeof(*item));
+ item->ref = &field;
+ item->seqtype = seqtype;
+ if(pollingitem && pollingref == item->ref && pollingseq == seqtype)
+ pollingitem = item;
+ item->seq = field.seq(seqtype);
+ item->defseq = &field.defseq(seqtype);
+ item->sortorder = sortorder + suborder[seqtype];
+ item->type = field.is_analog() ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL;
+ item->name = name;
+ item->owner_name = field.device().tag();
+ item->next = itemlist;
+ itemlist = item;
+
+ /* stop after one, unless we're analog */
+ if (item->type == INPUT_TYPE_DIGITAL)
+ break;
+ }
+ }
+ }
+ }
+
+ /* sort and populate the menu in a standard fashion */
+ populate_and_sort(itemlist);
+}
+
+ui_menu_input_specific::~ui_menu_input_specific()
+{
+}
+
+/*-------------------------------------------------
+ menu_input - display a menu for inputs
+-------------------------------------------------*/
+ui_menu_input::ui_menu_input(running_machine &machine, render_container *container) : ui_menu(machine, container), last_sortorder(0), record_next(false)
+{
+ pollingitem = nullptr;
+ pollingref = nullptr;
+ pollingseq = SEQ_TYPE_STANDARD;
+}
+
+ui_menu_input::~ui_menu_input()
+{
+}
+
+/*-------------------------------------------------
+ toggle_none_default - toggle between "NONE"
+ and the default item
+-------------------------------------------------*/
+
+void ui_menu_input::toggle_none_default(input_seq &selected_seq, input_seq &original_seq, const input_seq &selected_defseq)
+{
+ /* if we used to be "none", toggle to the default value */
+ if (original_seq.length() == 0)
+ selected_seq = selected_defseq;
+
+ /* otherwise, toggle to "none" */
+ else
+ selected_seq.reset();
+}
+
+void ui_menu_input::handle()
+{
+ input_item_data *seqchangeditem = nullptr;
+ const ui_menu_event *menu_event;
+ int invalidate = false;
+
+ /* process the menu */
+ menu_event = process((pollingitem != nullptr) ? UI_MENU_PROCESS_NOKEYS : 0);
+
+ /* if we are polling, handle as a special case */
+ if (pollingitem != nullptr)
+ {
+ input_item_data *item = pollingitem;
+
+ /* if UI_CANCEL is pressed, abort */
+ if (machine().ui_input().pressed(IPT_UI_CANCEL))
+ {
+ pollingitem = nullptr;
+ record_next = false;
+ toggle_none_default(item->seq, starting_seq, *item->defseq);
+ seqchangeditem = item;
+ }
+
+ /* poll again; if finished, update the sequence */
+ if (machine().input().seq_poll())
+ {
+ pollingitem = nullptr;
+ record_next = true;
+ item->seq = machine().input().seq_poll_final();
+ seqchangeditem = item;
+ }
+ }
+
+ /* otherwise, handle the events */
+ else if (menu_event != nullptr && menu_event->itemref != nullptr)
+ {
+ input_item_data *item = (input_item_data *)menu_event->itemref;
+ switch (menu_event->iptkey)
+ {
+ /* an item was selected: begin polling */
+ case IPT_UI_SELECT:
+ pollingitem = item;
+ last_sortorder = item->sortorder;
+ starting_seq = item->seq;
+ machine().input().seq_poll_start((item->type == INPUT_TYPE_ANALOG) ? ITEM_CLASS_ABSOLUTE : ITEM_CLASS_SWITCH, record_next ? &item->seq : nullptr);
+ invalidate = true;
+ break;
+
+ /* if the clear key was pressed, reset the selected item */
+ case IPT_UI_CLEAR:
+ toggle_none_default(item->seq, item->seq, *item->defseq);
+ record_next = false;
+ seqchangeditem = item;
+ break;
+ }
+
+ /* if the selection changed, reset the "record next" flag */
+ if (item->sortorder != last_sortorder)
+ record_next = false;
+ last_sortorder = item->sortorder;
+ }
+
+ /* if the sequence changed, update it */
+ if (seqchangeditem != nullptr)
+ {
+ update_input(seqchangeditem);
+
+ /* invalidate the menu to force an update */
+ invalidate = true;
+ }
+
+ /* if the menu is invalidated, clear it now */
+ if (invalidate)
+ {
+ pollingref = nullptr;
+ if (pollingitem != nullptr)
+ {
+ pollingref = pollingitem->ref;
+ pollingseq = pollingitem->seqtype;
+ }
+ reset(UI_MENU_RESET_REMEMBER_POSITION);
+ }
+}
+
+void ui_menu_input_general::update_input(struct input_item_data *seqchangeditem)
+{
+ const input_type_entry *entry = (const input_type_entry *)seqchangeditem->ref;
+ machine().ioport().set_type_seq(entry->type(), entry->player(), seqchangeditem->seqtype, seqchangeditem->seq);
+}
+
+void ui_menu_input_specific::update_input(struct input_item_data *seqchangeditem)
+{
+ ioport_field::user_settings settings;
+
+ ((ioport_field *)seqchangeditem->ref)->get_user_settings(settings);
+ settings.seq[seqchangeditem->seqtype] = seqchangeditem->seq;
+ ((ioport_field *)seqchangeditem->ref)->set_user_settings(settings);
+}
+
+
+/*-------------------------------------------------
+ menu_input_compare_items - compare two
+ items for quicksort
+-------------------------------------------------*/
+
+int ui_menu_input::compare_items(const void *i1, const void *i2)
+{
+ const input_item_data * const *data1 = (const input_item_data * const *)i1;
+ const input_item_data * const *data2 = (const input_item_data * const *)i2;
+ if ((*data1)->sortorder < (*data2)->sortorder)
+ return -1;
+ if ((*data1)->sortorder > (*data2)->sortorder)
+ return 1;
+ return 0;
+}
+
+
+/*-------------------------------------------------
+ menu_input_populate_and_sort - take a list
+ of input_item_data objects and build up the
+ menu from them
+-------------------------------------------------*/
+
+void ui_menu_input::populate_and_sort(input_item_data *itemlist)
+{
+ const char *nameformat[INPUT_TYPE_TOTAL] = { nullptr };
+ input_item_data **itemarray, *item;
+ int numitems = 0, curitem;
+ std::string subtext;
+ std::string prev_owner;
+ bool first_entry = true;
+
+ /* create a mini lookup table for name format based on type */
+ nameformat[INPUT_TYPE_DIGITAL] = "%s";
+ nameformat[INPUT_TYPE_ANALOG] = "%s Analog";
+ nameformat[INPUT_TYPE_ANALOG_INC] = "%s Analog Inc";
+ nameformat[INPUT_TYPE_ANALOG_DEC] = "%s Analog Dec";
+
+ /* first count the number of items */
+ for (item = itemlist; item != nullptr; item = item->next)
+ numitems++;
+
+ /* now allocate an array of items and fill it up */
+ itemarray = (input_item_data **)m_pool_alloc(sizeof(*itemarray) * numitems);
+ for (item = itemlist, curitem = 0; item != nullptr; item = item->next)
+ itemarray[curitem++] = item;
+
+ /* sort it */
+ qsort(itemarray, numitems, sizeof(*itemarray), compare_items);
+
+ /* build the menu */
+ for (curitem = 0; curitem < numitems; curitem++)
+ {
+ UINT32 flags = 0;
+
+ /* generate the name of the item itself, based off the base name and the type */
+ item = itemarray[curitem];
+ assert(nameformat[item->type] != nullptr);
+
+ if (item->owner_name && strcmp(item->owner_name, prev_owner.c_str()) != 0)
+ {
+ if (first_entry)
+ first_entry = false;
+ else
+ item_append(ui_menu_item_type::SEPARATOR);
+ item_append(string_format("[root%s]", item->owner_name).c_str(), nullptr, 0, nullptr);
+ prev_owner.assign(item->owner_name);
+ }
+
+ std::string text = string_format(nameformat[item->type], item->name);
+
+ /* if we're polling this item, use some spaces with left/right arrows */
+ if (pollingref == item->ref)
+ {
+ subtext.assign(" ");
+ flags |= MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW;
+ }
+
+ /* otherwise, generate the sequence name and invert it if different from the default */
+ else
+ {
+ subtext = machine().input().seq_name(item->seq);
+ flags |= (item->seq != *item->defseq) ? MENU_FLAG_INVERT : 0;
+ }
+
+ /* add the item */
+ item_append(text.c_str(), subtext.c_str(), flags, item);
+ }
+}
+
+
+/*-------------------------------------------------
+ menu_settings_dip_switches - handle the DIP
+ switches menu
+-------------------------------------------------*/
+
+ui_menu_settings_dip_switches::ui_menu_settings_dip_switches(running_machine &machine, render_container *container) : ui_menu_settings(machine, container, IPT_DIPSWITCH)
+{
+}
+
+ui_menu_settings_dip_switches::~ui_menu_settings_dip_switches()
+{
+}
+
+/*-------------------------------------------------
+ menu_settings_driver_config - handle the
+ driver config menu
+-------------------------------------------------*/
+
+ui_menu_settings_driver_config::ui_menu_settings_driver_config(running_machine &machine, render_container *container) : ui_menu_settings(machine, container, IPT_CONFIG)
+{
+}
+
+ui_menu_settings_driver_config::~ui_menu_settings_driver_config()
+{
+}
+
+/*-------------------------------------------------
+ menu_settings_common - handle one of the
+ switches menus
+-------------------------------------------------*/
+
+void ui_menu_settings::handle()
+{
+ // process the menu
+ const ui_menu_event *menu_event = process(0);
+
+ // handle events
+ if (menu_event != nullptr && menu_event->itemref != nullptr)
+ {
+ // reset
+ if ((FPTR)menu_event->itemref == 1)
+ {
+ if (menu_event->iptkey == IPT_UI_SELECT)
+ machine().schedule_hard_reset();
+ }
+ // actual settings
+ else
+ {
+ ioport_field *field = (ioport_field *)menu_event->itemref;
+ ioport_field::user_settings settings;
+ int changed = false;
+
+ switch (menu_event->iptkey)
+ {
+ /* if selected, reset to default value */
+ case IPT_UI_SELECT:
+ field->get_user_settings(settings);
+ settings.value = field->defvalue();
+ field->set_user_settings(settings);
+ changed = true;
+ break;
+
+ /* left goes to previous setting */
+ case IPT_UI_LEFT:
+ field->select_previous_setting();
+ changed = true;
+ break;
+
+ /* right goes to next setting */
+ case IPT_UI_RIGHT:
+ field->select_next_setting();
+ changed = true;
+ break;
+ }
+
+ /* if anything changed, rebuild the menu, trying to stay on the same field */
+ if (changed)
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ menu_settings_populate - populate one of the
+ switches menus
+-------------------------------------------------*/
+
+ui_menu_settings::ui_menu_settings(running_machine &machine, render_container *container, UINT32 _type) : ui_menu(machine, container), diplist(nullptr), dipcount(0)
+{
+ type = _type;
+}
+
+void ui_menu_settings::populate()
+{
+ dip_descriptor **diplist_tailptr;
+ std::string prev_owner;
+ bool first_entry = true;
+
+ /* reset the dip switch tracking */
+ dipcount = 0;
+ diplist = nullptr;
+ diplist_tailptr = &diplist;
+
+ /* loop over input ports and set up the current values */
+ for (ioport_port &port : machine().ioport().ports())
+ for (ioport_field &field : port.fields())
+ if (field.type() == type && field.enabled())
+ {
+ UINT32 flags = 0;
+
+ /* set the left/right flags appropriately */
+ if (field.has_previous_setting())
+ flags |= MENU_FLAG_LEFT_ARROW;
+ if (field.has_next_setting())
+ flags |= MENU_FLAG_RIGHT_ARROW;
+
+ /* add the menu item */
+ if (strcmp(field.device().tag(), prev_owner.c_str()) != 0)
+ {
+ if (first_entry)
+ first_entry = false;
+ else
+ item_append(ui_menu_item_type::SEPARATOR);
+ string_format("[root%s]", field.device().tag());
+ item_append(string_format("[root%s]", field.device().tag()).c_str(), nullptr, 0, nullptr);
+ prev_owner.assign(field.device().tag());
+ }
+
+ item_append(field.name(), field.setting_name(), flags, (void *)&field);
+
+ /* for DIP switches, build up the model */
+ if (type == IPT_DIPSWITCH && !field.diplocations().empty())
+ {
+ ioport_field::user_settings settings;
+ UINT32 accummask = field.mask();
+
+ /* get current settings */
+ field.get_user_settings(settings);
+
+ /* iterate over each bit in the field */
+ for (const ioport_diplocation &diploc : field.diplocations())
+ {
+ UINT32 mask = accummask & ~(accummask - 1);
+ dip_descriptor *dip;
+
+ /* find the matching switch name */
+ for (dip = diplist; dip != nullptr; dip = dip->next)
+ if (strcmp(dip->name, diploc.name()) == 0)
+ break;
+
+ /* allocate new if none */
+ if (dip == nullptr)
+ {
+ dip = (dip_descriptor *)m_pool_alloc(sizeof(*dip));
+ dip->next = nullptr;
+ dip->name = diploc.name();
+ dip->mask = dip->state = 0;
+ *diplist_tailptr = dip;
+ diplist_tailptr = &dip->next;
+ dipcount++;
+ }
+
+ /* apply the bits */
+ dip->mask |= 1 << (diploc.number() - 1);
+ if (((settings.value & mask) != 0 && !diploc.inverted()) || ((settings.value & mask) == 0 && diploc.inverted()))
+ dip->state |= 1 << (diploc.number() - 1);
+
+ /* clear the relevant bit in the accumulated mask */
+ accummask &= ~mask;
+ }
+ }
+ }
+ if (type == IPT_DIPSWITCH)
+ custombottom = dipcount ? dipcount * (DIP_SWITCH_HEIGHT + DIP_SWITCH_SPACING) + DIP_SWITCH_SPACING : 0;
+
+ item_append(ui_menu_item_type::SEPARATOR);
+ item_append(_("Reset"), nullptr, 0, (void *)1);
+}
+
+ui_menu_settings::~ui_menu_settings()
+{
+}
+
+/*-------------------------------------------------
+ menu_settings_custom_render - perform our special
+ rendering
+-------------------------------------------------*/
+
+void ui_menu_settings_dip_switches::custom_render(void *selectedref, float top, float bottom, float x1, float y1, float x2, float y2)
+{
+ // catch if no diploc has to be drawn
+ if (bottom == 0)
+ return;
+
+ // add borders
+ y1 = y2 + UI_BOX_TB_BORDER;
+ y2 = y1 + bottom;
+
+ // draw extra menu area
+ mame_machine_manager::instance()->ui().draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
+ y1 += (float)DIP_SWITCH_SPACING;
+
+ // iterate over DIP switches
+ for (dip_descriptor *dip = diplist; dip != nullptr; dip = dip->next)
+ {
+ UINT32 selectedmask = 0;
+
+ // determine the mask of selected bits
+ if ((FPTR)selectedref != 1)
+ {
+ ioport_field *field = (ioport_field *)selectedref;
+
+ if (field != nullptr && !field->diplocations().empty())
+ for (const ioport_diplocation &diploc : field->diplocations())
+ if (strcmp(dip->name, diploc.name()) == 0)
+ selectedmask |= 1 << (diploc.number() - 1);
+ }
+
+ // draw one switch
+ custom_render_one(x1, y1, x2, y1 + DIP_SWITCH_HEIGHT, dip, selectedmask);
+ y1 += (float)(DIP_SWITCH_SPACING + DIP_SWITCH_HEIGHT);
+ }
+}
+
+
+/*-------------------------------------------------
+ menu_settings_custom_render_one - draw a single
+ DIP switch
+-------------------------------------------------*/
+
+void ui_menu_settings_dip_switches::custom_render_one(float x1, float y1, float x2, float y2, const dip_descriptor *dip, UINT32 selectedmask)
+{
+ float switch_field_width = SINGLE_TOGGLE_SWITCH_FIELD_WIDTH * container->manager().ui_aspect();
+ float switch_width = SINGLE_TOGGLE_SWITCH_WIDTH * container->manager().ui_aspect();
+ int numtoggles, toggle;
+ float switch_toggle_gap;
+ float y1_off, y1_on;
+
+ /* determine the number of toggles in the DIP */
+ numtoggles = 32 - count_leading_zeros(dip->mask);
+
+ /* center based on the number of switches */
+ x1 += (x2 - x1 - numtoggles * switch_field_width) / 2;
+
+ /* draw the dip switch name */
+ mame_machine_manager::instance()->ui().draw_text_full( container,
+ dip->name,
+ 0,
+ y1 + (DIP_SWITCH_HEIGHT - UI_TARGET_FONT_HEIGHT) / 2,
+ x1 - mame_machine_manager::instance()->ui().get_string_width(" "),
+ JUSTIFY_RIGHT,
+ WRAP_NEVER,
+ DRAW_NORMAL,
+ UI_TEXT_COLOR,
+ PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA),
+ nullptr ,
+ nullptr);
+
+ /* compute top and bottom for on and off positions */
+ switch_toggle_gap = ((DIP_SWITCH_HEIGHT/2) - SINGLE_TOGGLE_SWITCH_HEIGHT)/2;
+ y1_off = y1 + UI_LINE_WIDTH + switch_toggle_gap;
+ y1_on = y1 + DIP_SWITCH_HEIGHT/2 + switch_toggle_gap;
+
+ /* iterate over toggles */
+ for (toggle = 0; toggle < numtoggles; toggle++)
+ {
+ float innerx1;
+
+ /* first outline the switch */
+ mame_machine_manager::instance()->ui().draw_outlined_box(container, x1, y1, x1 + switch_field_width, y2, UI_BACKGROUND_COLOR);
+
+ /* compute x1/x2 for the inner filled in switch */
+ innerx1 = x1 + (switch_field_width - switch_width) / 2;
+
+ /* see if the switch is actually used */
+ if (dip->mask & (1 << toggle))
+ {
+ float innery1 = (dip->state & (1 << toggle)) ? y1_on : y1_off;
+ container->add_rect(innerx1, innery1, innerx1 + switch_width, innery1 + SINGLE_TOGGLE_SWITCH_HEIGHT,
+ (selectedmask & (1 << toggle)) ? UI_DIPSW_COLOR : UI_TEXT_COLOR,
+ PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ }
+ else
+ {
+ container->add_rect(innerx1, y1_off, innerx1 + switch_width, y1_on + SINGLE_TOGGLE_SWITCH_HEIGHT,
+ UI_UNAVAILABLE_COLOR,
+ PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ }
+
+ /* advance to the next switch */
+ x1 += switch_field_width;
+ }
+}
+
+
+/*-------------------------------------------------
+ menu_analog - handle the analog settings menu
+-------------------------------------------------*/
+
+void ui_menu_analog::handle()
+{
+ /* process the menu */
+ const ui_menu_event *menu_event = process(UI_MENU_PROCESS_LR_REPEAT);
+
+ /* handle events */
+ if (menu_event != nullptr && menu_event->itemref != nullptr)
+ {
+ analog_item_data *data = (analog_item_data *)menu_event->itemref;
+ int newval = data->cur;
+
+ switch (menu_event->iptkey)
+ {
+ /* if selected, reset to default value */
+ case IPT_UI_SELECT:
+ newval = data->defvalue;
+ break;
+
+ /* left decrements */
+ case IPT_UI_LEFT:
+ newval -= machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1;
+ break;
+
+ /* right increments */
+ case IPT_UI_RIGHT:
+ newval += machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1;
+ break;
+ }
+
+ /* clamp to range */
+ if (newval < data->min)
+ newval = data->min;
+ if (newval > data->max)
+ newval = data->max;
+
+ /* if things changed, update */
+ if (newval != data->cur)
+ {
+ ioport_field::user_settings settings;
+
+ /* get the settings and set the new value */
+ data->field->get_user_settings(settings);
+ switch (data->type)
+ {
+ case ANALOG_ITEM_KEYSPEED: settings.delta = newval; break;
+ case ANALOG_ITEM_CENTERSPEED: settings.centerdelta = newval; break;
+ case ANALOG_ITEM_REVERSE: settings.reverse = newval; break;
+ case ANALOG_ITEM_SENSITIVITY: settings.sensitivity = newval; break;
+ }
+ data->field->set_user_settings(settings);
+
+ /* rebuild the menu */
+ reset(UI_MENU_RESET_REMEMBER_POSITION);
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ menu_analog_populate - populate the analog
+ settings menu
+-------------------------------------------------*/
+
+ui_menu_analog::ui_menu_analog(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+void ui_menu_analog::populate()
+{
+ std::string text;
+ std::string subtext;
+ std::string prev_owner;
+ bool first_entry = true;
+
+ /* loop over input ports and add the items */
+ for (ioport_port &port : machine().ioport().ports())
+ for (ioport_field &field : port.fields())
+ if (field.is_analog() && field.enabled())
+ {
+ ioport_field::user_settings settings;
+ int use_autocenter = false;
+ int type;
+
+ /* based on the type, determine if we enable autocenter */
+ switch (field.type())
+ {
+ case IPT_POSITIONAL:
+ case IPT_POSITIONAL_V:
+ if (field.analog_wraps())
+ break;
+
+ case IPT_AD_STICK_X:
+ case IPT_AD_STICK_Y:
+ case IPT_AD_STICK_Z:
+ case IPT_PADDLE:
+ case IPT_PADDLE_V:
+ case IPT_PEDAL:
+ case IPT_PEDAL2:
+ case IPT_PEDAL3:
+ use_autocenter = true;
+ break;
+
+ default:
+ break;
+ }
+
+ /* get the user settings */
+ field.get_user_settings(settings);
+
+ /* iterate over types */
+ for (type = 0; type < ANALOG_ITEM_COUNT; type++)
+ if (type != ANALOG_ITEM_CENTERSPEED || use_autocenter)
+ {
+ analog_item_data *data;
+ UINT32 flags = 0;
+ if (strcmp(field.device().tag(), prev_owner.c_str()) != 0)
+ {
+ if (first_entry)
+ first_entry = false;
+ else
+ item_append(ui_menu_item_type::SEPARATOR);
+ item_append(string_format("[root%s]", field.device().tag()).c_str(), nullptr, 0, nullptr);
+ prev_owner.assign(field.device().tag());
+ }
+
+ /* allocate a data item for tracking what this menu item refers to */
+ data = (analog_item_data *)m_pool_alloc(sizeof(*data));
+ data->field = &field;
+ data->type = type;
+
+ /* determine the properties of this item */
+ switch (type)
+ {
+ default:
+ case ANALOG_ITEM_KEYSPEED:
+ text = string_format("%s Digital Speed", field.name());
+ subtext = string_format("%d", settings.delta);
+ data->min = 0;
+ data->max = 255;
+ data->cur = settings.delta;
+ data->defvalue = field.delta();
+ break;
+
+ case ANALOG_ITEM_CENTERSPEED:
+ text = string_format("%s Autocenter Speed", field.name());
+ subtext = string_format("%d", settings.centerdelta);
+ data->min = 0;
+ data->max = 255;
+ data->cur = settings.centerdelta;
+ data->defvalue = field.centerdelta();
+ break;
+
+ case ANALOG_ITEM_REVERSE:
+ text = string_format("%s Reverse", field.name());
+ subtext.assign(settings.reverse ? "On" : "Off");
+ data->min = 0;
+ data->max = 1;
+ data->cur = settings.reverse;
+ data->defvalue = field.analog_reverse();
+ break;
+
+ case ANALOG_ITEM_SENSITIVITY:
+ text = string_format("%s Sensitivity", field.name());
+ subtext = string_format("%d", settings.sensitivity);
+ data->min = 1;
+ data->max = 255;
+ data->cur = settings.sensitivity;
+ data->defvalue = field.sensitivity();
+ break;
+ }
+
+ /* put on arrows */
+ if (data->cur > data->min)
+ flags |= MENU_FLAG_LEFT_ARROW;
+ if (data->cur < data->max)
+ flags |= MENU_FLAG_RIGHT_ARROW;
+
+ /* append a menu item */
+ item_append(text.c_str(), subtext.c_str(), flags, data);
+ }
+ }
+}
+
+ui_menu_analog::~ui_menu_analog()
+{
+}
diff --git a/src/frontend/mame/ui/inputmap.h b/src/frontend/mame/ui/inputmap.h
new file mode 100644
index 00000000000..32ad48092ea
--- /dev/null
+++ b/src/frontend/mame/ui/inputmap.h
@@ -0,0 +1,155 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/***************************************************************************
+
+ ui/inputmap.h
+
+ Internal menus for input mappings.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_INPUTMAP_H__
+#define __UI_INPUTMAP_H__
+
+//#include "drivenum.h"
+
+class ui_menu_input_groups : public ui_menu {
+public:
+ ui_menu_input_groups(running_machine &machine, render_container *container);
+ virtual ~ui_menu_input_groups();
+ virtual void populate() override;
+ virtual void handle() override;
+};
+
+class ui_menu_input : public ui_menu {
+public:
+ ui_menu_input(running_machine &machine, render_container *container);
+ virtual ~ui_menu_input();
+ virtual void handle() override;
+
+protected:
+ enum {
+ INPUT_TYPE_DIGITAL = 0,
+ INPUT_TYPE_ANALOG = 1,
+ INPUT_TYPE_ANALOG_DEC = INPUT_TYPE_ANALOG + SEQ_TYPE_DECREMENT,
+ INPUT_TYPE_ANALOG_INC = INPUT_TYPE_ANALOG + SEQ_TYPE_INCREMENT,
+ INPUT_TYPE_TOTAL = INPUT_TYPE_ANALOG + SEQ_TYPE_TOTAL
+ };
+
+ /* internal input menu item data */
+ struct input_item_data {
+ input_item_data * next; /* pointer to next item in the list */
+ const void * ref; /* reference to type description for global inputs or field for game inputs */
+ input_seq_type seqtype; /* sequence type */
+ input_seq seq; /* copy of the live sequence */
+ const input_seq * defseq; /* pointer to the default sequence */
+ const char * name; /* pointer to the base name of the item */
+ const char * owner_name; /* pointer to the name of the owner of the item */
+ UINT32 sortorder; /* sorting information */
+ UINT8 type; /* type of port */
+ };
+
+ void populate_and_sort(struct input_item_data *itemlist);
+ virtual void update_input(struct input_item_data *seqchangeditem) = 0;
+ void toggle_none_default(input_seq &selected_seq, input_seq &original_seq, const input_seq &selected_defseq);
+
+protected:
+ const void * pollingref;
+ input_seq_type pollingseq;
+ input_item_data * pollingitem;
+
+private:
+ UINT16 last_sortorder;
+ bool record_next;
+ input_seq starting_seq;
+
+ static int compare_items(const void *i1, const void *i2);
+};
+
+class ui_menu_input_general : public ui_menu_input {
+public:
+ ui_menu_input_general(running_machine &machine, render_container *container, int group);
+ virtual ~ui_menu_input_general();
+ virtual void populate() override;
+
+protected:
+ int group;
+ virtual void update_input(struct input_item_data *seqchangeditem) override;
+};
+
+class ui_menu_input_specific : public ui_menu_input {
+public:
+ ui_menu_input_specific(running_machine &machine, render_container *container);
+ virtual ~ui_menu_input_specific();
+ virtual void populate() override;
+
+protected:
+ virtual void update_input(struct input_item_data *seqchangeditem) override;
+};
+
+class ui_menu_settings : public ui_menu {
+public:
+ ui_menu_settings(running_machine &machine, render_container *container, UINT32 type);
+ virtual ~ui_menu_settings();
+ virtual void populate() override;
+ virtual void handle() override;
+
+protected:
+ /* DIP switch descriptor */
+ struct dip_descriptor {
+ dip_descriptor * next;
+ const char * name;
+ UINT32 mask;
+ UINT32 state;
+ };
+
+ dip_descriptor * diplist;
+ int dipcount;
+ int type;
+};
+
+class ui_menu_settings_dip_switches : public ui_menu_settings {
+public:
+ ui_menu_settings_dip_switches(running_machine &machine, render_container *container);
+ virtual ~ui_menu_settings_dip_switches();
+
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+private:
+ void custom_render_one(float x1, float y1, float x2, float y2, const dip_descriptor *dip, UINT32 selectedmask);
+};
+
+class ui_menu_settings_driver_config : public ui_menu_settings {
+public:
+ ui_menu_settings_driver_config(running_machine &machine, render_container *container);
+ virtual ~ui_menu_settings_driver_config();
+};
+
+class ui_menu_analog : public ui_menu {
+public:
+ ui_menu_analog(running_machine &machine, render_container *container);
+ virtual ~ui_menu_analog();
+ virtual void populate() override;
+ virtual void handle() override;
+
+private:
+ enum {
+ ANALOG_ITEM_KEYSPEED = 0,
+ ANALOG_ITEM_CENTERSPEED,
+ ANALOG_ITEM_REVERSE,
+ ANALOG_ITEM_SENSITIVITY,
+ ANALOG_ITEM_COUNT
+ };
+
+ /* internal analog menu item data */
+ struct analog_item_data {
+ ioport_field *field;
+ int type;
+ int min, max;
+ int cur;
+ int defvalue;
+ };
+};
+
+#endif /* __UI_INPUTMAP_H__ */
diff --git a/src/frontend/mame/ui/mainmenu.cpp b/src/frontend/mame/ui/mainmenu.cpp
new file mode 100644
index 00000000000..1202bd136f2
--- /dev/null
+++ b/src/frontend/mame/ui/mainmenu.cpp
@@ -0,0 +1,284 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/*********************************************************************
+
+ ui/mainmenu.cpp
+
+ Internal MAME menus for the user interface.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "crsshair.h"
+#include "emuopts.h"
+#include "rendutil.h"
+#include "cheat.h"
+#include "ui/menu.h"
+#include "ui/filemngr.h"
+#include "ui/barcode.h"
+#include "ui/cheatopt.h"
+#include "ui/info.h"
+#include "ui/info_pty.h"
+#include "ui/inputmap.h"
+#include "ui/mainmenu.h"
+#include "ui/miscmenu.h"
+#include "ui/selgame.h"
+#include "ui/simpleselgame.h"
+#include "ui/sliders.h"
+#include "ui/slotopt.h"
+#include "ui/tapectrl.h"
+#include "ui/videoopt.h"
+#include "imagedev/cassette.h"
+#include "machine/bcreader.h"
+#include "ui/datfile.h"
+#include "ui/inifile.h"
+#include "ui/datmenu.h"
+#include "ui/pluginopt.h"
+
+
+/***************************************************************************
+ MENU HANDLERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ ui_menu_main constructor - populate the main menu
+-------------------------------------------------*/
+
+ui_menu_main::ui_menu_main(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+void ui_menu_main::populate()
+{
+ /* add input menu items */
+ item_append(_("Input (general)"), nullptr, 0, (void *)INPUT_GROUPS);
+
+ item_append(_("Input (this Machine)"), nullptr, 0, (void *)INPUT_SPECIFIC);
+
+ /* add optional input-related menus */
+ if (machine().ioport().has_analog())
+ item_append(_("Analog Controls"), nullptr, 0, (void *)ANALOG);
+ if (machine().ioport().has_dips())
+ item_append(_("Dip Switches"), nullptr, 0, (void *)SETTINGS_DIP_SWITCHES);
+ if (machine().ioport().has_configs())
+ {
+ item_append(_("Machine Configuration"), nullptr, 0, (void *)SETTINGS_DRIVER_CONFIG);
+ }
+
+ /* add bookkeeping menu */
+ item_append(_("Bookkeeping Info"), nullptr, 0, (void *)BOOKKEEPING);
+
+ /* add game info menu */
+ item_append(_("Machine Information"), nullptr, 0, (void *)GAME_INFO);
+
+ for (device_image_interface &image : image_interface_iterator(machine().root_device()))
+ {
+ if (image.user_loadable())
+ {
+ /* add image info menu */
+ item_append(_("Image Information"), nullptr, 0, (void *)IMAGE_MENU_IMAGE_INFO);
+
+ /* add file manager menu */
+ item_append(_("File Manager"), nullptr, 0, (void *)IMAGE_MENU_FILE_MANAGER);
+
+ break;
+ }
+ }
+
+ /* add tape control menu */
+ if (cassette_device_iterator(machine().root_device()).first() != nullptr)
+ item_append(_("Tape Control"), nullptr, 0, (void *)TAPE_CONTROL);
+
+ if (pty_interface_iterator(machine().root_device()).first() != nullptr)
+ item_append(_("Pseudo terminals"), nullptr, 0, (void *)PTY_INFO);
+
+ if (machine().ioport().has_bioses())
+ item_append(_("Bios Selection"), nullptr, 0, (void *)BIOS_SELECTION);
+
+ /* add slot info menu */
+ if (slot_interface_iterator(machine().root_device()).first() != nullptr)
+ item_append(_("Slot Devices"), nullptr, 0, (void *)SLOT_DEVICES);
+
+ /* add Barcode reader menu */
+ if (barcode_reader_device_iterator(machine().root_device()).first() != nullptr)
+ item_append(_("Barcode Reader"), nullptr, 0, (void *)BARCODE_READ);
+
+ /* add network info menu */
+ if (network_interface_iterator(machine().root_device()).first() != nullptr)
+ item_append(_("Network Devices"), nullptr, 0, (void*)NETWORK_DEVICES);
+
+ /* add keyboard mode menu */
+ if (machine().ioport().has_keyboard() && machine().ioport().natkeyboard().can_post())
+ item_append(_("Keyboard Mode"), nullptr, 0, (void *)KEYBOARD_MODE);
+
+ /* add sliders menu */
+ item_append(_("Slider Controls"), nullptr, 0, (void *)SLIDERS);
+
+ /* add video options menu */
+ item_append(_("Video Options"), nullptr, 0, (machine().render().target_by_index(1) != nullptr) ? (void *)VIDEO_TARGETS : (void *)VIDEO_OPTIONS);
+
+ /* add crosshair options menu */
+ if (machine().crosshair().get_usage())
+ item_append(_("Crosshair Options"), nullptr, 0, (void *)CROSSHAIR);
+
+ /* add cheat menu */
+ if (machine().options().cheat())
+ item_append(_("Cheat"), nullptr, 0, (void *)CHEAT);
+
+ if (machine().options().plugins())
+ item_append(_("Plugin Options"), nullptr, 0, (void *)PLUGINS);
+
+ // add dats menu
+ if (mame_machine_manager::instance()->ui().options().enabled_dats() && mame_machine_manager::instance()->datfile().has_data())
+ item_append(_("External DAT View"), nullptr, 0, (void *)EXTERNAL_DATS);
+
+ item_append(ui_menu_item_type::SEPARATOR);
+
+ /* add favorite menu */
+ if (!mame_machine_manager::instance()->favorite().isgame_favorite())
+ item_append(_("Add To Favorites"), nullptr, 0, (void *)ADD_FAVORITE);
+ else
+ item_append(_("Remove From Favorites"), nullptr, 0, (void *)REMOVE_FAVORITE);
+
+ item_append(ui_menu_item_type::SEPARATOR);
+
+// item_append(_("Quit from Machine"), nullptr, 0, (void *)QUIT_GAME);
+
+ /* add reset and exit menus */
+ item_append(_("Select New Machine"), nullptr, 0, (void *)SELECT_GAME);
+}
+
+ui_menu_main::~ui_menu_main()
+{
+}
+
+/*-------------------------------------------------
+ menu_main - handle the main menu
+-------------------------------------------------*/
+
+void ui_menu_main::handle()
+{
+ /* process the menu */
+ const ui_menu_event *menu_event = process(0);
+ if (menu_event != nullptr && menu_event->iptkey == IPT_UI_SELECT) {
+ switch((long long)(menu_event->itemref)) {
+ case INPUT_GROUPS:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_input_groups>(machine(), container));
+ break;
+
+ case INPUT_SPECIFIC:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_input_specific>(machine(), container));
+ break;
+
+ case SETTINGS_DIP_SWITCHES:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_settings_dip_switches>(machine(), container));
+ break;
+
+ case SETTINGS_DRIVER_CONFIG:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_settings_driver_config>(machine(), container));
+ break;
+
+ case ANALOG:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_analog>(machine(), container));
+ break;
+
+ case BOOKKEEPING:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_bookkeeping>(machine(), container));
+ break;
+
+ case GAME_INFO:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_game_info>(machine(), container));
+ break;
+
+ case IMAGE_MENU_IMAGE_INFO:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_image_info>(machine(), container));
+ break;
+
+ case IMAGE_MENU_FILE_MANAGER:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_file_manager>(machine(), container, nullptr));
+ break;
+
+ case TAPE_CONTROL:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_tape_control>(machine(), container, nullptr));
+ break;
+
+ case PTY_INFO:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_pty_info>(machine(), container));
+ break;
+
+ case SLOT_DEVICES:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_slot_devices>(machine(), container));
+ break;
+
+ case NETWORK_DEVICES:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_network_devices>(machine(), container));
+ break;
+
+ case KEYBOARD_MODE:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_keyboard_mode>(machine(), container));
+ break;
+
+ case SLIDERS:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_sliders>(machine(), container, false));
+ break;
+
+ case VIDEO_TARGETS:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_video_targets>(machine(), container));
+ break;
+
+ case VIDEO_OPTIONS:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_video_options>(machine(), container, machine().render().first_target()));
+ break;
+
+ case CROSSHAIR:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_crosshair>(machine(), container));
+ break;
+
+ case CHEAT:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_cheat>(machine(), container));
+ break;
+
+ case PLUGINS:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_plugin>(machine(), container));
+ break;
+
+ case SELECT_GAME:
+ if (strcmp(machine().options().ui(),"simple")==0) {
+ ui_menu::stack_push(global_alloc_clear<ui_simple_menu_select_game>(machine(), container, nullptr));
+ } else {
+ ui_menu::stack_push(global_alloc_clear<ui_menu_select_game>(machine(), container, nullptr));
+ }
+ break;
+
+ case BIOS_SELECTION:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_bios_selection>(machine(), container));
+ break;
+
+ case BARCODE_READ:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_barcode_reader>(machine(), container, nullptr));
+ break;
+
+ case EXTERNAL_DATS:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_dats_view>(machine(), container));
+ break;
+
+ case ADD_FAVORITE:
+ mame_machine_manager::instance()->favorite().add_favorite_game();
+ reset(UI_MENU_RESET_REMEMBER_POSITION);
+ break;
+
+ case REMOVE_FAVORITE:
+ mame_machine_manager::instance()->favorite().remove_favorite_game();
+ reset(UI_MENU_RESET_REMEMBER_POSITION);
+ break;
+
+ case QUIT_GAME:
+ ui_menu::stack_pop(machine());
+ mame_machine_manager::instance()->ui().request_quit();
+ break;
+
+ default:
+ fatalerror("ui_menu_main::handle - unknown reference\n");
+ }
+ }
+}
diff --git a/src/frontend/mame/ui/mainmenu.h b/src/frontend/mame/ui/mainmenu.h
new file mode 100644
index 00000000000..cb12e6e1d1a
--- /dev/null
+++ b/src/frontend/mame/ui/mainmenu.h
@@ -0,0 +1,59 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/***************************************************************************
+
+ ui/mainmenu.h
+
+ Internal MAME menus for the user interface.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_MAINMENU_H__
+#define __UI_MAINMENU_H__
+
+#include "drivenum.h"
+
+class ui_menu_main : public ui_menu {
+public:
+ ui_menu_main(running_machine &machine, render_container *container);
+ virtual ~ui_menu_main();
+ virtual void populate() override;
+ virtual void handle() override;
+
+private:
+ enum {
+ INPUT_GROUPS,
+ INPUT_SPECIFIC,
+ SETTINGS_DIP_SWITCHES,
+ SETTINGS_DRIVER_CONFIG,
+ ANALOG,
+ BOOKKEEPING,
+ GAME_INFO,
+ IMAGE_MENU_IMAGE_INFO,
+ IMAGE_MENU_FILE_MANAGER,
+ TAPE_CONTROL,
+ SLOT_DEVICES,
+ NETWORK_DEVICES,
+ KEYBOARD_MODE,
+ SLIDERS,
+ VIDEO_TARGETS,
+ VIDEO_OPTIONS,
+ CROSSHAIR,
+ CHEAT,
+ PLUGINS,
+ SELECT_GAME,
+ BIOS_SELECTION,
+ BARCODE_READ,
+ PTY_INFO,
+ EXTERNAL_DATS,
+ ADD_FAVORITE,
+ REMOVE_FAVORITE,
+ QUIT_GAME
+ };
+
+ //bool submenu;
+};
+
+#endif /* __UI_MAINMENU_H__ */
diff --git a/src/frontend/mame/ui/menu.cpp b/src/frontend/mame/ui/menu.cpp
new file mode 100644
index 00000000000..3c144228d7a
--- /dev/null
+++ b/src/frontend/mame/ui/menu.cpp
@@ -0,0 +1,2965 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods, Maurizio Petrarota
+/*********************************************************************
+
+ ui/menu.cpp
+
+ Internal MAME menus for the user interface.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "rendutil.h"
+#include "cheat.h"
+#include "uiinput.h"
+#include "ui/ui.h"
+#include "ui/menu.h"
+#include "ui/mainmenu.h"
+#include "ui/utils.h"
+#include "ui/defimg.h"
+#include "ui/starimg.h"
+#include "ui/optsmenu.h"
+#include "ui/datfile.h"
+#include "rendfont.h"
+#include "ui/custmenu.h"
+#include "ui/icorender.h"
+#include "ui/toolbar.h"
+#include "ui/miscmenu.h"
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define UI_MENU_POOL_SIZE 65536
+#define MAX_ICONS_RENDER 40
+
+struct ui_arts_info
+{
+ const char *title, *path;
+};
+
+static const ui_arts_info arts_info[] =
+{
+ { __("Snapshots"), OPTION_SNAPSHOT_DIRECTORY },
+ { __("Cabinets"), OPTION_CABINETS_PATH },
+ { __("Control Panels"), OPTION_CPANELS_PATH },
+ { __("PCBs"), OPTION_PCBS_PATH },
+ { __("Flyers"), OPTION_FLYERS_PATH },
+ { __("Titles"), OPTION_TITLES_PATH },
+ { __("Ends"), OPTION_ENDS_PATH },
+ { __("Artwork Preview"), OPTION_ARTPREV_PATH },
+ { __("Bosses"), OPTION_BOSSES_PATH },
+ { __("Logos"), OPTION_LOGOS_PATH },
+ { __("Versus"), OPTION_VERSUS_PATH },
+ { __("Game Over"), OPTION_GAMEOVER_PATH },
+ { __("HowTo"), OPTION_HOWTO_PATH },
+ { __("Scores"), OPTION_SCORES_PATH },
+ { __("Select"), OPTION_SELECT_PATH },
+ { __("Marquees"), OPTION_MARQUEES_PATH },
+ { __("Covers"), OPTION_COVER_PATH },
+ { nullptr }
+};
+
+static const char *hover_msg[] = {
+ __("Add or remove favorites"),
+ __("Export displayed list to file"),
+ __("Show DATs view"),
+};
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+ui_menu *ui_menu::menu_stack;
+ui_menu *ui_menu::menu_free;
+std::unique_ptr<bitmap_rgb32> ui_menu::hilight_bitmap;
+render_texture *ui_menu::hilight_texture;
+render_texture *ui_menu::arrow_texture;
+render_texture *ui_menu::snapx_texture;
+render_texture *ui_menu::hilight_main_texture;
+render_texture *ui_menu::bgrnd_texture;
+render_texture *ui_menu::star_texture;
+render_texture *ui_menu::toolbar_texture[UI_TOOLBAR_BUTTONS];
+render_texture *ui_menu::sw_toolbar_texture[UI_TOOLBAR_BUTTONS];
+render_texture *ui_menu::icons_texture[MAX_ICONS_RENDER];
+std::unique_ptr<bitmap_argb32> ui_menu::snapx_bitmap;
+std::unique_ptr<bitmap_argb32> ui_menu::no_avail_bitmap;
+std::unique_ptr<bitmap_argb32> ui_menu::star_bitmap;
+std::unique_ptr<bitmap_argb32> ui_menu::bgrnd_bitmap;
+bitmap_argb32 *ui_menu::icons_bitmap[MAX_ICONS_RENDER];
+std::unique_ptr<bitmap_rgb32> ui_menu::hilight_main_bitmap;
+bitmap_argb32 *ui_menu::toolbar_bitmap[UI_TOOLBAR_BUTTONS];
+bitmap_argb32 *ui_menu::sw_toolbar_bitmap[UI_TOOLBAR_BUTTONS];
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+//-------------------------------------------------
+// is_selectable - return TRUE if the given
+// item is selectable
+//-------------------------------------------------
+
+inline bool ui_menu_item::is_selectable() const
+{
+ return ((flags & (MENU_FLAG_MULTILINE | MENU_FLAG_DISABLE)) == 0 && strcmp(text, MENU_SEPARATOR_ITEM) != 0);
+}
+
+
+//-------------------------------------------------
+// exclusive_input_pressed - return TRUE if the
+// given key is pressed and we haven't already
+// reported a key
+//-------------------------------------------------
+
+inline bool ui_menu::exclusive_input_pressed(int key, int repeat)
+{
+ if (menu_event.iptkey == IPT_INVALID && machine().ui_input().pressed_repeat(key, repeat))
+ {
+ menu_event.iptkey = key;
+ return true;
+ }
+ return false;
+}
+
+
+
+/***************************************************************************
+ CORE SYSTEM MANAGEMENT
+***************************************************************************/
+
+//-------------------------------------------------
+// init - initialize the menu system
+//-------------------------------------------------
+
+void ui_menu::init(running_machine &machine)
+{
+ // initialize the menu stack
+ ui_menu::stack_reset(machine);
+
+ // create a texture for hilighting items
+ hilight_bitmap = std::make_unique<bitmap_rgb32>(256, 1);
+ for (int x = 0; x < 256; x++)
+ {
+ int alpha = 0xff;
+ if (x < 25) alpha = 0xff * x / 25;
+ if (x > 256 - 25) alpha = 0xff * (255 - x) / 25;
+ hilight_bitmap->pix32(0, x) = rgb_t(alpha,0xff,0xff,0xff);
+ }
+ hilight_texture = machine.render().texture_alloc();
+ hilight_texture->set_bitmap(*hilight_bitmap, hilight_bitmap->cliprect(), TEXFORMAT_ARGB32);
+
+ // create a texture for arrow icons
+ arrow_texture = machine.render().texture_alloc(render_triangle);
+
+ // initialize ui
+ init_ui(machine);
+
+ // add an exit callback to free memory
+ machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(ui_menu::exit), &machine));
+}
+
+
+//-------------------------------------------------
+// exit - clean up after ourselves
+//-------------------------------------------------
+
+void ui_menu::exit(running_machine &machine)
+{
+ // free menus
+ ui_menu::stack_reset(machine);
+ ui_menu::clear_free_list(machine);
+
+ // free textures
+ render_manager &mre = machine.render();
+ mre.texture_free(hilight_texture);
+ mre.texture_free(arrow_texture);
+ mre.texture_free(snapx_texture);
+ mre.texture_free(hilight_main_texture);
+ mre.texture_free(bgrnd_texture);
+ mre.texture_free(star_texture);
+
+ for (auto & elem : icons_texture)
+ mre.texture_free(elem);
+
+ for (int i = 0; i < UI_TOOLBAR_BUTTONS; i++)
+ {
+ mre.texture_free(sw_toolbar_texture[i]);
+ mre.texture_free(toolbar_texture[i]);
+ }
+}
+
+
+
+/***************************************************************************
+ CORE MENU MANAGEMENT
+***************************************************************************/
+
+//-------------------------------------------------
+// ui_menu - menu constructor
+//-------------------------------------------------
+
+ui_menu::ui_menu(running_machine &machine, render_container *_container) : m_machine(machine)
+{
+ m_special_main_menu = false;
+ container = _container;
+
+ reset(UI_MENU_RESET_SELECT_FIRST);
+
+ top_line = 0;
+}
+
+
+//-------------------------------------------------
+// ~ui_menu - menu destructor
+//-------------------------------------------------
+
+ui_menu::~ui_menu()
+{
+ // free the pools
+ while (pool)
+ {
+ ui_menu_pool *ppool = pool;
+ pool = pool->next;
+ global_free(ppool);
+ }
+}
+
+
+//-------------------------------------------------
+// reset - free all items in the menu,
+// and all memory allocated from the memory pool
+//-------------------------------------------------
+
+void ui_menu::reset(ui_menu_reset_options options)
+{
+ // based on the reset option, set the reset info
+ resetpos = 0;
+ resetref = nullptr;
+ if (options == UI_MENU_RESET_REMEMBER_POSITION)
+ resetpos = selected;
+ else if (options == UI_MENU_RESET_REMEMBER_REF)
+ resetref = item[selected].ref;
+
+ // reset all the pools and the item.size() back to 0
+ for (ui_menu_pool *ppool = pool; ppool != nullptr; ppool = ppool->next)
+ ppool->top = (UINT8 *)(ppool + 1);
+ item.clear();
+ visitems = 0;
+ selected = 0;
+
+ // add an item to return
+ if (parent == nullptr)
+ item_append(_("Return to Machine"), nullptr, 0, nullptr);
+ else if (parent->is_special_main_menu())
+ {
+ if (strcmp(machine().options().ui(), "simple") == 0)
+ item_append(_("Exit"), nullptr, 0, nullptr);
+ else
+ item_append(_("Exit"), nullptr, MENU_FLAG_UI | MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW, nullptr);
+ }
+ else
+ {
+ if (strcmp(machine().options().ui(), "simple") != 0 && ui_menu::stack_has_special_main_menu())
+ item_append(_("Return to Previous Menu"), nullptr, MENU_FLAG_UI | MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW, nullptr);
+ else
+ item_append(_("Return to Previous Menu"), nullptr, 0, nullptr);
+ }
+
+}
+
+
+//-------------------------------------------------
+// is_special_main_menu - returns whether the
+// menu has special needs
+//-------------------------------------------------
+
+bool ui_menu::is_special_main_menu() const
+{
+ return m_special_main_menu;
+}
+
+
+//-------------------------------------------------
+// set_special_main_menu - set whether the
+// menu has special needs
+//-------------------------------------------------
+
+void ui_menu::set_special_main_menu(bool special)
+{
+ m_special_main_menu = special;
+}
+
+
+//-------------------------------------------------
+// item_append - append a new item to the
+// end of the menu
+//-------------------------------------------------
+
+void ui_menu::item_append(ui_menu_item item)
+{
+ item_append(item.text, item.subtext, item.flags, item.ref, item.type);
+}
+
+//-------------------------------------------------
+// item_append - append a new item to the
+// end of the menu
+//-------------------------------------------------
+
+void ui_menu::item_append(ui_menu_item_type type)
+{
+ if (type == ui_menu_item_type::SEPARATOR)
+ item_append(MENU_SEPARATOR_ITEM, nullptr, 0, nullptr);
+}
+
+//-------------------------------------------------
+// item_append - append a new item to the
+// end of the menu
+//-------------------------------------------------
+
+void ui_menu::item_append(const char *text, const char *subtext, UINT32 flags, void *ref, ui_menu_item_type type)
+{
+ // only allow multiline as the first item
+ if ((flags & MENU_FLAG_MULTILINE) != 0)
+ assert(item.size() == 1);
+
+ // only allow a single multi-line item
+ else if (item.size() >= 2)
+ assert((item[0].flags & MENU_FLAG_MULTILINE) == 0);
+
+ // allocate a new item and populate it
+ ui_menu_item pitem;
+ pitem.text = (text != nullptr) ? pool_strdup(text) : nullptr;
+ pitem.subtext = (subtext != nullptr) ? pool_strdup(subtext) : nullptr;
+ pitem.flags = flags;
+ pitem.ref = ref;
+ pitem.type = type;
+
+ // append to array
+ int index = item.size();
+ if (!item.empty())
+ {
+ item.insert(item.end() - 1, pitem);
+ --index;
+ }
+ else
+ item.push_back(pitem);
+
+ // update the selection if we need to
+ if (resetpos == index || (resetref != nullptr && resetref == ref))
+ selected = index;
+ if (resetpos == item.size() - 1)
+ selected = item.size() - 1;
+}
+
+
+//-------------------------------------------------
+// process - process a menu, drawing it
+// and returning any interesting events
+//-------------------------------------------------
+
+const ui_menu_event *ui_menu::process(UINT32 flags, float x0, float y0)
+{
+ // reset the menu_event
+ menu_event.iptkey = IPT_INVALID;
+
+ // first make sure our selection is valid
+ validate_selection(1);
+
+ // draw the menu
+ if (item.size() > 1 && (item[0].flags & MENU_FLAG_MULTILINE) != 0)
+ draw_text_box();
+ else if ((item[0].flags & MENU_FLAG_UI) != 0 || (item[0].flags & MENU_FLAG_UI_SWLIST) != 0)
+ draw_select_game((flags & UI_MENU_PROCESS_NOINPUT));
+ else if ((item[0].flags & MENU_FLAG_UI_PALETTE) != 0)
+ draw_palette_menu();
+ else if ((item[0].flags & MENU_FLAG_UI_DATS) != 0)
+ draw_dats_menu();
+ else
+ draw(flags, x0, y0);
+
+ // process input
+ if (!(flags & UI_MENU_PROCESS_NOKEYS) && !(flags & UI_MENU_PROCESS_NOINPUT))
+ {
+ // read events
+ if ((item[0].flags & MENU_FLAG_UI ) != 0 || (item[0].flags & MENU_FLAG_UI_SWLIST ) != 0)
+ handle_main_events(flags);
+ else
+ handle_events(flags);
+
+ // handle the keys if we don't already have an menu_event
+ if (menu_event.iptkey == IPT_INVALID)
+ {
+ if ((item[0].flags & MENU_FLAG_UI ) != 0 || (item[0].flags & MENU_FLAG_UI_SWLIST ) != 0)
+ handle_main_keys(flags);
+ else
+ handle_keys(flags);
+ }
+ }
+
+ // update the selected item in the menu_event
+ if (menu_event.iptkey != IPT_INVALID && selected >= 0 && selected < item.size())
+ {
+ menu_event.itemref = item[selected].ref;
+ menu_event.type = item[selected].type;
+ return &menu_event;
+ }
+ return nullptr;
+}
+
+
+//-------------------------------------------------
+// m_pool_alloc - allocate temporary memory
+// from the menu's memory pool
+//-------------------------------------------------
+
+void *ui_menu::m_pool_alloc(size_t size)
+{
+ ui_menu_pool *ppool;
+
+ assert(size < UI_MENU_POOL_SIZE);
+
+ // find a pool with enough room
+ for (ppool = pool; ppool != nullptr; ppool = ppool->next)
+ if (ppool->end - ppool->top >= size)
+ {
+ void *result = ppool->top;
+ ppool->top += size;
+ return result;
+ }
+
+ // allocate a new pool
+ ppool = (ui_menu_pool *)global_alloc_array_clear<UINT8>(sizeof(*ppool) + UI_MENU_POOL_SIZE);
+
+ // wire it up
+ ppool->next = pool;
+ pool = ppool;
+ ppool->top = (UINT8 *)(ppool + 1);
+ ppool->end = ppool->top + UI_MENU_POOL_SIZE;
+ return m_pool_alloc(size);
+}
+
+
+//-------------------------------------------------
+// pool_strdup - make a temporary string
+// copy in the menu's memory pool
+//-------------------------------------------------
+
+const char *ui_menu::pool_strdup(const char *string)
+{
+ return strcpy((char *)m_pool_alloc(strlen(string) + 1), string);
+}
+
+
+//-------------------------------------------------
+// get_selection - retrieves the index
+// of the currently selected menu item
+//-------------------------------------------------
+
+void *ui_menu::get_selection()
+{
+ return (selected >= 0 && selected < item.size()) ? item[selected].ref : nullptr;
+}
+
+
+//-------------------------------------------------
+// set_selection - changes the index
+// of the currently selected menu item
+//-------------------------------------------------
+
+void ui_menu::set_selection(void *selected_itemref)
+{
+ selected = -1;
+ for (int itemnum = 0; itemnum < item.size(); itemnum++)
+ if (item[itemnum].ref == selected_itemref)
+ {
+ selected = itemnum;
+ break;
+ }
+}
+
+
+
+/***************************************************************************
+ INTERNAL MENU PROCESSING
+***************************************************************************/
+
+//-------------------------------------------------
+// draw - draw a menu
+//-------------------------------------------------
+
+void ui_menu::draw(UINT32 flags, float origx0, float origy0)
+{
+ // first draw the FPS counter
+ if (mame_machine_manager::instance()->ui().show_fps_counter())
+ {
+ mame_machine_manager::instance()->ui().draw_text_full(container, machine().video().speed_text().c_str(), 0.0f, 0.0f, 1.0f,
+ JUSTIFY_RIGHT, WRAP_WORD, DRAW_OPAQUE, ARGB_WHITE, ARGB_BLACK, nullptr, nullptr);
+ }
+
+ bool customonly = (flags & UI_MENU_PROCESS_CUSTOM_ONLY);
+ bool noimage = (flags & UI_MENU_PROCESS_NOIMAGE);
+ bool noinput = (flags & UI_MENU_PROCESS_NOINPUT);
+ float line_height = mame_machine_manager::instance()->ui().get_line_height();
+ float lr_arrow_width = 0.4f * line_height * machine().render().ui_aspect();
+ float ud_arrow_width = line_height * machine().render().ui_aspect();
+ float gutter_width = lr_arrow_width * 1.3f;
+
+ bool selected_subitem_too_big = false;
+ int itemnum, linenum;
+ bool mouse_hit, mouse_button;
+ float mouse_x = -1, mouse_y = -1;
+
+ if (mame_machine_manager::instance()->ui().options().use_background_image() && &machine().system() == &GAME_NAME(___empty) && bgrnd_bitmap->valid() && !noimage)
+ container->add_quad(0.0f, 0.0f, 1.0f, 1.0f, ARGB_WHITE, bgrnd_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+
+ // compute the width and height of the full menu
+ float visible_width = 0;
+ float visible_main_menu_height = 0;
+ for (itemnum = 0; itemnum < item.size(); itemnum++)
+ {
+ const ui_menu_item &pitem = item[itemnum];
+ float total_width;
+
+ // compute width of left hand side
+ total_width = gutter_width + mame_machine_manager::instance()->ui().get_string_width(pitem.text) + gutter_width;
+
+ // add in width of right hand side
+ if (pitem.subtext)
+ total_width += 2.0f * gutter_width + mame_machine_manager::instance()->ui().get_string_width(pitem.subtext);
+
+ // track the maximum
+ if (total_width > visible_width)
+ visible_width = total_width;
+
+ // track the height as well
+ visible_main_menu_height += line_height;
+ }
+
+ // account for extra space at the top and bottom
+ float visible_extra_menu_height = customtop + custombottom;
+
+ // add a little bit of slop for rounding
+ visible_width += 0.01f;
+ visible_main_menu_height += 0.01f;
+
+ // if we are too wide or too tall, clamp it down
+ if (visible_width + 2.0f * UI_BOX_LR_BORDER > 1.0f)
+ visible_width = 1.0f - 2.0f * UI_BOX_LR_BORDER;
+
+ // if the menu and extra menu won't fit, take away part of the regular menu, it will scroll
+ if (visible_main_menu_height + visible_extra_menu_height + 2.0f * UI_BOX_TB_BORDER > 1.0f)
+ visible_main_menu_height = 1.0f - 2.0f * UI_BOX_TB_BORDER - visible_extra_menu_height;
+
+ visible_lines = floor(visible_main_menu_height / line_height);
+ if (visible_lines > item.size()) visible_lines = item.size();
+ visible_main_menu_height = (float)visible_lines * line_height;
+
+ // compute top/left of inner menu area by centering
+ float visible_left = (1.0f - visible_width) * 0.5f;
+ float visible_top = (1.0f - (visible_main_menu_height + visible_extra_menu_height)) * 0.5f;
+
+/* float visible_left;
+ float visible_top;
+ if (origx0 == 0.0f && origy0 == 0.0f)
+ {
+ visible_left = (1.0f - visible_width) * 0.5f;
+ visible_top = (1.0f - (visible_main_menu_height + visible_extra_menu_height)) * 0.5f;
+ }
+ else
+ {
+ INT32 mouse_target_x, mouse_target_y;
+ float m_x, m_y;
+ render_target *mouse_target = machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button);
+ if (mouse_target != nullptr)
+ {
+ if (mouse_target->map_point_container(origx0, origy0, *container, m_x, m_y))
+ {
+ visible_left = m_x;
+ visible_top = m_y;
+ }
+ else
+ {
+ visible_left = (1.0f - visible_width) * 0.5f;
+ visible_top = (1.0f - (visible_main_menu_height + visible_extra_menu_height)) * 0.5f;
+ }
+ }
+ else
+ {
+ visible_left = (1.0f - visible_width) * 0.5f;
+ visible_top = (1.0f - (visible_main_menu_height + visible_extra_menu_height)) * 0.5f;
+ }
+ }
+*/
+ // if the menu is at the bottom of the extra, adjust
+ visible_top += customtop;
+
+ // first add us a box
+ float x1 = visible_left - UI_BOX_LR_BORDER;
+ float y1 = visible_top - UI_BOX_TB_BORDER;
+ float x2 = visible_left + visible_width + UI_BOX_LR_BORDER;
+ float y2 = visible_top + visible_main_menu_height + UI_BOX_TB_BORDER;
+ if (!customonly)
+ mame_machine_manager::instance()->ui().draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
+
+ if (top_line < 0 || selected == 0)
+ top_line = 0;
+ if (top_line > item.size() - visible_lines || selected == (item.size() - 1))
+ top_line = item.size() - visible_lines;
+
+ bool show_top_arrow = false;
+ bool show_bottom_arrow = false;
+
+ // if scrolling, show arrows
+ if (item.size() > visible_lines)
+ {
+ if (top_line > 0)
+ show_top_arrow = true;
+ if (top_line != item.size() - visible_lines)
+ show_bottom_arrow = true;
+ }
+
+ // set the number of visible lines, minus 1 for top arrow and 1 for bottom arrow
+ visitems = visible_lines - show_top_arrow - show_bottom_arrow;
+
+ // determine effective positions taking into account the hilighting arrows
+ float effective_width = visible_width - 2.0f * gutter_width;
+ float effective_left = visible_left + gutter_width;
+
+ // locate mouse
+ mouse_hit = false;
+ mouse_button = false;
+ if (!customonly && !noinput)
+ {
+ INT32 mouse_target_x, mouse_target_y;
+ render_target *mouse_target = machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button);
+ if (mouse_target != nullptr)
+ if (mouse_target->map_point_container(mouse_target_x, mouse_target_y, *container, mouse_x, mouse_y))
+ mouse_hit = true;
+ }
+
+ // loop over visible lines
+ hover = item.size() + 1;
+ float line_x0 = x1 + 0.5f * UI_LINE_WIDTH;
+ float line_x1 = x2 - 0.5f * UI_LINE_WIDTH;
+ if (!customonly)
+ {
+ for (linenum = 0; linenum < visible_lines; linenum++)
+ {
+ float line_y = visible_top + (float)linenum * line_height;
+ itemnum = top_line + linenum;
+ const ui_menu_item &pitem = item[itemnum];
+ const char *itemtext = pitem.text;
+ rgb_t fgcolor = UI_TEXT_COLOR;
+ rgb_t bgcolor = UI_TEXT_BG_COLOR;
+ rgb_t fgcolor2 = UI_SUBITEM_COLOR;
+ rgb_t fgcolor3 = UI_CLONE_COLOR;
+ float line_y0 = line_y;
+ float line_y1 = line_y + line_height;
+
+ // set the hover if this is our item
+ if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y && pitem.is_selectable())
+ hover = itemnum;
+
+ // if we're selected, draw with a different background
+ if (itemnum == selected)
+ {
+ fgcolor = UI_SELECTED_COLOR;
+ bgcolor = UI_SELECTED_BG_COLOR;
+ fgcolor2 = UI_SELECTED_COLOR;
+ fgcolor3 = UI_SELECTED_COLOR;
+ }
+
+ // else if the mouse is over this item, draw with a different background
+ else if (itemnum == hover)
+ {
+ fgcolor = UI_MOUSEOVER_COLOR;
+ bgcolor = UI_MOUSEOVER_BG_COLOR;
+ fgcolor2 = UI_MOUSEOVER_COLOR;
+ fgcolor3 = UI_MOUSEOVER_COLOR;
+ }
+
+ // if we have some background hilighting to do, add a quad behind everything else
+ if (bgcolor != UI_TEXT_BG_COLOR)
+ highlight(container, line_x0, line_y0, line_x1, line_y1, bgcolor);
+
+ // if we're on the top line, display the up arrow
+ if (linenum == 0 && show_top_arrow)
+ {
+ draw_arrow(container,
+ 0.5f * (x1 + x2) - 0.5f * ud_arrow_width,
+ line_y + 0.25f * line_height,
+ 0.5f * (x1 + x2) + 0.5f * ud_arrow_width,
+ line_y + 0.75f * line_height,
+ fgcolor,
+ ROT0);
+ if (hover == itemnum)
+ hover = HOVER_ARROW_UP;
+ }
+
+ // if we're on the bottom line, display the down arrow
+ else if (linenum == visible_lines - 1 && show_bottom_arrow)
+ {
+ draw_arrow(container,
+ 0.5f * (x1 + x2) - 0.5f * ud_arrow_width,
+ line_y + 0.25f * line_height,
+ 0.5f * (x1 + x2) + 0.5f * ud_arrow_width,
+ line_y + 0.75f * line_height,
+ fgcolor,
+ ROT0 ^ ORIENTATION_FLIP_Y);
+ if (hover == itemnum)
+ hover = HOVER_ARROW_DOWN;
+ }
+
+ // if we're just a divider, draw a line
+ else if (strcmp(itemtext, MENU_SEPARATOR_ITEM) == 0)
+ container->add_line(visible_left, line_y + 0.5f * line_height, visible_left + visible_width, line_y + 0.5f * line_height, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+
+ // if we don't have a subitem, just draw the string centered
+ else if (pitem.subtext == nullptr)
+ {
+ if (pitem.flags & MENU_FLAG_UI_HEADING)
+ {
+ float heading_width = mame_machine_manager::instance()->ui().get_string_width(itemtext);
+ container->add_line(visible_left, line_y + 0.5f * line_height, visible_left + ((visible_width - heading_width) / 2) - UI_BOX_LR_BORDER, line_y + 0.5f * line_height, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ container->add_line(visible_left + visible_width - ((visible_width - heading_width) / 2) + UI_BOX_LR_BORDER, line_y + 0.5f * line_height, visible_left + visible_width, line_y + 0.5f * line_height, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ }
+ mame_machine_manager::instance()->ui().draw_text_full(container, itemtext, effective_left, line_y, effective_width,
+ JUSTIFY_CENTER, WRAP_TRUNCATE, DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr);
+ }
+
+ // otherwise, draw the item on the left and the subitem text on the right
+ else
+ {
+ int subitem_invert = pitem.flags & MENU_FLAG_INVERT;
+ const char *subitem_text = pitem.subtext;
+ float item_width, subitem_width;
+
+ // draw the left-side text
+ mame_machine_manager::instance()->ui().draw_text_full(container, itemtext, effective_left, line_y, effective_width,
+ JUSTIFY_LEFT, WRAP_TRUNCATE, DRAW_NORMAL, fgcolor, bgcolor, &item_width, nullptr);
+
+ // give 2 spaces worth of padding
+ item_width += 2.0f * gutter_width;
+
+ // if the subitem doesn't fit here, display dots
+ if (mame_machine_manager::instance()->ui().get_string_width(subitem_text) > effective_width - item_width)
+ {
+ subitem_text = "...";
+ if (itemnum == selected)
+ selected_subitem_too_big = true;
+ }
+
+ // customize subitem text color
+ if (!core_stricmp(subitem_text, _("On")))
+ fgcolor2 = rgb_t(0xff,0x00,0xff,0x00);
+
+ if (!core_stricmp(subitem_text, _("Off")))
+ fgcolor2 = rgb_t(0xff,0xff,0x00,0x00);
+
+ if (!core_stricmp(subitem_text, _("Auto")))
+ fgcolor2 = rgb_t(0xff,0xff,0xff,0x00);
+
+ // draw the subitem right-justified
+ mame_machine_manager::instance()->ui().draw_text_full(container, subitem_text, effective_left + item_width, line_y, effective_width - item_width,
+ JUSTIFY_RIGHT, WRAP_TRUNCATE, DRAW_NORMAL, subitem_invert ? fgcolor3 : fgcolor2, bgcolor, &subitem_width, nullptr);
+
+ // apply arrows
+ if (itemnum == selected && (pitem.flags & MENU_FLAG_LEFT_ARROW))
+ {
+ draw_arrow(container,
+ effective_left + effective_width - subitem_width - gutter_width,
+ line_y + 0.1f * line_height,
+ effective_left + effective_width - subitem_width - gutter_width + lr_arrow_width,
+ line_y + 0.9f * line_height,
+ fgcolor,
+ ROT90 ^ ORIENTATION_FLIP_X);
+ }
+ if (itemnum == selected && (pitem.flags & MENU_FLAG_RIGHT_ARROW))
+ {
+ draw_arrow(container,
+ effective_left + effective_width + gutter_width - lr_arrow_width,
+ line_y + 0.1f * line_height,
+ effective_left + effective_width + gutter_width,
+ line_y + 0.9f * line_height,
+ fgcolor,
+ ROT90);
+ }
+ }
+ }
+ }
+
+ // if the selected subitem is too big, display it in a separate offset box
+ if (selected_subitem_too_big)
+ {
+ const ui_menu_item &pitem = item[selected];
+ int subitem_invert = pitem.flags & MENU_FLAG_INVERT;
+ linenum = selected - top_line;
+ float line_y = visible_top + (float)linenum * line_height;
+ float target_width, target_height;
+ float target_x, target_y;
+
+ // compute the multi-line target width/height
+ mame_machine_manager::instance()->ui().draw_text_full(container, pitem.subtext, 0, 0, visible_width * 0.75f,
+ JUSTIFY_RIGHT, WRAP_WORD, DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &target_width, &target_height);
+
+ // determine the target location
+ target_x = visible_left + visible_width - target_width - UI_BOX_LR_BORDER;
+ target_y = line_y + line_height + UI_BOX_TB_BORDER;
+ if (target_y + target_height + UI_BOX_TB_BORDER > visible_main_menu_height)
+ target_y = line_y - target_height - UI_BOX_TB_BORDER;
+
+ // add a box around that
+ mame_machine_manager::instance()->ui().draw_outlined_box(container, target_x - UI_BOX_LR_BORDER,
+ target_y - UI_BOX_TB_BORDER,
+ target_x + target_width + UI_BOX_LR_BORDER,
+ target_y + target_height + UI_BOX_TB_BORDER,
+ subitem_invert ? UI_SELECTED_BG_COLOR : UI_BACKGROUND_COLOR);
+ mame_machine_manager::instance()->ui().draw_text_full(container, pitem.subtext, target_x, target_y, target_width,
+ JUSTIFY_RIGHT, WRAP_WORD, DRAW_NORMAL, UI_SELECTED_COLOR, UI_SELECTED_BG_COLOR, nullptr, nullptr);
+ }
+
+ // if there is something special to add, do it by calling the virtual method
+ custom_render((selected >= 0 && selected < item.size()) ? item[selected].ref : nullptr, customtop, custombottom, x1, y1, x2, y2);
+}
+
+void ui_menu::custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2)
+{
+}
+
+//-------------------------------------------------
+// draw_text_box - draw a multiline
+// word-wrapped text box with a menu item at the
+// bottom
+//-------------------------------------------------
+
+void ui_menu::draw_text_box()
+{
+ const char *text = item[0].text;
+ const char *backtext = item[1].text;
+ float line_height = mame_machine_manager::instance()->ui().get_line_height();
+ float lr_arrow_width = 0.4f * line_height * machine().render().ui_aspect();
+ float gutter_width = lr_arrow_width;
+ float target_width, target_height, prior_width;
+ float target_x, target_y;
+
+ // compute the multi-line target width/height
+ mame_machine_manager::instance()->ui().draw_text_full(container, text, 0, 0, 1.0f - 2.0f * UI_BOX_LR_BORDER - 2.0f * gutter_width,
+ JUSTIFY_LEFT, WRAP_WORD, DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &target_width, &target_height);
+ target_height += 2.0f * line_height;
+ if (target_height > 1.0f - 2.0f * UI_BOX_TB_BORDER)
+ target_height = floorf((1.0f - 2.0f * UI_BOX_TB_BORDER) / line_height) * line_height;
+
+ // maximum against "return to prior menu" text
+ prior_width = mame_machine_manager::instance()->ui().get_string_width(backtext) + 2.0f * gutter_width;
+ target_width = MAX(target_width, prior_width);
+
+ // determine the target location
+ target_x = 0.5f - 0.5f * target_width;
+ target_y = 0.5f - 0.5f * target_height;
+
+ // make sure we stay on-screen
+ if (target_x < UI_BOX_LR_BORDER + gutter_width)
+ target_x = UI_BOX_LR_BORDER + gutter_width;
+ if (target_x + target_width + gutter_width + UI_BOX_LR_BORDER > 1.0f)
+ target_x = 1.0f - UI_BOX_LR_BORDER - gutter_width - target_width;
+ if (target_y < UI_BOX_TB_BORDER)
+ target_y = UI_BOX_TB_BORDER;
+ if (target_y + target_height + UI_BOX_TB_BORDER > 1.0f)
+ target_y = 1.0f - UI_BOX_TB_BORDER - target_height;
+
+ // add a box around that
+ mame_machine_manager::instance()->ui().draw_outlined_box(container, target_x - UI_BOX_LR_BORDER - gutter_width,
+ target_y - UI_BOX_TB_BORDER,
+ target_x + target_width + gutter_width + UI_BOX_LR_BORDER,
+ target_y + target_height + UI_BOX_TB_BORDER,
+ (item[0].flags & MENU_FLAG_REDTEXT) ? UI_RED_COLOR : UI_BACKGROUND_COLOR);
+ mame_machine_manager::instance()->ui().draw_text_full(container, text, target_x, target_y, target_width,
+ JUSTIFY_LEFT, WRAP_WORD, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+
+ // draw the "return to prior menu" text with a hilight behind it
+ highlight(container,
+ target_x + 0.5f * UI_LINE_WIDTH,
+ target_y + target_height - line_height,
+ target_x + target_width - 0.5f * UI_LINE_WIDTH,
+ target_y + target_height,
+ UI_SELECTED_BG_COLOR);
+ mame_machine_manager::instance()->ui().draw_text_full(container, backtext, target_x, target_y + target_height - line_height, target_width,
+ JUSTIFY_CENTER, WRAP_TRUNCATE, DRAW_NORMAL, UI_SELECTED_COLOR, UI_SELECTED_BG_COLOR, nullptr, nullptr);
+
+ // artificially set the hover to the last item so a double-click exits
+ hover = item.size() - 1;
+}
+
+
+//-------------------------------------------------
+// handle_events - generically handle
+// input events for a menu
+//-------------------------------------------------
+
+void ui_menu::handle_events(UINT32 flags)
+{
+ bool stop = false;
+ ui_event local_menu_event;
+
+ // loop while we have interesting events
+ while (!stop && machine().ui_input().pop_event(&local_menu_event))
+ {
+ switch (local_menu_event.event_type)
+ {
+ // if we are hovering over a valid item, select it with a single click
+ case UI_EVENT_MOUSE_DOWN:
+ if ((flags & UI_MENU_PROCESS_ONLYCHAR) == 0)
+ {
+ if (hover >= 0 && hover < item.size())
+ selected = hover;
+ else if (hover == HOVER_ARROW_UP)
+ {
+ if ((flags & MENU_FLAG_UI_DATS) != 0)
+ {
+ top_line -= visitems - (top_line + visible_lines == item.size() - 1);
+ return;
+ }
+ selected -= visitems;
+ if (selected < 0)
+ selected = 0;
+ top_line -= visitems - (top_line + visible_lines == item.size() - 1);
+ }
+ else if (hover == HOVER_ARROW_DOWN)
+ {
+ if ((flags & MENU_FLAG_UI_DATS) != 0)
+ {
+ top_line += visible_lines - 2;
+ return;
+ }
+ selected += visible_lines - 2 + (selected == 0);
+ if (selected > item.size() - 1)
+ selected = item.size() - 1;
+ top_line += visible_lines - 2;
+ }
+ }
+ break;
+
+ // if we are hovering over a valid item, fake a UI_SELECT with a double-click
+ case UI_EVENT_MOUSE_DOUBLE_CLICK:
+ if ((flags & UI_MENU_PROCESS_ONLYCHAR) == 0 && hover >= 0 && hover < item.size())
+ {
+ selected = hover;
+ menu_event.iptkey = IPT_UI_SELECT;
+ if (selected == item.size() - 1)
+ {
+ menu_event.iptkey = IPT_UI_CANCEL;
+ ui_menu::stack_pop(machine());
+ }
+ stop = true;
+ }
+ break;
+
+ // caught scroll event
+ case UI_EVENT_MOUSE_WHEEL:
+ if ((flags & UI_MENU_PROCESS_ONLYCHAR) == 0)
+ {
+ if (local_menu_event.zdelta > 0)
+ {
+ if ((flags & MENU_FLAG_UI_DATS) != 0)
+ {
+ top_line -= local_menu_event.num_lines;
+ return;
+ }
+ (selected == 0) ? selected = top_line = item.size() - 1 : selected -= local_menu_event.num_lines;
+ validate_selection(-1);
+ top_line -= (selected <= top_line && top_line != 0);
+ if (selected <= top_line && visitems != visible_lines)
+ top_line -= local_menu_event.num_lines;
+ }
+ else
+ {
+ if ((flags & MENU_FLAG_UI_DATS) != 0)
+ {
+ top_line += local_menu_event.num_lines;
+ return;
+ }
+ (selected == item.size() - 1) ? selected = top_line = 0 : selected += local_menu_event.num_lines;
+ validate_selection(1);
+ top_line += (selected >= top_line + visitems + (top_line != 0));
+ if (selected >= (top_line + visitems + (top_line != 0)))
+ top_line += local_menu_event.num_lines;
+ }
+ }
+ break;
+
+ // translate CHAR events into specials
+ case UI_EVENT_CHAR:
+ menu_event.iptkey = IPT_SPECIAL;
+ menu_event.unichar = local_menu_event.ch;
+ stop = true;
+ break;
+
+ // ignore everything else
+ default:
+ break;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// handle_keys - generically handle
+// keys for a menu
+//-------------------------------------------------
+
+void ui_menu::handle_keys(UINT32 flags)
+{
+ bool ignorepause = ui_menu::stack_has_special_main_menu();
+ int code;
+
+ // bail if no items
+ if (item.empty())
+ return;
+
+ // if we hit select, return TRUE or pop the stack, depending on the item
+ if (exclusive_input_pressed(IPT_UI_SELECT, 0))
+ {
+ if (selected == item.size() - 1)
+ {
+ menu_event.iptkey = IPT_UI_CANCEL;
+ ui_menu::stack_pop(machine());
+ }
+ return;
+ }
+
+ // bail out
+ if ((flags & UI_MENU_PROCESS_ONLYCHAR) != 0)
+ return;
+
+ // hitting cancel also pops the stack
+ if (exclusive_input_pressed(IPT_UI_CANCEL, 0))
+ {
+ if (!menu_has_search_active())
+ ui_menu::stack_pop(machine());
+ return;
+ }
+
+ // validate the current selection
+ validate_selection(1);
+
+ // swallow left/right keys if they are not appropriate
+ bool ignoreleft = ((item[selected].flags & MENU_FLAG_LEFT_ARROW) == 0);
+ bool ignoreright = ((item[selected].flags & MENU_FLAG_RIGHT_ARROW) == 0);
+
+ if ((item[0].flags & MENU_FLAG_UI_DATS) != 0)
+ ignoreleft = ignoreright = false;
+
+ // accept left/right keys as-is with repeat
+ if (!ignoreleft && exclusive_input_pressed(IPT_UI_LEFT, (flags & UI_MENU_PROCESS_LR_REPEAT) ? 6 : 0))
+ return;
+ if (!ignoreright && exclusive_input_pressed(IPT_UI_RIGHT, (flags & UI_MENU_PROCESS_LR_REPEAT) ? 6 : 0))
+ return;
+
+ // up backs up by one item
+ if (exclusive_input_pressed(IPT_UI_UP, 6))
+ {
+ if ((item[0].flags & MENU_FLAG_UI_DATS) != 0)
+ {
+ top_line--;
+ return;
+ }
+ (selected == 0) ? selected = top_line = item.size() - 1 : --selected;
+ validate_selection(-1);
+ top_line -= (selected <= top_line && top_line != 0);
+ if (selected <= top_line && visitems != visible_lines)
+ top_line--;
+ }
+
+ // down advances by one item
+ if (exclusive_input_pressed(IPT_UI_DOWN, 6))
+ {
+ if ((item[0].flags & MENU_FLAG_UI_DATS) != 0)
+ {
+ top_line++;
+ return;
+ }
+ (selected == item.size() - 1) ? selected = top_line = 0 : ++selected;
+ validate_selection(1);
+ top_line += (selected >= top_line + visitems + (top_line != 0));
+ if (selected >= (top_line + visitems + (top_line != 0)))
+ top_line++;
+ }
+
+ // page up backs up by visitems
+ if (exclusive_input_pressed(IPT_UI_PAGE_UP, 6))
+ {
+ selected -= visitems;
+ top_line -= visitems - (top_line + visible_lines == item.size() - 1);
+ if (selected < 0)
+ selected = 0;
+ validate_selection(1);
+ }
+
+ // page down advances by visitems
+ if (exclusive_input_pressed(IPT_UI_PAGE_DOWN, 6))
+ {
+ selected += visible_lines - 2 + (selected == 0);
+ top_line += visible_lines - 2;
+
+ if (selected > item.size() - 1)
+ selected = item.size() - 1;
+ validate_selection(-1);
+ }
+
+ // home goes to the start
+ if (exclusive_input_pressed(IPT_UI_HOME, 0))
+ {
+ selected = top_line = 0;
+ validate_selection(1);
+ }
+
+ // end goes to the last
+ if (exclusive_input_pressed(IPT_UI_END, 0))
+ {
+ selected = top_line = item.size() - 1;
+ validate_selection(-1);
+ }
+
+ // pause enables/disables pause
+ if (!ignorepause && exclusive_input_pressed(IPT_UI_PAUSE, 0))
+ {
+ if (machine().paused())
+ machine().resume();
+ else
+ machine().pause();
+ }
+
+ // handle a toggle cheats request
+ if (machine().ui_input().pressed_repeat(IPT_UI_TOGGLE_CHEAT, 0))
+ mame_machine_manager::instance()->cheat().set_enable(!mame_machine_manager::instance()->cheat().enabled());
+
+ // see if any other UI keys are pressed
+ if (menu_event.iptkey == IPT_INVALID)
+ for (code = IPT_UI_FIRST + 1; code < IPT_UI_LAST; code++)
+ {
+ if (code == IPT_UI_CONFIGURE || (code == IPT_UI_LEFT && ignoreleft) || (code == IPT_UI_RIGHT && ignoreright) || (code == IPT_UI_PAUSE && ignorepause))
+ continue;
+ if (exclusive_input_pressed(code, 0))
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// validate_selection - validate the
+// current selection and ensure it is on a
+// correct item
+//-------------------------------------------------
+
+void ui_menu::validate_selection(int scandir)
+{
+ // clamp to be in range
+ if (selected < 0)
+ selected = 0;
+ else if (selected >= item.size())
+ selected = item.size() - 1;
+
+ // skip past unselectable items
+ while (!item[selected].is_selectable())
+ selected = (selected + item.size() + scandir) % item.size();
+}
+
+
+
+//-------------------------------------------------
+// clear_free_list - clear out anything
+// accumulated in the free list
+//-------------------------------------------------
+
+void ui_menu::clear_free_list(running_machine &machine)
+{
+ while (menu_free != nullptr)
+ {
+ ui_menu *menu = menu_free;
+ menu_free = menu->parent;
+ global_free(menu);
+ }
+}
+
+
+
+/***************************************************************************
+ MENU STACK MANAGEMENT
+***************************************************************************/
+
+//-------------------------------------------------
+// ui_menu::stack_reset - reset the menu stack
+//-------------------------------------------------
+
+void ui_menu::stack_reset(running_machine &machine)
+{
+ while (menu_stack != nullptr)
+ ui_menu::stack_pop(machine);
+}
+
+
+//-------------------------------------------------
+// stack_push - push a new menu onto the
+// stack
+//-------------------------------------------------
+
+void ui_menu::stack_push(ui_menu *menu)
+{
+ menu->parent = menu_stack;
+ menu_stack = menu;
+ menu->reset(UI_MENU_RESET_SELECT_FIRST);
+ menu->machine().ui_input().reset();
+}
+
+
+//-------------------------------------------------
+// stack_pop - pop a menu from the stack
+//-------------------------------------------------
+
+void ui_menu::stack_pop(running_machine &machine)
+{
+ if (menu_stack != nullptr)
+ {
+ ui_menu *menu = menu_stack;
+ menu_stack = menu->parent;
+ menu->parent = menu_free;
+ menu_free = menu;
+ machine.ui_input().reset();
+ }
+}
+
+
+//-------------------------------------------------
+// ui_menu::stack_has_special_main_menu -
+// check in the special main menu is in the stack
+//-------------------------------------------------
+
+bool ui_menu::stack_has_special_main_menu()
+{
+ ui_menu *menu;
+
+ for (menu = menu_stack; menu != nullptr; menu = menu->parent)
+ if (menu->is_special_main_menu())
+ return true;
+
+ return false;
+}
+
+void ui_menu::do_handle()
+{
+ if(item.size() < 2)
+ populate();
+ handle();
+}
+
+
+/***************************************************************************
+ UI SYSTEM INTERACTION
+***************************************************************************/
+
+//-------------------------------------------------
+// ui_menu_ui_handler - displays the current menu
+// and calls the menu handler
+//-------------------------------------------------
+
+UINT32 ui_menu::ui_handler(running_machine &machine, render_container *container, UINT32 state)
+{
+ // if we have no menus stacked up, start with the main menu
+ if (menu_stack == nullptr)
+ stack_push(global_alloc_clear<ui_menu_main>(machine, container));
+
+ // update the menu state
+ if (menu_stack != nullptr)
+ menu_stack->do_handle();
+
+ // clear up anything pending to be released
+ clear_free_list(machine);
+
+ // if the menus are to be hidden, return a cancel here
+ if (mame_machine_manager::instance()->ui().is_menu_active() && ((machine.ui_input().pressed(IPT_UI_CONFIGURE) && !stack_has_special_main_menu()) || menu_stack == nullptr))
+ return UI_HANDLER_CANCEL;
+
+ return 0;
+}
+
+/***************************************************************************
+ MENU HELPERS
+***************************************************************************/
+
+//-------------------------------------------------
+// render_triangle - render a triangle that
+// is used for up/down arrows and left/right
+// indicators
+//-------------------------------------------------
+
+void ui_menu::render_triangle(bitmap_argb32 &dest, bitmap_argb32 &source, const rectangle &sbounds, void *param)
+{
+ int halfwidth = dest.width() / 2;
+ int height = dest.height();
+ int x, y;
+
+ // start with all-transparent
+ dest.fill(rgb_t(0x00,0x00,0x00,0x00));
+
+ // render from the tip to the bottom
+ for (y = 0; y < height; y++)
+ {
+ int linewidth = (y * (halfwidth - 1) + (height / 2)) * 255 * 2 / height;
+ UINT32 *target = &dest.pix32(y, halfwidth);
+
+ // don't antialias if height < 12
+ if (dest.height() < 12)
+ {
+ int pixels = (linewidth + 254) / 255;
+ if (pixels % 2 == 0) pixels++;
+ linewidth = pixels * 255;
+ }
+
+ // loop while we still have data to generate
+ for (x = 0; linewidth > 0; x++)
+ {
+ int dalpha;
+
+ // first column we only consume one pixel
+ if (x == 0)
+ {
+ dalpha = MIN(0xff, linewidth);
+ target[x] = rgb_t(dalpha,0xff,0xff,0xff);
+ }
+
+ // remaining columns consume two pixels, one on each side
+ else
+ {
+ dalpha = MIN(0x1fe, linewidth);
+ target[x] = target[-x] = rgb_t(dalpha/2,0xff,0xff,0xff);
+ }
+
+ // account for the weight we consumed */
+ linewidth -= dalpha;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// highlight
+//-------------------------------------------------
+
+void ui_menu::highlight(render_container *container, float x0, float y0, float x1, float y1, rgb_t bgcolor)
+{
+ container->add_quad(x0, y0, x1, y1, bgcolor, hilight_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE) | PRIMFLAG_PACKABLE);
+}
+
+
+//-------------------------------------------------
+// draw_arrow
+//-------------------------------------------------
+
+void ui_menu::draw_arrow(render_container *container, float x0, float y0, float x1, float y1, rgb_t fgcolor, UINT32 orientation)
+{
+ container->add_quad(x0, y0, x1, y1, fgcolor, arrow_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(orientation) | PRIMFLAG_PACKABLE);
+}
+
+//-------------------------------------------------
+// init - initialize the ui menu system
+//-------------------------------------------------
+
+void ui_menu::init_ui(running_machine &machine)
+{
+ render_manager &mrender = machine.render();
+ // create a texture for hilighting items in main menu
+ hilight_main_bitmap = std::make_unique<bitmap_rgb32>(1, 26);
+ int r1 = 0, g1 = 169, b1 = 255; //Any start color
+ int r2 = 0, g2 = 39, b2 = 130; //Any stop color
+ for (int y = 0; y < 26; y++)
+ {
+ int r = r1 + (y * (r2 - r1) / 26);
+ int g = g1 + (y * (g2 - g1) / 26);
+ int b = b1 + (y * (b2 - b1) / 26);
+ hilight_main_bitmap->pix32(y, 0) = rgb_t(0xff, r, g, b);
+ }
+
+ hilight_main_texture = mrender.texture_alloc();
+ hilight_main_texture->set_bitmap(*hilight_main_bitmap, hilight_main_bitmap->cliprect(), TEXFORMAT_ARGB32);
+
+ // create a texture for snapshot
+ snapx_bitmap = std::make_unique<bitmap_argb32>(0, 0);
+ snapx_texture = mrender.texture_alloc(render_texture::hq_scale);
+
+ // allocates and sets the default "no available" image
+ no_avail_bitmap = std::make_unique<bitmap_argb32>(256, 256);
+ UINT32 *dst = &no_avail_bitmap->pix32(0);
+ memcpy(dst, no_avail_bmp, 256 * 256 * sizeof(UINT32));
+
+ // allocates and sets the favorites star image
+ star_bitmap = std::make_unique<bitmap_argb32>(32, 32);
+ dst = &star_bitmap->pix32(0);
+ memcpy(dst, favorite_star_bmp, 32 * 32 * sizeof(UINT32));
+ star_texture = mrender.texture_alloc();
+ star_texture->set_bitmap(*star_bitmap, star_bitmap->cliprect(), TEXFORMAT_ARGB32);
+
+ // allocate icons
+ for (int i = 0; i < MAX_ICONS_RENDER; i++)
+ {
+ icons_bitmap[i] = auto_alloc(machine, bitmap_argb32);
+ icons_texture[i] = mrender.texture_alloc();
+ }
+
+ // create a texture for main menu background
+ bgrnd_bitmap = std::make_unique<bitmap_argb32>(0, 0);
+ bgrnd_texture = mrender.texture_alloc(render_texture::hq_scale);
+
+ ui_options &mopt = mame_machine_manager::instance()->ui().options();
+ if (mopt.use_background_image() && &machine.system() == &GAME_NAME(___empty))
+ {
+ emu_file backgroundfile(".", OPEN_FLAG_READ);
+ render_load_jpeg(*bgrnd_bitmap, backgroundfile, nullptr, "background.jpg");
+
+ if (!bgrnd_bitmap->valid())
+ render_load_png(*bgrnd_bitmap, backgroundfile, nullptr, "background.png");
+
+ if (bgrnd_bitmap->valid())
+ bgrnd_texture->set_bitmap(*bgrnd_bitmap, bgrnd_bitmap->cliprect(), TEXFORMAT_ARGB32);
+ else
+ bgrnd_bitmap->reset();
+ }
+ else
+ bgrnd_bitmap->reset();
+
+ // create a texture for toolbar
+ for (int x = 0; x < UI_TOOLBAR_BUTTONS; ++x)
+ {
+ toolbar_bitmap[x] = auto_alloc(machine, bitmap_argb32(32, 32));
+ sw_toolbar_bitmap[x] = auto_alloc(machine, bitmap_argb32(32, 32));
+ toolbar_texture[x] = mrender.texture_alloc();
+ sw_toolbar_texture[x] = mrender.texture_alloc();
+ UINT32 *dst = &toolbar_bitmap[x]->pix32(0);
+ memcpy(dst, toolbar_bitmap_bmp[x], 32 * 32 * sizeof(UINT32));
+ if (toolbar_bitmap[x]->valid())
+ toolbar_texture[x]->set_bitmap(*toolbar_bitmap[x], toolbar_bitmap[x]->cliprect(), TEXFORMAT_ARGB32);
+ else
+ toolbar_bitmap[x]->reset();
+
+ if (x == 0 || x == 2)
+ {
+ dst = &sw_toolbar_bitmap[x]->pix32(0);
+ memcpy(dst, toolbar_bitmap_bmp[x], 32 * 32 * sizeof(UINT32));
+ if (sw_toolbar_bitmap[x]->valid())
+ sw_toolbar_texture[x]->set_bitmap(*sw_toolbar_bitmap[x], sw_toolbar_bitmap[x]->cliprect(), TEXFORMAT_ARGB32);
+ else
+ sw_toolbar_bitmap[x]->reset();
+ }
+ else
+ sw_toolbar_bitmap[x]->reset();
+
+ }
+}
+
+
+//-------------------------------------------------
+// draw main menu
+//-------------------------------------------------
+
+void ui_menu::draw_select_game(UINT32 flags)
+{
+ bool noinput = (flags & UI_MENU_PROCESS_NOINPUT);
+ float line_height = mame_machine_manager::instance()->ui().get_line_height();
+ float ud_arrow_width = line_height * machine().render().ui_aspect();
+ float gutter_width = 0.52f * ud_arrow_width;
+ mouse_x = -1, mouse_y = -1;
+ float right_panel_size = (ui_globals::panels_status == HIDE_BOTH || ui_globals::panels_status == HIDE_RIGHT_PANEL) ? 2.0f * UI_BOX_LR_BORDER : 0.3f;
+ float visible_width = 1.0f - 4.0f * UI_BOX_LR_BORDER;
+ float primary_left = (1.0f - visible_width) * 0.5f;
+ float primary_width = visible_width;
+ bool is_swlist = ((item[0].flags & MENU_FLAG_UI_SWLIST) != 0);
+ bool is_favorites = ((item[0].flags & MENU_FLAG_UI_FAVORITE) != 0);
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+
+ // draw background image if available
+ if (mame_machine_manager::instance()->ui().options().use_background_image() && bgrnd_bitmap->valid())
+ container->add_quad(0.0f, 0.0f, 1.0f, 1.0f, ARGB_WHITE, bgrnd_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+
+ hover = item.size() + 1;
+ visible_items = (is_swlist) ? item.size() - 2 : item.size() - 2 - skip_main_items;
+ float extra_height = (is_swlist) ? 2.0f * line_height : (2.0f + skip_main_items) * line_height;
+ float visible_extra_menu_height = customtop + custombottom + extra_height;
+
+ // locate mouse
+ mouse_hit = false;
+ mouse_button = false;
+ if (!noinput)
+ {
+ mouse_target = machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button);
+ if (mouse_target != nullptr)
+ if (mouse_target->map_point_container(mouse_target_x, mouse_target_y, *container, mouse_x, mouse_y))
+ mouse_hit = true;
+ }
+
+ // account for extra space at the top and bottom
+ float visible_main_menu_height = 1.0f - 2.0f * UI_BOX_TB_BORDER - visible_extra_menu_height;
+ visible_lines = floor(visible_main_menu_height / line_height);
+ visible_main_menu_height = (float)(visible_lines * line_height);
+
+ if (!is_swlist)
+ ui_globals::visible_main_lines = visible_lines;
+ else
+ ui_globals::visible_sw_lines = visible_lines;
+
+ // compute top/left of inner menu area by centering
+ float visible_left = primary_left;
+ float visible_top = (1.0f - (visible_main_menu_height + visible_extra_menu_height)) * 0.5f;
+
+ // if the menu is at the bottom of the extra, adjust
+ visible_top += customtop;
+
+ // compute left box size
+ float x1 = visible_left - UI_BOX_LR_BORDER;
+ float y1 = visible_top - UI_BOX_TB_BORDER;
+ float x2 = x1 + 2.0f * UI_BOX_LR_BORDER;
+ float y2 = visible_top + visible_main_menu_height + UI_BOX_TB_BORDER + extra_height;
+
+ // add left box
+ visible_left = draw_left_panel(x1, y1, x2, y2);
+ visible_width -= right_panel_size + visible_left - 2.0f * UI_BOX_LR_BORDER;
+
+ // compute and add main box
+ x1 = visible_left - UI_BOX_LR_BORDER;
+ x2 = visible_left + visible_width + UI_BOX_LR_BORDER;
+ float line = visible_top + (float)(visible_lines * line_height);
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
+
+ if (visible_items < visible_lines)
+ visible_lines = visible_items;
+ if (top_line < 0 || selected == 0)
+ top_line = 0;
+ if (selected < visible_items && top_line + visible_lines >= visible_items)
+ top_line = visible_items - visible_lines;
+
+ // determine effective positions taking into account the hilighting arrows
+ float effective_width = visible_width - 2.0f * gutter_width;
+ float effective_left = visible_left + gutter_width;
+
+ int n_loop = (visible_items >= visible_lines) ? visible_lines : visible_items;
+ if (m_prev_selected != nullptr && m_focus == focused_menu::main && selected < visible_items)
+ m_prev_selected = nullptr;
+
+ for (int linenum = 0; linenum < n_loop; linenum++)
+ {
+ float line_y = visible_top + (float)linenum * line_height;
+ int itemnum = top_line + linenum;
+ const ui_menu_item &pitem = item[itemnum];
+ const char *itemtext = pitem.text;
+ rgb_t fgcolor = UI_TEXT_COLOR;
+ rgb_t bgcolor = UI_TEXT_BG_COLOR;
+ rgb_t fgcolor3 = UI_CLONE_COLOR;
+ float line_x0 = x1 + 0.5f * UI_LINE_WIDTH;
+ float line_y0 = line_y;
+ float line_x1 = x2 - 0.5f * UI_LINE_WIDTH;
+ float line_y1 = line_y + line_height;
+
+ // set the hover if this is our item
+ if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y && pitem.is_selectable())
+ hover = itemnum;
+
+ // if we're selected, draw with a different background
+ if (itemnum == selected && m_focus == focused_menu::main)
+ {
+ fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00);
+ bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff);
+ fgcolor3 = rgb_t(0xff, 0xcc, 0xcc, 0x00);
+ mui.draw_textured_box(container, line_x0 + 0.01f, line_y0, line_x1 - 0.01f, line_y1, bgcolor, rgb_t(255, 43, 43, 43),
+ hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
+ }
+ // else if the mouse is over this item, draw with a different background
+ else if (itemnum == hover)
+ {
+ fgcolor = fgcolor3 = UI_MOUSEOVER_COLOR;
+ bgcolor = UI_MOUSEOVER_BG_COLOR;
+ highlight(container, line_x0, line_y0, line_x1, line_y1, bgcolor);
+ }
+ else if (pitem.ref == m_prev_selected)
+ {
+ fgcolor = fgcolor3 = UI_MOUSEOVER_COLOR;
+ bgcolor = UI_MOUSEOVER_BG_COLOR;
+ mui.draw_textured_box(container, line_x0 + 0.01f, line_y0, line_x1 - 0.01f, line_y1, bgcolor, rgb_t(255, 43, 43, 43),
+ hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
+ }
+
+ // if we're on the top line, display the up arrow
+ if (linenum == 0 && top_line != 0)
+ {
+ draw_arrow(container, 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height,
+ 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height, fgcolor, ROT0);
+
+ if (hover == itemnum)
+ hover = HOVER_ARROW_UP;
+ }
+ // if we're on the bottom line, display the down arrow
+ else if (linenum == visible_lines - 1 && itemnum != visible_items - 1)
+ {
+ draw_arrow(container, 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height,
+ 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height, fgcolor, ROT0 ^ ORIENTATION_FLIP_Y);
+
+ if (hover == itemnum)
+ hover = HOVER_ARROW_DOWN;
+ }
+ // if we're just a divider, draw a line
+ else if (strcmp(itemtext, MENU_SEPARATOR_ITEM) == 0)
+ container->add_line(visible_left, line_y + 0.5f * line_height, visible_left + visible_width, line_y + 0.5f * line_height,
+ UI_LINE_WIDTH, UI_TEXT_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ // draw the item centered
+ else if (pitem.subtext == nullptr)
+ {
+ int item_invert = pitem.flags & MENU_FLAG_INVERT;
+ float space = 0.0f;
+
+ if (ui_globals::has_icons && !is_swlist)
+ {
+ if (is_favorites)
+ {
+ ui_software_info *soft = (ui_software_info *)item[itemnum].ref;
+ if (soft->startempty == 1)
+ draw_icon(linenum, (void *)soft->driver, effective_left, line_y);
+ }
+ else
+ draw_icon(linenum, item[itemnum].ref, effective_left, line_y);
+
+ space = ud_arrow_width * 1.5f;
+ }
+ mui.draw_text_full(container, itemtext, effective_left + space, line_y, effective_width - space, JUSTIFY_LEFT, WRAP_TRUNCATE,
+ DRAW_NORMAL, item_invert ? fgcolor3 : fgcolor, bgcolor, nullptr, nullptr);
+ }
+ else
+ {
+ int item_invert = pitem.flags & MENU_FLAG_INVERT;
+ const char *subitem_text = pitem.subtext;
+ float item_width, subitem_width;
+
+ // compute right space for subitem
+ mui.draw_text_full(container, subitem_text, effective_left, line_y, mame_machine_manager::instance()->ui().get_string_width(pitem.subtext),
+ JUSTIFY_RIGHT, WRAP_NEVER, DRAW_NONE, item_invert ? fgcolor3 : fgcolor, bgcolor, &subitem_width, nullptr);
+ subitem_width += gutter_width;
+
+ // draw the item left-justified
+ mui.draw_text_full(container, itemtext, effective_left, line_y, effective_width - subitem_width,
+ JUSTIFY_LEFT, WRAP_TRUNCATE, DRAW_NORMAL, item_invert ? fgcolor3 : fgcolor, bgcolor, &item_width, nullptr);
+
+ // draw the subitem right-justified
+ mui.draw_text_full(container, subitem_text, effective_left + item_width, line_y, effective_width - item_width,
+ JUSTIFY_RIGHT, WRAP_NEVER, DRAW_NORMAL, item_invert ? fgcolor3 : fgcolor, bgcolor, nullptr, nullptr);
+ }
+ }
+
+ for (size_t count = visible_items; count < item.size(); count++)
+ {
+ const ui_menu_item &pitem = item[count];
+ const char *itemtext = pitem.text;
+ float line_x0 = x1 + 0.5f * UI_LINE_WIDTH;
+ float line_y0 = line;
+ float line_x1 = x2 - 0.5f * UI_LINE_WIDTH;
+ float line_y1 = line + line_height;
+ rgb_t fgcolor = UI_TEXT_COLOR;
+ rgb_t bgcolor = UI_TEXT_BG_COLOR;
+
+ if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y && pitem.is_selectable())
+ hover = count;
+
+ // if we're selected, draw with a different background
+ if (count == selected && m_focus == focused_menu::main)
+ {
+ fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00);
+ bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff);
+ mui.draw_textured_box(container, line_x0 + 0.01f, line_y0, line_x1 - 0.01f, line_y1, bgcolor, rgb_t(255, 43, 43, 43),
+ hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
+ }
+ // else if the mouse is over this item, draw with a different background
+ else if (count == hover)
+ {
+ fgcolor = UI_MOUSEOVER_COLOR;
+ bgcolor = UI_MOUSEOVER_BG_COLOR;
+ highlight(container, line_x0, line_y0, line_x1, line_y1, bgcolor);
+ }
+
+ if (strcmp(itemtext, MENU_SEPARATOR_ITEM) == 0)
+ container->add_line(visible_left, line + 0.5f * line_height, visible_left + visible_width, line + 0.5f * line_height,
+ UI_LINE_WIDTH, UI_TEXT_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ else
+ mui.draw_text_full(container, itemtext, effective_left, line, effective_width, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr);
+ line += line_height;
+ }
+
+ x1 = x2;
+ x2 += right_panel_size;
+
+ draw_right_panel((selected >= 0 && selected < item.size()) ? item[selected].ref : nullptr, x1, y1, x2, y2);
+
+ x1 = primary_left - UI_BOX_LR_BORDER;
+ x2 = primary_left + primary_width + UI_BOX_LR_BORDER;
+
+ // if there is something special to add, do it by calling the virtual method
+ custom_render((selected >= 0 && selected < item.size()) ? item[selected].ref : nullptr, customtop, custombottom, x1, y1, x2, y2);
+
+ // return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow
+ visitems = visible_lines - (top_line != 0) - (top_line + visible_lines != visible_items);
+
+ // reset redraw icon stage
+ if (!is_swlist)
+ ui_globals::redraw_icon = false;
+
+ // noinput
+ if (noinput)
+ {
+ int alpha = (1.0f - machine().options().pause_brightness()) * 255.0f;
+ if (alpha > 255)
+ alpha = 255;
+ if (alpha >= 0)
+ container->add_rect(0.0f, 0.0f, 1.0f, 1.0f, rgb_t(alpha, 0x00, 0x00, 0x00), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ }
+}
+
+//-------------------------------------------------
+// get title and search path for right panel
+//-------------------------------------------------
+
+void ui_menu::get_title_search(std::string &snaptext, std::string &searchstr)
+{
+ // get arts title text
+ snaptext.assign(_(arts_info[ui_globals::curimage_view].title));
+
+ // get search path
+ std::string addpath;
+ if (ui_globals::curimage_view == SNAPSHOT_VIEW)
+ {
+ emu_options moptions;
+ searchstr = machine().options().value(arts_info[ui_globals::curimage_view].path);
+ addpath = moptions.value(arts_info[ui_globals::curimage_view].path);
+ }
+ else
+ {
+ ui_options moptions;
+ searchstr = mame_machine_manager::instance()->ui().options().value(arts_info[ui_globals::curimage_view].path);
+ addpath = moptions.value(arts_info[ui_globals::curimage_view].path);
+ }
+
+ std::string tmp(searchstr);
+ path_iterator path(tmp.c_str());
+ path_iterator path_iter(addpath.c_str());
+ std::string c_path, curpath;
+
+ // iterate over path and add path for zipped formats
+ while (path.next(curpath))
+ {
+ path_iter.reset();
+ while (path_iter.next(c_path))
+ searchstr.append(";").append(curpath).append(PATH_SEPARATOR).append(c_path);
+ }
+}
+
+//-------------------------------------------------
+// handle keys for main menu
+//-------------------------------------------------
+
+void ui_menu::handle_main_keys(UINT32 flags)
+{
+ bool ignorepause = ui_menu::stack_has_special_main_menu();
+
+ // bail if no items
+ if (item.size() == 0)
+ return;
+
+ // if we hit select, return TRUE or pop the stack, depending on the item
+ if (exclusive_input_pressed(IPT_UI_SELECT, 0))
+ {
+ if (selected == item.size() - 1 && m_focus == focused_menu::main)
+ {
+ menu_event.iptkey = IPT_UI_CANCEL;
+ ui_menu::stack_pop(machine());
+ }
+ return;
+ }
+
+ // hitting cancel also pops the stack
+ if (exclusive_input_pressed(IPT_UI_CANCEL, 0))
+ {
+ if (!ui_error && !menu_has_search_active())
+ ui_menu::stack_pop(machine());
+ return;
+ }
+
+ // validate the current selection
+ validate_selection(1);
+
+ // swallow left/right keys if they are not appropriate
+ bool ignoreleft = ((item[selected].flags & MENU_FLAG_LEFT_ARROW) == 0);
+ bool ignoreright = ((item[selected].flags & MENU_FLAG_RIGHT_ARROW) == 0);
+ bool leftclose = (ui_globals::panels_status == HIDE_BOTH || ui_globals::panels_status == HIDE_LEFT_PANEL);
+ bool rightclose = (ui_globals::panels_status == HIDE_BOTH || ui_globals::panels_status == HIDE_RIGHT_PANEL);
+
+ // accept left/right keys as-is with repeat
+ if (!ignoreleft && exclusive_input_pressed(IPT_UI_LEFT, (flags & UI_MENU_PROCESS_LR_REPEAT) ? 6 : 0))
+ {
+ // Swap the right panel
+ if (m_focus == focused_menu::righttop)
+ menu_event.iptkey = IPT_UI_LEFT_PANEL;
+ return;
+ }
+
+ if (!ignoreright && exclusive_input_pressed(IPT_UI_RIGHT, (flags & UI_MENU_PROCESS_LR_REPEAT) ? 6 : 0))
+ {
+ // Swap the right panel
+ if (m_focus == focused_menu::righttop)
+ menu_event.iptkey = IPT_UI_RIGHT_PANEL;
+ return;
+ }
+
+ // up backs up by one item
+ if (exclusive_input_pressed(IPT_UI_UP, 6))
+ {
+ // Filter
+ if (!leftclose && m_focus == focused_menu::left)
+ {
+ menu_event.iptkey = IPT_UI_UP_FILTER;
+ return;
+ }
+
+ // Infos
+ if (!rightclose && m_focus == focused_menu::rightbottom)
+ {
+ menu_event.iptkey = IPT_UI_UP_PANEL;
+ topline_datsview--;
+ return;
+ }
+
+ if (selected == visible_items + 1 || selected == 0 || ui_error)
+ return;
+
+ selected--;
+
+ if (selected == top_line && top_line != 0)
+ top_line--;
+ }
+
+ // down advances by one item
+ if (exclusive_input_pressed(IPT_UI_DOWN, 6))
+ {
+ // Filter
+ if (!leftclose && m_focus == focused_menu::left)
+ {
+ menu_event.iptkey = IPT_UI_DOWN_FILTER;
+ return;
+ }
+
+ // Infos
+ if (!rightclose && m_focus == focused_menu::rightbottom)
+ {
+ menu_event.iptkey = IPT_UI_DOWN_PANEL;
+ topline_datsview++;
+ return;
+ }
+
+ if (selected == item.size() - 1 || selected == visible_items - 1 || ui_error)
+ return;
+
+ selected++;
+
+ if (selected == top_line + visitems + (top_line != 0))
+ top_line++;
+ }
+
+ // page up backs up by visitems
+ if (exclusive_input_pressed(IPT_UI_PAGE_UP, 6))
+ {
+ // Infos
+ if (!rightclose && m_focus == focused_menu::rightbottom)
+ {
+ menu_event.iptkey = IPT_UI_DOWN_PANEL;
+ topline_datsview -= right_visible_lines - 1;
+ return;
+ }
+
+ if (selected < visible_items && !ui_error)
+ {
+ selected -= visitems;
+
+ if (selected < 0)
+ selected = 0;
+
+ top_line -= visitems - (top_line + visible_lines == visible_items);
+ }
+ }
+
+ // page down advances by visitems
+ if (exclusive_input_pressed(IPT_UI_PAGE_DOWN, 6))
+ {
+ // Infos
+ if (!rightclose && m_focus == focused_menu::rightbottom)
+ {
+ menu_event.iptkey = IPT_UI_DOWN_PANEL;
+ topline_datsview += right_visible_lines - 1;
+ return;
+ }
+
+ if (selected < visible_items && !ui_error)
+ {
+ selected += visible_lines - 2 + (selected == 0);
+
+ if (selected >= visible_items)
+ selected = visible_items - 1;
+
+ top_line += visible_lines - 2;
+ }
+ }
+
+ // home goes to the start
+ if (exclusive_input_pressed(IPT_UI_HOME, 0))
+ {
+ // Infos
+ if (!rightclose && m_focus == focused_menu::rightbottom)
+ {
+ menu_event.iptkey = IPT_UI_DOWN_PANEL;
+ topline_datsview = 0;
+ return;
+ }
+
+ if (selected < visible_items && !ui_error)
+ {
+ selected = 0;
+ top_line = 0;
+ }
+ }
+
+ // end goes to the last
+ if (exclusive_input_pressed(IPT_UI_END, 0))
+ {
+ // Infos
+ if (!rightclose && m_focus == focused_menu::rightbottom)
+ {
+ menu_event.iptkey = IPT_UI_DOWN_PANEL;
+ topline_datsview = totallines;
+ return;
+ }
+
+ if (selected < visible_items && !ui_error)
+ selected = top_line = visible_items - 1;
+ }
+
+ // pause enables/disables pause
+ if (!ui_error && !ignorepause && exclusive_input_pressed(IPT_UI_PAUSE, 0))
+ {
+ if (machine().paused())
+ machine().resume();
+ else
+ machine().pause();
+ }
+
+ // handle a toggle cheats request
+ if (!ui_error && machine().ui_input().pressed_repeat(IPT_UI_TOGGLE_CHEAT, 0))
+ mame_machine_manager::instance()->cheat().set_enable(!mame_machine_manager::instance()->cheat().enabled());
+
+ // see if any other UI keys are pressed
+ if (menu_event.iptkey == IPT_INVALID)
+ for (int code = IPT_UI_FIRST + 1; code < IPT_UI_LAST; code++)
+ {
+ if (ui_error || code == IPT_UI_CONFIGURE || (code == IPT_UI_LEFT && ignoreleft) || (code == IPT_UI_RIGHT && ignoreright) || (code == IPT_UI_PAUSE && ignorepause))
+ continue;
+
+ if (exclusive_input_pressed(code, 0))
+ break;
+ }
+}
+
+//-------------------------------------------------
+// handle input events for main menu
+//-------------------------------------------------
+
+void ui_menu::handle_main_events(UINT32 flags)
+{
+ bool stop = false;
+ ui_event local_menu_event;
+
+ if (m_pressed)
+ {
+ bool pressed = mouse_pressed();
+ INT32 m_target_x, m_target_y;
+ bool m_button;
+ render_target *mouse_target = machine().ui_input().find_mouse(&m_target_x, &m_target_y, &m_button);
+ if (mouse_target != nullptr && m_button && (hover == HOVER_ARROW_DOWN || hover == HOVER_ARROW_UP))
+ {
+ if (pressed)
+ machine().ui_input().push_mouse_down_event(mouse_target, m_target_x, m_target_y);
+ }
+ else
+ reset_pressed();
+ }
+
+ // loop while we have interesting events
+ while (!stop && machine().ui_input().pop_event(&local_menu_event))
+ {
+ switch (local_menu_event.event_type)
+ {
+ // if we are hovering over a valid item, select it with a single click
+ case UI_EVENT_MOUSE_DOWN:
+ {
+ if (ui_error)
+ {
+ menu_event.iptkey = IPT_OTHER;
+ stop = true;
+ }
+ else
+ {
+ if (hover >= 0 && hover < item.size())
+ {
+ if (hover >= visible_items - 1 && selected < visible_items)
+ m_prev_selected = item[selected].ref;
+ selected = hover;
+ m_focus = focused_menu::main;
+ }
+ else if (hover == HOVER_ARROW_UP)
+ {
+ selected -= visitems;
+ if (selected < 0)
+ selected = 0;
+ top_line -= visitems - (top_line + visible_lines == visible_items);
+ set_pressed();
+ }
+ else if (hover == HOVER_ARROW_DOWN)
+ {
+ selected += visible_lines - 2 + (selected == 0);
+ if (selected >= visible_items)
+ selected = visible_items - 1;
+ top_line += visible_lines - 2;
+ set_pressed();
+ }
+ else if (hover == HOVER_UI_RIGHT)
+ menu_event.iptkey = IPT_UI_RIGHT;
+ else if (hover == HOVER_UI_LEFT)
+ menu_event.iptkey = IPT_UI_LEFT;
+ else if (hover == HOVER_DAT_DOWN)
+ topline_datsview += right_visible_lines - 1;
+ else if (hover == HOVER_DAT_UP)
+ topline_datsview -= right_visible_lines - 1;
+ else if (hover == HOVER_LPANEL_ARROW)
+ {
+ if (ui_globals::panels_status == HIDE_LEFT_PANEL)
+ ui_globals::panels_status = SHOW_PANELS;
+ else if (ui_globals::panels_status == HIDE_BOTH)
+ ui_globals::panels_status = HIDE_RIGHT_PANEL;
+ else if (ui_globals::panels_status == SHOW_PANELS)
+ ui_globals::panels_status = HIDE_LEFT_PANEL;
+ else if (ui_globals::panels_status == HIDE_RIGHT_PANEL)
+ ui_globals::panels_status = HIDE_BOTH;
+ }
+ else if (hover == HOVER_RPANEL_ARROW)
+ {
+ if (ui_globals::panels_status == HIDE_RIGHT_PANEL)
+ ui_globals::panels_status = SHOW_PANELS;
+ else if (ui_globals::panels_status == HIDE_BOTH)
+ ui_globals::panels_status = HIDE_LEFT_PANEL;
+ else if (ui_globals::panels_status == SHOW_PANELS)
+ ui_globals::panels_status = HIDE_RIGHT_PANEL;
+ else if (ui_globals::panels_status == HIDE_LEFT_PANEL)
+ ui_globals::panels_status = HIDE_BOTH;
+ }
+ else if (hover == HOVER_B_FAV)
+ {
+ menu_event.iptkey = IPT_UI_FAVORITES;
+ stop = true;
+ }
+ else if (hover == HOVER_B_EXPORT)
+ {
+ menu_event.iptkey = IPT_UI_EXPORT;
+ stop = true;
+ }
+ else if (hover == HOVER_B_DATS)
+ {
+ menu_event.iptkey = IPT_UI_DATS;
+ stop = true;
+ }
+ else if (hover >= HOVER_RP_FIRST && hover <= HOVER_RP_LAST)
+ {
+ ui_globals::rpanel = (HOVER_RP_FIRST - hover) * (-1);
+ stop = true;
+ }
+ else if (hover >= HOVER_SW_FILTER_FIRST && hover <= HOVER_SW_FILTER_LAST)
+ {
+ l_sw_hover = (HOVER_SW_FILTER_FIRST - hover) * (-1);
+ menu_event.iptkey = IPT_OTHER;
+ stop = true;
+ }
+ else if (hover >= HOVER_FILTER_FIRST && hover <= HOVER_FILTER_LAST)
+ {
+ l_hover = (HOVER_FILTER_FIRST - hover) * (-1);
+ menu_event.iptkey = IPT_OTHER;
+ stop = true;
+ }
+ }
+ break;
+ }
+
+ // if we are hovering over a valid item, fake a UI_SELECT with a double-click
+ case UI_EVENT_MOUSE_DOUBLE_CLICK:
+ if (hover >= 0 && hover < item.size())
+ {
+ selected = hover;
+ menu_event.iptkey = IPT_UI_SELECT;
+ }
+
+ if (selected == item.size() - 1)
+ {
+ menu_event.iptkey = IPT_UI_CANCEL;
+ ui_menu::stack_pop(machine());
+ }
+ stop = true;
+ break;
+
+ // caught scroll event
+ case UI_EVENT_MOUSE_WHEEL:
+ if (hover >= 0 && hover < item.size() - skip_main_items - 1)
+ {
+ if (local_menu_event.zdelta > 0)
+ {
+ if (selected >= visible_items || selected == 0 || ui_error)
+ break;
+ selected -= local_menu_event.num_lines;
+ if (selected < top_line + (top_line != 0))
+ top_line -= local_menu_event.num_lines;
+ }
+ else
+ {
+ if (selected >= visible_items - 1 || ui_error)
+ break;
+ selected += local_menu_event.num_lines;
+ if (selected > visible_items - 1)
+ selected = visible_items - 1;
+ if (selected >= top_line + visitems + (top_line != 0))
+ top_line += local_menu_event.num_lines;
+ }
+ }
+ break;
+
+ // translate CHAR events into specials
+ case UI_EVENT_CHAR:
+ if (exclusive_input_pressed(IPT_UI_CONFIGURE, 0))
+ {
+ menu_event.iptkey = IPT_UI_CONFIGURE;
+ stop = true;
+ }
+ else
+ {
+ menu_event.iptkey = IPT_SPECIAL;
+ menu_event.unichar = local_menu_event.ch;
+ stop = true;
+ }
+ break;
+
+ case UI_EVENT_MOUSE_RDOWN:
+ if (hover >= 0 && hover < item.size() - skip_main_items - 1)
+ {
+ selected = hover;
+ m_prev_selected = item[selected].ref;
+ m_focus = focused_menu::main;
+ menu_event.iptkey = IPT_CUSTOM;
+ menu_event.mouse.x0 = local_menu_event.mouse_x;
+ menu_event.mouse.y0 = local_menu_event.mouse_y;
+ stop = true;
+ }
+ break;
+
+ // ignore everything else
+ default:
+ break;
+ }
+ }
+}
+
+//-------------------------------------------------
+// draw right box title
+//-------------------------------------------------
+
+float ui_menu::draw_right_box_title(float x1, float y1, float x2, float y2)
+{
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+ float line_height = mui.get_line_height();
+ float midl = (x2 - x1) * 0.5f;
+
+ // add outlined box for options
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
+
+ // add separator line
+ container->add_line(x1 + midl, y1, x1 + midl, y1 + line_height, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+
+ std::string buffer[RP_LAST + 1];
+ buffer[RP_IMAGES] = _("Images");
+ buffer[RP_INFOS] = _("Infos");
+
+ // check size
+ float text_size = 1.0f;
+ for (auto & elem : buffer)
+ {
+ float textlen = mui.get_string_width(elem.c_str()) + 0.01f;
+ float tmp_size = (textlen > midl) ? (midl / textlen) : 1.0f;
+ text_size = MIN(text_size, tmp_size);
+ }
+
+ for (int cells = RP_FIRST; cells <= RP_LAST; ++cells)
+ {
+ rgb_t bgcolor = UI_TEXT_BG_COLOR;
+ rgb_t fgcolor = UI_TEXT_COLOR;
+
+ if (mouse_hit && x1 <= mouse_x && x1 + midl > mouse_x && y1 <= mouse_y && y1 + line_height > mouse_y)
+ {
+ if (ui_globals::rpanel != cells)
+ {
+ bgcolor = UI_MOUSEOVER_BG_COLOR;
+ fgcolor = UI_MOUSEOVER_COLOR;
+ hover = HOVER_RP_FIRST + cells;
+ }
+ }
+
+ if (ui_globals::rpanel != cells)
+ {
+ container->add_line(x1, y1 + line_height, x1 + midl, y1 + line_height, UI_LINE_WIDTH,
+ UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ if (fgcolor != UI_MOUSEOVER_COLOR)
+ fgcolor = UI_CLONE_COLOR;
+ }
+
+ if (m_focus == focused_menu::righttop && ui_globals::rpanel == cells)
+ {
+ fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00);
+ bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff);
+ mui.draw_textured_box(container, x1 + UI_LINE_WIDTH, y1 + UI_LINE_WIDTH, x1 + midl - UI_LINE_WIDTH, y1 + line_height,
+ bgcolor, rgb_t(255, 43, 43, 43), hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
+ }
+ else if (bgcolor == UI_MOUSEOVER_BG_COLOR)
+ container->add_rect(x1 + UI_LINE_WIDTH, y1 + UI_LINE_WIDTH, x1 + midl - UI_LINE_WIDTH, y1 + line_height,
+ bgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
+
+ mui.draw_text_full(container, buffer[cells].c_str(), x1 + UI_LINE_WIDTH, y1, midl - UI_LINE_WIDTH,
+ JUSTIFY_CENTER, WRAP_NEVER, DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr, text_size);
+ x1 += midl;
+ }
+
+ return (y1 + line_height + UI_LINE_WIDTH);
+}
+
+//-------------------------------------------------
+// common function for images render
+//-------------------------------------------------
+
+std::string ui_menu::arts_render_common(float origx1, float origy1, float origx2, float origy2)
+{
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+ float line_height = mui.get_line_height();
+ std::string snaptext, searchstr;
+ float title_size = 0.0f;
+ float txt_lenght = 0.0f;
+ float gutter_width = 0.4f * line_height * machine().render().ui_aspect() * 1.3f;
+
+ get_title_search(snaptext, searchstr);
+
+ // apply title to right panel
+ for (int x = FIRST_VIEW; x < LAST_VIEW; x++)
+ {
+ mui.draw_text_full(container, _(arts_info[x].title), origx1, origy1, origx2 - origx1, JUSTIFY_CENTER,
+ WRAP_TRUNCATE, DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &txt_lenght, nullptr);
+ txt_lenght += 0.01f;
+ title_size = MAX(txt_lenght, title_size);
+ }
+
+ rgb_t fgcolor = (m_focus == focused_menu::rightbottom) ? rgb_t(0xff, 0xff, 0xff, 0x00) : UI_TEXT_COLOR;
+ rgb_t bgcolor = (m_focus == focused_menu::rightbottom) ? rgb_t(0xff, 0xff, 0xff, 0xff) : UI_TEXT_BG_COLOR;
+ float middle = origx2 - origx1;
+
+ // check size
+ float sc = title_size + 2.0f * gutter_width;
+ float tmp_size = (sc > middle) ? ((middle - 2.0f * gutter_width) / sc) : 1.0f;
+ title_size *= tmp_size;
+
+ if (bgcolor != UI_TEXT_BG_COLOR)
+ mui.draw_textured_box(container, origx1 + ((middle - title_size) * 0.5f), origy1, origx1 + ((middle + title_size) * 0.5f),
+ origy1 + line_height, bgcolor, rgb_t(255, 43, 43, 43), hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
+
+ mui.draw_text_full(container, snaptext.c_str(), origx1, origy1, origx2 - origx1, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr, tmp_size);
+
+ draw_common_arrow(origx1, origy1, origx2, origy2, ui_globals::curimage_view, FIRST_VIEW, LAST_VIEW, title_size);
+
+ return searchstr;
+}
+
+//-------------------------------------------------
+// draw favorites star
+//-------------------------------------------------
+
+void ui_menu::draw_star(float x0, float y0)
+{
+ float y1 = y0 + mame_machine_manager::instance()->ui().get_line_height();
+ float x1 = x0 + mame_machine_manager::instance()->ui().get_line_height() * container->manager().ui_aspect();
+ container->add_quad(x0, y0, x1, y1, ARGB_WHITE, star_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_PACKABLE);
+}
+
+//-------------------------------------------------
+// draw toolbar
+//-------------------------------------------------
+
+void ui_menu::draw_toolbar(float x1, float y1, float x2, float y2, bool software)
+{
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, rgb_t(0xEF, 0x12, 0x47, 0x7B));
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+ y2 -= UI_BOX_TB_BORDER;
+
+ render_texture **t_texture = (software) ? sw_toolbar_texture : toolbar_texture;
+ bitmap_argb32 **t_bitmap = (software) ? sw_toolbar_bitmap : toolbar_bitmap;
+
+ int m_valid = 0;
+ for (int x = 0; x < UI_TOOLBAR_BUTTONS; ++x)
+ {
+ if (t_bitmap[x]->valid())
+ {
+ m_valid++;
+ }
+ }
+
+ float space_x = (y2 - y1) * container->manager().ui_aspect();
+ float total = (m_valid * space_x) + ((m_valid - 1) * 0.001f);
+ x1 = ((x2 - x1) * 0.5f) - (total / 2);
+ x2 = x1 + space_x;
+
+ for (int z = 0; z < UI_TOOLBAR_BUTTONS; ++z)
+ {
+ if (t_bitmap[z]->valid())
+ {
+ rgb_t color(0xEFEFEFEF);
+ if (mouse_hit && x1 <= mouse_x && x2 > mouse_x && y1 <= mouse_y && y2 > mouse_y)
+ {
+ hover = HOVER_B_FAV + z;
+ color = ARGB_WHITE;
+ float ypos = y2 + mame_machine_manager::instance()->ui().get_line_height() + 2.0f * UI_BOX_TB_BORDER;
+ mui.draw_text_box(container, _(hover_msg[z]), JUSTIFY_CENTER, 0.5f, ypos, UI_BACKGROUND_COLOR);
+ }
+
+ container->add_quad(x1, y1, x2, y2, color, t_texture[z], PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ x1 += space_x + ((z < UI_TOOLBAR_BUTTONS - 1) ? 0.001f : 0.0f);
+ x2 = x1 + space_x;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// perform rendering of image
+//-------------------------------------------------
+
+void ui_menu::arts_render_images(bitmap_argb32 *tmp_bitmap, float origx1, float origy1, float origx2, float origy2, bool software)
+{
+ bool no_available = false;
+ float line_height = mame_machine_manager::instance()->ui().get_line_height();
+
+ // if it fails, use the default image
+ if (!tmp_bitmap->valid())
+ {
+ tmp_bitmap->allocate(256, 256);
+ for (int x = 0; x < 256; x++)
+ for (int y = 0; y < 256; y++)
+ tmp_bitmap->pix32(y, x) = no_avail_bitmap->pix32(y, x);
+ no_available = true;
+ }
+
+ if (tmp_bitmap->valid())
+ {
+ float panel_width = origx2 - origx1 - 0.02f;
+ float panel_height = origy2 - origy1 - 0.02f - (2.0f * UI_BOX_TB_BORDER) - (2.0f * line_height);
+ int screen_width = machine().render().ui_target().width();
+ int screen_height = machine().render().ui_target().height();
+
+ if (machine().render().ui_target().orientation() & ORIENTATION_SWAP_XY)
+ std::swap(screen_height, screen_width);
+
+ int panel_width_pixel = panel_width * screen_width;
+ int panel_height_pixel = panel_height * screen_height;
+
+ // Calculate resize ratios for resizing
+ float ratioW = (float)panel_width_pixel / tmp_bitmap->width();
+ float ratioH = (float)panel_height_pixel / tmp_bitmap->height();
+ float ratioI = (float)tmp_bitmap->height() / tmp_bitmap->width();
+ int dest_xPixel = tmp_bitmap->width();
+ int dest_yPixel = tmp_bitmap->height();
+
+ // force 4:3 ratio min
+ if (mame_machine_manager::instance()->ui().options().forced_4x3_snapshot() && ratioI < 0.75f && ui_globals::curimage_view == SNAPSHOT_VIEW)
+ {
+ // smaller ratio will ensure that the image fits in the view
+ dest_yPixel = tmp_bitmap->width() * 0.75f;
+ ratioH = (float)panel_height_pixel / dest_yPixel;
+ float ratio = MIN(ratioW, ratioH);
+ dest_xPixel = tmp_bitmap->width() * ratio;
+ dest_yPixel *= ratio;
+ }
+ // resize the bitmap if necessary
+ else if (ratioW < 1 || ratioH < 1 || (mame_machine_manager::instance()->ui().options().enlarge_snaps() && !no_available))
+ {
+ // smaller ratio will ensure that the image fits in the view
+ float ratio = MIN(ratioW, ratioH);
+ dest_xPixel = tmp_bitmap->width() * ratio;
+ dest_yPixel = tmp_bitmap->height() * ratio;
+ }
+
+ bitmap_argb32 *dest_bitmap;
+
+ // resample if necessary
+ if (dest_xPixel != tmp_bitmap->width() || dest_yPixel != tmp_bitmap->height())
+ {
+ dest_bitmap = auto_alloc(machine(), bitmap_argb32);
+ dest_bitmap->allocate(dest_xPixel, dest_yPixel);
+ render_color color = { 1.0f, 1.0f, 1.0f, 1.0f };
+ render_resample_argb_bitmap_hq(*dest_bitmap, *tmp_bitmap, color, true);
+ }
+ else
+ dest_bitmap = tmp_bitmap;
+
+ snapx_bitmap->allocate(panel_width_pixel, panel_height_pixel);
+ int x1 = (0.5f * panel_width_pixel) - (0.5f * dest_xPixel);
+ int y1 = (0.5f * panel_height_pixel) - (0.5f * dest_yPixel);
+
+ for (int x = 0; x < dest_xPixel; x++)
+ for (int y = 0; y < dest_yPixel; y++)
+ snapx_bitmap->pix32(y + y1, x + x1) = dest_bitmap->pix32(y, x);
+
+ auto_free(machine(), dest_bitmap);
+
+ // apply bitmap
+ snapx_texture->set_bitmap(*snapx_bitmap, snapx_bitmap->cliprect(), TEXFORMAT_ARGB32);
+ }
+ else
+ snapx_bitmap->reset();
+}
+
+//-------------------------------------------------
+// draw common arrows
+//-------------------------------------------------
+
+void ui_menu::draw_common_arrow(float origx1, float origy1, float origx2, float origy2, int current, int dmin, int dmax, float title_size)
+{
+ float line_height = mame_machine_manager::instance()->ui().get_line_height();
+ float lr_arrow_width = 0.4f * line_height * machine().render().ui_aspect();
+ float gutter_width = lr_arrow_width * 1.3f;
+
+ // set left-right arrows dimension
+ float ar_x0 = 0.5f * (origx2 + origx1) + 0.5f * title_size + gutter_width - lr_arrow_width;
+ float ar_y0 = origy1 + 0.1f * line_height;
+ float ar_x1 = 0.5f * (origx2 + origx1) + 0.5f * title_size + gutter_width;
+ float ar_y1 = origy1 + 0.9f * line_height;
+
+ float al_x0 = 0.5f * (origx2 + origx1) - 0.5f * title_size - gutter_width;
+ float al_y0 = origy1 + 0.1f * line_height;
+ float al_x1 = 0.5f * (origx2 + origx1) - 0.5f * title_size - gutter_width + lr_arrow_width;
+ float al_y1 = origy1 + 0.9f * line_height;
+
+ rgb_t fgcolor_right, fgcolor_left;
+ fgcolor_right = fgcolor_left = UI_TEXT_COLOR;
+
+ // set hover
+ if (mouse_hit && ar_x0 <= mouse_x && ar_x1 > mouse_x && ar_y0 <= mouse_y && ar_y1 > mouse_y && current != dmax)
+ {
+ mame_machine_manager::instance()->ui().draw_textured_box(container, ar_x0 + 0.01f, ar_y0, ar_x1 - 0.01f, ar_y1, UI_MOUSEOVER_BG_COLOR, rgb_t(255, 43, 43, 43),
+ hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
+ hover = HOVER_UI_RIGHT;
+ fgcolor_right = UI_MOUSEOVER_COLOR;
+ }
+ else if (mouse_hit && al_x0 <= mouse_x && al_x1 > mouse_x && al_y0 <= mouse_y && al_y1 > mouse_y && current != dmin)
+ {
+ mame_machine_manager::instance()->ui().draw_textured_box(container, al_x0 + 0.01f, al_y0, al_x1 - 0.01f, al_y1, UI_MOUSEOVER_BG_COLOR, rgb_t(255, 43, 43, 43),
+ hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
+ hover = HOVER_UI_LEFT;
+ fgcolor_left = UI_MOUSEOVER_COLOR;
+ }
+
+ // apply arrow
+ if (current == dmin)
+ draw_arrow(container, ar_x0, ar_y0, ar_x1, ar_y1, fgcolor_right, ROT90);
+ else if (current == dmax)
+ draw_arrow(container, al_x0, al_y0, al_x1, al_y1, fgcolor_left, ROT90 ^ ORIENTATION_FLIP_X);
+ else
+ {
+ draw_arrow(container, ar_x0, ar_y0, ar_x1, ar_y1, fgcolor_right, ROT90);
+ draw_arrow(container, al_x0, al_y0, al_x1, al_y1, fgcolor_left, ROT90 ^ ORIENTATION_FLIP_X);
+ }
+}
+
+//-------------------------------------------------
+// draw icons
+//-------------------------------------------------
+
+void ui_menu::draw_icon(int linenum, void *selectedref, float x0, float y0)
+{
+ static const game_driver *olddriver[MAX_ICONS_RENDER] = { nullptr };
+ float x1 = x0 + mame_machine_manager::instance()->ui().get_line_height() * container->manager().ui_aspect(container);
+ float y1 = y0 + mame_machine_manager::instance()->ui().get_line_height();
+ const game_driver *driver = (const game_driver *)selectedref;
+
+ if (olddriver[linenum] != driver || ui_globals::redraw_icon)
+ {
+ olddriver[linenum] = driver;
+
+ // set clone status
+ bool cloneof = strcmp(driver->parent, "0");
+ if (cloneof)
+ {
+ int cx = driver_list::find(driver->parent);
+ if (cx != -1 && ((driver_list::driver(cx).flags & MACHINE_IS_BIOS_ROOT) != 0))
+ cloneof = false;
+ }
+
+ // get search path
+ path_iterator path(mame_machine_manager::instance()->ui().options().icons_directory());
+ std::string curpath;
+ std::string searchstr(mame_machine_manager::instance()->ui().options().icons_directory());
+
+ // iterate over path and add path for zipped formats
+ while (path.next(curpath))
+ searchstr.append(";").append(curpath.c_str()).append(PATH_SEPARATOR).append("icons");
+
+ bitmap_argb32 *tmp = auto_alloc(machine(), bitmap_argb32);
+ emu_file snapfile(searchstr.c_str(), OPEN_FLAG_READ);
+ std::string fullname = std::string(driver->name).append(".ico");
+ render_load_ico(*tmp, snapfile, nullptr, fullname.c_str());
+
+ if (!tmp->valid() && cloneof)
+ {
+ fullname.assign(driver->parent).append(".ico");
+ render_load_ico(*tmp, snapfile, nullptr, fullname.c_str());
+ }
+
+ if (tmp->valid())
+ {
+ float panel_width = x1 - x0;
+ float panel_height = y1 - y0;
+ int screen_width = machine().render().ui_target().width();
+ int screen_height = machine().render().ui_target().height();
+
+ if (machine().render().ui_target().orientation() & ORIENTATION_SWAP_XY)
+ std::swap(screen_height, screen_width);
+
+ int panel_width_pixel = panel_width * screen_width;
+ int panel_height_pixel = panel_height * screen_height;
+
+ // Calculate resize ratios for resizing
+ float ratioW = (float)panel_width_pixel / tmp->width();
+ float ratioH = (float)panel_height_pixel / tmp->height();
+ int dest_xPixel = tmp->width();
+ int dest_yPixel = tmp->height();
+
+ if (ratioW < 1 || ratioH < 1)
+ {
+ // smaller ratio will ensure that the image fits in the view
+ float ratio = MIN(ratioW, ratioH);
+ dest_xPixel = tmp->width() * ratio;
+ dest_yPixel = tmp->height() * ratio;
+ }
+
+ bitmap_argb32 *dest_bitmap;
+ dest_bitmap = auto_alloc(machine(), bitmap_argb32);
+
+ // resample if necessary
+ if (dest_xPixel != tmp->width() || dest_yPixel != tmp->height())
+ {
+ dest_bitmap->allocate(dest_xPixel, dest_yPixel);
+ render_color color = { 1.0f, 1.0f, 1.0f, 1.0f };
+ render_resample_argb_bitmap_hq(*dest_bitmap, *tmp, color, true);
+ }
+ else
+ dest_bitmap = tmp;
+
+ icons_bitmap[linenum]->reset();
+ icons_bitmap[linenum]->allocate(panel_width_pixel, panel_height_pixel);
+
+ for (int x = 0; x < dest_xPixel; x++)
+ for (int y = 0; y < dest_yPixel; y++)
+ icons_bitmap[linenum]->pix32(y, x) = dest_bitmap->pix32(y, x);
+
+ auto_free(machine(), dest_bitmap);
+
+ icons_texture[linenum]->set_bitmap(*icons_bitmap[linenum], icons_bitmap[linenum]->cliprect(), TEXFORMAT_ARGB32);
+ }
+ else if (icons_bitmap[linenum] != nullptr)
+ icons_bitmap[linenum]->reset();
+
+ auto_free(machine(), tmp);
+ }
+
+ if (icons_bitmap[linenum] != nullptr && icons_bitmap[linenum]->valid())
+ container->add_quad(x0, y0, x1, y1, ARGB_WHITE, icons_texture[linenum], PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+}
+
+//-------------------------------------------------
+// draw info arrow
+//-------------------------------------------------
+
+void ui_menu::info_arrow(int ub, float origx1, float origx2, float oy1, float line_height, float text_size, float ud_arrow_width)
+{
+ rgb_t fgcolor = UI_TEXT_COLOR;
+ UINT32 orientation = (!ub) ? ROT0 : ROT0 ^ ORIENTATION_FLIP_Y;
+
+ if (mouse_hit && origx1 <= mouse_x && origx2 > mouse_x && oy1 <= mouse_y && oy1 + (line_height * text_size) > mouse_y)
+ {
+ mame_machine_manager::instance()->ui().draw_textured_box(container, origx1 + 0.01f, oy1, origx2 - 0.01f, oy1 + (line_height * text_size), UI_MOUSEOVER_BG_COLOR,
+ rgb_t(255, 43, 43, 43), hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
+ hover = (!ub) ? HOVER_DAT_UP : HOVER_DAT_DOWN;
+ fgcolor = UI_MOUSEOVER_COLOR;
+ }
+
+ draw_arrow(container, 0.5f * (origx1 + origx2) - 0.5f * (ud_arrow_width * text_size), oy1 + 0.25f * (line_height * text_size),
+ 0.5f * (origx1 + origx2) + 0.5f * (ud_arrow_width * text_size), oy1 + 0.75f * (line_height * text_size), fgcolor, orientation);
+}
+
+//-------------------------------------------------
+// draw - draw palette menu
+//-------------------------------------------------
+
+void ui_menu::draw_palette_menu()
+{
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+ float line_height = mui.get_line_height();
+ float lr_arrow_width = 0.4f * line_height * machine().render().ui_aspect();
+ float ud_arrow_width = line_height * machine().render().ui_aspect();
+ float gutter_width = lr_arrow_width * 1.3f;
+ int itemnum, linenum;
+
+ if (mame_machine_manager::instance()->ui().options().use_background_image() && machine().options().system() == nullptr && bgrnd_bitmap->valid())
+ container->add_quad(0.0f, 0.0f, 1.0f, 1.0f, ARGB_WHITE, bgrnd_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+
+ // compute the width and height of the full menu
+ float visible_width = 0;
+ float visible_main_menu_height = 0;
+ for (itemnum = 0; itemnum < item.size(); itemnum++)
+ {
+ const ui_menu_item &pitem = item[itemnum];
+
+ // compute width of left hand side
+ float total_width = gutter_width + mui.get_string_width(pitem.text) + gutter_width;
+
+ // add in width of right hand side
+ if (pitem.subtext)
+ total_width += 2.0f * gutter_width + mui.get_string_width(pitem.subtext);
+
+ // track the maximum
+ if (total_width > visible_width)
+ visible_width = total_width;
+
+ // track the height as well
+ visible_main_menu_height += line_height;
+ }
+
+ // account for extra space at the top and bottom
+ float visible_extra_menu_height = customtop + custombottom;
+
+ // add a little bit of slop for rounding
+ visible_width += 0.01f;
+ visible_main_menu_height += 0.01f;
+
+ // if we are too wide or too tall, clamp it down
+ if (visible_width + 2.0f * UI_BOX_LR_BORDER > 1.0f)
+ visible_width = 1.0f - 2.0f * UI_BOX_LR_BORDER;
+
+ // if the menu and extra menu won't fit, take away part of the regular menu, it will scroll
+ if (visible_main_menu_height + visible_extra_menu_height + 2.0f * UI_BOX_TB_BORDER > 1.0f)
+ visible_main_menu_height = 1.0f - 2.0f * UI_BOX_TB_BORDER - visible_extra_menu_height;
+
+ int visible_lines = floor(visible_main_menu_height / line_height);
+ visible_main_menu_height = (float)visible_lines * line_height;
+
+ // compute top/left of inner menu area by centering
+ float visible_left = (1.0f - visible_width) * 0.5f;
+ float visible_top = (1.0f - (visible_main_menu_height + visible_extra_menu_height)) * 0.5f;
+
+ // if the menu is at the bottom of the extra, adjust
+ visible_top += customtop;
+
+ // first add us a box
+ float x1 = visible_left - UI_BOX_LR_BORDER;
+ float y1 = visible_top - UI_BOX_TB_BORDER;
+ float x2 = visible_left + visible_width + UI_BOX_LR_BORDER;
+ float y2 = visible_top + visible_main_menu_height + UI_BOX_TB_BORDER;
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
+
+ // determine the first visible line based on the current selection
+ int top_line = selected - visible_lines / 2;
+ if (top_line < 0)
+ top_line = 0;
+ if (top_line + visible_lines >= item.size())
+ top_line = item.size() - visible_lines;
+
+ // determine effective positions taking into account the hilighting arrows
+ float effective_width = visible_width - 2.0f * gutter_width;
+ float effective_left = visible_left + gutter_width;
+
+ // locate mouse
+ mouse_hit = false;
+ mouse_button = false;
+ mouse_target = machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button);
+ if (mouse_target != nullptr)
+ if (mouse_target->map_point_container(mouse_target_x, mouse_target_y, *container, mouse_x, mouse_y))
+ mouse_hit = true;
+
+ // loop over visible lines
+ hover = item.size() + 1;
+ float line_x0 = x1 + 0.5f * UI_LINE_WIDTH;
+ float line_x1 = x2 - 0.5f * UI_LINE_WIDTH;
+
+ for (linenum = 0; linenum < visible_lines; linenum++)
+ {
+ float line_y = visible_top + (float)linenum * line_height;
+ itemnum = top_line + linenum;
+ const ui_menu_item &pitem = item[itemnum];
+ const char *itemtext = pitem.text;
+ rgb_t fgcolor = UI_TEXT_COLOR;
+ rgb_t bgcolor = UI_TEXT_BG_COLOR;
+ float line_y0 = line_y;
+ float line_y1 = line_y + line_height;
+
+ // set the hover if this is our item
+ if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y && pitem.is_selectable())
+ hover = itemnum;
+
+ // if we're selected, draw with a different background
+ if (itemnum == selected)
+ {
+ fgcolor = UI_SELECTED_COLOR;
+ bgcolor = UI_SELECTED_BG_COLOR;
+ }
+
+ // else if the mouse is over this item, draw with a different background
+ else if (itemnum == hover)
+ {
+ fgcolor = UI_MOUSEOVER_COLOR;
+ bgcolor = UI_MOUSEOVER_BG_COLOR;
+ }
+
+ // if we have some background hilighting to do, add a quad behind everything else
+ if (bgcolor != UI_TEXT_BG_COLOR)
+ highlight(container, line_x0, line_y0, line_x1, line_y1, bgcolor);
+
+ // if we're on the top line, display the up arrow
+ if (linenum == 0 && top_line != 0)
+ {
+ draw_arrow(container,
+ 0.5f * (x1 + x2) - 0.5f * ud_arrow_width,
+ line_y + 0.25f * line_height,
+ 0.5f * (x1 + x2) + 0.5f * ud_arrow_width,
+ line_y + 0.75f * line_height,
+ fgcolor,
+ ROT0);
+ if (hover == itemnum)
+ hover = HOVER_ARROW_UP;
+ }
+
+ // if we're on the bottom line, display the down arrow
+ else if (linenum == visible_lines - 1 && itemnum != item.size() - 1)
+ {
+ draw_arrow(container,
+ 0.5f * (x1 + x2) - 0.5f * ud_arrow_width,
+ line_y + 0.25f * line_height,
+ 0.5f * (x1 + x2) + 0.5f * ud_arrow_width,
+ line_y + 0.75f * line_height,
+ fgcolor,
+ ROT0 ^ ORIENTATION_FLIP_Y);
+ if (hover == itemnum)
+ hover = HOVER_ARROW_DOWN;
+ }
+
+ // if we're just a divider, draw a line
+ else if (strcmp(itemtext, MENU_SEPARATOR_ITEM) == 0)
+ container->add_line(visible_left, line_y + 0.5f * line_height, visible_left + visible_width, line_y + 0.5f * line_height, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+
+ // if we don't have a subitem, just draw the string centered
+ else if (pitem.subtext == nullptr)
+ mui.draw_text_full(container, itemtext, effective_left, line_y, effective_width,
+ JUSTIFY_CENTER, WRAP_TRUNCATE, DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr);
+
+ // otherwise, draw the item on the left and the subitem text on the right
+ else
+ {
+ const char *subitem_text = pitem.subtext;
+ rgb_t color = rgb_t((UINT32)strtoul(subitem_text, nullptr, 16));
+
+ // draw the left-side text
+ mui.draw_text_full(container, itemtext, effective_left, line_y, effective_width,
+ JUSTIFY_LEFT, WRAP_TRUNCATE, DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr);
+
+ // give 2 spaces worth of padding
+ float subitem_width = mui.get_string_width("FF00FF00");
+
+ mui.draw_outlined_box(container, effective_left + effective_width - subitem_width, line_y0,
+ effective_left + effective_width, line_y1, color);
+ }
+ }
+
+ // if there is something special to add, do it by calling the virtual method
+ custom_render((selected >= 0 && selected < item.size()) ? item[selected].ref : nullptr, customtop, custombottom, x1, y1, x2, y2);
+
+ // return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow
+ visitems = visible_lines - (top_line != 0) - (top_line + visible_lines != item.size());
+}
+
+//-------------------------------------------------
+// draw - draw dats menu
+//-------------------------------------------------
+
+void ui_menu::draw_dats_menu()
+{
+ float line_height = mame_machine_manager::instance()->ui().get_line_height();
+ float ud_arrow_width = line_height * machine().render().ui_aspect();
+ float gutter_width = 0.52f * line_height * machine().render().ui_aspect();
+ mouse_x = -1, mouse_y = -1;
+ float visible_width = 1.0f - 2.0f * UI_BOX_LR_BORDER;
+ float visible_left = (1.0f - visible_width) * 0.5f;
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+
+ // draw background image if available
+ if (mame_machine_manager::instance()->ui().options().use_background_image() && bgrnd_bitmap->valid())
+ container->add_quad(0.0f, 0.0f, 1.0f, 1.0f, ARGB_WHITE, bgrnd_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+
+ hover = item.size() + 1;
+ visible_items = item.size() - 2;
+ float extra_height = 2.0f * line_height;
+ float visible_extra_menu_height = customtop + custombottom + extra_height;
+
+ // locate mouse
+ mouse_hit = false;
+ mouse_button = false;
+ mouse_target = machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button);
+ if (mouse_target != nullptr)
+ if (mouse_target->map_point_container(mouse_target_x, mouse_target_y, *container, mouse_x, mouse_y))
+ mouse_hit = true;
+
+ // account for extra space at the top and bottom
+ float visible_main_menu_height = 1.0f - 2.0f * UI_BOX_TB_BORDER - visible_extra_menu_height;
+ visible_lines = floor(visible_main_menu_height / line_height);
+ visible_main_menu_height = (float)(visible_lines * line_height);
+
+ // compute top/left of inner menu area by centering
+ float visible_top = (1.0f - (visible_main_menu_height + visible_extra_menu_height)) * 0.5f;
+
+ // if the menu is at the bottom of the extra, adjust
+ visible_top += customtop;
+
+ // compute left box size
+ float x1 = visible_left;
+ float y1 = visible_top - UI_BOX_TB_BORDER;
+ float x2 = x1 + visible_width;
+ float y2 = visible_top + visible_main_menu_height + UI_BOX_TB_BORDER + extra_height;
+ float line = visible_top + (float)(visible_lines * line_height);
+
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
+
+ if (visible_items < visible_lines)
+ visible_lines = visible_items;
+ if (top_line < 0)
+ top_line = 0;
+ if (top_line + visible_lines >= visible_items)
+ top_line = visible_items - visible_lines;
+
+ // determine effective positions taking into account the hilighting arrows
+ float effective_width = visible_width - 2.0f * gutter_width;
+ float effective_left = visible_left + gutter_width;
+
+ int n_loop = (visible_items >= visible_lines) ? visible_lines : visible_items;
+
+ for (int linenum = 0; linenum < n_loop; linenum++)
+ {
+ float line_y = visible_top + (float)linenum * line_height;
+ int itemnum = top_line + linenum;
+ const ui_menu_item &pitem = item[itemnum];
+ const char *itemtext = pitem.text;
+ rgb_t fgcolor = UI_TEXT_COLOR;
+ rgb_t bgcolor = UI_TEXT_BG_COLOR;
+ float line_x0 = x1 + 0.5f * UI_LINE_WIDTH;
+ float line_y0 = line_y;
+ float line_x1 = x2 - 0.5f * UI_LINE_WIDTH;
+ float line_y1 = line_y + line_height;
+
+ // if we're on the top line, display the up arrow
+ if (linenum == 0 && top_line != 0)
+ {
+ draw_arrow(container, 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height,
+ 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height, fgcolor, ROT0);
+
+ if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y)
+ {
+ fgcolor = UI_MOUSEOVER_COLOR;
+ bgcolor = UI_MOUSEOVER_BG_COLOR;
+ highlight(container, line_x0, line_y0, line_x1, line_y1, bgcolor);
+ hover = HOVER_ARROW_UP;
+ }
+ }
+ // if we're on the bottom line, display the down arrow
+ else if (linenum == visible_lines - 1 && itemnum != visible_items - 1)
+ {
+ draw_arrow(container, 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height,
+ 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height, fgcolor, ROT0 ^ ORIENTATION_FLIP_Y);
+
+ if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y)
+ {
+ fgcolor = UI_MOUSEOVER_COLOR;
+ bgcolor = UI_MOUSEOVER_BG_COLOR;
+ highlight(container, line_x0, line_y0, line_x1, line_y1, bgcolor);
+ hover = HOVER_ARROW_DOWN;
+ }
+ }
+
+ // draw dats text
+ else if (pitem.subtext == nullptr)
+ {
+ mui.draw_text_full(container, itemtext, effective_left, line_y, effective_width, JUSTIFY_LEFT, WRAP_NEVER,
+ DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr);
+ }
+ }
+
+ for (size_t count = visible_items; count < item.size(); count++)
+ {
+ const ui_menu_item &pitem = item[count];
+ const char *itemtext = pitem.text;
+ float line_x0 = x1 + 0.5f * UI_LINE_WIDTH;
+ float line_y0 = line;
+ float line_x1 = x2 - 0.5f * UI_LINE_WIDTH;
+ float line_y1 = line + line_height;
+ rgb_t fgcolor = UI_SELECTED_COLOR;
+ rgb_t bgcolor = UI_SELECTED_BG_COLOR;
+
+ if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y && pitem.is_selectable())
+ hover = count;
+
+ if (strcmp(itemtext, MENU_SEPARATOR_ITEM) == 0)
+ container->add_line(visible_left, line + 0.5f * line_height, visible_left + visible_width, line + 0.5f * line_height,
+ UI_LINE_WIDTH, UI_TEXT_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ else
+ {
+ highlight(container, line_x0, line_y0, line_x1, line_y1, bgcolor);
+ mui.draw_text_full(container, itemtext, effective_left, line, effective_width, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr);
+ }
+ line += line_height;
+ }
+
+ // if there is something special to add, do it by calling the virtual method
+ custom_render((selected >= 0 && selected < item.size()) ? item[selected].ref : nullptr, customtop, custombottom, x1, y1, x2, y2);
+
+ // return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow
+ visitems = visible_lines - (top_line != 0) - (top_line + visible_lines != visible_items);
+}
+
+void ui_menu::set_pressed()
+{
+ (m_repeat == 0) ? m_repeat = osd_ticks() + osd_ticks_per_second() / 2 : m_repeat = osd_ticks() + osd_ticks_per_second() / 4;
+ m_pressed = true;
+}
diff --git a/src/frontend/mame/ui/menu.h b/src/frontend/mame/ui/menu.h
new file mode 100644
index 00000000000..af2badd3305
--- /dev/null
+++ b/src/frontend/mame/ui/menu.h
@@ -0,0 +1,284 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/***************************************************************************
+
+ ui/menu.h
+
+ Internal MAME menus for the user interface.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_MENU_H__
+#define __UI_MENU_H__
+
+#include "render.h"
+#include "language.h"
+#include "ui/uimain.h"
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+// flags to pass to ui_menu_process
+#define UI_MENU_PROCESS_NOKEYS 1
+#define UI_MENU_PROCESS_LR_REPEAT 2
+#define UI_MENU_PROCESS_CUSTOM_ONLY 4
+#define UI_MENU_PROCESS_ONLYCHAR 8
+#define UI_MENU_PROCESS_NOINPUT 16
+#define UI_MENU_PROCESS_NOIMAGE 32
+
+// options for ui_menu_reset
+enum ui_menu_reset_options
+{
+ UI_MENU_RESET_SELECT_FIRST,
+ UI_MENU_RESET_REMEMBER_POSITION,
+ UI_MENU_RESET_REMEMBER_REF
+};
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+// menu-related events
+struct ui_menu_event
+{
+ void *itemref; // reference for the selected item
+ ui_menu_item_type type; // item type (eventually will go away when itemref is proper ui_menu_item class rather than void*)
+ int iptkey; // one of the IPT_* values from inptport.h
+ unicode_char unichar; // unicode character if iptkey == IPT_SPECIAL
+ render_bounds mouse; // mouse position if iptkey == IPT_CUSTOM
+};
+
+struct ui_menu_pool
+{
+ ui_menu_pool *next; // chain to next one
+ UINT8 *top; // top of the pool
+ UINT8 *end; // end of the pool
+};
+
+
+class ui_menu
+{
+public:
+ ui_menu(running_machine &machine, render_container *container);
+ virtual ~ui_menu();
+
+ running_machine &machine() const { return m_machine; }
+
+ render_container *container; // render_container we render to
+ ui_menu_event menu_event; // the UI menu_event that occurred
+ ui_menu *parent; // pointer to parent menu
+ int resetpos; // reset position
+ void *resetref; // reset reference
+ int selected; // which item is selected
+ int hover; // which item is being hovered over
+ int visitems; // number of visible items
+ float customtop; // amount of extra height to add at the top
+ float custombottom; // amount of extra height to add at the bottom
+ ui_menu_pool *pool; // list of memory pools
+ std::vector<ui_menu_item> item; // array of items
+
+ // free all items in the menu, and all memory allocated from the memory pool
+ void reset(ui_menu_reset_options options);
+
+ // append a new item to the end of the menu
+ void item_append(const char *text, const char *subtext, UINT32 flags, void *ref, ui_menu_item_type type = ui_menu_item_type::UNKNOWN);
+ void item_append(ui_menu_item item);
+ void item_append(ui_menu_item_type type);
+
+ // process a menu, drawing it and returning any interesting events
+ const ui_menu_event *process(UINT32 flags, float x0 = 0.0f, float y0 = 0.0f);
+
+ // configure the menu for custom rendering
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2);
+
+ // allocate temporary memory from the menu's memory pool
+ void *m_pool_alloc(size_t size);
+
+ // make a temporary string copy in the menu's memory pool
+ const char *pool_strdup(const char *string);
+
+ // retrieves the index of the currently selected menu item
+ void *get_selection();
+
+ // changes the index of the currently selected menu item
+ void set_selection(void *selected_itemref);
+
+ // request the specific handling of the game selection main menu
+ bool is_special_main_menu() const;
+ void set_special_main_menu(bool disable);
+
+ // Global initialization
+ static void init(running_machine &machine);
+ static void exit(running_machine &machine);
+
+ // reset the menus, clearing everything
+ static void stack_reset(running_machine &machine);
+
+ // push a new menu onto the stack
+ static void stack_push(ui_menu *menu);
+
+ // pop a menu from the stack
+ static void stack_pop(running_machine &machine);
+
+ // test if one of the menus in the stack requires hide disable
+ static bool stack_has_special_main_menu();
+
+ // highlight
+ static void highlight(render_container *container, float x0, float y0, float x1, float y1, rgb_t bgcolor);
+
+ // draw arrow
+ static void draw_arrow(render_container *container, float x0, float y0, float x1, float y1, rgb_t fgcolor, UINT32 orientation);
+
+ // master handler
+ static UINT32 ui_handler(running_machine &machine, render_container *container, UINT32 state);
+
+ // Used by sliders
+ void validate_selection(int scandir);
+ static ui_menu *menu_stack;
+
+ void do_handle();
+
+ // To be reimplemented in the menu subclass
+ virtual void populate() = 0;
+
+ // To be reimplemented in the menu subclass
+ virtual void handle() = 0;
+
+ // test if search is active
+ virtual bool menu_has_search_active() { return false; }
+
+private:
+ static ui_menu *menu_free;
+ static std::unique_ptr<bitmap_rgb32> hilight_bitmap;
+ static render_texture *hilight_texture, *arrow_texture;
+
+ bool m_special_main_menu;
+ running_machine &m_machine; // machine we are attached to
+
+ void draw(UINT32 flags, float x0 = 0.0f, float y0 = 0.0f);
+ void draw_text_box();
+ void handle_events(UINT32 flags);
+ void handle_keys(UINT32 flags);
+
+ inline bool exclusive_input_pressed(int key, int repeat);
+ static void clear_free_list(running_machine &machine);
+ static void render_triangle(bitmap_argb32 &dest, bitmap_argb32 &source, const rectangle &sbounds, void *param);
+
+public:
+ // tab navigation
+ enum class focused_menu
+ {
+ main,
+ left,
+ righttop,
+ rightbottom
+ };
+
+ focused_menu m_focus;
+ void *m_prev_selected;
+
+ int visible_items;
+ bool ui_error;
+
+ // mouse handling
+ bool mouse_hit, mouse_button;
+ render_target *mouse_target;
+ INT32 mouse_target_x, mouse_target_y;
+ float mouse_x, mouse_y;
+
+ // draw toolbar
+ void draw_toolbar(float x1, float y1, float x2, float y2, bool software = false);
+
+ // draw left panel
+ virtual float draw_left_panel(float x1, float y1, float x2, float y2) { return 0; }
+
+ // draw right panel
+ virtual void draw_right_panel(void *selectedref, float origx1, float origy1, float origx2, float origy2) { };
+
+ // draw star
+ void draw_star(float x0, float y0);
+
+ // Global initialization
+ static void init_ui(running_machine &machine);
+
+ // get arrows status
+ template <typename _T1, typename _T2, typename _T3>
+ UINT32 get_arrow_flags(_T1 min, _T2 max, _T3 actual)
+ {
+ if (max == 0)
+ return 0;
+ else
+ return ((actual <= min) ? MENU_FLAG_RIGHT_ARROW : (actual >= max ? MENU_FLAG_LEFT_ARROW : (MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW)));
+ }
+
+protected:
+ int topline_datsview; // right box top line
+ int top_line; // main box top line
+ int l_sw_hover;
+ int l_hover;
+ int totallines;
+ int skip_main_items;
+
+ // draw right box
+ float draw_right_box_title(float x1, float y1, float x2, float y2);
+
+ // draw arrow
+ void draw_common_arrow(float origx1, float origy1, float origx2, float origy2, int current, int dmin, int dmax, float title);
+ void info_arrow(int ub, float origx1, float origx2, float oy1, float line_height, float text_size, float ud_arrow_width);
+
+ // images render
+ std::string arts_render_common(float origx1, float origy1, float origx2, float origy2);
+ void arts_render_images(bitmap_argb32 *bitmap, float origx1, float origy1, float origx2, float origy2, bool software);
+
+ int visible_lines; // main box visible lines
+ int right_visible_lines; // right box lines
+
+ static std::unique_ptr<bitmap_argb32> snapx_bitmap;
+ static render_texture *snapx_texture;
+
+ static std::unique_ptr<bitmap_rgb32> hilight_main_bitmap;
+ static render_texture *hilight_main_texture;
+private:
+
+ // mouse button held down
+ bool m_pressed = false;
+ osd_ticks_t m_repeat = 0;
+ void reset_pressed() { m_pressed = false; m_repeat = 0; }
+ bool mouse_pressed() { return (osd_ticks() >= m_repeat); }
+ void set_pressed();
+
+ static std::unique_ptr<bitmap_argb32> no_avail_bitmap, bgrnd_bitmap, star_bitmap;
+ static render_texture *bgrnd_texture, *star_texture;
+ static bitmap_argb32 *icons_bitmap[];
+ static render_texture *icons_texture[];
+
+ // toolbar
+ static bitmap_argb32 *toolbar_bitmap[], *sw_toolbar_bitmap[];
+ static render_texture *toolbar_texture[], *sw_toolbar_texture[];
+
+ // draw game list
+ void draw_select_game(UINT32 flags);
+
+ // draw palette menu
+ void draw_palette_menu();
+
+ // draw dats menu
+ void draw_dats_menu();
+
+ void get_title_search(std::string &title, std::string &search);
+
+ // handle keys
+ void handle_main_keys(UINT32 flags);
+
+ // handle mouse
+ void handle_main_events(UINT32 flags);
+
+ void draw_icon(int linenum, void *selectedref, float x1, float y1);
+};
+
+#endif // __UI_MENU_H__
diff --git a/src/frontend/mame/ui/miscmenu.cpp b/src/frontend/mame/ui/miscmenu.cpp
new file mode 100644
index 00000000000..8ec09c4dc17
--- /dev/null
+++ b/src/frontend/mame/ui/miscmenu.cpp
@@ -0,0 +1,983 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods, Maurizio Petrarota
+/*********************************************************************
+
+ ui/miscmenu.cpp
+
+ Internal MAME menus for the user interface.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "mame.h"
+#include "osdnet.h"
+#include "mameopts.h"
+
+#include "uiinput.h"
+#include "ui/ui.h"
+#include "ui/menu.h"
+#include "ui/miscmenu.h"
+#include "ui/utils.h"
+#include "../info.h"
+#include "ui/inifile.h"
+#include "ui/submenu.h"
+
+/***************************************************************************
+ MENU HANDLERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ ui_menu_keyboard_mode - menu that
+-------------------------------------------------*/
+
+ui_menu_keyboard_mode::ui_menu_keyboard_mode(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+void ui_menu_keyboard_mode::populate()
+{
+ bool natural = mame_machine_manager::instance()->ui().use_natural_keyboard();
+ item_append(_("Keyboard Mode:"), natural ? _("Natural") : _("Emulated"), natural ? MENU_FLAG_LEFT_ARROW : MENU_FLAG_RIGHT_ARROW, nullptr);
+}
+
+ui_menu_keyboard_mode::~ui_menu_keyboard_mode()
+{
+}
+
+void ui_menu_keyboard_mode::handle()
+{
+ bool natural = mame_machine_manager::instance()->ui().use_natural_keyboard();
+
+ /* process the menu */
+ const ui_menu_event *menu_event = process(0);
+
+ if (menu_event != nullptr)
+ {
+ if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
+ {
+ mame_machine_manager::instance()->ui().set_use_natural_keyboard(natural ^ true);
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ ui_menu_bios_selection - populates the main
+ bios selection menu
+-------------------------------------------------*/
+
+ui_menu_bios_selection::ui_menu_bios_selection(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+void ui_menu_bios_selection::populate()
+{
+ /* cycle through all devices for this system */
+ for (device_t &device : device_iterator(machine().root_device()))
+ {
+ if (device.rom_region())
+ {
+ const char *val = "default";
+ for (const rom_entry *rom = device.rom_region(); !ROMENTRY_ISEND(rom); rom++)
+ {
+ if (ROMENTRY_ISSYSTEM_BIOS(rom) && ROM_GETBIOSFLAGS(rom) == device.system_bios())
+ {
+ val = ROM_GETHASHDATA(rom);
+ }
+ }
+ item_append(device.owner() == nullptr ? "driver" : device.tag()+1, val, MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW, (void *)&device);
+ }
+ }
+
+ item_append(ui_menu_item_type::SEPARATOR);
+ item_append(_("Reset"), nullptr, 0, (void *)1);
+}
+
+ui_menu_bios_selection::~ui_menu_bios_selection()
+{
+}
+
+/*-------------------------------------------------
+ ui_menu_bios_selection - menu that
+-------------------------------------------------*/
+
+void ui_menu_bios_selection::handle()
+{
+ /* process the menu */
+ const ui_menu_event *menu_event = process(0);
+
+ if (menu_event != nullptr && menu_event->itemref != nullptr)
+ {
+ if ((FPTR)menu_event->itemref == 1 && menu_event->iptkey == IPT_UI_SELECT)
+ machine().schedule_hard_reset();
+ else if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
+ {
+ device_t *dev = (device_t *)menu_event->itemref;
+ int cnt = 0;
+ for (const rom_entry *rom = dev->rom_region(); !ROMENTRY_ISEND(rom); rom++)
+ {
+ if (ROMENTRY_ISSYSTEM_BIOS(rom)) cnt ++;
+ }
+ int val = dev->system_bios() + ((menu_event->iptkey == IPT_UI_LEFT) ? -1 : +1);
+ if (val<1) val=cnt;
+ if (val>cnt) val=1;
+ dev->set_system_bios(val);
+ if (strcmp(dev->tag(),":")==0) {
+ std::string error;
+ machine().options().set_value("bios", val-1, OPTION_PRIORITY_CMDLINE, error);
+ assert(error.empty());
+ } else {
+ std::string error;
+ std::string value = string_format("%s,bios=%d", machine().options().main_value(dev->owner()->tag()+1), val-1);
+ machine().options().set_value(dev->owner()->tag()+1, value.c_str(), OPTION_PRIORITY_CMDLINE, error);
+ assert(error.empty());
+ }
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ }
+ }
+}
+
+
+
+ui_menu_network_devices::ui_menu_network_devices(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+ui_menu_network_devices::~ui_menu_network_devices()
+{
+}
+
+/*-------------------------------------------------
+ menu_network_devices_populate - populates the main
+ network device menu
+-------------------------------------------------*/
+
+void ui_menu_network_devices::populate()
+{
+ /* cycle through all devices for this system */
+ for (device_network_interface &network : network_interface_iterator(machine().root_device()))
+ {
+ int curr = network.get_interface();
+ const char *title = nullptr;
+ const osd_netdev::entry_t *entry = netdev_first();
+ while(entry) {
+ if(entry->id==curr) {
+ title = entry->description;
+ break;
+ }
+ entry = entry->m_next;
+ }
+
+ item_append(network.device().tag(), (title) ? title : "------", MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW, (void *)network);
+ }
+}
+
+/*-------------------------------------------------
+ ui_menu_network_devices - menu that
+-------------------------------------------------*/
+
+void ui_menu_network_devices::handle()
+{
+ /* process the menu */
+ const ui_menu_event *menu_event = process(0);
+
+ if (menu_event != nullptr && menu_event->itemref != nullptr)
+ {
+ if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) {
+ device_network_interface *network = (device_network_interface *)menu_event->itemref;
+ int curr = network->get_interface();
+ if (menu_event->iptkey == IPT_UI_LEFT) curr--; else curr++;
+ if (curr==-2) curr = netdev_count() - 1;
+ network->set_interface(curr);
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ menu_bookkeeping - handle the bookkeeping
+ information menu
+-------------------------------------------------*/
+
+void ui_menu_bookkeeping::handle()
+{
+ attotime curtime;
+
+ /* if the time has rolled over another second, regenerate */
+ curtime = machine().time();
+ if (prevtime.seconds() != curtime.seconds())
+ {
+ reset(UI_MENU_RESET_SELECT_FIRST);
+ prevtime = curtime;
+ populate();
+ }
+
+ /* process the menu */
+ process(0);
+}
+
+
+/*-------------------------------------------------
+ menu_bookkeeping - handle the bookkeeping
+ information menu
+-------------------------------------------------*/
+ui_menu_bookkeeping::ui_menu_bookkeeping(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+ui_menu_bookkeeping::~ui_menu_bookkeeping()
+{
+}
+
+void ui_menu_bookkeeping::populate()
+{
+ int tickets = machine().bookkeeping().get_dispensed_tickets();
+ std::ostringstream tempstring;
+ int ctrnum;
+
+ /* show total time first */
+ if (prevtime.seconds() >= (60 * 60))
+ util::stream_format(tempstring, _("Uptime: %1$d:%2$02d:%3$02d\n\n"), prevtime.seconds() / (60 * 60), (prevtime.seconds() / 60) % 60, prevtime.seconds() % 60);
+ else
+ util::stream_format(tempstring, _("Uptime: %1$d:%2$02d\n\n"), (prevtime.seconds() / 60) % 60, prevtime.seconds() % 60);
+
+ /* show tickets at the top */
+ if (tickets > 0)
+ util::stream_format(tempstring, _("Tickets dispensed: %1$d\n\n"), tickets);
+
+ /* loop over coin counters */
+ for (ctrnum = 0; ctrnum < COIN_COUNTERS; ctrnum++)
+ {
+ int count = machine().bookkeeping().coin_counter_get_count(ctrnum);
+
+ /* display the coin counter number */
+ /* display how many coins */
+ /* display whether or not we are locked out */
+ util::stream_format(tempstring,
+ (count == 0) ? _("Coin %1$c: NA%3$s\n") : _("Coin %1$c: %2$d%3$s\n"),
+ ctrnum + 'A',
+ count,
+ machine().bookkeeping().coin_lockout_get_state(ctrnum) ? _(" (locked)") : "");
+ }
+
+ /* append the single item */
+ item_append(tempstring.str().c_str(), nullptr, MENU_FLAG_MULTILINE, nullptr);
+}
+
+/*-------------------------------------------------
+ menu_crosshair - handle the crosshair settings
+ menu
+-------------------------------------------------*/
+
+void ui_menu_crosshair::handle()
+{
+ /* process the menu */
+ const ui_menu_event *menu_event = process(UI_MENU_PROCESS_LR_REPEAT);
+
+ /* handle events */
+ if (menu_event != nullptr && menu_event->itemref != nullptr)
+ {
+ crosshair_user_settings settings;
+ crosshair_item_data *data = (crosshair_item_data *)menu_event->itemref;
+ bool changed = false;
+ //int set_def = false;
+ int newval = data->cur;
+
+ /* retreive the user settings */
+ machine().crosshair().get_user_settings(data->player, &settings);
+
+ switch (menu_event->iptkey)
+ {
+ /* if selected, reset to default value */
+ case IPT_UI_SELECT:
+ newval = data->defvalue;
+ //set_def = true;
+ break;
+
+ /* left decrements */
+ case IPT_UI_LEFT:
+ newval -= machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1;
+ break;
+
+ /* right increments */
+ case IPT_UI_RIGHT:
+ newval += machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1;
+ break;
+ }
+
+ /* clamp to range */
+ if (newval < data->min)
+ newval = data->min;
+ if (newval > data->max)
+ newval = data->max;
+
+ /* if things changed, update */
+ if (newval != data->cur)
+ {
+ switch (data->type)
+ {
+ /* visibility state */
+ case CROSSHAIR_ITEM_VIS:
+ settings.mode = newval;
+ changed = true;
+ break;
+
+ /* auto time */
+ case CROSSHAIR_ITEM_AUTO_TIME:
+ settings.auto_time = newval;
+ changed = true;
+ break;
+ }
+ }
+
+ /* crosshair graphic name */
+ if (data->type == CROSSHAIR_ITEM_PIC)
+ {
+ switch (menu_event->iptkey)
+ {
+ case IPT_UI_SELECT:
+ /* clear the name string to reset to default crosshair */
+ settings.name[0] = 0;
+ changed = true;
+ break;
+
+ case IPT_UI_LEFT:
+ strcpy(settings.name, data->last_name);
+ changed = true;
+ break;
+
+ case IPT_UI_RIGHT:
+ strcpy(settings.name, data->next_name);
+ changed = true;
+ break;
+ }
+ }
+
+ if (changed)
+ {
+ /* save the user settings */
+ machine().crosshair().set_user_settings(data->player, &settings);
+
+ /* rebuild the menu */
+ reset(UI_MENU_RESET_REMEMBER_POSITION);
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ menu_crosshair_populate - populate the
+ crosshair settings menu
+-------------------------------------------------*/
+
+ui_menu_crosshair::ui_menu_crosshair(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+void ui_menu_crosshair::populate()
+{
+ crosshair_user_settings settings;
+ crosshair_item_data *data;
+ char temp_text[16];
+ int player;
+ UINT8 use_auto = false;
+ UINT32 flags = 0;
+
+ /* loop over player and add the manual items */
+ for (player = 0; player < MAX_PLAYERS; player++)
+ {
+ /* get the user settings */
+ machine().crosshair().get_user_settings(player, &settings);
+
+ /* add menu items for usable crosshairs */
+ if (settings.used)
+ {
+ /* Make sure to keep these matched to the CROSSHAIR_VISIBILITY_xxx types */
+ static const char *const vis_text[] = { "Off", "On", "Auto" };
+
+ /* track if we need the auto time menu */
+ if (settings.mode == CROSSHAIR_VISIBILITY_AUTO) use_auto = true;
+
+ /* CROSSHAIR_ITEM_VIS - allocate a data item and fill it */
+ data = (crosshair_item_data *)m_pool_alloc(sizeof(*data));
+ data->type = CROSSHAIR_ITEM_VIS;
+ data->player = player;
+ data->min = CROSSHAIR_VISIBILITY_OFF;
+ data->max = CROSSHAIR_VISIBILITY_AUTO;
+ data->defvalue = CROSSHAIR_VISIBILITY_DEFAULT;
+ data->cur = settings.mode;
+
+ /* put on arrows */
+ if (data->cur > data->min)
+ flags |= MENU_FLAG_LEFT_ARROW;
+ if (data->cur < data->max)
+ flags |= MENU_FLAG_RIGHT_ARROW;
+
+ /* add CROSSHAIR_ITEM_VIS menu */
+ sprintf(temp_text, "P%d Visibility", player + 1);
+ item_append(temp_text, vis_text[settings.mode], flags, data);
+
+ /* CROSSHAIR_ITEM_PIC - allocate a data item and fill it */
+ data = (crosshair_item_data *)m_pool_alloc(sizeof(*data));
+ data->type = CROSSHAIR_ITEM_PIC;
+ data->player = player;
+ data->last_name[0] = 0;
+ /* other data item not used by this menu */
+
+ /* search for crosshair graphics */
+
+ /* open a path to the crosshairs */
+ file_enumerator path(machine().options().crosshair_path());
+ const osd_directory_entry *dir;
+ /* reset search flags */
+ bool using_default = false;
+ bool finished = false;
+ bool found = false;
+
+ /* if we are using the default, then we just need to find the first in the list */
+ if (*(settings.name) == 0)
+ using_default = true;
+
+ /* look for the current name, then remember the name before */
+ /* and find the next name */
+ while (((dir = path.next()) != nullptr) && !finished)
+ {
+ int length = strlen(dir->name);
+
+ /* look for files ending in .png with a name not larger then 9 chars*/
+ if ((length > 4) && (length <= CROSSHAIR_PIC_NAME_LENGTH + 4) &&
+ dir->name[length - 4] == '.' &&
+ tolower((UINT8)dir->name[length - 3]) == 'p' &&
+ tolower((UINT8)dir->name[length - 2]) == 'n' &&
+ tolower((UINT8)dir->name[length - 1]) == 'g')
+
+ {
+ /* remove .png from length */
+ length -= 4;
+
+ if (found || using_default)
+ {
+ /* get the next name */
+ strncpy(data->next_name, dir->name, length);
+ data->next_name[length] = 0;
+ finished = true;
+ }
+ else if (!strncmp(dir->name, settings.name, length))
+ {
+ /* we found the current name */
+ /* so loop once more to find the next name */
+ found = true;
+ }
+ else
+ /* remember last name */
+ /* we will do it here in case files get added to the directory */
+ {
+ strncpy(data->last_name, dir->name, length);
+ data->last_name[length] = 0;
+ }
+ }
+ }
+ /* if name not found then next item is DEFAULT */
+ if (!found && !using_default)
+ {
+ data->next_name[0] = 0;
+ finished = true;
+ }
+ /* setup the selection flags */
+ flags = 0;
+ if (finished)
+ flags |= MENU_FLAG_RIGHT_ARROW;
+ if (found)
+ flags |= MENU_FLAG_LEFT_ARROW;
+
+ /* add CROSSHAIR_ITEM_PIC menu */
+ sprintf(temp_text, "P%d Crosshair", player + 1);
+ item_append(temp_text, using_default ? "DEFAULT" : settings.name, flags, data);
+ }
+ }
+ if (use_auto)
+ {
+ /* any player can be used to get the autotime */
+ machine().crosshair().get_user_settings(0, &settings);
+
+ /* CROSSHAIR_ITEM_AUTO_TIME - allocate a data item and fill it */
+ data = (crosshair_item_data *)m_pool_alloc(sizeof(*data));
+ data->type = CROSSHAIR_ITEM_AUTO_TIME;
+ data->min = CROSSHAIR_VISIBILITY_AUTOTIME_MIN;
+ data->max = CROSSHAIR_VISIBILITY_AUTOTIME_MAX;
+ data->defvalue = CROSSHAIR_VISIBILITY_AUTOTIME_DEFAULT;
+ data->cur = settings.auto_time;
+
+ /* put on arrows in visible menu */
+ if (data->cur > data->min)
+ flags |= MENU_FLAG_LEFT_ARROW;
+ if (data->cur < data->max)
+ flags |= MENU_FLAG_RIGHT_ARROW;
+
+ /* add CROSSHAIR_ITEM_AUTO_TIME menu */
+ sprintf(temp_text, "%d", settings.auto_time);
+ item_append(_("Visible Delay"), temp_text, flags, data);
+ }
+// else
+// /* leave a blank filler line when not in auto time so size does not rescale */
+// item_append("", "", NULL, NULL);
+}
+
+ui_menu_crosshair::~ui_menu_crosshair()
+{
+}
+
+/*-------------------------------------------------
+ menu_quit_game - handle the "menu" for
+ quitting the game
+-------------------------------------------------*/
+
+ui_menu_quit_game::ui_menu_quit_game(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+ui_menu_quit_game::~ui_menu_quit_game()
+{
+}
+
+void ui_menu_quit_game::populate()
+{
+}
+
+void ui_menu_quit_game::handle()
+{
+ /* request a reset */
+ machine().schedule_exit();
+
+ /* reset the menu stack */
+ ui_menu::stack_reset(machine());
+}
+
+//-------------------------------------------------
+// ctor / dtor
+//-------------------------------------------------
+
+ui_menu_export::ui_menu_export(running_machine &machine, render_container *container, std::vector<const game_driver *> drvlist)
+ : ui_menu(machine, container), m_list(drvlist)
+{
+}
+
+ui_menu_export::~ui_menu_export()
+{
+}
+
+//-------------------------------------------------
+// handlethe options menu
+//-------------------------------------------------
+
+void ui_menu_export::handle()
+{
+ // process the menu
+ ui_menu::menu_stack->parent->process(UI_MENU_PROCESS_NOINPUT);
+ const ui_menu_event *m_event = process(UI_MENU_PROCESS_NOIMAGE);
+ if (m_event != nullptr && m_event->itemref != nullptr)
+ {
+ switch ((FPTR)m_event->itemref)
+ {
+ case 1:
+ case 3:
+ {
+ if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ std::string filename("exported");
+ emu_file infile(mame_machine_manager::instance()->ui().options().ui_path(), OPEN_FLAG_READ);
+ if (infile.open(filename.c_str(), ".xml") == osd_file::error::NONE)
+ for (int seq = 0; ; ++seq)
+ {
+ std::string seqtext = string_format("%s_%04d", filename, seq);
+ if (infile.open(seqtext.c_str(), ".xml") != osd_file::error::NONE)
+ {
+ filename = seqtext;
+ break;
+ }
+ }
+
+ // attempt to open the output file
+ emu_file file(mame_machine_manager::instance()->ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ if (file.open(filename.c_str(), ".xml") == osd_file::error::NONE)
+ {
+ FILE *pfile;
+ std::string fullpath(file.fullpath());
+ file.close();
+ pfile = fopen(fullpath.c_str(), "w");
+
+ // create the XML and save to file
+ driver_enumerator drvlist(machine().options());
+ drvlist.exclude_all();
+ for (auto & elem : m_list)
+ drvlist.include(driver_list::find(*elem));
+
+ info_xml_creator creator(drvlist);
+ creator.output(pfile, ((FPTR)m_event->itemref == 1) ? false : true);
+ fclose(pfile);
+ machine().popmessage(_("%s.xml saved under ui folder."), filename.c_str());
+ }
+ }
+ break;
+ }
+ case 2:
+ {
+ if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ std::string filename("exported");
+ emu_file infile(mame_machine_manager::instance()->ui().options().ui_path(), OPEN_FLAG_READ);
+ if (infile.open(filename.c_str(), ".txt") == osd_file::error::NONE)
+ for (int seq = 0; ; ++seq)
+ {
+ std::string seqtext = string_format("%s_%04d", filename, seq);
+ if (infile.open(seqtext.c_str(), ".txt") != osd_file::error::NONE)
+ {
+ filename = seqtext;
+ break;
+ }
+ }
+
+ // attempt to open the output file
+ emu_file file(mame_machine_manager::instance()->ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ if (file.open(filename.c_str(), ".txt") == osd_file::error::NONE)
+ {
+ // print the header
+ std::ostringstream buffer;
+ buffer << _("Name: Description:\n");
+ driver_enumerator drvlist(machine().options());
+ drvlist.exclude_all();
+ for (auto & elem : m_list)
+ drvlist.include(driver_list::find(*elem));
+
+ // iterate through drivers and output the info
+ while (drvlist.next())
+ if ((drvlist.driver().flags & MACHINE_NO_STANDALONE) == 0)
+ util::stream_format(buffer, "%-18s\"%s\"\n", drvlist.driver().name, drvlist.driver().description);
+ file.puts(buffer.str().c_str());
+ file.close();
+ machine().popmessage(_("%s.txt saved under ui folder."), filename.c_str());
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_export::populate()
+{
+ // add options items
+ item_append(_("Export list in XML format (like -listxml)"), nullptr, 0, (void *)(FPTR)1);
+ item_append(_("Export list in XML format (like -listxml, but exclude devices)"), nullptr, 0, (void *)(FPTR)3);
+ item_append(_("Export list in TXT format (like -listfull)"), nullptr, 0, (void *)(FPTR)2);
+ item_append(ui_menu_item_type::SEPARATOR);
+}
+
+//-------------------------------------------------
+// ctor / dtor
+//-------------------------------------------------
+
+ui_menu_machine_configure::ui_menu_machine_configure(running_machine &machine, render_container *container, const game_driver *prev, float _x0, float _y0)
+ : ui_menu(machine, container)
+ , m_drv(prev)
+ , m_opts(machine.options())
+ , x0(_x0)
+ , y0(_y0)
+ , m_curbios(0)
+{
+ // parse the INI file
+ std::string error;
+ mame_options::parse_standard_inis(m_opts,error, m_drv);
+ setup_bios();
+}
+
+ui_menu_machine_configure::~ui_menu_machine_configure()
+{
+}
+
+//-------------------------------------------------
+// handlethe options menu
+//-------------------------------------------------
+
+void ui_menu_machine_configure::handle()
+{
+ // process the menu
+ ui_menu::menu_stack->parent->process(UI_MENU_PROCESS_NOINPUT);
+ const ui_menu_event *m_event = process(UI_MENU_PROCESS_NOIMAGE, x0, y0);
+ if (m_event != nullptr && m_event->itemref != nullptr)
+ {
+ if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ switch ((FPTR)m_event->itemref)
+ {
+ case SAVE:
+ {
+ std::string filename(m_drv->name);
+ emu_file file(machine().options().ini_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE);
+ osd_file::error filerr = file.open(filename.c_str(), ".ini");
+ if (filerr == osd_file::error::NONE)
+ {
+ std::string inistring = m_opts.output_ini();
+ file.puts(inistring.c_str());
+ mame_machine_manager::instance()->ui().popup_time(2, "%s", _("\n Configuration saved \n\n"));
+ }
+ break;
+ }
+ case ADDFAV:
+ mame_machine_manager::instance()->favorite().add_favorite_game(m_drv);
+ reset(UI_MENU_RESET_REMEMBER_POSITION);
+ break;
+
+ case DELFAV:
+ mame_machine_manager::instance()->favorite().remove_favorite_game();
+ reset(UI_MENU_RESET_REMEMBER_POSITION);
+ break;
+ case CONTROLLER:
+ if (m_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(global_alloc_clear<ui_submenu>(machine(), container, control_submenu_options, m_drv, &m_opts));
+ break;
+ case VIDEO:
+ if (m_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(global_alloc_clear<ui_submenu>(machine(), container, video_submenu_options, m_drv, &m_opts));
+ break;
+ case ADVANCED:
+ if (m_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(global_alloc_clear<ui_submenu>(machine(), container, advanced_submenu_options, m_drv, &m_opts));
+ break;
+ default:
+ break;
+ }
+ }
+ else if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT)
+ {
+ (m_event->iptkey == IPT_UI_LEFT) ? --m_curbios : ++m_curbios;
+ std::string error;
+ m_opts.set_value(OPTION_BIOS, m_bios[m_curbios].second, OPTION_PRIORITY_CMDLINE, error);
+ m_opts.mark_changed(OPTION_BIOS);
+ reset(UI_MENU_RESET_REMEMBER_POSITION);
+ }
+ }
+}
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_machine_configure::populate()
+{
+ // add options items
+ item_append(_("Bios"), nullptr, MENU_FLAG_DISABLE | MENU_FLAG_UI_HEADING, nullptr);
+ if (!m_bios.empty())
+ {
+ UINT32 arrows = get_arrow_flags(0, m_bios.size() - 1, m_curbios);
+ item_append(_("Driver"), m_bios[m_curbios].first.c_str(), arrows, (void *)(FPTR)BIOS);
+ }
+ else
+ item_append(_("This machine has no bios."), nullptr, MENU_FLAG_DISABLE, nullptr);
+
+ item_append(ui_menu_item_type::SEPARATOR);
+ item_append(_(advanced_submenu_options[0].description), nullptr, 0, (void *)(FPTR)ADVANCED);
+ item_append(_(video_submenu_options[0].description), nullptr, 0, (void *)(FPTR)VIDEO);
+ item_append(_(control_submenu_options[0].description), nullptr, 0, (void *)(FPTR)CONTROLLER);
+ item_append(ui_menu_item_type::SEPARATOR);
+
+ if (!mame_machine_manager::instance()->favorite().isgame_favorite(m_drv))
+ item_append(_("Add To Favorites"), nullptr, 0, (void *)ADDFAV);
+ else
+ item_append(_("Remove From Favorites"), nullptr, 0, (void *)DELFAV);
+
+ item_append(ui_menu_item_type::SEPARATOR);
+ item_append(_("Save machine configuration"), nullptr, 0, (void *)(FPTR)SAVE);
+ item_append(ui_menu_item_type::SEPARATOR);
+ customtop = 2.0f * mame_machine_manager::instance()->ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER;
+}
+
+//-------------------------------------------------
+// perform our special rendering
+//-------------------------------------------------
+
+void ui_menu_machine_configure::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ float width;
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+ std::string text[2];
+ float maxwidth = origx2 - origx1;
+
+ text[0] = _("Configure machine:");
+ text[1] = m_drv->description;
+
+ for (auto & elem : text)
+ {
+ mui.draw_text_full(container, elem.c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += 2 * UI_BOX_LR_BORDER;
+ maxwidth = MAX(maxwidth, width);
+ }
+
+ // compute our bounds
+ float x1 = 0.5f - 0.5f * maxwidth;
+// float x1 = origx1;
+ float x2 = x1 + maxwidth;
+ float y1 = origy1 - top;
+ float y2 = origy1 - UI_BOX_TB_BORDER;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ for (auto & elem : text)
+ {
+ mui.draw_text_full(container, elem.c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+ y1 += mui.get_line_height();
+ }
+}
+
+void ui_menu_machine_configure::setup_bios()
+{
+ if (m_drv->rom == nullptr)
+ return;
+
+ std::string specbios(m_opts.bios());
+ std::string default_name;
+ for (const rom_entry *rom = m_drv->rom; !ROMENTRY_ISEND(rom); ++rom)
+ if (ROMENTRY_ISDEFAULT_BIOS(rom))
+ default_name = ROM_GETNAME(rom);
+
+ int bios_count = 0;
+ for (const rom_entry *rom = m_drv->rom; !ROMENTRY_ISEND(rom); ++rom)
+ {
+ if (ROMENTRY_ISSYSTEM_BIOS(rom))
+ {
+ std::string name(ROM_GETHASHDATA(rom));
+ std::string biosname(ROM_GETNAME(rom));
+ int bios_flags = ROM_GETBIOSFLAGS(rom);
+ std::string bios_number = std::to_string(bios_flags - 1);
+
+ // check biosnumber and name
+ if (bios_number == specbios || biosname == specbios)
+ m_curbios = bios_count;
+
+ if (biosname == default_name)
+ {
+ name.append(_(" (default)"));
+ if (specbios == "default")
+ m_curbios = bios_count;
+ }
+
+ m_bios.emplace_back(name, bios_flags - 1);
+ bios_count++;
+ }
+ }
+
+}
+
+//-------------------------------------------------
+// ctor / dtor
+//-------------------------------------------------
+
+ui_menu_plugins_configure::ui_menu_plugins_configure(running_machine &machine, render_container *container)
+ : ui_menu(machine, container)
+{
+}
+
+ui_menu_plugins_configure::~ui_menu_plugins_configure()
+{
+ emu_file file_plugin(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ if (file_plugin.open("plugin.ini") != osd_file::error::NONE)
+ throw emu_fatalerror("Unable to create file plugin.ini\n");
+ // generate the updated INI
+ file_plugin.puts(mame_machine_manager::instance()->plugins().output_ini().c_str());
+}
+
+//-------------------------------------------------
+// handlethe options menu
+//-------------------------------------------------
+
+void ui_menu_plugins_configure::handle()
+{
+ // process the menu
+ bool changed = false;
+ plugin_options& plugins = mame_machine_manager::instance()->plugins();
+ ui_menu::menu_stack->parent->process(UI_MENU_PROCESS_NOINPUT);
+ const ui_menu_event *m_event = process(UI_MENU_PROCESS_NOIMAGE);
+ if (m_event != nullptr && m_event->itemref != nullptr)
+ {
+ if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT || m_event->iptkey == IPT_UI_SELECT)
+ {
+ int oldval = plugins.int_value((const char*)m_event->itemref);
+ std::string error_string;
+ plugins.set_value((const char*)m_event->itemref, oldval == 1 ? 0 : 1, OPTION_PRIORITY_CMDLINE, error_string);
+ changed = true;
+ }
+ }
+ if (changed)
+ reset(UI_MENU_RESET_REMEMBER_REF);
+}
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_plugins_configure::populate()
+{
+ plugin_options& plugins = mame_machine_manager::instance()->plugins();
+
+ for (auto &curentry : plugins)
+ {
+ if (!curentry.is_header())
+ {
+ auto enabled = std::string(curentry.value()) == "1";
+ item_append(curentry.description(), enabled ? _("On") : _("Off"),
+ enabled ? MENU_FLAG_RIGHT_ARROW : MENU_FLAG_LEFT_ARROW, (void *)(FPTR)curentry.name());
+ }
+ }
+ item_append(ui_menu_item_type::SEPARATOR);
+ customtop = mame_machine_manager::instance()->ui().get_line_height() + (3.0f * UI_BOX_TB_BORDER);
+}
+
+//-------------------------------------------------
+// perform our special rendering
+//-------------------------------------------------
+
+void ui_menu_plugins_configure::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ float width;
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+
+ mui.draw_text_full(container, _("Plugins"), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += 2 * UI_BOX_LR_BORDER;
+ float maxwidth = MAX(origx2 - origx1, width);
+
+ // compute our bounds
+ float x1 = 0.5f - 0.5f * maxwidth;
+ float x2 = x1 + maxwidth;
+ float y1 = origy1 - top;
+ float y2 = origy1 - UI_BOX_TB_BORDER;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ mui.draw_text_full(container, _("Plugins"), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+}
diff --git a/src/frontend/mame/ui/miscmenu.h b/src/frontend/mame/ui/miscmenu.h
new file mode 100644
index 00000000000..18f22c49d54
--- /dev/null
+++ b/src/frontend/mame/ui/miscmenu.h
@@ -0,0 +1,154 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods, Maurizio Petrarota
+/***************************************************************************
+
+ ui/miscmenu.h
+
+ Internal MAME menus for the user interface.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_MISCMENU_H__
+#define __UI_MISCMENU_H__
+
+#include "crsshair.h"
+#include "emuopts.h"
+
+using s_bios = std::vector<std::pair<std::string, int>>;
+
+class ui_menu_keyboard_mode : public ui_menu {
+public:
+ ui_menu_keyboard_mode(running_machine &machine, render_container *container);
+ virtual ~ui_menu_keyboard_mode();
+ virtual void populate() override;
+ virtual void handle() override;
+};
+
+class ui_menu_network_devices : public ui_menu {
+public:
+ ui_menu_network_devices(running_machine &machine, render_container *container);
+ virtual ~ui_menu_network_devices();
+ virtual void populate() override;
+ virtual void handle() override;
+};
+
+class ui_menu_bookkeeping : public ui_menu {
+public:
+ ui_menu_bookkeeping(running_machine &machine, render_container *container);
+ virtual ~ui_menu_bookkeeping();
+ virtual void populate() override;
+ virtual void handle() override;
+
+private:
+ attotime prevtime;
+};
+
+class ui_menu_crosshair : public ui_menu {
+public:
+ ui_menu_crosshair(running_machine &machine, render_container *container);
+ virtual ~ui_menu_crosshair();
+ virtual void populate() override;
+ virtual void handle() override;
+
+private:
+ enum {
+ CROSSHAIR_ITEM_VIS = 0,
+ CROSSHAIR_ITEM_PIC,
+ CROSSHAIR_ITEM_AUTO_TIME
+ };
+
+ /* internal crosshair menu item data */
+ struct crosshair_item_data {
+ UINT8 type;
+ UINT8 player;
+ UINT8 min, max;
+ UINT8 cur;
+ UINT8 defvalue;
+ char last_name[CROSSHAIR_PIC_NAME_LENGTH + 1];
+ char next_name[CROSSHAIR_PIC_NAME_LENGTH + 1];
+ };
+};
+
+class ui_menu_quit_game : public ui_menu {
+public:
+ ui_menu_quit_game(running_machine &machine, render_container *container);
+ virtual ~ui_menu_quit_game();
+ virtual void populate() override;
+ virtual void handle() override;
+};
+
+class ui_menu_bios_selection : public ui_menu {
+public:
+ ui_menu_bios_selection(running_machine &machine, render_container *container);
+ virtual ~ui_menu_bios_selection();
+ virtual void populate() override;
+ virtual void handle() override;
+};
+
+
+//-------------------------------------------------
+// export menu
+//-------------------------------------------------
+
+class ui_menu_export : public ui_menu
+{
+public:
+ ui_menu_export(running_machine &machine, render_container *container, std::vector<const game_driver*> list);
+ virtual ~ui_menu_export();
+ virtual void populate() override;
+ virtual void handle() override;
+
+private:
+ std::vector<const game_driver*> m_list;
+};
+
+//-------------------------------------------------
+// machine configure menu
+//-------------------------------------------------
+
+class ui_menu_machine_configure : public ui_menu
+{
+public:
+ ui_menu_machine_configure(running_machine &machine, render_container *container, const game_driver *prev, float x0 = 0.0f, float y0 = 0.0f);
+ virtual ~ui_menu_machine_configure();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+private:
+ enum
+ {
+ ADDFAV = 1,
+ DELFAV,
+ SAVE,
+ CONTROLLER,
+ VIDEO,
+ BIOS,
+ ADVANCED,
+ LAST = ADVANCED
+ };
+ const game_driver *m_drv;
+ emu_options m_opts;
+ float x0, y0;
+ s_bios m_bios;
+ int m_curbios;
+ void setup_bios();
+};
+
+//-------------------------------------------------
+// plugins configure menu
+//-------------------------------------------------
+
+class ui_menu_plugins_configure : public ui_menu
+{
+public:
+ ui_menu_plugins_configure(running_machine &machine, render_container *container);
+ virtual ~ui_menu_plugins_configure();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+};
+
+#endif /* __UI_MISCMENU_H__ */
diff --git a/src/frontend/mame/ui/moptions.cpp b/src/frontend/mame/ui/moptions.cpp
new file mode 100644
index 00000000000..3c8d37fec12
--- /dev/null
+++ b/src/frontend/mame/ui/moptions.cpp
@@ -0,0 +1,90 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/***************************************************************************
+
+ ui/moptions.cpp
+
+ UI main options manager.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "options.h"
+#include "ui/moptions.h"
+
+
+//**************************************************************************
+// UI EXTRA OPTIONS
+//**************************************************************************
+
+const options_entry ui_options::s_option_entries[] =
+{
+ // seach path options
+ { nullptr, nullptr, OPTION_HEADER, "UI SEARCH PATH OPTIONS" },
+ { OPTION_HISTORY_PATH, "history;dats;.", OPTION_STRING, "path to history files" },
+ { OPTION_EXTRAINI_PATH, "folders", OPTION_STRING, "path to extra ini files" },
+ { OPTION_CABINETS_PATH, "cabinets;cabdevs", OPTION_STRING, "path to cabinets / devices image" },
+ { OPTION_CPANELS_PATH, "cpanel", OPTION_STRING, "path to control panel image" },
+ { OPTION_PCBS_PATH, "pcb", OPTION_STRING, "path to pcbs image" },
+ { OPTION_FLYERS_PATH, "flyers", OPTION_STRING, "path to flyers image" },
+ { OPTION_TITLES_PATH, "titles", OPTION_STRING, "path to titles image" },
+ { OPTION_ENDS_PATH, "ends", OPTION_STRING, "path to ends image" },
+ { OPTION_MARQUEES_PATH, "marquees", OPTION_STRING, "path to marquees image" },
+ { OPTION_ARTPREV_PATH, "artwork preview;artpreview", OPTION_STRING, "path to artwork preview image" },
+ { OPTION_BOSSES_PATH, "bosses", OPTION_STRING, "path to bosses image" },
+ { OPTION_LOGOS_PATH, "logo", OPTION_STRING, "path to logos image" },
+ { OPTION_SCORES_PATH, "scores", OPTION_STRING, "path to scores image" },
+ { OPTION_VERSUS_PATH, "versus", OPTION_STRING, "path to versus image" },
+ { OPTION_GAMEOVER_PATH, "gameover", OPTION_STRING, "path to gameover image" },
+ { OPTION_HOWTO_PATH, "howto", OPTION_STRING, "path to howto image" },
+ { OPTION_SELECT_PATH, "select", OPTION_STRING, "path to select image" },
+ { OPTION_ICONS_PATH, "icons", OPTION_STRING, "path to ICOns image" },
+ { OPTION_COVER_PATH, "covers", OPTION_STRING, "path to software cover image" },
+ { OPTION_UI_PATH, "ui", OPTION_STRING, "path to UI files" },
+
+ // misc options
+ { nullptr, nullptr, OPTION_HEADER, "UI MISC OPTIONS" },
+ { OPTION_DATS_ENABLED, "1", OPTION_BOOLEAN, "enable DATs support" },
+ { OPTION_REMEMBER_LAST, "1", OPTION_BOOLEAN, "reselect in main menu last played game" },
+ { OPTION_ENLARGE_SNAPS, "1", OPTION_BOOLEAN, "enlarge arts (snapshot, title, etc...) in right panel (keeping aspect ratio)" },
+ { OPTION_FORCED4X3, "1", OPTION_BOOLEAN, "force the appearance of the snapshot in the list software to 4:3" },
+ { OPTION_USE_BACKGROUND, "1", OPTION_BOOLEAN, "enable background image in main view" },
+ { OPTION_SKIP_BIOS_MENU, "0", OPTION_BOOLEAN, "skip bios submenu, start with configured or default" },
+ { OPTION_SKIP_PARTS_MENU, "0", OPTION_BOOLEAN, "skip parts submenu, start with first part" },
+ { OPTION_LAST_USED_FILTER, "", OPTION_STRING, "latest used filter" },
+ { OPTION_LAST_USED_MACHINE, "", OPTION_STRING, "latest used machine" },
+ { OPTION_INFO_AUTO_AUDIT, "0", OPTION_BOOLEAN, "enable auto audit in the general info panel" },
+
+ // UI options
+ { nullptr, nullptr, OPTION_HEADER, "UI OPTIONS" },
+ { OPTION_INFOS_SIZE "(0.05-1.00)", "0.75", OPTION_FLOAT, "UI right panel infos text size (0.05 - 1.00)" },
+ { OPTION_FONT_ROWS "(25-40)", "30", OPTION_INTEGER, "UI font text size (25 - 40)" },
+ { OPTION_HIDE_PANELS "(0-3)", "0", OPTION_INTEGER, "UI hide left/right panel in main view (0 = Show all, 1 = hide left, 2 = hide right, 3 = hide both" },
+ { OPTION_UI_BORDER_COLOR, "ffffffff", OPTION_STRING, "UI border color (ARGB)" },
+ { OPTION_UI_BACKGROUND_COLOR, "ef101030", OPTION_STRING, "UI background color (ARGB)" },
+ { OPTION_UI_CLONE_COLOR, "ff808080", OPTION_STRING, "UI clone color (ARGB)" },
+ { OPTION_UI_DIPSW_COLOR, "ffffff00", OPTION_STRING, "UI dipswitch color (ARGB)" },
+ { OPTION_UI_GFXVIEWER_BG_COLOR, "ef101030", OPTION_STRING, "UI gfx viewer color (ARGB)" },
+ { OPTION_UI_MOUSEDOWN_BG_COLOR, "b0606000", OPTION_STRING, "UI mouse down bg color (ARGB)" },
+ { OPTION_UI_MOUSEDOWN_COLOR, "ffffff80", OPTION_STRING, "UI mouse down color (ARGB)" },
+ { OPTION_UI_MOUSEOVER_BG_COLOR, "70404000", OPTION_STRING, "UI mouse over bg color (ARGB)" },
+ { OPTION_UI_MOUSEOVER_COLOR, "ffffff80", OPTION_STRING, "UI mouse over color (ARGB)" },
+ { OPTION_UI_SELECTED_BG_COLOR, "ef808000", OPTION_STRING, "UI selected bg color (ARGB)" },
+ { OPTION_UI_SELECTED_COLOR, "ffffff00", OPTION_STRING, "UI selected color (ARGB)" },
+ { OPTION_UI_SLIDER_COLOR, "ffffffff", OPTION_STRING, "UI slider color (ARGB)" },
+ { OPTION_UI_SUBITEM_COLOR, "ffffffff", OPTION_STRING, "UI subitem color (ARGB)" },
+ { OPTION_UI_TEXT_BG_COLOR, "ef000000", OPTION_STRING, "UI text bg color (ARGB)" },
+ { OPTION_UI_TEXT_COLOR, "ffffffff", OPTION_STRING, "UI text color (ARGB)" },
+ { OPTION_UI_UNAVAILABLE_COLOR, "ff404040", OPTION_STRING, "UI unavailable color (ARGB)" },
+ { nullptr }
+};
+
+//-------------------------------------------------
+// ui_options - constructor
+//-------------------------------------------------
+
+ui_options::ui_options()
+: core_options()
+{
+ add_entries(ui_options::s_option_entries);
+}
diff --git a/src/frontend/mame/ui/moptions.h b/src/frontend/mame/ui/moptions.h
new file mode 100644
index 00000000000..55d800651f4
--- /dev/null
+++ b/src/frontend/mame/ui/moptions.h
@@ -0,0 +1,139 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/***************************************************************************
+
+ ui/moptions.h
+
+ UI main options manager.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_OPTS_H__
+#define __UI_OPTS_H__
+
+#include "options.h"
+
+// core directory options
+#define OPTION_HISTORY_PATH "historypath"
+#define OPTION_EXTRAINI_PATH "extrainipath"
+#define OPTION_CABINETS_PATH "cabinets_directory"
+#define OPTION_CPANELS_PATH "cpanels_directory"
+#define OPTION_PCBS_PATH "pcbs_directory"
+#define OPTION_FLYERS_PATH "flyers_directory"
+#define OPTION_TITLES_PATH "titles_directory"
+#define OPTION_ENDS_PATH "ends_directory"
+#define OPTION_MARQUEES_PATH "marquees_directory"
+#define OPTION_ARTPREV_PATH "artwork_preview_directory"
+#define OPTION_BOSSES_PATH "bosses_directory"
+#define OPTION_LOGOS_PATH "logos_directory"
+#define OPTION_SCORES_PATH "scores_directory"
+#define OPTION_VERSUS_PATH "versus_directory"
+#define OPTION_GAMEOVER_PATH "gameover_directory"
+#define OPTION_HOWTO_PATH "howto_directory"
+#define OPTION_SELECT_PATH "select_directory"
+#define OPTION_ICONS_PATH "icons_directory"
+#define OPTION_COVER_PATH "covers_directory"
+#define OPTION_UI_PATH "ui_path"
+
+// core misc options
+#define OPTION_DATS_ENABLED "dats_enabled"
+#define OPTION_REMEMBER_LAST "remember_last"
+#define OPTION_ENLARGE_SNAPS "enlarge_snaps"
+#define OPTION_FORCED4X3 "forced4x3"
+#define OPTION_USE_BACKGROUND "use_background"
+#define OPTION_SKIP_BIOS_MENU "skip_biosmenu"
+#define OPTION_SKIP_PARTS_MENU "skip_partsmenu"
+#define OPTION_LAST_USED_FILTER "last_used_filter"
+#define OPTION_LAST_USED_MACHINE "last_used_machine"
+#define OPTION_INFO_AUTO_AUDIT "info_audit_enabled"
+
+// core UI options
+#define OPTION_INFOS_SIZE "infos_text_size"
+#define OPTION_FONT_ROWS "font_rows"
+#define OPTION_HIDE_PANELS "hide_main_panel"
+
+#define OPTION_UI_BORDER_COLOR "ui_border_color"
+#define OPTION_UI_BACKGROUND_COLOR "ui_bg_color"
+#define OPTION_UI_GFXVIEWER_BG_COLOR "ui_gfxviewer_color"
+#define OPTION_UI_UNAVAILABLE_COLOR "ui_unavail_color"
+#define OPTION_UI_TEXT_COLOR "ui_text_color"
+#define OPTION_UI_TEXT_BG_COLOR "ui_text_bg_color"
+#define OPTION_UI_SUBITEM_COLOR "ui_subitem_color"
+#define OPTION_UI_CLONE_COLOR "ui_clone_color"
+#define OPTION_UI_SELECTED_COLOR "ui_selected_color"
+#define OPTION_UI_SELECTED_BG_COLOR "ui_selected_bg_color"
+#define OPTION_UI_MOUSEOVER_COLOR "ui_mouseover_color"
+#define OPTION_UI_MOUSEOVER_BG_COLOR "ui_mouseover_bg_color"
+#define OPTION_UI_MOUSEDOWN_COLOR "ui_mousedown_color"
+#define OPTION_UI_MOUSEDOWN_BG_COLOR "ui_mousedown_bg_color"
+#define OPTION_UI_DIPSW_COLOR "ui_dipsw_color"
+#define OPTION_UI_SLIDER_COLOR "ui_slider_color"
+
+class ui_options : public core_options
+{
+public:
+ // construction/destruction
+ ui_options();
+
+ // Search path options
+ const char *history_path() const { return value(OPTION_HISTORY_PATH); }
+ const char *extraini_path() const { return value(OPTION_EXTRAINI_PATH); }
+ const char *cabinets_directory() const { return value(OPTION_CABINETS_PATH); }
+ const char *cpanels_directory() const { return value(OPTION_CPANELS_PATH); }
+ const char *pcbs_directory() const { return value(OPTION_PCBS_PATH); }
+ const char *flyers_directory() const { return value(OPTION_FLYERS_PATH); }
+ const char *titles_directory() const { return value(OPTION_TITLES_PATH); }
+ const char *ends_directory() const { return value(OPTION_ENDS_PATH); }
+ const char *marquees_directory() const { return value(OPTION_MARQUEES_PATH); }
+ const char *artprev_directory() const { return value(OPTION_ARTPREV_PATH); }
+ const char *bosses_directory() const { return value(OPTION_BOSSES_PATH); }
+ const char *logos_directory() const { return value(OPTION_LOGOS_PATH); }
+ const char *scores_directory() const { return value(OPTION_SCORES_PATH); }
+ const char *versus_directory() const { return value(OPTION_VERSUS_PATH); }
+ const char *gameover_directory() const { return value(OPTION_GAMEOVER_PATH); }
+ const char *howto_directory() const { return value(OPTION_HOWTO_PATH); }
+ const char *select_directory() const { return value(OPTION_SELECT_PATH); }
+ const char *icons_directory() const { return value(OPTION_ICONS_PATH); }
+ const char *covers_directory() const { return value(OPTION_COVER_PATH); }
+ const char *ui_path() const { return value(OPTION_UI_PATH); }
+
+ // Misc options
+ bool enabled_dats() const { return bool_value(OPTION_DATS_ENABLED); }
+ bool remember_last() const { return bool_value(OPTION_REMEMBER_LAST); }
+ bool enlarge_snaps() const { return bool_value(OPTION_ENLARGE_SNAPS); }
+ bool forced_4x3_snapshot() const { return bool_value(OPTION_FORCED4X3); }
+ bool use_background_image() const { return bool_value(OPTION_USE_BACKGROUND); }
+ bool skip_bios_menu() const { return bool_value(OPTION_SKIP_BIOS_MENU); }
+ bool skip_parts_menu() const { return bool_value(OPTION_SKIP_PARTS_MENU); }
+ const char *last_used_machine() const { return value(OPTION_LAST_USED_MACHINE); }
+ const char *last_used_filter() const { return value(OPTION_LAST_USED_FILTER); }
+ bool info_audit() const { return bool_value(OPTION_INFO_AUTO_AUDIT); }
+
+ // UI options
+ float infos_size() const { return float_value(OPTION_INFOS_SIZE); }
+ int font_rows() const { return int_value(OPTION_FONT_ROWS); }
+ int hide_panels() const { return int_value(OPTION_HIDE_PANELS); }
+
+ const char *ui_border_color() const { return value(OPTION_UI_BORDER_COLOR); }
+ const char *ui_bg_color() const { return value(OPTION_UI_BACKGROUND_COLOR); }
+ const char *ui_gfx_bg_color() const { return value(OPTION_UI_GFXVIEWER_BG_COLOR); }
+ const char *ui_unavail_color() const { return value(OPTION_UI_UNAVAILABLE_COLOR); }
+ const char *ui_text_color() const { return value(OPTION_UI_TEXT_COLOR); }
+ const char *ui_text_bg_color() const { return value(OPTION_UI_TEXT_BG_COLOR); }
+ const char *ui_subitem_color() const { return value(OPTION_UI_SUBITEM_COLOR); }
+ const char *ui_clone_color() const { return value(OPTION_UI_CLONE_COLOR); }
+ const char *ui_selected_color() const { return value(OPTION_UI_SELECTED_COLOR); }
+ const char *ui_selected_bg_color() const { return value(OPTION_UI_SELECTED_BG_COLOR); }
+ const char *ui_mouseover_color() const { return value(OPTION_UI_MOUSEOVER_COLOR); }
+ const char *ui_mouseover_bg_color() const { return value(OPTION_UI_MOUSEOVER_BG_COLOR); }
+ const char *ui_mousedown_color() const { return value(OPTION_UI_MOUSEDOWN_COLOR); }
+ const char *ui_mousedown_bg_color() const { return value(OPTION_UI_MOUSEDOWN_BG_COLOR); }
+ const char *ui_dipsw_color() const { return value(OPTION_UI_DIPSW_COLOR); }
+ const char *ui_slider_color() const { return value(OPTION_UI_SLIDER_COLOR); }
+private:
+ static const options_entry s_option_entries[];
+};
+
+#endif /* __UI_OPTS_H__ */
diff --git a/src/frontend/mame/ui/optsmenu.cpp b/src/frontend/mame/ui/optsmenu.cpp
new file mode 100644
index 00000000000..b08b82b1268
--- /dev/null
+++ b/src/frontend/mame/ui/optsmenu.cpp
@@ -0,0 +1,390 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/*********************************************************************
+
+ ui/optsmenu.cpp
+
+ UI main options menu manager.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "mameopts.h"
+#include "ui/ui.h"
+#include "ui/menu.h"
+#include "ui/submenu.h"
+#include "ui/datfile.h"
+#include "ui/inifile.h"
+#include "ui/selector.h"
+#include "ui/custui.h"
+#include "ui/sndmenu.h"
+#include "ui/miscmenu.h"
+#include "ui/optsmenu.h"
+#include "ui/custmenu.h"
+#include "ui/inputmap.h"
+#include "ui/dirmenu.h"
+#include "rendfont.h"
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+ui_menu_game_options::ui_menu_game_options(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+ m_main = main_filters::actual;
+}
+
+//-------------------------------------------------
+// dtor
+//-------------------------------------------------
+
+ui_menu_game_options::~ui_menu_game_options()
+{
+ main_filters::actual = m_main;
+ ui_menu::menu_stack->reset(UI_MENU_RESET_SELECT_FIRST);
+ save_ui_options(machine());
+ ui_globals::switch_image = true;
+}
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_menu_game_options::handle()
+{
+ bool changed = false;
+
+ // process the menu
+ const ui_menu_event *m_event;
+ if (strcmp(machine().options().ui(), "simple") == 0)
+ {
+ m_event = process(UI_MENU_PROCESS_LR_REPEAT);
+ }
+ else
+ {
+ ui_menu::menu_stack->parent->process(UI_MENU_PROCESS_NOINPUT);
+ m_event = process(UI_MENU_PROCESS_LR_REPEAT | UI_MENU_PROCESS_NOIMAGE);
+ }
+
+ if (m_event != nullptr && m_event->itemref != nullptr)
+ switch ((FPTR)m_event->itemref)
+ {
+ case FILTER_MENU:
+ {
+ if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT)
+ {
+ (m_event->iptkey == IPT_UI_RIGHT) ? ++m_main : --m_main;
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ int total = main_filters::length;
+ std::vector<std::string> s_sel(total);
+ for (int index = 0; index < total; ++index)
+ s_sel[index] = main_filters::text[index];
+
+ ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, s_sel, m_main));
+ }
+ break;
+ }
+ case FILE_CATEGORY_FILTER:
+ {
+ if (m_event->iptkey == IPT_UI_LEFT)
+ {
+ mame_machine_manager::instance()->inifile().move_file(-1);
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_RIGHT)
+ {
+ mame_machine_manager::instance()->inifile().move_file(1);
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ inifile_manager &ifile = mame_machine_manager::instance()->inifile();
+ int total = ifile.total();
+ std::vector<std::string> s_sel(total);
+ mame_machine_manager::instance()->inifile().set_cat(0);
+ for (size_t index = 0; index < total; ++index)
+ s_sel[index] = ifile.get_file(index);
+
+ ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, s_sel, ifile.cur_file(), SELECTOR_INIFILE));
+ }
+ break;
+ }
+ case CATEGORY_FILTER:
+ {
+ if (m_event->iptkey == IPT_UI_LEFT)
+ {
+ mame_machine_manager::instance()->inifile().move_cat(-1);
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_RIGHT)
+ {
+ mame_machine_manager::instance()->inifile().move_cat(1);
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ inifile_manager &ifile = mame_machine_manager::instance()->inifile();
+ int total = ifile.cat_total();
+ std::vector<std::string> s_sel(total);
+ for (int index = 0; index < total; ++index)
+ s_sel[index] = ifile.get_category(index);
+
+ ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, s_sel, ifile.cur_cat(), SELECTOR_CATEGORY));
+ }
+ break;
+ }
+ case MANUFACT_CAT_FILTER:
+ if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT)
+ {
+ (m_event->iptkey == IPT_UI_RIGHT) ? c_mnfct::actual++ : c_mnfct::actual--;
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, c_mnfct::ui, c_mnfct::actual));
+
+ break;
+ case YEAR_CAT_FILTER:
+ if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT)
+ {
+ (m_event->iptkey == IPT_UI_RIGHT) ? c_year::actual++ : c_year::actual--;
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, c_year::ui, c_year::actual));
+
+ break;
+ case CONF_DIR:
+ if (m_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_directory>(machine(), container));
+ break;
+ case MISC_MENU:
+ if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ ui_menu::stack_push(global_alloc_clear<ui_submenu>(machine(), container, misc_submenu_options));
+ ui_globals::reset = true;
+ }
+ break;
+ case SOUND_MENU:
+ if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ ui_menu::stack_push(global_alloc_clear<ui_menu_sound_options>(machine(), container));
+ ui_globals::reset = true;
+ }
+ break;
+ case DISPLAY_MENU:
+ if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ ui_menu::stack_push(global_alloc_clear<ui_submenu>(machine(), container, video_submenu_options));
+ ui_globals::reset = true;
+ }
+ break;
+ case CUSTOM_MENU:
+ if (m_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_custom_ui>(machine(), container));
+ break;
+ case CONTROLLER_MENU:
+ if (m_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(global_alloc_clear<ui_submenu>(machine(), container, control_submenu_options));
+ break;
+ case CGI_MENU:
+ if (m_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_input_groups>(machine(), container));
+ break;
+ case CUSTOM_FILTER:
+ if (m_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_custom_filter>(machine(), container));
+ break;
+ case ADVANCED_MENU:
+ if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ ui_menu::stack_push(global_alloc_clear<ui_submenu>(machine(), container, advanced_submenu_options));
+ ui_globals::reset = true;
+ }
+ break;
+ case SAVE_CONFIG:
+ if (m_event->iptkey == IPT_UI_SELECT)
+ save_main_option(machine());
+ break;
+ }
+
+ if (changed)
+ reset(UI_MENU_RESET_REMEMBER_REF);
+}
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_game_options::populate()
+{
+ if (strcmp(machine().options().ui(),"simple")!=0)
+ {
+ // set filter arrow
+ std::string fbuff;
+
+ // add filter item
+ UINT32 arrow_flags = get_arrow_flags((int)FILTER_FIRST, (int)FILTER_LAST, m_main);
+ item_append(_("Filter"), main_filters::text[m_main], arrow_flags, (void *)(FPTR)FILTER_MENU);
+
+ // add category subitem
+ if (m_main == FILTER_CATEGORY && mame_machine_manager::instance()->inifile().total() > 0)
+ {
+ inifile_manager &inif = mame_machine_manager::instance()->inifile();
+
+ arrow_flags = get_arrow_flags(0, inif.total() - 1, inif.cur_file());
+ fbuff = _(" ^!File");
+ convert_command_glyph(fbuff);
+ item_append(fbuff.c_str(), inif.get_file().c_str(), arrow_flags, (void *)(FPTR)FILE_CATEGORY_FILTER);
+
+ arrow_flags = get_arrow_flags(0, inif.cat_total() - 1, inif.cur_cat());
+ fbuff = _(" ^!Category");
+ convert_command_glyph(fbuff);
+ item_append(fbuff.c_str(), inif.get_category().c_str(), arrow_flags, (void *)(FPTR)CATEGORY_FILTER);
+ }
+ // add manufacturer subitem
+ else if (m_main == FILTER_MANUFACTURER && c_mnfct::ui.size() > 0)
+ {
+ arrow_flags = get_arrow_flags(0, c_mnfct::ui.size() - 1, c_mnfct::actual);
+ fbuff = _("^!Manufacturer");
+ convert_command_glyph(fbuff);
+ item_append(fbuff.c_str(), c_mnfct::ui[c_mnfct::actual].c_str(), arrow_flags, (void *)(FPTR)MANUFACT_CAT_FILTER);
+ }
+ // add year subitem
+ else if (m_main == FILTER_YEAR && c_year::ui.size() > 0)
+ {
+ arrow_flags = get_arrow_flags(0, c_year::ui.size() - 1, c_year::actual);
+ fbuff.assign(_("^!Year"));
+ convert_command_glyph(fbuff);
+ item_append(fbuff.c_str(), c_year::ui[c_year::actual].c_str(), arrow_flags, (void *)(FPTR)YEAR_CAT_FILTER);
+ }
+ // add custom subitem
+ else if (m_main == FILTER_CUSTOM)
+ {
+ fbuff = _("^!Setup custom filter");
+ convert_command_glyph(fbuff);
+ item_append(fbuff.c_str(), nullptr, 0, (void *)(FPTR)CUSTOM_FILTER);
+ }
+
+ item_append(ui_menu_item_type::SEPARATOR);
+
+ // add options items
+ item_append(_("Customize UI"), nullptr, 0, (void *)(FPTR)CUSTOM_MENU);
+ item_append(_("Configure Directories"), nullptr, 0, (void *)(FPTR)CONF_DIR);
+ }
+ item_append(_(video_submenu_options[0].description), nullptr, 0, (void *)(FPTR)DISPLAY_MENU);
+ item_append(_("Sound Options"), nullptr, 0, (void *)(FPTR)SOUND_MENU);
+ item_append(_(misc_submenu_options[0].description), nullptr, 0, (void *)(FPTR)MISC_MENU);
+ item_append(_(control_submenu_options[0].description), nullptr, 0, (void *)(FPTR)CONTROLLER_MENU);
+ item_append(_("General Inputs"), nullptr, 0, (void *)(FPTR)CGI_MENU);
+ item_append(_(advanced_submenu_options[0].description), nullptr, 0, (void *)(FPTR)ADVANCED_MENU);
+ item_append(ui_menu_item_type::SEPARATOR);
+ item_append(_("Save Configuration"), nullptr, 0, (void *)(FPTR)SAVE_CONFIG);
+
+ custombottom = 2.0f * mame_machine_manager::instance()->ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER;
+ customtop = mame_machine_manager::instance()->ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER;
+}
+
+//-------------------------------------------------
+// perform our special rendering
+//-------------------------------------------------
+
+void ui_menu_game_options::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ float width;
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+ mui.draw_text_full(container, _("Settings"), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += 2 * UI_BOX_LR_BORDER;
+ float maxwidth = MAX(origx2 - origx1, width);
+
+ // compute our bounds
+ float x1 = 0.5f - 0.5f * maxwidth;
+ float x2 = x1 + maxwidth;
+ float y1 = origy1 - top;
+ float y2 = origy1 - UI_BOX_TB_BORDER;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ mui.draw_text_full(container, _("Settings"), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+}
+
+//-------------------------------------------------
+// save ui options
+//-------------------------------------------------
+
+void save_ui_options(running_machine &machine)
+{
+ // attempt to open the output file
+ emu_file file(machine.options().ini_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ if (file.open("ui.ini") == osd_file::error::NONE)
+ {
+ // generate the updated INI
+ std::string initext = mame_machine_manager::instance()->ui().options().output_ini();
+ file.puts(initext.c_str());
+ file.close();
+ }
+ else
+ machine.popmessage(_("**Error saving ui.ini**"));
+}
+
+//-------------------------------------------------
+// save main option
+//-------------------------------------------------
+
+void save_main_option(running_machine &machine)
+{
+ // parse the file
+ std::string error;
+ emu_options options(machine.options()); // This way we make sure that all OSD parts are in
+ std::string error_string;
+
+ // attempt to open the main ini file
+ {
+ emu_file file(machine.options().ini_path(), OPEN_FLAG_READ);
+ if (file.open(emulator_info::get_configname(), ".ini") == osd_file::error::NONE)
+ {
+ bool result = options.parse_ini_file((util::core_file&)file, OPTION_PRIORITY_MAME_INI, OPTION_PRIORITY_DRIVER_INI, error);
+ if (!result)
+ {
+ osd_printf_error("**Error loading %s.ini**", emulator_info::get_configname());
+ return;
+ }
+ }
+ }
+
+ for (emu_options::entry &f_entry : machine.options())
+ {
+ if (f_entry.is_changed())
+ {
+ options.set_value(f_entry.name(), f_entry.value(), OPTION_PRIORITY_CMDLINE, error_string);
+ }
+ }
+
+ // attempt to open the output file
+ {
+ emu_file file(machine.options().ini_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ if (file.open(emulator_info::get_configname(), ".ini") == osd_file::error::NONE)
+ {
+ // generate the updated INI
+ std::string initext = options.output_ini();
+ file.puts(initext.c_str());
+ file.close();
+ }
+ else {
+ machine.popmessage(_("**Error saving %s.ini**"), emulator_info::get_configname());
+ return;
+ }
+ }
+ mame_machine_manager::instance()->ui().popup_time(3, "%s", _("\n Configuration saved \n\n"));
+}
diff --git a/src/frontend/mame/ui/optsmenu.h b/src/frontend/mame/ui/optsmenu.h
new file mode 100644
index 00000000000..f6b4243afa0
--- /dev/null
+++ b/src/frontend/mame/ui/optsmenu.h
@@ -0,0 +1,53 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/***************************************************************************
+
+ ui/optsmenu.h
+
+ UI main options menu manager.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_OPTSMENU_H__
+#define __UI_OPTSMENU_H__
+
+class ui_menu_game_options : public ui_menu
+{
+public:
+ ui_menu_game_options(running_machine &machine, render_container *container);
+ virtual ~ui_menu_game_options();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+private:
+ UINT16 m_main;
+
+ enum
+ {
+ FILTER_MENU = 1,
+ FILE_CATEGORY_FILTER,
+ MANUFACT_CAT_FILTER,
+ YEAR_CAT_FILTER,
+ CATEGORY_FILTER,
+ CONF_DIR,
+ DISPLAY_MENU,
+ CUSTOM_MENU,
+ SOUND_MENU,
+ CONTROLLER_MENU,
+ MISC_MENU,
+ ADVANCED_MENU,
+ SAVE_OPTIONS,
+ CGI_MENU,
+ CUSTOM_FILTER,
+ SAVE_CONFIG
+ };
+};
+
+// save options to file
+void save_ui_options(running_machine &machine);
+void save_main_option(running_machine &machine);
+
+#endif /* __UI_OPTSMENU_H__ */
diff --git a/src/frontend/mame/ui/pluginopt.cpp b/src/frontend/mame/ui/pluginopt.cpp
new file mode 100644
index 00000000000..6d026c8fabe
--- /dev/null
+++ b/src/frontend/mame/ui/pluginopt.cpp
@@ -0,0 +1,113 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/*********************************************************************
+
+ ui/pluginopt.cpp
+
+ Internal menu for the plugin interface.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "mame.h"
+#include "luaengine.h"
+
+#include "ui/pluginopt.h"
+
+void ui_menu_plugin::handle()
+{
+ const ui_menu_event *menu_event = process(0);
+
+ if (menu_event != nullptr && menu_event->itemref != nullptr)
+ {
+ if (menu_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_plugin_opt>(machine(), container, (char *)menu_event->itemref));
+ }
+}
+
+ui_menu_plugin::ui_menu_plugin(running_machine &machine, render_container *container) :
+ ui_menu(machine, container),
+ m_plugins(mame_machine_manager::instance()->lua()->get_menu())
+{
+}
+
+void ui_menu_plugin::populate()
+{
+ for (auto &curplugin : m_plugins)
+ item_append(curplugin.c_str(), 0, 0, (void *)curplugin.c_str());
+ item_append(ui_menu_item_type::SEPARATOR);
+}
+
+ui_menu_plugin::~ui_menu_plugin()
+{
+}
+
+ui_menu_plugin_opt::ui_menu_plugin_opt(running_machine &machine, render_container *container, char *menu) :
+ ui_menu(machine, container),
+ m_menu(menu)
+{
+}
+
+void ui_menu_plugin_opt::handle()
+{
+ const ui_menu_event *menu_event = process(0);
+
+ if (menu_event != nullptr && (FPTR)menu_event->itemref)
+ {
+ std::string key;
+ switch(menu_event->iptkey)
+ {
+ case IPT_UI_UP:
+ key = "up";
+ break;
+ case IPT_UI_DOWN:
+ key = "down";
+ break;
+ case IPT_UI_LEFT:
+ key = "left";
+ break;
+ case IPT_UI_RIGHT:
+ key = "right";
+ break;
+ case IPT_UI_SELECT:
+ key = "select";
+ break;
+ case IPT_UI_DISPLAY_COMMENT:
+ key = "comment";
+ break;
+ case IPT_UI_CLEAR:
+ key = "clear";
+ break;
+ default:
+ return;
+ }
+ if(mame_machine_manager::instance()->lua()->menu_callback(m_menu, (FPTR)menu_event->itemref, key))
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ }
+}
+
+void ui_menu_plugin_opt::populate()
+{
+ std::vector<lua_engine::menu_item> menu_list;
+ mame_machine_manager::instance()->lua()->menu_populate(m_menu, menu_list);
+ FPTR i = 1;
+ for(auto &item : menu_list)
+ {
+ UINT32 flags = 0;
+ if(item.flags == "off")
+ flags = MENU_FLAG_DISABLE;
+ else if(item.flags == "l")
+ flags = MENU_FLAG_LEFT_ARROW;
+ else if(item.flags == "r")
+ flags = MENU_FLAG_RIGHT_ARROW;
+ else if(item.flags == "lr")
+ flags = MENU_FLAG_RIGHT_ARROW | MENU_FLAG_LEFT_ARROW;
+
+ item_append(item.text.c_str(), item.subtext.c_str(), flags, (void *)i++);
+ }
+ item_append(ui_menu_item_type::SEPARATOR);
+}
+
+ui_menu_plugin_opt::~ui_menu_plugin_opt()
+{
+}
diff --git a/src/frontend/mame/ui/pluginopt.h b/src/frontend/mame/ui/pluginopt.h
new file mode 100644
index 00000000000..9d529e93749
--- /dev/null
+++ b/src/frontend/mame/ui/pluginopt.h
@@ -0,0 +1,38 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods, Carl
+/***************************************************************************
+
+ ui/pluginopt.h
+
+ Internal menu for the plugin interface.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_PLUGINOPT_H__
+#define __UI_PLUGINOPT_H__
+
+#include "ui/ui.h"
+#include "ui/menu.h"
+
+class ui_menu_plugin : public ui_menu {
+public:
+ ui_menu_plugin(running_machine &machine, render_container *container);
+ virtual ~ui_menu_plugin();
+ virtual void populate() override;
+ virtual void handle() override;
+private:
+ std::vector<std::string> &m_plugins;
+};
+
+class ui_menu_plugin_opt : public ui_menu {
+public:
+ ui_menu_plugin_opt(running_machine &machine, render_container *container, char *menu);
+ virtual ~ui_menu_plugin_opt();
+ virtual void populate() override;
+ virtual void handle() override;
+private:
+ std::string m_menu;
+};
+#endif /* __UI_PLUGINOPT_H__ */
diff --git a/src/frontend/mame/ui/selector.cpp b/src/frontend/mame/ui/selector.cpp
new file mode 100644
index 00000000000..4f06bd961f4
--- /dev/null
+++ b/src/frontend/mame/ui/selector.cpp
@@ -0,0 +1,257 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/*********************************************************************
+
+ ui/selector.cpp
+
+ Internal UI user interface.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "ui/ui.h"
+#include "ui/menu.h"
+#include "ui/selector.h"
+#include "ui/inifile.h"
+
+//-------------------------------------------------
+// ctor / dtor
+//-------------------------------------------------
+
+ui_menu_selector::ui_menu_selector(running_machine &machine, render_container *container, std::vector<std::string> const &s_sel, UINT16 &s_actual, int category, int _hover)
+ : ui_menu(machine, container)
+ , m_selector(s_actual)
+ , m_category(category)
+ , m_hover(_hover)
+ , m_first_pass(true)
+ , m_str_items(s_sel)
+{
+ m_search[0] = '\0';
+ m_searchlist[0] = nullptr;
+}
+
+ui_menu_selector::ui_menu_selector(running_machine &machine, render_container *container, std::vector<std::string> &&s_sel, UINT16 &s_actual, int category, int _hover)
+ : ui_menu(machine, container)
+ , m_selector(s_actual)
+ , m_category(category)
+ , m_hover(_hover)
+ , m_first_pass(true)
+ , m_str_items(std::move(s_sel))
+{
+ m_search[0] = '\0';
+ m_searchlist[0] = nullptr;
+}
+
+ui_menu_selector::~ui_menu_selector()
+{
+}
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_menu_selector::handle()
+{
+ // process the menu
+ const ui_menu_event *m_event = process(0);
+
+ if (m_event != nullptr && m_event->itemref != nullptr)
+ {
+ if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ for (size_t idx = 0; idx < m_str_items.size(); ++idx)
+ if ((void*)&m_str_items[idx] == m_event->itemref)
+ m_selector = idx;
+
+ switch (m_category)
+ {
+ case SELECTOR_INIFILE:
+ mame_machine_manager::instance()->inifile().set_file(m_selector);
+ mame_machine_manager::instance()->inifile().set_cat(0);
+ ui_menu::menu_stack->parent->reset(UI_MENU_RESET_REMEMBER_REF);
+ break;
+
+ case SELECTOR_CATEGORY:
+ mame_machine_manager::instance()->inifile().set_cat(m_selector);
+ ui_menu::menu_stack->parent->reset(UI_MENU_RESET_REMEMBER_REF);
+ break;
+
+ case SELECTOR_GAME:
+ main_filters::actual = m_hover;
+ ui_menu::menu_stack->parent->reset(UI_MENU_RESET_SELECT_FIRST);
+ break;
+
+ case SELECTOR_SOFTWARE:
+ sw_filters::actual = m_hover;
+ ui_menu::menu_stack->parent->reset(UI_MENU_RESET_SELECT_FIRST);
+ break;
+
+ default:
+ ui_menu::menu_stack->parent->reset(UI_MENU_RESET_REMEMBER_REF);
+ break;
+ }
+
+ ui_globals::switch_image = true;
+ ui_menu::stack_pop(machine());
+ }
+ else if (m_event->iptkey == IPT_SPECIAL)
+ {
+ int buflen = strlen(m_search);
+
+ // if it's a backspace and we can handle it, do so
+ if ((m_event->unichar == 8 || m_event->unichar == 0x7f) && buflen > 0)
+ {
+ *(char *)utf8_previous_char(&m_search[buflen]) = 0;
+ reset(UI_MENU_RESET_SELECT_FIRST);
+ }
+
+ // if it's any other key and we're not maxed out, update
+ else if (m_event->unichar >= ' ' && m_event->unichar < 0x7f)
+ {
+ buflen += utf8_from_uchar(&m_search[buflen], ARRAY_LENGTH(m_search) - buflen, m_event->unichar);
+ m_search[buflen] = 0;
+ reset(UI_MENU_RESET_SELECT_FIRST);
+ }
+ }
+
+ // escape pressed with non-empty text clears the text
+ else if (m_event->iptkey == IPT_UI_CANCEL && m_search[0] != 0)
+ {
+ m_search[0] = '\0';
+ reset(UI_MENU_RESET_SELECT_FIRST);
+ }
+ }
+}
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_selector::populate()
+{
+ if (m_search[0] != 0)
+ {
+ find_matches(m_search);
+
+ for (int curitem = 0; m_searchlist[curitem]; ++curitem)
+ item_append(m_searchlist[curitem]->c_str(), nullptr, 0, (void *)m_searchlist[curitem]);
+ }
+ else
+ {
+ for (size_t index = 0, added = 0; index < m_str_items.size(); ++index)
+ if (m_str_items[index] != "_skip_")
+ {
+ if (m_first_pass && m_selector == index)
+ selected = added;
+
+ added++;
+ item_append(m_str_items[index].c_str(), nullptr, 0, (void *)&m_str_items[index]);
+ }
+ }
+
+ item_append(ui_menu_item_type::SEPARATOR);
+ customtop = custombottom = mame_machine_manager::instance()->ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER;
+ m_first_pass = false;
+}
+
+//-------------------------------------------------
+// perform our special rendering
+//-------------------------------------------------
+
+void ui_menu_selector::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ float width;
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+ std::string tempbuf = std::string(_("Selection List - Search: ")).append(m_search).append("_");
+
+ // get the size of the text
+ mui.draw_text_full(container, tempbuf.c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += (2.0f * UI_BOX_LR_BORDER) + 0.01f;
+ float maxwidth = MAX(width, origx2 - origx1);
+
+ // compute our bounds
+ float x1 = 0.5f - 0.5f * maxwidth;
+ float x2 = x1 + maxwidth;
+ float y1 = origy1 - top;
+ float y2 = origy1 - UI_BOX_TB_BORDER;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ mui.draw_text_full(container, tempbuf.c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+
+ // bottom text
+ // get the text for 'UI Select'
+ std::string ui_select_text = machine().input().seq_name(machine().ioport().type_seq(IPT_UI_SELECT, 0, SEQ_TYPE_STANDARD));
+ tempbuf = string_format(_("Double click or press %1$s to select"), ui_select_text);
+
+ mui.draw_text_full(container, tempbuf.c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += 2 * UI_BOX_LR_BORDER;
+ maxwidth = MAX(maxwidth, width);
+
+ // compute our bounds
+ x1 = 0.5f - 0.5f * maxwidth;
+ x2 = x1 + maxwidth;
+ y1 = origy2 + UI_BOX_TB_BORDER;
+ y2 = origy2 + bottom;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_RED_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ mui.draw_text_full(container, tempbuf.c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+}
+
+//-------------------------------------------------
+// find approximate matches
+//-------------------------------------------------
+
+void ui_menu_selector::find_matches(const char *str)
+{
+ // allocate memory to track the penalty value
+ std::vector<int> penalty(VISIBLE_GAMES_IN_SEARCH, 9999);
+ int index = 0;
+
+ for (; index < m_str_items.size(); ++index)
+ {
+ if (m_str_items[index] == "_skip_")
+ continue;
+
+ // pick the best match between driver name and description
+ int curpenalty = fuzzy_substring(str, m_str_items[index]);
+
+ // insert into the sorted table of matches
+ for (int matchnum = VISIBLE_GAMES_IN_SEARCH - 1; matchnum >= 0; --matchnum)
+ {
+ // stop if we're worse than the current entry
+ if (curpenalty >= penalty[matchnum])
+ break;
+
+ // as long as this isn't the last entry, bump this one down
+ if (matchnum < VISIBLE_GAMES_IN_SEARCH - 1)
+ {
+ penalty[matchnum + 1] = penalty[matchnum];
+ m_searchlist[matchnum + 1] = m_searchlist[matchnum];
+ }
+
+ m_searchlist[matchnum] = &m_str_items[index];
+ penalty[matchnum] = curpenalty;
+ }
+ }
+ (index < VISIBLE_GAMES_IN_SEARCH) ? m_searchlist[index] = nullptr : m_searchlist[VISIBLE_GAMES_IN_SEARCH] = nullptr;
+}
diff --git a/src/frontend/mame/ui/selector.h b/src/frontend/mame/ui/selector.h
new file mode 100644
index 00000000000..6809729396d
--- /dev/null
+++ b/src/frontend/mame/ui/selector.h
@@ -0,0 +1,52 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/***************************************************************************
+
+ ui/selector.h
+
+ Internal UI user interface.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_SELECTOR_H__
+#define __UI_SELECTOR_H__
+
+enum
+{
+ SELECTOR_INIFILE = 1,
+ SELECTOR_CATEGORY,
+ SELECTOR_GAME,
+ SELECTOR_SOFTWARE
+};
+
+//-------------------------------------------------
+// class selector menu
+//-------------------------------------------------
+
+class ui_menu_selector : public ui_menu
+{
+public:
+ ui_menu_selector(running_machine &machine, render_container *container, std::vector<std::string> const &_sel, UINT16 &_actual, int _category = 0, int _hover = 0);
+ ui_menu_selector(running_machine &machine, render_container *container, std::vector<std::string> &&_sel, UINT16 &_actual, int _category = 0, int _hover = 0);
+ virtual ~ui_menu_selector();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+ virtual bool menu_has_search_active() override { return (m_search[0] != 0); }
+
+private:
+ enum { VISIBLE_GAMES_IN_SEARCH = 200 };
+ char m_search[40];
+ UINT16 &m_selector;
+ int m_category, m_hover;
+ bool m_first_pass;
+ std::vector<std::string> m_str_items;
+ std::string *m_searchlist[VISIBLE_GAMES_IN_SEARCH + 1];
+
+ void find_matches(const char *str);
+};
+
+#endif /* __UI_SELECTOR_H__ */
diff --git a/src/frontend/mame/ui/selgame.cpp b/src/frontend/mame/ui/selgame.cpp
new file mode 100644
index 00000000000..00fbd75108e
--- /dev/null
+++ b/src/frontend/mame/ui/selgame.cpp
@@ -0,0 +1,2493 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/*********************************************************************
+
+ ui/selgame.cpp
+
+ Main UI menu.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "mame.h"
+#include "emuopts.h"
+#include "ui/ui.h"
+#include "uiinput.h"
+#include "ui/selgame.h"
+#include "ui/miscmenu.h"
+#include "audit.h"
+#include "ui/datfile.h"
+#include "ui/inifile.h"
+#include "rendfont.h"
+#include "ui/datmenu.h"
+#include "ui/optsmenu.h"
+#include "ui/selector.h"
+#include "ui/selsoft.h"
+#include "sound/samples.h"
+#include "ui/custmenu.h"
+#include "../info.h"
+#include "ui/auditmenu.h"
+#include "rendutil.h"
+#include "softlist.h"
+
+extern const char UI_VERSION_TAG[];
+
+static bool first_start = true;
+static const char *dats_info[] = {
+ __("General Info"),
+ __("History"),
+ __("Mameinfo"),
+ __("Sysinfo"),
+ __("Messinfo"),
+ __("Command"),
+ __("Gameinit"),
+ __("Mamescore") };
+
+std::vector<const game_driver *> ui_menu_select_game::m_sortedlist;
+int ui_menu_select_game::m_isabios = 0;
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+ui_menu_select_game::ui_menu_select_game(running_machine &machine, render_container *container, const char *gamename) : ui_menu(machine, container)
+{
+ m_focus = focused_menu::main;
+ highlight = 0;
+ std::string error_string, last_filter, sub_filter;
+ ui_options &moptions = mame_machine_manager::instance()->ui().options();
+
+ // load drivers cache
+ init_sorted_list();
+
+ // check if there are available icons
+ ui_globals::has_icons = false;
+ file_enumerator path(moptions.icons_directory());
+ const osd_directory_entry *dir;
+ while ((dir = path.next()) != nullptr)
+ {
+ std::string src(dir->name);
+ if (src.find(".ico") != std::string::npos || src.find("icons") != std::string::npos)
+ {
+ ui_globals::has_icons = true;
+ break;
+ }
+ }
+
+ // build drivers list
+ if (!load_available_machines())
+ build_available_list();
+
+ // load custom filter
+ load_custom_filters();
+
+ if (first_start)
+ {
+ reselect_last::driver = moptions.last_used_machine();
+ std::string tmp(moptions.last_used_filter());
+ std::size_t found = tmp.find_first_of(",");
+ if (found == std::string::npos)
+ last_filter = tmp;
+ else
+ {
+ last_filter = tmp.substr(0, found);
+ sub_filter = tmp.substr(found + 1);
+ }
+
+ main_filters::actual = FILTER_ALL;
+ for (size_t ind = 0; ind < main_filters::length; ++ind)
+ if (last_filter == main_filters::text[ind])
+ {
+ main_filters::actual = ind;
+ break;
+ }
+
+ if (main_filters::actual == FILTER_CATEGORY)
+ main_filters::actual = FILTER_ALL;
+ else if (main_filters::actual == FILTER_MANUFACTURER)
+ {
+ for (size_t id = 0; id < c_mnfct::ui.size(); ++id)
+ if (sub_filter == c_mnfct::ui[id])
+ c_mnfct::actual = id;
+ }
+ else if (main_filters::actual == FILTER_YEAR)
+ {
+ for (size_t id = 0; id < c_year::ui.size(); ++id)
+ if (sub_filter == c_year::ui[id])
+ c_year::actual = id;
+ }
+ first_start = false;
+ }
+
+ if (!moptions.remember_last())
+ reselect_last::reset();
+
+ machine.options().set_value(OPTION_SNAPNAME, "%g/%i", OPTION_PRIORITY_CMDLINE, error_string);
+ machine.options().set_value(OPTION_SOFTWARENAME, "", OPTION_PRIORITY_CMDLINE, error_string);
+
+ ui_globals::curimage_view = FIRST_VIEW;
+ ui_globals::curdats_view = UI_FIRST_LOAD;
+ ui_globals::switch_image = false;
+ ui_globals::default_image = true;
+ ui_globals::panels_status = moptions.hide_panels();
+ m_searchlist[0] = nullptr;
+}
+
+//-------------------------------------------------
+// dtor
+//-------------------------------------------------
+
+ui_menu_select_game::~ui_menu_select_game()
+{
+ std::string error_string, last_driver;
+ const game_driver *driver = nullptr;
+ ui_software_info *swinfo = nullptr;
+ ui_options &mopt = mame_machine_manager::instance()->ui().options();
+ if (isfavorite())
+ swinfo = (selected >= 0 && selected < item.size()) ? (ui_software_info *)item[selected].ref : nullptr;
+ else
+ driver = (selected >= 0 && selected < item.size()) ? (const game_driver *)item[selected].ref : nullptr;
+
+ if ((FPTR)driver > skip_main_items)
+ last_driver = driver->name;
+
+ if ((FPTR)swinfo > skip_main_items)
+ last_driver = swinfo->shortname;
+
+ std::string filter(main_filters::text[main_filters::actual]);
+ if (main_filters::actual == FILTER_MANUFACTURER)
+ filter.append(",").append(c_mnfct::ui[c_mnfct::actual]);
+ else if (main_filters::actual == FILTER_YEAR)
+ filter.append(",").append(c_year::ui[c_year::actual]);
+
+ mopt.set_value(OPTION_LAST_USED_FILTER, filter.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
+ mopt.set_value(OPTION_LAST_USED_MACHINE, last_driver.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
+ mopt.set_value(OPTION_HIDE_PANELS, ui_globals::panels_status, OPTION_PRIORITY_CMDLINE, error_string);
+ save_ui_options(machine());
+}
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_menu_select_game::handle()
+{
+ if (m_prev_selected == nullptr)
+ m_prev_selected = item[0].ref;
+
+ bool check_filter = false;
+ bool enabled_dats = mame_machine_manager::instance()->ui().options().enabled_dats();
+
+ // if i have to load datfile, performe an hard reset
+ if (ui_globals::reset)
+ {
+ ui_globals::reset = false;
+ machine().schedule_hard_reset();
+ ui_menu::stack_reset(machine());
+ return;
+ }
+
+ // if i have to reselect a software, force software list submenu
+ if (reselect_last::get())
+ {
+ const game_driver *driver = (const game_driver *)item[selected].ref;
+ ui_menu::stack_push(global_alloc_clear<ui_menu_select_software>(machine(), container, driver));
+ return;
+ }
+
+ // ignore pause keys by swallowing them before we process the menu
+ machine().ui_input().pressed(IPT_UI_PAUSE);
+
+ // process the menu
+ const ui_menu_event *m_event = process(UI_MENU_PROCESS_LR_REPEAT);
+ if (m_event != nullptr && m_event->itemref != nullptr)
+ {
+ // reset the error on any future m_event
+ if (ui_error)
+ {
+ ui_error = false;
+ machine().ui_input().reset();
+ }
+
+ // handle selections
+ else if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ if (m_focus == focused_menu::main)
+ {
+ if (isfavorite())
+ inkey_select_favorite(m_event);
+ else
+ inkey_select(m_event);
+ }
+ else if (m_focus == focused_menu::left)
+ {
+ l_hover = highlight;
+ check_filter = true;
+ m_prev_selected = nullptr;
+ }
+ }
+
+ // handle IPT_CUSTOM (mouse right click)
+ else if (m_event->iptkey == IPT_CUSTOM)
+ {
+ if (!isfavorite())
+ ui_menu::stack_push(global_alloc_clear<ui_menu_machine_configure>(machine(), container, (const game_driver *)m_prev_selected, m_event->mouse.x0, m_event->mouse.y0));
+ }
+
+ // handle UI_LEFT
+ else if (m_event->iptkey == IPT_UI_LEFT)
+ {
+ // Images
+ if (ui_globals::rpanel == RP_IMAGES && ui_globals::curimage_view > FIRST_VIEW)
+ {
+ ui_globals::curimage_view--;
+ ui_globals::switch_image = true;
+ ui_globals::default_image = false;
+ }
+
+ // Infos
+ else if (ui_globals::rpanel == RP_INFOS)
+ {
+ if (!isfavorite())
+ {
+ const game_driver *drv = (const game_driver *)m_event->itemref;
+ if ((FPTR)drv > skip_main_items && ui_globals::curdats_view > UI_FIRST_LOAD)
+ {
+ ui_globals::curdats_view--;
+ topline_datsview = 0;
+ }
+ }
+ else
+ {
+ ui_software_info *drv = (ui_software_info *)m_event->itemref;
+ if (drv->startempty == 1 && ui_globals::curdats_view > UI_FIRST_LOAD)
+ {
+ ui_globals::curdats_view--;
+ topline_datsview = 0;
+ }
+ else if ((FPTR)drv > skip_main_items && ui_globals::cur_sw_dats_view > 0)
+ {
+ ui_globals::cur_sw_dats_view--;
+ topline_datsview = 0;
+ }
+ }
+ }
+ }
+
+ // handle UI_RIGHT
+ else if (m_event->iptkey == IPT_UI_RIGHT)
+ {
+ // Images
+ if (ui_globals::rpanel == RP_IMAGES && ui_globals::curimage_view < LAST_VIEW)
+ {
+ ui_globals::curimage_view++;
+ ui_globals::switch_image = true;
+ ui_globals::default_image = false;
+ }
+
+ // Infos
+ else if (ui_globals::rpanel == RP_INFOS)
+ {
+ if (!isfavorite())
+ {
+ const game_driver *drv = (const game_driver *)m_event->itemref;
+ if ((FPTR)drv > skip_main_items && ui_globals::curdats_view < UI_LAST_LOAD)
+ {
+ ui_globals::curdats_view++;
+ topline_datsview = 0;
+ }
+ }
+ else
+ {
+ ui_software_info *drv = (ui_software_info *)m_event->itemref;
+ if (drv->startempty == 1 && ui_globals::curdats_view < UI_LAST_LOAD)
+ {
+ ui_globals::curdats_view++;
+ topline_datsview = 0;
+ }
+ else if ((FPTR)drv > skip_main_items && ui_globals::cur_sw_dats_view < 1)
+ {
+ ui_globals::cur_sw_dats_view++;
+ topline_datsview = 0;
+ }
+ }
+ }
+ }
+
+ // handle UI_UP_FILTER
+ else if (m_event->iptkey == IPT_UI_UP_FILTER && highlight > FILTER_FIRST)
+ {
+ highlight--;
+ }
+
+ // handle UI_DOWN_FILTER
+ else if (m_event->iptkey == IPT_UI_DOWN_FILTER && highlight < FILTER_LAST)
+ {
+ highlight++;
+ }
+
+ // handle UI_LEFT_PANEL
+ else if (m_event->iptkey == IPT_UI_LEFT_PANEL)
+ ui_globals::rpanel = RP_IMAGES;
+
+ // handle UI_RIGHT_PANEL
+ else if (m_event->iptkey == IPT_UI_RIGHT_PANEL)
+ ui_globals::rpanel = RP_INFOS;
+
+ // escape pressed with non-empty text clears the text
+ else if (m_event->iptkey == IPT_UI_CANCEL && m_search[0] != 0)
+ {
+ m_search[0] = '\0';
+ reset(UI_MENU_RESET_SELECT_FIRST);
+ }
+
+ // handle UI_DATS
+ else if (m_event->iptkey == IPT_UI_DATS && enabled_dats)
+ {
+ if (!isfavorite())
+ {
+ const game_driver *driver = (const game_driver *)m_event->itemref;
+ if ((FPTR)driver > skip_main_items && mame_machine_manager::instance()->datfile().has_data(driver))
+ ui_menu::stack_push(global_alloc_clear<ui_menu_dats_view>(machine(), container, driver));
+ }
+ else
+ {
+ ui_software_info *ui_swinfo = (ui_software_info *)m_event->itemref;
+ datfile_manager &mdat = mame_machine_manager::instance()->datfile();
+
+ if ((FPTR)ui_swinfo > skip_main_items)
+ {
+ if (ui_swinfo->startempty == 1 && mdat.has_history(ui_swinfo->driver))
+ ui_menu::stack_push(global_alloc_clear<ui_menu_dats_view>(machine(), container, ui_swinfo->driver));
+ else if (mdat.has_software(ui_swinfo->listname, ui_swinfo->shortname, ui_swinfo->parentname) || !ui_swinfo->usage.empty())
+ ui_menu::stack_push(global_alloc_clear<ui_menu_dats_view>(machine(), container, ui_swinfo));
+ }
+ }
+ }
+
+ // handle UI_FAVORITES
+ else if (m_event->iptkey == IPT_UI_FAVORITES)
+ {
+ if (!isfavorite())
+ {
+ const game_driver *driver = (const game_driver *)m_event->itemref;
+ if ((FPTR)driver > skip_main_items)
+ {
+ if (!mame_machine_manager::instance()->favorite().isgame_favorite(driver))
+ {
+ mame_machine_manager::instance()->favorite().add_favorite_game(driver);
+ machine().popmessage(_("%s\n added to favorites list."), driver->description);
+ }
+
+ else
+ {
+ mame_machine_manager::instance()->favorite().remove_favorite_game();
+ machine().popmessage(_("%s\n removed from favorites list."), driver->description);
+ }
+ }
+ }
+ else
+ {
+ ui_software_info *swinfo = (ui_software_info *)m_event->itemref;
+ if ((FPTR)swinfo > skip_main_items)
+ {
+ machine().popmessage(_("%s\n removed from favorites list."), swinfo->longname.c_str());
+ mame_machine_manager::instance()->favorite().remove_favorite_game(*swinfo);
+ reset(UI_MENU_RESET_SELECT_FIRST);
+ }
+ }
+ }
+
+ // handle UI_EXPORT
+ else if (m_event->iptkey == IPT_UI_EXPORT && !isfavorite())
+ inkey_export();
+
+ // handle UI_AUDIT_FAST
+ else if (m_event->iptkey == IPT_UI_AUDIT_FAST && !m_unavailsortedlist.empty())
+ ui_menu::stack_push(global_alloc_clear<ui_menu_audit>(machine(), container, m_availsortedlist, m_unavailsortedlist, 1));
+
+ // handle UI_AUDIT_ALL
+ else if (m_event->iptkey == IPT_UI_AUDIT_ALL)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_audit>(machine(), container, m_availsortedlist, m_unavailsortedlist, 2));
+
+ // typed characters append to the buffer
+ else if (m_event->iptkey == IPT_SPECIAL)
+ inkey_special(m_event);
+
+ else if (m_event->iptkey == IPT_UI_CONFIGURE)
+ inkey_configure(m_event);
+
+ else if (m_event->iptkey == IPT_OTHER)
+ {
+ m_prev_selected = nullptr;
+ check_filter = true;
+ highlight = l_hover;
+ }
+ }
+
+ if (m_event != nullptr && m_event->itemref == nullptr)
+ {
+ if (m_event->iptkey == IPT_SPECIAL)
+ inkey_special(m_event);
+ else if (m_event->iptkey == IPT_UI_CONFIGURE)
+ inkey_configure(m_event);
+ else if (m_event->iptkey == IPT_OTHER)
+ {
+ m_focus = focused_menu::left;
+ m_prev_selected = nullptr;
+ l_hover = highlight;
+ check_filter = true;
+ }
+ // handle UI_UP_FILTER
+ else if (m_event->iptkey == IPT_UI_UP_FILTER && highlight > FILTER_FIRST)
+ {
+ highlight--;
+ }
+
+ // handle UI_DOWN_FILTER
+ else if (m_event->iptkey == IPT_UI_DOWN_FILTER && highlight < FILTER_LAST)
+ {
+ highlight++;
+ }
+ }
+
+ // if we're in an error state, overlay an error message
+ if (ui_error)
+ mame_machine_manager::instance()->ui().draw_text_box(container, _("The selected machine is missing one or more required ROM or CHD images. "
+ "Please select a different machine.\n\nPress any key to continue."), JUSTIFY_CENTER, 0.5f, 0.5f, UI_RED_COLOR);
+
+ // handle filters selection from key shortcuts
+ if (check_filter)
+ {
+ m_search[0] = '\0';
+ if (l_hover == FILTER_CATEGORY)
+ {
+ main_filters::actual = l_hover;
+ ui_menu::stack_push(global_alloc_clear<ui_menu_game_options>(machine(), container));
+ }
+ else if (l_hover == FILTER_CUSTOM)
+ {
+ main_filters::actual = l_hover;
+ ui_menu::stack_push(global_alloc_clear<ui_menu_custom_filter>(machine(), container, true));
+ }
+ else if (l_hover == FILTER_MANUFACTURER)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, c_mnfct::ui, c_mnfct::actual, SELECTOR_GAME, l_hover));
+ else if (l_hover == FILTER_YEAR)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, c_year::ui, c_year::actual, SELECTOR_GAME, l_hover));
+ else
+ {
+ if (l_hover >= FILTER_ALL)
+ main_filters::actual = l_hover;
+ reset(UI_MENU_RESET_SELECT_FIRST);
+ }
+ }
+}
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_select_game::populate()
+{
+ ui_globals::redraw_icon = true;
+ ui_globals::switch_image = true;
+ int old_item_selected = -1;
+
+ if (!isfavorite())
+ {
+ // if search is not empty, find approximate matches
+ if (m_search[0] != 0 && !isfavorite())
+ populate_search();
+ else
+ {
+ // reset search string
+ m_search[0] = '\0';
+ m_displaylist.clear();
+
+ // if filter is set on category, build category list
+ switch (main_filters::actual)
+ {
+ case FILTER_CATEGORY:
+ build_category();
+ break;
+ case FILTER_MANUFACTURER:
+ build_list(c_mnfct::ui[c_mnfct::actual].c_str());
+ break;
+ case FILTER_YEAR:
+ build_list(c_year::ui[c_year::actual].c_str());
+ break;
+ case FILTER_CUSTOM:
+ build_custom();
+ break;
+ default:
+ build_list();
+ break;
+ }
+
+ // iterate over entries
+ int curitem = 0;
+ for (auto & elem : m_displaylist)
+ {
+ UINT32 flags_ui = MENU_FLAG_UI | MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW;
+
+ if (old_item_selected == -1 && elem->name == reselect_last::driver)
+ old_item_selected = curitem;
+
+ bool cloneof = strcmp(elem->parent, "0");
+ if (cloneof)
+ {
+ int cx = driver_list::find(elem->parent);
+ if (cx != -1 && ((driver_list::driver(cx).flags & MACHINE_IS_BIOS_ROOT) != 0))
+ cloneof = false;
+ }
+ if (cloneof)
+ flags_ui |= MENU_FLAG_INVERT;
+
+ item_append(elem->description, nullptr, flags_ui, (void *)elem);
+ curitem++;
+ }
+ }
+ }
+ // populate favorites list
+ else
+ {
+ m_search[0] = '\0';
+ int curitem = 0;
+ // iterate over entries
+ for (auto & mfavorite : mame_machine_manager::instance()->favorite().m_list)
+ {
+ UINT32 flags_ui = MENU_FLAG_UI | MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW | MENU_FLAG_UI_FAVORITE;
+ if (mfavorite.startempty == 1)
+ {
+ if (old_item_selected == -1 && mfavorite.shortname == reselect_last::driver)
+ old_item_selected = curitem;
+
+ bool cloneof = strcmp(mfavorite.driver->parent, "0");
+ if (cloneof)
+ {
+ int cx = driver_list::find(mfavorite.driver->parent);
+ if (cx != -1 && ((driver_list::driver(cx).flags & MACHINE_IS_BIOS_ROOT) != 0))
+ cloneof = false;
+ }
+ if (cloneof)
+ flags_ui |= MENU_FLAG_INVERT;
+
+ item_append(mfavorite.longname.c_str(), nullptr, flags_ui, (void *)&mfavorite);
+ }
+ else
+ {
+ if (old_item_selected == -1 && mfavorite.shortname == reselect_last::driver)
+ old_item_selected = curitem;
+ item_append(mfavorite.longname.c_str(), mfavorite.devicetype.c_str(),
+ mfavorite.parentname.empty() ? flags_ui : (MENU_FLAG_INVERT | flags_ui), (void *)&mfavorite);
+ }
+ curitem++;
+ }
+ }
+
+ item_append(MENU_SEPARATOR_ITEM, nullptr, MENU_FLAG_UI, nullptr);
+
+ // add special items
+ if (ui_menu::stack_has_special_main_menu())
+ {
+ UINT32 flags_ui = MENU_FLAG_UI | MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW;
+ item_append(_("Configure Options"), nullptr, flags_ui, (void *)(FPTR)CONF_OPTS);
+ item_append(_("Configure Machine"), nullptr, flags_ui, (void *)(FPTR)CONF_MACHINE);
+ skip_main_items = 2;
+ if (machine().options().plugins())
+ {
+ item_append(_("Plugins"), nullptr, flags_ui, (void *)(FPTR)CONF_PLUGINS);
+ skip_main_items++;
+ }
+ }
+ else
+ skip_main_items = 0;
+
+ // configure the custom rendering
+ customtop = 3.0f * mame_machine_manager::instance()->ui().get_line_height() + 5.0f * UI_BOX_TB_BORDER;
+ custombottom = 5.0f * mame_machine_manager::instance()->ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER;
+
+ // reselect prior game launched, if any
+ if (old_item_selected != -1)
+ {
+ selected = old_item_selected;
+ if (ui_globals::visible_main_lines == 0)
+ top_line = (selected != 0) ? selected - 1 : 0;
+ else
+ top_line = selected - (ui_globals::visible_main_lines / 2);
+
+ if (reselect_last::software.empty())
+ reselect_last::reset();
+ }
+ else
+ reselect_last::reset();
+}
+
+//-------------------------------------------------
+// build a list of available drivers
+//-------------------------------------------------
+
+void ui_menu_select_game::build_available_list()
+{
+ int m_total = driver_list::total();
+ std::vector<bool> m_included(m_total, false);
+
+ // open a path to the ROMs and find them in the array
+ file_enumerator path(machine().options().media_path());
+ const osd_directory_entry *dir;
+
+ // iterate while we get new objects
+ while ((dir = path.next()) != nullptr)
+ {
+ char drivername[50];
+ char *dst = drivername;
+ const char *src;
+
+ // build a name for it
+ for (src = dir->name; *src != 0 && *src != '.' && dst < &drivername[ARRAY_LENGTH(drivername) - 1]; ++src)
+ *dst++ = tolower((UINT8) * src);
+
+ *dst = 0;
+ int drivnum = driver_list::find(drivername);
+ if (drivnum != -1 && !m_included[drivnum])
+ {
+ m_availsortedlist.push_back(&driver_list::driver(drivnum));
+ m_included[drivnum] = true;
+ }
+ }
+
+ // now check and include NONE_NEEDED
+ for (int x = 0; x < m_total; ++x)
+ {
+ const game_driver *driver = &driver_list::driver(x);
+ if (!m_included[x] && driver != &GAME_NAME(___empty))
+ {
+ const rom_entry *rom = driver->rom;
+ bool noroms = true;
+
+ // check NO-DUMP
+ for (; !ROMENTRY_ISEND(rom) && noroms == true; ++rom)
+ if (ROMENTRY_ISFILE(rom))
+ {
+ hash_collection hashes(ROM_GETHASHDATA(rom));
+ if (!hashes.flag(hash_collection::FLAG_NO_DUMP) && !ROM_ISOPTIONAL(rom))
+ noroms = false;
+ }
+
+ if (!noroms)
+ {
+ // check if clone == parent
+ int cx = driver_list::clone(*driver);
+ if (cx != -1 && m_included[cx])
+ {
+ const game_driver *drv = &driver_list::driver(cx);
+ const rom_entry *parentrom = drv->rom;
+ if ((rom = driver->rom) == parentrom)
+ noroms = true;
+
+ // check if clone < parent
+ if (!noroms)
+ {
+ noroms = true;
+ for (; !ROMENTRY_ISEND(rom) && noroms == true; ++rom)
+ {
+ if (ROMENTRY_ISFILE(rom))
+ {
+ hash_collection hashes(ROM_GETHASHDATA(rom));
+ if (hashes.flag(hash_collection::FLAG_NO_DUMP) || ROM_ISOPTIONAL(rom))
+ continue;
+
+ UINT64 lenght = ROM_GETLENGTH(rom);
+ bool found = false;
+ for (parentrom = drv->rom; !ROMENTRY_ISEND(parentrom) && found == false; ++parentrom)
+ {
+ if (ROMENTRY_ISFILE(parentrom) && ROM_GETLENGTH(parentrom) == lenght)
+ {
+ hash_collection parenthashes(ROM_GETHASHDATA(parentrom));
+ if (parenthashes.flag(hash_collection::FLAG_NO_DUMP) || ROM_ISOPTIONAL(parentrom))
+ continue;
+
+ if (hashes == parenthashes)
+ found = true;
+ }
+ }
+ noroms = found;
+ }
+ }
+ }
+ }
+ }
+
+ if (noroms)
+ {
+ m_availsortedlist.push_back(&driver_list::driver(x));
+ m_included[x] = true;
+ }
+ }
+ }
+
+ // sort
+ std::stable_sort(m_availsortedlist.begin(), m_availsortedlist.end(), sorted_game_list);
+
+ // now build the unavailable list
+ for (int x = 0; x < m_total; ++x)
+ if (!m_included[x] && &driver_list::driver(x) != &GAME_NAME(___empty))
+ m_unavailsortedlist.push_back(&driver_list::driver(x));
+
+ // sort
+ std::stable_sort(m_unavailsortedlist.begin(), m_unavailsortedlist.end(), sorted_game_list);
+}
+
+//-------------------------------------------------
+// perform our special rendering
+//-------------------------------------------------
+
+void ui_menu_select_game::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ const game_driver *driver = nullptr;
+ ui_software_info *swinfo = nullptr;
+ float width, maxwidth = origx2 - origx1;
+ std::string tempbuf[5];
+ rgb_t color = UI_BACKGROUND_COLOR;
+ bool isstar = false;
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+ float tbarspace = mui.get_line_height();
+ float text_size = 1.0f;
+
+ tempbuf[0] = string_format(_("%1$s %2$s ( %3$d / %4$d machines (%5$d BIOS) )"),
+ emulator_info::get_appname(),
+ bare_build_version,
+ visible_items,
+ (driver_list::total() - 1),
+ m_isabios);
+
+ std::string filtered;
+ if (main_filters::actual == FILTER_CATEGORY && mame_machine_manager::instance()->inifile().total() > 0)
+ {
+ filtered = string_format(_("%1$s (%2$s - %3$s) - "),
+ main_filters::text[main_filters::actual],
+ mame_machine_manager::instance()->inifile().get_file(),
+ mame_machine_manager::instance()->inifile().get_category());
+ }
+ else if (main_filters::actual == FILTER_MANUFACTURER)
+ {
+ filtered = string_format(_("%1$s (%2$s) - "),
+ main_filters::text[main_filters::actual],
+ c_mnfct::ui[c_mnfct::actual]);
+ }
+ else if (main_filters::actual == FILTER_YEAR)
+ {
+ filtered = string_format(_("%1$s (%2$s) - "),
+ main_filters::text[main_filters::actual],
+ c_year::ui[c_year::actual]);
+ }
+
+ // display the current typeahead
+ if (isfavorite())
+ tempbuf[1].clear();
+ else
+ tempbuf[1] = string_format(_("%1$s Search: %2$s_"), filtered, m_search);
+
+ // get the size of the text
+ for (int line = 0; line < 2; ++line)
+ {
+ mui.draw_text_full(container, tempbuf[line].c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += 2 * UI_BOX_LR_BORDER;
+ maxwidth = MAX(width, maxwidth);
+ }
+
+ if (maxwidth > origx2 - origx1)
+ {
+ text_size = (origx2 - origx1) / maxwidth;
+ maxwidth = origx2 - origx1;
+ }
+
+ // compute our bounds
+ float x1 = 0.5f - 0.5f * maxwidth;
+ float x2 = x1 + maxwidth;
+ float y1 = origy1 - top;
+ float y2 = origy1 - 3.0f * UI_BOX_TB_BORDER - tbarspace;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ for (int line = 0; line < 2; ++line)
+ {
+ mui.draw_text_full(container, tempbuf[line].c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, text_size);
+ y1 += mui.get_line_height();
+ }
+
+ // determine the text to render below
+ if (!isfavorite())
+ driver = ((FPTR)selectedref > skip_main_items) ? (const game_driver *)selectedref : ((m_prev_selected != nullptr) ? (const game_driver *)m_prev_selected : nullptr);
+ else
+ {
+ swinfo = ((FPTR)selectedref > skip_main_items) ? (ui_software_info *)selectedref : ((m_prev_selected != nullptr) ? (ui_software_info *)m_prev_selected : nullptr);
+ if (swinfo != nullptr && swinfo->startempty == 1)
+ driver = swinfo->driver;
+ }
+
+ if (driver != nullptr)
+ {
+ isstar = mame_machine_manager::instance()->favorite().isgame_favorite(driver);
+
+ // first line is game name
+ tempbuf[0] = string_format(_("Romset: %1$-.100s"), driver->name);
+
+ // next line is year, manufacturer
+ tempbuf[1] = string_format(_("%1$s, %2$-.100s"), driver->year, driver->manufacturer);
+
+ // next line is clone/parent status
+ int cloneof = driver_list::non_bios_clone(*driver);
+
+ if (cloneof != -1)
+ tempbuf[2] = string_format(_("Driver is clone of: %1$-.100s"), driver_list::driver(cloneof).description);
+ else
+ tempbuf[2] = _("Driver is parent");
+
+ // next line is overall driver status
+ if (driver->flags & MACHINE_NOT_WORKING)
+ tempbuf[3] = _("Overall: NOT WORKING");
+ else if (driver->flags & MACHINE_UNEMULATED_PROTECTION)
+ tempbuf[3] = _("Overall: Unemulated Protection");
+ else
+ tempbuf[3] = _("Overall: Working");
+
+ // next line is graphics, sound status
+ if (driver->flags & (MACHINE_IMPERFECT_GRAPHICS | MACHINE_WRONG_COLORS | MACHINE_IMPERFECT_COLORS))
+ tempbuf[4] = _("Graphics: Imperfect, ");
+ else
+ tempbuf[4] = _("Graphics: OK, ");
+
+ if (driver->flags & MACHINE_NO_SOUND)
+ tempbuf[4].append(_("Sound: Unimplemented"));
+ else if (driver->flags & MACHINE_IMPERFECT_SOUND)
+ tempbuf[4].append(_("Sound: Imperfect"));
+ else
+ tempbuf[4].append(_("Sound: OK"));
+
+ color = UI_GREEN_COLOR;
+
+ if ((driver->flags & (MACHINE_IMPERFECT_GRAPHICS | MACHINE_WRONG_COLORS | MACHINE_IMPERFECT_COLORS
+ | MACHINE_NO_SOUND | MACHINE_IMPERFECT_SOUND)) != 0)
+ color = UI_YELLOW_COLOR;
+
+ if ((driver->flags & (MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION)) != 0)
+ color = UI_RED_COLOR;
+ }
+
+ else if (swinfo != nullptr)
+ {
+ isstar = mame_machine_manager::instance()->favorite().isgame_favorite(*swinfo);
+
+ // first line is system
+ tempbuf[0] = string_format(_("System: %1$-.100s"), swinfo->driver->description);
+
+ // next line is year, publisher
+ tempbuf[1] = string_format(_("%1$s, %2$-.100s"), swinfo->year.c_str(), swinfo->publisher.c_str());
+
+ // next line is parent/clone
+ if (!swinfo->parentname.empty())
+ tempbuf[2] = string_format(_("Software is clone of: %1$-.100s"), !swinfo->parentlongname.empty() ? swinfo->parentlongname.c_str() : swinfo->parentname.c_str());
+ else
+ tempbuf[2] = _("Software is parent");
+
+ // next line is supported status
+ if (swinfo->supported == SOFTWARE_SUPPORTED_NO)
+ {
+ tempbuf[3] = _("Supported: No");
+ color = UI_RED_COLOR;
+ }
+ else if (swinfo->supported == SOFTWARE_SUPPORTED_PARTIAL)
+ {
+ tempbuf[3] = _("Supported: Partial");
+ color = UI_YELLOW_COLOR;
+ }
+ else
+ {
+ tempbuf[3] = _("Supported: Yes");
+ color = UI_GREEN_COLOR;
+ }
+
+ // last line is romset name
+ tempbuf[4] = string_format(_("romset: %1$-.100s"), swinfo->shortname.c_str());
+ }
+ else
+ {
+ std::string copyright(emulator_info::get_copyright());
+ size_t found = copyright.find("\n");
+ tempbuf[0].clear();
+ tempbuf[1] = string_format(_("%1$s %2$s"), emulator_info::get_appname(), build_version);
+ tempbuf[2] = copyright.substr(0, found);
+ tempbuf[3] = copyright.substr(found + 1);
+ tempbuf[4].clear();
+ }
+
+ // compute our bounds
+ x1 = 0.5f - 0.5f * maxwidth;
+ x2 = x1 + maxwidth;
+ y1 = y2;
+ y2 = origy1 - UI_BOX_TB_BORDER;
+
+ // draw toolbar
+ draw_toolbar(x1, y1, x2, y2);
+
+ // get the size of the text
+ maxwidth = origx2 - origx1;
+
+ for (auto & elem : tempbuf)
+ {
+ mui.draw_text_full(container, elem.c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += 2 * UI_BOX_LR_BORDER;
+ maxwidth = MAX(maxwidth, width);
+ }
+
+ if (maxwidth > origx2 - origx1)
+ {
+ text_size = (origx2 - origx1) / maxwidth;
+ maxwidth = origx2 - origx1;
+ }
+
+ // compute our bounds
+ x1 = 0.5f - 0.5f * maxwidth;
+ x2 = x1 + maxwidth;
+ y1 = origy2 + UI_BOX_TB_BORDER;
+ y2 = origy2 + bottom;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, color);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // is favorite? draw the star
+ if (isstar)
+ draw_star(x1, y1);
+
+ // draw all lines
+ for (auto & elem : tempbuf)
+ {
+ mui.draw_text_full(container, elem.c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, text_size);
+ y1 += mui.get_line_height();
+ }
+}
+
+//-------------------------------------------------
+// force the game select menu to be visible
+// and inescapable
+//-------------------------------------------------
+
+void ui_menu_select_game::force_game_select(running_machine &machine, render_container *container)
+{
+ // reset the menu stack
+ ui_menu::stack_reset(machine);
+
+ // add the quit entry followed by the game select entry
+ ui_menu *quit = global_alloc_clear<ui_menu_quit_game>(machine, container);
+ quit->set_special_main_menu(true);
+ ui_menu::stack_push(quit);
+ ui_menu::stack_push(global_alloc_clear<ui_menu_select_game>(machine, container, nullptr));
+
+ // force the menus on
+ mame_machine_manager::instance()->ui().show_menu();
+
+ // make sure MAME is paused
+ machine.pause();
+}
+
+//-------------------------------------------------
+// handle select key event
+//-------------------------------------------------
+
+void ui_menu_select_game::inkey_select(const ui_menu_event *m_event)
+{
+ const game_driver *driver = (const game_driver *)m_event->itemref;
+
+ // special case for configure options
+ if ((FPTR)driver == CONF_OPTS)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_game_options>(machine(), container));
+
+ // special case for configure machine
+ else if ((FPTR)driver == CONF_MACHINE)
+ {
+ if (m_prev_selected != nullptr)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_machine_configure>(machine(), container, (const game_driver *)m_prev_selected));
+ else
+ return;
+ }
+
+ // special case for configure plugins
+ else if ((FPTR)driver == CONF_PLUGINS)
+ {
+ ui_menu::stack_push(global_alloc_clear<ui_menu_plugins_configure>(machine(), container));
+ }
+ // anything else is a driver
+ else
+ {
+ // audit the game first to see if we're going to work
+ driver_enumerator enumerator(machine().options(), *driver);
+ enumerator.next();
+ media_auditor auditor(enumerator);
+ media_auditor::summary summary = auditor.audit_media(AUDIT_VALIDATE_FAST);
+
+ // if everything looks good, schedule the new driver
+ if (summary == media_auditor::CORRECT || summary == media_auditor::BEST_AVAILABLE || summary == media_auditor::NONE_NEEDED)
+ {
+ if ((driver->flags & MACHINE_TYPE_ARCADE) == 0)
+ {
+ for (software_list_device &swlistdev : software_list_device_iterator(enumerator.config().root_device()))
+ if (!swlistdev.get_info().empty())
+ {
+ ui_menu::stack_push(global_alloc_clear<ui_menu_select_software>(machine(), container, driver));
+ return;
+ }
+ }
+
+ s_bios biosname;
+ if (!mame_machine_manager::instance()->ui().options().skip_bios_menu() && has_multiple_bios(driver, biosname))
+ ui_menu::stack_push(global_alloc_clear<ui_bios_selection>(machine(), container, biosname, (void *)driver, false, false));
+ else
+ {
+ reselect_last::driver = driver->name;
+ reselect_last::software.clear();
+ reselect_last::swlist.clear();
+ mame_machine_manager::instance()->schedule_new_driver(*driver);
+ machine().schedule_hard_reset();
+ ui_menu::stack_reset(machine());
+ }
+ }
+ // otherwise, display an error
+ else
+ {
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ ui_error = true;
+ }
+ }
+}
+
+//-------------------------------------------------
+// handle select key event for favorites menu
+//-------------------------------------------------
+
+void ui_menu_select_game::inkey_select_favorite(const ui_menu_event *m_event)
+{
+ ui_software_info *ui_swinfo = (ui_software_info *)m_event->itemref;
+ ui_options &mopt = mame_machine_manager::instance()->ui().options();
+
+ // special case for configure options
+ if ((FPTR)ui_swinfo == CONF_OPTS)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_game_options>(machine(), container));
+ /* special case for configure machine TODO
+ else if ((FPTR)ui_swinfo == CONF_MACHINE)
+ {
+ if (m_prev_selected != nullptr)
+ {
+ ui_software_info *swinfo = (ui_software_info *)m_prev_selected;
+ if (swinfo->startempty == 1)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_machine_configure>(machine(), container, swinfo->driver));
+ }
+ else
+ return;
+ } */
+ // special case for configure plugins
+ else if ((FPTR)ui_swinfo == CONF_PLUGINS)
+ {
+ ui_menu::stack_push(global_alloc_clear<ui_menu_plugins_configure>(machine(), container));
+ }
+ else if (ui_swinfo->startempty == 1)
+ {
+ // audit the game first to see if we're going to work
+ driver_enumerator enumerator(machine().options(), *ui_swinfo->driver);
+ enumerator.next();
+ media_auditor auditor(enumerator);
+ media_auditor::summary summary = auditor.audit_media(AUDIT_VALIDATE_FAST);
+
+ // if everything looks good, schedule the new driver
+ if (summary == media_auditor::CORRECT || summary == media_auditor::BEST_AVAILABLE || summary == media_auditor::NONE_NEEDED)
+ {
+ s_bios biosname;
+ if (!mopt.skip_bios_menu() && has_multiple_bios(ui_swinfo->driver, biosname))
+ ui_menu::stack_push(global_alloc_clear<ui_bios_selection>(machine(), container, biosname, (void *)ui_swinfo->driver, false, false));
+ else
+ {
+ reselect_last::driver = ui_swinfo->driver->name;
+ reselect_last::software.clear();
+ reselect_last::swlist.clear();
+ reselect_last::set(true);
+ mame_machine_manager::instance()->schedule_new_driver(*ui_swinfo->driver);
+ machine().schedule_hard_reset();
+ ui_menu::stack_reset(machine());
+ }
+ }
+
+ // otherwise, display an error
+ else
+ {
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ ui_error = true;
+ }
+ }
+ else
+ {
+ // first validate
+ driver_enumerator drv(machine().options(), *ui_swinfo->driver);
+ media_auditor auditor(drv);
+ drv.next();
+ software_list_device *swlist = software_list_device::find_by_name(drv.config(), ui_swinfo->listname.c_str());
+ software_info *swinfo = swlist->find(ui_swinfo->shortname.c_str());
+ media_auditor::summary summary = auditor.audit_software(swlist->list_name(), swinfo, AUDIT_VALIDATE_FAST);
+ if (summary == media_auditor::CORRECT || summary == media_auditor::BEST_AVAILABLE || summary == media_auditor::NONE_NEEDED)
+ {
+ s_bios biosname;
+ if (!mopt.skip_bios_menu() && has_multiple_bios(ui_swinfo->driver, biosname))
+ {
+ ui_menu::stack_push(global_alloc_clear<ui_bios_selection>(machine(), container, biosname, (void *)ui_swinfo, true, false));
+ return;
+ }
+ else if (!mopt.skip_parts_menu() && swinfo->has_multiple_parts(ui_swinfo->interface.c_str()))
+ {
+ s_parts parts;
+ for (const software_part &swpart : swinfo->parts())
+ {
+ if (swpart.matches_interface(ui_swinfo->interface.c_str()))
+ {
+ std::string menu_part_name(swpart.name());
+ if (swpart.feature("part_id") != nullptr)
+ menu_part_name.assign("(").append(swpart.feature("part_id")).append(")");
+ parts.emplace(swpart.name(), menu_part_name);
+ }
+ }
+ ui_menu::stack_push(global_alloc_clear<ui_software_parts>(machine(), container, parts, ui_swinfo));
+ return;
+ }
+
+ std::string error_string;
+ std::string string_list = std::string(ui_swinfo->listname).append(":").append(ui_swinfo->shortname).append(":").append(ui_swinfo->part).append(":").append(ui_swinfo->instance);
+ mopt.set_value(OPTION_SOFTWARENAME, string_list.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
+ std::string snap_list = std::string(ui_swinfo->listname).append(PATH_SEPARATOR).append(ui_swinfo->shortname);
+ mopt.set_value(OPTION_SNAPNAME, snap_list.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
+ reselect_last::driver = drv.driver().name;
+ reselect_last::software = ui_swinfo->shortname;
+ reselect_last::swlist = ui_swinfo->listname;
+ mame_machine_manager::instance()->schedule_new_driver(drv.driver());
+ machine().schedule_hard_reset();
+ ui_menu::stack_reset(machine());
+ }
+ // otherwise, display an error
+ else
+ {
+ reset(UI_MENU_RESET_REMEMBER_POSITION);
+ ui_error = true;
+ }
+ }
+}
+
+//-------------------------------------------------
+// returns if the search can be activated
+//-------------------------------------------------
+
+inline bool ui_menu_select_game::isfavorite()
+{
+ return (main_filters::actual == FILTER_FAVORITE);
+}
+
+//-------------------------------------------------
+// handle special key event
+//-------------------------------------------------
+
+void ui_menu_select_game::inkey_special(const ui_menu_event *m_event)
+{
+ int buflen = strlen(m_search);
+
+ // if it's a backspace and we can handle it, do so
+ if (((m_event->unichar == 8 || m_event->unichar == 0x7f) && buflen > 0) && !isfavorite())
+ {
+ *(char *)utf8_previous_char(&m_search[buflen]) = 0;
+ reset(UI_MENU_RESET_SELECT_FIRST);
+ }
+ else if ((m_event->unichar >= ' ' && m_event->unichar < 0x7f) && !isfavorite())
+ {
+ // if it's any other key and we're not maxed out, update
+ buflen += utf8_from_uchar(&m_search[buflen], ARRAY_LENGTH(m_search) - buflen, m_event->unichar);
+ m_search[buflen] = 0;
+ reset(UI_MENU_RESET_SELECT_FIRST);
+ }
+}
+
+
+void ui_menu_select_game::inkey_configure(const ui_menu_event *m_event)
+{
+ if (selected <= visible_items && m_focus == focused_menu::main)
+ {
+ m_prev_selected = item[selected].ref;
+ selected = visible_items + 1;
+ }
+ else if (selected > visible_items && m_focus == focused_menu::main)
+ {
+ if (ui_globals::panels_status != HIDE_LEFT_PANEL)
+ m_focus = focused_menu::left;
+
+ else if (ui_globals::panels_status == HIDE_BOTH)
+ {
+ for (int x = 0; x < item.size(); ++x)
+ if (item[x].ref == m_prev_selected)
+ selected = x;
+ }
+ else
+ m_focus = focused_menu::righttop;
+ }
+ else if (m_focus == focused_menu::left)
+ {
+ if (ui_globals::panels_status != HIDE_RIGHT_PANEL)
+ m_focus = focused_menu::righttop;
+ else
+ {
+ m_focus = focused_menu::main;
+ if (m_prev_selected == nullptr)
+ {
+ selected = 0;
+ return;
+ }
+
+ for (int x = 0; x < item.size(); ++x)
+ if (item[x].ref == m_prev_selected)
+ selected = x;
+ }
+ }
+ else if (m_focus == focused_menu::righttop)
+ m_focus = focused_menu::rightbottom;
+ else if (m_focus == focused_menu::rightbottom)
+ {
+ m_focus = focused_menu::main;
+ if (m_prev_selected == nullptr)
+ {
+ selected = 0;
+ return;
+ }
+
+ for (int x = 0; x < item.size(); ++x)
+ if (item[x].ref == m_prev_selected)
+ selected = x;
+ }
+}
+
+//-------------------------------------------------
+// build list
+//-------------------------------------------------
+
+void ui_menu_select_game::build_list(const char *filter_text, int filter, bool bioscheck, std::vector<const game_driver *> s_drivers)
+{
+ int cx = 0;
+ bool cloneof = false;
+
+ if (s_drivers.empty())
+ {
+ filter = main_filters::actual;
+ if (filter == FILTER_AVAILABLE)
+ s_drivers = m_availsortedlist;
+ else if (filter == FILTER_UNAVAILABLE)
+ s_drivers = m_unavailsortedlist;
+ else
+ s_drivers = m_sortedlist;
+ }
+
+ for (auto & s_driver : s_drivers)
+ {
+ if (!bioscheck && filter != FILTER_BIOS && (s_driver->flags & MACHINE_IS_BIOS_ROOT) != 0)
+ continue;
+
+ switch (filter)
+ {
+ case FILTER_ALL:
+ case FILTER_AVAILABLE:
+ case FILTER_UNAVAILABLE:
+ m_displaylist.push_back(s_driver);
+ break;
+
+ case FILTER_WORKING:
+ if (!(s_driver->flags & MACHINE_NOT_WORKING))
+ m_displaylist.push_back(s_driver);
+ break;
+
+ case FILTER_NOT_MECHANICAL:
+ if (!(s_driver->flags & MACHINE_MECHANICAL))
+ m_displaylist.push_back(s_driver);
+ break;
+
+ case FILTER_BIOS:
+ if (s_driver->flags & MACHINE_IS_BIOS_ROOT)
+ m_displaylist.push_back(s_driver);
+ break;
+
+ case FILTER_PARENT:
+ case FILTER_CLONES:
+ cloneof = strcmp(s_driver->parent, "0");
+ if (cloneof)
+ {
+ cx = driver_list::find(s_driver->parent);
+ if (cx != -1 && ((driver_list::driver(cx).flags & MACHINE_IS_BIOS_ROOT) != 0))
+ cloneof = false;
+ }
+
+ if (filter == FILTER_CLONES && cloneof)
+ m_displaylist.push_back(s_driver);
+ else if (filter == FILTER_PARENT && !cloneof)
+ m_displaylist.push_back(s_driver);
+ break;
+
+ case FILTER_NOT_WORKING:
+ if (s_driver->flags & MACHINE_NOT_WORKING)
+ m_displaylist.push_back(s_driver);
+ break;
+
+ case FILTER_MECHANICAL:
+ if (s_driver->flags & MACHINE_MECHANICAL)
+ m_displaylist.push_back(s_driver);
+ break;
+
+ case FILTER_SAVE:
+ if (s_driver->flags & MACHINE_SUPPORTS_SAVE)
+ m_displaylist.push_back(s_driver);
+ break;
+
+ case FILTER_NOSAVE:
+ if (!(s_driver->flags & MACHINE_SUPPORTS_SAVE))
+ m_displaylist.push_back(s_driver);
+ break;
+
+ case FILTER_YEAR:
+ if (!core_stricmp(filter_text, s_driver->year))
+ m_displaylist.push_back(s_driver);
+ break;
+
+ case FILTER_VERTICAL:
+ if (s_driver->flags & ORIENTATION_SWAP_XY)
+ m_displaylist.push_back(s_driver);
+ break;
+
+ case FILTER_HORIZONTAL:
+ if (!(s_driver->flags & ORIENTATION_SWAP_XY))
+ m_displaylist.push_back(s_driver);
+ break;
+
+ case FILTER_MANUFACTURER:
+ {
+ std::string name = c_mnfct::getname(s_driver->manufacturer);
+ if (!core_stricmp(filter_text, name.c_str()))
+ m_displaylist.push_back(s_driver);
+ break;
+ }
+ case FILTER_CHD:
+ for (const rom_entry *rom = s_driver->rom; !ROMENTRY_ISEND(rom); ++rom)
+ if (ROMENTRY_ISREGION(rom) && ROMREGION_ISDISKDATA(rom))
+ {
+ m_displaylist.push_back(s_driver);
+ break;
+ }
+ break;
+ case FILTER_NOCHD:
+ {
+ bool found = false;
+ for (const rom_entry *rom = s_driver->rom; !ROMENTRY_ISEND(rom); ++rom)
+ if (ROMENTRY_ISREGION(rom) && ROMREGION_ISDISKDATA(rom))
+ {
+ found = true;
+ break;
+ }
+ if (!found)
+ m_displaylist.push_back(s_driver);
+ break;
+ }
+ }
+ }
+}
+
+//-------------------------------------------------
+// build custom display list
+//-------------------------------------------------
+
+void ui_menu_select_game::build_custom()
+{
+ std::vector<const game_driver *> s_drivers;
+ bool bioscheck = false;
+
+ if (custfltr::main == FILTER_AVAILABLE)
+ s_drivers = m_availsortedlist;
+ else if (custfltr::main == FILTER_UNAVAILABLE)
+ s_drivers = m_unavailsortedlist;
+ else
+ s_drivers = m_sortedlist;
+
+ for (auto & elem : s_drivers)
+ {
+ m_displaylist.push_back(elem);
+ }
+
+ for (int count = 1; count <= custfltr::numother; ++count)
+ {
+ int filter = custfltr::other[count];
+ if (filter == FILTER_BIOS)
+ bioscheck = true;
+ }
+
+ for (int count = 1; count <= custfltr::numother; ++count)
+ {
+ int filter = custfltr::other[count];
+ s_drivers = m_displaylist;
+ m_displaylist.clear();
+
+ switch (filter)
+ {
+ case FILTER_YEAR:
+ build_list(c_year::ui[custfltr::year[count]].c_str(), filter, bioscheck, s_drivers);
+ break;
+ case FILTER_MANUFACTURER:
+ build_list(c_mnfct::ui[custfltr::mnfct[count]].c_str(), filter, bioscheck, s_drivers);
+ break;
+ default:
+ build_list(nullptr, filter, bioscheck, s_drivers);
+ break;
+ }
+ }
+}
+
+//-------------------------------------------------
+// build category list
+//-------------------------------------------------
+
+void ui_menu_select_game::build_category()
+{
+ m_displaylist.clear();
+ std::vector<int> temp_filter;
+ mame_machine_manager::instance()->inifile().load_ini_category(temp_filter);
+
+ for (auto actual : temp_filter)
+ m_displaylist.push_back(&driver_list::driver(actual));
+
+ std::stable_sort(m_displaylist.begin(), m_displaylist.end(), sorted_game_list);
+}
+
+//-------------------------------------------------
+// populate search list
+//-------------------------------------------------
+
+void ui_menu_select_game::populate_search()
+{
+ // allocate memory to track the penalty value
+ std::vector<int> penalty(VISIBLE_GAMES_IN_SEARCH, 9999);
+ int index = 0;
+ for (; index < m_displaylist.size(); ++index)
+ {
+ // pick the best match between driver name and description
+ int curpenalty = fuzzy_substring(m_search, m_displaylist[index]->description);
+ int tmp = fuzzy_substring(m_search, m_displaylist[index]->name);
+ curpenalty = MIN(curpenalty, tmp);
+
+ // insert into the sorted table of matches
+ for (int matchnum = VISIBLE_GAMES_IN_SEARCH - 1; matchnum >= 0; --matchnum)
+ {
+ // stop if we're worse than the current entry
+ if (curpenalty >= penalty[matchnum])
+ break;
+
+ // as long as this isn't the last entry, bump this one down
+ if (matchnum < VISIBLE_GAMES_IN_SEARCH - 1)
+ {
+ penalty[matchnum + 1] = penalty[matchnum];
+ m_searchlist[matchnum + 1] = m_searchlist[matchnum];
+ }
+
+ m_searchlist[matchnum] = m_displaylist[index];
+ penalty[matchnum] = curpenalty;
+ }
+ }
+
+ (index < VISIBLE_GAMES_IN_SEARCH) ? m_searchlist[index] = nullptr : m_searchlist[VISIBLE_GAMES_IN_SEARCH] = nullptr;
+ UINT32 flags_ui = MENU_FLAG_UI | MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW;
+ for (int curitem = 0; m_searchlist[curitem]; ++curitem)
+ {
+ bool cloneof = strcmp(m_searchlist[curitem]->parent, "0");
+ if (cloneof)
+ {
+ int cx = driver_list::find(m_searchlist[curitem]->parent);
+ if (cx != -1 && ((driver_list::driver(cx).flags & MACHINE_IS_BIOS_ROOT) != 0))
+ cloneof = false;
+ }
+ item_append(m_searchlist[curitem]->description, nullptr, (!cloneof) ? flags_ui : (MENU_FLAG_INVERT | flags_ui),
+ (void *)m_searchlist[curitem]);
+ }
+}
+
+//-------------------------------------------------
+// generate general info
+//-------------------------------------------------
+
+void ui_menu_select_game::general_info(const game_driver *driver, std::string &buffer)
+{
+ std::ostringstream str;
+
+ util::stream_format(str, _("Romset: %1$-.100s\n"), driver->name);
+ util::stream_format(str, _("Year: %1$s\n"), driver->year);
+ util::stream_format(str, _("Manufacturer: %1$-.100s\n"), driver->manufacturer);
+
+ int cloneof = driver_list::non_bios_clone(*driver);
+ if (cloneof != -1)
+ util::stream_format(str, _("Driver is Clone of: %1$-.100s\n"), driver_list::driver(cloneof).description);
+ else
+ str << _("Driver is Parent\n");
+
+ if (driver->flags & MACHINE_NOT_WORKING)
+ str << _("Overall: NOT WORKING\n");
+ else if (driver->flags & MACHINE_UNEMULATED_PROTECTION)
+ str << _("Overall: Unemulated Protection\n");
+ else
+ str << _("Overall: Working\n");
+
+ if (driver->flags & MACHINE_IMPERFECT_COLORS)
+ str << _("Graphics: Imperfect Colors\n");
+ else if (driver->flags & MACHINE_WRONG_COLORS)
+ str << ("Graphics: Wrong Colors\n");
+ else if (driver->flags & MACHINE_IMPERFECT_GRAPHICS)
+ str << _("Graphics: Imperfect\n");
+ else
+ str << _("Graphics: OK\n");
+
+ if (driver->flags & MACHINE_NO_SOUND)
+ str << _("Sound: Unimplemented\n");
+ else if (driver->flags & MACHINE_IMPERFECT_SOUND)
+ str << _("Sound: Imperfect\n");
+ else
+ str << _("Sound: OK\n");
+
+ util::stream_format(str, _("Driver is Skeleton: %1$s\n"), ((driver->flags & MACHINE_IS_SKELETON) ? _("Yes") : _("No")));
+ util::stream_format(str, _("Game is Mechanical: %1$s\n"), ((driver->flags & MACHINE_MECHANICAL) ? _("Yes") : _("No")));
+ util::stream_format(str, _("Requires Artwork: %1$s\n"), ((driver->flags & MACHINE_REQUIRES_ARTWORK) ? _("Yes") : _("No")));
+ util::stream_format(str, _("Requires Clickable Artwork: %1$s\n"), ((driver->flags & MACHINE_CLICKABLE_ARTWORK) ? _("Yes") : _("No")));
+ util::stream_format(str, _("Support Cocktail: %1$s\n"), ((driver->flags & MACHINE_NO_COCKTAIL) ? _("Yes") : _("No")));
+ util::stream_format(str, _("Driver is Bios: %1$s\n"), ((driver->flags & MACHINE_IS_BIOS_ROOT) ? _("Yes") : _("No")));
+ util::stream_format(str, _("Support Save: %1$s\n"), ((driver->flags & MACHINE_SUPPORTS_SAVE) ? _("Yes") : _("No")));
+ util::stream_format(str, _("Screen Orientation: %1$s\n"), ((driver->flags & ORIENTATION_SWAP_XY) ? _("Vertical") : _("Horizontal")));
+ bool found = false;
+ for (const rom_entry *rom = driver->rom; !ROMENTRY_ISEND(rom); ++rom)
+ if (ROMENTRY_ISREGION(rom) && ROMREGION_ISDISKDATA(rom))
+ {
+ found = true;
+ break;
+ }
+ util::stream_format(str, _("Requires CHD: %1$s\n"), found ? _("Yes") : _("No"));
+
+ // audit the game first to see if we're going to work
+ if (mame_machine_manager::instance()->ui().options().info_audit())
+ {
+ driver_enumerator enumerator(machine().options(), *driver);
+ enumerator.next();
+ media_auditor auditor(enumerator);
+ media_auditor::summary summary = auditor.audit_media(AUDIT_VALIDATE_FAST);
+ media_auditor::summary summary_samples = auditor.audit_samples();
+
+ // if everything looks good, schedule the new driver
+ if (summary == media_auditor::CORRECT || summary == media_auditor::BEST_AVAILABLE || summary == media_auditor::NONE_NEEDED)
+ str << _("Roms Audit Pass: OK\n");
+ else
+ str << _("Roms Audit Pass: BAD\n");
+
+ if (summary_samples == media_auditor::NONE_NEEDED)
+ str << _("Samples Audit Pass: None Needed\n");
+ else if (summary_samples == media_auditor::CORRECT || summary_samples == media_auditor::BEST_AVAILABLE)
+ str << _("Samples Audit Pass: OK\n");
+ else
+ str << _("Samples Audit Pass: BAD\n");
+ }
+ else
+ str << _("Roms Audit Pass: Disabled\nSamples Audit Pass: Disabled\n");
+
+ buffer = str.str();
+}
+
+void ui_menu_select_game::inkey_export()
+{
+ std::vector<const game_driver *> list;
+ if (m_search[0] != 0)
+ {
+ for (int curitem = 0; m_searchlist[curitem]; ++curitem)
+ {
+ list.push_back(m_searchlist[curitem]);
+ }
+ }
+ else
+ {
+ list = m_displaylist;
+ }
+ ui_menu::stack_push(global_alloc_clear<ui_menu_export>(machine(), container, list));
+}
+
+//-------------------------------------------------
+// save drivers infos to file
+//-------------------------------------------------
+
+void ui_menu_select_game::init_sorted_list()
+{
+ if (!m_sortedlist.empty())
+ return;
+
+ // generate full list
+ for (int x = 0; x < driver_list::total(); ++x)
+ {
+ const game_driver *driver = &driver_list::driver(x);
+ if (driver == &GAME_NAME(___empty))
+ continue;
+ if (driver->flags & MACHINE_IS_BIOS_ROOT)
+ m_isabios++;
+
+ m_sortedlist.push_back(driver);
+ c_mnfct::set(driver->manufacturer);
+ c_year::set(driver->year);
+ }
+
+ // sort manufacturers - years and driver
+ std::stable_sort(c_mnfct::ui.begin(), c_mnfct::ui.end());
+ std::stable_sort(c_year::ui.begin(), c_year::ui.end());
+ std::stable_sort(m_sortedlist.begin(), m_sortedlist.end(), sorted_game_list);
+}
+
+//-------------------------------------------------
+// load drivers infos from file
+//-------------------------------------------------
+
+bool ui_menu_select_game::load_available_machines()
+{
+ // try to load available drivers from file
+ emu_file file(mame_machine_manager::instance()->ui().options().ui_path(), OPEN_FLAG_READ);
+ if (file.open(emulator_info::get_configname(), "_avail.ini") != osd_file::error::NONE)
+ return false;
+
+ std::string readbuf;
+ char rbuf[MAX_CHAR_INFO];
+ file.gets(rbuf, MAX_CHAR_INFO);
+ file.gets(rbuf, MAX_CHAR_INFO);
+ readbuf = chartrimcarriage(rbuf);
+ std::string a_rev = std::string(UI_VERSION_TAG).append(bare_build_version);
+
+ // version not matching ? exit
+ if (a_rev != readbuf)
+ {
+ file.close();
+ return false;
+ }
+
+ file.gets(rbuf, MAX_CHAR_INFO);
+ file.gets(rbuf, MAX_CHAR_INFO);
+ int avsize = 0, unavsize = 0;
+ file.gets(rbuf, MAX_CHAR_INFO);
+ avsize = atoi(rbuf);
+ file.gets(rbuf, MAX_CHAR_INFO);
+ unavsize = atoi(rbuf);
+
+ // load available list
+ for (int x = 0; x < avsize; ++x)
+ {
+ file.gets(rbuf, MAX_CHAR_INFO);
+ int find = atoi(rbuf);
+ m_availsortedlist.push_back(&driver_list::driver(find));
+ }
+
+ // load unavailable list
+ for (int x = 0; x < unavsize; ++x)
+ {
+ file.gets(rbuf, MAX_CHAR_INFO);
+ int find = atoi(rbuf);
+ m_unavailsortedlist.push_back(&driver_list::driver(find));
+ }
+ file.close();
+ return true;
+}
+
+//-------------------------------------------------
+// load custom filters info from file
+//-------------------------------------------------
+
+void ui_menu_select_game::load_custom_filters()
+{
+ // attempt to open the output file
+ emu_file file(mame_machine_manager::instance()->ui().options().ui_path(), OPEN_FLAG_READ);
+ if (file.open("custom_", emulator_info::get_configname(), "_filter.ini") == osd_file::error::NONE)
+ {
+ char buffer[MAX_CHAR_INFO];
+
+ // get number of filters
+ file.gets(buffer, MAX_CHAR_INFO);
+ char *pb = strchr(buffer, '=');
+ custfltr::numother = atoi(++pb) - 1;
+
+ // get main filter
+ file.gets(buffer, MAX_CHAR_INFO);
+ pb = strchr(buffer, '=') + 2;
+
+ for (int y = 0; y < main_filters::length; ++y)
+ if (!strncmp(pb, main_filters::text[y], strlen(main_filters::text[y])))
+ {
+ custfltr::main = y;
+ break;
+ }
+
+ for (int x = 1; x <= custfltr::numother; ++x)
+ {
+ file.gets(buffer, MAX_CHAR_INFO);
+ char *cb = strchr(buffer, '=') + 2;
+ for (int y = 0; y < main_filters::length; ++y)
+ if (!strncmp(cb, main_filters::text[y], strlen(main_filters::text[y])))
+ {
+ custfltr::other[x] = y;
+ if (y == FILTER_MANUFACTURER)
+ {
+ file.gets(buffer, MAX_CHAR_INFO);
+ char *ab = strchr(buffer, '=') + 2;
+ for (size_t z = 0; z < c_mnfct::ui.size(); ++z)
+ if (!strncmp(ab, c_mnfct::ui[z].c_str(), c_mnfct::ui[z].length()))
+ custfltr::mnfct[x] = z;
+ }
+ else if (y == FILTER_YEAR)
+ {
+ file.gets(buffer, MAX_CHAR_INFO);
+ char *db = strchr(buffer, '=') + 2;
+ for (size_t z = 0; z < c_year::ui.size(); ++z)
+ if (!strncmp(db, c_year::ui[z].c_str(), c_year::ui[z].length()))
+ custfltr::year[x] = z;
+ }
+ }
+ }
+ file.close();
+ }
+
+}
+
+
+//-------------------------------------------------
+// draw left box
+//-------------------------------------------------
+
+float ui_menu_select_game::draw_left_panel(float x1, float y1, float x2, float y2)
+{
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+ float line_height = mui.get_line_height();
+
+ if (ui_globals::panels_status == SHOW_PANELS || ui_globals::panels_status == HIDE_RIGHT_PANEL)
+ {
+ float origy1 = y1;
+ float origy2 = y2;
+ float text_size = mame_machine_manager::instance()->ui().options().infos_size();
+ float line_height_max = line_height * text_size;
+ float left_width = 0.0f;
+ int text_lenght = main_filters::length;
+ int afilter = main_filters::actual;
+ int phover = HOVER_FILTER_FIRST;
+ const char **text = main_filters::text;
+ float sc = y2 - y1 - (2.0f * UI_BOX_TB_BORDER);
+
+ if ((text_lenght * line_height_max) > sc)
+ {
+ float lm = sc / (text_lenght);
+ text_size = lm / line_height;
+ line_height_max = line_height * text_size;
+ }
+
+ float text_sign = mui.get_string_width("_# ", text_size);
+ for (int x = 0; x < text_lenght; ++x)
+ {
+ float total_width;
+
+ // compute width of left hand side
+ total_width = mui.get_string_width(text[x], text_size);
+ total_width += text_sign;
+
+ // track the maximum
+ if (total_width > left_width)
+ left_width = total_width;
+ }
+
+ x2 = x1 + left_width + 2.0f * UI_BOX_LR_BORDER;
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+ y2 -= UI_BOX_TB_BORDER;
+
+ for (int filter = 0; filter < text_lenght; ++filter)
+ {
+ std::string str(text[filter]);
+ rgb_t bgcolor = UI_TEXT_BG_COLOR;
+ rgb_t fgcolor = UI_TEXT_COLOR;
+
+ if (mouse_hit && x1 <= mouse_x && x2 > mouse_x && y1 <= mouse_y && y1 + line_height_max > mouse_y)
+ {
+ bgcolor = UI_MOUSEOVER_BG_COLOR;
+ fgcolor = UI_MOUSEOVER_COLOR;
+ hover = phover + filter;
+ ui_menu::highlight(container, x1, y1, x2, y1+ line_height_max, bgcolor);
+ }
+
+ if (highlight == filter && m_focus == focused_menu::left)
+ {
+ fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00);
+ bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff);
+ mui.draw_textured_box(container, x1, y1, x2, y1 + line_height_max, bgcolor, rgb_t(255, 43, 43, 43),
+ hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
+ }
+
+ float x1t = x1 + text_sign;
+ if (afilter == FILTER_CUSTOM)
+ {
+ if (filter == custfltr::main)
+ {
+ str.assign("@custom1 ").append(text[filter]);
+ x1t -= text_sign;
+ }
+ else
+ {
+ for (int count = 1; count <= custfltr::numother; ++count)
+ {
+ int cfilter = custfltr::other[count];
+ if (cfilter == filter)
+ {
+ str = string_format("@custom%d %s", count + 1, text[filter]);
+ x1t -= text_sign;
+ break;
+ }
+ }
+ }
+ convert_command_glyph(str);
+ }
+ else if (filter == main_filters::actual)
+ {
+ str.assign("_> ").append(text[filter]);
+ x1t -= text_sign;
+ convert_command_glyph(str);
+ }
+
+ mui.draw_text_full(container, str.c_str(), x1t, y1, x2 - x1, JUSTIFY_LEFT, WRAP_NEVER,
+ DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr, text_size);
+ y1 += line_height_max;
+ }
+
+ x1 = x2 + UI_BOX_LR_BORDER;
+ x2 = x1 + 2.0f * UI_BOX_LR_BORDER;
+ y1 = origy1;
+ y2 = origy2;
+ float space = x2 - x1;
+ float lr_arrow_width = 0.4f * space * machine().render().ui_aspect();
+ rgb_t fgcolor = UI_TEXT_COLOR;
+
+ // set left-right arrows dimension
+ float ar_x0 = 0.5f * (x2 + x1) - 0.5f * lr_arrow_width;
+ float ar_y0 = 0.5f * (y2 + y1) + 0.1f * space;
+ float ar_x1 = ar_x0 + lr_arrow_width;
+ float ar_y1 = 0.5f * (y2 + y1) + 0.9f * space;
+
+ mui.draw_outlined_box(container, x1, y1, x2, y2, rgb_t(0xEF, 0x12, 0x47, 0x7B));
+
+ if (mouse_hit && x1 <= mouse_x && x2 > mouse_x && y1 <= mouse_y && y2 > mouse_y)
+ {
+ fgcolor = UI_MOUSEOVER_COLOR;
+ hover = HOVER_LPANEL_ARROW;
+ }
+
+ draw_arrow(container, ar_x0, ar_y0, ar_x1, ar_y1, fgcolor, ROT90 ^ ORIENTATION_FLIP_X);
+ return x2 + UI_BOX_LR_BORDER;
+ }
+ else
+ {
+ float space = x2 - x1;
+ float lr_arrow_width = 0.4f * space * machine().render().ui_aspect();
+ rgb_t fgcolor = UI_TEXT_COLOR;
+
+ // set left-right arrows dimension
+ float ar_x0 = 0.5f * (x2 + x1) - 0.5f * lr_arrow_width;
+ float ar_y0 = 0.5f * (y2 + y1) + 0.1f * space;
+ float ar_x1 = ar_x0 + lr_arrow_width;
+ float ar_y1 = 0.5f * (y2 + y1) + 0.9f * space;
+
+ mui.draw_outlined_box(container, x1, y1, x2, y2, rgb_t(0xEF, 0x12, 0x47, 0x7B));
+
+ if (mouse_hit && x1 <= mouse_x && x2 > mouse_x && y1 <= mouse_y && y2 > mouse_y)
+ {
+ fgcolor = UI_MOUSEOVER_COLOR;
+ hover = HOVER_LPANEL_ARROW;
+ }
+
+ draw_arrow(container, ar_x0, ar_y0, ar_x1, ar_y1, fgcolor, ROT90);
+ return x2 + UI_BOX_LR_BORDER;
+ }
+}
+
+//-------------------------------------------------
+// draw infos
+//-------------------------------------------------
+
+void ui_menu_select_game::infos_render(void *selectedref, float origx1, float origy1, float origx2, float origy2)
+{
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+ float line_height = mui.get_line_height();
+ static std::string buffer;
+ std::vector<int> xstart;
+ std::vector<int> xend;
+ float text_size = mame_machine_manager::instance()->ui().options().infos_size();
+ const game_driver *driver = nullptr;
+ ui_software_info *soft = nullptr;
+ bool is_favorites = ((item[0].flags & MENU_FLAG_UI_FAVORITE) != 0);
+ static ui_software_info *oldsoft = nullptr;
+ static const game_driver *olddriver = nullptr;
+ static int oldview = -1;
+ static int old_sw_view = -1;
+
+ if (is_favorites)
+ {
+ soft = ((FPTR)selectedref > skip_main_items) ? (ui_software_info *)selectedref : ((m_prev_selected != nullptr) ? (ui_software_info *)m_prev_selected : nullptr);
+ if (soft && soft->startempty == 1)
+ {
+ driver = soft->driver;
+ oldsoft = nullptr;
+ }
+ else
+ olddriver = nullptr;
+ }
+ else
+ {
+ driver = ((FPTR)selectedref > skip_main_items) ? (const game_driver *)selectedref : ((m_prev_selected != nullptr) ? (const game_driver *)m_prev_selected : nullptr);
+ oldsoft = nullptr;
+ }
+
+ if (driver)
+ {
+ float gutter_width = 0.4f * line_height * machine().render().ui_aspect() * 1.3f;
+ float ud_arrow_width = line_height * machine().render().ui_aspect();
+ float oy1 = origy1 + line_height;
+
+ // MAMESCORE? Full size text
+ if (ui_globals::curdats_view == UI_STORY_LOAD)
+ text_size = 1.0f;
+
+ std::string snaptext(_(dats_info[ui_globals::curdats_view]));
+
+ // apply title to right panel
+ float title_size = 0.0f;
+ float txt_length = 0.0f;
+
+ for (int x = UI_FIRST_LOAD; x < UI_LAST_LOAD; ++x)
+ {
+ mui.draw_text_full(container, _(dats_info[x]), origx1, origy1, origx2 - origx1, JUSTIFY_CENTER,
+ WRAP_NEVER, DRAW_NONE, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, &txt_length, nullptr);
+ txt_length += 0.01f;
+ title_size = (std::max)(txt_length, title_size);
+ }
+
+ rgb_t fgcolor = UI_TEXT_COLOR;
+ rgb_t bgcolor = UI_TEXT_BG_COLOR;
+ if (m_focus == focused_menu::rightbottom)
+ {
+ fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00);
+ bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff);
+ }
+
+ float middle = origx2 - origx1;
+
+ // check size
+ float sc = title_size + 2.0f * gutter_width;
+ float tmp_size = (sc > middle) ? ((middle - 2.0f * gutter_width) / sc) : 1.0f;
+ title_size *= tmp_size;
+
+ if (bgcolor != UI_TEXT_BG_COLOR)
+ mui.draw_textured_box(container, origx1 + ((middle - title_size) * 0.5f), origy1, origx1 + ((middle + title_size) * 0.5f),
+ origy1 + line_height, bgcolor, rgb_t(255, 43, 43, 43), hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
+
+ mui.draw_text_full(container, snaptext.c_str(), origx1, origy1, origx2 - origx1, JUSTIFY_CENTER,
+ WRAP_NEVER, DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr, tmp_size);
+
+ draw_common_arrow(origx1, origy1, origx2, origy2, ui_globals::curdats_view, UI_FIRST_LOAD, UI_LAST_LOAD, title_size);
+
+ if (driver != olddriver || ui_globals::curdats_view != oldview)
+ {
+ buffer.clear();
+ olddriver = driver;
+ oldview = ui_globals::curdats_view;
+ topline_datsview = 0;
+ totallines = 0;
+ std::vector<std::string> m_item;
+
+ if (ui_globals::curdats_view == UI_GENERAL_LOAD)
+ general_info(driver, buffer);
+ else if (ui_globals::curdats_view != UI_COMMAND_LOAD)
+ mame_machine_manager::instance()->datfile().load_data_info(driver, buffer, ui_globals::curdats_view);
+ else
+ mame_machine_manager::instance()->datfile().command_sub_menu(driver, m_item);
+
+ if (!m_item.empty() && ui_globals::curdats_view == UI_COMMAND_LOAD)
+ {
+ for (size_t x = 0; x < m_item.size(); ++x)
+ {
+ std::string t_buffer;
+ buffer.append(m_item[x]).append("\n");
+ mame_machine_manager::instance()->datfile().load_command_info(t_buffer, m_item[x]);
+ if (!t_buffer.empty())
+ buffer.append(t_buffer).append("\n");
+ }
+ convert_command_glyph(buffer);
+ }
+ }
+
+ if (buffer.empty())
+ {
+ mui.draw_text_full(container, _("No Infos Available"), origx1, (origy2 + origy1) * 0.5f, origx2 - origx1, JUSTIFY_CENTER,
+ WRAP_WORD, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+ return;
+ }
+ else if (ui_globals::curdats_view != UI_STORY_LOAD && ui_globals::curdats_view != UI_COMMAND_LOAD)
+ totallines = mui.wrap_text(container, buffer.c_str(), origx1, origy1, origx2 - origx1 - (2.0f * gutter_width), xstart, xend, text_size);
+ else
+ totallines = mui.wrap_text(container, buffer.c_str(), 0.0f, 0.0f, 1.0f - (2.0f * gutter_width), xstart, xend, text_size);
+
+ int r_visible_lines = floor((origy2 - oy1) / (line_height * text_size));
+ if (totallines < r_visible_lines)
+ r_visible_lines = totallines;
+ if (topline_datsview < 0)
+ topline_datsview = 0;
+ if (topline_datsview + r_visible_lines >= totallines)
+ topline_datsview = totallines - r_visible_lines;
+
+ sc = origx2 - origx1 - (2.0f * UI_BOX_LR_BORDER);
+ for (int r = 0; r < r_visible_lines; ++r)
+ {
+ int itemline = r + topline_datsview;
+ std::string tempbuf(buffer.substr(xstart[itemline], xend[itemline] - xstart[itemline]));
+
+ // up arrow
+ if (r == 0 && topline_datsview != 0)
+ info_arrow(0, origx1, origx2, oy1, line_height, text_size, ud_arrow_width);
+ // bottom arrow
+ else if (r == r_visible_lines - 1 && itemline != totallines - 1)
+ info_arrow(1, origx1, origx2, oy1, line_height, text_size, ud_arrow_width);
+ // special case for mamescore
+ else if (ui_globals::curdats_view == UI_STORY_LOAD)
+ {
+ // check size
+ float textlen = mui.get_string_width(tempbuf.c_str(), text_size);
+ float tmp_size = (textlen > sc) ? text_size * (sc / textlen) : text_size;
+
+ size_t last_underscore = tempbuf.find_last_of("_");
+ if (last_underscore == std::string::npos)
+ {
+ mui.draw_text_full(container, tempbuf.c_str(), origx1, oy1, origx2 - origx1, JUSTIFY_CENTER,
+ WRAP_TRUNCATE, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, tmp_size);
+ }
+ else
+ {
+ float effective_width = origx2 - origx1 - gutter_width;
+ float effective_left = origx1 + gutter_width;
+ std::string last_part(tempbuf.substr(last_underscore + 1));
+ std::string first_part(tempbuf.substr(0, tempbuf.find("___")));
+ float item_width;
+
+ mui.draw_text_full(container, first_part.c_str(), effective_left, oy1, effective_width,
+ JUSTIFY_LEFT, WRAP_TRUNCATE, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, &item_width, nullptr, tmp_size);
+
+ mui.draw_text_full(container, last_part.c_str(), effective_left + item_width, oy1,
+ origx2 - origx1 - 2.0f * gutter_width - item_width, JUSTIFY_RIGHT, WRAP_TRUNCATE,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, tmp_size);
+ }
+ }
+
+ // special case for command
+ else if (ui_globals::curdats_view == UI_COMMAND_LOAD || ui_globals::curdats_view == UI_GENERAL_LOAD)
+ {
+ // check size
+ float textlen = mui.get_string_width(tempbuf.c_str(), text_size);
+ float tmp_size = (textlen > sc) ? text_size * (sc / textlen) : text_size;
+
+ int first_dspace = (ui_globals::curdats_view == UI_COMMAND_LOAD) ? tempbuf.find(" ") : tempbuf.find(":");
+ if (first_dspace > 0)
+ {
+ float effective_width = origx2 - origx1 - gutter_width;
+ float effective_left = origx1 + gutter_width;
+ std::string first_part(tempbuf.substr(0, first_dspace));
+ std::string last_part(tempbuf.substr(first_dspace + 1));
+ strtrimspace(last_part);
+ mui.draw_text_full(container, first_part.c_str(), effective_left, oy1, effective_width, JUSTIFY_LEFT,
+ WRAP_TRUNCATE, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, tmp_size);
+
+ mui.draw_text_full(container, last_part.c_str(), effective_left, oy1, origx2 - origx1 - 2.0f * gutter_width,
+ JUSTIFY_RIGHT, WRAP_TRUNCATE, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, tmp_size);
+ }
+ else
+ mui.draw_text_full(container, tempbuf.c_str(), origx1 + gutter_width, oy1, origx2 - origx1, JUSTIFY_LEFT,
+ WRAP_TRUNCATE, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, tmp_size);
+ }
+ else
+ mui.draw_text_full(container, tempbuf.c_str(), origx1 + gutter_width, oy1, origx2 - origx1, JUSTIFY_LEFT,
+ WRAP_TRUNCATE, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, text_size);
+
+ oy1 += (line_height * text_size);
+ }
+
+ // return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow
+ right_visible_lines = r_visible_lines - (topline_datsview != 0) - (topline_datsview + r_visible_lines != totallines);
+ }
+ else if (soft)
+ {
+ float gutter_width = 0.4f * line_height * machine().render().ui_aspect() * 1.3f;
+ float ud_arrow_width = line_height * machine().render().ui_aspect();
+ float oy1 = origy1 + line_height;
+
+ // apply title to right panel
+ if (soft->usage.empty())
+ {
+ mui.draw_text_full(container, _("History"), origx1, origy1, origx2 - origx1, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+ ui_globals::cur_sw_dats_view = 0;
+ }
+ else
+ {
+ float title_size = 0.0f;
+ float txt_length = 0.0f;
+ std::string t_text[2];
+ t_text[0] = _("History");
+ t_text[1] = _("Usage");
+
+ for (auto & elem: t_text)
+ {
+ mui.draw_text_full(container, elem.c_str(), origx1, origy1, origx2 - origx1, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NONE, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, &txt_length, nullptr);
+ txt_length += 0.01f;
+ title_size = (std::max)(txt_length, title_size);
+ }
+
+ rgb_t fgcolor = UI_TEXT_COLOR;
+ rgb_t bgcolor = UI_TEXT_BG_COLOR;
+ if (m_focus == focused_menu::rightbottom)
+ {
+ fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00);
+ bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff);
+ }
+
+ float middle = origx2 - origx1;
+
+ if (bgcolor != UI_TEXT_BG_COLOR)
+ mui.draw_textured_box(container, origx1 + ((middle - title_size) * 0.5f), origy1, origx1 + ((middle + title_size) * 0.5f),
+ origy1 + line_height, bgcolor, rgb_t(255, 43, 43, 43), hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
+
+ mui.draw_text_full(container, t_text[ui_globals::cur_sw_dats_view].c_str(), origx1, origy1, origx2 - origx1,
+ JUSTIFY_CENTER, WRAP_TRUNCATE, DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr);
+
+ draw_common_arrow(origx1, origy1, origx2, origy2, ui_globals::cur_sw_dats_view, 0, 1, title_size);
+ }
+
+ if (oldsoft != soft || old_sw_view != ui_globals::cur_sw_dats_view)
+ {
+ buffer.clear();
+ old_sw_view = ui_globals::cur_sw_dats_view;
+ oldsoft = soft;
+ if (ui_globals::cur_sw_dats_view == 0)
+ {
+ if (soft->startempty == 1)
+ mame_machine_manager::instance()->datfile().load_data_info(soft->driver, buffer, UI_HISTORY_LOAD);
+ else
+ mame_machine_manager::instance()->datfile().load_software_info(soft->listname, buffer, soft->shortname, soft->parentname);
+ }
+ else
+ buffer = soft->usage;
+ }
+
+ if (buffer.empty())
+ {
+ mui.draw_text_full(container, _("No Infos Available"), origx1, (origy2 + origy1) * 0.5f, origx2 - origx1, JUSTIFY_CENTER,
+ WRAP_WORD, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+ return;
+ }
+ else
+ totallines = mui.wrap_text(container, buffer.c_str(), origx1, origy1, origx2 - origx1 - (2.0f * gutter_width), xstart, xend, text_size);
+
+ int r_visible_lines = floor((origy2 - oy1) / (line_height * text_size));
+ if (totallines < r_visible_lines)
+ r_visible_lines = totallines;
+ if (topline_datsview < 0)
+ topline_datsview = 0;
+ if (topline_datsview + r_visible_lines >= totallines)
+ topline_datsview = totallines - r_visible_lines;
+
+ for (int r = 0; r < r_visible_lines; ++r)
+ {
+ int itemline = r + topline_datsview;
+ std::string tempbuf(buffer.substr(xstart[itemline], xend[itemline] - xstart[itemline]));
+
+ // up arrow
+ if (r == 0 && topline_datsview != 0)
+ info_arrow(0, origx1, origx2, oy1, line_height, text_size, ud_arrow_width);
+ // bottom arrow
+ else if (r == r_visible_lines - 1 && itemline != totallines - 1)
+ info_arrow(1, origx1, origx2, oy1, line_height, text_size, ud_arrow_width);
+ else
+ mui.draw_text_full(container, tempbuf.c_str(), origx1 + gutter_width, oy1, origx2 - origx1, JUSTIFY_LEFT,
+ WRAP_TRUNCATE, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, text_size);
+ oy1 += (line_height * text_size);
+ }
+
+ // return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow
+ right_visible_lines = r_visible_lines - (topline_datsview != 0) - (topline_datsview + r_visible_lines != totallines);
+ }
+}
+
+//-------------------------------------------------
+// draw right panel
+//-------------------------------------------------
+
+void ui_menu_select_game::draw_right_panel(void *selectedref, float origx1, float origy1, float origx2, float origy2)
+{
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+ rgb_t fgcolor = UI_TEXT_COLOR;
+ bool hide = (ui_globals::panels_status == HIDE_RIGHT_PANEL || ui_globals::panels_status == HIDE_BOTH);
+ float x2 = (hide) ? origx2 : origx1 + 2.0f * UI_BOX_LR_BORDER;
+ float space = x2 - origx1;
+ float lr_arrow_width = 0.4f * space * machine().render().ui_aspect();
+
+ // set left-right arrows dimension
+ float ar_x0 = 0.5f * (x2 + origx1) - 0.5f * lr_arrow_width;
+ float ar_y0 = 0.5f * (origy2 + origy1) + 0.1f * space;
+ float ar_x1 = ar_x0 + lr_arrow_width;
+ float ar_y1 = 0.5f * (origy2 + origy1) + 0.9f * space;
+
+ mui.draw_outlined_box(container, origx1, origy1, origx2, origy2, rgb_t(0xEF, 0x12, 0x47, 0x7B));
+
+ if (mouse_hit && origx1 <= mouse_x && x2 > mouse_x && origy1 <= mouse_y && origy2 > mouse_y)
+ {
+ fgcolor = UI_MOUSEOVER_COLOR;
+ hover = HOVER_RPANEL_ARROW;
+ }
+
+ if (hide)
+ {
+ draw_arrow(container, ar_x0, ar_y0, ar_x1, ar_y1, fgcolor, ROT90 ^ ORIENTATION_FLIP_X);
+ return;
+ }
+
+ draw_arrow(container, ar_x0, ar_y0, ar_x1, ar_y1, fgcolor, ROT90);
+ origx1 = x2;
+ origy1 = draw_right_box_title(origx1, origy1, origx2, origy2);
+
+ if (ui_globals::rpanel == RP_IMAGES)
+ arts_render(selectedref, origx1, origy1, origx2, origy2);
+ else
+ infos_render(selectedref, origx1, origy1, origx2, origy2);
+}
+
+//-------------------------------------------------
+// perform our special rendering
+//-------------------------------------------------
+
+void ui_menu_select_game::arts_render(void *selectedref, float origx1, float origy1, float origx2, float origy2)
+{
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+ float line_height = mui.get_line_height();
+ bool is_favorites = ((item[0].flags & MENU_FLAG_UI_FAVORITE) != 0);
+ static ui_software_info *oldsoft = nullptr;
+ static const game_driver *olddriver = nullptr;
+ const game_driver *driver = nullptr;
+ ui_software_info *soft = nullptr;
+
+ if (is_favorites)
+ {
+ soft = ((FPTR)selectedref > skip_main_items) ? (ui_software_info *)selectedref : ((m_prev_selected != nullptr) ? (ui_software_info *)m_prev_selected : nullptr);
+ if (soft && soft->startempty == 1)
+ {
+ driver = soft->driver;
+ oldsoft = nullptr;
+ }
+ else
+ olddriver = nullptr;
+ }
+ else
+ {
+ driver = ((FPTR)selectedref > skip_main_items) ? (const game_driver *)selectedref : ((m_prev_selected != nullptr) ? (const game_driver *)m_prev_selected : nullptr);
+ oldsoft = nullptr;
+ }
+
+ if (driver != nullptr)
+ {
+ if (ui_globals::default_image)
+ ((driver->flags & MACHINE_TYPE_ARCADE) == 0) ? ui_globals::curimage_view = CABINETS_VIEW : ui_globals::curimage_view = SNAPSHOT_VIEW;
+
+ std::string searchstr;
+ searchstr = arts_render_common(origx1, origy1, origx2, origy2);
+
+ // loads the image if necessary
+ if (driver != olddriver || !snapx_bitmap->valid() || ui_globals::switch_image)
+ {
+ emu_file snapfile(searchstr.c_str(), OPEN_FLAG_READ);
+ snapfile.set_restrict_to_mediapath(true);
+ bitmap_argb32 *tmp_bitmap;
+ tmp_bitmap = auto_alloc(machine(), bitmap_argb32);
+
+ // try to load snapshot first from saved "0000.png" file
+ std::string fullname(driver->name);
+ render_load_png(*tmp_bitmap, snapfile, fullname.c_str(), "0000.png");
+
+ if (!tmp_bitmap->valid())
+ render_load_jpeg(*tmp_bitmap, snapfile, fullname.c_str(), "0000.jpg");
+
+ // if fail, attemp to load from standard file
+ if (!tmp_bitmap->valid())
+ {
+ fullname.assign(driver->name).append(".png");
+ render_load_png(*tmp_bitmap, snapfile, nullptr, fullname.c_str());
+
+ if (!tmp_bitmap->valid())
+ {
+ fullname.assign(driver->name).append(".jpg");
+ render_load_jpeg(*tmp_bitmap, snapfile, nullptr, fullname.c_str());
+ }
+ }
+
+ // if fail again, attemp to load from parent file
+ if (!tmp_bitmap->valid())
+ {
+ // set clone status
+ bool cloneof = strcmp(driver->parent, "0");
+ if (cloneof)
+ {
+ int cx = driver_list::find(driver->parent);
+ if (cx != -1 && ((driver_list::driver(cx).flags & MACHINE_IS_BIOS_ROOT) != 0))
+ cloneof = false;
+ }
+
+ if (cloneof)
+ {
+ fullname.assign(driver->parent).append(".png");
+ render_load_png(*tmp_bitmap, snapfile, nullptr, fullname.c_str());
+
+ if (!tmp_bitmap->valid())
+ {
+ fullname.assign(driver->parent).append(".jpg");
+ render_load_jpeg(*tmp_bitmap, snapfile, nullptr, fullname.c_str());
+ }
+ }
+ }
+
+ olddriver = driver;
+ ui_globals::switch_image = false;
+ arts_render_images(tmp_bitmap, origx1, origy1, origx2, origy2, false);
+ auto_free(machine(), tmp_bitmap);
+ }
+
+ // if the image is available, loaded and valid, display it
+ if (snapx_bitmap->valid())
+ {
+ float x1 = origx1 + 0.01f;
+ float x2 = origx2 - 0.01f;
+ float y1 = origy1 + UI_BOX_TB_BORDER + line_height;
+ float y2 = origy2 - UI_BOX_TB_BORDER - line_height;
+
+ // apply texture
+ container->add_quad( x1, y1, x2, y2, ARGB_WHITE, snapx_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ }
+ }
+ else if (soft != nullptr)
+ {
+ std::string fullname, pathname;
+
+ if (ui_globals::default_image)
+ (soft->startempty == 0) ? ui_globals::curimage_view = SNAPSHOT_VIEW : ui_globals::curimage_view = CABINETS_VIEW;
+
+ // arts title and searchpath
+ std::string searchstr;
+ searchstr = arts_render_common(origx1, origy1, origx2, origy2);
+
+ // loads the image if necessary
+ if (soft != oldsoft || !snapx_bitmap->valid() || ui_globals::switch_image)
+ {
+ emu_file snapfile(searchstr.c_str(), OPEN_FLAG_READ);
+ bitmap_argb32 *tmp_bitmap;
+ tmp_bitmap = auto_alloc(machine(), bitmap_argb32);
+
+ if (soft->startempty == 1)
+ {
+ // Load driver snapshot
+ fullname.assign(soft->driver->name).append(".png");
+ render_load_png(*tmp_bitmap, snapfile, nullptr, fullname.c_str());
+
+ if (!tmp_bitmap->valid())
+ {
+ fullname.assign(soft->driver->name).append(".jpg");
+ render_load_jpeg(*tmp_bitmap, snapfile, nullptr, fullname.c_str());
+ }
+ }
+ else if (ui_globals::curimage_view == TITLES_VIEW)
+ {
+ // First attempt from name list
+ pathname.assign(soft->listname).append("_titles");
+ fullname.assign(soft->shortname).append(".png");
+ render_load_png(*tmp_bitmap, snapfile, pathname.c_str(), fullname.c_str());
+
+ if (!tmp_bitmap->valid())
+ {
+ fullname.assign(soft->shortname).append(".jpg");
+ render_load_jpeg(*tmp_bitmap, snapfile, pathname.c_str(), fullname.c_str());
+ }
+ }
+ else
+ {
+ // First attempt from name list
+ pathname = soft->listname;
+ fullname.assign(soft->shortname).append(".png");
+ render_load_png(*tmp_bitmap, snapfile, pathname.c_str(), fullname.c_str());
+
+ if (!tmp_bitmap->valid())
+ {
+ fullname.assign(soft->shortname).append(".jpg");
+ render_load_jpeg(*tmp_bitmap, snapfile, pathname.c_str(), fullname.c_str());
+ }
+
+ if (!tmp_bitmap->valid())
+ {
+ // Second attempt from driver name + part name
+ pathname.assign(soft->driver->name).append(soft->part.c_str());
+ fullname.assign(soft->shortname).append(".png");
+ render_load_png(*tmp_bitmap, snapfile, pathname.c_str(), fullname.c_str());
+
+ if (!tmp_bitmap->valid())
+ {
+ fullname.assign(soft->shortname).append(".jpg");
+ render_load_jpeg(*tmp_bitmap, snapfile, pathname.c_str(), fullname.c_str());
+ }
+ }
+ }
+
+ oldsoft = soft;
+ ui_globals::switch_image = false;
+ arts_render_images(tmp_bitmap, origx1, origy1, origx2, origy2, true);
+ auto_free(machine(), tmp_bitmap);
+ }
+
+ // if the image is available, loaded and valid, display it
+ if (snapx_bitmap->valid())
+ {
+ float x1 = origx1 + 0.01f;
+ float x2 = origx2 - 0.01f;
+ float y1 = origy1 + UI_BOX_TB_BORDER + line_height;
+ float y2 = origy2 - UI_BOX_TB_BORDER - line_height;
+
+ // apply texture
+ container->add_quad(x1, y1, x2, y2, ARGB_WHITE, snapx_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ }
+ }
+}
diff --git a/src/frontend/mame/ui/selgame.h b/src/frontend/mame/ui/selgame.h
new file mode 100644
index 00000000000..225e9c2cf3a
--- /dev/null
+++ b/src/frontend/mame/ui/selgame.h
@@ -0,0 +1,85 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/***************************************************************************
+
+ ui/selgame.h
+
+ Main UI menu.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_MAIN_H__
+#define __UI_MAIN_H__
+
+#include "ui/menu.h"
+
+class ui_menu_select_game : public ui_menu
+{
+public:
+ ui_menu_select_game(running_machine &machine, render_container *container, const char *gamename);
+ virtual ~ui_menu_select_game();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+ // force game select menu
+ static void force_game_select(running_machine &machine, render_container *container);
+
+ virtual bool menu_has_search_active() override { return (m_search[0] != 0); }
+
+ // draw left panel
+ virtual float draw_left_panel(float x1, float y1, float x2, float y2) override;
+
+ // draw right panel
+ virtual void draw_right_panel(void *selectedref, float origx1, float origy1, float origx2, float origy2) override;
+
+private:
+ enum
+ {
+ CONF_OPTS = 1,
+ CONF_MACHINE,
+ CONF_PLUGINS,
+ };
+
+ enum { VISIBLE_GAMES_IN_SEARCH = 200 };
+ char m_search[40];
+ static int m_isabios;
+ int highlight;
+
+ static std::vector<const game_driver *> m_sortedlist;
+ std::vector<const game_driver *> m_availsortedlist;
+ std::vector<const game_driver *> m_unavailsortedlist;
+ std::vector<const game_driver *> m_displaylist;
+
+ const game_driver *m_searchlist[VISIBLE_GAMES_IN_SEARCH + 1];
+
+ // internal methods
+ void build_custom();
+ void build_category();
+ void build_available_list();
+ void build_list(const char *filter_text = nullptr, int filter = 0, bool bioscheck = false, std::vector<const game_driver *> vec = {});
+
+ bool isfavorite();
+ void populate_search();
+ void init_sorted_list();
+ bool load_available_machines();
+ void load_custom_filters();
+
+ // General info
+ void general_info(const game_driver *driver, std::string &buffer);
+
+ void arts_render(void *selectedref, float x1, float y1, float x2, float y2);
+ void infos_render(void *selectedref, float x1, float y1, float x2, float y2);
+
+ // handlers
+ void inkey_select(const ui_menu_event *menu_event);
+ void inkey_select_favorite(const ui_menu_event *menu_event);
+ void inkey_special(const ui_menu_event *menu_event);
+ void inkey_export();
+ void inkey_configure(const ui_menu_event *menu_event);
+};
+
+
+#endif /* __UI_MAIN_H__ */
diff --git a/src/frontend/mame/ui/selsoft.cpp b/src/frontend/mame/ui/selsoft.cpp
new file mode 100644
index 00000000000..b9aae4170f3
--- /dev/null
+++ b/src/frontend/mame/ui/selsoft.cpp
@@ -0,0 +1,2148 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/***************************************************************************
+
+ ui/selsoft.cpp
+
+ UI software menu.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "mame.h"
+#include "emuopts.h"
+#include "ui/ui.h"
+#include "ui/menu.h"
+#include "uiinput.h"
+#include "audit.h"
+#include "ui/selsoft.h"
+#include "ui/datmenu.h"
+#include "ui/datfile.h"
+#include "ui/inifile.h"
+#include "ui/selector.h"
+#include "rendfont.h"
+#include "rendutil.h"
+#include "softlist.h"
+
+std::string reselect_last::driver;
+std::string reselect_last::software;
+std::string reselect_last::swlist;
+bool reselect_last::m_reselect = false;
+static const char *region_lists[] = { "arab", "arg", "asia", "aus", "aut", "bel", "blr", "bra", "can", "chi", "chn", "cze", "den",
+ "ecu", "esp", "euro", "fin", "fra", "gbr", "ger", "gre", "hkg", "hun", "irl", "isr",
+ "isv", "ita", "jpn", "kaz", "kor", "lat", "lux", "mex", "ned", "nld", "nor", "nzl",
+ "pol", "rus", "slo", "spa", "sui", "swe", "tha", "tpe", "tw", "uk", "ukr", "usa" };
+
+//-------------------------------------------------
+// compares two items in the software list and
+// sort them by parent-clone
+//-------------------------------------------------
+
+bool compare_software(ui_software_info a, ui_software_info b)
+{
+ ui_software_info *x = &a;
+ ui_software_info *y = &b;
+
+ bool clonex = (x->parentname[0] != '\0');
+ bool cloney = (y->parentname[0] != '\0');
+
+ if (!clonex && !cloney)
+ return (strmakelower(x->longname) < strmakelower(y->longname));
+
+ std::string cx(x->parentlongname), cy(y->parentlongname);
+
+ if (clonex && cx[0] == '\0')
+ clonex = false;
+
+ if (cloney && cy[0] == '\0')
+ cloney = false;
+
+ if (!clonex && !cloney)
+ return (strmakelower(x->longname) < strmakelower(y->longname));
+ else if (clonex && cloney)
+ {
+ if (!core_stricmp(x->parentname.c_str(), y->parentname.c_str()) && !core_stricmp(x->instance.c_str(), y->instance.c_str()))
+ return (strmakelower(x->longname) < strmakelower(y->longname));
+ else
+ return (strmakelower(cx) < strmakelower(cy));
+ }
+ else if (!clonex && cloney)
+ {
+ if (!core_stricmp(x->shortname.c_str(), y->parentname.c_str()) && !core_stricmp(x->instance.c_str(), y->instance.c_str()))
+ return true;
+ else
+ return (strmakelower(x->longname) < strmakelower(cy));
+ }
+ else
+ {
+ if (!core_stricmp(x->parentname.c_str(), y->shortname.c_str()) && !core_stricmp(x->instance.c_str(), y->instance.c_str()))
+ return false;
+ else
+ return (strmakelower(cx) < strmakelower(y->longname));
+ }
+}
+
+//-------------------------------------------------
+// get bios count
+//-------------------------------------------------
+
+bool has_multiple_bios(const game_driver *driver, s_bios &biosname)
+{
+ if (driver->rom == nullptr)
+ return false;
+
+ std::string default_name;
+ for (const rom_entry *rom = driver->rom; !ROMENTRY_ISEND(rom); ++rom)
+ if (ROMENTRY_ISDEFAULT_BIOS(rom))
+ default_name = ROM_GETNAME(rom);
+
+ for (const rom_entry *rom = driver->rom; !ROMENTRY_ISEND(rom); ++rom)
+ {
+ if (ROMENTRY_ISSYSTEM_BIOS(rom))
+ {
+ std::string name(ROM_GETHASHDATA(rom));
+ std::string bname(ROM_GETNAME(rom));
+ int bios_flags = ROM_GETBIOSFLAGS(rom);
+
+ if (bname == default_name)
+ {
+ name.append(_(" (default)"));
+ biosname.emplace(biosname.begin(), name, bios_flags - 1);
+ }
+ else
+ biosname.emplace_back(name, bios_flags - 1);
+ }
+ }
+ return (biosname.size() > 1);
+}
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+ui_menu_select_software::ui_menu_select_software(running_machine &machine, render_container *container, const game_driver *driver) : ui_menu(machine, container)
+{
+ if (reselect_last::get())
+ reselect_last::set(false);
+
+ sw_filters::actual = 0;
+ highlight = 0;
+
+ m_driver = driver;
+ build_software_list();
+ load_sw_custom_filters();
+
+ ui_globals::curimage_view = SNAPSHOT_VIEW;
+ ui_globals::switch_image = true;
+ ui_globals::cur_sw_dats_view = UI_FIRST_LOAD;
+
+ std::string error_string;
+ machine.options().set_value(OPTION_SOFTWARENAME, "", OPTION_PRIORITY_CMDLINE, error_string);
+}
+
+//-------------------------------------------------
+// dtor
+//-------------------------------------------------
+
+ui_menu_select_software::~ui_menu_select_software()
+{
+ ui_globals::curimage_view = CABINETS_VIEW;
+ ui_globals::switch_image = true;
+}
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_menu_select_software::handle()
+{
+ if (m_prev_selected == nullptr)
+ m_prev_selected = item[0].ref;
+
+ bool check_filter = false;
+
+ // ignore pause keys by swallowing them before we process the menu
+ machine().ui_input().pressed(IPT_UI_PAUSE);
+
+ // process the menu
+ const ui_menu_event *m_event = process(UI_MENU_PROCESS_LR_REPEAT);
+
+ if (m_event != nullptr && m_event->itemref != nullptr)
+ {
+ // reset the error on any future m_event
+ if (ui_error)
+ {
+ ui_error = false;
+ machine().ui_input().reset();
+ }
+
+ // handle selections
+ else if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ if (m_focus == focused_menu::main)
+ {
+ inkey_select(m_event);
+ }
+ else if (m_focus == focused_menu::left)
+ {
+ l_sw_hover = highlight;
+ check_filter = true;
+ m_prev_selected = nullptr;
+ }
+ }
+
+ // handle UI_LEFT
+ else if (m_event->iptkey == IPT_UI_LEFT)
+ {
+ // Images
+ if (ui_globals::rpanel == RP_IMAGES && ui_globals::curimage_view > FIRST_VIEW)
+ {
+ ui_globals::curimage_view--;
+ ui_globals::switch_image = true;
+ ui_globals::default_image = false;
+ }
+
+ // Infos
+ else if (ui_globals::rpanel == RP_INFOS && ui_globals::cur_sw_dats_view > 0)
+ {
+ ui_globals::cur_sw_dats_view--;
+ topline_datsview = 0;
+ }
+ }
+
+ // handle UI_RIGHT
+ else if (m_event->iptkey == IPT_UI_RIGHT)
+ {
+ // Images
+ if (ui_globals::rpanel == RP_IMAGES && ui_globals::curimage_view < LAST_VIEW)
+ {
+ ui_globals::curimage_view++;
+ ui_globals::switch_image = true;
+ ui_globals::default_image = false;
+ }
+
+ // Infos
+ else if (ui_globals::rpanel == RP_INFOS && ui_globals::cur_sw_dats_view < 1)
+ {
+ ui_globals::cur_sw_dats_view++;
+ topline_datsview = 0;
+ }
+ }
+
+ // handle UI_UP_FILTER
+ else if (m_event->iptkey == IPT_UI_UP_FILTER && highlight > UI_SW_FIRST)
+ {
+ highlight--;
+ }
+
+ // handle UI_DOWN_FILTER
+ else if (m_event->iptkey == IPT_UI_DOWN_FILTER && highlight < UI_SW_LAST)
+ {
+ highlight++;
+ }
+
+ // handle UI_DATS
+ else if (m_event->iptkey == IPT_UI_DATS && mame_machine_manager::instance()->ui().options().enabled_dats())
+ {
+ ui_software_info *ui_swinfo = (ui_software_info *)m_event->itemref;
+ datfile_manager &mdat = mame_machine_manager::instance()->datfile();
+
+ if (ui_swinfo->startempty == 1 && mdat.has_history(ui_swinfo->driver))
+ ui_menu::stack_push(global_alloc_clear<ui_menu_dats_view>(machine(), container, ui_swinfo->driver));
+ else if (mdat.has_software(ui_swinfo->listname, ui_swinfo->shortname, ui_swinfo->parentname) || !ui_swinfo->usage.empty())
+ ui_menu::stack_push(global_alloc_clear<ui_menu_dats_view>(machine(), container, ui_swinfo));
+ }
+
+ // handle UI_LEFT_PANEL
+ else if (m_event->iptkey == IPT_UI_LEFT_PANEL)
+ ui_globals::rpanel = RP_IMAGES;
+
+ // handle UI_RIGHT_PANEL
+ else if (m_event->iptkey == IPT_UI_RIGHT_PANEL)
+ ui_globals::rpanel = RP_INFOS;
+
+ // escape pressed with non-empty text clears the text
+ else if (m_event->iptkey == IPT_UI_CANCEL && m_search[0] != 0)
+ {
+ m_search[0] = '\0';
+ reset(UI_MENU_RESET_SELECT_FIRST);
+ }
+
+ // handle UI_FAVORITES
+ else if (m_event->iptkey == IPT_UI_FAVORITES)
+ {
+ ui_software_info *swinfo = (ui_software_info *)m_event->itemref;
+
+ if ((FPTR)swinfo > 2)
+ {
+ if (!mame_machine_manager::instance()->favorite().isgame_favorite(*swinfo))
+ {
+ mame_machine_manager::instance()->favorite().add_favorite_game(*swinfo);
+ machine().popmessage(_("%s\n added to favorites list."), swinfo->longname.c_str());
+ }
+
+ else
+ {
+ machine().popmessage(_("%s\n removed from favorites list."), swinfo->longname.c_str());
+ mame_machine_manager::instance()->favorite().remove_favorite_game();
+ }
+ }
+ }
+
+ // typed characters append to the buffer
+ else if (m_event->iptkey == IPT_SPECIAL)
+ inkey_special(m_event);
+
+ else if (m_event->iptkey == IPT_OTHER)
+ {
+ highlight = l_sw_hover;
+ check_filter = true;
+ m_prev_selected = nullptr;
+ }
+
+ else if (m_event->iptkey == IPT_UI_CONFIGURE)
+ inkey_configure(m_event);
+ }
+
+ if (m_event != nullptr && m_event->itemref == nullptr)
+ {
+ if (m_event->iptkey == IPT_UI_CONFIGURE)
+ inkey_configure(m_event);
+
+ // handle UI_LEFT
+ else if (m_event->iptkey == IPT_UI_LEFT)
+ {
+ // Images
+ if (ui_globals::rpanel == RP_IMAGES && ui_globals::curimage_view > FIRST_VIEW)
+ {
+ ui_globals::curimage_view--;
+ ui_globals::switch_image = true;
+ ui_globals::default_image = false;
+ }
+
+ // Infos
+ else if (ui_globals::rpanel == RP_INFOS && ui_globals::cur_sw_dats_view > 0)
+ {
+ ui_globals::cur_sw_dats_view--;
+ topline_datsview = 0;
+ }
+ }
+
+ // handle UI_RIGHT
+ else if (m_event->iptkey == IPT_UI_RIGHT)
+ {
+ // Images
+ if (ui_globals::rpanel == RP_IMAGES && ui_globals::curimage_view < LAST_VIEW)
+ {
+ ui_globals::curimage_view++;
+ ui_globals::switch_image = true;
+ ui_globals::default_image = false;
+ }
+
+ // Infos
+ else if (ui_globals::rpanel == RP_INFOS && ui_globals::cur_sw_dats_view < 1)
+ {
+ ui_globals::cur_sw_dats_view++;
+ topline_datsview = 0;
+ }
+ }
+
+ // handle UI_LEFT_PANEL
+ else if (m_event->iptkey == IPT_UI_LEFT_PANEL)
+ ui_globals::rpanel = RP_IMAGES;
+
+ // handle UI_RIGHT_PANEL
+ else if (m_event->iptkey == IPT_UI_RIGHT_PANEL)
+ ui_globals::rpanel = RP_INFOS;
+
+ // handle UI_UP_FILTER
+ else if (m_event->iptkey == IPT_UI_UP_FILTER && highlight > UI_SW_FIRST)
+ {
+ highlight--;
+ }
+
+ // handle UI_DOWN_FILTER
+ else if (m_event->iptkey == IPT_UI_DOWN_FILTER && highlight < UI_SW_LAST)
+ {
+ highlight++;
+ }
+ else if (m_event->iptkey == IPT_OTHER && m_focus == focused_menu::left)
+ {
+ l_sw_hover = highlight;
+ check_filter = true;
+ m_prev_selected = nullptr;
+ }
+
+ }
+
+ // if we're in an error state, overlay an error message
+ if (ui_error)
+ mame_machine_manager::instance()->ui().draw_text_box(container, _("The selected software is missing one or more required files. "
+ "Please select a different software.\n\nPress any key to continue."),
+ JUSTIFY_CENTER, 0.5f, 0.5f, UI_RED_COLOR);
+
+ // handle filters selection from key shortcuts
+ if (check_filter)
+ {
+ m_search[0] = '\0';
+ switch (l_sw_hover)
+ {
+ case UI_SW_REGION:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, m_filter.region.ui,
+ m_filter.region.actual, SELECTOR_SOFTWARE, l_sw_hover));
+ break;
+ case UI_SW_YEARS:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, m_filter.year.ui,
+ m_filter.year.actual, SELECTOR_SOFTWARE, l_sw_hover));
+ break;
+ case UI_SW_LIST:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, m_filter.swlist.description,
+ m_filter.swlist.actual, SELECTOR_SOFTWARE, l_sw_hover));
+ break;
+ case UI_SW_TYPE:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, m_filter.type.ui,
+ m_filter.type.actual, SELECTOR_SOFTWARE, l_sw_hover));
+ break;
+ case UI_SW_PUBLISHERS:
+ ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, m_filter.publisher.ui,
+ m_filter.publisher.actual, SELECTOR_SOFTWARE, l_sw_hover));
+ break;
+ case UI_SW_CUSTOM:
+ sw_filters::actual = l_sw_hover;
+ ui_menu::stack_push(global_alloc_clear<ui_menu_swcustom_filter>(machine(), container, m_driver, m_filter));
+ break;
+ default:
+ sw_filters::actual = l_sw_hover;
+ reset(UI_MENU_RESET_SELECT_FIRST);
+ break;
+ }
+ }
+}
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_select_software::populate()
+{
+ UINT32 flags_ui = MENU_FLAG_UI_SWLIST | MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW;
+ m_has_empty_start = true;
+ int old_software = -1;
+
+ machine_config config(*m_driver, machine().options());
+ for (device_image_interface &image : image_interface_iterator(config.root_device()))
+ if (image.filename() == nullptr && image.must_be_loaded())
+ {
+ m_has_empty_start = false;
+ break;
+ }
+
+ // no active search
+ if (m_search[0] == 0)
+ {
+ // if the device can be loaded empty, add an item
+ if (m_has_empty_start)
+ item_append("[Start empty]", nullptr, flags_ui, (void *)&m_swinfo[0]);
+
+ m_displaylist.clear();
+ m_tmp.clear();
+
+ switch (sw_filters::actual)
+ {
+ case UI_SW_PUBLISHERS:
+ build_list(m_tmp, m_filter.publisher.ui[m_filter.publisher.actual].c_str());
+ break;
+
+ case UI_SW_LIST:
+ build_list(m_tmp, m_filter.swlist.name[m_filter.swlist.actual].c_str());
+ break;
+
+ case UI_SW_YEARS:
+ build_list(m_tmp, m_filter.year.ui[m_filter.year.actual].c_str());
+ break;
+
+ case UI_SW_TYPE:
+ build_list(m_tmp, m_filter.type.ui[m_filter.type.actual].c_str());
+ break;
+
+ case UI_SW_REGION:
+ build_list(m_tmp, m_filter.region.ui[m_filter.region.actual].c_str());
+ break;
+
+ case UI_SW_CUSTOM:
+ build_custom();
+ break;
+
+ default:
+ build_list(m_tmp);
+ break;
+ }
+
+ // iterate over entries
+ for (size_t curitem = 0; curitem < m_displaylist.size(); ++curitem)
+ {
+ if (reselect_last::software == "[Start empty]" && !reselect_last::driver.empty())
+ old_software = 0;
+
+ else if (m_displaylist[curitem]->shortname == reselect_last::software && m_displaylist[curitem]->listname == reselect_last::swlist)
+ old_software = m_has_empty_start ? curitem + 1 : curitem;
+
+ item_append(m_displaylist[curitem]->longname.c_str(), m_displaylist[curitem]->devicetype.c_str(),
+ m_displaylist[curitem]->parentname.empty() ? flags_ui : (MENU_FLAG_INVERT | flags_ui), (void *)m_displaylist[curitem]);
+ }
+ }
+
+ else
+ {
+ find_matches(m_search, VISIBLE_GAMES_IN_SEARCH);
+
+ for (int curitem = 0; m_searchlist[curitem] != nullptr; ++curitem)
+ item_append(m_searchlist[curitem]->longname.c_str(), m_searchlist[curitem]->devicetype.c_str(),
+ m_searchlist[curitem]->parentname.empty() ? flags_ui : (MENU_FLAG_INVERT | flags_ui),
+ (void *)m_searchlist[curitem]);
+ }
+
+ item_append(MENU_SEPARATOR_ITEM, nullptr, flags_ui, nullptr);
+
+ // configure the custom rendering
+ customtop = 4.0f * mame_machine_manager::instance()->ui().get_line_height() + 5.0f * UI_BOX_TB_BORDER;
+ custombottom = 5.0f * mame_machine_manager::instance()->ui().get_line_height() + 4.0f * UI_BOX_TB_BORDER;
+
+ if (old_software != -1)
+ {
+ selected = old_software;
+ top_line = selected - (ui_globals::visible_sw_lines / 2);
+ }
+
+ reselect_last::reset();
+}
+
+//-------------------------------------------------
+// build a list of software
+//-------------------------------------------------
+
+void ui_menu_select_software::build_software_list()
+{
+ // add start empty item
+ m_swinfo.emplace_back(m_driver->name, m_driver->description, "", "", "", 0, "", m_driver, "", "", "", 1, "", "", "", true);
+
+ machine_config config(*m_driver, machine().options());
+
+ // iterate thru all software lists
+ for (software_list_device &swlist : software_list_device_iterator(config.root_device()))
+ {
+ m_filter.swlist.name.push_back(swlist.list_name());
+ m_filter.swlist.description.push_back(swlist.description());
+ for (software_info &swinfo : swlist.get_info())
+ {
+ software_part *part = swinfo.first_part();
+ if (part->is_compatible(swlist))
+ {
+ const char *instance_name = nullptr;
+ const char *type_name = nullptr;
+ ui_software_info tmpmatches;
+ for (device_image_interface &image : image_interface_iterator(config.root_device()))
+ {
+ const char *interface = image.image_interface();
+ if (interface != nullptr && part->matches_interface(interface))
+ {
+ instance_name = image.instance_name();
+ if (instance_name != nullptr)
+ tmpmatches.instance = image.instance_name();
+
+ type_name = image.image_type_name();
+ if (type_name != nullptr)
+ tmpmatches.devicetype = type_name;
+ break;
+ }
+ }
+
+ if (instance_name == nullptr || type_name == nullptr)
+ continue;
+
+ tmpmatches.shortname = strensure(swinfo.shortname());
+ tmpmatches.longname = strensure(swinfo.longname());
+ tmpmatches.parentname = strensure(swinfo.parentname());
+ tmpmatches.year = strensure(swinfo.year());
+ tmpmatches.publisher = strensure(swinfo.publisher());
+ tmpmatches.supported = swinfo.supported();
+ tmpmatches.part = strensure(part->name());
+ tmpmatches.driver = m_driver;
+ tmpmatches.listname = strensure(swlist.list_name());
+ tmpmatches.interface = strensure(part->interface());
+ tmpmatches.startempty = 0;
+ tmpmatches.parentlongname.clear();
+ tmpmatches.usage.clear();
+ tmpmatches.available = false;
+
+ for (feature_list_item &flist : swinfo.other_info())
+ if (!strcmp(flist.name(), "usage"))
+ tmpmatches.usage = flist.value();
+
+ m_swinfo.push_back(tmpmatches);
+ m_filter.region.set(tmpmatches.longname);
+ m_filter.publisher.set(tmpmatches.publisher);
+ m_filter.year.set(tmpmatches.year);
+ m_filter.type.set(tmpmatches.devicetype);
+ }
+ }
+ }
+ m_displaylist.resize(m_swinfo.size() + 1);
+
+ // retrieve and set the long name of software for parents
+ for (size_t y = 1; y < m_swinfo.size(); ++y)
+ {
+ if (!m_swinfo[y].parentname.empty())
+ {
+ std::string lparent(m_swinfo[y].parentname);
+ bool found = false;
+
+ // first scan backward
+ for (int x = y; x > 0; --x)
+ if (lparent == m_swinfo[x].shortname && m_swinfo[y].listname == m_swinfo[x].listname)
+ {
+ m_swinfo[y].parentlongname = m_swinfo[x].longname;
+ found = true;
+ break;
+ }
+
+ // not found? then scan forward
+ for (size_t x = y; !found && x < m_swinfo.size(); ++x)
+ if (lparent == m_swinfo[x].shortname && m_swinfo[y].listname == m_swinfo[x].listname)
+ {
+ m_swinfo[y].parentlongname = m_swinfo[x].longname;
+ break;
+ }
+ }
+ }
+
+ std::string searchstr, curpath;
+ const osd_directory_entry *dir;
+ for (auto & elem : m_filter.swlist.name)
+ {
+ path_iterator path(machine().options().media_path());
+ while (path.next(curpath))
+ {
+ searchstr.assign(curpath).append(PATH_SEPARATOR).append(elem).append(";");
+ file_enumerator fpath(searchstr.c_str());
+
+ // iterate while we get new objects
+ while ((dir = fpath.next()) != nullptr)
+ {
+ std::string name;
+ if (dir->type == ENTTYPE_FILE)
+ name = core_filename_extract_base(dir->name, true);
+ else if (dir->type == ENTTYPE_DIR && strcmp(dir->name, ".") != 0)
+ name = dir->name;
+ else
+ continue;
+
+ strmakelower(name);
+ for (auto & yelem : m_swinfo)
+ if (yelem.shortname == name && yelem.listname == elem)
+ {
+ yelem.available = true;
+ break;
+ }
+ }
+ }
+ }
+
+ // sort array
+ std::stable_sort(m_swinfo.begin() + 1, m_swinfo.end(), compare_software);
+ std::stable_sort(m_filter.region.ui.begin(), m_filter.region.ui.end());
+ std::stable_sort(m_filter.year.ui.begin(), m_filter.year.ui.end());
+ std::stable_sort(m_filter.type.ui.begin(), m_filter.type.ui.end());
+ std::stable_sort(m_filter.publisher.ui.begin(), m_filter.publisher.ui.end());
+
+ for (size_t x = 1; x < m_swinfo.size(); ++x)
+ m_sortedlist.push_back(&m_swinfo[x]);
+}
+
+//-------------------------------------------------
+// perform our special rendering
+//-------------------------------------------------
+
+void ui_menu_select_software::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ ui_software_info *swinfo = (selectedref != nullptr) ? (ui_software_info *)selectedref : ((m_prev_selected != nullptr) ? (ui_software_info *)m_prev_selected : nullptr);
+ const game_driver *driver = nullptr;
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+ float width;
+ std::string tempbuf[5], filtered;
+ rgb_t color = UI_BACKGROUND_COLOR;
+ bool isstar = false;
+ float tbarspace = mui.get_line_height();
+ float text_size = 1.0f;
+
+ // determine the text for the header
+ int vis_item = (m_search[0] != 0) ? visible_items : (m_has_empty_start ? visible_items - 1 : visible_items);
+ tempbuf[0] = string_format(_("%1$s %2$s ( %3$d / %4$d software packages )"), emulator_info::get_appname(), bare_build_version, vis_item, m_swinfo.size() - 1);
+ tempbuf[1] = string_format(_("Driver: \"%1$s\" software list "), m_driver->description);
+
+ if (sw_filters::actual == UI_SW_REGION && m_filter.region.ui.size() != 0)
+ filtered = string_format(_("Region: %1$s -"), m_filter.region.ui[m_filter.region.actual]);
+ else if (sw_filters::actual == UI_SW_PUBLISHERS)
+ filtered = string_format(_("Publisher: %1$s -"), m_filter.publisher.ui[m_filter.publisher.actual]);
+ else if (sw_filters::actual == UI_SW_YEARS)
+ filtered = string_format(_("Year: %1$s -"), m_filter.year.ui[m_filter.year.actual]);
+ else if (sw_filters::actual == UI_SW_LIST)
+ filtered = string_format(_("Software List: %1$s -"), m_filter.swlist.description[m_filter.swlist.actual]);
+ else if (sw_filters::actual == UI_SW_TYPE)
+ filtered = string_format(_("Device type: %1$s -"), m_filter.type.ui[m_filter.type.actual]);
+
+ tempbuf[2] = string_format(_("%s Search: %s_"), filtered, m_search);
+
+ // get the size of the text
+ float maxwidth = origx2 - origx1;
+
+ for (int line = 0; line < 3; ++line)
+ {
+ mui.draw_text_full(container, tempbuf[line].c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += 2 * UI_BOX_LR_BORDER;
+ maxwidth = MAX(width, maxwidth);
+ }
+
+ if (maxwidth > origx2 - origx1)
+ {
+ text_size = (origx2 - origx1) / maxwidth;
+ maxwidth = origx2 - origx1;
+ }
+
+ // compute our bounds
+ float x1 = 0.5f - 0.5f * maxwidth;
+ float x2 = x1 + maxwidth;
+ float y1 = origy1 - top;
+ float y2 = origy1 - 3.0f * UI_BOX_TB_BORDER - tbarspace;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ for (int line = 0; line < 3; ++line)
+ {
+ mui.draw_text_full(container, tempbuf[line].c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, text_size);
+ y1 += mui.get_line_height();
+ }
+
+ // determine the text to render below
+ if (swinfo != nullptr && swinfo->startempty == 1)
+ driver = swinfo->driver;
+
+ if (driver != nullptr)
+ {
+ isstar = mame_machine_manager::instance()->favorite().isgame_favorite(driver);
+
+ // first line is game description
+ tempbuf[0] = string_format(_("%1$-.100s"), driver->description);
+
+ // next line is year, manufacturer
+ tempbuf[1] = string_format(_("%1$s, %2$-.100s"), driver->year, driver->manufacturer);
+
+ // next line is clone/parent status
+ int cloneof = driver_list::non_bios_clone(*driver);
+
+ if (cloneof != -1)
+ tempbuf[2] = string_format(_("Driver is clone of: %1$-.100s"), driver_list::driver(cloneof).description);
+ else
+ tempbuf[2] = _("Driver is parent");
+
+ // next line is overall driver status
+ if (driver->flags & MACHINE_NOT_WORKING)
+ tempbuf[3] = _("Overall: NOT WORKING");
+ else if (driver->flags & MACHINE_UNEMULATED_PROTECTION)
+ tempbuf[3] = _("Overall: Unemulated Protection");
+ else
+ tempbuf[3] = _("Overall: Working");
+
+ // next line is graphics, sound status
+ if (driver->flags & (MACHINE_IMPERFECT_GRAPHICS | MACHINE_WRONG_COLORS | MACHINE_IMPERFECT_COLORS))
+ tempbuf[4] = _("Graphics: Imperfect, ");
+ else
+ tempbuf[4] = _("Graphics: OK, ");
+
+ if (driver->flags & MACHINE_NO_SOUND)
+ tempbuf[4].append(_("Sound: Unimplemented"));
+ else if (driver->flags & MACHINE_IMPERFECT_SOUND)
+ tempbuf[4].append(_("Sound: Imperfect"));
+ else
+ tempbuf[4].append(_("Sound: OK"));
+
+ color = UI_GREEN_COLOR;
+
+ if ((driver->flags & (MACHINE_IMPERFECT_GRAPHICS | MACHINE_WRONG_COLORS | MACHINE_IMPERFECT_COLORS
+ | MACHINE_NO_SOUND | MACHINE_IMPERFECT_SOUND)) != 0)
+ color = UI_YELLOW_COLOR;
+
+ if ((driver->flags & (MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION)) != 0)
+ color = UI_RED_COLOR;
+
+ }
+
+ else if (swinfo != nullptr)
+ {
+ isstar = mame_machine_manager::instance()->favorite().isgame_favorite(*swinfo);
+
+ // first line is long name
+ tempbuf[0] = string_format(_("%1$-.100s"), swinfo->longname.c_str());
+
+ // next line is year, publisher
+ tempbuf[1] = string_format(_("%1$s, %2$-.100s"), swinfo->year.c_str(), swinfo->publisher.c_str());
+
+ // next line is parent/clone
+ if (!swinfo->parentname.empty())
+ tempbuf[2] = string_format(_("Software is clone of: %1$-.100s"), !swinfo->parentlongname.empty() ? swinfo->parentlongname.c_str() : swinfo->parentname.c_str());
+ else
+ tempbuf[2] = _("Software is parent");
+
+ // next line is supported status
+ if (swinfo->supported == SOFTWARE_SUPPORTED_NO)
+ {
+ tempbuf[3] = _("Supported: No");
+ color = UI_RED_COLOR;
+ }
+ else if (swinfo->supported == SOFTWARE_SUPPORTED_PARTIAL)
+ {
+ tempbuf[3] = _("Supported: Partial");
+ color = UI_YELLOW_COLOR;
+ }
+ else
+ {
+ tempbuf[3] = _("Supported: Yes");
+ color = UI_GREEN_COLOR;
+ }
+
+ // last line is romset name
+ tempbuf[4] = string_format(_("romset: %1$-.100s"), swinfo->shortname.c_str());
+ }
+
+ else
+ {
+ std::string copyright(emulator_info::get_copyright());
+ size_t found = copyright.find("\n");
+
+ tempbuf[0].clear();
+ tempbuf[1] = string_format("%s %s", emulator_info::get_appname(), build_version);
+ tempbuf[2] = copyright.substr(0, found);
+ tempbuf[3] = copyright.substr(found + 1);
+ tempbuf[4].clear();
+ }
+
+ // compute our bounds
+ x1 = 0.5f - 0.5f * maxwidth;
+ x2 = x1 + maxwidth;
+ y1 = y2;
+ y2 = origy1 - UI_BOX_TB_BORDER;
+
+ // draw toolbar
+ draw_toolbar(x1, y1, x2, y2, true);
+
+ // get the size of the text
+ maxwidth = origx2 - origx1;
+
+ for (auto & elem : tempbuf)
+ {
+ mui.draw_text_full(container, elem.c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += 2 * UI_BOX_LR_BORDER;
+ maxwidth = MAX(maxwidth, width);
+ }
+
+ if (maxwidth > origx2 - origx1)
+ {
+ text_size = (origx2 - origx1) / maxwidth;
+ maxwidth = origx2 - origx1;
+ }
+
+ // compute our bounds
+ x1 = 0.5f - 0.5f * maxwidth;
+ x2 = x1 + maxwidth;
+ y1 = origy2 + UI_BOX_TB_BORDER;
+ y2 = origy2 + bottom;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, color);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // is favorite? draw the star
+ if (isstar)
+ draw_star(x1, y1);
+
+ // draw all lines
+ for (auto & elem : tempbuf)
+ {
+ mui.draw_text_full(container, elem.c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, text_size);
+ y1 += mame_machine_manager::instance()->ui().get_line_height();
+ }
+}
+
+//-------------------------------------------------
+// handle select key event
+//-------------------------------------------------
+
+void ui_menu_select_software::inkey_select(const ui_menu_event *m_event)
+{
+ ui_software_info *ui_swinfo = (ui_software_info *)m_event->itemref;
+ ui_options &mopt = mame_machine_manager::instance()->ui().options();
+
+ if (ui_swinfo->startempty == 1)
+ {
+ s_bios biosname;
+ if (!mopt.skip_bios_menu() && has_multiple_bios(ui_swinfo->driver, biosname))
+ ui_menu::stack_push(global_alloc_clear<ui_bios_selection>(machine(), container, biosname, (void *)ui_swinfo->driver, false, true));
+ else
+ {
+ reselect_last::driver = ui_swinfo->driver->name;
+ reselect_last::software = "[Start empty]";
+ reselect_last::swlist.clear();
+ reselect_last::set(true);
+ mame_machine_manager::instance()->schedule_new_driver(*ui_swinfo->driver);
+ machine().schedule_hard_reset();
+ ui_menu::stack_reset(machine());
+ }
+ }
+
+ else
+ {
+ // first validate
+ driver_enumerator drivlist(machine().options(), *ui_swinfo->driver);
+ media_auditor auditor(drivlist);
+ drivlist.next();
+ software_list_device *swlist = software_list_device::find_by_name(drivlist.config(), ui_swinfo->listname.c_str());
+ software_info *swinfo = swlist->find(ui_swinfo->shortname.c_str());
+
+ media_auditor::summary summary = auditor.audit_software(swlist->list_name(), swinfo, AUDIT_VALIDATE_FAST);
+
+ if (summary == media_auditor::CORRECT || summary == media_auditor::BEST_AVAILABLE || summary == media_auditor::NONE_NEEDED)
+ {
+ s_bios biosname;
+ if (!mopt.skip_bios_menu() && has_multiple_bios(ui_swinfo->driver, biosname))
+ {
+ ui_menu::stack_push(global_alloc_clear<ui_bios_selection>(machine(), container, biosname, (void *)ui_swinfo, true, false));
+ return;
+ }
+ else if (!mopt.skip_parts_menu() && swinfo->has_multiple_parts(ui_swinfo->interface.c_str()))
+ {
+ s_parts parts;
+ for (const software_part &swpart : swinfo->parts())
+ {
+ if (swpart.matches_interface(ui_swinfo->interface.c_str()))
+ {
+ std::string menu_part_name(swpart.name());
+ if (swpart.feature("part_id") != nullptr)
+ menu_part_name.assign("(").append(swpart.feature("part_id")).append(")");
+ parts.emplace(swpart.name(), menu_part_name);
+ }
+ }
+ ui_menu::stack_push(global_alloc_clear<ui_software_parts>(machine(), container, parts, ui_swinfo));
+ return;
+ }
+ std::string error_string;
+ std::string string_list = std::string(ui_swinfo->listname).append(":").append(ui_swinfo->shortname).append(":").append(ui_swinfo->part).append(":").append(ui_swinfo->instance);
+ machine().options().set_value(OPTION_SOFTWARENAME, string_list.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
+ std::string snap_list = std::string(ui_swinfo->listname).append(PATH_SEPARATOR).append(ui_swinfo->shortname);
+ machine().options().set_value(OPTION_SNAPNAME, snap_list.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
+ reselect_last::driver = drivlist.driver().name;
+ reselect_last::software = ui_swinfo->shortname;
+ reselect_last::swlist = ui_swinfo->listname;
+ reselect_last::set(true);
+ mame_machine_manager::instance()->schedule_new_driver(drivlist.driver());
+ machine().schedule_hard_reset();
+ ui_menu::stack_reset(machine());
+ }
+
+ // otherwise, display an error
+ else
+ {
+ reset(UI_MENU_RESET_REMEMBER_POSITION);
+ ui_error = true;
+ }
+ }
+}
+
+//-------------------------------------------------
+// handle special key event
+//-------------------------------------------------
+
+void ui_menu_select_software::inkey_special(const ui_menu_event *m_event)
+{
+ int buflen = strlen(m_search);
+
+ // if it's a backspace and we can handle it, do so
+ if ((m_event->unichar == 8 || m_event->unichar == 0x7f) && buflen > 0)
+ {
+ *(char *)utf8_previous_char(&m_search[buflen]) = 0;
+ reset(UI_MENU_RESET_SELECT_FIRST);
+ }
+
+ // if it's any other key and we're not maxed out, update
+ else if (m_event->unichar >= ' ' && m_event->unichar < 0x7f)
+ {
+ buflen += utf8_from_uchar(&m_search[buflen], ARRAY_LENGTH(m_search) - buflen, m_event->unichar);
+ m_search[buflen] = 0;
+ reset(UI_MENU_RESET_SELECT_FIRST);
+ }
+}
+
+void ui_menu_select_software::inkey_configure(const ui_menu_event *m_event)
+{
+ if (selected <= visible_items && m_focus == focused_menu::main)
+ {
+ m_prev_selected = item[selected].ref;
+ selected = visible_items + 1;
+ }
+ else if (selected > visible_items && m_focus == focused_menu::main)
+ {
+ if (ui_globals::panels_status != HIDE_LEFT_PANEL)
+ m_focus = focused_menu::left;
+
+ else if (ui_globals::panels_status == HIDE_BOTH)
+ {
+ for (int x = 0; x < item.size(); ++x)
+ if (item[x].ref == m_prev_selected)
+ selected = x;
+ }
+ else
+ m_focus = focused_menu::righttop;
+ }
+ else if (m_focus == focused_menu::left)
+ {
+ if (ui_globals::panels_status != HIDE_RIGHT_PANEL)
+ m_focus = focused_menu::righttop;
+ else
+ {
+ m_focus = focused_menu::main;
+ if (m_prev_selected == nullptr)
+ {
+ selected = 0;
+ return;
+ }
+
+ for (int x = 0; x < item.size(); ++x)
+ if (item[x].ref == m_prev_selected)
+ selected = x;
+ }
+ }
+ else if (m_focus == focused_menu::righttop)
+ m_focus = focused_menu::rightbottom;
+ else if (m_focus == focused_menu::rightbottom)
+ {
+ m_focus = focused_menu::main;
+ if (m_prev_selected == nullptr)
+ {
+ selected = 0;
+ return;
+ }
+
+ for (int x = 0; x < item.size(); ++x)
+ if (item[x].ref == m_prev_selected)
+ selected = x;
+ }
+}
+
+//-------------------------------------------------
+// load custom filters info from file
+//-------------------------------------------------
+
+void ui_menu_select_software::load_sw_custom_filters()
+{
+ // attempt to open the output file
+ emu_file file(mame_machine_manager::instance()->ui().options().ui_path(), OPEN_FLAG_READ);
+ if (file.open("custom_", m_driver->name, "_filter.ini") == osd_file::error::NONE)
+ {
+ char buffer[MAX_CHAR_INFO];
+
+ // get number of filters
+ file.gets(buffer, MAX_CHAR_INFO);
+ char *pb = strchr(buffer, '=');
+ sw_custfltr::numother = atoi(++pb) - 1;
+
+ // get main filter
+ file.gets(buffer, MAX_CHAR_INFO);
+ pb = strchr(buffer, '=') + 2;
+
+ for (int y = 0; y < sw_filters::length; ++y)
+ if (!strncmp(pb, sw_filters::text[y], strlen(sw_filters::text[y])))
+ {
+ sw_custfltr::main = y;
+ break;
+ }
+
+ for (int x = 1; x <= sw_custfltr::numother; ++x)
+ {
+ file.gets(buffer, MAX_CHAR_INFO);
+ char *cb = strchr(buffer, '=') + 2;
+ for (int y = 0; y < sw_filters::length; y++)
+ {
+ if (!strncmp(cb, sw_filters::text[y], strlen(sw_filters::text[y])))
+ {
+ sw_custfltr::other[x] = y;
+ if (y == UI_SW_PUBLISHERS)
+ {
+ file.gets(buffer, MAX_CHAR_INFO);
+ char *ab = strchr(buffer, '=') + 2;
+ for (size_t z = 0; z < m_filter.publisher.ui.size(); ++z)
+ if (!strncmp(ab, m_filter.publisher.ui[z].c_str(), m_filter.publisher.ui[z].length()))
+ sw_custfltr::mnfct[x] = z;
+ }
+ else if (y == UI_SW_YEARS)
+ {
+ file.gets(buffer, MAX_CHAR_INFO);
+ char *db = strchr(buffer, '=') + 2;
+ for (size_t z = 0; z < m_filter.year.ui.size(); ++z)
+ if (!strncmp(db, m_filter.year.ui[z].c_str(), m_filter.year.ui[z].length()))
+ sw_custfltr::year[x] = z;
+ }
+ else if (y == UI_SW_LIST)
+ {
+ file.gets(buffer, MAX_CHAR_INFO);
+ char *gb = strchr(buffer, '=') + 2;
+ for (size_t z = 0; z < m_filter.swlist.name.size(); ++z)
+ if (!strncmp(gb, m_filter.swlist.name[z].c_str(), m_filter.swlist.name[z].length()))
+ sw_custfltr::list[x] = z;
+ }
+ else if (y == UI_SW_TYPE)
+ {
+ file.gets(buffer, MAX_CHAR_INFO);
+ char *fb = strchr(buffer, '=') + 2;
+ for (size_t z = 0; z < m_filter.type.ui.size(); ++z)
+ if (!strncmp(fb, m_filter.type.ui[z].c_str(), m_filter.type.ui[z].length()))
+ sw_custfltr::type[x] = z;
+ }
+ else if (y == UI_SW_REGION)
+ {
+ file.gets(buffer, MAX_CHAR_INFO);
+ char *eb = strchr(buffer, '=') + 2;
+ for (size_t z = 0; z < m_filter.region.ui.size(); ++z)
+ if (!strncmp(eb, m_filter.region.ui[z].c_str(), m_filter.region.ui[z].length()))
+ sw_custfltr::region[x] = z;
+ }
+ }
+ }
+ }
+ file.close();
+ }
+}
+
+//-------------------------------------------------
+// set software regions
+//-------------------------------------------------
+
+void c_sw_region::set(std::string &str)
+{
+ std::string name = getname(str);
+ if (std::find(ui.begin(), ui.end(), name) != ui.end())
+ return;
+
+ ui.push_back(name);
+}
+
+std::string c_sw_region::getname(std::string &str)
+{
+ std::string fullname(str);
+ strmakelower(fullname);
+ size_t found = fullname.find("(");
+
+ if (found != std::string::npos)
+ {
+ size_t ends = fullname.find_first_not_of("abcdefghijklmnopqrstuvwxyz", found + 1);
+ std::string temp(fullname.substr(found + 1, ends - found - 1));
+
+ for (auto & elem : region_lists)
+ if (temp == elem)
+ return (str.substr(found + 1, ends - found - 1));
+ }
+ return std::string("<none>");
+}
+
+//-------------------------------------------------
+// set software device type
+//-------------------------------------------------
+
+void c_sw_type::set(std::string &str)
+{
+ if (std::find(ui.begin(), ui.end(), str) != ui.end())
+ return;
+
+ ui.push_back(str);
+}
+
+//-------------------------------------------------
+// set software years
+//-------------------------------------------------
+
+void c_sw_year::set(std::string &str)
+{
+ if (std::find(ui.begin(), ui.end(), str) != ui.end())
+ return;
+
+ ui.push_back(str);
+}
+
+//-------------------------------------------------
+// set software publishers
+//-------------------------------------------------
+
+void c_sw_publisher::set(std::string &str)
+{
+ std::string name = getname(str);
+ if (std::find(ui.begin(), ui.end(), name) != ui.end())
+ return;
+
+ ui.push_back(name);
+}
+
+std::string c_sw_publisher::getname(std::string &str)
+{
+ size_t found = str.find("(");
+
+ if (found != std::string::npos)
+ return (str.substr(0, found - 1));
+ else
+ return str;
+}
+
+//-------------------------------------------------
+// build display list
+//-------------------------------------------------
+void ui_menu_select_software::build_list(std::vector<ui_software_info *> &s_drivers, const char *filter_text, int filter)
+{
+ if (s_drivers.empty() && filter == -1)
+ {
+ filter = sw_filters::actual;
+ s_drivers = m_sortedlist;
+ }
+
+ // iterate over entries
+ for (auto & s_driver : s_drivers)
+ {
+ switch (filter)
+ {
+ case UI_SW_PARENTS:
+ if (s_driver->parentname.empty())
+ m_displaylist.push_back(s_driver);
+ break;
+
+ case UI_SW_CLONES:
+ if (!s_driver->parentname.empty())
+ m_displaylist.push_back(s_driver);
+ break;
+
+ case UI_SW_AVAILABLE:
+ if (s_driver->available)
+ m_displaylist.push_back(s_driver);
+ break;
+
+ case UI_SW_UNAVAILABLE:
+ if (!s_driver->available)
+ m_displaylist.push_back(s_driver);
+ break;
+
+ case UI_SW_SUPPORTED:
+ if (s_driver->supported == SOFTWARE_SUPPORTED_YES)
+ m_displaylist.push_back(s_driver);
+ break;
+
+ case UI_SW_PARTIAL_SUPPORTED:
+ if (s_driver->supported == SOFTWARE_SUPPORTED_PARTIAL)
+ m_displaylist.push_back(s_driver);
+ break;
+
+ case UI_SW_UNSUPPORTED:
+ if (s_driver->supported == SOFTWARE_SUPPORTED_NO)
+ m_displaylist.push_back(s_driver);
+ break;
+
+ case UI_SW_REGION:
+ {
+ std::string name = m_filter.region.getname(s_driver->longname);
+
+ if(!name.empty() && name == filter_text)
+ m_displaylist.push_back(s_driver);
+ break;
+ }
+
+ case UI_SW_PUBLISHERS:
+ {
+ std::string name = m_filter.publisher.getname(s_driver->publisher);
+
+ if(!name.empty() && name == filter_text)
+ m_displaylist.push_back(s_driver);
+ break;
+ }
+
+ case UI_SW_YEARS:
+ if(s_driver->year == filter_text)
+ m_displaylist.push_back(s_driver);
+ break;
+
+ case UI_SW_LIST:
+ if(s_driver->listname == filter_text)
+ m_displaylist.push_back(s_driver);
+ break;
+
+ case UI_SW_TYPE:
+ if(s_driver->devicetype == filter_text)
+ m_displaylist.push_back(s_driver);
+ break;
+
+ default:
+ m_displaylist.push_back(s_driver);
+ break;
+ }
+ }
+}
+
+//-------------------------------------------------
+// find approximate matches
+//-------------------------------------------------
+
+void ui_menu_select_software::find_matches(const char *str, int count)
+{
+ // allocate memory to track the penalty value
+ std::vector<int> penalty(count, 9999);
+ int index = 0;
+
+ for (; index < m_displaylist.size(); ++index)
+ {
+ // pick the best match between driver name and description
+ int curpenalty = fuzzy_substring(str, m_displaylist[index]->longname);
+ int tmp = fuzzy_substring(str, m_displaylist[index]->shortname);
+ curpenalty = MIN(curpenalty, tmp);
+
+ // insert into the sorted table of matches
+ for (int matchnum = count - 1; matchnum >= 0; --matchnum)
+ {
+ // stop if we're worse than the current entry
+ if (curpenalty >= penalty[matchnum])
+ break;
+
+ // as long as this isn't the last entry, bump this one down
+ if (matchnum < count - 1)
+ {
+ penalty[matchnum + 1] = penalty[matchnum];
+ m_searchlist[matchnum + 1] = m_searchlist[matchnum];
+ }
+
+ m_searchlist[matchnum] = m_displaylist[index];
+ penalty[matchnum] = curpenalty;
+ }
+ }
+ (index < count) ? m_searchlist[index] = nullptr : m_searchlist[count] = nullptr;
+}
+
+//-------------------------------------------------
+// build custom display list
+//-------------------------------------------------
+
+void ui_menu_select_software::build_custom()
+{
+ std::vector<ui_software_info *> s_drivers;
+
+ build_list(m_sortedlist, nullptr, sw_custfltr::main);
+
+ for (int count = 1; count <= sw_custfltr::numother; ++count)
+ {
+ int filter = sw_custfltr::other[count];
+ s_drivers = m_displaylist;
+ m_displaylist.clear();
+
+ switch (filter)
+ {
+ case UI_SW_YEARS:
+ build_list(s_drivers, m_filter.year.ui[sw_custfltr::year[count]].c_str(), filter);
+ break;
+ case UI_SW_LIST:
+ build_list(s_drivers, m_filter.swlist.name[sw_custfltr::list[count]].c_str(), filter);
+ break;
+ case UI_SW_TYPE:
+ build_list(s_drivers, m_filter.type.ui[sw_custfltr::type[count]].c_str(), filter);
+ break;
+ case UI_SW_PUBLISHERS:
+ build_list(s_drivers, m_filter.publisher.ui[sw_custfltr::mnfct[count]].c_str(), filter);
+ break;
+ case UI_SW_REGION:
+ build_list(s_drivers, m_filter.region.ui[sw_custfltr::region[count]].c_str(), filter);
+ break;
+ default:
+ build_list(s_drivers, nullptr, filter);
+ break;
+ }
+ }
+}
+
+//-------------------------------------------------
+// draw left box
+//-------------------------------------------------
+
+float ui_menu_select_software::draw_left_panel(float x1, float y1, float x2, float y2)
+{
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+
+ if (ui_globals::panels_status == SHOW_PANELS || ui_globals::panels_status == HIDE_RIGHT_PANEL)
+ {
+ float origy1 = y1;
+ float origy2 = y2;
+ float text_size = 0.75f;
+ float l_height = mui.get_line_height();
+ float line_height = l_height * text_size;
+ float left_width = 0.0f;
+ int text_lenght = sw_filters::length;
+ int afilter = sw_filters::actual;
+ int phover = HOVER_SW_FILTER_FIRST;
+ const char **text = sw_filters::text;
+ float sc = y2 - y1 - (2.0f * UI_BOX_TB_BORDER);
+
+ if ((text_lenght * line_height) > sc)
+ {
+ float lm = sc / (text_lenght);
+ text_size = lm / l_height;
+ line_height = l_height * text_size;
+ }
+
+ float text_sign = mui.get_string_width("_# ", text_size);
+ for (int x = 0; x < text_lenght; ++x)
+ {
+ float total_width;
+
+ // compute width of left hand side
+ total_width = mui.get_string_width(text[x], text_size);
+ total_width += text_sign;
+
+ // track the maximum
+ if (total_width > left_width)
+ left_width = total_width;
+ }
+
+ x2 = x1 + left_width + 2.0f * UI_BOX_LR_BORDER;
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+ y2 -= UI_BOX_TB_BORDER;
+
+ for (int filter = 0; filter < text_lenght; ++filter)
+ {
+ std::string str(text[filter]);
+ rgb_t bgcolor = UI_TEXT_BG_COLOR;
+ rgb_t fgcolor = UI_TEXT_COLOR;
+
+ if (mouse_hit && x1 <= mouse_x && x2 > mouse_x && y1 <= mouse_y && y1 + line_height > mouse_y)
+ {
+ bgcolor = UI_MOUSEOVER_BG_COLOR;
+ fgcolor = UI_MOUSEOVER_COLOR;
+ hover = phover + filter;
+ }
+
+ if (highlight == filter && m_focus == focused_menu::left)
+ {
+ fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00);
+ bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff);
+ }
+
+ if (bgcolor != UI_TEXT_BG_COLOR)
+ mui.draw_textured_box(container, x1, y1, x2, y1 + line_height, bgcolor, rgb_t(255, 43, 43, 43),
+ hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
+
+ float x1t = x1 + text_sign;
+ if (afilter == UI_SW_CUSTOM)
+ {
+ if (filter == sw_custfltr::main)
+ {
+ str.assign("@custom1 ").append(text[filter]);
+ x1t -= text_sign;
+ }
+ else
+ {
+ for (int count = 1; count <= sw_custfltr::numother; ++count)
+ {
+ int cfilter = sw_custfltr::other[count];
+ if (cfilter == filter)
+ {
+ str = string_format("@custom%d %s", count + 1, text[filter]);
+ x1t -= text_sign;
+ break;
+ }
+ }
+ }
+ convert_command_glyph(str);
+ }
+ else if (filter == sw_filters::actual)
+ {
+ str.assign("_> ").append(text[filter]);
+ x1t -= text_sign;
+ convert_command_glyph(str);
+ }
+
+ mui.draw_text_full(container, str.c_str(), x1t, y1, x2 - x1, JUSTIFY_LEFT, WRAP_NEVER,
+ DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr, text_size);
+ y1 += line_height;
+ }
+
+ x1 = x2 + UI_BOX_LR_BORDER;
+ x2 = x1 + 2.0f * UI_BOX_LR_BORDER;
+ y1 = origy1;
+ y2 = origy2;
+ float space = x2 - x1;
+ float lr_arrow_width = 0.4f * space * machine().render().ui_aspect();
+ rgb_t fgcolor = UI_TEXT_COLOR;
+
+ // set left-right arrows dimension
+ float ar_x0 = 0.5f * (x2 + x1) - 0.5f * lr_arrow_width;
+ float ar_y0 = 0.5f * (y2 + y1) + 0.1f * space;
+ float ar_x1 = ar_x0 + lr_arrow_width;
+ float ar_y1 = 0.5f * (y2 + y1) + 0.9f * space;
+
+ mui.draw_outlined_box(container, x1, y1, x2, y2, rgb_t(0xEF, 0x12, 0x47, 0x7B));
+
+ if (mouse_hit && x1 <= mouse_x && x2 > mouse_x && y1 <= mouse_y && y2 > mouse_y)
+ {
+ fgcolor = UI_MOUSEOVER_COLOR;
+ hover = HOVER_LPANEL_ARROW;
+ }
+
+ draw_arrow(container, ar_x0, ar_y0, ar_x1, ar_y1, fgcolor, ROT90 ^ ORIENTATION_FLIP_X);
+ return x2 + UI_BOX_LR_BORDER;
+ }
+ else
+ {
+ float space = x2 - x1;
+ float lr_arrow_width = 0.4f * space * machine().render().ui_aspect();
+ rgb_t fgcolor = UI_TEXT_COLOR;
+
+ // set left-right arrows dimension
+ float ar_x0 = 0.5f * (x2 + x1) - 0.5f * lr_arrow_width;
+ float ar_y0 = 0.5f * (y2 + y1) + 0.1f * space;
+ float ar_x1 = ar_x0 + lr_arrow_width;
+ float ar_y1 = 0.5f * (y2 + y1) + 0.9f * space;
+
+ mui.draw_outlined_box(container, x1, y1, x2, y2, rgb_t(0xEF, 0x12, 0x47, 0x7B));
+
+ if (mouse_hit && x1 <= mouse_x && x2 > mouse_x && y1 <= mouse_y && y2 > mouse_y)
+ {
+ fgcolor = UI_MOUSEOVER_COLOR;
+ hover = HOVER_LPANEL_ARROW;
+ }
+
+ draw_arrow(container, ar_x0, ar_y0, ar_x1, ar_y1, fgcolor, ROT90);
+ return x2 + UI_BOX_LR_BORDER;
+ }
+}
+
+//-------------------------------------------------
+// draw infos
+//-------------------------------------------------
+
+void ui_menu_select_software::infos_render(void *selectedref, float origx1, float origy1, float origx2, float origy2)
+{
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+ float line_height = mui.get_line_height();
+ static std::string buffer;
+ std::vector<int> xstart;
+ std::vector<int> xend;
+ float text_size = mame_machine_manager::instance()->ui().options().infos_size();
+ ui_software_info *soft = (selectedref != nullptr) ? (ui_software_info *)selectedref : ((m_prev_selected != nullptr) ? (ui_software_info *)m_prev_selected : nullptr);
+ static ui_software_info *oldsoft = nullptr;
+ static int old_sw_view = -1;
+
+ float gutter_width = 0.4f * line_height * machine().render().ui_aspect() * 1.3f;
+ float ud_arrow_width = line_height * machine().render().ui_aspect();
+ float oy1 = origy1 + line_height;
+
+ // apply title to right panel
+ if (soft != nullptr && soft->usage.empty())
+ {
+ float title_size = 0.0f;
+
+ mui.draw_text_full(container, _("History"), origx1, origy1, origx2 - origx1, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NONE, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, &title_size, nullptr);
+ title_size += 0.01f;
+
+ rgb_t fgcolor = UI_TEXT_COLOR;
+ rgb_t bgcolor = UI_TEXT_BG_COLOR;
+ if (m_focus == focused_menu::rightbottom)
+ {
+ fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00);
+ bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff);
+ }
+
+ float middle = origx2 - origx1;
+
+ if (bgcolor != UI_TEXT_BG_COLOR)
+ mui.draw_textured_box(container, origx1 + ((middle - title_size) * 0.5f), origy1, origx1 + ((middle + title_size) * 0.5f),
+ origy1 + line_height, bgcolor, rgb_t(255, 43, 43, 43), hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
+
+ mui.draw_text_full(container, _("History"), origx1, origy1, origx2 - origx1, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr);
+ ui_globals::cur_sw_dats_view = 0;
+ }
+ else
+ {
+ float title_size = 0.0f;
+ float txt_lenght = 0.0f;
+ std::string t_text[2];
+ t_text[0] = _("History");
+ t_text[1] = _("Usage");
+
+ for (auto & elem : t_text)
+ {
+ mui.draw_text_full(container, elem.c_str(), origx1, origy1, origx2 - origx1, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NONE, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, &txt_lenght, nullptr);
+ txt_lenght += 0.01f;
+ title_size = MAX(txt_lenght, title_size);
+ }
+
+ rgb_t fgcolor = UI_TEXT_COLOR;
+ rgb_t bgcolor = UI_TEXT_BG_COLOR;
+ if (m_focus == focused_menu::rightbottom)
+ {
+ fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00);
+ bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff);
+ }
+
+ float middle = origx2 - origx1;
+
+ // check size
+ float sc = title_size + 2.0f * gutter_width;
+ float tmp_size = (sc > middle) ? ((middle - 2.0f * gutter_width) / sc) : 1.0f;
+ title_size *= tmp_size;
+
+ if (bgcolor != UI_TEXT_BG_COLOR)
+ mui.draw_textured_box(container, origx1 + ((middle - title_size) * 0.5f), origy1, origx1 + ((middle + title_size) * 0.5f),
+ origy1 + line_height, bgcolor, rgb_t(255, 43, 43, 43), hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
+
+ mui.draw_text_full(container, t_text[ui_globals::cur_sw_dats_view].c_str(), origx1, origy1, origx2 - origx1,
+ JUSTIFY_CENTER, WRAP_NEVER, DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr, tmp_size);
+
+ draw_common_arrow(origx1, origy1, origx2, origy2, ui_globals::cur_sw_dats_view, 0, 1, title_size);
+ }
+
+ if (oldsoft != soft || old_sw_view != ui_globals::cur_sw_dats_view)
+ {
+ buffer.clear();
+ old_sw_view = ui_globals::cur_sw_dats_view;
+ oldsoft = soft;
+ if (ui_globals::cur_sw_dats_view == 0)
+ {
+ if (soft->startempty == 1)
+ mame_machine_manager::instance()->datfile().load_data_info(soft->driver, buffer, UI_HISTORY_LOAD);
+ else
+ mame_machine_manager::instance()->datfile().load_software_info(soft->listname, buffer, soft->shortname, soft->parentname);
+ }
+ else
+ buffer = soft->usage;
+ }
+
+ if (buffer.empty())
+ {
+ mui.draw_text_full(container, _("No Infos Available"), origx1, (origy2 + origy1) * 0.5f, origx2 - origx1, JUSTIFY_CENTER,
+ WRAP_WORD, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+ return;
+ }
+ else
+ totallines = mui.wrap_text(container, buffer.c_str(), origx1, origy1, origx2 - origx1 - (2.0f * gutter_width), xstart, xend, text_size);
+
+ int r_visible_lines = floor((origy2 - oy1) / (line_height * text_size));
+ if (totallines < r_visible_lines)
+ r_visible_lines = totallines;
+ if (topline_datsview < 0)
+ topline_datsview = 0;
+ if (topline_datsview + r_visible_lines >= totallines)
+ topline_datsview = totallines - r_visible_lines;
+
+ for (int r = 0; r < r_visible_lines; ++r)
+ {
+ int itemline = r + topline_datsview;
+ std::string tempbuf;
+ tempbuf.assign(buffer.substr(xstart[itemline], xend[itemline] - xstart[itemline]));
+
+ // up arrow
+ if (r == 0 && topline_datsview != 0)
+ info_arrow(0, origx1, origx2, oy1, line_height, text_size, ud_arrow_width);
+ // bottom arrow
+ else if (r == r_visible_lines - 1 && itemline != totallines - 1)
+ info_arrow(1, origx1, origx2, oy1, line_height, text_size, ud_arrow_width);
+ else
+ mui.draw_text_full(container, tempbuf.c_str(), origx1 + gutter_width, oy1, origx2 - origx1,
+ JUSTIFY_LEFT, WRAP_TRUNCATE, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR,
+ nullptr, nullptr, text_size);
+ oy1 += (line_height * text_size);
+ }
+
+ // return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow
+ right_visible_lines = r_visible_lines - (topline_datsview != 0) - (topline_datsview + r_visible_lines != totallines);
+}
+
+//-------------------------------------------------
+// perform our special rendering
+//-------------------------------------------------
+
+void ui_menu_select_software::arts_render(void *selectedref, float origx1, float origy1, float origx2, float origy2)
+{
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+ float line_height = mui.get_line_height();
+ static ui_software_info *oldsoft = nullptr;
+ static const game_driver *olddriver = nullptr;
+ const game_driver *driver = nullptr;
+ ui_software_info *soft = (selectedref != nullptr) ? (ui_software_info *)selectedref : ((m_prev_selected != nullptr) ? (ui_software_info *)m_prev_selected : nullptr);
+
+ if (soft != nullptr && soft->startempty == 1)
+ {
+ driver = soft->driver;
+ oldsoft = nullptr;
+ }
+ else
+ olddriver = nullptr;
+
+ if (driver != nullptr)
+ {
+ if (ui_globals::default_image)
+ ((driver->flags & MACHINE_TYPE_ARCADE) == 0) ? ui_globals::curimage_view = CABINETS_VIEW : ui_globals::curimage_view = SNAPSHOT_VIEW;
+
+ std::string searchstr;
+ searchstr = arts_render_common(origx1, origy1, origx2, origy2);
+
+ // loads the image if necessary
+ if (driver != olddriver || !snapx_bitmap->valid() || ui_globals::switch_image)
+ {
+ emu_file snapfile(searchstr.c_str(), OPEN_FLAG_READ);
+ snapfile.set_restrict_to_mediapath(true);
+ bitmap_argb32 *tmp_bitmap;
+ tmp_bitmap = auto_alloc(machine(), bitmap_argb32);
+
+ // try to load snapshot first from saved "0000.png" file
+ std::string fullname(driver->name);
+ render_load_png(*tmp_bitmap, snapfile, fullname.c_str(), "0000.png");
+
+ if (!tmp_bitmap->valid())
+ render_load_jpeg(*tmp_bitmap, snapfile, fullname.c_str(), "0000.jpg");
+
+ // if fail, attemp to load from standard file
+ if (!tmp_bitmap->valid())
+ {
+ fullname.assign(driver->name).append(".png");
+ render_load_png(*tmp_bitmap, snapfile, nullptr, fullname.c_str());
+
+ if (!tmp_bitmap->valid())
+ {
+ fullname.assign(driver->name).append(".jpg");
+ render_load_jpeg(*tmp_bitmap, snapfile, nullptr, fullname.c_str());
+ }
+ }
+
+ // if fail again, attemp to load from parent file
+ if (!tmp_bitmap->valid())
+ {
+ // set clone status
+ bool cloneof = strcmp(driver->parent, "0");
+ if (cloneof)
+ {
+ int cx = driver_list::find(driver->parent);
+ if (cx != -1 && ((driver_list::driver(cx).flags & MACHINE_IS_BIOS_ROOT) != 0))
+ cloneof = false;
+ }
+
+ if (cloneof)
+ {
+ fullname.assign(driver->parent).append(".png");
+ render_load_png(*tmp_bitmap, snapfile, nullptr, fullname.c_str());
+
+ if (!tmp_bitmap->valid())
+ {
+ fullname.assign(driver->parent).append(".jpg");
+ render_load_jpeg(*tmp_bitmap, snapfile, nullptr, fullname.c_str());
+ }
+ }
+ }
+
+ olddriver = driver;
+ ui_globals::switch_image = false;
+ arts_render_images(tmp_bitmap, origx1, origy1, origx2, origy2, false);
+ auto_free(machine(), tmp_bitmap);
+ }
+
+ // if the image is available, loaded and valid, display it
+ if (snapx_bitmap->valid())
+ {
+ float x1 = origx1 + 0.01f;
+ float x2 = origx2 - 0.01f;
+ float y1 = origy1 + UI_BOX_TB_BORDER + line_height;
+ float y2 = origy2 - UI_BOX_TB_BORDER - line_height;
+
+ // apply texture
+ container->add_quad( x1, y1, x2, y2, ARGB_WHITE, snapx_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ }
+ }
+ else if (soft != nullptr)
+ {
+ std::string fullname, pathname;
+ if (ui_globals::default_image)
+ (soft->startempty == 0) ? ui_globals::curimage_view = SNAPSHOT_VIEW : ui_globals::curimage_view = CABINETS_VIEW;
+
+ // arts title and searchpath
+ std::string searchstr;
+ searchstr = arts_render_common(origx1, origy1, origx2, origy2);
+
+ // loads the image if necessary
+ if (soft != oldsoft || !snapx_bitmap->valid() || ui_globals::switch_image)
+ {
+ emu_file snapfile(searchstr.c_str(), OPEN_FLAG_READ);
+ bitmap_argb32 *tmp_bitmap;
+ tmp_bitmap = auto_alloc(machine(), bitmap_argb32);
+
+ if (soft->startempty == 1)
+ {
+ // Load driver snapshot
+ fullname.assign(soft->driver->name).append(".png");
+ render_load_png(*tmp_bitmap, snapfile, nullptr, fullname.c_str());
+
+ if (!tmp_bitmap->valid())
+ {
+ fullname.assign(soft->driver->name).append(".jpg");
+ render_load_jpeg(*tmp_bitmap, snapfile, nullptr, fullname.c_str());
+ }
+ }
+ else if (ui_globals::curimage_view == TITLES_VIEW)
+ {
+ // First attempt from name list
+ pathname.assign(soft->listname).append("_titles");
+ fullname.assign(soft->shortname).append(".png");
+ render_load_png(*tmp_bitmap, snapfile, pathname.c_str(), fullname.c_str());
+
+ if (!tmp_bitmap->valid())
+ {
+ fullname.assign(soft->shortname).append(".jpg");
+ render_load_jpeg(*tmp_bitmap, snapfile, pathname.c_str(), fullname.c_str());
+ }
+ }
+ else
+ {
+ // First attempt from name list
+ pathname = soft->listname;
+ fullname.assign(soft->shortname).append(".png");
+ render_load_png(*tmp_bitmap, snapfile, pathname.c_str(), fullname.c_str());
+
+ if (!tmp_bitmap->valid())
+ {
+ fullname.assign(soft->shortname).append(".jpg");
+ render_load_jpeg(*tmp_bitmap, snapfile, pathname.c_str(), fullname.c_str());
+ }
+
+ if (!tmp_bitmap->valid())
+ {
+ // Second attempt from driver name + part name
+ pathname.assign(soft->driver->name).append(soft->part);
+ fullname.assign(soft->shortname).append(".png");
+ render_load_png(*tmp_bitmap, snapfile, pathname.c_str(), fullname.c_str());
+
+ if (!tmp_bitmap->valid())
+ {
+ fullname.assign(soft->shortname).append(".jpg");
+ render_load_jpeg(*tmp_bitmap, snapfile, pathname.c_str(), fullname.c_str());
+ }
+ }
+ }
+
+ oldsoft = soft;
+ ui_globals::switch_image = false;
+ arts_render_images(tmp_bitmap, origx1, origy1, origx2, origy2, true);
+ auto_free(machine(), tmp_bitmap);
+ }
+
+ // if the image is available, loaded and valid, display it
+ if (snapx_bitmap->valid())
+ {
+ float x1 = origx1 + 0.01f;
+ float x2 = origx2 - 0.01f;
+ float y1 = origy1 + UI_BOX_TB_BORDER + line_height;
+ float y2 = origy2 - UI_BOX_TB_BORDER - line_height;
+
+ // apply texture
+ container->add_quad(x1, y1, x2, y2, ARGB_WHITE, snapx_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ }
+ }
+}
+
+void ui_menu_select_software::draw_right_panel(void *selectedref, float origx1, float origy1, float origx2, float origy2)
+{
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+ rgb_t fgcolor = UI_TEXT_COLOR;
+ bool hide = (ui_globals::panels_status == HIDE_RIGHT_PANEL || ui_globals::panels_status == HIDE_BOTH);
+ float x2 = (hide) ? origx2 : origx1 + 2.0f * UI_BOX_LR_BORDER;
+ float space = x2 - origx1;
+ float lr_arrow_width = 0.4f * space * machine().render().ui_aspect();
+
+ // set left-right arrows dimension
+ float ar_x0 = 0.5f * (x2 + origx1) - 0.5f * lr_arrow_width;
+ float ar_y0 = 0.5f * (origy2 + origy1) + 0.1f * space;
+ float ar_x1 = ar_x0 + lr_arrow_width;
+ float ar_y1 = 0.5f * (origy2 + origy1) + 0.9f * space;
+
+ mui.draw_outlined_box(container, origx1, origy1, origx2, origy2, rgb_t(0xEF, 0x12, 0x47, 0x7B));
+
+ if (mouse_hit && origx1 <= mouse_x && x2 > mouse_x && origy1 <= mouse_y && origy2 > mouse_y)
+ {
+ fgcolor = UI_MOUSEOVER_COLOR;
+ hover = HOVER_RPANEL_ARROW;
+ }
+
+ if (hide)
+ {
+ draw_arrow(container, ar_x0, ar_y0, ar_x1, ar_y1, fgcolor, ROT90 ^ ORIENTATION_FLIP_X);
+ return;
+ }
+
+ draw_arrow(container, ar_x0, ar_y0, ar_x1, ar_y1, fgcolor, ROT90);
+ origx1 = x2;
+ origy1 = draw_right_box_title(origx1, origy1, origx2, origy2);
+
+ if (ui_globals::rpanel == RP_IMAGES)
+ arts_render(selectedref, origx1, origy1, origx2, origy2);
+ else
+ infos_render(selectedref, origx1, origy1, origx2, origy2);
+}
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+ui_software_parts::ui_software_parts(running_machine &machine, render_container *container, s_parts parts, ui_software_info *ui_info) : ui_menu(machine, container)
+{
+ m_parts = parts;
+ m_uiinfo = ui_info;
+}
+
+//-------------------------------------------------
+// dtor
+//-------------------------------------------------
+
+ui_software_parts::~ui_software_parts()
+{
+}
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_software_parts::populate()
+{
+ for (auto & elem : m_parts)
+ item_append(elem.first.c_str(), elem.second.c_str(), 0, (void *)&elem);
+
+ item_append(ui_menu_item_type::SEPARATOR);
+ customtop = mame_machine_manager::instance()->ui().get_line_height() + (3.0f * UI_BOX_TB_BORDER);
+}
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_software_parts::handle()
+{
+ // process the menu
+ const ui_menu_event *event = process(0);
+ if (event != nullptr && event->iptkey == IPT_UI_SELECT && event->itemref != nullptr)
+ for (auto & elem : m_parts)
+ if ((void*)&elem == event->itemref)
+ {
+ std::string error_string;
+ std::string string_list = std::string(m_uiinfo->listname).append(":").append(m_uiinfo->shortname).append(":").append(elem.first).append(":").append(m_uiinfo->instance);
+ machine().options().set_value(OPTION_SOFTWARENAME, string_list.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
+
+ reselect_last::driver = m_uiinfo->driver->name;
+ reselect_last::software = m_uiinfo->shortname;
+ reselect_last::swlist = m_uiinfo->listname;
+ reselect_last::set(true);
+
+ std::string snap_list = std::string(m_uiinfo->listname).append("/").append(m_uiinfo->shortname);
+ machine().options().set_value(OPTION_SNAPNAME, snap_list.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
+
+ mame_machine_manager::instance()->schedule_new_driver(*m_uiinfo->driver);
+ machine().schedule_hard_reset();
+ ui_menu::stack_reset(machine());
+ }
+}
+
+//-------------------------------------------------
+// perform our special rendering
+//-------------------------------------------------
+
+void ui_software_parts::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ float width;
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+ mui.draw_text_full(container, _("Software part selection:"), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += 2 * UI_BOX_LR_BORDER;
+ float maxwidth = MAX(origx2 - origx1, width);
+
+ // compute our bounds
+ float x1 = 0.5f - 0.5f * maxwidth;
+ float x2 = x1 + maxwidth;
+ float y1 = origy1 - top;
+ float y2 = origy1 - UI_BOX_TB_BORDER;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ mui.draw_text_full(container, _("Software part selection:"), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+}
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+ui_bios_selection::ui_bios_selection(running_machine &machine, render_container *container, s_bios biosname, void *_driver, bool _software, bool _inlist) : ui_menu(machine, container)
+{
+ m_bios = biosname;
+ m_driver = _driver;
+ m_software = _software;
+ m_inlist = _inlist;
+}
+
+//-------------------------------------------------
+// dtor
+//-------------------------------------------------
+
+ui_bios_selection::~ui_bios_selection()
+{
+}
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_bios_selection::populate()
+{
+ for (auto & elem : m_bios)
+ item_append(elem.first.c_str(), nullptr, 0, (void *)&elem.first);
+
+ item_append(ui_menu_item_type::SEPARATOR);
+ customtop = mame_machine_manager::instance()->ui().get_line_height() + (3.0f * UI_BOX_TB_BORDER);
+}
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_bios_selection::handle()
+{
+ // process the menu
+ const ui_menu_event *event = process(0);
+ emu_options &moptions = machine().options();
+ if (event != nullptr && event->iptkey == IPT_UI_SELECT && event->itemref != nullptr)
+ for (auto & elem : m_bios)
+ if ((void*)&elem.first == event->itemref)
+ {
+ if (!m_software)
+ {
+ const game_driver *s_driver = (const game_driver *)m_driver;
+ reselect_last::driver = s_driver->name;
+ if (m_inlist)
+ reselect_last::software = "[Start empty]";
+ else
+ {
+ reselect_last::software.clear();
+ reselect_last::swlist.clear();
+ reselect_last::set(true);
+ }
+
+ std::string error;
+ moptions.set_value(OPTION_BIOS, elem.second, OPTION_PRIORITY_CMDLINE, error);
+ mame_machine_manager::instance()->schedule_new_driver(*s_driver);
+ machine().schedule_hard_reset();
+ ui_menu::stack_reset(machine());
+ }
+ else
+ {
+ ui_software_info *ui_swinfo = (ui_software_info *)m_driver;
+ std::string error;
+ machine().options().set_value(OPTION_BIOS, elem.second, OPTION_PRIORITY_CMDLINE, error);
+ driver_enumerator drivlist(machine().options(), *ui_swinfo->driver);
+ drivlist.next();
+ software_list_device *swlist = software_list_device::find_by_name(drivlist.config(), ui_swinfo->listname.c_str());
+ software_info *swinfo = swlist->find(ui_swinfo->shortname.c_str());
+ if (!mame_machine_manager::instance()->ui().options().skip_parts_menu() && swinfo->has_multiple_parts(ui_swinfo->interface.c_str()))
+ {
+ s_parts parts;
+ for (const software_part &swpart : swinfo->parts())
+ {
+ if (swpart.matches_interface(ui_swinfo->interface.c_str()))
+ {
+ std::string menu_part_name(swpart.name());
+ if (swpart.feature("part_id") != nullptr)
+ menu_part_name.assign("(").append(swpart.feature("part_id")).append(")");
+ parts.emplace(swpart.name(), menu_part_name);
+ }
+ }
+ ui_menu::stack_push(global_alloc_clear<ui_software_parts>(machine(), container, parts, ui_swinfo));
+ return;
+ }
+ std::string error_string;
+ std::string string_list = std::string(ui_swinfo->listname).append(":").append(ui_swinfo->shortname).append(":").append(ui_swinfo->part).append(":").append(ui_swinfo->instance);
+ moptions.set_value(OPTION_SOFTWARENAME, string_list.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
+ std::string snap_list = std::string(ui_swinfo->listname).append(PATH_SEPARATOR).append(ui_swinfo->shortname);
+ moptions.set_value(OPTION_SNAPNAME, snap_list.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
+ reselect_last::driver = drivlist.driver().name;
+ reselect_last::software = ui_swinfo->shortname;
+ reselect_last::swlist = ui_swinfo->listname;
+ reselect_last::set(true);
+ mame_machine_manager::instance()->schedule_new_driver(drivlist.driver());
+ machine().schedule_hard_reset();
+ ui_menu::stack_reset(machine());
+ }
+ }
+}
+
+//-------------------------------------------------
+// perform our special rendering
+//-------------------------------------------------
+
+void ui_bios_selection::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ float width;
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+ mui.draw_text_full(container, _("Bios selection:"), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += 2 * UI_BOX_LR_BORDER;
+ float maxwidth = MAX(origx2 - origx1, width);
+
+ // compute our bounds
+ float x1 = 0.5f - 0.5f * maxwidth;
+ float x2 = x1 + maxwidth;
+ float y1 = origy1 - top;
+ float y2 = origy1 - UI_BOX_TB_BORDER;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ mui.draw_text_full(container, _("Bios selection:"), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+}
diff --git a/src/frontend/mame/ui/selsoft.h b/src/frontend/mame/ui/selsoft.h
new file mode 100644
index 00000000000..64ce0ac4cdb
--- /dev/null
+++ b/src/frontend/mame/ui/selsoft.h
@@ -0,0 +1,110 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/***************************************************************************
+
+ ui/selsoft.h
+
+ UI software menu.
+
+***************************************************************************/
+#pragma once
+
+#ifndef __UI_SELSOFT_H__
+#define __UI_SELSOFT_H__
+
+#include "ui/custmenu.h"
+
+using s_bios = std::vector<std::pair<std::string, int>>;
+using s_parts = std::unordered_map<std::string, std::string>;
+
+// Menu Class
+class ui_menu_select_software : public ui_menu
+{
+public:
+ ui_menu_select_software(running_machine &machine, render_container *container, const game_driver *driver);
+ virtual ~ui_menu_select_software();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+ virtual bool menu_has_search_active() override { return (m_search[0] != 0); }
+
+ // draw left panel
+ virtual float draw_left_panel(float x1, float y1, float x2, float y2) override;
+
+ // draw right panel
+ virtual void draw_right_panel(void *selectedref, float origx1, float origy1, float origx2, float origy2) override;
+
+private:
+ enum { VISIBLE_GAMES_IN_SEARCH = 200 };
+ char m_search[40];
+ const game_driver *m_driver;
+ bool m_has_empty_start;
+ s_filter m_filter;
+ int highlight;
+
+ ui_software_info *m_searchlist[VISIBLE_GAMES_IN_SEARCH + 1];
+ std::vector<ui_software_info *> m_displaylist, m_tmp, m_sortedlist;
+ std::vector<ui_software_info> m_swinfo;
+
+ void build_software_list();
+ void build_list(std::vector<ui_software_info *> &vec, const char *filter_text = nullptr, int filter = -1);
+ void build_custom();
+ void find_matches(const char *str, int count);
+ void load_sw_custom_filters();
+
+ void arts_render(void *selectedref, float x1, float y1, float x2, float y2);
+ void infos_render(void *selectedref, float x1, float y1, float x2, float y2);
+
+ // handlers
+ void inkey_select(const ui_menu_event *menu_event);
+ void inkey_special(const ui_menu_event *menu_event);
+ void inkey_configure(const ui_menu_event *menu_event);
+};
+
+class ui_software_parts : public ui_menu
+{
+public:
+ ui_software_parts(running_machine &machine, render_container *container, s_parts parts, ui_software_info *ui_info);
+ virtual ~ui_software_parts();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+private:
+ ui_software_info *m_uiinfo;
+ s_parts m_parts;
+};
+
+class ui_bios_selection : public ui_menu
+{
+public:
+ ui_bios_selection(running_machine &machine, render_container *container, s_bios biosname, void *driver, bool software, bool inlist);
+ virtual ~ui_bios_selection();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+private:
+
+ void *m_driver;
+ bool m_software, m_inlist;
+ s_bios m_bios;
+};
+
+struct reselect_last
+{
+ static std::string driver, software, swlist;
+ static void set(bool value) { m_reselect = value; }
+ static bool get() { return m_reselect; }
+ static void reset() { driver.clear(); software.clear(); swlist.clear(); set(false); }
+
+private:
+ static bool m_reselect;
+};
+
+// Getter
+bool has_multiple_bios(const game_driver *driver, s_bios &biosname);
+
+
+#endif /* __UI_SELSOFT_H__ */
diff --git a/src/frontend/mame/ui/simpleselgame.cpp b/src/frontend/mame/ui/simpleselgame.cpp
new file mode 100644
index 00000000000..16818ea2c8c
--- /dev/null
+++ b/src/frontend/mame/ui/simpleselgame.cpp
@@ -0,0 +1,446 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/***************************************************************************
+
+ ui/simpleselgame.cpp
+
+ Game selector
+
+***************************************************************************/
+
+#include "emu.h"
+#include "mame.h"
+#include "emuopts.h"
+#include "ui/ui.h"
+#include "ui/menu.h"
+#include "uiinput.h"
+#include "ui/simpleselgame.h"
+#include "ui/inputmap.h"
+#include "ui/miscmenu.h"
+#include "ui/optsmenu.h"
+#include "audit.h"
+#include <ctype.h>
+
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+ui_simple_menu_select_game::ui_simple_menu_select_game(running_machine &machine, render_container *container, const char *gamename) : ui_menu(machine, container), m_driverlist(driver_list::total() + 1)
+{
+ build_driver_list();
+ if(gamename)
+ strcpy(m_search, gamename);
+ m_matchlist[0] = -1;
+}
+
+
+//-------------------------------------------------
+// dtor
+//-------------------------------------------------
+
+ui_simple_menu_select_game::~ui_simple_menu_select_game()
+{
+}
+
+
+
+//-------------------------------------------------
+// build_driver_list - build a list of available
+// drivers
+//-------------------------------------------------
+
+void ui_simple_menu_select_game::build_driver_list()
+{
+ // start with an empty list
+ m_drivlist = std::make_unique<driver_enumerator>(machine().options());
+ m_drivlist->exclude_all();
+
+ // open a path to the ROMs and find them in the array
+ file_enumerator path(machine().options().media_path());
+ const osd_directory_entry *dir;
+
+ // iterate while we get new objects
+ while ((dir = path.next()) != nullptr)
+ {
+ char drivername[50];
+ char *dst = drivername;
+ const char *src;
+
+ // build a name for it
+ for (src = dir->name; *src != 0 && *src != '.' && dst < &drivername[ARRAY_LENGTH(drivername) - 1]; src++)
+ *dst++ = tolower((UINT8)*src);
+ *dst = 0;
+
+ int drivnum = m_drivlist->find(drivername);
+ if (drivnum != -1)
+ m_drivlist->include(drivnum);
+ }
+
+ // now build the final list
+ m_drivlist->reset();
+ int listnum = 0;
+ while (m_drivlist->next())
+ m_driverlist[listnum++] = &m_drivlist->driver();
+
+ // NULL-terminate
+ m_driverlist[listnum] = nullptr;
+}
+
+
+
+//-------------------------------------------------
+// handle - handle the game select menu
+//-------------------------------------------------
+
+void ui_simple_menu_select_game::handle()
+{
+ // ignore pause keys by swallowing them before we process the menu
+ machine().ui_input().pressed(IPT_UI_PAUSE);
+
+ // process the menu
+ const ui_menu_event *menu_event = process(0);
+ if (menu_event != nullptr && menu_event->itemref != nullptr)
+ {
+ // reset the error on any future menu_event
+ if (m_error)
+ {
+ m_error = false;
+ machine().ui_input().reset();
+ }
+
+ // handle selections
+ else
+ {
+ switch(menu_event->iptkey)
+ {
+ case IPT_UI_SELECT:
+ inkey_select(menu_event);
+ break;
+ case IPT_UI_CANCEL:
+ inkey_cancel(menu_event);
+ break;
+ case IPT_SPECIAL:
+ inkey_special(menu_event);
+ break;
+ }
+ }
+ }
+
+ // if we're in an error state, overlay an error message
+ if (m_error)
+ mame_machine_manager::instance()->ui().draw_text_box(container,
+ "The selected game is missing one or more required ROM or CHD images. "
+ "Please select a different game.\n\nPress any key to continue.",
+ JUSTIFY_CENTER, 0.5f, 0.5f, UI_RED_COLOR);
+}
+
+
+//-------------------------------------------------
+// inkey_select
+//-------------------------------------------------
+
+void ui_simple_menu_select_game::inkey_select(const ui_menu_event *menu_event)
+{
+ const game_driver *driver = (const game_driver *)menu_event->itemref;
+
+ // special case for configure inputs
+ if ((FPTR)driver == 1)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_game_options>(machine(), container));
+ // anything else is a driver
+ else
+ {
+ // audit the game first to see if we're going to work
+ driver_enumerator enumerator(machine().options(), *driver);
+ enumerator.next();
+ media_auditor auditor(enumerator);
+ media_auditor::summary summary = auditor.audit_media(AUDIT_VALIDATE_FAST);
+
+ // if everything looks good, schedule the new driver
+ if (summary == media_auditor::CORRECT || summary == media_auditor::BEST_AVAILABLE || summary == media_auditor::NONE_NEEDED)
+ {
+ mame_machine_manager::instance()->schedule_new_driver(*driver);
+ machine().schedule_hard_reset();
+ ui_menu::stack_reset(machine());
+ }
+
+ // otherwise, display an error
+ else
+ {
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ m_error = true;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// inkey_cancel
+//-------------------------------------------------
+
+void ui_simple_menu_select_game::inkey_cancel(const ui_menu_event *menu_event)
+{
+ // escape pressed with non-empty text clears the text
+ if (m_search[0] != 0)
+ {
+ m_search[0] = '\0';
+ reset(UI_MENU_RESET_SELECT_FIRST);
+ }
+}
+
+
+//-------------------------------------------------
+// inkey_special - typed characters append to the buffer
+//-------------------------------------------------
+
+void ui_simple_menu_select_game::inkey_special(const ui_menu_event *menu_event)
+{
+ // typed characters append to the buffer
+ int buflen = strlen(m_search);
+
+ // if it's a backspace and we can handle it, do so
+ if ((menu_event->unichar == 8 || menu_event->unichar == 0x7f) && buflen > 0)
+ {
+ *(char *)utf8_previous_char(&m_search[buflen]) = 0;
+ m_rerandomize = true;
+ reset(UI_MENU_RESET_SELECT_FIRST);
+ }
+
+ // if it's any other key and we're not maxed out, update
+ else if (menu_event->unichar >= ' ' && menu_event->unichar < 0x7f)
+ {
+ buflen += utf8_from_uchar(&m_search[buflen], ARRAY_LENGTH(m_search) - buflen, menu_event->unichar);
+ m_search[buflen] = 0;
+ reset(UI_MENU_RESET_SELECT_FIRST);
+ }
+}
+
+
+//-------------------------------------------------
+// populate - populate the game select menu
+//-------------------------------------------------
+
+void ui_simple_menu_select_game::populate()
+{
+ int matchcount;
+ int curitem;
+
+ for (curitem = matchcount = 0; m_driverlist[curitem] != nullptr && matchcount < VISIBLE_GAMES_IN_LIST; curitem++)
+ if (!(m_driverlist[curitem]->flags & MACHINE_NO_STANDALONE))
+ matchcount++;
+
+ // if nothing there, add a single multiline item and return
+ if (matchcount == 0)
+ {
+ std::string txt = string_format(
+ _("No machines found. Please check the rompath specified in the %1$s.ini file.\n\n"
+ "If this is your first time using %2$s, please see the config.txt file in "
+ "the docs directory for information on configuring %2$s."),
+ emulator_info::get_configname(),
+ emulator_info::get_appname());
+ item_append(txt.c_str(), nullptr, MENU_FLAG_MULTILINE | MENU_FLAG_REDTEXT, nullptr);
+ return;
+ }
+
+ // otherwise, rebuild the match list
+ assert(m_drivlist != nullptr);
+ if (m_search[0] != 0 || m_matchlist[0] == -1 || m_rerandomize)
+ m_drivlist->find_approximate_matches(m_search, matchcount, m_matchlist);
+ m_rerandomize = false;
+
+ // iterate over entries
+ for (curitem = 0; curitem < matchcount; curitem++)
+ {
+ int curmatch = m_matchlist[curitem];
+ if (curmatch != -1)
+ {
+ int cloneof = m_drivlist->non_bios_clone(curmatch);
+ item_append(m_drivlist->driver(curmatch).name, m_drivlist->driver(curmatch).description, (cloneof == -1) ? 0 : MENU_FLAG_INVERT, (void *)&m_drivlist->driver(curmatch));
+ }
+ }
+
+ // if we're forced into this, allow general input configuration as well
+ if (ui_menu::stack_has_special_main_menu())
+ {
+ item_append(ui_menu_item_type::SEPARATOR);
+ item_append(_("Configure Options"), nullptr, 0, (void *)1);
+ skip_main_items = 1;
+ }
+
+ // configure the custom rendering
+ customtop = mame_machine_manager::instance()->ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER;
+ custombottom = 4.0f * mame_machine_manager::instance()->ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER;
+}
+
+
+//-------------------------------------------------
+// custom_render - perform our special rendering
+//-------------------------------------------------
+
+void ui_simple_menu_select_game::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ const game_driver *driver;
+ float width, maxwidth;
+ float x1, y1, x2, y2;
+ std::string tempbuf[5];
+ rgb_t color;
+ int line;
+
+ // display the current typeahead
+ if (m_search[0] != 0)
+ tempbuf[0] = string_format(_("Type name or select: %1$s_"), m_search);
+ else
+ tempbuf[0] = _("Type name or select: (random)");
+
+ // get the size of the text
+ mame_machine_manager::instance()->ui().draw_text_full(container, tempbuf[0].c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += 2 * UI_BOX_LR_BORDER;
+ maxwidth = MAX(width, origx2 - origx1);
+
+ // compute our bounds
+ x1 = 0.5f - 0.5f * maxwidth;
+ x2 = x1 + maxwidth;
+ y1 = origy1 - top;
+ y2 = origy1 - UI_BOX_TB_BORDER;
+
+ // draw a box
+ mame_machine_manager::instance()->ui().draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ mame_machine_manager::instance()->ui().draw_text_full(container, tempbuf[0].c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+
+ // determine the text to render below
+ driver = ((FPTR)selectedref > skip_main_items) ? (const game_driver *)selectedref : nullptr;
+ if (driver != nullptr)
+ {
+ const char *gfxstat, *soundstat;
+
+ // first line is game name
+ tempbuf[0] = string_format(_("%1$-.100s"), driver->description);
+
+ // next line is year, manufacturer
+ tempbuf[1] = string_format(_("%1$s, %2$-.100s"), driver->year, driver->manufacturer);
+
+ // next line source path
+ tempbuf[2] = string_format(_("Driver: %1$-.100s"), core_filename_extract_base(driver->source_file).c_str());
+
+ // next line is overall driver status
+ if (driver->flags & MACHINE_NOT_WORKING)
+ tempbuf[3].assign(_("Overall: NOT WORKING"));
+ else if (driver->flags & MACHINE_UNEMULATED_PROTECTION)
+ tempbuf[3].assign(_("Overall: Unemulated Protection"));
+ else
+ tempbuf[3].assign(_("Overall: Working"));
+
+ // next line is graphics, sound status
+ if (driver->flags & (MACHINE_IMPERFECT_GRAPHICS | MACHINE_WRONG_COLORS | MACHINE_IMPERFECT_COLORS))
+ gfxstat = _("Imperfect");
+ else
+ gfxstat = _("OK");
+
+ if (driver->flags & MACHINE_NO_SOUND)
+ soundstat = _("Unimplemented");
+ else if (driver->flags & MACHINE_IMPERFECT_SOUND)
+ soundstat = _("Imperfect");
+ else
+ soundstat = _("OK");
+
+ tempbuf[4] = string_format(_("Gfx: %s, Sound: %s"), gfxstat, soundstat);
+ }
+ else
+ {
+ const char *s = emulator_info::get_copyright();
+ line = 0;
+
+ // first line is version string
+ tempbuf[line++] = string_format("%s %s", emulator_info::get_appname(), build_version);
+
+ // output message
+ while (line < ARRAY_LENGTH(tempbuf))
+ {
+ if (!(*s == 0 || *s == '\n'))
+ tempbuf[line].push_back(*s);
+
+ if (*s == '\n')
+ {
+ line++;
+ s++;
+ } else if (*s != 0)
+ s++;
+ else
+ line++;
+ }
+ }
+
+ // get the size of the text
+ maxwidth = origx2 - origx1;
+ for (line = 0; line < 4; line++)
+ {
+ mame_machine_manager::instance()->ui().draw_text_full(container, tempbuf[line].c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += 2 * UI_BOX_LR_BORDER;
+ maxwidth = MAX(maxwidth, width);
+ }
+
+ // compute our bounds
+ x1 = 0.5f - 0.5f * maxwidth;
+ x2 = x1 + maxwidth;
+ y1 = origy2 + UI_BOX_TB_BORDER;
+ y2 = origy2 + bottom;
+
+ // draw a box
+ color = UI_BACKGROUND_COLOR;
+ if (driver != nullptr)
+ color = UI_GREEN_COLOR;
+ if (driver != nullptr && (driver->flags & (MACHINE_IMPERFECT_GRAPHICS | MACHINE_WRONG_COLORS | MACHINE_IMPERFECT_COLORS | MACHINE_NO_SOUND | MACHINE_IMPERFECT_SOUND)) != 0)
+ color = UI_YELLOW_COLOR;
+ if (driver != nullptr && (driver->flags & (MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION)) != 0)
+ color = UI_RED_COLOR;
+ mame_machine_manager::instance()->ui().draw_outlined_box(container, x1, y1, x2, y2, color);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw all lines
+ for (line = 0; line < 4; line++)
+ {
+ mame_machine_manager::instance()->ui().draw_text_full(container, tempbuf[line].c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+ y1 += mame_machine_manager::instance()->ui().get_line_height();
+ }
+}
+
+
+//-------------------------------------------------
+// force_game_select - force the game
+// select menu to be visible and inescapable
+//-------------------------------------------------
+
+void ui_simple_menu_select_game::force_game_select(running_machine &machine, render_container *container)
+{
+ char *gamename = (char *)machine.options().system_name();
+
+ // reset the menu stack
+ ui_menu::stack_reset(machine);
+
+ // add the quit entry followed by the game select entry
+ ui_menu *quit = global_alloc_clear<ui_menu_quit_game>(machine, container);
+ quit->set_special_main_menu(true);
+ ui_menu::stack_push(quit);
+ ui_menu::stack_push(global_alloc_clear<ui_simple_menu_select_game>(machine, container, gamename));
+
+ // force the menus on
+ mame_machine_manager::instance()->ui().show_menu();
+
+ // make sure MAME is paused
+ machine.pause();
+}
diff --git a/src/frontend/mame/ui/simpleselgame.h b/src/frontend/mame/ui/simpleselgame.h
new file mode 100644
index 00000000000..316e3747b2f
--- /dev/null
+++ b/src/frontend/mame/ui/simpleselgame.h
@@ -0,0 +1,48 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/***************************************************************************
+
+ ui/selgame.h
+
+ Game selector
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_SIMPLESELGAME_H__
+#define __UI_SIMPLESELGAME_H__
+
+#include "drivenum.h"
+#include "menu.h"
+
+class ui_simple_menu_select_game : public ui_menu {
+public:
+ ui_simple_menu_select_game(running_machine &machine, render_container *container, const char *gamename);
+ virtual ~ui_simple_menu_select_game();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+ // force game select menu
+ static void force_game_select(running_machine &machine, render_container *container);
+
+ virtual bool menu_has_search_active() override { return (m_search[0] != 0); }
+private:
+ // internal state
+ enum { VISIBLE_GAMES_IN_LIST = 15 };
+ UINT8 m_error;
+ bool m_rerandomize;
+ char m_search[40];
+ int m_matchlist[VISIBLE_GAMES_IN_LIST];
+ std::vector<const game_driver *> m_driverlist;
+ std::unique_ptr<driver_enumerator> m_drivlist;
+
+ // internal methods
+ void build_driver_list();
+ void inkey_select(const ui_menu_event *menu_event);
+ void inkey_cancel(const ui_menu_event *menu_event);
+ void inkey_special(const ui_menu_event *menu_event);
+};
+
+#endif /* __UI_SELGAME_H__ */
diff --git a/src/frontend/mame/ui/sliders.cpp b/src/frontend/mame/ui/sliders.cpp
new file mode 100644
index 00000000000..8ec21b8894c
--- /dev/null
+++ b/src/frontend/mame/ui/sliders.cpp
@@ -0,0 +1,283 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/*********************************************************************
+
+ ui/sliders.cpp
+
+ Internal MAME menus for the user interface.
+
+*********************************************************************/
+
+#include "emu.h"
+
+#include "osdepend.h"
+#include "uiinput.h"
+#include "ui/ui.h"
+#include "ui/menu.h"
+#include "ui/sliders.h"
+
+
+ui_menu_sliders::ui_menu_sliders(running_machine &machine, render_container *container, bool menuless_mode) : ui_menu(machine, container)
+{
+ m_menuless_mode = m_hidden = menuless_mode;
+}
+
+ui_menu_sliders::~ui_menu_sliders()
+{
+}
+
+/*-------------------------------------------------
+ menu_sliders - handle the sliders menu
+-------------------------------------------------*/
+
+void ui_menu_sliders::handle()
+{
+ const ui_menu_event *menu_event;
+
+ /* process the menu */
+ menu_event = process(UI_MENU_PROCESS_LR_REPEAT | (m_hidden ? UI_MENU_PROCESS_CUSTOM_ONLY : 0));
+ if (menu_event != nullptr)
+ {
+ /* handle keys if there is a valid item selected */
+ if (menu_event->itemref != nullptr && menu_event->type == ui_menu_item_type::SLIDER)
+ {
+ const slider_state *slider = (const slider_state *)menu_event->itemref;
+ INT32 curvalue = (*slider->update)(machine(), slider->arg, slider->id, nullptr, SLIDER_NOCHANGE);
+ INT32 increment = 0;
+ bool alt_pressed = machine().input().code_pressed(KEYCODE_LALT) || machine().input().code_pressed(KEYCODE_RALT);
+ bool ctrl_pressed = machine().input().code_pressed(KEYCODE_LCONTROL) || machine().input().code_pressed(KEYCODE_RCONTROL);
+ bool shift_pressed = machine().input().code_pressed(KEYCODE_LSHIFT) || machine().input().code_pressed(KEYCODE_RSHIFT);
+
+ switch (menu_event->iptkey)
+ {
+ /* toggle visibility */
+ case IPT_UI_ON_SCREEN_DISPLAY:
+ if (m_menuless_mode)
+ ui_menu::stack_pop(machine());
+ else
+ m_hidden = !m_hidden;
+ break;
+
+ /* decrease value */
+ case IPT_UI_LEFT:
+ if (alt_pressed && shift_pressed)
+ increment = -1;
+ if (alt_pressed)
+ increment = -(curvalue - slider->minval);
+ else if (shift_pressed)
+ increment = (slider->incval > 10) ? -(slider->incval / 10) : -1;
+ else if (ctrl_pressed)
+ increment = -slider->incval * 10;
+ else
+ increment = -slider->incval;
+ break;
+
+ /* increase value */
+ case IPT_UI_RIGHT:
+ if (alt_pressed && shift_pressed)
+ increment = 1;
+ if (alt_pressed)
+ increment = slider->maxval - curvalue;
+ else if (shift_pressed)
+ increment = (slider->incval > 10) ? (slider->incval / 10) : 1;
+ else if (ctrl_pressed)
+ increment = slider->incval * 10;
+ else
+ increment = slider->incval;
+ break;
+
+ /* restore default */
+ case IPT_UI_SELECT:
+ increment = slider->defval - curvalue;
+ break;
+ }
+
+ /* handle any changes */
+ if (increment != 0)
+ {
+ INT32 newvalue = curvalue + increment;
+
+ /* clamp within bounds */
+ if (newvalue < slider->minval)
+ newvalue = slider->minval;
+ if (newvalue > slider->maxval)
+ newvalue = slider->maxval;
+
+ /* update the slider and recompute the menu */
+ (*slider->update)(machine(), slider->arg, slider->id, nullptr, newvalue);
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ }
+ }
+
+ /* if we are selecting an invalid item and we are hidden, skip to the next one */
+ else if (m_hidden)
+ {
+ /* if we got here via up or page up, select the previous item */
+ if (menu_event->iptkey == IPT_UI_UP || menu_event->iptkey == IPT_UI_PAGE_UP)
+ {
+ selected = (selected + item.size() - 1) % item.size();
+ validate_selection(-1);
+ }
+
+ /* otherwise select the next item */
+ else if (menu_event->iptkey == IPT_UI_DOWN || menu_event->iptkey == IPT_UI_PAGE_DOWN)
+ {
+ selected = (selected + 1) % item.size();
+ validate_selection(1);
+ }
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ menu_sliders_populate - populate the sliders
+ menu
+-------------------------------------------------*/
+
+void ui_menu_sliders::populate()
+{
+ std::string tempstring;
+
+ /* add UI sliders */
+ std::vector<ui_menu_item> ui_sliders = mame_machine_manager::instance()->ui().get_slider_list();
+ for (ui_menu_item item : ui_sliders)
+ {
+ if (item.type == ui_menu_item_type::SLIDER)
+ {
+ slider_state* slider = reinterpret_cast<slider_state *>(item.ref);
+ INT32 curval = (*slider->update)(machine(), slider->arg, slider->id, &tempstring, SLIDER_NOCHANGE);
+ UINT32 flags = 0;
+ if (curval > slider->minval)
+ flags |= MENU_FLAG_LEFT_ARROW;
+ if (curval < slider->maxval)
+ flags |= MENU_FLAG_RIGHT_ARROW;
+ item_append(slider->description, tempstring.c_str(), flags, (void *)slider, ui_menu_item_type::SLIDER);
+ }
+ else
+ {
+ item_append(item);
+ }
+ }
+
+ item_append(ui_menu_item_type::SEPARATOR);
+
+ /* add OSD options */
+ std::vector<ui_menu_item> osd_sliders = machine().osd().get_slider_list();
+ for (ui_menu_item item : osd_sliders)
+ {
+ if (item.type == ui_menu_item_type::SLIDER)
+ {
+ slider_state* slider = reinterpret_cast<slider_state *>(item.ref);
+ INT32 curval = (*slider->update)(machine(), slider->arg, slider->id, &tempstring, SLIDER_NOCHANGE);
+ UINT32 flags = 0;
+ if (curval > slider->minval)
+ flags |= MENU_FLAG_LEFT_ARROW;
+ if (curval < slider->maxval)
+ flags |= MENU_FLAG_RIGHT_ARROW;
+ item_append(slider->description, tempstring.c_str(), flags, (void *)slider, ui_menu_item_type::SLIDER);
+ }
+ else
+ {
+ item_append(item);
+ }
+ }
+
+ custombottom = 2.0f * mame_machine_manager::instance()->ui().get_line_height() + 2.0f * UI_BOX_TB_BORDER;
+}
+
+/*-------------------------------------------------
+ menu_sliders_custom_render - perform our special
+ rendering
+-------------------------------------------------*/
+
+void ui_menu_sliders::custom_render(void *selectedref, float top, float bottom, float x1, float y1, float x2, float y2)
+{
+ const slider_state *curslider = (const slider_state *)selectedref;
+ if (curslider != nullptr)
+ {
+ float bar_left, bar_area_top, bar_width, bar_area_height, bar_top, bar_bottom, default_x, current_x;
+ float line_height = mame_machine_manager::instance()->ui().get_line_height();
+ float percentage, default_percentage;
+ std::string tempstring;
+ float text_height;
+ INT32 curval;
+
+ /* determine the current value and text */
+ curval = (*curslider->update)(machine(), curslider->arg, curslider->id, &tempstring, SLIDER_NOCHANGE);
+
+ /* compute the current and default percentages */
+ percentage = (float)(curval - curslider->minval) / (float)(curslider->maxval - curslider->minval);
+ default_percentage = (float)(curslider->defval - curslider->minval) / (float)(curslider->maxval - curslider->minval);
+
+ /* assemble the text */
+ tempstring.insert(0, " ").insert(0, curslider->description);
+
+ /* move us to the bottom of the screen, and expand to full width */
+ y2 = 1.0f - UI_BOX_TB_BORDER;
+ y1 = y2 - bottom;
+ x1 = UI_BOX_LR_BORDER;
+ x2 = 1.0f - UI_BOX_LR_BORDER;
+
+ /* draw extra menu area */
+ mame_machine_manager::instance()->ui().draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
+ y1 += UI_BOX_TB_BORDER;
+
+ /* determine the text height */
+ mame_machine_manager::instance()->ui().draw_text_full(container, tempstring.c_str(), 0, 0, x2 - x1 - 2.0f * UI_BOX_LR_BORDER,
+ JUSTIFY_CENTER, WRAP_TRUNCATE, DRAW_NONE, ARGB_WHITE, ARGB_BLACK, nullptr, &text_height);
+
+ /* draw the thermometer */
+ bar_left = x1 + UI_BOX_LR_BORDER;
+ bar_area_top = y1;
+ bar_width = x2 - x1 - 2.0f * UI_BOX_LR_BORDER;
+ bar_area_height = line_height;
+
+ /* compute positions */
+ bar_top = bar_area_top + 0.125f * bar_area_height;
+ bar_bottom = bar_area_top + 0.875f * bar_area_height;
+ default_x = bar_left + bar_width * default_percentage;
+ current_x = bar_left + bar_width * percentage;
+
+ /* fill in the percentage */
+ container->add_rect(bar_left, bar_top, current_x, bar_bottom, UI_SLIDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+
+ /* draw the top and bottom lines */
+ container->add_line(bar_left, bar_top, bar_left + bar_width, bar_top, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ container->add_line(bar_left, bar_bottom, bar_left + bar_width, bar_bottom, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+
+ /* draw default marker */
+ container->add_line(default_x, bar_area_top, default_x, bar_top, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ container->add_line(default_x, bar_bottom, default_x, bar_area_top + bar_area_height, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+
+ /* draw the actual text */
+ mame_machine_manager::instance()->ui().draw_text_full(container, tempstring.c_str(), x1 + UI_BOX_LR_BORDER, y1 + line_height, x2 - x1 - 2.0f * UI_BOX_LR_BORDER,
+ JUSTIFY_CENTER, WRAP_WORD, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, &text_height);
+ }
+}
+
+
+/*-------------------------------------------------
+ ui_slider_ui_handler - pushes the slider
+ menu on the stack and hands off to the
+ standard menu handler
+ -------------------------------------------------*/
+
+UINT32 ui_menu_sliders::ui_handler(running_machine &machine, render_container *container, UINT32 state)
+{
+ UINT32 result;
+
+ /* if this is the first call, push the sliders menu */
+ if (state)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_sliders>(machine, container, true));
+
+ /* handle standard menus */
+ result = ui_menu::ui_handler(machine, container, state);
+
+ /* if we are cancelled, pop the sliders menu */
+ if (result == UI_HANDLER_CANCEL)
+ ui_menu::stack_pop(machine);
+
+ ui_menu_sliders *uim = dynamic_cast<ui_menu_sliders *>(menu_stack);
+ return uim && uim->m_menuless_mode ? 0 : UI_HANDLER_CANCEL;
+}
diff --git a/src/frontend/mame/ui/sliders.h b/src/frontend/mame/ui/sliders.h
new file mode 100644
index 00000000000..f420b094cbe
--- /dev/null
+++ b/src/frontend/mame/ui/sliders.h
@@ -0,0 +1,39 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/***************************************************************************
+
+ ui/miscmenu.h
+
+ Internal MAME menus for the user interface.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_SLIDERS_H__
+#define __UI_SLIDERS_H__
+
+#include <map>
+
+class ui_menu_sliders : public ui_menu {
+public:
+ ui_menu_sliders(running_machine &machine, render_container *container, bool menuless_mode = false);
+ virtual ~ui_menu_sliders();
+ virtual void populate() override;
+ virtual void handle() override;
+
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+ static UINT32 ui_handler(running_machine &machine, render_container *container, UINT32 state);
+
+private:
+ enum {
+ INPUT_GROUPS,
+ INPUT_SPECIFIC,
+ };
+ bool m_menuless_mode;
+ bool m_hidden;
+};
+
+
+#endif /* __UI_SLIDERS_H__ */
diff --git a/src/frontend/mame/ui/slotopt.cpp b/src/frontend/mame/ui/slotopt.cpp
new file mode 100644
index 00000000000..9b6afa92132
--- /dev/null
+++ b/src/frontend/mame/ui/slotopt.cpp
@@ -0,0 +1,210 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/*********************************************************************
+
+ ui/slotopt.cpp
+
+ Internal menu for the slot options.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "emuopts.h"
+#include "mameopts.h"
+#include "ui/ui.h"
+#include "ui/menu.h"
+#include "ui/slotopt.h"
+#include "ui/devopt.h"
+
+
+/*-------------------------------------------------
+ ui_slot_get_current_option - returns
+-------------------------------------------------*/
+device_slot_option *ui_menu_slot_devices::slot_get_current_option(device_slot_interface &slot)
+{
+ std::string current;
+ if (slot.fixed())
+ {
+ if (slot.default_option() == nullptr) return nullptr;
+ current.assign(slot.default_option());
+ }
+ else
+ {
+ current = machine().options().main_value(slot.device().tag() + 1);
+ }
+
+ return slot.option(current.c_str());
+}
+
+/*-------------------------------------------------
+ ui_slot_get_current_index - returns
+-------------------------------------------------*/
+int ui_menu_slot_devices::slot_get_current_index(device_slot_interface &slot)
+{
+ const device_slot_option *current = slot_get_current_option(slot);
+
+ if (current != nullptr)
+ {
+ int val = 0;
+ for (const device_slot_option &option : slot.option_list())
+ {
+ if (&option == current)
+ return val;
+
+ if (option.selectable())
+ val++;
+ }
+ }
+
+ return -1;
+}
+
+/*-------------------------------------------------
+ ui_slot_get_length - returns
+-------------------------------------------------*/
+int ui_menu_slot_devices::slot_get_length(device_slot_interface &slot)
+{
+ int val = 0;
+ for (const device_slot_option &option : slot.option_list())
+ if (option.selectable())
+ val++;
+
+ return val;
+}
+
+/*-------------------------------------------------
+ ui_slot_get_next - returns
+-------------------------------------------------*/
+const char *ui_menu_slot_devices::slot_get_next(device_slot_interface &slot)
+{
+ int idx = slot_get_current_index(slot);
+ if (idx < 0)
+ idx = 0;
+ else
+ idx++;
+
+ if (idx >= slot_get_length(slot))
+ return "";
+
+ return slot_get_option(slot, idx);
+}
+
+/*-------------------------------------------------
+ ui_slot_get_prev - returns
+-------------------------------------------------*/
+const char *ui_menu_slot_devices::slot_get_prev(device_slot_interface &slot)
+{
+ int idx = slot_get_current_index(slot);
+ if (idx < 0)
+ idx = slot_get_length(slot) - 1;
+ else
+ idx--;
+
+ if (idx < 0)
+ return "";
+
+ return slot_get_option(slot, idx);
+}
+
+/*-------------------------------------------------
+ ui_slot_get_option - returns
+-------------------------------------------------*/
+const char *ui_menu_slot_devices::slot_get_option(device_slot_interface &slot, int index)
+{
+ if (index >= 0)
+ {
+ int val = 0;
+ for (const device_slot_option &option : slot.option_list())
+ {
+ if (val == index)
+ return option.name();
+
+ if (option.selectable())
+ val++;
+ }
+ }
+
+ return "";
+}
+
+
+/*-------------------------------------------------
+ ui_set_use_natural_keyboard - specifies
+ whether the natural keyboard is active
+-------------------------------------------------*/
+
+void ui_menu_slot_devices::set_slot_device(device_slot_interface &slot, const char *val)
+{
+ std::string error;
+ machine().options().set_value(slot.device().tag()+1, val, OPTION_PRIORITY_CMDLINE, error);
+ assert(error.empty());
+}
+
+/*-------------------------------------------------
+ menu_slot_devices_populate - populates the main
+ slot device menu
+-------------------------------------------------*/
+
+ui_menu_slot_devices::ui_menu_slot_devices(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+void ui_menu_slot_devices::populate()
+{
+ /* cycle through all devices for this system */
+ for (device_slot_interface &slot : slot_interface_iterator(machine().root_device()))
+ {
+ /* record the menu item */
+ const device_slot_option *option = slot_get_current_option(slot);
+ std::string opt_name;
+ if (option == nullptr)
+ opt_name.assign("------");
+ else
+ {
+ opt_name.assign(option->name());
+ if (slot.fixed() || slot_get_length(slot) == 0)
+ opt_name.append(_(" [internal]"));
+ }
+
+ item_append(slot.device().tag() + 1, opt_name.c_str(), (slot.fixed() || slot_get_length(slot) == 0) ? 0 : (MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW), (void *)&slot);
+ }
+ item_append(ui_menu_item_type::SEPARATOR);
+ item_append(_("Reset"), nullptr, 0, (void *)1);
+}
+
+ui_menu_slot_devices::~ui_menu_slot_devices()
+{
+}
+
+/*-------------------------------------------------
+ ui_menu_slot_devices - menu that
+-------------------------------------------------*/
+
+void ui_menu_slot_devices::handle()
+{
+ /* process the menu */
+ const ui_menu_event *menu_event = process(0);
+
+ if (menu_event != nullptr && menu_event->itemref != nullptr)
+ {
+ if ((FPTR)menu_event->itemref == 1 && menu_event->iptkey == IPT_UI_SELECT)
+ {
+ mame_options::add_slot_options(machine().options());
+ machine().schedule_hard_reset();
+ }
+ else if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
+ {
+ device_slot_interface *slot = (device_slot_interface *)menu_event->itemref;
+ const char *val = (menu_event->iptkey == IPT_UI_LEFT) ? slot_get_prev(*slot) : slot_get_next(*slot);
+ set_slot_device(*slot, val);
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ }
+ else if (menu_event->iptkey == IPT_UI_SELECT)
+ {
+ device_slot_interface *slot = (device_slot_interface *)menu_event->itemref;
+ device_slot_option *option = slot_get_current_option(*slot);
+ if (option)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_device_config>(machine(), container, slot, option));
+ }
+ }
+}
diff --git a/src/frontend/mame/ui/slotopt.h b/src/frontend/mame/ui/slotopt.h
new file mode 100644
index 00000000000..8d7c4ab6b18
--- /dev/null
+++ b/src/frontend/mame/ui/slotopt.h
@@ -0,0 +1,35 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/***************************************************************************
+
+ ui/slotopt.h
+
+ Internal menu for the slot options.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_SLOTOPT_H__
+#define __UI_SLOTOPT_H__
+
+//#include "drivenum.h"
+
+class ui_menu_slot_devices : public ui_menu {
+public:
+ ui_menu_slot_devices(running_machine &machine, render_container *container);
+ virtual ~ui_menu_slot_devices();
+ virtual void populate() override;
+ virtual void handle() override;
+
+private:
+ device_slot_option *slot_get_current_option(device_slot_interface &slot);
+ int slot_get_current_index(device_slot_interface &slot);
+ int slot_get_length(device_slot_interface &slot);
+ const char *slot_get_next(device_slot_interface &slot);
+ const char *slot_get_prev(device_slot_interface &slot);
+ const char *slot_get_option(device_slot_interface &slot, int index);
+ void set_slot_device(device_slot_interface &slot, const char *val);
+};
+
+#endif /* __UI_SLOTOPT_H__ */
diff --git a/src/frontend/mame/ui/sndmenu.cpp b/src/frontend/mame/ui/sndmenu.cpp
new file mode 100644
index 00000000000..58362585dc2
--- /dev/null
+++ b/src/frontend/mame/ui/sndmenu.cpp
@@ -0,0 +1,171 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/*********************************************************************
+
+ ui/sndmenu.cpp
+
+ Internal UI user interface.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "ui/ui.h"
+#include "ui/menu.h"
+#include "ui/sndmenu.h"
+#include "ui/selector.h"
+#include "../osd/modules/lib/osdobj_common.h" // TODO: remove
+
+const int ui_menu_sound_options::m_sound_rate[] = { 11025, 22050, 44100, 48000 };
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+ui_menu_sound_options::ui_menu_sound_options(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+ osd_options &options = downcast<osd_options &>(machine.options());
+
+ m_sample_rate = machine.options().sample_rate();
+ m_sound = (strcmp(options.sound(), OSDOPTVAL_NONE) && strcmp(options.sound(), "0"));
+ m_samples = machine.options().samples();
+
+ int total = ARRAY_LENGTH(m_sound_rate);
+
+ for (m_cur_rates = 0; m_cur_rates < total; m_cur_rates++)
+ if (m_sample_rate == m_sound_rate[m_cur_rates])
+ break;
+
+ if (m_cur_rates == total)
+ m_cur_rates = 2;
+}
+
+//-------------------------------------------------
+// dtor
+//-------------------------------------------------
+
+ui_menu_sound_options::~ui_menu_sound_options()
+{
+ std::string error_string;
+ emu_options &moptions = machine().options();
+
+ if (strcmp(moptions.value(OSDOPTION_SOUND),m_sound ? OSDOPTVAL_AUTO : OSDOPTVAL_NONE)!=0)
+ {
+ moptions.set_value(OSDOPTION_SOUND, m_sound ? OSDOPTVAL_AUTO : OSDOPTVAL_NONE, OPTION_PRIORITY_CMDLINE, error_string);
+ machine().options().mark_changed(OSDOPTION_SOUND);
+ }
+ if (moptions.int_value(OPTION_SAMPLERATE)!=m_sound_rate[m_cur_rates])
+ {
+ moptions.set_value(OPTION_SAMPLERATE, m_sound_rate[m_cur_rates], OPTION_PRIORITY_CMDLINE, error_string);
+ machine().options().mark_changed(OPTION_SAMPLERATE);
+ }
+ if (moptions.bool_value(OPTION_SAMPLES)!=m_samples)
+ {
+ moptions.set_value(OPTION_SAMPLES, m_samples, OPTION_PRIORITY_CMDLINE, error_string);
+ machine().options().mark_changed(OPTION_SAMPLES);
+ }
+}
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_menu_sound_options::handle()
+{
+ bool changed = false;
+
+ // process the menu
+ const ui_menu_event *m_event = process(0);
+
+ if (m_event != nullptr && m_event->itemref != nullptr)
+ {
+ switch ((FPTR)m_event->itemref)
+ {
+ case ENABLE_SOUND:
+ if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT || m_event->iptkey == IPT_UI_SELECT)
+ {
+ m_sound = !m_sound;
+ changed = true;
+ }
+ break;
+
+ case SAMPLE_RATE:
+ if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT)
+ {
+ (m_event->iptkey == IPT_UI_LEFT) ? m_cur_rates-- : m_cur_rates++;
+ changed = true;
+ }
+ else if (m_event->iptkey == IPT_UI_SELECT)
+ {
+ int total = ARRAY_LENGTH(m_sound_rate);
+ std::vector<std::string> s_sel(total);
+ for (int index = 0; index < total; index++)
+ s_sel[index] = std::to_string(m_sound_rate[index]);
+
+ ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, s_sel, m_cur_rates));
+ }
+ break;
+
+ case ENABLE_SAMPLES:
+ if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT || m_event->iptkey == IPT_UI_SELECT)
+ {
+ m_samples = !m_samples;
+ changed = true;
+ }
+ break;
+ }
+ }
+
+ if (changed)
+ reset(UI_MENU_RESET_REMEMBER_REF);
+
+}
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_sound_options::populate()
+{
+ UINT32 arrow_flags = get_arrow_flags(0, ARRAY_LENGTH(m_sound_rate) - 1, m_cur_rates);
+ m_sample_rate = m_sound_rate[m_cur_rates];
+
+ // add options items
+ item_append(_("Sound"), m_sound ? _("On") : _("Off"), m_sound ? MENU_FLAG_RIGHT_ARROW : MENU_FLAG_LEFT_ARROW, (void *)(FPTR)ENABLE_SOUND);
+ item_append(_("Sample Rate"), string_format("%d", m_sample_rate).c_str(), arrow_flags, (void *)(FPTR)SAMPLE_RATE);
+ item_append(_("Use External Samples"), m_samples ? _("On") : _("Off"), m_samples ? MENU_FLAG_RIGHT_ARROW : MENU_FLAG_LEFT_ARROW, (void *)(FPTR)ENABLE_SAMPLES);
+ item_append(ui_menu_item_type::SEPARATOR);
+
+ customtop = mame_machine_manager::instance()->ui().get_line_height() + (3.0f * UI_BOX_TB_BORDER);
+}
+
+//-------------------------------------------------
+// perform our special rendering
+//-------------------------------------------------
+
+void ui_menu_sound_options::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ float width;
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+ mui.draw_text_full(container, _("Sound Options"), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += 2 * UI_BOX_LR_BORDER;
+ float maxwidth = MAX(origx2 - origx1, width);
+
+ // compute our bounds
+ float x1 = 0.5f - 0.5f * maxwidth;
+ float x2 = x1 + maxwidth;
+ float y1 = origy1 - top;
+ float y2 = origy1 - UI_BOX_TB_BORDER;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ mui.draw_text_full(container, _("Sound Options"), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+}
diff --git a/src/frontend/mame/ui/sndmenu.h b/src/frontend/mame/ui/sndmenu.h
new file mode 100644
index 00000000000..24bb0a79277
--- /dev/null
+++ b/src/frontend/mame/ui/sndmenu.h
@@ -0,0 +1,42 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/***************************************************************************
+
+ ui/sndmenu.h
+
+ Internal UI user interface.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_SNDMENU_H__
+#define __UI_SNDMENU_H__
+
+//-------------------------------------------------
+// class sound options menu
+//-------------------------------------------------
+class ui_menu_sound_options : public ui_menu
+{
+public:
+ ui_menu_sound_options(running_machine &machine, render_container *container);
+ virtual ~ui_menu_sound_options();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+private:
+ enum
+ {
+ ENABLE_SOUND = 1,
+ SAMPLE_RATE,
+ ENABLE_SAMPLES
+ };
+
+ UINT16 m_cur_rates;
+ static const int m_sound_rate[];
+ int m_sample_rate;
+ bool m_samples, m_sound;
+};
+
+#endif /* __UI_SNDMENU_H__ */
diff --git a/src/frontend/mame/ui/starimg.h b/src/frontend/mame/ui/starimg.h
new file mode 100644
index 00000000000..f57ebb8797f
--- /dev/null
+++ b/src/frontend/mame/ui/starimg.h
@@ -0,0 +1,38 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+
+static const UINT32 favorite_star_bmp[] =
+{
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02D07A00, 0x15D07A00, 0x0FD07A00, 0x00D07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x76D27F04, 0xBFDA9714, 0xB9D78F0E, 0x4DD17B01, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3BD07A00, 0xFFE8B228, 0xFFFDEB50, 0xFFFBE34A, 0xD0E1A11C, 0x13D07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0BD07A00, 0xA0D48306, 0xFFFACE42, 0xFFFBCE45, 0xFFFCD146, 0xFFF2BD34, 0x67D07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x49D27E03, 0xE9EAAB26, 0xFFFDD044, 0xFFF9C741, 0xFFFAC942, 0xFFFED245, 0xD1DF9716, 0x27D07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xA2DB8D0F, 0xFFF6C236, 0xFFFAC740, 0xFFF8C53F, 0xFFF8C53F, 0xFFFDCB41, 0xF7F0B62E, 0x71D68308, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x31D07A00, 0xFFE7A420, 0xFFFDCA3F, 0xFFF8C23D, 0xFFF8C23D, 0xFFF8C23D, 0xFFF8C23D, 0xFFFCC83D, 0xE0E19818, 0x11D07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x08D07A00, 0x99D38004, 0xFFF9C237, 0xFFFAC43C, 0xFFF8BF3A, 0xFFF8BF3A, 0xFFF8BF3A, 0xFFF8BF3A, 0xFFFBC53C, 0xFFF1B32B, 0x63D07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x01D07A00, 0x15D07A00, 0x24D07A00, 0x39D07A00, 0x4AD07A00, 0x79D48205, 0xE6E9A820, 0xFFFDC539, 0xFFF8BC37, 0xFFF8BC37, 0xFFF8BC37, 0xFFF8BC37, 0xFFF8BC37, 0xFFF9BD37, 0xFFFEC63A, 0xD8DF9613, 0x64D17C01, 0x3FD07A00, 0x2FD07A00, 0x1CD07A00, 0x0AD07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x04D07A00, 0x3BD07A00, 0x8BD07A00, 0xA5D17B01, 0xBFDA940F, 0xCEE1A317, 0xE2E7B622, 0xF4EDC229, 0xFFF1C62D, 0xFFFAC735, 0xFFFABC35, 0xFFF8B934, 0xFFF8B934, 0xFFF8B934, 0xFFF8B934, 0xFFF8B934, 0xFFF8B934, 0xFFFCBF36, 0xFFF7C733, 0xFCEFC52C, 0xE9EABB24, 0xD8E4AE1D, 0xC6DD9C13, 0xB4D58608, 0x99D07A00, 0x75D07A00, 0x20D07A00, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x01D07A00, 0xBBD78608, 0xFFE9AE1F, 0xFFF9D133, 0xFFFCD839, 0xFFFCD338, 0xFFFCCC36, 0xFFFCC333, 0xFFFCBB32, 0xFFF7B630, 0xFFF7B630, 0xFFF7B630, 0xFFF7B630, 0xFFF7B630, 0xFFF7B630, 0xFFF7B630, 0xFFF7B630, 0xFFF7B630, 0xFFF7B630, 0xFFF7B630, 0xFFFAB831, 0xFFFCC033, 0xFFFCC735, 0xFFFCD037, 0xFFFCD739, 0xFFFBD536, 0xFFF5C92F, 0xE8E4A318, 0x55D78507, 0x00000000, 0x00000000,
+ 0x00000000, 0x13D07A00, 0xFFDF9212, 0xFFFABC2F, 0xFFF9B72F, 0xFFF8B32E, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B32D, 0xFFF9B52E, 0xFFF9B92F, 0xFFF6B52A, 0xC1DB8B0D, 0x00000000, 0x00000000,
+ 0x00000000, 0x07D07A00, 0xE6DC8B0E, 0xFFF4AB27, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFEFA421, 0xAAD9860A, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x5ED58005, 0xE8E39213, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF4A925, 0xE2DC890C, 0x45D27C02, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x41D07A00, 0xE7E18F11, 0xFFF3A420, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFEFA11D, 0xE0DB880A, 0x35D07A00, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5DD47E03, 0xE6E08D0D, 0xFFF5A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF3A11D, 0xDFDB8609, 0x4FD27C01, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40D07A00, 0xE6E08A0C, 0xFFF29D19, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFEE9917, 0xDDDA8407, 0x30D07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5BD37D02, 0xE6DF880A, 0xFFF59C18, 0xFFF69D18, 0xFFF69D18, 0xFFF69D18, 0xFFF69D18, 0xFFF69D18, 0xFFF69D18, 0xFFF69D18, 0xFFF69D18, 0xFFF69D18, 0xFFF69D18, 0xFFF69D18, 0xFFF69D18, 0xFFF69D18, 0xFFF69D18, 0xFFF29A16, 0xDCD98306, 0x49D17B01, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x7BD07A00, 0xFFEF9311, 0xFFF69A15, 0xFFF59915, 0xFFF59915, 0xFFF59915, 0xFFF59915, 0xFFF59915, 0xFFF59915, 0xFFF59915, 0xFFF59915, 0xFFF59915, 0xFFF59915, 0xFFF59915, 0xFFF59915, 0xFFF69915, 0xFFE2890A, 0x3BD07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x01D07A00, 0xA2D17B00, 0xFFF59612, 0xFFF69713, 0xFFF59612, 0xFFF59612, 0xFFF59612, 0xFFF59612, 0xFFF59612, 0xFFF59612, 0xFFF59612, 0xFFF59612, 0xFFF59612, 0xFFF59612, 0xFFF59612, 0xFFF59612, 0xFFF79712, 0xFFE98D0B, 0x4BD07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x14D07A00, 0xBED87F03, 0xFFF6940E, 0xFFF5930E, 0xFFF5930E, 0xFFF5930E, 0xFFF5930E, 0xFFF5930E, 0xFFF5930E, 0xFFF5930E, 0xFFF5930E, 0xFFF5930E, 0xFFF5930E, 0xFFF5930E, 0xFFF5930E, 0xFFF5930E, 0xFFF7940E, 0xFFF1900B, 0x7ED07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x27D07A00, 0xD1DE8205, 0xFFF8920C, 0xFFF5900C, 0xFFF5900C, 0xFFF5900C, 0xFFF5900C, 0xFFF5900C, 0xFFF5900C, 0xFFF5900C, 0xFFF5900C, 0xFFF5900C, 0xFFF5900C, 0xFFF5900C, 0xFFF5900C, 0xFFF5900C, 0xFFF6910C, 0xFFF5910C, 0xA5D27B01, 0x03D07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40D07A00, 0xEAE48505, 0xFFFA9009, 0xFFF58D09, 0xFFF58D09, 0xFFF58D09, 0xFFF58D09, 0xFFF58D09, 0xFFF58D09, 0xFFF58D09, 0xFFF58D09, 0xFFF58D09, 0xFFF58D09, 0xFFF58D09, 0xFFF58D09, 0xFFF58D09, 0xFFF58D09, 0xFFF78E09, 0xC1D97F02, 0x17D07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x57D17B00, 0xFBE88504, 0xFFF78D06, 0xFFF48B06, 0xFFF48B06, 0xFFF48B06, 0xFFF48B06, 0xFFF48B06, 0xFFF38B06, 0xFFEC8705, 0xFFF18A06, 0xFFF48B06, 0xFFF48B06, 0xFFF48B06, 0xFFF48B06, 0xFFF48B06, 0xFFF48B06, 0xFFF88E06, 0xD6DF8102, 0x2CD07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x83D67D01, 0xFFED8503, 0xFFF48804, 0xFFF48804, 0xFFF48804, 0xFFF48804, 0xFFF28804, 0xFFEA8503, 0xCDDC7F02, 0x79D17B00, 0xA1D47C01, 0xEFE18102, 0xFFEE8604, 0xFFF38804, 0xFFF48804, 0xFFF48804, 0xFFF48804, 0xFFF88B04, 0xEFE58203, 0x46D07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xA0D87D01, 0xFFED8401, 0xFFF48602, 0xFFF48602, 0xFFF48602, 0xFFEF8501, 0xE9DE7F01, 0x8FD67D00, 0x23D07A00, 0x04D07A00, 0x0DD07A00, 0x46D07A00, 0xC3D97D01, 0xFFE28001, 0xFFF38602, 0xFFF48602, 0xFFF48602, 0xFFF58702, 0xFDE88201, 0x59D17A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5FD47B00, 0xF3E58000, 0xFFF18400, 0xFFED8200, 0xDEE07F01, 0x90D37B00, 0x1FD07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x01D07A00, 0x3BD07A00, 0xBDD67C00, 0xF2E48000, 0xFFEF8300, 0xFFF08300, 0xDEDF7E01, 0x34D07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x10D07A00, 0x71D57C00, 0xD2DB7D00, 0x9AD87C00, 0x34D07A00, 0x0AD07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x13D07A00, 0x52D27B00, 0xBBD97D00, 0xCBDA7D00, 0x5DD27B00, 0x0AD07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
+};
diff --git a/src/frontend/mame/ui/submenu.cpp b/src/frontend/mame/ui/submenu.cpp
new file mode 100644
index 00000000000..68b8d85d36a
--- /dev/null
+++ b/src/frontend/mame/ui/submenu.cpp
@@ -0,0 +1,368 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota,Jeffrey Clark
+/***************************************************************************
+
+ ui/submenu.cpp
+
+ UI options menu
+
+***************************************************************************/
+
+#include "emu.h"
+#include "ui/ui.h"
+#include "ui/submenu.h"
+#include "ui/utils.h"
+#include <limits>
+#include <iterator>
+
+//-------------------------------------------------
+// ctor / dtor
+//-------------------------------------------------
+
+ui_submenu::ui_submenu(running_machine &machine, render_container *container, std::vector<ui_submenu::option> &suboptions, const game_driver *drv, emu_options *options)
+ : ui_menu(machine, container)
+ , m_options(suboptions)
+ , m_driver(drv)
+{
+ core_options *opts = nullptr;
+ if (m_driver == nullptr)
+ opts = dynamic_cast<core_options*>(&machine.options());
+ else
+ opts = dynamic_cast<core_options*>(options);
+
+ for (auto & sm_option : m_options)
+ {
+ switch (sm_option.type)
+ {
+ case ui_submenu::EMU:
+ sm_option.entry = opts->get_entry(sm_option.name);
+ sm_option.options = opts;
+ if (sm_option.entry->type() == OPTION_STRING)
+ {
+ sm_option.value.clear();
+ std::string namestr(sm_option.entry->description());
+ int lparen = namestr.find_first_of('(', 0);
+ int vslash = namestr.find_first_of('|', lparen + 1);
+ int rparen = namestr.find_first_of(')', vslash + 1);
+ if (lparen != -1 && vslash != -1 && rparen != -1)
+ {
+ int semi;
+ namestr.erase(rparen);
+ namestr.erase(0, lparen + 1);
+ while ((semi = namestr.find_first_of('|')) != -1)
+ {
+ sm_option.value.emplace_back(namestr.substr(0, semi));
+ namestr.erase(0, semi + 1);
+ }
+ sm_option.value.emplace_back(namestr);
+ }
+ }
+ break;
+ case ui_submenu::OSD:
+ sm_option.entry = opts->get_entry(sm_option.name);
+ sm_option.options = opts;
+ if (sm_option.entry->type() == OPTION_STRING)
+ {
+ sm_option.value.clear();
+ std::string descr(sm_option.entry->description()), delim(", ");
+ descr.erase(0, descr.find(":") + 2);
+ size_t p1, p2 = 0;
+ while ((p1 = descr.find_first_not_of(delim, p2)) != std::string::npos)
+ {
+ p2 = descr.find_first_of(delim, p1 + 1);
+ if (p2 != std::string::npos)
+ {
+ std::string txt(descr.substr(p1, p2 - p1));
+ if (txt != "or")
+ sm_option.value.push_back(txt);
+ }
+ else
+ {
+ sm_option.value.push_back(descr.substr(p1));
+ break;
+ }
+ }
+ }
+ break;
+ case ui_submenu::UI:
+ sm_option.entry = mame_machine_manager::instance()->ui().options().get_entry(sm_option.name);
+ sm_option.options = dynamic_cast<core_options*>(&mame_machine_manager::instance()->ui().options());
+ break;
+ default:
+ continue;
+ break;
+ }
+ }
+}
+
+ui_submenu::~ui_submenu()
+{
+}
+
+//-------------------------------------------------
+// handlethe options menu
+//-------------------------------------------------
+
+void ui_submenu::handle()
+{
+ bool changed = false;
+ std::string error_string, tmptxt;
+ float f_cur, f_step;
+
+ // process the menu
+ const ui_menu_event *m_event = process(UI_MENU_PROCESS_LR_REPEAT);
+
+ if (m_event != nullptr && m_event->itemref != nullptr &&
+ (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT || m_event->iptkey == IPT_UI_SELECT))
+ {
+ ui_submenu::option *sm_option = (ui_submenu::option *)m_event->itemref;
+
+ switch (sm_option->type)
+ {
+ case ui_submenu::EMU:
+ case ui_submenu::UI:
+ case ui_submenu::OSD:
+ switch (sm_option->entry->type())
+ {
+ case OPTION_BOOLEAN:
+ changed = true;
+ sm_option->options->set_value(sm_option->name, !strcmp(sm_option->entry->value(),"1") ? "0" : "1", OPTION_PRIORITY_CMDLINE, error_string);
+ sm_option->entry->mark_changed();
+ break;
+ case OPTION_INTEGER:
+ if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT)
+ {
+ changed = true;
+ int i_cur = atoi(sm_option->entry->value());
+ (m_event->iptkey == IPT_UI_LEFT) ? i_cur-- : i_cur++;
+ sm_option->options->set_value(sm_option->name, i_cur, OPTION_PRIORITY_CMDLINE, error_string);
+ sm_option->entry->mark_changed();
+ }
+ break;
+ case OPTION_FLOAT:
+ if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT)
+ {
+ changed = true;
+ f_cur = atof(sm_option->entry->value());
+ if (sm_option->entry->has_range())
+ {
+ f_step = atof(sm_option->entry->minimum());
+ if (f_step <= 0.0f) {
+ int pmin = getprecisionchr(sm_option->entry->minimum());
+ int pmax = getprecisionchr(sm_option->entry->maximum());
+ tmptxt = '1' + std::string((pmin > pmax) ? pmin : pmax, '0');
+ f_step = 1 / atof(tmptxt.c_str());
+ }
+ }
+ else
+ {
+ int precision = getprecisionchr(sm_option->entry->default_value());
+ tmptxt = '1' + std::string(precision, '0');
+ f_step = 1 / atof(tmptxt.c_str());
+ }
+ if (m_event->iptkey == IPT_UI_LEFT)
+ f_cur -= f_step;
+ else
+ f_cur += f_step;
+ tmptxt = string_format("%g", f_cur);
+ sm_option->options->set_value(sm_option->name, tmptxt.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
+ sm_option->entry->mark_changed();
+ }
+ break;
+ case OPTION_STRING:
+ if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT)
+ {
+ changed = true;
+ std::string v_cur(sm_option->entry->value());
+ int cur_value = std::distance(sm_option->value.begin(), std::find(sm_option->value.begin(), sm_option->value.end(), v_cur));
+ if (m_event->iptkey == IPT_UI_LEFT)
+ v_cur = sm_option->value[--cur_value];
+ else
+ v_cur = sm_option->value[++cur_value];
+ sm_option->options->set_value(sm_option->name, v_cur.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
+ sm_option->entry->mark_changed();
+ }
+ break;
+ }
+ break;
+ default:
+ osd_printf_error("Unhandled option: %s", _(sm_option->description));
+ break;
+ }
+ }
+
+ if (changed)
+ reset(UI_MENU_RESET_REMEMBER_REF);
+}
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_submenu::populate()
+{
+ UINT32 arrow_flags;
+
+ // add options
+ for (auto sm_option = m_options.begin(); sm_option < m_options.end(); sm_option++)
+ {
+ // skip first heading (is menu title)
+ if (sm_option == m_options.begin() && sm_option->type == ui_submenu::HEAD) continue;
+
+ switch (sm_option->type)
+ {
+ case ui_submenu::HEAD:
+ item_append(_(sm_option->description), nullptr, MENU_FLAG_DISABLE | MENU_FLAG_UI_HEADING, nullptr);
+ break;
+ case ui_submenu::SEP:
+ item_append(ui_menu_item_type::SEPARATOR);
+ break;
+ case ui_submenu::CMD:
+ item_append(_(sm_option->description), nullptr, 0, static_cast<void*>(&(*sm_option)));
+ break;
+ case ui_submenu::EMU:
+ case ui_submenu::UI:
+ case ui_submenu::OSD:
+ switch (sm_option->entry->type())
+ {
+ case OPTION_BOOLEAN:
+ arrow_flags = sm_option->options->bool_value(sm_option->name) ? MENU_FLAG_RIGHT_ARROW : MENU_FLAG_LEFT_ARROW;
+ item_append(_(sm_option->description),
+ (arrow_flags == MENU_FLAG_RIGHT_ARROW) ? "On" : "Off",
+ arrow_flags,
+ static_cast<void*>(&(*sm_option)));
+ break;
+ case OPTION_INTEGER:
+ {
+ int i_min, i_max;
+ int i_cur = atoi(sm_option->entry->value());
+ if (sm_option->entry->has_range())
+ {
+ i_min = atoi(sm_option->entry->minimum());
+ i_max = atoi(sm_option->entry->maximum());
+ }
+ else
+ {
+ i_min = std::numeric_limits<int>::min();
+ i_max = std::numeric_limits<int>::max();
+ }
+ arrow_flags = get_arrow_flags(i_min, i_max, i_cur);
+ item_append(_(sm_option->description),
+ sm_option->entry->value(),
+ arrow_flags,
+ static_cast<void*>(&(*sm_option)));
+ break;
+ }
+ case OPTION_FLOAT:
+ {
+ float f_min, f_max;
+ float f_cur = atof(sm_option->entry->value());
+ if (sm_option->entry->has_range())
+ {
+ f_min = atof(sm_option->entry->minimum());
+ f_max = atof(sm_option->entry->maximum());
+ }
+ else
+ {
+ f_min = 0.0f;
+ f_max = std::numeric_limits<float>::max();
+ }
+ arrow_flags = get_arrow_flags(f_min, f_max, f_cur);
+ std::string tmptxt = string_format("%g", f_cur);
+ item_append(_(sm_option->description),
+ tmptxt.c_str(),
+ arrow_flags,
+ static_cast<void*>(&(*sm_option)));
+ break;
+ }
+ case OPTION_STRING:
+ {
+ std::string v_cur(sm_option->entry->value());
+ int cur_value = std::distance(sm_option->value.begin(), std::find(sm_option->value.begin(), sm_option->value.end(), v_cur));
+ arrow_flags = get_arrow_flags(0, sm_option->value.size() - 1, cur_value);
+ item_append(_(sm_option->description),
+ sm_option->options->value(sm_option->name),
+ arrow_flags, static_cast<void*>(&(*sm_option)));
+ break;
+ }
+ default:
+ arrow_flags = MENU_FLAG_RIGHT_ARROW;
+ item_append(_(sm_option->description),
+ sm_option->options->value(sm_option->name),
+ arrow_flags, static_cast<void*>(&(*sm_option)));
+ break;
+ }
+ break;
+ default:
+ osd_printf_error("Unknown option type: %s", _(sm_option->description));
+ break;
+ }
+ }
+
+ item_append(ui_menu_item_type::SEPARATOR);
+ custombottom = customtop = mame_machine_manager::instance()->ui().get_line_height() + (3.0f * UI_BOX_TB_BORDER);
+}
+
+//-------------------------------------------------
+// perform our special rendering
+//-------------------------------------------------
+
+void ui_submenu::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ float width;
+ mame_ui_manager &mui = mame_machine_manager::instance()->ui();
+
+ mui.draw_text_full(container, _(m_options[0].description), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ width += 2 * UI_BOX_LR_BORDER;
+ float maxwidth = MAX(origx2 - origx1, width);
+
+ // compute our bounds
+ float x1 = 0.5f - 0.5f * maxwidth;
+ float x2 = x1 + maxwidth;
+ float y1 = origy1 - top;
+ float y2 = origy1 - UI_BOX_TB_BORDER;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ mui.draw_text_full(container, _(m_options[0].description), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+
+ if (selectedref != nullptr)
+ {
+ ui_submenu::option *selected_sm_option = (ui_submenu::option *)selectedref;
+ if (selected_sm_option->entry != nullptr)
+ {
+ mui.draw_text_full(container, selected_sm_option->entry->description(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+
+ width += 2 * UI_BOX_LR_BORDER;
+ maxwidth = MAX(origx2 - origx1, width);
+
+ // compute our bounds
+ x1 = 0.5f - 0.5f * maxwidth;
+ x2 = x1 + maxwidth;
+ y1 = origy2 + UI_BOX_TB_BORDER;
+ y2 = origy2 + bottom;
+
+ // draw a box
+ mui.draw_outlined_box(container, x1, y1, x2, y2, UI_RED_COLOR);
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+
+ // draw the text within it
+ mui.draw_text_full(container, selected_sm_option->entry->description(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+ }
+ }
+}
diff --git a/src/frontend/mame/ui/submenu.h b/src/frontend/mame/ui/submenu.h
new file mode 100644
index 00000000000..8168ab4bb7a
--- /dev/null
+++ b/src/frontend/mame/ui/submenu.h
@@ -0,0 +1,160 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota,Jeffrey Clark
+/***************************************************************************
+
+ ui/submenu.h
+
+ UI options menu.
+
+***************************************************************************/
+#pragma once
+
+#ifndef __UI_SUBMENU_H__
+#define __UI_SUBMENU_H__
+
+#include "emuopts.h"
+#include "ui/menu.h"
+
+#if defined(UI_WINDOWS) && !defined(UI_SDL)
+#include "../osd/windows/winmain.h"
+#else
+#include "../osd/modules/lib/osdobj_common.h"
+#endif
+
+//-------------------------------------------------
+// class ui menu
+//-------------------------------------------------
+class ui_submenu : public ui_menu
+{
+public:
+ enum option_type {
+ HEAD,
+ SEP,
+ MENU,
+ CMD,
+ EMU,
+ UI,
+ OSD,
+ };
+
+ struct option {
+ option_type type;
+ const char *description;
+ const char *name;
+ core_options::entry *entry;
+ core_options (*options);
+ std::vector<std::string> value;
+ };
+
+ ui_submenu(running_machine &machine, render_container *container, std::vector<ui_submenu::option> &suboptions, const game_driver *drv = nullptr, emu_options *options = nullptr);
+ virtual ~ui_submenu();
+ virtual void populate() override;
+ virtual void handle() override;
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+private:
+ std::vector<option> &m_options;
+ const game_driver *m_driver;
+};
+
+static std::vector<ui_submenu::option> misc_submenu_options = {
+ { ui_submenu::HEAD, __("Miscellaneous Options") },
+ { ui_submenu::UI, __("Re-select last machine played"), OPTION_REMEMBER_LAST },
+ { ui_submenu::UI, __("Enlarge images in the right panel"), OPTION_ENLARGE_SNAPS },
+ { ui_submenu::UI, __("DATs info"), OPTION_DATS_ENABLED },
+ { ui_submenu::EMU, __("Cheats"), OPTION_CHEAT },
+ { ui_submenu::EMU, __("Show mouse pointer"), OPTION_UI_MOUSE },
+ { ui_submenu::EMU, __("Confirm quit from machines"), OPTION_CONFIRM_QUIT },
+ { ui_submenu::EMU, __("Skip information screen at startup"), OPTION_SKIP_GAMEINFO },
+ { ui_submenu::UI, __("Force 4:3 aspect for snapshot display"), OPTION_FORCED4X3 },
+ { ui_submenu::UI, __("Use image as background"), OPTION_USE_BACKGROUND },
+ { ui_submenu::UI, __("Skip bios selection menu"), OPTION_SKIP_BIOS_MENU },
+ { ui_submenu::UI, __("Skip software parts selection menu"), OPTION_SKIP_PARTS_MENU },
+ { ui_submenu::UI, __("Info auto audit"), OPTION_INFO_AUTO_AUDIT },
+};
+
+static std::vector<ui_submenu::option> advanced_submenu_options = {
+ { ui_submenu::HEAD, __("Advanced Options") },
+ { ui_submenu::HEAD, __("Performance Options") },
+ { ui_submenu::EMU, __("Auto frame skip"), OPTION_AUTOFRAMESKIP },
+ { ui_submenu::EMU, __("Frame skip"), OPTION_FRAMESKIP },
+ { ui_submenu::EMU, __("Throttle"), OPTION_THROTTLE },
+ { ui_submenu::EMU, __("Sleep"), OPTION_SLEEP },
+ { ui_submenu::EMU, __("Speed"), OPTION_SPEED },
+ { ui_submenu::EMU, __("Refresh speed"), OPTION_REFRESHSPEED },
+
+ { ui_submenu::HEAD, __("Rotation Options") },
+ { ui_submenu::EMU, __("Rotate"), OPTION_ROTATE },
+ { ui_submenu::EMU, __("Rotate right"), OPTION_ROR },
+ { ui_submenu::EMU, __("Rotate left"), OPTION_ROL },
+ { ui_submenu::EMU, __("Auto rotate right"), OPTION_AUTOROR },
+ { ui_submenu::EMU, __("Auto rotate left"), OPTION_AUTOROL },
+ { ui_submenu::EMU, __("Flip X"), OPTION_FLIPX },
+ { ui_submenu::EMU, __("Flip Y"), OPTION_FLIPY },
+
+ { ui_submenu::HEAD, __("Artwork Options") },
+ { ui_submenu::EMU, __("Artwork Crop"), OPTION_ARTWORK_CROP },
+ { ui_submenu::EMU, __("Use Backdrops"), OPTION_USE_BACKDROPS },
+ { ui_submenu::EMU, __("Use Overlays"), OPTION_USE_OVERLAYS },
+ { ui_submenu::EMU, __("Use Bezels"), OPTION_USE_BEZELS },
+ { ui_submenu::EMU, __("Use Control Panels"), OPTION_USE_CPANELS },
+ { ui_submenu::EMU, __("Use Marquees"), OPTION_USE_MARQUEES },
+
+ { ui_submenu::HEAD, __("State/Playback Options") },
+ { ui_submenu::EMU, __("Automatic save/restore"), OPTION_AUTOSAVE },
+ { ui_submenu::EMU, __("Bilinear snapshot"), OPTION_SNAPBILINEAR },
+ { ui_submenu::EMU, __("Burn-in"), OPTION_BURNIN },
+
+ { ui_submenu::HEAD, __("Input Options") },
+ { ui_submenu::EMU, __("Coin lockout"), OPTION_COIN_LOCKOUT },
+ { ui_submenu::EMU, __("Mouse"), OPTION_MOUSE },
+ { ui_submenu::EMU, __("Joystick"), OPTION_JOYSTICK },
+ { ui_submenu::EMU, __("Lightgun"), OPTION_LIGHTGUN },
+ { ui_submenu::EMU, __("Multi-keyboard"), OPTION_MULTIKEYBOARD },
+ { ui_submenu::EMU, __("Multi-mouse"), OPTION_MULTIMOUSE },
+ { ui_submenu::EMU, __("Steadykey"), OPTION_STEADYKEY },
+ { ui_submenu::EMU, __("UI active"), OPTION_UI_ACTIVE },
+ { ui_submenu::EMU, __("Offscreen reload"), OPTION_OFFSCREEN_RELOAD },
+ { ui_submenu::EMU, __("Joystick deadzone"), OPTION_JOYSTICK_DEADZONE },
+ { ui_submenu::EMU, __("Joystick saturation"), OPTION_JOYSTICK_SATURATION },
+ { ui_submenu::EMU, __("Natural keyboard"), OPTION_NATURAL_KEYBOARD },
+ { ui_submenu::EMU, __("Simultaneous contradictory"), OPTION_JOYSTICK_CONTRADICTORY },
+ { ui_submenu::EMU, __("Coin impulse"), OPTION_COIN_IMPULSE },
+};
+
+static std::vector<ui_submenu::option> control_submenu_options = {
+ { ui_submenu::HEAD, __("Device Mapping") },
+ { ui_submenu::EMU, __("Lightgun Device Assignment"), OPTION_LIGHTGUN_DEVICE },
+ { ui_submenu::EMU, __("Trackball Device Assignment"), OPTION_TRACKBALL_DEVICE },
+ { ui_submenu::EMU, __("Pedal Device Assignment"), OPTION_PEDAL_DEVICE },
+ { ui_submenu::EMU, __("Adstick Device Assignment"), OPTION_ADSTICK_DEVICE },
+ { ui_submenu::EMU, __("Paddle Device Assignment"), OPTION_PADDLE_DEVICE },
+ { ui_submenu::EMU, __("Dial Device Assignment"), OPTION_DIAL_DEVICE },
+ { ui_submenu::EMU, __("Positional Device Assignment"), OPTION_POSITIONAL_DEVICE },
+ { ui_submenu::EMU, __("Mouse Device Assignment"), OPTION_MOUSE_DEVICE }
+};
+
+static std::vector<ui_submenu::option> video_submenu_options = {
+ { ui_submenu::HEAD, __("Video Options") },
+ { ui_submenu::OSD, __("Video Mode"), OSDOPTION_VIDEO },
+ { ui_submenu::OSD, __("Number Of Screens"), OSDOPTION_NUMSCREENS },
+#if defined(UI_WINDOWS) && !defined(UI_SDL)
+ { ui_submenu::OSD, __("Triple Buffering"), WINOPTION_TRIPLEBUFFER },
+ { ui_submenu::OSD, __("HLSL"), WINOPTION_HLSL_ENABLE },
+#endif
+ { ui_submenu::OSD, __("GLSL"), OSDOPTION_GL_GLSL },
+ { ui_submenu::OSD, __("Bilinear Filtering"), OSDOPTION_FILTER },
+ { ui_submenu::OSD, __("Bitmap Prescaling"), OSDOPTION_PRESCALE },
+ { ui_submenu::OSD, __("Window Mode"), OSDOPTION_WINDOW },
+ { ui_submenu::EMU, __("Enforce Aspect Ratio"), OPTION_KEEPASPECT },
+ { ui_submenu::OSD, __("Start Out Maximized"), OSDOPTION_MAXIMIZE },
+ { ui_submenu::OSD, __("Synchronized Refresh"), OSDOPTION_SYNCREFRESH },
+ { ui_submenu::OSD, __("Wait Vertical Sync"), OSDOPTION_WAITVSYNC }
+};
+
+//static std::vector<ui_submenu::option> export_submenu_options = {
+// { ui_submenu::COMMAND, __("Export XML format (like -listxml)"), "exportxml" },
+// { ui_submenu::COMMAND, __("Export TXT format (like -listfull)"), "exporttxt" },
+//};
+
+#endif /* __UI_SUBMENU_H__ */
diff --git a/src/frontend/mame/ui/swlist.cpp b/src/frontend/mame/ui/swlist.cpp
new file mode 100644
index 00000000000..915c11239b9
--- /dev/null
+++ b/src/frontend/mame/ui/swlist.cpp
@@ -0,0 +1,458 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/*********************************************************************
+
+ ui/swlist.cpp
+
+ Internal MAME user interface for software list.
+
+ *********************************************************************/
+
+#include "emu.h"
+#include "ui/ui.h"
+#include "ui/menu.h"
+#include "ui/swlist.h"
+#include "softlist.h"
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* time (in seconds) to display errors */
+#define ERROR_MESSAGE_TIME 5
+
+
+/***************************************************************************
+ SOFTWARE PARTS
+***************************************************************************/
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+ui_menu_software_parts::ui_menu_software_parts(running_machine &machine, render_container *container, const software_info *info, const char *interface, const software_part **part, bool other_opt, int *result)
+ : ui_menu(machine, container)
+{
+ m_info = info;
+ m_interface = interface;
+ m_selected_part = part;
+ m_other_opt = other_opt;
+ m_result = result;
+}
+
+
+//-------------------------------------------------
+// dtor
+//-------------------------------------------------
+
+ui_menu_software_parts::~ui_menu_software_parts()
+{
+}
+
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_software_parts::populate()
+{
+ if (m_other_opt)
+ {
+ software_part_menu_entry *entry1 = (software_part_menu_entry *) m_pool_alloc(sizeof(*entry1));
+ entry1->type = T_EMPTY;
+ entry1->part = nullptr;
+ item_append(_("[empty slot]"), nullptr, 0, entry1);
+
+ software_part_menu_entry *entry2 = (software_part_menu_entry *) m_pool_alloc(sizeof(*entry2));
+ entry2->type = T_FMGR;
+ entry2->part = nullptr;
+ item_append(_("[file manager]"), nullptr, 0, entry2);
+
+
+ software_part_menu_entry *entry3 = (software_part_menu_entry *) m_pool_alloc(sizeof(*entry3));
+ entry3->type = T_SWLIST;
+ entry3->part = nullptr;
+ item_append(_("[software list]"), nullptr, 0, entry3);
+ }
+
+ for (const software_part &swpart : m_info->parts())
+ {
+ if (swpart.matches_interface(m_interface))
+ {
+ software_part_menu_entry *entry = (software_part_menu_entry *) m_pool_alloc(sizeof(*entry));
+ // check if the available parts have specific part_id to be displayed (e.g. "Map Disc", "Bonus Disc", etc.)
+ // if not, we simply display "part_name"; if yes we display "part_name (part_id)"
+ std::string menu_part_name(swpart.name());
+ if (swpart.feature("part_id") != nullptr)
+ menu_part_name.append(" (").append(swpart.feature("part_id")).append(")");
+ entry->type = T_ENTRY;
+ entry->part = &swpart;
+ item_append(m_info->shortname(), menu_part_name.c_str(), 0, entry);
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_menu_software_parts::handle()
+{
+ // process the menu
+ const ui_menu_event *event = process(0);
+
+ if (event != nullptr && event->iptkey == IPT_UI_SELECT && event->itemref != nullptr)
+ {
+ software_part_menu_entry *entry = (software_part_menu_entry *) event->itemref;
+ *m_result = entry->type;
+ *m_selected_part = entry->part;
+ ui_menu::stack_pop(machine());
+ }
+}
+
+
+/***************************************************************************
+ SOFTWARE LIST
+***************************************************************************/
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+ui_menu_software_list::ui_menu_software_list(running_machine &machine, render_container *container, software_list_device *swlist, const char *interface, std::string &result)
+ : ui_menu(machine, container), m_result(result)
+{
+ m_swlist = swlist;
+ m_interface = interface;
+ m_entrylist = nullptr;
+ m_ordered_by_shortname = true;
+}
+
+
+//-------------------------------------------------
+// dtor
+//-------------------------------------------------
+
+ui_menu_software_list::~ui_menu_software_list()
+{
+}
+
+
+//-------------------------------------------------
+// compare_entries
+//-------------------------------------------------
+
+int ui_menu_software_list::compare_entries(const entry_info *e1, const entry_info *e2, bool shortname)
+{
+ int result;
+ const char *e1_basename;
+ const char *e2_basename;
+
+ if (shortname)
+ {
+ e1_basename = (e1->short_name != nullptr) ? e1->short_name : "";
+ e2_basename = (e2->short_name != nullptr) ? e2->short_name : "";
+ }
+ else
+ {
+ e1_basename = (e1->long_name != nullptr) ? e1->long_name : "";
+ e2_basename = (e2->long_name != nullptr) ? e2->long_name : "";
+ }
+
+ result = core_stricmp(e1_basename, e2_basename);
+ if (result == 0)
+ {
+ result = strcmp(e1_basename, e2_basename);
+ if (result == 0)
+ {
+ if (e1 < e2)
+ result = -1;
+ else if (e1 > e2)
+ result = 1;
+ }
+ }
+
+ return result;
+}
+
+
+//-------------------------------------------------
+// append_software_entry - populate a specific list
+//-------------------------------------------------
+
+ui_menu_software_list::entry_info *ui_menu_software_list::append_software_entry(const software_info &swinfo)
+{
+ entry_info *entry = nullptr;
+ entry_info **entryptr;
+ bool entry_updated = FALSE;
+
+ // check if at least one of the parts has the correct interface and add a menu entry only in this case
+ for (const software_part &swpart : swinfo.parts())
+ {
+ if (swpart.matches_interface(m_interface) && swpart.is_compatible(*m_swlist))
+ {
+ entry_updated = TRUE;
+ // allocate a new entry
+ entry = (entry_info *) m_pool_alloc(sizeof(*entry));
+ memset(entry, 0, sizeof(*entry));
+
+ entry->short_name = pool_strdup(swinfo.shortname());
+ entry->long_name = pool_strdup(swinfo.longname());
+ break;
+ }
+ }
+
+ // skip this if no new entry has been allocated (e.g. if the software has no matching interface for this image device)
+ if (entry_updated)
+ {
+ // find the end of the list
+ entryptr = &m_entrylist;
+ while ((*entryptr != nullptr) && (compare_entries(entry, *entryptr, m_ordered_by_shortname) >= 0))
+ entryptr = &(*entryptr)->next;
+
+ // insert the entry
+ entry->next = *entryptr;
+ *entryptr = entry;
+ }
+
+ return entry;
+}
+
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_software_list::populate()
+{
+ // build up the list of entries for the menu
+ for (const software_info &swinfo : m_swlist->get_info())
+ append_software_entry(swinfo);
+
+ // add an entry to change ordering
+ item_append(_("Switch Item Ordering"), nullptr, 0, (void *)1);
+
+ // append all of the menu entries
+ for (entry_info *entry = m_entrylist; entry != nullptr; entry = entry->next)
+ item_append(entry->short_name, entry->long_name, 0, entry);
+}
+
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_menu_software_list::handle()
+{
+ const entry_info *entry;
+ const entry_info *selected_entry = nullptr;
+ int bestmatch = 0;
+
+ // process the menu
+ const ui_menu_event *event = process(0);
+
+ if (event != nullptr && event->itemref != nullptr)
+ {
+ if ((FPTR)event->itemref == 1 && event->iptkey == IPT_UI_SELECT)
+ {
+ m_ordered_by_shortname = !m_ordered_by_shortname;
+ m_entrylist = nullptr;
+
+ // reset the char buffer if we change ordering criterion
+ memset(m_filename_buffer, '\0', ARRAY_LENGTH(m_filename_buffer));
+
+ // reload the menu with the new order
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ machine().popmessage(_("Switched Order: entries now ordered by %s"), m_ordered_by_shortname ? _("shortname") : _("description"));
+ }
+ // handle selections
+ else if (event->iptkey == IPT_UI_SELECT)
+ {
+ entry_info *info = (entry_info *) event->itemref;
+ m_result = info->short_name;
+ ui_menu::stack_pop(machine());
+ }
+ else if (event->iptkey == IPT_SPECIAL)
+ {
+ int buflen = strlen(m_filename_buffer);
+ bool update_selected = false;
+
+ // if it's a backspace and we can handle it, do so
+ if ((event->unichar == 8 || event->unichar == 0x7f) && buflen > 0)
+ {
+ *(char *)utf8_previous_char(&m_filename_buffer[buflen]) = 0;
+ update_selected = true;
+
+ if (ARRAY_LENGTH(m_filename_buffer) > 0)
+ mame_machine_manager::instance()->ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_filename_buffer);
+ }
+ // if it's any other key and we're not maxed out, update
+ else if (event->unichar >= ' ' && event->unichar < 0x7f)
+ {
+ buflen += utf8_from_uchar(&m_filename_buffer[buflen], ARRAY_LENGTH(m_filename_buffer) - buflen, event->unichar);
+ m_filename_buffer[buflen] = 0;
+ update_selected = true;
+
+ if (ARRAY_LENGTH(m_filename_buffer) > 0)
+ mame_machine_manager::instance()->ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_filename_buffer);
+ }
+
+ if (update_selected)
+ {
+ const entry_info *cur_selected;
+
+ // if the current selection is a software entry, start search from here
+ if ((FPTR)event->itemref != 1)
+ cur_selected= (const entry_info *)get_selection();
+ // else (if we are on the 'Switch Order' entry) start from the beginning
+ else
+ cur_selected = m_entrylist;
+
+ // check for entries which matches our filename_buffer:
+ // from current entry to the end
+ for (entry = cur_selected; entry != nullptr; entry = entry->next)
+ {
+ const char *compare_name = m_ordered_by_shortname ? entry->short_name : entry->long_name;
+
+ if (compare_name != nullptr && m_filename_buffer != nullptr)
+ {
+ int match = 0;
+ for (int i = 0; i < ARRAY_LENGTH(m_filename_buffer); i++)
+ {
+ if (core_strnicmp(compare_name, m_filename_buffer, i) == 0)
+ match = i;
+ }
+
+ if (match > bestmatch)
+ {
+ bestmatch = match;
+ selected_entry = entry;
+ }
+ }
+ }
+ // and from the first entry to current one
+ for (entry = m_entrylist; entry != cur_selected; entry = entry->next)
+ {
+ const char *compare_name = m_ordered_by_shortname ? entry->short_name : entry->long_name;
+
+ if (compare_name != nullptr && m_filename_buffer != nullptr)
+ {
+ int match = 0;
+ for (int i = 0; i < ARRAY_LENGTH(m_filename_buffer); i++)
+ {
+ if (core_strnicmp(compare_name, m_filename_buffer, i) == 0)
+ match = i;
+ }
+
+ if (match > bestmatch)
+ {
+ bestmatch = match;
+ selected_entry = entry;
+ }
+ }
+ }
+
+ if (selected_entry != nullptr && selected_entry != cur_selected)
+ {
+ set_selection((void *)selected_entry);
+ top_line = selected - (visible_lines / 2);
+ }
+ }
+ }
+ else if (event->iptkey == IPT_UI_CANCEL)
+ {
+ // reset the char buffer also in this case
+ if (m_filename_buffer[0] != '\0')
+ memset(m_filename_buffer, '\0', ARRAY_LENGTH(m_filename_buffer));
+ m_result = m_filename_buffer;
+ ui_menu::stack_pop(machine());
+ }
+ }
+}
+
+
+/***************************************************************************
+ SOFTWARE MENU - list of available software lists - i.e. cartridges,
+ floppies
+***************************************************************************/
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+ui_menu_software::ui_menu_software(running_machine &machine, render_container *container, const char *interface, software_list_device **result)
+ : ui_menu(machine, container)
+{
+ m_interface = interface;
+ m_result = result;
+}
+
+
+//-------------------------------------------------
+// dtor
+//-------------------------------------------------
+
+ui_menu_software::~ui_menu_software()
+{
+}
+
+
+//-------------------------------------------------
+// populate
+//-------------------------------------------------
+
+void ui_menu_software::populate()
+{
+ bool have_compatible = false;
+
+ // Add original software lists for this system
+ software_list_device_iterator iter(machine().config().root_device());
+ for (software_list_device &swlistdev : iter)
+ if (swlistdev.list_type() == SOFTWARE_LIST_ORIGINAL_SYSTEM)
+ if (!swlistdev.get_info().empty() && m_interface != nullptr)
+ {
+ bool found = false;
+ for (const software_info &swinfo : swlistdev.get_info())
+ if (swinfo.first_part()->matches_interface(m_interface))
+ found = true;
+ if (found)
+ item_append(swlistdev.description(), nullptr, 0, (void *)&swlistdev);
+ }
+
+ // add compatible software lists for this system
+ for (software_list_device &swlistdev : iter)
+ if (swlistdev.list_type() == SOFTWARE_LIST_COMPATIBLE_SYSTEM)
+ if (!swlistdev.get_info().empty() && m_interface != nullptr)
+ {
+ bool found = false;
+ for (const software_info &swinfo : swlistdev.get_info())
+ if (swinfo.first_part()->matches_interface(m_interface))
+ found = true;
+ if (found)
+ {
+ if (!have_compatible)
+ item_append(_("[compatible lists]"), nullptr, MENU_FLAG_DISABLE, nullptr);
+ item_append(swlistdev.description(), nullptr, 0, (void *)&swlistdev);
+ }
+ have_compatible = true;
+ }
+}
+
+
+//-------------------------------------------------
+// handle
+//-------------------------------------------------
+
+void ui_menu_software::handle()
+{
+ // process the menu
+ const ui_menu_event *event = process(0);
+
+ if (event != nullptr && event->iptkey == IPT_UI_SELECT) {
+ // ui_menu::stack_push(global_alloc_clear<ui_menu_software_list>(machine(), container, (software_list_config *)event->itemref, image));
+ *m_result = (software_list_device *)event->itemref;
+ ui_menu::stack_pop(machine());
+ }
+}
diff --git a/src/frontend/mame/ui/swlist.h b/src/frontend/mame/ui/swlist.h
new file mode 100644
index 00000000000..253eeb6e7c8
--- /dev/null
+++ b/src/frontend/mame/ui/swlist.h
@@ -0,0 +1,84 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/***************************************************************************
+
+ ui/swlist.h
+
+ Internal MAME user interface for software list.
+
+***************************************************************************/
+
+#ifndef __UI_SWLIST_H__
+#define __UI_SWLIST_H__
+
+// ======================> ui_menu_software_parts
+
+class ui_menu_software_parts : public ui_menu {
+public:
+ enum { T_EMPTY, T_FMGR, T_SWLIST, T_ENTRY };
+ ui_menu_software_parts(running_machine &machine, render_container *container, const software_info *info, const char *interface, const software_part **part, bool other_opt, int *result);
+ virtual ~ui_menu_software_parts();
+ virtual void populate() override;
+ virtual void handle() override;
+
+private:
+ struct software_part_menu_entry {
+ int type;
+ const software_part *part;
+ };
+
+ // variables
+ const software_info * m_info;
+ const char * m_interface;
+ const software_part ** m_selected_part;
+ bool m_other_opt;
+ int * m_result;
+};
+
+
+// ======================> ui_menu_software_list
+
+class ui_menu_software_list : public ui_menu {
+public:
+ ui_menu_software_list(running_machine &machine, render_container *container, software_list_device *swlist, const char *interface, std::string &result);
+ virtual ~ui_menu_software_list();
+ virtual void populate() override;
+ virtual void handle() override;
+
+private:
+ struct entry_info {
+ entry_info *next;
+
+ const char *short_name;
+ const char *long_name;
+ };
+
+ // variables
+ software_list_device * m_swlist; // currently selected list
+ const char * m_interface;
+ std::string & m_result;
+ entry_info * m_entrylist;
+ char m_filename_buffer[1024];
+ bool m_ordered_by_shortname;
+
+ // functions
+ int compare_entries(const entry_info *e1, const entry_info *e2, bool shortname);
+ entry_info *append_software_entry(const software_info &swinfo);
+};
+
+
+// ======================> ui_menu_software
+
+class ui_menu_software : public ui_menu {
+public:
+ ui_menu_software(running_machine &machine, render_container *container, const char *interface, software_list_device **result);
+ virtual ~ui_menu_software();
+ virtual void populate() override;
+ virtual void handle() override;
+
+private:
+ const char * m_interface;
+ software_list_device ** m_result;
+};
+
+#endif /* __UI_SWLIST_H__ */
diff --git a/src/frontend/mame/ui/tapectrl.cpp b/src/frontend/mame/ui/tapectrl.cpp
new file mode 100644
index 00000000000..510d0eb3fb3
--- /dev/null
+++ b/src/frontend/mame/ui/tapectrl.cpp
@@ -0,0 +1,182 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/***************************************************************************
+
+ ui/tapectrl.cpp
+
+ Tape control
+
+***************************************************************************/
+
+#include "emu.h"
+#include "ui/menu.h"
+#include "ui/tapectrl.h"
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define TAPECMD_NULL ((void *) 0x0000)
+#define TAPECMD_STOP ((void *) 0x0001)
+#define TAPECMD_PLAY ((void *) 0x0002)
+#define TAPECMD_RECORD ((void *) 0x0003)
+#define TAPECMD_REWIND ((void *) 0x0004)
+#define TAPECMD_FAST_FORWARD ((void *) 0x0005)
+#define TAPECMD_SLIDER ((void *) 0x0006)
+#define TAPECMD_SELECT ((void *) 0x0007)
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+//-------------------------------------------------
+// ctor
+//-------------------------------------------------
+
+ui_menu_tape_control::ui_menu_tape_control(running_machine &machine, render_container *container, cassette_image_device *device)
+ : ui_menu_device_control<cassette_image_device>(machine, container, device)
+{
+}
+
+
+//-------------------------------------------------
+// dtor
+//-------------------------------------------------
+
+ui_menu_tape_control::~ui_menu_tape_control()
+{
+}
+
+
+//-------------------------------------------------
+// populate - populates the main tape control menu
+//-------------------------------------------------
+
+void ui_menu_tape_control::populate()
+{
+ if (current_device())
+ {
+ // name of tape
+ item_append(current_display_name().c_str(), current_device()->exists() ? current_device()->filename() : "No Tape Image loaded", current_display_flags(), TAPECMD_SELECT);
+
+ if (current_device()->exists())
+ {
+ std::string timepos;
+ cassette_state state;
+ double t0 = current_device()->get_position();
+ double t1 = current_device()->get_length();
+ UINT32 tapeflags = 0;
+
+ // state
+ if (t1 > 0)
+ {
+ if (t0 > 0)
+ tapeflags |= MENU_FLAG_LEFT_ARROW;
+ if (t0 < t1)
+ tapeflags |= MENU_FLAG_RIGHT_ARROW;
+ }
+
+ get_time_string(timepos, current_device(), nullptr, nullptr);
+ state = current_device()->get_state();
+ item_append(
+ (state & CASSETTE_MASK_UISTATE) == CASSETTE_STOPPED
+ ? _("stopped")
+ : ((state & CASSETTE_MASK_UISTATE) == CASSETTE_PLAY
+ ? ((state & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_ENABLED ? _("playing") : _("(playing)"))
+ : ((state & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_ENABLED ? _("recording") : _("(recording)"))
+ ),
+ timepos.c_str(),
+ tapeflags,
+ TAPECMD_SLIDER);
+
+ // pause or stop
+ item_append(_("Pause/Stop"), nullptr, 0, TAPECMD_STOP);
+
+ // play
+ item_append(_("Play"), nullptr, 0, TAPECMD_PLAY);
+
+ // record
+ item_append(_("Record"), nullptr, 0, TAPECMD_RECORD);
+
+ // rewind
+ item_append(_("Rewind"), nullptr, 0, TAPECMD_REWIND);
+
+ // fast forward
+ item_append(_("Fast Forward"), nullptr, 0, TAPECMD_FAST_FORWARD);
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// handle - main tape control menu
+//-------------------------------------------------
+
+void ui_menu_tape_control::handle()
+{
+ // rebuild the menu (so to update the selected device, if the user has pressed L or R, and the tape counter)
+ reset(UI_MENU_RESET_REMEMBER_POSITION);
+ populate();
+
+ // process the menu
+ const ui_menu_event *event = process(UI_MENU_PROCESS_LR_REPEAT);
+ if (event != nullptr)
+ {
+ switch(event->iptkey)
+ {
+ case IPT_UI_LEFT:
+ if (event->itemref == TAPECMD_SLIDER)
+ current_device()->seek(-1, SEEK_CUR);
+ else if (event->itemref == TAPECMD_SELECT)
+ previous();
+ break;
+
+ case IPT_UI_RIGHT:
+ if (event->itemref == TAPECMD_SLIDER)
+ current_device()->seek(+1, SEEK_CUR);
+ else if (event->itemref == TAPECMD_SELECT)
+ next();
+ break;
+
+ case IPT_UI_SELECT:
+ if (event->itemref == TAPECMD_STOP)
+ current_device()->change_state(CASSETTE_STOPPED, CASSETTE_MASK_UISTATE);
+ else if (event->itemref == TAPECMD_PLAY)
+ current_device()->change_state(CASSETTE_PLAY, CASSETTE_MASK_UISTATE);
+ else if (event->itemref == TAPECMD_RECORD)
+ current_device()->change_state(CASSETTE_RECORD, CASSETTE_MASK_UISTATE);
+ else if (event->itemref == TAPECMD_REWIND)
+ current_device()->seek(-30, SEEK_CUR);
+ else if (event->itemref == TAPECMD_FAST_FORWARD)
+ current_device()->seek(30, SEEK_CUR);
+ else if (event->itemref == TAPECMD_SLIDER)
+ current_device()->seek(0, SEEK_SET);
+ break;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// get_time_string - returns a textual
+// representation of the time
+//-------------------------------------------------
+
+void ui_menu_tape_control::get_time_string(std::string &dest, cassette_image_device *cassette, int *curpos, int *endpos)
+{
+ double t0, t1;
+
+ t0 = cassette->get_position();
+ t1 = cassette->get_length();
+
+ if (t1)
+ dest = string_format("%04d/%04d", (int)t0, (int)t1);
+ else
+ dest = string_format("%04d/%04d", 0, (int)t1);
+
+ if (curpos != nullptr)
+ *curpos = t0;
+ if (endpos != nullptr)
+ *endpos = t1;
+}
diff --git a/src/frontend/mame/ui/tapectrl.h b/src/frontend/mame/ui/tapectrl.h
new file mode 100644
index 00000000000..9cfa1316a99
--- /dev/null
+++ b/src/frontend/mame/ui/tapectrl.h
@@ -0,0 +1,30 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/***************************************************************************
+
+ ui/tapectrl.h
+
+ Tape control
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_TAPECTRL_H__
+#define __UI_TAPECTRL_H__
+
+#include "imagedev/cassette.h"
+#include "ui/devctrl.h"
+
+class ui_menu_tape_control : public ui_menu_device_control<cassette_image_device> {
+public:
+ ui_menu_tape_control(running_machine &machine, render_container *container, cassette_image_device *device);
+ virtual ~ui_menu_tape_control();
+ virtual void populate() override;
+ virtual void handle() override;
+
+private:
+ static void get_time_string(std::string &dest, cassette_image_device *cassette, int *curpos, int *endpos);
+};
+
+#endif /* __UI_TAPECTRL_H__ */
diff --git a/src/frontend/mame/ui/toolbar.h b/src/frontend/mame/ui/toolbar.h
new file mode 100644
index 00000000000..93ee1e3467b
--- /dev/null
+++ b/src/frontend/mame/ui/toolbar.h
@@ -0,0 +1,110 @@
+// license:BSD-3-Clause
+// copyright-holders:Dankan1890
+static const UINT32 toolbar_bitmap_bmp[][1024] = {
+{
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02D07A00, 0x15D07A00, 0x0FD07A00, 0x00D07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x76D27F04, 0xBFDA9714, 0xB9D78F0E, 0x4DD17B01, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3BD07A00, 0xFFE8B228, 0xFFFDEB50, 0xFFFBE34A, 0xD0E1A11C, 0x13D07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0BD07A00, 0xA0D48306, 0xFFFACE42, 0xFFFBCE45, 0xFFFCD146, 0xFFF2BD34, 0x67D07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x49D27E03, 0xE9EAAB26, 0xFFFDD044, 0xFFF9C741, 0xFFFAC942, 0xFFFED245, 0xD1DF9716, 0x27D07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xA2DB8D0F, 0xFFF6C236, 0xFFFAC740, 0xFFF8C53F, 0xFFF8C53F, 0xFFFDCB41, 0xF7F0B62E, 0x71D68308, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x31D07A00, 0xFFE7A420, 0xFFFDCA3F, 0xFFF8C23D, 0xFFF8C23D, 0xFFF8C23D, 0xFFF8C23D, 0xFFFCC83D, 0xE0E19818, 0x11D07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x08D07A00, 0x99D38004, 0xFFF9C237, 0xFFFAC43C, 0xFFF8BF3A, 0xFFF8BF3A, 0xFFF8BF3A, 0xFFF8BF3A, 0xFFFBC53C, 0xFFF1B32B, 0x63D07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x01D07A00, 0x15D07A00, 0x24D07A00, 0x39D07A00, 0x4AD07A00, 0x79D48205, 0xE6E9A820, 0xFFFDC539, 0xFFF8BC37, 0xFFF8BC37, 0xFFF8BC37, 0xFFF8BC37, 0xFFF8BC37, 0xFFF9BD37, 0xFFFEC63A, 0xD8DF9613, 0x64D17C01, 0x3FD07A00, 0x2FD07A00, 0x1CD07A00, 0x0AD07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x04D07A00, 0x3BD07A00, 0x8BD07A00, 0xA5D17B01, 0xBFDA940F, 0xCEE1A317, 0xE2E7B622, 0xF4EDC229, 0xFFF1C62D, 0xFFFAC735, 0xFFFABC35, 0xFFF8B934, 0xFFF8B934, 0xFFF8B934, 0xFFF8B934, 0xFFF8B934, 0xFFF8B934, 0xFFFCBF36, 0xFFF7C733, 0xFCEFC52C, 0xE9EABB24, 0xD8E4AE1D, 0xC6DD9C13, 0xB4D58608, 0x99D07A00, 0x75D07A00, 0x20D07A00, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x01D07A00, 0xBBD78608, 0xFFE9AE1F, 0xFFF9D133, 0xFFFCD839, 0xFFFCD338, 0xFFFCCC36, 0xFFFCC333, 0xFFFCBB32, 0xFFF7B630, 0xFFF7B630, 0xFFF7B630, 0xFFF7B630, 0xFFF7B630, 0xFFF7B630, 0xFFF7B630, 0xFFF7B630, 0xFFF7B630, 0xFFF7B630, 0xFFF7B630, 0xFFFAB831, 0xFFFCC033, 0xFFFCC735, 0xFFFCD037, 0xFFFCD739, 0xFFFBD536, 0xFFF5C92F, 0xE8E4A318, 0x55D78507, 0x00000000, 0x00000000,
+ 0x00000000, 0x13D07A00, 0xFFDF9212, 0xFFFABC2F, 0xFFF9B72F, 0xFFF8B32E, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B32D, 0xFFF9B52E, 0xFFF9B92F, 0xFFF6B52A, 0xC1DB8B0D, 0x00000000, 0x00000000,
+ 0x00000000, 0x07D07A00, 0xE6DC8B0E, 0xFFF4AB27, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFEFA421, 0xAAD9860A, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x5ED58005, 0xE8E39213, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF4A925, 0xE2DC890C, 0x45D27C02, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x41D07A00, 0xE7E18F11, 0xFFF3A420, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFEFA11D, 0xE0DB880A, 0x35D07A00, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5DD47E03, 0xE6E08D0D, 0xFFF5A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFF3A11D, 0xDFDB8609, 0x4FD27C01, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40D07A00, 0xE6E08A0C, 0xFFF29D19, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFF6A01C, 0xFFEE9917, 0xDDDA8407, 0x30D07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5BD37D02, 0xE6DF880A, 0xFFF59C18, 0xFFF69D18, 0xFFF69D18, 0xFFF69D18, 0xFFF69D18, 0xFFF69D18, 0xFFF69D18, 0xFFF69D18, 0xFFF69D18, 0xFFF69D18, 0xFFF69D18, 0xFFF69D18, 0xFFF69D18, 0xFFF69D18, 0xFFF69D18, 0xFFF29A16, 0xDCD98306, 0x49D17B01, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x7BD07A00, 0xFFEF9311, 0xFFF69A15, 0xFFF59915, 0xFFF59915, 0xFFF59915, 0xFFF59915, 0xFFF59915, 0xFFF59915, 0xFFF59915, 0xFFF59915, 0xFFF59915, 0xFFF59915, 0xFFF59915, 0xFFF59915, 0xFFF69915, 0xFFE2890A, 0x3BD07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x01D07A00, 0xA2D17B00, 0xFFF59612, 0xFFF69713, 0xFFF59612, 0xFFF59612, 0xFFF59612, 0xFFF59612, 0xFFF59612, 0xFFF59612, 0xFFF59612, 0xFFF59612, 0xFFF59612, 0xFFF59612, 0xFFF59612, 0xFFF59612, 0xFFF79712, 0xFFE98D0B, 0x4BD07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x14D07A00, 0xBED87F03, 0xFFF6940E, 0xFFF5930E, 0xFFF5930E, 0xFFF5930E, 0xFFF5930E, 0xFFF5930E, 0xFFF5930E, 0xFFF5930E, 0xFFF5930E, 0xFFF5930E, 0xFFF5930E, 0xFFF5930E, 0xFFF5930E, 0xFFF5930E, 0xFFF7940E, 0xFFF1900B, 0x7ED07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x27D07A00, 0xD1DE8205, 0xFFF8920C, 0xFFF5900C, 0xFFF5900C, 0xFFF5900C, 0xFFF5900C, 0xFFF5900C, 0xFFF5900C, 0xFFF5900C, 0xFFF5900C, 0xFFF5900C, 0xFFF5900C, 0xFFF5900C, 0xFFF5900C, 0xFFF5900C, 0xFFF6910C, 0xFFF5910C, 0xA5D27B01, 0x03D07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40D07A00, 0xEAE48505, 0xFFFA9009, 0xFFF58D09, 0xFFF58D09, 0xFFF58D09, 0xFFF58D09, 0xFFF58D09, 0xFFF58D09, 0xFFF58D09, 0xFFF58D09, 0xFFF58D09, 0xFFF58D09, 0xFFF58D09, 0xFFF58D09, 0xFFF58D09, 0xFFF58D09, 0xFFF78E09, 0xC1D97F02, 0x17D07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x57D17B00, 0xFBE88504, 0xFFF78D06, 0xFFF48B06, 0xFFF48B06, 0xFFF48B06, 0xFFF48B06, 0xFFF48B06, 0xFFF38B06, 0xFFEC8705, 0xFFF18A06, 0xFFF48B06, 0xFFF48B06, 0xFFF48B06, 0xFFF48B06, 0xFFF48B06, 0xFFF48B06, 0xFFF88E06, 0xD6DF8102, 0x2CD07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x83D67D01, 0xFFED8503, 0xFFF48804, 0xFFF48804, 0xFFF48804, 0xFFF48804, 0xFFF28804, 0xFFEA8503, 0xCDDC7F02, 0x79D17B00, 0xA1D47C01, 0xEFE18102, 0xFFEE8604, 0xFFF38804, 0xFFF48804, 0xFFF48804, 0xFFF48804, 0xFFF88B04, 0xEFE58203, 0x46D07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xA0D87D01, 0xFFED8401, 0xFFF48602, 0xFFF48602, 0xFFF48602, 0xFFEF8501, 0xE9DE7F01, 0x8FD67D00, 0x23D07A00, 0x04D07A00, 0x0DD07A00, 0x46D07A00, 0xC3D97D01, 0xFFE28001, 0xFFF38602, 0xFFF48602, 0xFFF48602, 0xFFF58702, 0xFDE88201, 0x59D17A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5FD47B00, 0xF3E58000, 0xFFF18400, 0xFFED8200, 0xDEE07F01, 0x90D37B00, 0x1FD07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x01D07A00, 0x3BD07A00, 0xBDD67C00, 0xF2E48000, 0xFFEF8300, 0xFFF08300, 0xDEDF7E01, 0x34D07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x10D07A00, 0x71D57C00, 0xD2DB7D00, 0x9AD87C00, 0x34D07A00, 0x0AD07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x13D07A00, 0x52D27B00, 0xBBD97D00, 0xCBDA7D00, 0x5DD27B00, 0x0AD07A00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
+},
+
+{
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x41D07A00, 0x8BD07A00, 0xAAD07A00, 0xAAD07A00, 0xAAC48715, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAACA810B, 0xAAD07A00, 0xA4D07A00, 0x7DD07A00, 0x1CD07A00, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x07D07A00, 0x7BD38206, 0xFFE8B82B, 0xFFF9E24B, 0xFFFEEE55, 0xFFFDEE55, 0xFFCBA95F, 0xFFEBEBEB, 0xFFF1F1F1, 0xFFF3F3F3, 0xFFF7F7F7, 0xFFF9F9F9, 0xFFFCFCFC, 0xFFFEFEFE, 0xFFFEFEFE, 0xFFFEFEFE, 0xFFFCFCFC, 0xFFFAFAFA, 0xFFF7F7F7, 0xFFF5F5F5, 0xFFF2F2F2, 0xFFE9E9E9, 0xFFD4AC2F, 0xFFFDEE55, 0xFFFDEC53, 0xFFF6DE47, 0xE4DE9E19, 0x49D38105, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x2DD07A00, 0xD7E39E1C, 0xFFFDDC4A, 0xFFFBD047, 0xFFFACC45, 0xFFF9CB45, 0xFFC4A258, 0xFFD0D0D0, 0xFFD6D6D6, 0xFFDDDDDD, 0xFFE6E6E6, 0xFFEEEEEE, 0xFFF6F6F6, 0xFFFBFBFB, 0xFFF0E5CC, 0xFFD4B167, 0xFFD2B066, 0xFFD0AE64, 0xFFE9E9E9, 0xFFE1E1E1, 0xFFD8D8D8, 0xFFD2D2D2, 0xFFD3A12A, 0xFFF9CB45, 0xFFFACD46, 0xFFFBD348, 0xFFF7CD3E, 0xB2DB9112, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x52D07A00, 0xFCEBAD2C, 0xFFFCCC44, 0xFFF9C943, 0xFFF9C943, 0xFFF9C943, 0xFFC4A258, 0xFFD0D0D0, 0xFFD6D6D6, 0xFFDDDDDD, 0xFFE6E6E6, 0xFFEEEEEE, 0xFFF6F6F6, 0xFFFBFBFB, 0xFFE9D8B3, 0xFFE6B437, 0xFFF9C943, 0xFFD3A02A, 0xFFE9E9E9, 0xFFE1E1E1, 0xFFD8D8D8, 0xFFD2D2D2, 0xFFD3A02A, 0xFFF9C943, 0xFFF9C943, 0xFFF9C943, 0xFFFBCB44, 0xFADD9416, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x55D07A00, 0xFFEBAD2B, 0xFFF9C741, 0xFFF9C741, 0xFFF9C741, 0xFFF9C741, 0xFFC4A258, 0xFFD0D0D0, 0xFFD6D6D6, 0xFFDDDDDD, 0xFFE6E6E6, 0xFFEEEEEE, 0xFFF6F6F6, 0xFFFBFBFB, 0xFFE9D8B3, 0xFFE6B335, 0xFFF9C741, 0xFFD3A029, 0xFFE9E9E9, 0xFFE1E1E1, 0xFFD8D8D8, 0xFFD2D2D2, 0xFFD3A029, 0xFFF9C741, 0xFFF9C741, 0xFFF9C741, 0xFFF9C741, 0xFFDD9416, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x55D07A00, 0xFFEAAB2A, 0xFFF8C43F, 0xFFF8C43F, 0xFFF8C43F, 0xFFF8C43F, 0xFFC4A258, 0xFFD0D0D0, 0xFFD6D6D6, 0xFFDDDDDD, 0xFFE6E6E6, 0xFFEEEEEE, 0xFFF6F6F6, 0xFFFBFBFB, 0xFFE9D8B3, 0xFFE5B133, 0xFFF8C43F, 0xFFD29F28, 0xFFE9E9E9, 0xFFE1E1E1, 0xFFD8D8D8, 0xFFD2D2D2, 0xFFD29F28, 0xFFF8C43F, 0xFFF8C43F, 0xFFF8C43F, 0xFFF8C43F, 0xFFDD9315, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x55D07A00, 0xFFEAAA28, 0xFFF8C23C, 0xFFF8C23C, 0xFFF8C23C, 0xFFF8C23C, 0xFFC4A258, 0xFFD0D0D0, 0xFFD6D6D6, 0xFFDDDDDD, 0xFFE6E6E6, 0xFFEEEEEE, 0xFFF6F6F6, 0xFFFBFBFB, 0xFFE9D8B3, 0xFFE5B032, 0xFFF8C23C, 0xFFD29E27, 0xFFE9E9E9, 0xFFE1E1E1, 0xFFD8D8D8, 0xFFD2D2D2, 0xFFD29E27, 0xFFF8C23C, 0xFFF8C23C, 0xFFF8C23C, 0xFFF8C23C, 0xFFDD9214, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x55D07A00, 0xFFEAA826, 0xFFF8BF39, 0xFFF8BF39, 0xFFF8BF39, 0xFFF8BF39, 0xFFC9A352, 0xFFCFCDC7, 0xFFD6D6D6, 0xFFDDDDDD, 0xFFE6E6E6, 0xFFEEEEEE, 0xFFF6F6F6, 0xFFFBFBFB, 0xFFE9D8B3, 0xFFD8A329, 0xFFE5AE30, 0xFFCC9723, 0xFFECECEC, 0xFFE1E1E1, 0xFFD8D8D8, 0xFFD0CCC2, 0xFFD8A128, 0xFFF8BF39, 0xFFF8BF39, 0xFFF8BF39, 0xFFF8BF39, 0xFFDD9113, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x55D07A00, 0xFFEAA624, 0xFFF8BC36, 0xFFF8BC36, 0xFFF8BC36, 0xFFF8BC36, 0xFFD7A63B, 0xFFCCBFA3, 0xFFD6D6D6, 0xFFDDDDDD, 0xFFE6E6E6, 0xFFEEEEEE, 0xFFF6F6F6, 0xFFFBFBFB, 0xFFF8F2E6, 0xFFEAD8B3, 0xFFEAD8B3, 0xFFEAD8B3, 0xFFF5F5F5, 0xFFE1E1E1, 0xFFD8D7D5, 0xFFCBB280, 0xFFE9AF2F, 0xFFF8BC36, 0xFFF8BC36, 0xFFF8BC36, 0xFFF8BC36, 0xFFDD9012, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x55D07A00, 0xFFEAA422, 0xFFF8B933, 0xFFF8B933, 0xFFF8B933, 0xFFF8B933, 0xFFF1B430, 0xFFD6A02D, 0xFFD0B57B, 0xFFD3C099, 0xFFD9C8A3, 0xFFDFCDA8, 0xFFE4D3AE, 0xFFE7D6B1, 0xFFE9D8B3, 0xFFE8D7B2, 0xFFE5D3AE, 0xFFE1CFAA, 0xFFDBCAA5, 0xFFD5C298, 0xFFD0AB5D, 0xFFDDA42C, 0xFFF8B933, 0xFFF8B933, 0xFFF8B933, 0xFFF8B933, 0xFFF8B933, 0xFFDD8F11, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x55D07A00, 0xFFEAA120, 0xFFF7B530, 0xFFF7B530, 0xFFF7B530, 0xFFF7B530, 0xFFF7B530, 0xFFF4B32F, 0xFFE9AB2B, 0xFFE5A72A, 0xFFE4A729, 0xFFE4A729, 0xFFE4A729, 0xFFE4A729, 0xFFE4A729, 0xFFE4A729, 0xFFE4A729, 0xFFE4A729, 0xFFE4A729, 0xFFE5A82A, 0xFFEDAE2D, 0xFFF5B430, 0xFFF7B530, 0xFFF7B530, 0xFFF7B530, 0xFFF7B530, 0xFFF7B530, 0xFFDD8E10, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x55D07A00, 0xFFEA9F1E, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFF7B22D, 0xFFDD8D0F, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x55D07A00, 0xFFEA9D1C, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFF7AF2A, 0xFFDD8B0E, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x55D07A00, 0xFFEA9A19, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF0A725, 0xFFE8A324, 0xFFE4A123, 0xFFE4A123, 0xFFE4A123, 0xFFE4A123, 0xFFE4A123, 0xFFE4A123, 0xFFE4A123, 0xFFE4A123, 0xFFE4A123, 0xFFE4A123, 0xFFE4A123, 0xFFE4A123, 0xFFE5A124, 0xFFE9A424, 0xFFF4AA26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFF7AB26, 0xFFDD8A0D, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x55D07A00, 0xFFE99917, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFE9A122, 0xFFD7A84A, 0xFFE5CC98, 0xFFEAD8B3, 0xFFEAD8B3, 0xFFEAD8B3, 0xFFEAD8B3, 0xFFEAD8B3, 0xFFEAD8B3, 0xFFEAD8B3, 0xFFEAD8B3, 0xFFEAD8B3, 0xFFEAD8B3, 0xFFEAD8B3, 0xFFEAD8B3, 0xFFE9D6AE, 0xFFE4C78C, 0xFFD89C2A, 0xFFF0A522, 0xFFF6A823, 0xFFF6A823, 0xFFF6A823, 0xFFDD890B, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x55D07A00, 0xFFE99614, 0xFFF6A41F, 0xFFF6A41F, 0xFFEFA11F, 0xFFD7A94D, 0xFFFBF9F6, 0xFFF7F7F7, 0xFFEFEFEF, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFF2F2F2, 0xFFF8F8F8, 0xFFEEE1C5, 0xFFDBA136, 0xFFF6A41F, 0xFFF6A41F, 0xFFF6A41F, 0xFFDC880A, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x55D07A00, 0xFFE99413, 0xFFF6A11C, 0xFFF6A11C, 0xFFE79B1C, 0xFFDDC594, 0xFFF3F3F3, 0xFFEDEDED, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFEDEDED, 0xFFF2EFEA, 0xFFD2AA59, 0xFFF6A11C, 0xFFF6A11C, 0xFFF6A11C, 0xFFDC8709, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x55D07A00, 0xFFE99110, 0xFFF69D18, 0xFFF69D18, 0xFFE49719, 0xFFDCCAA5, 0xFFE9E9E9, 0xFFE2E2E2, 0xFFDEDEDE, 0xFFDEDEDE, 0xFFDEDEDE, 0xFFDEDEDE, 0xFFDEDEDE, 0xFFDEDEDE, 0xFFDEDEDE, 0xFFDEDEDE, 0xFFDEDEDE, 0xFFDEDEDE, 0xFFDEDEDE, 0xFFDEDEDE, 0xFFDEDEDE, 0xFFE6E6E6, 0xFFEAEAEA, 0xFFCEAB61, 0xFFF69D18, 0xFFF69D18, 0xFFF69D18, 0xFFDC8608, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x55D07A00, 0xFFE88F0E, 0xFFF59A15, 0xFFF59A15, 0xFFE39518, 0xFFDAC9A4, 0xFFE7E7E7, 0xFFE0E0E0, 0xFFDCDCDC, 0xFFDCDCDC, 0xFFDCDCDC, 0xFFDCDCDC, 0xFFDCDCDC, 0xFFDCDCDC, 0xFFDCDCDC, 0xFFDCDCDC, 0xFFDCDCDC, 0xFFDCDCDC, 0xFFDCDCDC, 0xFFDCDCDC, 0xFFDCDCDC, 0xFFE4E4E4, 0xFFE7E7E7, 0xFFCDAA60, 0xFFF59A15, 0xFFF59A15, 0xFFF59A15, 0xFFDC8507, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x55D07A00, 0xFFE88D0C, 0xFFF59712, 0xFFF59712, 0xFFE39315, 0xFFD8C6A1, 0xFFE4E4E4, 0xFFE4E4E4, 0xFFE4E4E4, 0xFFE4E4E4, 0xFFE4E4E4, 0xFFE4E4E4, 0xFFE4E4E4, 0xFFE4E4E4, 0xFFE4E4E4, 0xFFE4E4E4, 0xFFE4E4E4, 0xFFE4E4E4, 0xFFE4E4E4, 0xFFE4E4E4, 0xFFE4E4E4, 0xFFE4E4E4, 0xFFE4E4E4, 0xFFCCA95F, 0xFFF59712, 0xFFF59712, 0xFFF59712, 0xFFDC8406, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x55D07A00, 0xFFE88B0A, 0xFFF5930F, 0xFFF5930F, 0xFFE39114, 0xFFD5C49F, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFCBA85E, 0xFFF5930F, 0xFFF5930F, 0xFFF5930F, 0xFFDC8205, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x55D07A00, 0xFFE88808, 0xFFF5900C, 0xFFF5900C, 0xFFE38E11, 0xFFD3C29D, 0xFFDCDCDC, 0xFFCECECE, 0xFFC7C7C7, 0xFFC7C7C7, 0xFFC7C7C7, 0xFFC7C7C7, 0xFFC7C7C7, 0xFFC7C7C7, 0xFFC7C7C7, 0xFFC7C7C7, 0xFFC7C7C7, 0xFFC7C7C7, 0xFFC7C7C7, 0xFFC7C7C7, 0xFFC7C7C7, 0xFFD6D6D6, 0xFFDDDDDD, 0xFFCAA75D, 0xFFF5900C, 0xFFF5900C, 0xFFF5900C, 0xFFDC8104, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x55D07A00, 0xFFE88706, 0xFFF58E09, 0xFFF58E09, 0xFFE38D10, 0xFFD1C09B, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFC8A65C, 0xFFF58E09, 0xFFF58E09, 0xFFF58E09, 0xFFDC8103, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x55D07A00, 0xFFE88504, 0xFFF48B07, 0xFFF48B07, 0xFFE38B0E, 0xFFCEBD98, 0xFFD6D6D6, 0xFFD6D6D6, 0xFFD6D6D6, 0xFFD6D6D6, 0xFFD6D6D6, 0xFFD6D6D6, 0xFFD6D6D6, 0xFFD6D6D6, 0xFFD6D6D6, 0xFFD6D6D6, 0xFFD6D6D6, 0xFFD6D6D6, 0xFFD6D6D6, 0xFFD6D6D6, 0xFFD6D6D6, 0xFFD6D6D6, 0xFFD6D6D6, 0xFFC7A55B, 0xFFF48B07, 0xFFF48B07, 0xFFF48B07, 0xFFDC8002, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x52D07A00, 0xFCE78404, 0xFFF48905, 0xFFF48905, 0xFFE28A0D, 0xFFCDBC97, 0xFFD3D3D3, 0xFFC6C6C6, 0xFFBFBFBF, 0xFFBFBFBF, 0xFFBFBFBF, 0xFFBFBFBF, 0xFFBFBFBF, 0xFFBFBFBF, 0xFFBFBFBF, 0xFFBFBFBF, 0xFFBFBFBF, 0xFFBFBFBF, 0xFFBFBFBF, 0xFFBFBFBF, 0xFFBFBFBF, 0xFFCDCDCD, 0xFFD4D4D4, 0xFFC7A45A, 0xFFF48905, 0xFFF48905, 0xFFF38905, 0xFADC7F02, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x2ED07A00, 0xD8DF7F01, 0xFFF38602, 0xFFF48602, 0xFFE2880B, 0xFFCBBA95, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFC6A359, 0xFFF48602, 0xFFF48602, 0xFFED8402, 0xB2D97D01, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x08D07A00, 0x7BD37B00, 0xFFE27F00, 0xFFF08401, 0xFFE2870A, 0xFFCAB893, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFC5A258, 0xFFF38501, 0xFFEE8301, 0xE4DB7D00, 0x49D27B00, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x43D07A00, 0x8DD07A00, 0xAACD7D05, 0xAAC28919, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC08C1D, 0xAAC48715, 0xA5D07A00, 0x7FD07A00, 0x1DD07A00, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
+},
+
+{
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0E999999, 0x59999999, 0x9E999999, 0xAA999999, 0xAA999999, 0xAA999999, 0xAA999999, 0xAA999999, 0xAA999999, 0xAA999999, 0xAA999999, 0xAA999999, 0xAA999999, 0xAA999999, 0xAA999999, 0xAA999999, 0xAA999999, 0xAA999999, 0xAA999999, 0xAA999999, 0xAA999999, 0xAA999999, 0x8B999999, 0x41999999, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x0F999999, 0xC8AEAEAE, 0xFFDADADA, 0xFFF7F7F7, 0xFFFAFAFA, 0xFFFAFAFA, 0xFFFAFAFA, 0xFFFAFAFA, 0xFFFAFAFA, 0xFFFAFAFA, 0xFFFAFAFA, 0xFFFAFAFA, 0xFFFAFAFA, 0xFFFAFAFA, 0xFFFAFAFA, 0xFFFAFAFA, 0xFFFAFAFA, 0xFFFAFAFA, 0xFFFAFAFA, 0xFFFAFAFA, 0xFFFAFAFA, 0xFFFAFAFA, 0xFFFAFAFA, 0xFFF1F1F1, 0xFFCDCDCD, 0x7BA1A1A1, 0x08999999, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x5B999999, 0xFFDADADA, 0xFFF8F8F8, 0xFFF2F2F2, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFF0F0F0, 0xFFF3F3F3, 0xFFFAFAFA, 0xD8BFBFBF, 0x2E999999, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xA3999999, 0xFFEEEEEE, 0xFFF0F0F0, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFEFEFEF, 0xFFF2F2F2, 0xFCD1D1D1, 0x53999999, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xAA999999, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFEEEEEE, 0xFFD1D1D1, 0x55999999, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xAA999999, 0xFFEDEDED, 0xFFEDEDED, 0xFFEDEDED, 0xFFB5B5B5, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF9A9A9A, 0xFFD3D3D3, 0xFFEDEDED, 0xFFEDEDED, 0xFFD1D1D1, 0x55999999, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xAA999999, 0xFFEDEDED, 0xFFEDEDED, 0xFFEDEDED, 0xFFDADADA, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFD1D1D1, 0xFFE4E4E4, 0xFFEDEDED, 0xFFEDEDED, 0xFFD1D1D1, 0x55999999, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xAA999999, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFECECEC, 0xFFD0D0D0, 0x55999999, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xAA999999, 0xFFEBEBEB, 0xFFEBEBEB, 0xFFEBEBEB, 0xFFEBEBEB, 0xFFEBEBEB, 0xFFEBEBEB, 0xFFEBEBEB, 0xFFEBEBEB, 0xFFEBEBEB, 0xFFEBEBEB, 0xFFEBEBEB, 0xFFEBEBEB, 0xFFEBEBEB, 0xFFEBEBEB, 0xFFEBEBEB, 0xFFEBEBEB, 0xFFEBEBEB, 0xFFEBEBEB, 0xFFEBEBEB, 0xFFEBEBEB, 0xFFEBEBEB, 0xFFEBEBEB, 0xFFEBEBEB, 0xFFEBEBEB, 0xFFCFCFCF, 0x55999999, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xAA999999, 0xFFEAEAEA, 0xFFEAEAEA, 0xFFEAEAEA, 0xFFD8D8D8, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFCFCFCF, 0xFFE1E1E1, 0xFFEAEAEA, 0xFFEAEAEA, 0xFFCFCFCF, 0x55999999, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xAA999999, 0xFFE9E9E9, 0xFFE9E9E9, 0xFFE9E9E9, 0xFFB4B4B4, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF9A9A9A, 0xFFD0D0D0, 0xFFE9E9E9, 0xFFE9E9E9, 0xFFCECECE, 0x55999999, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xAA999999, 0xFFE8E8E8, 0xFFE8E8E8, 0xFFE8E8E8, 0xFFE8E8E8, 0xFFE8E8E8, 0xFFE8E8E8, 0xFFE8E8E8, 0xFFE8E8E8, 0xFFE8E8E8, 0xFFE8E8E8, 0xFFE8E8E8, 0xFFE8E8E8, 0xFFE8E8E8, 0xFFE8E8E8, 0xFFE8E8E8, 0xFFE8E8E8, 0xFFE8E8E8, 0xFFE8E8E8, 0xFFE8E8E8, 0xFFE8E8E8, 0xFFE8E8E8, 0xFFE8E8E8, 0xFFE8E8E8, 0xFFE8E8E8, 0xFFCDCDCD, 0x55999999, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xAA999999, 0xFFE7E7E7, 0xFFE7E7E7, 0xFFE7E7E7, 0xFFE7E7E7, 0xFFE7E7E7, 0xFFE7E7E7, 0xFFE7E7E7, 0xFFE7E7E7, 0xFFE7E7E7, 0xFFE7E7E7, 0xFFE7E7E7, 0xFFE7E7E7, 0xFFE7E7E7, 0xFFE7E7E7, 0xFFE7E7E7, 0xFFE7E7E7, 0xFFE7E7E7, 0xFFE7E7E7, 0xFFE7E7E7, 0xFFE7E7E7, 0xFFE7E7E7, 0xFFE7E7E7, 0xFFE7E7E7, 0xFFE7E7E7, 0xFFCDCDCD, 0x55999999, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xAA999999, 0xFFE6E6E6, 0xFFE6E6E6, 0xFFE6E6E6, 0xFFE6E6E6, 0xFFE6E6E6, 0xFFE6E6E6, 0xFFE6E6E6, 0xFFE6E6E6, 0xFFE6E6E6, 0xFFE6E6E6, 0xFFE6E6E6, 0xFFE6E6E6, 0xFFE6E6E6, 0xFFE6E6E6, 0xFFE6E6E6, 0xFFE6E6E6, 0xFFE6E6E6, 0xFFE6E6E6, 0xFFE6E6E6, 0xFFE6E6E6, 0xFFE6E6E6, 0xFFE6E6E6, 0xFFE6E6E6, 0xFFE6E6E6, 0xFFCCCCCC, 0x55999999, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xAA999999, 0xFFE5E5E5, 0xFFE5E5E5, 0xFFE5E5E5, 0xFFE5E5E5, 0xFFE5E5E5, 0xFFE5E5E5, 0xFFE5E5E5, 0xFFE5E5E5, 0xFFE5E5E5, 0xFFE5E5E5, 0xFFE5E5E5, 0xFFE5E5E5, 0xFFE5E5E5, 0xFFE5E5E5, 0xFFE5E5E5, 0xFFE5E5E5, 0xFFE5E5E5, 0xFFE5E5E5, 0xFFE5E5E5, 0xFFE5E5E5, 0xFFE5E5E5, 0xFFE5E5E5, 0xFFE5E5E5, 0xFFE5E5E5, 0xFFCBCBCB, 0x55999999, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xAA999999, 0xFFE4E4E4, 0xFFE4E4E4, 0xFFE4E4E4, 0xFFB2B2B2, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF999999, 0xFF9A9A9A, 0xFFCCCCCC, 0xFFE4E4E4, 0xFFE4E4E4, 0xFFCBCBCB, 0x55999999, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xAA999999, 0xFFE3E3E3, 0xFFE3E3E3, 0xFFE3E3E3, 0xFFD2D2D2, 0xFFCACACA, 0xFFCACACA, 0xFFCACACA, 0xFFCACACA, 0xFFCACACA, 0xFFCACACA, 0xFFCACACA, 0xFFCACACA, 0xFFCACACA, 0xFFCACACA, 0xFFCACACA, 0xFFCACACA, 0xFFCACACA, 0xFFCACACA, 0xFFCACACA, 0xFFB0BABD, 0xFFAEB9BC, 0xFFDADBDB, 0xFFABC1C8, 0xFFD9DDDE, 0xFFCACACA, 0x55999999, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xAA999999, 0xFFE2E2E2, 0xFFE2E2E2, 0xFFE2E2E2, 0xFFE2E2E2, 0xFFE2E2E2, 0xFFE2E2E2, 0xFFE2E2E2, 0xFFE2E2E2, 0xFFE2E2E2, 0xFFE2E2E2, 0xFFE2E2E2, 0xFFE2E2E2, 0xFFE2E2E2, 0xFFE2E2E2, 0xFFE2E2E2, 0xFFE2E2E2, 0xFFDEE0E0, 0xFFBECFD4, 0xFFC5D1D4, 0xFF6CADC1, 0xFF53B4CE, 0xFF89B6C4, 0xFF35AAC8, 0xFFA8C3CC, 0xFFA6B9BE, 0x59758F96, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xAA999999, 0xFFE1E1E1, 0xFFE1E1E1, 0xFFE1E1E1, 0xFFE1E1E1, 0xFFE1E1E1, 0xFFE1E1E1, 0xFFE1E1E1, 0xFFE1E1E1, 0xFFE1E1E1, 0xFFE1E1E1, 0xFFE1E1E1, 0xFFE1E1E1, 0xFFE1E1E1, 0xFFE1E1E1, 0xFFE1E1E1, 0xFFE1E1E1, 0xFFD2D7D9, 0xFF5CABC4, 0xFF4AB6D1, 0xFF35ACD0, 0xFF2ABAE5, 0xFF25B0D9, 0xFF28B6E3, 0xFF49ACC8, 0xFF3AACCB, 0x632385A4, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xAA999999, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFE0E0E0, 0xFFDEDFDF, 0xFFA7C0C9, 0xFF79B4C5, 0xFF3CA1C0, 0xFF29B3E0, 0xFF25B0DC, 0xFF5DC2E3, 0xFFB1E2F2, 0xFF59C2E3, 0xFF26B3DE, 0xFF26A8D2, 0xA41C8CAD, 0x661783A4, 0x180E6784,
+ 0x00000000, 0x00000000, 0x00000000, 0xAA999999, 0xFFDFDFDF, 0xFFDFDFDF, 0xFFDFDFDF, 0xFFC0C0C0, 0xFFB0B0B0, 0xFFB0B0B0, 0xFFB0B0B0, 0xFFB0B0B0, 0xFFB0B0B0, 0xFFB0B0B0, 0xFFB0B0B0, 0xFFB0B0B0, 0xFFB0B0B0, 0xFFB0B0B0, 0xFFDEDEDE, 0xFF87AEBA, 0xFF24A7D1, 0xFF25ABD5, 0xFF25A8D1, 0xFF1EA4CF, 0xFF9BD7EA, 0xFFFFFFFF, 0xFF91D3E8, 0xFF23A6D0, 0xFF25A9D2, 0xFD26ACD4, 0xD11E94B8, 0x280D647F,
+ 0x00000000, 0x00000000, 0x00000000, 0xAA999999, 0xFFDEDEDE, 0xFFDEDEDE, 0xFFDEDEDE, 0xFFBFBFBF, 0xFFB0B0B0, 0xFFB0B0B0, 0xFFB0B0B0, 0xFFB0B0B0, 0xFFB0B0B0, 0xFFB0B0B0, 0xFFB0B0B0, 0xFFB0B0B0, 0xFFB0B0B0, 0xFFB0B0B0, 0xFFBFCCD1, 0xFF85B3C2, 0xFF1F96BC, 0xFF229FC7, 0xFF229FC6, 0xFF1B9BC5, 0xFF95D1E4, 0xFFFFFFFF, 0xFF8DCDE2, 0xFF219DC6, 0xFF229FC6, 0xFF22A0C8, 0xBE1986A9, 0x46137696,
+ 0x00000000, 0x00000000, 0x00000000, 0xAA999999, 0xFFDDDDDD, 0xFFDDDDDD, 0xFFDDDDDD, 0xFFDDDDDD, 0xFFDDDDDD, 0xFFDDDDDD, 0xFFDDDDDD, 0xFFDDDDDD, 0xFFDDDDDD, 0xFFDDDDDD, 0xFFDDDDDD, 0xFFDDDDDD, 0xFFDDDDDD, 0xFFDDDDDD, 0xFF77A5B4, 0xFF2795B9, 0xFF2099C0, 0xFF2097BD, 0xFF2097BD, 0xFF1A95BC, 0xFF8BC9DD, 0xFFFEFEFF, 0xFF7CC2D8, 0xFF1D96BC, 0xFF2097BD, 0xFF2097BE, 0xFB219BC1, 0xDE1780A1,
+ 0x00000000, 0x00000000, 0x00000000, 0xAA999999, 0xFFDCDCDC, 0xFFDCDCDC, 0xFFDCDCDC, 0xFFDCDCDC, 0xFFDCDCDC, 0xFFDCDCDC, 0xFFDCDCDC, 0xFFDCDCDC, 0xFFDCDCDC, 0xFFDCDCDC, 0xFFDCDCDC, 0xFFDCDCDC, 0xFFDCDCDC, 0xFFDCDCDC, 0xFFCBD2D3, 0xFF5293A8, 0xFF1D8FB3, 0xFF1C8EB1, 0xFF1C8EB1, 0xFF198CB0, 0xFF77BAD0, 0xFFFCFDFE, 0xFF64B1CA, 0xFF178BAF, 0xFF1C8EB1, 0xFF1C8EB2, 0xF21984A6, 0x5E0F6884,
+ 0x00000000, 0x00000000, 0x00000000, 0xAA999999, 0xFFDBDBDB, 0xFFDBDBDB, 0xFFDBDBDB, 0xFFDBDBDB, 0xFFDBDBDB, 0xFFDBDBDB, 0xFFDBDBDB, 0xFFDBDBDB, 0xFFDBDBDB, 0xFFDBDBDB, 0xFFDBDBDB, 0xFFDBDBDB, 0xFFDBDBDB, 0xFFDBDBDB, 0xFF85ABB8, 0xFF2789AA, 0xFF1B87A9, 0xFF1A85A7, 0xFF1A85A7, 0xFF1884A6, 0xFF69AEC5, 0xFFF9FCFD, 0xFF51A2BC, 0xFF1683A5, 0xFF1A85A7, 0xFF1A85A7, 0xFB1B88AB, 0xC0147695,
+ 0x00000000, 0x00000000, 0x00000000, 0xAA999999, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFAFC0C6, 0xFF5F95A6, 0xFF177998, 0xFF187C9D, 0xFF187C9C, 0xFF177B9C, 0xFF2C87A4, 0xFF75B0C3, 0xFF1E7F9F, 0xFF177B9C, 0xFF187C9C, 0xFF177D9D, 0xD7147190, 0x7C0F6682,
+ 0x00000000, 0x00000000, 0x00000000, 0xAA999999, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFFDADADA, 0xFF94B1B9, 0xFF167695, 0xFF167695, 0xFF157593, 0xFF137492, 0xFF4E97AE, 0xFFA3CAD6, 0xFF4390A9, 0xFF147492, 0xFF157593, 0xFF177796, 0xBD126D8B, 0x190B5B75,
+ 0x00000000, 0x00000000, 0x00000000, 0x91999999, 0xFFD2D2D2, 0xFFD9D9D9, 0xFFD9D9D9, 0xFFD9D9D9, 0xFFD9D9D9, 0xFFD9D9D9, 0xFFD9D9D9, 0xFFD9D9D9, 0xFFD9D9D9, 0xFFD9D9D9, 0xFFD9D9D9, 0xFFD9D9D9, 0xFFD9D9D9, 0xFFD9D9D9, 0xFFD6D7D8, 0xFF7FA4B0, 0xFF4D899B, 0xFF21718B, 0xFF136D8A, 0xFF0C6986, 0xFF7FB0BF, 0xFFE5EFF2, 0xFF78ABBB, 0xFF116C89, 0xFC136C88, 0xCA106682, 0x990F6580, 0x240B5E78,
+ 0x00000000, 0x00000000, 0x00000000, 0x45999999, 0xFFBCBCBC, 0xFFD8D8D8, 0xFFD9D9D9, 0xFFD9D9D9, 0xFFD9D9D9, 0xFFD9D9D9, 0xFFD9D9D9, 0xFFD9D9D9, 0xFFD9D9D9, 0xFFD9D9D9, 0xFFD9D9D9, 0xFFD9D9D9, 0xFFD9D9D9, 0xFFD9D9D9, 0xFFD9D9D9, 0xFFD3D6D6, 0xFFBFC9CC, 0xFF3D7E93, 0xFF126681, 0xFF116682, 0xFF22728B, 0xFF44889D, 0xFF1F6F89, 0xF90F6480, 0xFC116681, 0x620D607A, 0x0A0A5A74, 0x020A5B75,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x7B9C9C9C, 0xD7B1B1B1, 0xFAC1C1C1, 0xFFC3C3C3, 0xFFC3C3C3, 0xFFC3C3C3, 0xFFC3C3C3, 0xFFC3C3C3, 0xFFC3C3C3, 0xFFC3C3C3, 0xFFC3C3C3, 0xFFC3C3C3, 0xFFC3C3C3, 0xFFC3C3C3, 0xFFC3C3C3, 0xFFC3C3C3, 0xFFBDBFC0, 0xFF819BA4, 0xFF96A8AD, 0xFF467C8E, 0xF220687F, 0xCB276A7F, 0xE90E607A, 0x520B5D77, 0x5F0B5D77, 0x2B0B5D77, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x07999999, 0x2D999999, 0x50999999, 0x55999999, 0x55999999, 0x55999999, 0x55999999, 0x55999999, 0x55999999, 0x55999999, 0x55999999, 0x55999999, 0x55999999, 0x55999999, 0x55999999, 0x55999999, 0x55999999, 0x55999999, 0x55999999, 0x72407283, 0x6626687D, 0x22467584, 0x800B5C76, 0x1A0A5B75, 0x00000000, 0x00000000, 0x00000000, 0x00000000
+}
+};
+
+#define UI_TOOLBAR_BUTTONS ARRAY_LENGTH(toolbar_bitmap_bmp)
diff --git a/src/frontend/mame/ui/ui.cpp b/src/frontend/mame/ui/ui.cpp
new file mode 100644
index 00000000000..173eff6ad9c
--- /dev/null
+++ b/src/frontend/mame/ui/ui.cpp
@@ -0,0 +1,2738 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/*********************************************************************
+
+ ui.cpp
+
+ Functions used to handle MAME's user interface.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "mame.h"
+#include "emuopts.h"
+#include "mameopts.h"
+#include "video/vector.h"
+#include "machine/laserdsc.h"
+#include "render.h"
+#include "luaengine.h"
+#include "cheat.h"
+#include "rendfont.h"
+#include "uiinput.h"
+#include "ui/ui.h"
+#include "ui/menu.h"
+#include "ui/mainmenu.h"
+#include "ui/filemngr.h"
+#include "ui/sliders.h"
+#include "ui/viewgfx.h"
+#include "imagedev/cassette.h"
+#include "image.h"
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+enum
+{
+ LOADSAVE_NONE,
+ LOADSAVE_LOAD,
+ LOADSAVE_SAVE
+};
+
+#define MAX_SAVED_STATE_JOYSTICK 4
+
+
+/***************************************************************************
+ LOCAL VARIABLES
+***************************************************************************/
+
+// list of natural keyboard keys that are not associated with UI_EVENT_CHARs
+static const input_item_id non_char_keys[] =
+{
+ ITEM_ID_ESC,
+ ITEM_ID_F1,
+ ITEM_ID_F2,
+ ITEM_ID_F3,
+ ITEM_ID_F4,
+ ITEM_ID_F5,
+ ITEM_ID_F6,
+ ITEM_ID_F7,
+ ITEM_ID_F8,
+ ITEM_ID_F9,
+ ITEM_ID_F10,
+ ITEM_ID_F11,
+ ITEM_ID_F12,
+ ITEM_ID_NUMLOCK,
+ ITEM_ID_0_PAD,
+ ITEM_ID_1_PAD,
+ ITEM_ID_2_PAD,
+ ITEM_ID_3_PAD,
+ ITEM_ID_4_PAD,
+ ITEM_ID_5_PAD,
+ ITEM_ID_6_PAD,
+ ITEM_ID_7_PAD,
+ ITEM_ID_8_PAD,
+ ITEM_ID_9_PAD,
+ ITEM_ID_DEL_PAD,
+ ITEM_ID_PLUS_PAD,
+ ITEM_ID_MINUS_PAD,
+ ITEM_ID_INSERT,
+ ITEM_ID_DEL,
+ ITEM_ID_HOME,
+ ITEM_ID_END,
+ ITEM_ID_PGUP,
+ ITEM_ID_PGDN,
+ ITEM_ID_UP,
+ ITEM_ID_DOWN,
+ ITEM_ID_LEFT,
+ ITEM_ID_RIGHT,
+ ITEM_ID_PAUSE,
+ ITEM_ID_CANCEL
+};
+
+static const char *s_color_list[] = {
+ OPTION_UI_BORDER_COLOR,
+ OPTION_UI_BACKGROUND_COLOR,
+ OPTION_UI_GFXVIEWER_BG_COLOR,
+ OPTION_UI_UNAVAILABLE_COLOR,
+ OPTION_UI_TEXT_COLOR,
+ OPTION_UI_TEXT_BG_COLOR,
+ OPTION_UI_SUBITEM_COLOR,
+ OPTION_UI_CLONE_COLOR,
+ OPTION_UI_SELECTED_COLOR,
+ OPTION_UI_SELECTED_BG_COLOR,
+ OPTION_UI_MOUSEOVER_COLOR,
+ OPTION_UI_MOUSEOVER_BG_COLOR,
+ OPTION_UI_MOUSEDOWN_COLOR,
+ OPTION_UI_MOUSEDOWN_BG_COLOR,
+ OPTION_UI_DIPSW_COLOR,
+ OPTION_UI_SLIDER_COLOR
+};
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+// messagebox buffer
+std::string mame_ui_manager::messagebox_text;
+std::string mame_ui_manager::messagebox_poptext;
+rgb_t mame_ui_manager::messagebox_backcolor;
+
+// slider info
+std::vector<ui_menu_item> mame_ui_manager::slider_list;
+slider_state *mame_ui_manager::slider_current;
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+// slider controls
+static slider_state *slider_alloc(running_machine &machine, const char *title, INT32 minval, INT32 defval, INT32 maxval, INT32 incval, slider_update update, void *arg);
+static INT32 slider_volume(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_mixervol(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_adjuster(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_overclock(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_refresh(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_brightness(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_contrast(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_gamma(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_xscale(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_yscale(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_xoffset(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_yoffset(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_overxscale(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_overyscale(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_overxoffset(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_overyoffset(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_flicker(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_beam_width_min(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_beam_width_max(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_beam_intensity_weight(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static std::string slider_get_screen_desc(screen_device &screen);
+#ifdef MAME_DEBUG
+static INT32 slider_crossscale(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_crossoffset(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+#endif
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+//-------------------------------------------------
+// load ui options
+//-------------------------------------------------
+
+static void load_ui_options(running_machine &machine)
+{
+ // parse the file
+ std::string error;
+ // attempt to open the output file
+ emu_file file(machine.options().ini_path(), OPEN_FLAG_READ);
+ if (file.open("ui.ini") == osd_file::error::NONE)
+ {
+ bool result = mame_machine_manager::instance()->ui().options().parse_ini_file((util::core_file&)file, OPTION_PRIORITY_MAME_INI, OPTION_PRIORITY_DRIVER_INI, error);
+ if (!result)
+ osd_printf_error("**Error loading ui.ini**");
+ }
+}
+
+//-------------------------------------------------
+// is_breakable_char - is a given unicode
+// character a possible line break?
+//-------------------------------------------------
+
+static inline int is_breakable_char(unicode_char ch)
+{
+ // regular spaces and hyphens are breakable
+ if (ch == ' ' || ch == '-')
+ return TRUE;
+
+ // In the following character sets, any character is breakable:
+ // Hiragana (3040-309F)
+ // Katakana (30A0-30FF)
+ // Bopomofo (3100-312F)
+ // Hangul Compatibility Jamo (3130-318F)
+ // Kanbun (3190-319F)
+ // Bopomofo Extended (31A0-31BF)
+ // CJK Strokes (31C0-31EF)
+ // Katakana Phonetic Extensions (31F0-31FF)
+ // Enclosed CJK Letters and Months (3200-32FF)
+ // CJK Compatibility (3300-33FF)
+ // CJK Unified Ideographs Extension A (3400-4DBF)
+ // Yijing Hexagram Symbols (4DC0-4DFF)
+ // CJK Unified Ideographs (4E00-9FFF)
+ if (ch >= 0x3040 && ch <= 0x9fff)
+ return TRUE;
+
+ // Hangul Syllables (AC00-D7AF) are breakable
+ if (ch >= 0xac00 && ch <= 0xd7af)
+ return TRUE;
+
+ // CJK Compatibility Ideographs (F900-FAFF) are breakable
+ if (ch >= 0xf900 && ch <= 0xfaff)
+ return TRUE;
+
+ return FALSE;
+}
+
+
+
+/***************************************************************************
+ CORE IMPLEMENTATION
+***************************************************************************/
+
+static const UINT32 mouse_bitmap[32*32] =
+{
+ 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x09a46f30,0x81ac7c43,0x24af8049,0x00ad7d45,0x00a8753a,0x00a46f30,0x009f6725,0x009b611c,0x00985b14,0x0095560d,0x00935308,0x00915004,0x00904e02,0x008f4e01,0x008f4d00,0x008f4d00,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x00a16a29,0xa2aa783d,0xffbb864a,0xc0b0824c,0x5aaf7f48,0x09ac7b42,0x00a9773c,0x00a67134,0x00a26b2b,0x009e6522,0x009a5e19,0x00965911,0x0094550b,0x00925207,0x00915004,0x008f4e01,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x009a5e18,0x39a06827,0xffb97c34,0xffe8993c,0xffc88940,0xedac7c43,0x93ad7c44,0x2dac7c43,0x00ab793f,0x00a87438,0x00a46f30,0x00a06827,0x009c611d,0x00985c15,0x0095570e,0x00935309,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x00935308,0x00965810,0xcc9a5e19,0xffe78a21,0xfffb9929,0xfff49931,0xffd88e39,0xffb9813f,0xc9ac7c43,0x66ad7c44,0x0cac7a41,0x00a9773c,0x00a67134,0x00a26b2b,0x009e6522,0x009a5e19,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x008f4e01,0x00904e02,0x60925106,0xffba670a,0xfff88b11,0xfff98f19,0xfff99422,0xfff9982b,0xffe89434,0xffc9883c,0xf3ac7a41,0x9cad7c44,0x39ac7c43,0x00ab7a40,0x00a87539,0x00a56f31,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x008e4d00,0x008e4d00,0x098e4d00,0xea8f4d00,0xffee7f03,0xfff68407,0xfff6870d,0xfff78b15,0xfff78f1d,0xfff79426,0xfff49730,0xffd98d38,0xffbc823f,0xd2ac7c43,0x6fad7c44,0x12ac7b42,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x008e4d00,0x008e4d00,0x008e4c00,0x8a8e4c00,0xffc46800,0xfff37e00,0xfff37f02,0xfff38106,0xfff3830a,0xfff48711,0xfff48b19,0xfff58f21,0xfff5942b,0xffe79134,0xffcb863b,0xf9ac7a41,0xa5ac7c43,0x3fac7c43,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x008e4d00,0x008e4d00,0x008e4c00,0x218d4c00,0xfc8e4c00,0xffee7a00,0xfff07c00,0xfff17c00,0xfff17d02,0xfff17e04,0xfff18008,0xfff2830d,0xfff28614,0xfff38a1c,0xfff38f25,0xfff2932e,0xffd98b37,0xffbc813e,0xdbac7c43,0x78ad7c44,0x15ac7b42,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x008e4d00,0x008e4d00,0x008e4d00,0x008e4c00,0xb18d4c00,0xffcf6b00,0xffed7900,0xffed7900,0xffee7900,0xffee7a01,0xffee7a01,0xffee7b03,0xffee7c06,0xffef7e0a,0xffef8110,0xfff08618,0xfff08a20,0xfff18f2a,0xffe78f33,0xffcc863b,0xfcab7a40,0xaeac7c43,0x4bac7c43,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x008f4d00,0x008e4d00,0x008e4d00,0x008e4c00,0x488d4c00,0xffa85800,0xffe97500,0xffea7600,0xffea7600,0xffeb7600,0xffeb7600,0xffeb7600,0xffeb7701,0xffeb7702,0xffeb7804,0xffec7a07,0xffec7d0d,0xffec8013,0xffed851c,0xffee8a25,0xffee8f2e,0xffd98937,0xffbe813d,0xe4ab7a40,0x81ab7a40,0x1ba9763b,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x008f4d00,0x008e4d00,0x008e4d00,0x008e4c00,0x008d4c00,0xdb8d4c00,0xffd86c00,0xffe77300,0xffe77300,0xffe87300,0xffe87300,0xffe87300,0xffe87300,0xffe87300,0xffe87401,0xffe87401,0xffe87503,0xffe97606,0xffe9780a,0xffe97c10,0xffea7f16,0xffeb831d,0xffeb8623,0xffe48426,0xffc67725,0xffa5661f,0xb7985c15,0x54935309,0x038e4d00,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x008f4d00,0x008e4d00,0x008e4d00,0x008e4d00,0x008e4c00,0x6f8d4c00,0xffb25b00,0xffe36f00,0xffe47000,0xffe47000,0xffe57000,0xffe57000,0xffe57000,0xffe57000,0xffe57000,0xffe57000,0xffe57000,0xffe57000,0xffe57101,0xffe57000,0xffe47000,0xffe16e00,0xffde6c00,0xffd86900,0xffd06600,0xffc76200,0xffaa5500,0xff8a4800,0xea743f00,0x5a7a4200,0x00ffffff,0x00ffffff,
+ 0x008f4d00,0x008f4d00,0x008e4d00,0x008e4d00,0x008e4c00,0x0f8d4c00,0xf38d4c00,0xffdc6a00,0xffe16d00,0xffe16d00,0xffe26d00,0xffe26d00,0xffe26d00,0xffe26d00,0xffe26d00,0xffe16d00,0xffe06c00,0xffde6b00,0xffd96900,0xffd16500,0xffc76000,0xffb95900,0xffab5200,0xff9c4b00,0xff894300,0xff6b3600,0xf9512c00,0xa5542d00,0x3c5e3200,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x008f4d00,0x008f4d00,0x008e4d00,0x008e4d00,0x008e4c00,0x008d4c00,0x968d4c00,0xffbc5d00,0xffde6a00,0xffde6a00,0xffde6a00,0xffdf6a00,0xffdf6a00,0xffdf6a00,0xffde6a00,0xffdc6800,0xffd66600,0xffcc6100,0xffbf5b00,0xffaf5300,0xff9d4a00,0xff8a4200,0xff6d3500,0xff502900,0xe7402300,0x7b3f2200,0x15442500,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x008f4d00,0x008f4d00,0x008f4d00,0x008e4d00,0x008e4d00,0x008e4c00,0x2a8d4c00,0xff9b5000,0xffda6600,0xffdb6700,0xffdb6700,0xffdc6700,0xffdc6700,0xffdb6700,0xffd96500,0xffd16200,0xffc25b00,0xffad5100,0xff974700,0xff7f3c00,0xff602f00,0xff472500,0xbd3d2100,0x513d2100,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x008f4d00,0x008f4d00,0x008f4d00,0x008e4d00,0x008e4d00,0x008e4c00,0x008e4c00,0xc08d4c00,0xffc35c00,0xffd76300,0xffd76300,0xffd86300,0xffd86300,0xffd76300,0xffd06000,0xffc05800,0xffa54c00,0xff7f3b00,0xff582c00,0xf03f2200,0x903c2000,0x2a3e2100,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008e4d00,0x008e4d00,0x008e4c00,0x548d4c00,0xffa55200,0xffd35f00,0xffd46000,0xffd46000,0xffd46000,0xffd25e00,0xffc65900,0xffac4e00,0xff833c00,0xe7472600,0x693c2000,0x0c3d2100,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008e4d00,0x008e4d00,0x008e4c00,0x038d4c00,0xe48d4c00,0xffc95a00,0xffd15d00,0xffd15d00,0xffd15d00,0xffcb5a00,0xffb95200,0xff984300,0xff5f2e00,0x723f2200,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008e4d00,0x008e4d00,0x008e4d00,0x008e4c00,0x7b8d4c00,0xffad5200,0xffce5a00,0xffce5a00,0xffcd5900,0xffc35500,0xffaa4a00,0xff853a00,0xf9472600,0x15432400,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008e4d00,0x008e4d00,0x008e4c00,0x188d4c00,0xf98e4c00,0xffc95600,0xffcb5700,0xffc75500,0xffb94f00,0xff9b4200,0xff6c3100,0xab442500,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008e4d00,0x008e4d00,0x008e4d00,0x008e4c00,0xa58d4c00,0xffb35000,0xffc75300,0xffc05000,0xffac4800,0xff8b3a00,0xff542a00,0x45462500,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008e4d00,0x008e4d00,0x008e4c00,0x398d4c00,0xff994d00,0xffc24f00,0xffb74b00,0xff9e4000,0xff763200,0xde472600,0x03492800,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008e4d00,0x008e4d00,0x008e4c00,0x008e4c00,0xcf8d4c00,0xffb24b00,0xffab4500,0xff8d3900,0xff5e2b00,0x7e452500,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008e4d00,0x008e4d00,0x008e4d00,0x008e4c00,0x638d4c00,0xff984800,0xffa03f00,0xff7e3200,0xfc492800,0x1b472600,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008e4d00,0x008e4d00,0x008e4c00,0x098b4b00,0xed824600,0xff903800,0xff692c00,0xb4462600,0x004c2900,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008e4d00,0x008e4d00,0x008e4c00,0x008a4a00,0x8a7e4400,0xff793500,0xff572900,0x51472600,0x00542d00,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008e4d00,0x008d4c00,0x00884900,0x247a4200,0xfc633500,0xe74f2a00,0x034d2900,0x005e3300,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008e4d00,0x008d4c00,0x00884900,0x00794100,0xb4643600,0x87552e00,0x00593000,0x006b3900,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008f4d00,0x008d4c00,0x00884900,0x007c4300,0x486d3b00,0x24643600,0x00693800,0x00774000,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
+ 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff
+};
+
+
+//-------------------------------------------------
+// ctor - set up the user interface
+//-------------------------------------------------
+
+mame_ui_manager::mame_ui_manager(running_machine &machine)
+ : ui_manager(machine)
+{
+}
+
+void mame_ui_manager::init()
+{
+ load_ui_options(machine());
+ // initialize the other UI bits
+ ui_menu::init(machine());
+ ui_gfx_init(machine());
+
+ // reset instance variables
+ m_font = nullptr;
+ m_handler_callback = nullptr;
+ m_handler_param = 0;
+ m_single_step = false;
+ m_showfps = false;
+ m_showfps_end = 0;
+ m_show_profiler = false;
+ m_popup_text_end = 0;
+ m_mouse_arrow_texture = nullptr;
+ m_load_save_hold = false;
+
+ get_font_rows(&machine());
+ decode_ui_color(0, &machine());
+
+ // more initialization
+ set_handler(handler_messagebox, 0);
+ m_non_char_keys_down = std::make_unique<UINT8[]>((ARRAY_LENGTH(non_char_keys) + 7) / 8);
+ m_mouse_show = machine().system().flags & MACHINE_CLICKABLE_ARTWORK ? true : false;
+
+ // request a callback upon exiting
+ machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(mame_ui_manager::exit), this));
+
+ // retrieve options
+ m_use_natural_keyboard = machine().options().natural_keyboard();
+ bitmap_argb32 *ui_mouse_bitmap = auto_alloc(machine(), bitmap_argb32(32, 32));
+ UINT32 *dst = &ui_mouse_bitmap->pix32(0);
+ memcpy(dst,mouse_bitmap,32*32*sizeof(UINT32));
+ m_mouse_arrow_texture = machine().render().texture_alloc();
+ m_mouse_arrow_texture->set_bitmap(*ui_mouse_bitmap, ui_mouse_bitmap->cliprect(), TEXFORMAT_ARGB32);
+}
+
+
+//-------------------------------------------------
+// exit - clean up ourselves on exit
+//-------------------------------------------------
+
+void mame_ui_manager::exit()
+{
+ // free the mouse texture
+ machine().render().texture_free(m_mouse_arrow_texture);
+ m_mouse_arrow_texture = nullptr;
+
+ // free the font
+ if (m_font != nullptr)
+ {
+ machine().render().font_free(m_font);
+ m_font = nullptr;
+ }
+}
+
+
+//-------------------------------------------------
+// initialize - initialize ui lists
+//-------------------------------------------------
+
+void mame_ui_manager::initialize(running_machine &machine)
+{
+ // initialize the on-screen display system
+ slider_list = slider_init(machine);
+ if (slider_list.size() > 0)
+ {
+ slider_current = reinterpret_cast<slider_state *>(slider_list[0].ref);
+ }
+ else
+ {
+ slider_current = nullptr;
+ }
+}
+
+
+//-------------------------------------------------
+// set_handler - set a callback/parameter
+// pair for the current UI handler
+//-------------------------------------------------
+
+UINT32 mame_ui_manager::set_handler(ui_callback callback, UINT32 param)
+{
+ m_handler_callback = callback;
+ m_handler_param = param;
+ return param;
+}
+
+
+//-------------------------------------------------
+// display_startup_screens - display the
+// various startup screens
+//-------------------------------------------------
+
+void mame_ui_manager::display_startup_screens(bool first_time)
+{
+ const int maxstate = 3;
+ int str = machine().options().seconds_to_run();
+ bool show_gameinfo = !machine().options().skip_gameinfo();
+ bool show_warnings = true, show_mandatory_fileman = true;
+ int state;
+
+ // disable everything if we are using -str for 300 or fewer seconds, or if we're the empty driver,
+ // or if we are debugging
+ if (!first_time || (str > 0 && str < 60*5) || &machine().system() == &GAME_NAME(___empty) || (machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ show_gameinfo = show_warnings = show_mandatory_fileman = FALSE;
+
+ #if defined(EMSCRIPTEN)
+ // also disable for the JavaScript port since the startup screens do not run asynchronously
+ show_gameinfo = show_warnings = FALSE;
+ #endif
+
+ // loop over states
+ set_handler(handler_ingame, 0);
+ for (state = 0; state < maxstate && !machine().scheduled_event_pending() && !ui_menu::stack_has_special_main_menu(); state++)
+ {
+ // default to standard colors
+ messagebox_backcolor = UI_BACKGROUND_COLOR;
+
+ // pick the next state
+ switch (state)
+ {
+ case 0:
+ if (show_warnings && warnings_string(messagebox_text).length() > 0)
+ {
+ set_handler(handler_messagebox_anykey, 0);
+ if (machine().system().flags & (MACHINE_WRONG_COLORS | MACHINE_IMPERFECT_COLORS | MACHINE_REQUIRES_ARTWORK | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_KEYBOARD | MACHINE_NO_SOUND))
+ messagebox_backcolor = UI_YELLOW_COLOR;
+ if (machine().system().flags & (MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION | MACHINE_MECHANICAL))
+ messagebox_backcolor = UI_RED_COLOR;
+ }
+ break;
+
+ case 1:
+ if (show_gameinfo && game_info_astring(messagebox_text).length() > 0)
+ set_handler(handler_messagebox_anykey, 0);
+ break;
+
+ case 2:
+ if (show_mandatory_fileman && machine().image().mandatory_scan(messagebox_text).length() > 0)
+ {
+ std::string warning;
+ warning.assign(_("This driver requires images to be loaded in the following device(s): ")).append(messagebox_text.substr(0, messagebox_text.length() - 2));
+ ui_menu_file_manager::force_file_manager(machine(), &machine().render().ui_container(), warning.c_str());
+ }
+ break;
+ }
+
+ // clear the input memory
+ machine().input().reset_polling();
+ while (machine().input().poll_switches() != INPUT_CODE_INVALID) { }
+
+ // loop while we have a handler
+ while (m_handler_callback != handler_ingame && !machine().scheduled_event_pending() && !ui_menu::stack_has_special_main_menu())
+ {
+ machine().video().frame_update();
+ }
+
+ // clear the handler and force an update
+ set_handler(handler_ingame, 0);
+ machine().video().frame_update();
+ }
+
+ // if we're the empty driver, force the menus on
+ if (ui_menu::stack_has_special_main_menu())
+ set_handler(ui_menu::ui_handler, 0);
+}
+
+
+//-------------------------------------------------
+// set_startup_text - set the text to display
+// at startup
+//-------------------------------------------------
+
+void mame_ui_manager::set_startup_text(const char *text, bool force)
+{
+ static osd_ticks_t lastupdatetime = 0;
+ osd_ticks_t curtime = osd_ticks();
+
+ // copy in the new text
+ messagebox_text.assign(text);
+ messagebox_backcolor = UI_BACKGROUND_COLOR;
+
+ // don't update more than 4 times/second
+ if (force || (curtime - lastupdatetime) > osd_ticks_per_second() / 4)
+ {
+ lastupdatetime = curtime;
+ machine().video().frame_update();
+ }
+}
+
+
+//-------------------------------------------------
+// update_and_render - update the UI and
+// render it; called by video.c
+//-------------------------------------------------
+
+void mame_ui_manager::update_and_render(render_container *container)
+{
+ // always start clean
+ container->empty();
+
+ // if we're paused, dim the whole screen
+ if (machine().phase() >= MACHINE_PHASE_RESET && (single_step() || machine().paused()))
+ {
+ int alpha = (1.0f - machine().options().pause_brightness()) * 255.0f;
+ if (ui_menu::stack_has_special_main_menu())
+ alpha = 255;
+ if (alpha > 255)
+ alpha = 255;
+ if (alpha >= 0)
+ container->add_rect(0.0f, 0.0f, 1.0f, 1.0f, rgb_t(alpha,0x00,0x00,0x00), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ }
+
+ // render any cheat stuff at the bottom
+ if (machine().phase() >= MACHINE_PHASE_RESET)
+ {
+ mame_machine_manager::instance()->lua()->on_frame_done();
+ mame_machine_manager::instance()->cheat().render_text(*container);
+ }
+
+ // call the current UI handler
+ assert(m_handler_callback != nullptr);
+ m_handler_param = (*m_handler_callback)(machine(), container, m_handler_param);
+
+ // display any popup messages
+ if (osd_ticks() < m_popup_text_end)
+ draw_text_box(container, messagebox_poptext.c_str(), JUSTIFY_CENTER, 0.5f, 0.9f, messagebox_backcolor);
+ else
+ m_popup_text_end = 0;
+
+ // display the internal mouse cursor
+ if (m_mouse_show || (is_menu_active() && machine().options().ui_mouse()))
+ {
+ INT32 mouse_target_x, mouse_target_y;
+ bool mouse_button;
+ render_target *mouse_target = machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button);
+
+ if (mouse_target != nullptr)
+ {
+ float mouse_y=-1,mouse_x=-1;
+ if (mouse_target->map_point_container(mouse_target_x, mouse_target_y, *container, mouse_x, mouse_y))
+ {
+ const float cursor_size = 0.6 * mame_machine_manager::instance()->ui().get_line_height();
+ container->add_quad(mouse_x, mouse_y, mouse_x + cursor_size*container->manager().ui_aspect(container), mouse_y + cursor_size, UI_TEXT_COLOR, m_mouse_arrow_texture, PRIMFLAG_ANTIALIAS(1) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ }
+ }
+ }
+
+ // cancel takes us back to the ingame handler
+ if (m_handler_param == UI_HANDLER_CANCEL)
+ set_handler(handler_ingame, 0);
+}
+
+
+//-------------------------------------------------
+// get_font - return the UI font
+//-------------------------------------------------
+
+render_font *mame_ui_manager::get_font()
+{
+ // allocate the font and messagebox string
+ if (m_font == nullptr)
+ m_font = machine().render().font_alloc(machine().options().ui_font());
+ return m_font;
+}
+
+
+//-------------------------------------------------
+// get_line_height - return the current height
+// of a line
+//-------------------------------------------------
+
+float mame_ui_manager::get_line_height()
+{
+ INT32 raw_font_pixel_height = get_font()->pixel_height();
+ render_target &ui_target = machine().render().ui_target();
+ INT32 target_pixel_height = ui_target.height();
+ float one_to_one_line_height;
+ float scale_factor;
+
+ // compute the font pixel height at the nominal size
+ one_to_one_line_height = (float)raw_font_pixel_height / (float)target_pixel_height;
+
+ // determine the scale factor
+ scale_factor = UI_TARGET_FONT_HEIGHT / one_to_one_line_height;
+
+ // if our font is small-ish, do integral scaling
+ if (raw_font_pixel_height < 24)
+ {
+ // do we want to scale smaller? only do so if we exceed the threshold
+ if (scale_factor <= 1.0f)
+ {
+ if (one_to_one_line_height < UI_MAX_FONT_HEIGHT || raw_font_pixel_height < 12)
+ scale_factor = 1.0f;
+ }
+
+ // otherwise, just ensure an integral scale factor
+ else
+ scale_factor = floor(scale_factor);
+ }
+
+ // otherwise, just make sure we hit an even number of pixels
+ else
+ {
+ INT32 height = scale_factor * one_to_one_line_height * (float)target_pixel_height;
+ scale_factor = (float)height / (one_to_one_line_height * (float)target_pixel_height);
+ }
+
+ return scale_factor * one_to_one_line_height;
+}
+
+
+//-------------------------------------------------
+// get_char_width - return the width of a
+// single character
+//-------------------------------------------------
+
+float mame_ui_manager::get_char_width(unicode_char ch)
+{
+ return get_font()->char_width(get_line_height(), machine().render().ui_aspect(), ch);
+}
+
+
+//-------------------------------------------------
+// get_string_width - return the width of a
+// character string
+//-------------------------------------------------
+
+float mame_ui_manager::get_string_width(const char *s, float text_size)
+{
+ return get_font()->utf8string_width(get_line_height() * text_size, machine().render().ui_aspect(), s);
+}
+
+
+//-------------------------------------------------
+// draw_outlined_box - add primitives to draw
+// an outlined box with the given background
+// color
+//-------------------------------------------------
+
+void mame_ui_manager::draw_outlined_box(render_container *container, float x0, float y0, float x1, float y1, rgb_t backcolor)
+{
+ draw_outlined_box(container, x0, y0, x1, y1, UI_BORDER_COLOR, backcolor);
+}
+
+
+//-------------------------------------------------
+// draw_outlined_box - add primitives to draw
+// an outlined box with the given background
+// color
+//-------------------------------------------------
+
+void mame_ui_manager::draw_outlined_box(render_container *container, float x0, float y0, float x1, float y1, rgb_t fgcolor, rgb_t bgcolor)
+{
+ container->add_rect(x0, y0, x1, y1, bgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ container->add_line(x0, y0, x1, y0, UI_LINE_WIDTH, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ container->add_line(x1, y0, x1, y1, UI_LINE_WIDTH, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ container->add_line(x1, y1, x0, y1, UI_LINE_WIDTH, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ container->add_line(x0, y1, x0, y0, UI_LINE_WIDTH, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+}
+
+
+//-------------------------------------------------
+// draw_text - simple text renderer
+//-------------------------------------------------
+
+void mame_ui_manager::draw_text(render_container *container, const char *buf, float x, float y)
+{
+ draw_text_full(container, buf, x, y, 1.0f - x, JUSTIFY_LEFT, WRAP_WORD, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+}
+
+
+//-------------------------------------------------
+// draw_text_full - full featured text
+// renderer with word wrapping, justification,
+// and full size computation
+//-------------------------------------------------
+
+void mame_ui_manager::draw_text_full(render_container *container, const char *origs, float x, float y, float origwrapwidth, int justify, int wrap, int draw, rgb_t fgcolor, rgb_t bgcolor, float *totalwidth, float *totalheight, float text_size)
+{
+ float lineheight = get_line_height() * text_size;
+ const char *ends = origs + strlen(origs);
+ float wrapwidth = origwrapwidth;
+ const char *s = origs;
+ const char *linestart;
+ float cury = y;
+ float maxwidth = 0;
+ float aspect = machine().render().ui_aspect(container);
+
+ // if we don't want wrapping, guarantee a huge wrapwidth
+ if (wrap == WRAP_NEVER)
+ wrapwidth = 1000000.0f;
+ if (wrapwidth <= 0)
+ return;
+
+ // loop over lines
+ while (*s != 0)
+ {
+ const char *lastbreak = nullptr;
+ int line_justify = justify;
+ unicode_char schar;
+ int scharcount;
+ float lastbreak_width = 0;
+ float curwidth = 0;
+ float curx = x;
+
+ // get the current character
+ scharcount = uchar_from_utf8(&schar, s, ends - s);
+ if (scharcount == -1)
+ break;
+
+ // if the line starts with a tab character, center it regardless
+ if (schar == '\t')
+ {
+ s += scharcount;
+ line_justify = JUSTIFY_CENTER;
+ }
+
+ // remember the starting position of the line
+ linestart = s;
+
+ // loop while we have characters and are less than the wrapwidth
+ while (*s != 0 && curwidth <= wrapwidth)
+ {
+ float chwidth;
+
+ // get the current chcaracter
+ scharcount = uchar_from_utf8(&schar, s, ends - s);
+ if (scharcount == -1)
+ break;
+
+ // if we hit a newline, stop immediately
+ if (schar == '\n')
+ break;
+
+ // get the width of this character
+ chwidth = get_font()->char_width(lineheight, aspect, schar);
+
+ // if we hit a space, remember the location and width *without* the space
+ if (schar == ' ')
+ {
+ lastbreak = s;
+ lastbreak_width = curwidth;
+ }
+
+ // add the width of this character and advance
+ curwidth += chwidth;
+ s += scharcount;
+
+ // if we hit any non-space breakable character, remember the location and width
+ // *with* the breakable character
+ if (schar != ' ' && is_breakable_char(schar) && curwidth <= wrapwidth)
+ {
+ lastbreak = s;
+ lastbreak_width = curwidth;
+ }
+ }
+
+ // if we accumulated too much for the current width, we need to back off
+ if (curwidth > wrapwidth)
+ {
+ // if we're word wrapping, back up to the last break if we can
+ if (wrap == WRAP_WORD)
+ {
+ // if we hit a break, back up to there with the appropriate width
+ if (lastbreak != nullptr)
+ {
+ s = lastbreak;
+ curwidth = lastbreak_width;
+ }
+
+ // if we didn't hit a break, back up one character
+ else if (s > linestart)
+ {
+ // get the previous character
+ s = (const char *)utf8_previous_char(s);
+ scharcount = uchar_from_utf8(&schar, s, ends - s);
+ if (scharcount == -1)
+ break;
+
+ curwidth -= get_font()->char_width(lineheight, aspect, schar);
+ // if back to 0, there is no space to draw even a single char
+ if (curwidth <= 0)
+ break;
+ }
+ }
+
+ // if we're truncating, make sure we have enough space for the ...
+ else if (wrap == WRAP_TRUNCATE)
+ {
+ // add in the width of the ...
+ curwidth += 3.0f * get_font()->char_width(lineheight, aspect, '.');
+
+ // while we are above the wrap width, back up one character
+ while (curwidth > wrapwidth && s > linestart)
+ {
+ // get the previous character
+ s = (const char *)utf8_previous_char(s);
+ scharcount = uchar_from_utf8(&schar, s, ends - s);
+ if (scharcount == -1)
+ break;
+
+ curwidth -= get_font()->char_width(lineheight, aspect, schar);
+ }
+ }
+ }
+
+ // align according to the justfication
+ if (line_justify == JUSTIFY_CENTER)
+ curx += (origwrapwidth - curwidth) * 0.5f;
+ else if (line_justify == JUSTIFY_RIGHT)
+ curx += origwrapwidth - curwidth;
+
+ // track the maximum width of any given line
+ if (curwidth > maxwidth)
+ maxwidth = curwidth;
+
+ // if opaque, add a black box
+ if (draw == DRAW_OPAQUE)
+ container->add_rect(curx, cury, curx + curwidth, cury + lineheight, bgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+
+ // loop from the line start and add the characters
+ while (linestart < s)
+ {
+ // get the current character
+ unicode_char linechar;
+ int linecharcount = uchar_from_utf8(&linechar, linestart, ends - linestart);
+ if (linecharcount == -1)
+ break;
+
+ if (draw != DRAW_NONE)
+ {
+ container->add_char(curx, cury, lineheight, aspect, fgcolor, *get_font(), linechar);
+ curx += get_font()->char_width(lineheight, aspect, linechar);
+ }
+ linestart += linecharcount;
+ }
+
+ // append ellipses if needed
+ if (wrap == WRAP_TRUNCATE && *s != 0 && draw != DRAW_NONE)
+ {
+ container->add_char(curx, cury, lineheight, aspect, fgcolor, *get_font(), '.');
+ curx += get_font()->char_width(lineheight, aspect, '.');
+ container->add_char(curx, cury, lineheight, aspect, fgcolor, *get_font(), '.');
+ curx += get_font()->char_width(lineheight, aspect, '.');
+ container->add_char(curx, cury, lineheight, aspect, fgcolor, *get_font(), '.');
+ curx += get_font()->char_width(lineheight, aspect, '.');
+ }
+
+ // if we're not word-wrapping, we're done
+ if (wrap != WRAP_WORD)
+ break;
+
+ // advance by a row
+ cury += lineheight;
+
+ // skip past any spaces at the beginning of the next line
+ scharcount = uchar_from_utf8(&schar, s, ends - s);
+ if (scharcount == -1)
+ break;
+
+ if (schar == '\n')
+ s += scharcount;
+ else
+ while (*s && isspace(schar))
+ {
+ s += scharcount;
+ scharcount = uchar_from_utf8(&schar, s, ends - s);
+ if (scharcount == -1)
+ break;
+ }
+ }
+
+ // report the width and height of the resulting space
+ if (totalwidth)
+ *totalwidth = maxwidth;
+ if (totalheight)
+ *totalheight = cury - y;
+}
+
+
+//-------------------------------------------------
+// draw_text_box - draw a multiline text
+// message with a box around it
+//-------------------------------------------------
+
+void mame_ui_manager::draw_text_box(render_container *container, const char *text, int justify, float xpos, float ypos, rgb_t backcolor)
+{
+ float line_height = get_line_height();
+ float max_width = 2.0f * ((xpos <= 0.5f) ? xpos : 1.0f - xpos) - 2.0f * UI_BOX_LR_BORDER;
+ float target_width = max_width;
+ float target_height = line_height;
+ float target_x = 0, target_y = 0;
+ float last_target_height = 0;
+
+ // limit this iteration to a finite number of passes
+ for (int pass = 0; pass < 5; pass++)
+ {
+ // determine the target location
+ target_x = xpos - 0.5f * target_width;
+ target_y = ypos - 0.5f * target_height;
+
+ // make sure we stay on-screen
+ if (target_x < UI_BOX_LR_BORDER)
+ target_x = UI_BOX_LR_BORDER;
+ if (target_x + target_width + UI_BOX_LR_BORDER > 1.0f)
+ target_x = 1.0f - UI_BOX_LR_BORDER - target_width;
+ if (target_y < UI_BOX_TB_BORDER)
+ target_y = UI_BOX_TB_BORDER;
+ if (target_y + target_height + UI_BOX_TB_BORDER > 1.0f)
+ target_y = 1.0f - UI_BOX_TB_BORDER - target_height;
+
+ // compute the multi-line target width/height
+ draw_text_full(container, text, target_x, target_y, target_width + 0.00001f,
+ justify, WRAP_WORD, DRAW_NONE, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, &target_width, &target_height);
+ if (target_height > 1.0f - 2.0f * UI_BOX_TB_BORDER)
+ target_height = floorf((1.0f - 2.0f * UI_BOX_TB_BORDER) / line_height) * line_height;
+
+ // if we match our last value, we're done
+ if (target_height == last_target_height)
+ break;
+ last_target_height = target_height;
+ }
+
+ // add a box around that
+ draw_outlined_box(container, target_x - UI_BOX_LR_BORDER,
+ target_y - UI_BOX_TB_BORDER,
+ target_x + target_width + UI_BOX_LR_BORDER,
+ target_y + target_height + UI_BOX_TB_BORDER, backcolor);
+ draw_text_full(container, text, target_x, target_y, target_width + 0.00001f,
+ justify, WRAP_WORD, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+}
+
+
+//-------------------------------------------------
+// draw_message_window - draw a multiline text
+// message with a box around it
+//-------------------------------------------------
+
+void mame_ui_manager::draw_message_window(render_container *container, const char *text)
+{
+ draw_text_box(container, text, JUSTIFY_LEFT, 0.5f, 0.5f, UI_BACKGROUND_COLOR);
+}
+
+
+//-------------------------------------------------
+// show_fps_temp - show the FPS counter for
+// a specific period of time
+//-------------------------------------------------
+
+void mame_ui_manager::show_fps_temp(double seconds)
+{
+ if (!m_showfps)
+ m_showfps_end = osd_ticks() + seconds * osd_ticks_per_second();
+}
+
+
+//-------------------------------------------------
+// set_show_fps - show/hide the FPS counter
+//-------------------------------------------------
+
+void mame_ui_manager::set_show_fps(bool show)
+{
+ m_showfps = show;
+ if (!show)
+ {
+ m_showfps = 0;
+ m_showfps_end = 0;
+ }
+}
+
+
+//-------------------------------------------------
+// show_fps - return the current FPS
+// counter visibility state
+//-------------------------------------------------
+
+bool mame_ui_manager::show_fps() const
+{
+ return m_showfps || (m_showfps_end != 0);
+}
+
+
+//-------------------------------------------------
+// show_fps_counter
+//-------------------------------------------------
+
+bool mame_ui_manager::show_fps_counter()
+{
+ bool result = m_showfps || osd_ticks() < m_showfps_end;
+ if (!result)
+ m_showfps_end = 0;
+ return result;
+}
+
+
+//-------------------------------------------------
+// set_show_profiler - show/hide the profiler
+//-------------------------------------------------
+
+void mame_ui_manager::set_show_profiler(bool show)
+{
+ m_show_profiler = show;
+ g_profiler.enable(show);
+}
+
+
+//-------------------------------------------------
+// show_profiler - return the current
+// profiler visibility state
+//-------------------------------------------------
+
+bool mame_ui_manager::show_profiler() const
+{
+ return m_show_profiler;
+}
+
+
+//-------------------------------------------------
+// show_menu - show the menus
+//-------------------------------------------------
+
+void mame_ui_manager::show_menu()
+{
+ set_handler(ui_menu::ui_handler, 0);
+}
+
+
+//-------------------------------------------------
+// show_mouse - change mouse status
+//-------------------------------------------------
+
+void mame_ui_manager::show_mouse(bool status)
+{
+ m_mouse_show = status;
+}
+
+
+//-------------------------------------------------
+// is_menu_active - return true if the menu
+// UI handler is active
+//-------------------------------------------------
+
+bool mame_ui_manager::is_menu_active(void)
+{
+ return (m_handler_callback == ui_menu::ui_handler);
+}
+
+
+/***************************************************************************
+ TEXT GENERATORS
+***************************************************************************/
+
+//-------------------------------------------------
+// warnings_string - print the warning flags
+// text to the given buffer
+//-------------------------------------------------
+
+std::string &mame_ui_manager::warnings_string(std::string &str)
+{
+#define WARNING_FLAGS ( MACHINE_NOT_WORKING | \
+ MACHINE_UNEMULATED_PROTECTION | \
+ MACHINE_MECHANICAL | \
+ MACHINE_WRONG_COLORS | \
+ MACHINE_IMPERFECT_COLORS | \
+ MACHINE_REQUIRES_ARTWORK | \
+ MACHINE_NO_SOUND | \
+ MACHINE_IMPERFECT_SOUND | \
+ MACHINE_IMPERFECT_GRAPHICS | \
+ MACHINE_IMPERFECT_KEYBOARD | \
+ MACHINE_NO_COCKTAIL| \
+ MACHINE_IS_INCOMPLETE| \
+ MACHINE_NO_SOUND_HW )
+
+ str.clear();
+
+ // if no warnings, nothing to return
+ if (machine().rom_load().warnings() == 0 && machine().rom_load().knownbad() == 0 && !(machine().system().flags & WARNING_FLAGS) && machine().rom_load().software_load_warnings_message().length() == 0)
+ return str;
+
+ // add a warning if any ROMs were loaded with warnings
+ if (machine().rom_load().warnings() > 0)
+ {
+ str.append(_("One or more ROMs/CHDs for this machine are incorrect. The machine may not run correctly.\n"));
+ if (machine().system().flags & WARNING_FLAGS)
+ str.append("\n");
+ }
+
+ if (machine().rom_load().software_load_warnings_message().length()>0) {
+ str.append(machine().rom_load().software_load_warnings_message());
+ if (machine().system().flags & WARNING_FLAGS)
+ str.append("\n");
+ }
+ // if we have at least one warning flag, print the general header
+ if ((machine().system().flags & WARNING_FLAGS) || machine().rom_load().knownbad() > 0)
+ {
+ str.append(_("There are known problems with this machine\n\n"));
+
+ // add a warning if any ROMs are flagged BAD_DUMP/NO_DUMP
+ if (machine().rom_load().knownbad() > 0) {
+ str.append(_("One or more ROMs/CHDs for this machine have not been correctly dumped.\n"));
+ }
+ // add one line per warning flag
+ if (machine().system().flags & MACHINE_IMPERFECT_KEYBOARD)
+ str.append(_("The keyboard emulation may not be 100% accurate.\n"));
+ if (machine().system().flags & MACHINE_IMPERFECT_COLORS)
+ str.append(_("The colors aren't 100% accurate.\n"));
+ if (machine().system().flags & MACHINE_WRONG_COLORS)
+ str.append(_("The colors are completely wrong.\n"));
+ if (machine().system().flags & MACHINE_IMPERFECT_GRAPHICS)
+ str.append(_("The video emulation isn't 100% accurate.\n"));
+ if (machine().system().flags & MACHINE_IMPERFECT_SOUND)
+ str.append(_("The sound emulation isn't 100% accurate.\n"));
+ if (machine().system().flags & MACHINE_NO_SOUND) {
+ str.append(_("The machine lacks sound.\n"));
+ }
+ if (machine().system().flags & MACHINE_NO_COCKTAIL)
+ str.append(_("Screen flipping in cocktail mode is not supported.\n"));
+
+ // check if external artwork is present before displaying this warning?
+ if (machine().system().flags & MACHINE_REQUIRES_ARTWORK) {
+ str.append(_("The machine requires external artwork files\n"));
+ }
+
+ if (machine().system().flags & MACHINE_IS_INCOMPLETE )
+ {
+ str.append(_("This machine was never completed. It may exhibit strange behavior or missing elements that are not bugs in the emulation.\n"));
+ }
+
+ if (machine().system().flags & MACHINE_NO_SOUND_HW )
+ {
+ str.append(_("This machine has no sound hardware, MAME will produce no sounds, this is expected behaviour.\n"));
+ }
+
+ // if there's a NOT WORKING, UNEMULATED PROTECTION or GAME MECHANICAL warning, make it stronger
+ if (machine().system().flags & (MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION | MACHINE_MECHANICAL))
+ {
+ // add the strings for these warnings
+ if (machine().system().flags & MACHINE_UNEMULATED_PROTECTION) {
+ str.append(_("The machine has protection which isn't fully emulated.\n"));
+ }
+ if (machine().system().flags & MACHINE_NOT_WORKING) {
+ str.append(_("\nTHIS MACHINE DOESN'T WORK. The emulation for this machine is not yet complete. "
+ "There is nothing you can do to fix this problem except wait for the developers to improve the emulation.\n"));
+ }
+ if (machine().system().flags & MACHINE_MECHANICAL) {
+ str.append(_("\nCertain elements of this machine cannot be emulated as it requires actual physical interaction or consists of mechanical devices. "
+ "It is not possible to fully play this machine.\n"));
+ }
+
+ // find the parent of this driver
+ driver_enumerator drivlist(machine().options());
+ int maindrv = drivlist.find(machine().system());
+ int clone_of = drivlist.non_bios_clone(maindrv);
+ if (clone_of != -1)
+ maindrv = clone_of;
+
+ // scan the driver list for any working clones and add them
+ bool foundworking = false;
+ while (drivlist.next())
+ if (drivlist.current() == maindrv || drivlist.clone() == maindrv)
+ if ((drivlist.driver().flags & (MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION | MACHINE_MECHANICAL)) == 0)
+ {
+ // this one works, add a header and display the name of the clone
+ if (!foundworking) {
+ str.append(_("\n\nThere are working clones of this machine: "));
+ }
+ else
+ str.append(", ");
+ str.append(drivlist.driver().name);
+ foundworking = true;
+ }
+
+ if (foundworking)
+ str.append("\n");
+ }
+ }
+
+ // add the 'press OK' string
+ str.append(_("\n\nPress any key to continue"));
+ return str;
+}
+
+
+//-------------------------------------------------
+// game_info_std::string - populate an allocated
+// string with the game info text
+//-------------------------------------------------
+
+std::string &mame_ui_manager::game_info_astring(std::string &str)
+{
+ std::ostringstream buf;
+
+ // print description, manufacturer, and CPU:
+ util::stream_format(buf, _("%1$s\n%2$s %3$s\nDriver: %4$s\n\nCPU:\n"),
+ machine().system().description,
+ machine().system().year,
+ machine().system().manufacturer,
+ core_filename_extract_base(machine().system().source_file));
+
+ // loop over all CPUs
+ execute_interface_iterator execiter(machine().root_device());
+ std::unordered_set<std::string> exectags;
+ for (device_execute_interface &exec : execiter)
+ {
+ if (!exectags.insert(exec.device().tag()).second)
+ continue;
+ // get cpu specific clock that takes internal multiplier/dividers into account
+ int clock = exec.device().clock();
+
+ // count how many identical CPUs we have
+ int count = 1;
+ const char *name = exec.device().name();
+ for (device_execute_interface &scan : execiter)
+ {
+ if (exec.device().type() == scan.device().type() && strcmp(name, scan.device().name()) == 0 && exec.device().clock() == scan.device().clock())
+ if (exectags.insert(scan.device().tag()).second)
+ count++;
+ }
+
+ // if more than one, prepend a #x in front of the CPU name
+ // display clock in kHz or MHz
+ util::stream_format(buf,
+ (count > 1) ? "%1$d" UTF8_MULTIPLY "%2$s %3$d.%4$0*5$d%6$s\n" : "%2$s %3$d.%4$0*5$d%6$s\n",
+ count,
+ name,
+ (clock >= 1000000) ? (clock / 1000000) : (clock / 1000),
+ (clock >= 1000000) ? (clock % 1000000) : (clock % 1000),
+ (clock >= 1000000) ? 6 : 3,
+ (clock >= 1000000) ? _("MHz") : _("kHz"));
+ }
+
+ // loop over all sound chips
+ sound_interface_iterator snditer(machine().root_device());
+ std::unordered_set<std::string> soundtags;
+ bool found_sound = false;
+ for (device_sound_interface &sound : snditer)
+ {
+ if (!soundtags.insert(sound.device().tag()).second)
+ continue;
+
+ // append the Sound: string
+ if (!found_sound)
+ buf << _("\nSound:\n");
+ found_sound = true;
+
+ // count how many identical sound chips we have
+ int count = 1;
+ for (device_sound_interface &scan : snditer)
+ {
+ if (sound.device().type() == scan.device().type() && sound.device().clock() == scan.device().clock())
+ if (soundtags.insert(scan.device().tag()).second)
+ count++;
+ }
+
+ // if more than one, prepend a #x in front of the CPU name
+ // display clock in kHz or MHz
+ int clock = sound.device().clock();
+ util::stream_format(buf,
+ (count > 1)
+ ? ((clock != 0) ? "%1$d" UTF8_MULTIPLY "%2$s %3$d.%4$0*5$d%6$s\n" : "%1$d" UTF8_MULTIPLY "%2$s\n")
+ : ((clock != 0) ? "%2$s %3$d.%4$0*5$d%6$s\n" : "%2$s\n"),
+ count,
+ sound.device().name(),
+ (clock >= 1000000) ? (clock / 1000000) : (clock / 1000),
+ (clock >= 1000000) ? (clock % 1000000) : (clock % 1000),
+ (clock >= 1000000) ? 6 : 3,
+ (clock >= 1000000) ? _("MHz") : _("kHz"));
+ }
+
+ // display screen information
+ buf << _("\nVideo:\n");
+ screen_device_iterator scriter(machine().root_device());
+ int scrcount = scriter.count();
+ if (scrcount == 0)
+ buf << _("None\n");
+ else
+ {
+ for (screen_device &screen : scriter)
+ {
+ std::string detail;
+ if (screen.screen_type() == SCREEN_TYPE_VECTOR)
+ detail = _("Vector");
+ else
+ {
+ const rectangle &visarea = screen.visible_area();
+ detail = string_format("%d " UTF8_MULTIPLY " %d (%s) %f" UTF8_NBSP "Hz",
+ visarea.width(), visarea.height(),
+ (machine().system().flags & ORIENTATION_SWAP_XY) ? "V" : "H",
+ ATTOSECONDS_TO_HZ(screen.frame_period().attoseconds()));
+ }
+
+ util::stream_format(buf,
+ (scrcount > 1) ? _("%1$s: %2$s\n") : _("%2$s\n"),
+ slider_get_screen_desc(screen), detail);
+ }
+ }
+
+ return str = buf.str();
+}
+
+
+
+/***************************************************************************
+ UI HANDLERS
+***************************************************************************/
+
+//-------------------------------------------------
+// handler_messagebox - displays the current
+// messagebox_text string but handles no input
+//-------------------------------------------------
+
+UINT32 mame_ui_manager::handler_messagebox(running_machine &machine, render_container *container, UINT32 state)
+{
+ mame_machine_manager::instance()->ui().draw_text_box(container, messagebox_text.c_str(), JUSTIFY_LEFT, 0.5f, 0.5f, messagebox_backcolor);
+ return 0;
+}
+
+
+//-------------------------------------------------
+// handler_messagebox_anykey - displays the
+// current messagebox_text string and waits for
+// any keypress
+//-------------------------------------------------
+
+UINT32 mame_ui_manager::handler_messagebox_anykey(running_machine &machine, render_container *container, UINT32 state)
+{
+ // draw a standard message window
+ mame_machine_manager::instance()->ui().draw_text_box(container, messagebox_text.c_str(), JUSTIFY_LEFT, 0.5f, 0.5f, messagebox_backcolor);
+
+ // if the user cancels, exit out completely
+ if (machine.ui_input().pressed(IPT_UI_CANCEL))
+ {
+ machine.schedule_exit();
+ state = UI_HANDLER_CANCEL;
+ }
+
+ // if any key is pressed, just exit
+ else if (machine.input().poll_switches() != INPUT_CODE_INVALID)
+ state = UI_HANDLER_CANCEL;
+
+ return state;
+}
+
+
+//-------------------------------------------------
+// process_natural_keyboard - processes any
+// natural keyboard input
+//-------------------------------------------------
+
+void mame_ui_manager::process_natural_keyboard()
+{
+ ui_event event;
+ int i, pressed;
+ input_item_id itemid;
+ input_code code;
+ UINT8 *key_down_ptr;
+ UINT8 key_down_mask;
+
+ // loop while we have interesting events
+ while (machine().ui_input().pop_event(&event))
+ {
+ // if this was a UI_EVENT_CHAR event, post it
+ if (event.event_type == UI_EVENT_CHAR)
+ machine().ioport().natkeyboard().post(event.ch);
+ }
+
+ // process natural keyboard keys that don't get UI_EVENT_CHARs
+ for (i = 0; i < ARRAY_LENGTH(non_char_keys); i++)
+ {
+ // identify this keycode
+ itemid = non_char_keys[i];
+ code = machine().input().code_from_itemid(itemid);
+
+ // ...and determine if it is pressed
+ pressed = machine().input().code_pressed(code);
+
+ // figure out whey we are in the key_down map
+ key_down_ptr = &m_non_char_keys_down[i / 8];
+ key_down_mask = 1 << (i % 8);
+
+ if (pressed && !(*key_down_ptr & key_down_mask))
+ {
+ // this key is now down
+ *key_down_ptr |= key_down_mask;
+
+ // post the key
+ machine().ioport().natkeyboard().post(UCHAR_MAMEKEY_BEGIN + code.item_id());
+ }
+ else if (!pressed && (*key_down_ptr & key_down_mask))
+ {
+ // this key is now up
+ *key_down_ptr &= ~key_down_mask;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// increase_frameskip
+//-------------------------------------------------
+
+void mame_ui_manager::increase_frameskip()
+{
+ // get the current value and increment it
+ int newframeskip = machine().video().frameskip() + 1;
+ if (newframeskip > MAX_FRAMESKIP)
+ newframeskip = -1;
+ machine().video().set_frameskip(newframeskip);
+
+ // display the FPS counter for 2 seconds
+ mame_machine_manager::instance()->ui().show_fps_temp(2.0);
+}
+
+
+//-------------------------------------------------
+// decrease_frameskip
+//-------------------------------------------------
+
+void mame_ui_manager::decrease_frameskip()
+{
+ // get the current value and decrement it
+ int newframeskip = machine().video().frameskip() - 1;
+ if (newframeskip < -1)
+ newframeskip = MAX_FRAMESKIP;
+ machine().video().set_frameskip(newframeskip);
+
+ // display the FPS counter for 2 seconds
+ mame_machine_manager::instance()->ui().show_fps_temp(2.0);
+}
+
+
+//-------------------------------------------------
+// can_paste
+//-------------------------------------------------
+
+bool mame_ui_manager::can_paste()
+{
+ // retrieve the clipboard text
+ char *text = osd_get_clipboard_text();
+
+ // free the string if allocated
+ if (text != nullptr)
+ osd_free(text);
+
+ // did we have text?
+ return text != nullptr;
+}
+
+
+//-------------------------------------------------
+// paste - does a paste from the keyboard
+//-------------------------------------------------
+
+void mame_ui_manager::paste()
+{
+ // retrieve the clipboard text
+ char *text = osd_get_clipboard_text();
+
+ // was a result returned?
+ if (text != nullptr)
+ {
+ // post the text
+ machine().ioport().natkeyboard().post_utf8(text);
+
+ // free the string
+ osd_free(text);
+ }
+}
+
+
+//-------------------------------------------------
+// image_handler_ingame - execute display
+// callback function for each image device
+//-------------------------------------------------
+
+void mame_ui_manager::image_handler_ingame()
+{
+ // run display routine for devices
+ if (machine().phase() == MACHINE_PHASE_RUNNING)
+ for (device_image_interface &image : image_interface_iterator(machine().root_device()))
+ image.call_display();
+}
+
+
+#define ANIMATION_FPS 1
+#define ANIMATION_FRAMES 4
+
+void mame_ui_manager::image_display(const device_type &type, device_image_interface *image)
+{
+ if (type == CASSETTE)
+ {
+ cassette_image_device *cass = dynamic_cast<cassette_image_device *>(image);
+ if (cass != nullptr)
+ {
+ char buf[65];
+ float x, y;
+ int n;
+ double position, length;
+ cassette_state uistate;
+ static const UINT8 shapes[8] = { 0x2d, 0x5c, 0x7c, 0x2f, 0x2d, 0x20, 0x20, 0x20 };
+
+ /* figure out where we are in the cassette */
+ position = cass->get_position();
+ length = cass->get_length();
+ uistate = (cassette_state)(cass->get_state() & CASSETTE_MASK_UISTATE);
+
+ /* choose a location on the screen */
+ x = 0.2f;
+ y = 0.5f;
+
+ y += cassette_device_iterator(machine().root_device()).indexof(*cass);
+
+ y *= get_line_height() + 2.0f * UI_BOX_TB_BORDER;
+ /* choose which frame of the animation we are at */
+ n = ((int)position / ANIMATION_FPS) % ANIMATION_FRAMES;
+ /* Since you can have anything in a BDF file, we will use crude ascii characters instead */
+ snprintf(buf, ARRAY_LENGTH(buf), "%c%c %c %02d:%02d (%04d) [%02d:%02d (%04d)]",
+ shapes[n], /* cassette icon left */
+ shapes[n | 4], /* cassette icon right */
+ (uistate == CASSETTE_PLAY) ? 0x50 : 0x52, /* play (P) or record (R) */
+ ((int)position / 60),
+ ((int)position % 60),
+ (int)position,
+ ((int)length / 60),
+ ((int)length % 60),
+ (int)length);
+
+ // draw the cassette
+ draw_text_box(&machine().render().ui_container(), buf, JUSTIFY_LEFT, x, y, UI_BACKGROUND_COLOR);
+ }
+ }
+}
+
+//-------------------------------------------------
+// handler_ingame - in-game handler takes care
+// of the standard keypresses
+//-------------------------------------------------
+
+UINT32 mame_ui_manager::handler_ingame(running_machine &machine, render_container *container, UINT32 state)
+{
+ bool is_paused = machine.paused();
+
+ // first draw the FPS counter
+ if (mame_machine_manager::instance()->ui().show_fps_counter())
+ {
+ mame_machine_manager::instance()->ui().draw_text_full(container, machine.video().speed_text().c_str(), 0.0f, 0.0f, 1.0f,
+ JUSTIFY_RIGHT, WRAP_WORD, DRAW_OPAQUE, ARGB_WHITE, ARGB_BLACK, nullptr, nullptr);
+ }
+
+ // Show the duration of current part (intro or gameplay or extra)
+ if (mame_machine_manager::instance()->ui().show_timecode_counter()) {
+ std::string tempstring;
+ mame_machine_manager::instance()->ui().draw_text_full(container, machine.video().timecode_text(tempstring).c_str(), 0.0f, 0.0f, 1.0f,
+ JUSTIFY_RIGHT, WRAP_WORD, DRAW_OPAQUE, rgb_t(0xf0,0xf0,0x10,0x10), ARGB_BLACK, NULL, NULL);
+ }
+ // Show the total time elapsed for the video preview (all parts intro, gameplay, extras)
+ if (mame_machine_manager::instance()->ui().show_timecode_total()) {
+ std::string tempstring;
+ mame_machine_manager::instance()->ui().draw_text_full(container, machine.video().timecode_total_text(tempstring).c_str(), 0.0f, 0.0f, 1.0f,
+ JUSTIFY_LEFT, WRAP_WORD, DRAW_OPAQUE, rgb_t(0xf0,0x10,0xf0,0x10), ARGB_BLACK, NULL, NULL);
+ }
+
+
+ // draw the profiler if visible
+ if (mame_machine_manager::instance()->ui().show_profiler())
+ {
+ const char *text = g_profiler.text(machine);
+ mame_machine_manager::instance()->ui().draw_text_full(container, text, 0.0f, 0.0f, 1.0f, JUSTIFY_LEFT, WRAP_WORD, DRAW_OPAQUE, ARGB_WHITE, ARGB_BLACK, nullptr, nullptr);
+ }
+
+ // if we're single-stepping, pause now
+ if (mame_machine_manager::instance()->ui().single_step())
+ {
+ machine.pause();
+ mame_machine_manager::instance()->ui().set_single_step(false);
+ }
+
+ // determine if we should disable the rest of the UI
+ bool ui_disabled = (machine.ioport().has_keyboard() && !machine.ui_active());
+
+ // is ScrLk UI toggling applicable here?
+ if (machine.ioport().has_keyboard())
+ {
+ // are we toggling the UI with ScrLk?
+ if (machine.ui_input().pressed(IPT_UI_TOGGLE_UI))
+ {
+ // toggle the UI
+ machine.set_ui_active(!machine.ui_active());
+
+ // display a popup indicating the new status
+ if (machine.ui_active())
+ {
+ mame_machine_manager::instance()->ui().popup_time(2, "%s\n%s\n%s\n%s\n%s\n%s\n",
+ _("Keyboard Emulation Status"),
+ "-------------------------",
+ _("Mode: PARTIAL Emulation"),
+ _("UI: Enabled"),
+ "-------------------------",
+ _("**Use ScrLock to toggle**"));
+ }
+ else
+ {
+ mame_machine_manager::instance()->ui().popup_time(2, "%s\n%s\n%s\n%s\n%s\n%s\n",
+ _("Keyboard Emulation Status"),
+ "-------------------------",
+ _("Mode: FULL Emulation"),
+ _("UI: Disabled"),
+ "-------------------------",
+ _("**Use ScrLock to toggle**"));
+ }
+ }
+ }
+
+ // is the natural keyboard enabled?
+ if (mame_machine_manager::instance()->ui().use_natural_keyboard() && (machine.phase() == MACHINE_PHASE_RUNNING))
+ mame_machine_manager::instance()->ui().process_natural_keyboard();
+
+ if (!ui_disabled)
+ {
+ // paste command
+ if (machine.ui_input().pressed(IPT_UI_PASTE))
+ mame_machine_manager::instance()->ui().paste();
+ }
+
+ mame_machine_manager::instance()->ui().image_handler_ingame();
+
+ // handle a save input timecode request
+ if (machine.ui_input().pressed(IPT_UI_TIMECODE))
+ machine.video().save_input_timecode();
+
+ if (ui_disabled) return ui_disabled;
+
+ if (machine.ui_input().pressed(IPT_UI_CANCEL))
+ {
+ mame_machine_manager::instance()->ui().request_quit();
+ return 0;
+ }
+
+ // turn on menus if requested
+ if (machine.ui_input().pressed(IPT_UI_CONFIGURE))
+ return mame_machine_manager::instance()->ui().set_handler(ui_menu::ui_handler, 0);
+
+ // if the on-screen display isn't up and the user has toggled it, turn it on
+ if ((machine.debug_flags & DEBUG_FLAG_ENABLED) == 0 && machine.ui_input().pressed(IPT_UI_ON_SCREEN_DISPLAY))
+ return mame_machine_manager::instance()->ui().set_handler(ui_menu_sliders::ui_handler, 1);
+
+ // handle a reset request
+ if (machine.ui_input().pressed(IPT_UI_RESET_MACHINE))
+ machine.schedule_hard_reset();
+ if (machine.ui_input().pressed(IPT_UI_SOFT_RESET))
+ machine.schedule_soft_reset();
+
+ // handle a request to display graphics/palette
+ if (machine.ui_input().pressed(IPT_UI_SHOW_GFX))
+ {
+ if (!is_paused)
+ machine.pause();
+ return mame_machine_manager::instance()->ui().set_handler(ui_gfx_ui_handler, is_paused);
+ }
+
+ // handle a tape control key
+ if (machine.ui_input().pressed(IPT_UI_TAPE_START))
+ {
+ for (cassette_image_device &cass : cassette_device_iterator(machine.root_device()))
+ {
+ cass.change_state(CASSETTE_PLAY, CASSETTE_MASK_UISTATE);
+ return 0;
+ }
+ }
+ if (machine.ui_input().pressed(IPT_UI_TAPE_STOP))
+ {
+ for (cassette_image_device &cass : cassette_device_iterator(machine.root_device()))
+ {
+ cass.change_state(CASSETTE_STOPPED, CASSETTE_MASK_UISTATE);
+ return 0;
+ }
+ }
+
+ // handle a save state request
+ if (machine.ui_input().pressed(IPT_UI_SAVE_STATE))
+ {
+ machine.pause();
+ mame_machine_manager::instance()->ui().m_load_save_hold = true;
+ return mame_machine_manager::instance()->ui().set_handler(handler_load_save, LOADSAVE_SAVE);
+ }
+
+ // handle a load state request
+ if (machine.ui_input().pressed(IPT_UI_LOAD_STATE))
+ {
+ machine.pause();
+ mame_machine_manager::instance()->ui().m_load_save_hold = true;
+ return mame_machine_manager::instance()->ui().set_handler(handler_load_save, LOADSAVE_LOAD);
+ }
+
+ // handle a save snapshot request
+ if (machine.ui_input().pressed(IPT_UI_SNAPSHOT))
+ machine.video().save_active_screen_snapshots();
+
+ // toggle pause
+ if (machine.ui_input().pressed(IPT_UI_PAUSE))
+ machine.toggle_pause();
+
+ // pause single step
+ if (machine.ui_input().pressed(IPT_UI_PAUSE_SINGLE))
+ {
+ mame_machine_manager::instance()->ui().set_single_step(true);
+ machine.resume();
+ }
+
+ // handle a toggle cheats request
+ if (machine.ui_input().pressed(IPT_UI_TOGGLE_CHEAT))
+ mame_machine_manager::instance()->cheat().set_enable(!mame_machine_manager::instance()->cheat().enabled());
+
+ // toggle movie recording
+ if (machine.ui_input().pressed(IPT_UI_RECORD_MOVIE))
+ machine.video().toggle_record_movie();
+
+ // toggle profiler display
+ if (machine.ui_input().pressed(IPT_UI_SHOW_PROFILER))
+ mame_machine_manager::instance()->ui().set_show_profiler(!mame_machine_manager::instance()->ui().show_profiler());
+
+ // toggle FPS display
+ if (machine.ui_input().pressed(IPT_UI_SHOW_FPS))
+ mame_machine_manager::instance()->ui().set_show_fps(!mame_machine_manager::instance()->ui().show_fps());
+
+ // increment frameskip?
+ if (machine.ui_input().pressed(IPT_UI_FRAMESKIP_INC))
+ mame_machine_manager::instance()->ui().increase_frameskip();
+
+ // decrement frameskip?
+ if (machine.ui_input().pressed(IPT_UI_FRAMESKIP_DEC))
+ mame_machine_manager::instance()->ui().decrease_frameskip();
+
+ // toggle throttle?
+ if (machine.ui_input().pressed(IPT_UI_THROTTLE))
+ machine.video().toggle_throttle();
+
+ // toggle autofire
+ if (machine.ui_input().pressed(IPT_UI_TOGGLE_AUTOFIRE))
+ {
+ if (!machine.options().cheat())
+ {
+ machine.popmessage(_("Autofire can't be enabled"));
+ }
+ else
+ {
+ bool autofire_toggle = machine.ioport().get_autofire_toggle();
+ machine.ioport().set_autofire_toggle(!autofire_toggle);
+ machine.popmessage("Autofire %s", autofire_toggle ? _("Enabled") : _("Disabled"));
+ }
+ }
+
+ // check for fast forward
+ if (machine.ioport().type_pressed(IPT_UI_FAST_FORWARD))
+ {
+ machine.video().set_fastforward(true);
+ mame_machine_manager::instance()->ui().show_fps_temp(0.5);
+ }
+ else
+ machine.video().set_fastforward(false);
+
+ return 0;
+}
+
+
+//-------------------------------------------------
+// handler_load_save - leads the user through
+// specifying a game to save or load
+//-------------------------------------------------
+
+UINT32 mame_ui_manager::handler_load_save(running_machine &machine, render_container *container, UINT32 state)
+{
+ char filename[20];
+ char file = 0;
+
+ // if we're not in the middle of anything, skip
+ if (state == LOADSAVE_NONE)
+ return 0;
+
+ // okay, we're waiting for a key to select a slot; display a message
+ if (state == LOADSAVE_SAVE)
+ mame_machine_manager::instance()->ui().draw_message_window(container, _("Select position to save to"));
+ else
+ mame_machine_manager::instance()->ui().draw_message_window(container, _("Select position to load from"));
+
+ // if load/save state sequence is still being pressed, do not read the filename yet
+ if (mame_machine_manager::instance()->ui().m_load_save_hold) {
+ bool seq_in_progress = false;
+ const input_seq &load_save_seq = state == LOADSAVE_SAVE ?
+ machine.ioport().type_seq(IPT_UI_SAVE_STATE) :
+ machine.ioport().type_seq(IPT_UI_LOAD_STATE);
+
+ for (int i = 0; i < load_save_seq.length(); i++)
+ if (machine.input().code_pressed_once(load_save_seq[i]))
+ seq_in_progress = true;
+
+ if (seq_in_progress)
+ return state;
+ else
+ mame_machine_manager::instance()->ui().m_load_save_hold = false;
+ }
+
+ // check for cancel key
+ if (machine.ui_input().pressed(IPT_UI_CANCEL))
+ {
+ // display a popup indicating things were cancelled
+ if (state == LOADSAVE_SAVE)
+ machine.popmessage(_("Save cancelled"));
+ else
+ machine.popmessage(_("Load cancelled"));
+
+ // reset the state
+ machine.resume();
+ return UI_HANDLER_CANCEL;
+ }
+
+ // check for A-Z or 0-9
+ for (input_item_id id = ITEM_ID_A; id <= ITEM_ID_Z; ++id)
+ if (machine.input().code_pressed_once(input_code(DEVICE_CLASS_KEYBOARD, 0, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, id)))
+ file = id - ITEM_ID_A + 'a';
+ if (file == 0)
+ for (input_item_id id = ITEM_ID_0; id <= ITEM_ID_9; ++id)
+ if (machine.input().code_pressed_once(input_code(DEVICE_CLASS_KEYBOARD, 0, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, id)))
+ file = id - ITEM_ID_0 + '0';
+ if (file == 0)
+ for (input_item_id id = ITEM_ID_0_PAD; id <= ITEM_ID_9_PAD; ++id)
+ if (machine.input().code_pressed_once(input_code(DEVICE_CLASS_KEYBOARD, 0, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, id)))
+ file = id - ITEM_ID_0_PAD + '0';
+ if (file == 0)
+ {
+ bool found = false;
+
+ for (int joy_index = 0; joy_index <= MAX_SAVED_STATE_JOYSTICK; joy_index++)
+ for (input_item_id id = ITEM_ID_BUTTON1; id <= ITEM_ID_BUTTON32; ++id)
+ if (machine.input().code_pressed_once(input_code(DEVICE_CLASS_JOYSTICK, joy_index, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, id)))
+ {
+ snprintf(filename, sizeof(filename), "joy%i-%i", joy_index, id - ITEM_ID_BUTTON1 + 1);
+ found = true;
+ break;
+ }
+
+ if (!found)
+ return state;
+ }
+ else
+ {
+ sprintf(filename, "%c", file);
+ }
+
+ // display a popup indicating that the save will proceed
+ if (state == LOADSAVE_SAVE)
+ {
+ machine.popmessage(_("Save to position %s"), filename);
+ machine.schedule_save(filename);
+ }
+ else
+ {
+ machine.popmessage(_("Load from position %s"), filename);
+ machine.schedule_load(filename);
+ }
+
+ // avoid handling the name of the save state slot as a seperate input
+ machine.ui_input().mark_all_as_pressed();
+
+ // remove the pause and reset the state
+ machine.resume();
+ return UI_HANDLER_CANCEL;
+}
+
+
+//-------------------------------------------------
+// request_quit
+//-------------------------------------------------
+
+void mame_ui_manager::request_quit()
+{
+ if (!machine().options().confirm_quit())
+ machine().schedule_exit();
+ else
+ set_handler(handler_confirm_quit, 0);
+}
+
+
+//-------------------------------------------------
+// handler_confirm_quit - leads the user through
+// confirming quit emulation
+//-------------------------------------------------
+
+UINT32 mame_ui_manager::handler_confirm_quit(running_machine &machine, render_container *container, UINT32 state)
+{
+ // get the text for 'UI Select'
+ std::string ui_select_text = machine.input().seq_name(machine.ioport().type_seq(IPT_UI_SELECT, 0, SEQ_TYPE_STANDARD));
+
+ // get the text for 'UI Cancel'
+ std::string ui_cancel_text = machine.input().seq_name(machine.ioport().type_seq(IPT_UI_CANCEL, 0, SEQ_TYPE_STANDARD));
+
+ // assemble the quit message
+ std::string quit_message = string_format(_("Are you sure you want to quit?\n\n"
+ "Press ''%1$s'' to quit,\n"
+ "Press ''%2$s'' to return to emulation."),
+ ui_select_text,
+ ui_cancel_text);
+
+ mame_machine_manager::instance()->ui().draw_text_box(container, quit_message.c_str(), JUSTIFY_CENTER, 0.5f, 0.5f, UI_RED_COLOR);
+ machine.pause();
+
+ // if the user press ENTER, quit the game
+ if (machine.ui_input().pressed(IPT_UI_SELECT))
+ machine.schedule_exit();
+
+ // if the user press ESC, just continue
+ else if (machine.ui_input().pressed(IPT_UI_CANCEL))
+ {
+ machine.resume();
+ state = UI_HANDLER_CANCEL;
+ }
+
+ return state;
+}
+
+
+/***************************************************************************
+ SLIDER CONTROLS
+***************************************************************************/
+
+//-------------------------------------------------
+// ui_get_slider_list - get the list of sliders
+//-------------------------------------------------
+
+std::vector<ui_menu_item>& mame_ui_manager::get_slider_list(void)
+{
+ return slider_list;
+}
+
+
+//-------------------------------------------------
+// slider_alloc - allocate a new slider entry
+//-------------------------------------------------
+
+static slider_state *slider_alloc(running_machine &machine, const char *title, INT32 minval, INT32 defval, INT32 maxval, INT32 incval, slider_update update, void *arg)
+{
+ int size = sizeof(slider_state) + strlen(title);
+ slider_state *state = (slider_state *)auto_alloc_array_clear(machine, UINT8, size);
+
+ state->minval = minval;
+ state->defval = defval;
+ state->maxval = maxval;
+ state->incval = incval;
+ state->update = update;
+ state->arg = arg;
+ state->id = -1;
+ strcpy(state->description, title);
+
+ return state;
+}
+
+
+//----------------------------------------------------------
+// mame_ui_manager::slider_init - initialize the list of slider
+// controls
+//----------------------------------------------------------
+
+std::vector<ui_menu_item> mame_ui_manager::slider_init(running_machine &machine)
+{
+ std::vector<slider_state *> sliders;
+
+ // add overall volume
+ sliders.push_back(slider_alloc(machine, _("Master Volume"), -32, 0, 0, 1, slider_volume, nullptr));
+
+ // add per-channel volume
+ mixer_input info;
+ for (int item = 0; machine.sound().indexed_mixer_input(item, info); item++)
+ {
+ INT32 maxval = 2000;
+ INT32 defval = 1000;
+
+ std::string str = string_format(_("%1$s Volume"), info.stream->input_name(info.inputnum));
+ sliders.push_back(slider_alloc(machine, str.c_str(), 0, defval, maxval, 20, slider_mixervol, (void *)(FPTR)item));
+ }
+
+ // add analog adjusters
+ for (ioport_port &port : machine.ioport().ports())
+ {
+ for (ioport_field &field : port.fields())
+ {
+ if (field.type() == IPT_ADJUSTER)
+ {
+ sliders.push_back(slider_alloc(machine, field.name(), field.minval(), field.defvalue(), field.maxval(), 1, slider_adjuster, (void *)&field));
+ }
+ }
+ }
+
+ // add CPU overclocking (cheat only)
+ if (machine.options().cheat())
+ {
+ for (device_execute_interface &exec : execute_interface_iterator(machine.root_device()))
+ {
+ void *param = (void *)&exec.device();
+ std::string str = string_format(_("Overclock CPU %1$s"), exec.device().tag());
+ sliders.push_back(slider_alloc(machine, str.c_str(), 10, 1000, 2000, 1, slider_overclock, param));
+ }
+ }
+
+ // add screen parameters
+ screen_device_iterator scriter(machine.root_device());
+ for (screen_device &screen : scriter)
+ {
+ int defxscale = floor(screen.xscale() * 1000.0f + 0.5f);
+ int defyscale = floor(screen.yscale() * 1000.0f + 0.5f);
+ int defxoffset = floor(screen.xoffset() * 1000.0f + 0.5f);
+ int defyoffset = floor(screen.yoffset() * 1000.0f + 0.5f);
+ void *param = (void *)&screen;
+ std::string screen_desc = slider_get_screen_desc(screen);
+
+ // add refresh rate tweaker
+ if (machine.options().cheat())
+ {
+ std::string str = string_format(_("%1$s Refresh Rate"), screen_desc);
+ sliders.push_back(slider_alloc(machine, str.c_str(), -10000, 0, 10000, 1000, slider_refresh, param));
+ }
+
+ // add standard brightness/contrast/gamma controls per-screen
+ std::string str = string_format(_("%1$s Brightness"), screen_desc);
+ sliders.push_back(slider_alloc(machine, str.c_str(), 100, 1000, 2000, 10, slider_brightness, param));
+ str = string_format(_("%1$s Contrast"), screen_desc);
+ sliders.push_back(slider_alloc(machine, str.c_str(), 100, 1000, 2000, 50, slider_contrast, param));
+ str = string_format(_("%1$s Gamma"), screen_desc);
+ sliders.push_back(slider_alloc(machine, str.c_str(), 100, 1000, 3000, 50, slider_gamma, param));
+
+ // add scale and offset controls per-screen
+ str = string_format(_("%1$s Horiz Stretch"), screen_desc);
+ sliders.push_back(slider_alloc(machine, str.c_str(), 500, defxscale, 1500, 2, slider_xscale, param));
+ str = string_format(_("%1$s Horiz Position"), screen_desc);
+ sliders.push_back(slider_alloc(machine, str.c_str(), -500, defxoffset, 500, 2, slider_xoffset, param));
+ str = string_format(_("%1$s Vert Stretch"), screen_desc);
+ sliders.push_back(slider_alloc(machine, str.c_str(), 500, defyscale, 1500, 2, slider_yscale, param));
+ str = string_format(_("%1$s Vert Position"), screen_desc);
+ sliders.push_back(slider_alloc(machine, str.c_str(), -500, defyoffset, 500, 2, slider_yoffset, param));
+ }
+
+ for (laserdisc_device &laserdisc : laserdisc_device_iterator(machine.root_device()))
+ {
+ if (laserdisc.overlay_configured())
+ {
+ laserdisc_overlay_config config;
+ laserdisc.get_overlay_config(config);
+ int defxscale = floor(config.m_overscalex * 1000.0f + 0.5f);
+ int defyscale = floor(config.m_overscaley * 1000.0f + 0.5f);
+ int defxoffset = floor(config.m_overposx * 1000.0f + 0.5f);
+ int defyoffset = floor(config.m_overposy * 1000.0f + 0.5f);
+ void *param = (void *)&laserdisc;
+
+ // add scale and offset controls per-overlay
+ std::string str = string_format(_("Laserdisc '%1$s' Horiz Stretch"), laserdisc.tag());
+ sliders.push_back(slider_alloc(machine, str.c_str(), 500, (defxscale == 0) ? 1000 : defxscale, 1500, 2, slider_overxscale, param));
+ str = string_format(_("Laserdisc '%1$s' Horiz Position"), laserdisc.tag());
+ sliders.push_back(slider_alloc(machine, str.c_str(), -500, defxoffset, 500, 2, slider_overxoffset, param));
+ str = string_format(_("Laserdisc '%1$s' Vert Stretch"), laserdisc.tag());
+ sliders.push_back(slider_alloc(machine, str.c_str(), 500, (defyscale == 0) ? 1000 : defyscale, 1500, 2, slider_overyscale, param));
+ str = string_format(_("Laserdisc '%1$s' Vert Position"), laserdisc.tag());
+ sliders.push_back(slider_alloc(machine, str.c_str(), -500, defyoffset, 500, 2, slider_overyoffset, param));
+ }
+ }
+
+ for (screen_device &screen : scriter)
+ {
+ if (screen.screen_type() == SCREEN_TYPE_VECTOR)
+ {
+ // add vector control
+ sliders.push_back(slider_alloc(machine, _("Vector Flicker"), 0, 0, 1000, 10, slider_flicker, nullptr));
+ sliders.push_back(slider_alloc(machine, _("Beam Width Minimum"), 1, 100, 1000, 1, slider_beam_width_min, nullptr));
+ sliders.push_back(slider_alloc(machine, _("Beam Width Maximum"), 1, 100, 1000, 1, slider_beam_width_max, nullptr));
+ sliders.push_back(slider_alloc(machine, _("Beam Intensity Weight"), -1000, 0, 1000, 10, slider_beam_intensity_weight, nullptr));
+ break;
+ }
+ }
+
+#ifdef MAME_DEBUG
+ // add crosshair adjusters
+ for (ioport_port &port : machine.ioport().ports())
+ {
+ for (ioport_field &field : port.fields())
+ {
+ if (field.crosshair_axis() != CROSSHAIR_AXIS_NONE && field.player() == 0)
+ {
+ std::string str = string_format(_("Crosshair Scale %1$s"), (field.crosshair_axis() == CROSSHAIR_AXIS_X) ? _("X") : _("Y"));
+ sliders.push_back(slider_alloc(machine, str.c_str(), -3000, 1000, 3000, 100, slider_crossscale, (void *)&field));
+ str = string_format(_("Crosshair Offset %1$s"), (field.crosshair_axis() == CROSSHAIR_AXIS_X) ? _("X") : _("Y"));
+ sliders.push_back(slider_alloc(machine, str.c_str(), -3000, 0, 3000, 100, slider_crossoffset, (void *)&field));
+ }
+ }
+ }
+#endif
+
+ std::vector<ui_menu_item> items;
+ for (slider_state *slider : sliders)
+ {
+ ui_menu_item item;
+ item.text = slider->description;
+ item.subtext = "";
+ item.flags = 0;
+ item.ref = slider;
+ item.type = ui_menu_item_type::SLIDER;
+ items.push_back(item);
+ }
+
+ return items;
+}
+
+
+//-------------------------------------------------
+// slider_volume - global volume slider callback
+//-------------------------------------------------
+
+static INT32 slider_volume(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
+{
+ if (newval != SLIDER_NOCHANGE)
+ machine.sound().set_attenuation(newval);
+ if (str)
+ *str = string_format(_("%1$3ddB"), machine.sound().attenuation());
+ return machine.sound().attenuation();
+}
+
+
+//-------------------------------------------------
+// slider_mixervol - single channel volume
+// slider callback
+//-------------------------------------------------
+
+static INT32 slider_mixervol(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
+{
+ mixer_input info;
+ if (!machine.sound().indexed_mixer_input((FPTR)arg, info))
+ return 0;
+ if (newval != SLIDER_NOCHANGE)
+ {
+ INT32 curval = floor(info.stream->user_gain(info.inputnum) * 1000.0f + 0.5f);
+ if (newval > curval && (newval - curval) <= 4) newval += 4; // round up on increment
+ info.stream->set_user_gain(info.inputnum, (float)newval * 0.001f);
+ }
+ if (str)
+ *str = string_format("%4.2f", info.stream->user_gain(info.inputnum));
+ return floorf(info.stream->user_gain(info.inputnum) * 1000.0f + 0.5f);
+}
+
+
+//-------------------------------------------------
+// slider_adjuster - analog adjuster slider
+// callback
+//-------------------------------------------------
+
+static INT32 slider_adjuster(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
+{
+ ioport_field *field = (ioport_field *)arg;
+ ioport_field::user_settings settings;
+
+ field->get_user_settings(settings);
+ if (newval != SLIDER_NOCHANGE)
+ {
+ settings.value = newval;
+ field->set_user_settings(settings);
+ }
+ if (str)
+ *str = string_format(_("%1$d%%"), settings.value);
+ return settings.value;
+}
+
+
+//-------------------------------------------------
+// slider_overclock - CPU overclocker slider
+// callback
+//-------------------------------------------------
+
+static INT32 slider_overclock(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
+{
+ device_t *cpu = (device_t *)arg;
+ if (newval != SLIDER_NOCHANGE)
+ cpu->set_clock_scale((float)newval * 0.001f);
+ if (str)
+ *str = string_format(_("%1$3.0f%%"), floor(cpu->clock_scale() * 100.0 + 0.5));
+ return floor(cpu->clock_scale() * 1000.0 + 0.5);
+}
+
+
+//-------------------------------------------------
+// slider_refresh - refresh rate slider callback
+//-------------------------------------------------
+
+static INT32 slider_refresh(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
+{
+ screen_device *screen = reinterpret_cast<screen_device *>(arg);
+ double defrefresh = ATTOSECONDS_TO_HZ(screen->refresh_attoseconds());
+ double refresh;
+
+ if (newval != SLIDER_NOCHANGE)
+ {
+ int width = screen->width();
+ int height = screen->height();
+ const rectangle &visarea = screen->visible_area();
+ screen->configure(width, height, visarea, HZ_TO_ATTOSECONDS(defrefresh + (double)newval * 0.001));
+ }
+ if (str)
+ *str = string_format(_("%1$.3ffps"), ATTOSECONDS_TO_HZ(machine.first_screen()->frame_period().attoseconds()));
+ refresh = ATTOSECONDS_TO_HZ(machine.first_screen()->frame_period().attoseconds());
+ return floor((refresh - defrefresh) * 1000.0 + 0.5);
+}
+
+
+//-------------------------------------------------
+// slider_brightness - screen brightness slider
+// callback
+//-------------------------------------------------
+
+static INT32 slider_brightness(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
+{
+ screen_device *screen = reinterpret_cast<screen_device *>(arg);
+ render_container::user_settings settings;
+
+ screen->container().get_user_settings(settings);
+ if (newval != SLIDER_NOCHANGE)
+ {
+ settings.m_brightness = (float)newval * 0.001f;
+ screen->container().set_user_settings(settings);
+ }
+ if (str)
+ *str = string_format(_("%1$.3f"), settings.m_brightness);
+ return floor(settings.m_brightness * 1000.0f + 0.5f);
+}
+
+
+//-------------------------------------------------
+// slider_contrast - screen contrast slider
+// callback
+//-------------------------------------------------
+
+static INT32 slider_contrast(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
+{
+ screen_device *screen = reinterpret_cast<screen_device *>(arg);
+ render_container::user_settings settings;
+
+ screen->container().get_user_settings(settings);
+ if (newval != SLIDER_NOCHANGE)
+ {
+ settings.m_contrast = (float)newval * 0.001f;
+ screen->container().set_user_settings(settings);
+ }
+ if (str)
+ *str = string_format(_("%1$.3f"), settings.m_contrast);
+ return floor(settings.m_contrast * 1000.0f + 0.5f);
+}
+
+
+//-------------------------------------------------
+// slider_gamma - screen gamma slider callback
+//-------------------------------------------------
+
+static INT32 slider_gamma(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
+{
+ screen_device *screen = reinterpret_cast<screen_device *>(arg);
+ render_container::user_settings settings;
+
+ screen->container().get_user_settings(settings);
+ if (newval != SLIDER_NOCHANGE)
+ {
+ settings.m_gamma = (float)newval * 0.001f;
+ screen->container().set_user_settings(settings);
+ }
+ if (str)
+ *str = string_format(_("%1$.3f"), settings.m_gamma);
+ return floor(settings.m_gamma * 1000.0f + 0.5f);
+}
+
+
+//-------------------------------------------------
+// slider_xscale - screen horizontal scale slider
+// callback
+//-------------------------------------------------
+
+static INT32 slider_xscale(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
+{
+ screen_device *screen = reinterpret_cast<screen_device *>(arg);
+ render_container::user_settings settings;
+
+ screen->container().get_user_settings(settings);
+ if (newval != SLIDER_NOCHANGE)
+ {
+ settings.m_xscale = (float)newval * 0.001f;
+ screen->container().set_user_settings(settings);
+ }
+ if (str)
+ *str = string_format(_("%1$.3f"), settings.m_xscale);
+ return floor(settings.m_xscale * 1000.0f + 0.5f);
+}
+
+
+//-------------------------------------------------
+// slider_yscale - screen vertical scale slider
+// callback
+//-------------------------------------------------
+
+static INT32 slider_yscale(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
+{
+ screen_device *screen = reinterpret_cast<screen_device *>(arg);
+ render_container::user_settings settings;
+
+ screen->container().get_user_settings(settings);
+ if (newval != SLIDER_NOCHANGE)
+ {
+ settings.m_yscale = (float)newval * 0.001f;
+ screen->container().set_user_settings(settings);
+ }
+ if (str)
+ *str = string_format(_("%1$.3f"), settings.m_yscale);
+ return floor(settings.m_yscale * 1000.0f + 0.5f);
+}
+
+
+//-------------------------------------------------
+// slider_xoffset - screen horizontal position
+// slider callback
+//-------------------------------------------------
+
+static INT32 slider_xoffset(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
+{
+ screen_device *screen = reinterpret_cast<screen_device *>(arg);
+ render_container::user_settings settings;
+
+ screen->container().get_user_settings(settings);
+ if (newval != SLIDER_NOCHANGE)
+ {
+ settings.m_xoffset = (float)newval * 0.001f;
+ screen->container().set_user_settings(settings);
+ }
+ if (str)
+ *str = string_format(_("%1$.3f"), settings.m_xoffset);
+ return floor(settings.m_xoffset * 1000.0f + 0.5f);
+}
+
+
+//-------------------------------------------------
+// slider_yoffset - screen vertical position
+// slider callback
+//-------------------------------------------------
+
+static INT32 slider_yoffset(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
+{
+ screen_device *screen = reinterpret_cast<screen_device *>(arg);
+ render_container::user_settings settings;
+
+ screen->container().get_user_settings(settings);
+ if (newval != SLIDER_NOCHANGE)
+ {
+ settings.m_yoffset = (float)newval * 0.001f;
+ screen->container().set_user_settings(settings);
+ }
+ if (str)
+ *str = string_format(_("%1$.3f"), settings.m_yoffset);
+ return floor(settings.m_yoffset * 1000.0f + 0.5f);
+}
+
+
+//-------------------------------------------------
+// slider_overxscale - screen horizontal scale slider
+// callback
+//-------------------------------------------------
+
+static INT32 slider_overxscale(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
+{
+ laserdisc_device *laserdisc = (laserdisc_device *)arg;
+ laserdisc_overlay_config settings;
+
+ laserdisc->get_overlay_config(settings);
+ if (newval != SLIDER_NOCHANGE)
+ {
+ settings.m_overscalex = (float)newval * 0.001f;
+ laserdisc->set_overlay_config(settings);
+ }
+ if (str)
+ *str = string_format(_("%1$.3f"), settings.m_overscalex);
+ return floor(settings.m_overscalex * 1000.0f + 0.5f);
+}
+
+
+//-------------------------------------------------
+// slider_overyscale - screen vertical scale slider
+// callback
+//-------------------------------------------------
+
+static INT32 slider_overyscale(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
+{
+ laserdisc_device *laserdisc = (laserdisc_device *)arg;
+ laserdisc_overlay_config settings;
+
+ laserdisc->get_overlay_config(settings);
+ if (newval != SLIDER_NOCHANGE)
+ {
+ settings.m_overscaley = (float)newval * 0.001f;
+ laserdisc->set_overlay_config(settings);
+ }
+ if (str)
+ *str = string_format(_("%1$.3f"), settings.m_overscaley);
+ return floor(settings.m_overscaley * 1000.0f + 0.5f);
+}
+
+
+//-------------------------------------------------
+// slider_overxoffset - screen horizontal position
+// slider callback
+//-------------------------------------------------
+
+static INT32 slider_overxoffset(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
+{
+ laserdisc_device *laserdisc = (laserdisc_device *)arg;
+ laserdisc_overlay_config settings;
+
+ laserdisc->get_overlay_config(settings);
+ if (newval != SLIDER_NOCHANGE)
+ {
+ settings.m_overposx = (float)newval * 0.001f;
+ laserdisc->set_overlay_config(settings);
+ }
+ if (str)
+ *str = string_format(_("%1$.3f"), settings.m_overposx);
+ return floor(settings.m_overposx * 1000.0f + 0.5f);
+}
+
+
+//-------------------------------------------------
+// slider_overyoffset - screen vertical position
+// slider callback
+//-------------------------------------------------
+
+static INT32 slider_overyoffset(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
+{
+ laserdisc_device *laserdisc = (laserdisc_device *)arg;
+ laserdisc_overlay_config settings;
+
+ laserdisc->get_overlay_config(settings);
+ if (newval != SLIDER_NOCHANGE)
+ {
+ settings.m_overposy = (float)newval * 0.001f;
+ laserdisc->set_overlay_config(settings);
+ }
+ if (str)
+ *str = string_format(_("%1$.3f"), settings.m_overposy);
+ return floor(settings.m_overposy * 1000.0f + 0.5f);
+}
+
+
+//-------------------------------------------------
+// slider_flicker - vector flicker slider
+// callback
+//-------------------------------------------------
+
+static INT32 slider_flicker(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
+{
+ if (newval != SLIDER_NOCHANGE)
+ vector_options::s_flicker = (float)newval * 0.001f;
+ if (str)
+ *str = string_format(_("%1$1.2f"), vector_options::s_flicker);
+ return floor(vector_options::s_flicker * 1000.0f + 0.5f);
+}
+
+
+//-------------------------------------------------
+// slider_beam_width_min - minimum vector beam width slider
+// callback
+//-------------------------------------------------
+
+static INT32 slider_beam_width_min(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
+{
+ if (newval != SLIDER_NOCHANGE)
+ vector_options::s_beam_width_min = MIN((float)newval * 0.01f, vector_options::s_beam_width_max);
+ if (str != nullptr)
+ *str = string_format(_("%1$1.2f"), vector_options::s_beam_width_min);
+ return floor(vector_options::s_beam_width_min * 100.0f + 0.5f);
+}
+
+
+//-------------------------------------------------
+// slider_beam_width_max - maximum vector beam width slider
+// callback
+//-------------------------------------------------
+
+static INT32 slider_beam_width_max(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
+{
+ if (newval != SLIDER_NOCHANGE)
+ vector_options::s_beam_width_max = MAX((float)newval * 0.01f, vector_options::s_beam_width_min);
+ if (str != nullptr)
+ *str = string_format(_("%1$1.2f"), vector_options::s_beam_width_max);
+ return floor(vector_options::s_beam_width_max * 100.0f + 0.5f);
+}
+
+
+//-------------------------------------------------
+// slider_beam_intensity_weight - vector beam intensity weight slider
+// callback
+//-------------------------------------------------
+
+static INT32 slider_beam_intensity_weight(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
+{
+ if (newval != SLIDER_NOCHANGE)
+ vector_options::s_beam_intensity_weight = (float)newval * 0.001f;
+ if (str != nullptr)
+ *str = string_format(_("%1$1.2f"), vector_options::s_beam_intensity_weight);
+ return floor(vector_options::s_beam_intensity_weight * 1000.0f + 0.5f);
+}
+
+
+//-------------------------------------------------
+// slider_get_screen_desc - returns the
+// description for a given screen
+//-------------------------------------------------
+
+static std::string slider_get_screen_desc(screen_device &screen)
+{
+ if (screen_device_iterator(screen.machine().root_device()).count() > 1)
+ return string_format(_("Screen '%1$s'"), screen.tag());
+ else
+ return _("Screen");
+}
+
+//-------------------------------------------------
+// slider_crossscale - crosshair scale slider
+// callback
+//-------------------------------------------------
+
+#ifdef MAME_DEBUG
+static INT32 slider_crossscale(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
+{
+ ioport_field *field = (ioport_field *)arg;
+
+ if (newval != SLIDER_NOCHANGE)
+ field->set_crosshair_scale(float(newval) * 0.001);
+ if (str)
+ *str = string_format((field->crosshair_axis() == CROSSHAIR_AXIS_X) ? _("Crosshair Scale X %1$1.3f") : _("Crosshair Scale Y %1$1.3f"), float(newval) * 0.001f);
+ return floor(field->crosshair_scale() * 1000.0f + 0.5f);
+}
+#endif
+
+
+//-------------------------------------------------
+// slider_crossoffset - crosshair scale slider
+// callback
+//-------------------------------------------------
+
+#ifdef MAME_DEBUG
+static INT32 slider_crossoffset(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
+{
+ ioport_field *field = (ioport_field *)arg;
+
+ if (newval != SLIDER_NOCHANGE)
+ field->set_crosshair_offset(float(newval) * 0.001f);
+ if (str)
+ *str = string_format((field->crosshair_axis() == CROSSHAIR_AXIS_X) ? _("Crosshair Offset X %1$1.3f") : _("Crosshair Offset Y %1$1.3f"), float(newval) * 0.001f);
+ return field->crosshair_offset();
+}
+#endif
+
+//-------------------------------------------------
+// set_use_natural_keyboard - specifies
+// whether the natural keyboard is active
+//-------------------------------------------------
+
+void mame_ui_manager::set_use_natural_keyboard(bool use_natural_keyboard)
+{
+ m_use_natural_keyboard = use_natural_keyboard;
+ std::string error;
+ machine().options().set_value(OPTION_NATURAL_KEYBOARD, use_natural_keyboard, OPTION_PRIORITY_CMDLINE, error);
+ assert(error.empty());
+}
+
+//-------------------------------------------------
+// wrap_text
+//-------------------------------------------------
+
+int mame_ui_manager::wrap_text(render_container *container, const char *origs, float x, float y, float origwrapwidth, std::vector<int> &xstart, std::vector<int> &xend, float text_size)
+{
+ float lineheight = get_line_height() * text_size;
+ const char *ends = origs + strlen(origs);
+ float wrapwidth = origwrapwidth;
+ const char *s = origs;
+ const char *linestart;
+ float maxwidth = 0;
+ float aspect = machine().render().ui_aspect(container);
+ int count = 0;
+
+ // loop over lines
+ while (*s != 0)
+ {
+ const char *lastbreak = nullptr;
+ unicode_char schar;
+ int scharcount;
+ float lastbreak_width = 0;
+ float curwidth = 0;
+
+ // get the current character
+ scharcount = uchar_from_utf8(&schar, s, ends - s);
+ if (scharcount == -1)
+ break;
+
+ // remember the starting position of the line
+ linestart = s;
+
+ // loop while we have characters and are less than the wrapwidth
+ while (*s != 0 && curwidth <= wrapwidth)
+ {
+ float chwidth;
+
+ // get the current chcaracter
+ scharcount = uchar_from_utf8(&schar, s, ends - s);
+ if (scharcount == -1)
+ break;
+
+ // if we hit a newline, stop immediately
+ if (schar == '\n')
+ break;
+
+ // get the width of this character
+ chwidth = get_font()->char_width(lineheight, aspect, schar);
+
+ // if we hit a space, remember the location and width *without* the space
+ if (schar == ' ')
+ {
+ lastbreak = s;
+ lastbreak_width = curwidth;
+ }
+
+ // add the width of this character and advance
+ curwidth += chwidth;
+ s += scharcount;
+
+ // if we hit any non-space breakable character, remember the location and width
+ // *with* the breakable character
+ if (schar != ' ' && is_breakable_char(schar) && curwidth <= wrapwidth)
+ {
+ lastbreak = s;
+ lastbreak_width = curwidth;
+ }
+ }
+
+ // if we accumulated too much for the current width, we need to back off
+ if (curwidth > wrapwidth)
+ {
+ // if we hit a break, back up to there with the appropriate width
+ if (lastbreak != nullptr)
+ {
+ s = lastbreak;
+ curwidth = lastbreak_width;
+ }
+
+ // if we didn't hit a break, back up one character
+ else if (s > linestart)
+ {
+ // get the previous character
+ s = (const char *)utf8_previous_char(s);
+ scharcount = uchar_from_utf8(&schar, s, ends - s);
+ if (scharcount == -1)
+ break;
+
+ curwidth -= get_font()->char_width(lineheight, aspect, schar);
+ }
+ }
+
+ // track the maximum width of any given line
+ if (curwidth > maxwidth)
+ maxwidth = curwidth;
+
+ xstart.push_back(linestart - origs);
+ xend.push_back(s - origs);
+
+ // loop from the line start and add the characters
+ while (linestart < s)
+ {
+ // get the current character
+ unicode_char linechar;
+ int linecharcount = uchar_from_utf8(&linechar, linestart, ends - linestart);
+ if (linecharcount == -1)
+ break;
+ linestart += linecharcount;
+ }
+
+ // advance by a row
+ count++;
+
+ // skip past any spaces at the beginning of the next line
+ scharcount = uchar_from_utf8(&schar, s, ends - s);
+ if (scharcount == -1)
+ break;
+
+ if (schar == '\n')
+ s += scharcount;
+ else
+ while (*s && isspace(schar))
+ {
+ s += scharcount;
+ scharcount = uchar_from_utf8(&schar, s, ends - s);
+ if (scharcount == -1)
+ break;
+ }
+ }
+ return count;
+}
+
+//-------------------------------------------------
+// draw_textured_box - add primitives to
+// draw an outlined box with the given
+// textured background and line color
+//-------------------------------------------------
+
+void mame_ui_manager::draw_textured_box(render_container *container, float x0, float y0, float x1, float y1, rgb_t backcolor, rgb_t linecolor, render_texture *texture, UINT32 flags)
+{
+ container->add_quad(x0, y0, x1, y1, backcolor, texture, flags);
+ container->add_line(x0, y0, x1, y0, UI_LINE_WIDTH, linecolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ container->add_line(x1, y0, x1, y1, UI_LINE_WIDTH, linecolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ container->add_line(x1, y1, x0, y1, UI_LINE_WIDTH, linecolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ container->add_line(x0, y1, x0, y0, UI_LINE_WIDTH, linecolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+}
+
+//-------------------------------------------------
+// decode UI color options
+//-------------------------------------------------
+
+rgb_t decode_ui_color(int id, running_machine *machine)
+{
+ static rgb_t color[ARRAY_LENGTH(s_color_list)];
+
+ if (machine != nullptr) {
+ ui_options option;
+ for (int x = 0; x < ARRAY_LENGTH(s_color_list); ++x) {
+ const char *o_default = option.value(s_color_list[x]);
+ const char *s_option = mame_machine_manager::instance()->ui().options().value(s_color_list[x]);
+ int len = strlen(s_option);
+ if (len != 8)
+ color[x] = rgb_t((UINT32)strtoul(o_default, nullptr, 16));
+ else
+ color[x] = rgb_t((UINT32)strtoul(s_option, nullptr, 16));
+ }
+ }
+ return color[id];
+}
+
+//-------------------------------------------------
+// get font rows from options
+//-------------------------------------------------
+
+int get_font_rows(running_machine *machine)
+{
+ static int value;
+
+ return ((machine != nullptr) ? value = mame_machine_manager::instance()->ui().options().font_rows() : value);
+}
+
+void mame_ui_manager::popup_time_string(int seconds, std::string message)
+{
+ // extract the text
+ messagebox_poptext = message;
+ messagebox_backcolor = UI_BACKGROUND_COLOR;
+
+ // set a timer
+ m_popup_text_end = osd_ticks() + osd_ticks_per_second() * seconds;
+}
diff --git a/src/frontend/mame/ui/ui.h b/src/frontend/mame/ui/ui.h
new file mode 100644
index 00000000000..b45d20c6e63
--- /dev/null
+++ b/src/frontend/mame/ui/ui.h
@@ -0,0 +1,223 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/***************************************************************************
+
+ ui.h
+
+ Functions used to handle MAME's crude user interface.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __USRINTRF_H__
+#define __USRINTRF_H__
+
+#include <vector>
+
+#include "render.h"
+#include "moptions.h"
+#include "mame.h"
+#include "language.h"
+#include "ui/uimain.h"
+
+class ui_menu_item;
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* preferred font height; use ui_get_line_height() to get actual height */
+#define UI_TARGET_FONT_ROWS get_font_rows()
+
+#define UI_TARGET_FONT_HEIGHT (1.0f / (float)UI_TARGET_FONT_ROWS)
+#define UI_MAX_FONT_HEIGHT (1.0f / 15.0f)
+
+/* width of lines drawn in the UI */
+#define UI_LINE_WIDTH (1.0f / 500.0f)
+
+/* border between outlines and inner text on left/right and top/bottom sides */
+#define UI_BOX_LR_BORDER (UI_TARGET_FONT_HEIGHT * 0.25f)
+#define UI_BOX_TB_BORDER (UI_TARGET_FONT_HEIGHT * 0.25f)
+
+/* handy colors */
+#define ARGB_WHITE rgb_t(0xff,0xff,0xff,0xff)
+#define ARGB_BLACK rgb_t(0xff,0x00,0x00,0x00)
+#define UI_GREEN_COLOR rgb_t(0xef,0x10,0x60,0x10)
+#define UI_YELLOW_COLOR rgb_t(0xef,0x60,0x60,0x10)
+#define UI_RED_COLOR rgb_t(0xf0,0x60,0x10,0x10)
+#define UI_BORDER_COLOR decode_ui_color(0)
+#define UI_BACKGROUND_COLOR decode_ui_color(1)
+#define UI_GFXVIEWER_BG_COLOR decode_ui_color(2)
+#define UI_UNAVAILABLE_COLOR decode_ui_color(3)
+#define UI_TEXT_COLOR decode_ui_color(4)
+#define UI_TEXT_BG_COLOR decode_ui_color(5)
+#define UI_SUBITEM_COLOR decode_ui_color(6)
+#define UI_CLONE_COLOR decode_ui_color(7)
+#define UI_SELECTED_COLOR decode_ui_color(8)
+#define UI_SELECTED_BG_COLOR decode_ui_color(9)
+#define UI_MOUSEOVER_COLOR decode_ui_color(10)
+#define UI_MOUSEOVER_BG_COLOR decode_ui_color(11)
+#define UI_MOUSEDOWN_COLOR decode_ui_color(12)
+#define UI_MOUSEDOWN_BG_COLOR decode_ui_color(13)
+#define UI_DIPSW_COLOR decode_ui_color(14)
+#define UI_SLIDER_COLOR decode_ui_color(15)
+
+/* cancel return value for a UI handler */
+#define UI_HANDLER_CANCEL ((UINT32)~0)
+
+/* justification options for ui_draw_text_full */
+enum
+{
+ JUSTIFY_LEFT = 0,
+ JUSTIFY_CENTER,
+ JUSTIFY_RIGHT
+};
+
+/* word wrapping options for ui_draw_text_full */
+enum
+{
+ WRAP_NEVER,
+ WRAP_TRUNCATE,
+ WRAP_WORD
+};
+
+/* drawing options for ui_draw_text_full */
+enum
+{
+ DRAW_NONE,
+ DRAW_NORMAL,
+ DRAW_OPAQUE
+};
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef UINT32 (*ui_callback)(running_machine &, render_container *, UINT32);
+
+// ======================> mame_ui_manager
+
+class mame_ui_manager : public ui_manager
+{
+public:
+ // construction/destruction
+ mame_ui_manager(running_machine &machine);
+
+ void init();
+
+ // getters
+ running_machine &machine() const { return m_machine; }
+ bool single_step() const { return m_single_step; }
+ ui_options &options() { return m_ui_options; }
+
+ // setters
+ void set_single_step(bool single_step) { m_single_step = single_step; }
+
+ // methods
+ void initialize(running_machine &machine);
+ std::vector<ui_menu_item> slider_init(running_machine &machine);
+ UINT32 set_handler(ui_callback callback, UINT32 param);
+ void display_startup_screens(bool first_time);
+ virtual void set_startup_text(const char *text, bool force) override;
+ void update_and_render(render_container *container);
+ render_font *get_font();
+ float get_line_height();
+ float get_char_width(unicode_char ch);
+ float get_string_width(const char *s, float text_size = 1.0f);
+ void draw_outlined_box(render_container *container, float x0, float y0, float x1, float y1, rgb_t backcolor);
+ void draw_outlined_box(render_container *container, float x0, float y0, float x1, float y1, rgb_t fgcolor, rgb_t bgcolor);
+ void draw_text(render_container *container, const char *buf, float x, float y);
+ void draw_text_full(render_container *container, const char *origs, float x, float y, float origwrapwidth, int justify, int wrap, int draw, rgb_t fgcolor, rgb_t bgcolor, float *totalwidth = nullptr, float *totalheight = nullptr, float text_size = 1.0f);
+ void draw_text_box(render_container *container, const char *text, int justify, float xpos, float ypos, rgb_t backcolor);
+ void draw_message_window(render_container *container, const char *text);
+
+ template <typename Format, typename... Params> void popup_time(int seconds, Format &&fmt, Params &&... args);
+ void show_fps_temp(double seconds);
+ void set_show_fps(bool show);
+ bool show_fps() const;
+ bool show_fps_counter();
+ void set_show_profiler(bool show);
+ bool show_profiler() const;
+ void show_menu();
+ void show_mouse(bool status);
+ virtual bool is_menu_active() override;
+ bool can_paste();
+ void paste();
+ void set_use_natural_keyboard(bool use_natural_keyboard);
+ void image_handler_ingame();
+ void increase_frameskip();
+ void decrease_frameskip();
+ void request_quit();
+
+ // print the game info string into a buffer
+ std::string &game_info_astring(std::string &str);
+
+ // slider controls
+ std::vector<ui_menu_item>& get_slider_list(void);
+
+ // other
+ void process_natural_keyboard();
+
+ // word wrap
+ int wrap_text(render_container *container, const char *origs, float x, float y, float origwrapwidth, std::vector<int> &xstart, std::vector<int> &xend, float text_size = 1.0f);
+
+ // draw an outlined box with given line color and filled with a texture
+ void draw_textured_box(render_container *container, float x0, float y0, float x1, float y1, rgb_t backcolor, rgb_t linecolor, render_texture *texture = nullptr, UINT32 flags = PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ virtual void popup_time_string(int seconds, std::string message) override;
+
+ virtual void image_display(const device_type &type, device_image_interface *image) override;
+private:
+ // instance variables
+ render_font * m_font;
+ ui_callback m_handler_callback;
+ UINT32 m_handler_param;
+ bool m_single_step;
+ bool m_showfps;
+ osd_ticks_t m_showfps_end;
+ bool m_show_profiler;
+ osd_ticks_t m_popup_text_end;
+ std::unique_ptr<UINT8[]> m_non_char_keys_down;
+ render_texture * m_mouse_arrow_texture;
+ bool m_mouse_show;
+ bool m_load_save_hold;
+ ui_options m_ui_options;
+
+ // static variables
+ static std::string messagebox_text;
+ static std::string messagebox_poptext;
+ static rgb_t messagebox_backcolor;
+
+ static std::vector<ui_menu_item> slider_list;
+ static slider_state *slider_current;
+
+ // text generators
+ std::string &warnings_string(std::string &buffer);
+
+ // UI handlers
+ static UINT32 handler_messagebox(running_machine &machine, render_container *container, UINT32 state);
+ static UINT32 handler_messagebox_anykey(running_machine &machine, render_container *container, UINT32 state);
+ static UINT32 handler_ingame(running_machine &machine, render_container *container, UINT32 state);
+ static UINT32 handler_load_save(running_machine &machine, render_container *container, UINT32 state);
+ static UINT32 handler_confirm_quit(running_machine &machine, render_container *container, UINT32 state);
+
+ // private methods
+ void exit();
+};
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+rgb_t decode_ui_color(int id, running_machine *machine = nullptr);
+int get_font_rows(running_machine *machine = nullptr);
+
+template <typename Format, typename... Params>
+inline void mame_ui_manager::popup_time(int seconds, Format &&fmt, Params &&... args)
+{
+ // extract the text
+ popup_time_string(seconds, string_format(std::forward<Format>(fmt), std::forward<Params>(args)...));
+}
+
+#endif /* __USRINTRF_H__ */
diff --git a/src/frontend/mame/ui/uicmd14.png b/src/frontend/mame/ui/uicmd14.png
new file mode 100644
index 00000000000..d3cae952cac
--- /dev/null
+++ b/src/frontend/mame/ui/uicmd14.png
Binary files differ
diff --git a/src/frontend/mame/ui/utils.cpp b/src/frontend/mame/ui/utils.cpp
new file mode 100644
index 00000000000..d65bbc52ef7
--- /dev/null
+++ b/src/frontend/mame/ui/utils.cpp
@@ -0,0 +1,181 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/***************************************************************************
+
+ ui/utils.cpp
+
+ Internal UI user interface.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "ui/utils.h"
+
+extern const char UI_VERSION_TAG[];
+const char UI_VERSION_TAG[] = "# UI INFO ";
+
+// Years index
+UINT16 c_year::actual = 0;
+std::vector<std::string> c_year::ui;
+
+// Manufacturers index
+UINT16 c_mnfct::actual = 0;
+std::vector<std::string> c_mnfct::ui;
+
+// Main filters
+UINT16 main_filters::actual = 0;
+const char *main_filters::text[] = { "All", "Available", "Unavailable", "Working", "Not Working", "Mechanical", "Not Mechanical",
+ "Category", "Favorites", "BIOS", "Parents", "Clones", "Manufacturers", "Years", "Support Save",
+ "Not Support Save", "CHD", "No CHD", "Vertical", "Horizontal", "Custom" };
+size_t main_filters::length = ARRAY_LENGTH(main_filters::text);
+
+// Software filters
+UINT16 sw_filters::actual = 0;
+const char *sw_filters::text[] = { "All", "Available", "Unavailable", "Parents", "Clones", "Years", "Publishers", "Supported",
+ "Partial Supported", "Unsupported", "Region", "Device Type", "Software List", "Custom" };
+size_t sw_filters::length = ARRAY_LENGTH(sw_filters::text);
+
+// Globals
+UINT8 ui_globals::rpanel = 0;
+UINT8 ui_globals::curimage_view = 0;
+UINT8 ui_globals::curdats_view = 0;
+UINT8 ui_globals::cur_sw_dats_view = 0;
+bool ui_globals::switch_image = false;
+bool ui_globals::default_image = true;
+bool ui_globals::reset = false;
+bool ui_globals::redraw_icon = false;
+int ui_globals::visible_main_lines = 0;
+int ui_globals::visible_sw_lines = 0;
+UINT16 ui_globals::panels_status = 0;
+bool ui_globals::has_icons = false;
+
+// Custom filter
+UINT16 custfltr::main = 0;
+UINT16 custfltr::numother = 0;
+UINT16 custfltr::other[MAX_CUST_FILTER];
+UINT16 custfltr::mnfct[MAX_CUST_FILTER];
+UINT16 custfltr::year[MAX_CUST_FILTER];
+UINT16 custfltr::screen[MAX_CUST_FILTER];
+
+// Custom filter
+UINT16 sw_custfltr::main = 0;
+UINT16 sw_custfltr::numother = 0;
+UINT16 sw_custfltr::other[MAX_CUST_FILTER];
+UINT16 sw_custfltr::mnfct[MAX_CUST_FILTER];
+UINT16 sw_custfltr::year[MAX_CUST_FILTER];
+UINT16 sw_custfltr::region[MAX_CUST_FILTER];
+UINT16 sw_custfltr::type[MAX_CUST_FILTER];
+UINT16 sw_custfltr::list[MAX_CUST_FILTER];
+
+char* chartrimcarriage(char str[])
+{
+ char *pstr = strrchr(str, '\n');
+ if (pstr)
+ str[pstr - str] = '\0';
+ pstr = strrchr(str, '\r');
+ if (pstr)
+ str[pstr - str] = '\0';
+ return str;
+}
+
+const char* strensure(const char* s)
+{
+ return s == nullptr ? "" : s;
+}
+
+int getprecisionchr(const char* s)
+{
+ int precision = 1;
+ char *dp = const_cast<char *>(strchr(s, '.'));
+ if (dp != nullptr)
+ precision = strlen(s) - (dp - s) - 1;
+ return precision;
+}
+
+//-------------------------------------------------
+// search a substring with even partial matching
+//-------------------------------------------------
+
+int fuzzy_substring(std::string s_needle, std::string s_haystack)
+{
+ if (s_needle.empty())
+ return s_haystack.size();
+ if (s_haystack.empty())
+ return s_needle.size();
+
+ strmakelower(s_needle);
+ strmakelower(s_haystack);
+
+ if (s_needle == s_haystack)
+ return 0;
+ if (s_haystack.find(s_needle) != std::string::npos)
+ return 0;
+
+ auto *row1 = global_alloc_array_clear<int>(s_haystack.size() + 2);
+ auto *row2 = global_alloc_array_clear<int>(s_haystack.size() + 2);
+
+ for (int i = 0; i < s_needle.size(); ++i)
+ {
+ row2[0] = i + 1;
+ for (int j = 0; j < s_haystack.size(); ++j)
+ {
+ int cost = (s_needle[i] == s_haystack[j]) ? 0 : 1;
+ row2[j + 1] = MIN(row1[j + 1] + 1, MIN(row2[j] + 1, row1[j] + cost));
+ }
+
+ int *tmp = row1;
+ row1 = row2;
+ row2 = tmp;
+ }
+
+ int *first, *smallest;
+ first = smallest = row1;
+ int *last = row1 + s_haystack.size();
+
+ while (++first != last)
+ if (*first < *smallest)
+ smallest = first;
+
+ int rv = *smallest;
+ global_free_array(row1);
+ global_free_array(row2);
+
+ return rv;
+}
+
+//-------------------------------------------------
+// set manufacturers
+//-------------------------------------------------
+
+void c_mnfct::set(const char *str)
+{
+ std::string name = getname(str);
+ if (std::find(ui.begin(), ui.end(), name) != ui.end())
+ return;
+
+ ui.push_back(name);
+}
+
+std::string c_mnfct::getname(const char *str)
+{
+ std::string name(str);
+ size_t found = name.find("(");
+
+ if (found != std::string::npos)
+ return (name.substr(0, found - 1));
+ else
+ return name;
+}
+
+//-------------------------------------------------
+// set years
+//-------------------------------------------------
+
+void c_year::set(const char *str)
+{
+ std::string name(str);
+ if (std::find(ui.begin(), ui.end(), name) != ui.end())
+ return;
+
+ ui.push_back(name);
+}
diff --git a/src/frontend/mame/ui/utils.h b/src/frontend/mame/ui/utils.h
new file mode 100644
index 00000000000..d31b3746e77
--- /dev/null
+++ b/src/frontend/mame/ui/utils.h
@@ -0,0 +1,256 @@
+// license:BSD-3-Clause
+// copyright-holders:Maurizio Petrarota
+/***************************************************************************
+
+ ui/utils.h
+
+ Internal UI user interface.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_UTILS_H__
+#define __UI_UTILS_H__
+
+#define MAX_CHAR_INFO 256
+#define MAX_CUST_FILTER 8
+
+// GLOBAL ENUMERATORS
+enum
+{
+ FILTER_FIRST = 0,
+ FILTER_ALL = FILTER_FIRST,
+ FILTER_AVAILABLE,
+ FILTER_UNAVAILABLE,
+ FILTER_WORKING,
+ FILTER_NOT_WORKING,
+ FILTER_MECHANICAL,
+ FILTER_NOT_MECHANICAL,
+ FILTER_CATEGORY,
+ FILTER_FAVORITE,
+ FILTER_BIOS,
+ FILTER_PARENT,
+ FILTER_CLONES,
+ FILTER_MANUFACTURER,
+ FILTER_YEAR,
+ FILTER_SAVE,
+ FILTER_NOSAVE,
+ FILTER_CHD,
+ FILTER_NOCHD,
+ FILTER_VERTICAL,
+ FILTER_HORIZONTAL,
+ FILTER_CUSTOM,
+ FILTER_LAST = FILTER_CUSTOM
+};
+
+enum
+{
+ FIRST_VIEW = 0,
+ SNAPSHOT_VIEW = FIRST_VIEW,
+ CABINETS_VIEW,
+ CPANELS_VIEW,
+ PCBS_VIEW,
+ FLYERS_VIEW,
+ TITLES_VIEW,
+ ENDS_VIEW,
+ ARTPREV_VIEW,
+ BOSSES_VIEW,
+ LOGOS_VIEW,
+ VERSUS_VIEW,
+ GAMEOVER_VIEW,
+ HOWTO_VIEW,
+ SCORES_VIEW,
+ SELECT_VIEW,
+ MARQUEES_VIEW,
+ LAST_VIEW = MARQUEES_VIEW
+};
+
+enum
+{
+ RP_FIRST = 0,
+ RP_IMAGES = RP_FIRST,
+ RP_INFOS,
+ RP_LAST = RP_INFOS
+};
+
+enum
+{
+ SHOW_PANELS = 0,
+ HIDE_LEFT_PANEL,
+ HIDE_RIGHT_PANEL,
+ HIDE_BOTH
+};
+
+enum
+{
+ UI_FIRST_LOAD = 0,
+ UI_GENERAL_LOAD = UI_FIRST_LOAD,
+ UI_HISTORY_LOAD,
+ UI_MAMEINFO_LOAD,
+ UI_SYSINFO_LOAD,
+ UI_MESSINFO_LOAD,
+ UI_COMMAND_LOAD,
+ UI_GINIT_LOAD,
+ UI_STORY_LOAD,
+ UI_LAST_LOAD = UI_STORY_LOAD
+};
+
+enum
+{
+ UI_SW_FIRST = 0,
+ UI_SW_ALL = UI_SW_FIRST,
+ UI_SW_AVAILABLE,
+ UI_SW_UNAVAILABLE,
+ UI_SW_PARENTS,
+ UI_SW_CLONES,
+ UI_SW_YEARS,
+ UI_SW_PUBLISHERS,
+ UI_SW_SUPPORTED,
+ UI_SW_PARTIAL_SUPPORTED,
+ UI_SW_UNSUPPORTED,
+ UI_SW_REGION,
+ UI_SW_TYPE,
+ UI_SW_LIST,
+ UI_SW_CUSTOM,
+ UI_SW_LAST = UI_SW_CUSTOM
+};
+
+enum
+{
+ HOVER_DAT_UP = -1000,
+ HOVER_DAT_DOWN,
+ HOVER_UI_LEFT,
+ HOVER_UI_RIGHT,
+ HOVER_ARROW_UP,
+ HOVER_ARROW_DOWN,
+ HOVER_B_FAV,
+ HOVER_B_EXPORT,
+ HOVER_B_DATS,
+ HOVER_RPANEL_ARROW,
+ HOVER_LPANEL_ARROW,
+ HOVER_FILTER_FIRST,
+ HOVER_FILTER_LAST = (HOVER_FILTER_FIRST) + 1 + FILTER_LAST,
+ HOVER_SW_FILTER_FIRST,
+ HOVER_SW_FILTER_LAST = (HOVER_SW_FILTER_FIRST) + 1 + UI_SW_LAST,
+ HOVER_RP_FIRST,
+ HOVER_RP_LAST = (HOVER_RP_FIRST) + 1 + RP_LAST
+};
+
+// GLOBAL STRUCTURES
+struct ui_software_info
+{
+ ui_software_info() {}
+ ui_software_info(std::string sname, std::string lname, std::string pname, std::string y, std::string pub,
+ UINT8 s, std::string pa, const game_driver *d, std::string li, std::string i, std::string is, UINT8 em,
+ std::string plong, std::string u, std::string de, bool av)
+ {
+ shortname = sname; longname = lname; parentname = pname; year = y; publisher = pub;
+ supported = s; part = pa; driver = d; listname = li; interface = i; instance = is; startempty = em;
+ parentlongname = plong; usage = u; devicetype = de; available = av;
+ }
+ std::string shortname;
+ std::string longname;
+ std::string parentname;
+ std::string year;
+ std::string publisher;
+ UINT8 supported = 0;
+ std::string part;
+ const game_driver *driver = nullptr;
+ std::string listname;
+ std::string interface;
+ std::string instance;
+ UINT8 startempty = 0;
+ std::string parentlongname;
+ std::string usage;
+ std::string devicetype;
+ bool available = false;
+
+ bool operator==(const ui_software_info& r)
+ {
+ if (shortname == r.shortname && longname == r.longname && parentname == r.parentname
+ && year == r.year && publisher == r.publisher && supported == r.supported
+ && part == r.part && driver == r.driver && listname == r.listname
+ && interface == r.interface && instance == r.instance && startempty == r.startempty
+ && parentlongname == r.parentlongname && usage == r.usage && devicetype == r.devicetype)
+ return true;
+
+ return false;
+ }
+};
+
+// Manufacturers
+struct c_mnfct
+{
+ static void set(const char *str);
+ static std::string getname(const char *str);
+ static std::vector<std::string> ui;
+ static UINT16 actual;
+};
+
+// Years
+struct c_year
+{
+ static void set(const char *str);
+ static std::vector<std::string> ui;
+ static UINT16 actual;
+};
+
+// GLOBAL CLASS
+struct ui_globals
+{
+ static UINT8 curimage_view, curdats_view, cur_sw_dats_view, rpanel;
+ static bool switch_image, redraw_icon, default_image, reset;
+ static int visible_main_lines, visible_sw_lines;
+ static UINT16 panels_status;
+ static bool has_icons;
+};
+
+#define main_struct(name) \
+struct name##_filters \
+{ \
+ static UINT16 actual; \
+ static const char *text[]; \
+ static size_t length; \
+};
+
+main_struct(main);
+main_struct(sw);
+
+// Custom filter
+struct custfltr
+{
+ static UINT16 main;
+ static UINT16 numother;
+ static UINT16 other[MAX_CUST_FILTER];
+ static UINT16 mnfct[MAX_CUST_FILTER];
+ static UINT16 screen[MAX_CUST_FILTER];
+ static UINT16 year[MAX_CUST_FILTER];
+};
+
+// Software custom filter
+struct sw_custfltr
+{
+ static UINT16 main;
+ static UINT16 numother;
+ static UINT16 other[MAX_CUST_FILTER];
+ static UINT16 mnfct[MAX_CUST_FILTER];
+ static UINT16 year[MAX_CUST_FILTER];
+ static UINT16 region[MAX_CUST_FILTER];
+ static UINT16 type[MAX_CUST_FILTER];
+ static UINT16 list[MAX_CUST_FILTER];
+};
+
+// GLOBAL FUNCTIONS
+
+// advanced search function
+int fuzzy_substring(std::string needle, std::string haystack);
+
+// trim carriage return
+char* chartrimcarriage(char str[]);
+
+const char* strensure(const char* s);
+
+int getprecisionchr(const char* s);
+
+#endif /* __UI_UTILS_H__ */
diff --git a/src/frontend/mame/ui/videoopt.cpp b/src/frontend/mame/ui/videoopt.cpp
new file mode 100644
index 00000000000..f0f54a20702
--- /dev/null
+++ b/src/frontend/mame/ui/videoopt.cpp
@@ -0,0 +1,232 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/*********************************************************************
+
+ ui/videoopt.cpp
+
+ Internal menus for video options
+
+*********************************************************************/
+
+#include "emu.h"
+#include "rendutil.h"
+
+#include "ui/menu.h"
+#include "ui/videoopt.h"
+
+/*-------------------------------------------------
+ menu_video_targets - handle the video targets
+ menu
+-------------------------------------------------*/
+
+void ui_menu_video_targets::handle()
+{
+ /* process the menu */
+ const ui_menu_event *menu_event = process(0);
+ if (menu_event != nullptr && menu_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(global_alloc_clear<ui_menu_video_options>(machine(), container, static_cast<render_target *>(menu_event->itemref)));
+}
+
+
+/*-------------------------------------------------
+ menu_video_targets_populate - populate the
+ video targets menu
+-------------------------------------------------*/
+
+ui_menu_video_targets::ui_menu_video_targets(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+void ui_menu_video_targets::populate()
+{
+ int targetnum;
+
+ /* find the targets */
+ for (targetnum = 0; ; targetnum++)
+ {
+ render_target *target = machine().render().target_by_index(targetnum);
+ char buffer[40];
+
+ /* stop when we run out */
+ if (target == nullptr)
+ break;
+
+ /* add a menu item */
+ sprintf(buffer, _("Screen #%d"), targetnum);
+ item_append(buffer, nullptr, 0, target);
+ }
+}
+
+ui_menu_video_targets::~ui_menu_video_targets()
+{
+}
+
+/*-------------------------------------------------
+ menu_video_options - handle the video options
+ menu
+-------------------------------------------------*/
+
+void ui_menu_video_options::handle()
+{
+ bool changed = false;
+
+ /* process the menu */
+ const ui_menu_event *menu_event = process(0);
+ if (menu_event != nullptr && menu_event->itemref != nullptr)
+ {
+ switch ((FPTR)menu_event->itemref)
+ {
+ /* rotate adds rotation depending on the direction */
+ case VIDEO_ITEM_ROTATE:
+ if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
+ {
+ int delta = (menu_event->iptkey == IPT_UI_LEFT) ? ROT270 : ROT90;
+ target->set_orientation(orientation_add(delta, target->orientation()));
+ if (target->is_ui_target())
+ {
+ render_container::user_settings settings;
+ container->get_user_settings(settings);
+ settings.m_orientation = orientation_add(delta ^ ROT180, settings.m_orientation);
+ container->set_user_settings(settings);
+ }
+ changed = true;
+ }
+ break;
+
+ /* layer config bitmasks handle left/right keys the same (toggle) */
+ case VIDEO_ITEM_BACKDROPS:
+ if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
+ {
+ target->set_backdrops_enabled(!target->backdrops_enabled());
+ changed = true;
+ }
+ break;
+
+ case VIDEO_ITEM_OVERLAYS:
+ if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
+ {
+ target->set_overlays_enabled(!target->overlays_enabled());
+ changed = true;
+ }
+ break;
+
+ case VIDEO_ITEM_BEZELS:
+ if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
+ {
+ target->set_bezels_enabled(!target->bezels_enabled());
+ changed = true;
+ }
+ break;
+
+ case VIDEO_ITEM_CPANELS:
+ if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
+ {
+ target->set_cpanels_enabled(!target->cpanels_enabled());
+ changed = true;
+ }
+ break;
+
+ case VIDEO_ITEM_MARQUEES:
+ if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
+ {
+ target->set_marquees_enabled(!target->marquees_enabled());
+ changed = true;
+ }
+ break;
+
+ case VIDEO_ITEM_ZOOM:
+ if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
+ {
+ target->set_zoom_to_screen(!target->zoom_to_screen());
+ changed = true;
+ }
+ break;
+
+ /* anything else is a view item */
+ default:
+ if (menu_event->iptkey == IPT_UI_SELECT && (int)(FPTR)menu_event->itemref >= VIDEO_ITEM_VIEW)
+ {
+ target->set_view((FPTR)menu_event->itemref - VIDEO_ITEM_VIEW);
+ changed = true;
+ }
+ break;
+ }
+ }
+
+ /* if something changed, rebuild the menu */
+ if (changed)
+ reset(UI_MENU_RESET_REMEMBER_REF);
+}
+
+
+/*-------------------------------------------------
+ menu_video_options_populate - populate the
+ video options menu
+-------------------------------------------------*/
+
+ui_menu_video_options::ui_menu_video_options(running_machine &machine, render_container *container, render_target *_target) : ui_menu(machine, container)
+{
+ target = _target;
+}
+
+void ui_menu_video_options::populate()
+{
+ const char *subtext = "";
+ std::string tempstring;
+ int viewnum;
+ int enabled;
+
+ /* add items for each view */
+ for (viewnum = 0; ; viewnum++)
+ {
+ const char *name = target->view_name(viewnum);
+ if (name == nullptr)
+ break;
+
+ /* create a string for the item, replacing underscores with spaces */
+ tempstring.assign(name);
+ strreplace(tempstring, "_", " ");
+ item_append(tempstring.c_str(), nullptr, 0, (void *)(FPTR)(VIDEO_ITEM_VIEW + viewnum));
+ }
+
+ /* add a separator */
+ item_append(ui_menu_item_type::SEPARATOR);
+
+ /* add a rotate item */
+ switch (target->orientation())
+ {
+ case ROT0: subtext = "None"; break;
+ case ROT90: subtext = "CW 90" UTF8_DEGREES; break;
+ case ROT180: subtext = "180" UTF8_DEGREES; break;
+ case ROT270: subtext = "CCW 90" UTF8_DEGREES; break;
+ }
+ item_append(_("Rotate"), subtext, MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW, (void *)VIDEO_ITEM_ROTATE);
+
+ /* backdrop item */
+ enabled = target->backdrops_enabled();
+ item_append(_("Backdrops"), enabled ? _("Enabled") : _("Disabled"), enabled ? MENU_FLAG_LEFT_ARROW : MENU_FLAG_RIGHT_ARROW, (void *)VIDEO_ITEM_BACKDROPS);
+
+ /* overlay item */
+ enabled = target->overlays_enabled();
+ item_append(_("Overlays"), enabled ? _("Enabled") : _("Disabled"), enabled ? MENU_FLAG_LEFT_ARROW : MENU_FLAG_RIGHT_ARROW, (void *)VIDEO_ITEM_OVERLAYS);
+
+ /* bezel item */
+ enabled = target->bezels_enabled();
+ item_append(_("Bezels"), enabled ? _("Enabled") : _("Disabled"), enabled ? MENU_FLAG_LEFT_ARROW : MENU_FLAG_RIGHT_ARROW, (void *)VIDEO_ITEM_BEZELS);
+
+ /* cpanel item */
+ enabled = target->cpanels_enabled();
+ item_append(_("CPanels"), enabled ? _("Enabled") : _("Disabled"), enabled ? MENU_FLAG_LEFT_ARROW : MENU_FLAG_RIGHT_ARROW, (void *)VIDEO_ITEM_CPANELS);
+
+ /* marquee item */
+ enabled = target->marquees_enabled();
+ item_append(_("Marquees"), enabled ? _("Enabled") : _("Disabled"), enabled ? MENU_FLAG_LEFT_ARROW : MENU_FLAG_RIGHT_ARROW, (void *)VIDEO_ITEM_MARQUEES);
+
+ /* cropping */
+ enabled = target->zoom_to_screen();
+ item_append(_("View"), enabled ? _("Cropped") : _("Full"), enabled ? MENU_FLAG_RIGHT_ARROW : MENU_FLAG_LEFT_ARROW, (void *)VIDEO_ITEM_ZOOM);
+}
+
+ui_menu_video_options::~ui_menu_video_options()
+{
+}
diff --git a/src/frontend/mame/ui/videoopt.h b/src/frontend/mame/ui/videoopt.h
new file mode 100644
index 00000000000..802f1295c08
--- /dev/null
+++ b/src/frontend/mame/ui/videoopt.h
@@ -0,0 +1,48 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/***************************************************************************
+
+ ui/videoopt.h
+
+ Internal menus for video options
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_VIDEOOPT_H__
+#define __UI_VIDEOOPT_H__
+
+
+class ui_menu_video_targets : public ui_menu {
+public:
+ ui_menu_video_targets(running_machine &machine, render_container *container);
+ virtual ~ui_menu_video_targets();
+ virtual void populate() override;
+ virtual void handle() override;
+};
+
+class ui_menu_video_options : public ui_menu {
+public:
+ ui_menu_video_options(running_machine &machine, render_container *container, render_target *target);
+ virtual ~ui_menu_video_options();
+ virtual void populate() override;
+ virtual void handle() override;
+
+private:
+ enum {
+ VIDEO_ITEM_ROTATE = 0x80000000,
+ VIDEO_ITEM_BACKDROPS,
+ VIDEO_ITEM_OVERLAYS,
+ VIDEO_ITEM_BEZELS,
+ VIDEO_ITEM_CPANELS,
+ VIDEO_ITEM_MARQUEES,
+ VIDEO_ITEM_ZOOM,
+ VIDEO_ITEM_VIEW
+ };
+
+ render_target *target;
+};
+
+
+#endif /* __UI_VIDEOOPT_H__ */
diff --git a/src/frontend/mame/ui/viewgfx.cpp b/src/frontend/mame/ui/viewgfx.cpp
new file mode 100644
index 00000000000..2a49b00983d
--- /dev/null
+++ b/src/frontend/mame/ui/viewgfx.cpp
@@ -0,0 +1,1162 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/*********************************************************************
+
+ ui/viewgfx.cpp
+
+ Internal graphics viewer.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "ui/ui.h"
+#include "uiinput.h"
+#include "render.h"
+#include "rendfont.h"
+#include "rendutil.h"
+#include "ui/viewgfx.h"
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+enum ui_gfx_modes
+{
+ UI_GFX_PALETTE = 0,
+ UI_GFX_GFXSET,
+ UI_GFX_TILEMAP
+};
+
+const int MAX_GFX_DECODERS = 8;
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+// information about a single gfx device
+struct ui_gfx_info
+{
+ device_gfx_interface *interface; // pointer to device's gfx interface
+ UINT8 setcount; // how many gfx sets device has
+ UINT8 rotate[MAX_GFX_ELEMENTS]; // current rotation (orientation) value
+ UINT8 columns[MAX_GFX_ELEMENTS]; // number of items per row
+ int offset[MAX_GFX_ELEMENTS]; // current offset of top,left item
+ int color[MAX_GFX_ELEMENTS]; // current color selected
+};
+
+struct ui_gfx_state
+{
+ bool started; // have we called ui_gfx_count_devices() yet?
+ UINT8 mode; // which mode are we in?
+
+ // intermediate bitmaps
+ bool bitmap_dirty; // is the bitmap dirty?
+ bitmap_rgb32 * bitmap; // bitmap for drawing gfx and tilemaps
+ render_texture *texture; // texture for rendering the above bitmap
+
+ // palette-specific data
+ struct
+ {
+ palette_device *device; // pointer to current device
+ int devcount; // how many palette devices exist
+ int devindex; // which palette device is visible
+ UINT8 which; // which subset (pens or indirect colors)?
+ UINT8 columns; // number of items per row
+ int offset; // current offset of top left item
+ } palette;
+
+ // graphics-specific data
+ struct
+ {
+ UINT8 devcount; // how many gfx devices exist
+ UINT8 devindex; // which device is visible
+ UINT8 set; // which set is visible
+ } gfxset;
+
+ // information about each gfx device
+ ui_gfx_info gfxdev[MAX_GFX_DECODERS];
+
+ // tilemap-specific data
+ struct
+ {
+ int which; // which tilemap are we viewing?
+ int xoffs; // current X offset
+ int yoffs; // current Y offset
+ int zoom; // zoom factor
+ UINT8 rotate; // current rotation (orientation) value
+ } tilemap;
+};
+
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+static ui_gfx_state ui_gfx;
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void ui_gfx_count_devices(running_machine &machine, ui_gfx_state &state);
+static void ui_gfx_exit(running_machine &machine);
+
+// palette handling
+static void palette_set_device(running_machine &machine, ui_gfx_state &state);
+static void palette_handle_keys(running_machine &machine, ui_gfx_state &state);
+static void palette_handler(running_machine &machine, render_container *container, ui_gfx_state &state);
+
+// graphics set handling
+static void gfxset_handle_keys(running_machine &machine, ui_gfx_state &state, int xcells, int ycells);
+static void gfxset_draw_item(running_machine &machine, gfx_element &gfx, int index, bitmap_rgb32 &bitmap, int dstx, int dsty, int color, int rotate);
+static void gfxset_update_bitmap(running_machine &machine, ui_gfx_state &state, int xcells, int ycells, gfx_element &gfx);
+static void gfxset_handler(running_machine &machine, render_container *container, ui_gfx_state &state);
+
+// tilemap handling
+static void tilemap_handle_keys(running_machine &machine, ui_gfx_state &state, int viswidth, int visheight);
+static void tilemap_update_bitmap(running_machine &machine, ui_gfx_state &state, int width, int height);
+static void tilemap_handler(running_machine &machine, render_container *container, ui_gfx_state &state);
+
+
+
+/***************************************************************************
+ CORE IMPLEMENTATION
+***************************************************************************/
+
+//-------------------------------------------------
+// ui_gfx_init - initialize the graphics viewer
+//-------------------------------------------------
+
+void ui_gfx_init(running_machine &machine)
+{
+ ui_gfx_state *state = &ui_gfx;
+ int rotate = machine.system().flags & ORIENTATION_MASK;
+
+ // make sure we clean up after ourselves
+ machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(ui_gfx_exit), &machine));
+
+ // initialize our global state
+ memset(state, 0, sizeof(*state));
+
+ // set up the palette state
+ state->palette.columns = 16;
+
+ // set up the graphics state
+ for (int i = 0; i < MAX_GFX_DECODERS; i++)
+ for (int j = 0; j < MAX_GFX_ELEMENTS; j++)
+ {
+ state->gfxdev[i].rotate[j] = rotate;
+ state->gfxdev[i].columns[j] = 16;
+ }
+
+ // set up the tilemap state
+ state->tilemap.rotate = rotate;
+}
+
+
+//-------------------------------------------------
+// ui_gfx_count_devices - count the palettes,
+// gfx decoders and gfx sets in the machine
+//-------------------------------------------------
+
+static void ui_gfx_count_devices(running_machine &machine, ui_gfx_state &state)
+{
+ // count the palette devices
+ state.palette.devcount = palette_device_iterator(machine.root_device()).count();
+
+ // set the pointer to the first palette
+ if (state.palette.devcount > 0)
+ palette_set_device(machine, state);
+
+ // count the gfx devices
+ state.gfxset.devcount = 0;
+ for (device_gfx_interface &interface : gfx_interface_iterator(machine.root_device()))
+ {
+ // count the gfx sets in each device, skipping devices with none
+ int count = 0;
+ while (count < MAX_GFX_ELEMENTS && interface.gfx(count) != nullptr)
+ count++;
+
+ // count = index of first NULL
+ if (count > 0)
+ {
+ state.gfxdev[state.gfxset.devcount].interface = &interface;
+ state.gfxdev[state.gfxset.devcount].setcount = count;
+ if (++state.gfxset.devcount == MAX_GFX_DECODERS)
+ break;
+ }
+ }
+
+ state.started = true;
+}
+
+
+//-------------------------------------------------
+// ui_gfx_exit - clean up after ourselves
+//-------------------------------------------------
+
+static void ui_gfx_exit(running_machine &machine)
+{
+ // free the texture
+ machine.render().texture_free(ui_gfx.texture);
+ ui_gfx.texture = nullptr;
+
+ // free the bitmap
+ global_free(ui_gfx.bitmap);
+ ui_gfx.bitmap = nullptr;
+}
+
+
+//-------------------------------------------------
+// ui_gfx_is_relevant - returns 'true' if the
+// internal graphics viewer has relevance
+//
+// NOTE: this must not be called before machine
+// initialization is complete, as some drivers
+// create or modify gfx sets in VIDEO_START
+//-------------------------------------------------
+
+bool ui_gfx_is_relevant(running_machine &machine)
+{
+ ui_gfx_state &state = ui_gfx;
+
+ if (!state.started)
+ ui_gfx_count_devices(machine, state);
+
+ return state.palette.devcount > 0
+ || state.gfxset.devcount > 0
+ || machine.tilemap().count() > 0;
+}
+
+
+//-------------------------------------------------
+// ui_gfx_ui_handler - primary UI handler
+//-------------------------------------------------
+
+UINT32 ui_gfx_ui_handler(running_machine &machine, render_container *container, UINT32 uistate)
+{
+ ui_gfx_state &state = ui_gfx;
+
+ // if we have nothing, implicitly cancel
+ if (!ui_gfx_is_relevant(machine))
+ goto cancel;
+
+ // if we're not paused, mark the bitmap dirty
+ if (!machine.paused())
+ state.bitmap_dirty = true;
+
+ // switch off the state to display something
+again:
+ switch (state.mode)
+ {
+ case UI_GFX_PALETTE:
+ // if we have a palette, display it
+ if (state.palette.devcount > 0)
+ {
+ palette_handler(machine, container, state);
+ break;
+ }
+
+ // fall through...
+ state.mode++;
+
+ case UI_GFX_GFXSET:
+ // if we have graphics sets, display them
+ if (state.gfxset.devcount > 0)
+ {
+ gfxset_handler(machine, container, state);
+ break;
+ }
+
+ // fall through...
+ state.mode++;
+
+ case UI_GFX_TILEMAP:
+ // if we have tilemaps, display them
+ if (machine.tilemap().count() > 0)
+ {
+ tilemap_handler(machine, container, state);
+ break;
+ }
+
+ state.mode = UI_GFX_PALETTE;
+ goto again;
+ }
+
+ // handle keys
+ if (machine.ui_input().pressed(IPT_UI_SELECT))
+ {
+ state.mode = (state.mode + 1) % 3;
+ state.bitmap_dirty = true;
+ }
+
+ if (machine.ui_input().pressed(IPT_UI_PAUSE))
+ {
+ if (machine.paused())
+ machine.resume();
+ else
+ machine.pause();
+ }
+
+ if (machine.ui_input().pressed(IPT_UI_CANCEL) || machine.ui_input().pressed(IPT_UI_SHOW_GFX))
+ goto cancel;
+
+ return uistate;
+
+cancel:
+ if (!uistate)
+ machine.resume();
+ state.bitmap_dirty = true;
+ return UI_HANDLER_CANCEL;
+}
+
+
+
+/***************************************************************************
+ PALETTE VIEWER
+***************************************************************************/
+
+//-------------------------------------------------
+// palette_set_device - set the pointer to the
+// current palette device
+//-------------------------------------------------
+
+static void palette_set_device(running_machine &machine, ui_gfx_state &state)
+{
+ palette_device_iterator pal_iter(machine.root_device());
+ state.palette.device = pal_iter.byindex(state.palette.devindex);
+}
+
+
+//-------------------------------------------------
+// palette_handler - handler for the palette
+// viewer
+//-------------------------------------------------
+
+static void palette_handler(running_machine &machine, render_container *container, ui_gfx_state &state)
+{
+ palette_device *palette = state.palette.device;
+
+ int total = state.palette.which ? palette->indirect_entries() : palette->entries();
+ const rgb_t *raw_color = palette->palette()->entry_list_raw();
+ render_font *ui_font = mame_machine_manager::instance()->ui().get_font();
+ float cellwidth, cellheight;
+ float chwidth, chheight;
+ float titlewidth;
+ float x0, y0;
+ render_bounds cellboxbounds;
+ render_bounds boxbounds;
+ int x, y, skip;
+ char title[100];
+
+ // add a half character padding for the box
+ chheight = mame_machine_manager::instance()->ui().get_line_height();
+ chwidth = ui_font->char_width(chheight, machine.render().ui_aspect(), '0');
+ boxbounds.x0 = 0.0f + 0.5f * chwidth;
+ boxbounds.x1 = 1.0f - 0.5f * chwidth;
+ boxbounds.y0 = 0.0f + 0.5f * chheight;
+ boxbounds.y1 = 1.0f - 0.5f * chheight;
+
+ // the character cell box bounds starts a half character in from the box
+ cellboxbounds = boxbounds;
+ cellboxbounds.x0 += 0.5f * chwidth;
+ cellboxbounds.x1 -= 0.5f * chwidth;
+ cellboxbounds.y0 += 0.5f * chheight;
+ cellboxbounds.y1 -= 0.5f * chheight;
+
+ // add space on the left for 5 characters of text, plus a half character of padding
+ cellboxbounds.x0 += 5.5f * chwidth;
+
+ // add space on the top for a title, a half line of padding, a header, and another half line
+ cellboxbounds.y0 += 3.0f * chheight;
+
+ // figure out the title and expand the outer box to fit
+ const char *suffix = palette->indirect_entries() == 0 ? "" : state.palette.which ? _(" COLORS") : _(" PENS");
+ sprintf(title, "'%s'%s", palette->tag(), suffix);
+ titlewidth = ui_font->string_width(chheight, machine.render().ui_aspect(), title);
+ x0 = 0.0f;
+ if (boxbounds.x1 - boxbounds.x0 < titlewidth + chwidth)
+ x0 = boxbounds.x0 - (0.5f - 0.5f * (titlewidth + chwidth));
+
+ // go ahead and draw the outer box now
+ mame_machine_manager::instance()->ui().draw_outlined_box(container, boxbounds.x0 - x0, boxbounds.y0, boxbounds.x1 + x0, boxbounds.y1, UI_GFXVIEWER_BG_COLOR);
+
+ // draw the title
+ x0 = 0.5f - 0.5f * titlewidth;
+ y0 = boxbounds.y0 + 0.5f * chheight;
+ for (x = 0; title[x] != 0; x++)
+ {
+ container->add_char(x0, y0, chheight, machine.render().ui_aspect(), ARGB_WHITE, *ui_font, title[x]);
+ x0 += ui_font->char_width(chheight, machine.render().ui_aspect(), title[x]);
+ }
+
+ // compute the cell size
+ cellwidth = (cellboxbounds.x1 - cellboxbounds.x0) / (float)state.palette.columns;
+ cellheight = (cellboxbounds.y1 - cellboxbounds.y0) / (float)state.palette.columns;
+
+ // draw the top column headers
+ skip = (int)(chwidth / cellwidth);
+ for (x = 0; x < state.palette.columns; x += 1 + skip)
+ {
+ x0 = boxbounds.x0 + 6.0f * chwidth + (float)x * cellwidth;
+ y0 = boxbounds.y0 + 2.0f * chheight;
+ container->add_char(x0 + 0.5f * (cellwidth - chwidth), y0, chheight, machine.render().ui_aspect(), ARGB_WHITE, *ui_font, "0123456789ABCDEF"[x & 0xf]);
+
+ // if we're skipping, draw a point between the character and the box to indicate which
+ // one it's referring to
+ if (skip != 0)
+ container->add_point(x0 + 0.5f * cellwidth, 0.5f * (y0 + chheight + cellboxbounds.y0), UI_LINE_WIDTH, ARGB_WHITE, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ }
+
+ // draw the side column headers
+ skip = (int)(chheight / cellheight);
+ for (y = 0; y < state.palette.columns; y += 1 + skip)
+
+ // only display if there is data to show
+ if (state.palette.offset + y * state.palette.columns < total)
+ {
+ char buffer[10];
+
+ // if we're skipping, draw a point between the character and the box to indicate which
+ // one it's referring to
+ x0 = boxbounds.x0 + 5.5f * chwidth;
+ y0 = boxbounds.y0 + 3.5f * chheight + (float)y * cellheight;
+ if (skip != 0)
+ container->add_point(0.5f * (x0 + cellboxbounds.x0), y0 + 0.5f * cellheight, UI_LINE_WIDTH, ARGB_WHITE, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+
+ // draw the row header
+ sprintf(buffer, "%5X", state.palette.offset + y * state.palette.columns);
+ for (x = 4; x >= 0; x--)
+ {
+ x0 -= ui_font->char_width(chheight, machine.render().ui_aspect(), buffer[x]);
+ container->add_char(x0, y0 + 0.5f * (cellheight - chheight), chheight, machine.render().ui_aspect(), ARGB_WHITE, *ui_font, buffer[x]);
+ }
+ }
+
+ // now add the rectangles for the colors
+ for (y = 0; y < state.palette.columns; y++)
+ for (x = 0; x < state.palette.columns; x++)
+ {
+ int index = state.palette.offset + y * state.palette.columns + x;
+ if (index < total)
+ {
+ pen_t pen = state.palette.which ? palette->indirect_color(index) : raw_color[index];
+ container->add_rect(cellboxbounds.x0 + x * cellwidth, cellboxbounds.y0 + y * cellheight,
+ cellboxbounds.x0 + (x + 1) * cellwidth, cellboxbounds.y0 + (y + 1) * cellheight,
+ 0xff000000 | pen, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ }
+ }
+
+ // handle keys
+ palette_handle_keys(machine, state);
+}
+
+
+//-------------------------------------------------
+// palette_handle_keys - handle key inputs for
+// the palette viewer
+//-------------------------------------------------
+
+static void palette_handle_keys(running_machine &machine, ui_gfx_state &state)
+{
+ palette_device *palette = state.palette.device;
+ int rowcount, screencount;
+ int total;
+
+ // handle zoom (minus,plus)
+ if (machine.ui_input().pressed(IPT_UI_ZOOM_OUT))
+ state.palette.columns /= 2;
+ if (machine.ui_input().pressed(IPT_UI_ZOOM_IN))
+ state.palette.columns *= 2;
+
+ // clamp within range
+ if (state.palette.columns <= 4)
+ state.palette.columns = 4;
+ if (state.palette.columns > 64)
+ state.palette.columns = 64;
+
+ // handle colormap selection (open bracket,close bracket)
+ if (machine.ui_input().pressed(IPT_UI_PREV_GROUP))
+ {
+ if (state.palette.which)
+ state.palette.which = 0;
+ else if (state.palette.devindex > 0)
+ {
+ state.palette.devindex--;
+ palette_set_device(machine, state);
+ palette = state.palette.device;
+ state.palette.which = (palette->indirect_entries() > 0);
+ }
+ }
+ if (machine.ui_input().pressed(IPT_UI_NEXT_GROUP))
+ {
+ if (!state.palette.which && palette->indirect_entries() > 0)
+ state.palette.which = 1;
+ else if (state.palette.devindex < state.palette.devcount - 1)
+ {
+ state.palette.devindex++;
+ palette_set_device(machine, state);
+ palette = state.palette.device;
+ state.palette.which = 0;
+ }
+ }
+
+ // cache some info in locals
+ total = state.palette.which ? palette->indirect_entries() : palette->entries();
+
+ // determine number of entries per row and total
+ rowcount = state.palette.columns;
+ screencount = rowcount * rowcount;
+
+ // handle keyboard navigation
+ if (machine.ui_input().pressed_repeat(IPT_UI_UP, 4))
+ state.palette.offset -= rowcount;
+ if (machine.ui_input().pressed_repeat(IPT_UI_DOWN, 4))
+ state.palette.offset += rowcount;
+ if (machine.ui_input().pressed_repeat(IPT_UI_PAGE_UP, 6))
+ state.palette.offset -= screencount;
+ if (machine.ui_input().pressed_repeat(IPT_UI_PAGE_DOWN, 6))
+ state.palette.offset += screencount;
+ if (machine.ui_input().pressed_repeat(IPT_UI_HOME, 4))
+ state.palette.offset = 0;
+ if (machine.ui_input().pressed_repeat(IPT_UI_END, 4))
+ state.palette.offset = total;
+
+ // clamp within range
+ if (state.palette.offset + screencount > ((total + rowcount - 1) / rowcount) * rowcount)
+ state.palette.offset = ((total + rowcount - 1) / rowcount) * rowcount - screencount;
+ if (state.palette.offset < 0)
+ state.palette.offset = 0;
+}
+
+
+
+/***************************************************************************
+ GRAPHICS VIEWER
+***************************************************************************/
+
+//-------------------------------------------------
+// gfxset_handler - handler for the graphics
+// viewer
+//-------------------------------------------------
+
+static void gfxset_handler(running_machine &machine, render_container *container, ui_gfx_state &state)
+{
+ render_font *ui_font = mame_machine_manager::instance()->ui().get_font();
+ int dev = state.gfxset.devindex;
+ int set = state.gfxset.set;
+ ui_gfx_info &info = state.gfxdev[dev];
+ device_gfx_interface &interface = *info.interface;
+ gfx_element &gfx = *interface.gfx(set);
+ float fullwidth, fullheight;
+ float cellwidth, cellheight;
+ float chwidth, chheight;
+ float titlewidth;
+ //float cellaspect;
+ float x0, y0;
+ render_bounds cellboxbounds;
+ render_bounds boxbounds;
+ int cellboxwidth, cellboxheight;
+ int targwidth = machine.render().ui_target().width();
+ int targheight = machine.render().ui_target().height();
+ int cellxpix, cellypix;
+ int xcells, ycells;
+ int pixelscale = 0;
+ int x, y, skip;
+ char title[100];
+
+ // add a half character padding for the box
+ chheight = mame_machine_manager::instance()->ui().get_line_height();
+ chwidth = ui_font->char_width(chheight, machine.render().ui_aspect(), '0');
+ boxbounds.x0 = 0.0f + 0.5f * chwidth;
+ boxbounds.x1 = 1.0f - 0.5f * chwidth;
+ boxbounds.y0 = 0.0f + 0.5f * chheight;
+ boxbounds.y1 = 1.0f - 0.5f * chheight;
+
+ // the character cell box bounds starts a half character in from the box
+ cellboxbounds = boxbounds;
+ cellboxbounds.x0 += 0.5f * chwidth;
+ cellboxbounds.x1 -= 0.5f * chwidth;
+ cellboxbounds.y0 += 0.5f * chheight;
+ cellboxbounds.y1 -= 0.5f * chheight;
+
+ // add space on the left for 5 characters of text, plus a half character of padding
+ cellboxbounds.x0 += 5.5f * chwidth;
+
+ // add space on the top for a title, a half line of padding, a header, and another half line
+ cellboxbounds.y0 += 3.0f * chheight;
+
+ // convert back to pixels
+ cellboxwidth = (cellboxbounds.x1 - cellboxbounds.x0) * (float)targwidth;
+ cellboxheight = (cellboxbounds.y1 - cellboxbounds.y0) * (float)targheight;
+
+ // compute the number of source pixels in a cell
+ cellxpix = 1 + ((info.rotate[set] & ORIENTATION_SWAP_XY) ? gfx.height() : gfx.width());
+ cellypix = 1 + ((info.rotate[set] & ORIENTATION_SWAP_XY) ? gfx.width() : gfx.height());
+
+ // compute the largest pixel scale factor that still fits
+ xcells = info.columns[set];
+ while (xcells > 1)
+ {
+ pixelscale = (cellboxwidth / xcells) / cellxpix;
+ if (pixelscale != 0)
+ break;
+ xcells--;
+ }
+ info.columns[set] = xcells;
+
+ // worst case, we need a pixel scale of 1
+ pixelscale = MAX(1, pixelscale);
+
+ // in the Y direction, we just display as many as we can
+ ycells = cellboxheight / (pixelscale * cellypix);
+
+ // now determine the actual cellbox size
+ cellboxwidth = MIN(cellboxwidth, xcells * pixelscale * cellxpix);
+ cellboxheight = MIN(cellboxheight, ycells * pixelscale * cellypix);
+
+ // compute the size of a single cell at this pixel scale factor, as well as the aspect ratio
+ cellwidth = (cellboxwidth / (float)xcells) / (float)targwidth;
+ cellheight = (cellboxheight / (float)ycells) / (float)targheight;
+ //cellaspect = cellwidth / cellheight;
+
+ // working from the new width/height, recompute the boxbounds
+ fullwidth = (float)cellboxwidth / (float)targwidth + 6.5f * chwidth;
+ fullheight = (float)cellboxheight / (float)targheight + 4.0f * chheight;
+
+ // recompute boxbounds from this
+ boxbounds.x0 = (1.0f - fullwidth) * 0.5f;
+ boxbounds.x1 = boxbounds.x0 + fullwidth;
+ boxbounds.y0 = (1.0f - fullheight) * 0.5f;
+ boxbounds.y1 = boxbounds.y0 + fullheight;
+
+ // figure out the title and expand the outer box to fit
+ sprintf(title, "'%s' %d/%d %dx%d COLOR %X",
+ interface.device().tag(),
+ set, info.setcount - 1,
+ gfx.width(), gfx.height(),
+ info.color[set]);
+ titlewidth = ui_font->string_width(chheight, machine.render().ui_aspect(), title);
+ x0 = 0.0f;
+ if (boxbounds.x1 - boxbounds.x0 < titlewidth + chwidth)
+ x0 = boxbounds.x0 - (0.5f - 0.5f * (titlewidth + chwidth));
+
+ // go ahead and draw the outer box now
+ mame_machine_manager::instance()->ui().draw_outlined_box(container, boxbounds.x0 - x0, boxbounds.y0, boxbounds.x1 + x0, boxbounds.y1, UI_GFXVIEWER_BG_COLOR);
+
+ // draw the title
+ x0 = 0.5f - 0.5f * titlewidth;
+ y0 = boxbounds.y0 + 0.5f * chheight;
+ for (x = 0; title[x] != 0; x++)
+ {
+ container->add_char(x0, y0, chheight, machine.render().ui_aspect(), ARGB_WHITE, *ui_font, title[x]);
+ x0 += ui_font->char_width(chheight, machine.render().ui_aspect(), title[x]);
+ }
+
+ // draw the top column headers
+ skip = (int)(chwidth / cellwidth);
+ for (x = 0; x < xcells; x += 1 + skip)
+ {
+ x0 = boxbounds.x0 + 6.0f * chwidth + (float)x * cellwidth;
+ y0 = boxbounds.y0 + 2.0f * chheight;
+ container->add_char(x0 + 0.5f * (cellwidth - chwidth), y0, chheight, machine.render().ui_aspect(), ARGB_WHITE, *ui_font, "0123456789ABCDEF"[x & 0xf]);
+
+ // if we're skipping, draw a point between the character and the box to indicate which
+ // one it's referring to
+ if (skip != 0)
+ container->add_point(x0 + 0.5f * cellwidth, 0.5f * (y0 + chheight + boxbounds.y0 + 3.5f * chheight), UI_LINE_WIDTH, ARGB_WHITE, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ }
+
+ // draw the side column headers
+ skip = (int)(chheight / cellheight);
+ for (y = 0; y < ycells; y += 1 + skip)
+
+ // only display if there is data to show
+ if (info.offset[set] + y * xcells < gfx.elements())
+ {
+ char buffer[10];
+
+ // if we're skipping, draw a point between the character and the box to indicate which
+ // one it's referring to
+ x0 = boxbounds.x0 + 5.5f * chwidth;
+ y0 = boxbounds.y0 + 3.5f * chheight + (float)y * cellheight;
+ if (skip != 0)
+ container->add_point(0.5f * (x0 + boxbounds.x0 + 6.0f * chwidth), y0 + 0.5f * cellheight, UI_LINE_WIDTH, ARGB_WHITE, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+
+ // draw the row header
+ sprintf(buffer, "%5X", info.offset[set] + y * xcells);
+ for (x = 4; x >= 0; x--)
+ {
+ x0 -= ui_font->char_width(chheight, machine.render().ui_aspect(), buffer[x]);
+ container->add_char(x0, y0 + 0.5f * (cellheight - chheight), chheight, machine.render().ui_aspect(), ARGB_WHITE, *ui_font, buffer[x]);
+ }
+ }
+
+ // update the bitmap
+ gfxset_update_bitmap(machine, state, xcells, ycells, gfx);
+
+ // add the final quad
+ container->add_quad(boxbounds.x0 + 6.0f * chwidth, boxbounds.y0 + 3.5f * chheight,
+ boxbounds.x0 + 6.0f * chwidth + (float)cellboxwidth / (float)targwidth,
+ boxbounds.y0 + 3.5f * chheight + (float)cellboxheight / (float)targheight,
+ ARGB_WHITE, state.texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+
+ // handle keyboard navigation before drawing
+ gfxset_handle_keys(machine, state, xcells, ycells);
+}
+
+
+//-------------------------------------------------
+// gfxset_handle_keys - handle keys for the
+// graphics viewer
+//-------------------------------------------------
+
+static void gfxset_handle_keys(running_machine &machine, ui_gfx_state &state, int xcells, int ycells)
+{
+ // handle gfxset selection (open bracket,close bracket)
+ if (machine.ui_input().pressed(IPT_UI_PREV_GROUP))
+ {
+ if (state.gfxset.set > 0)
+ state.gfxset.set--;
+ else if (state.gfxset.devindex > 0)
+ {
+ state.gfxset.devindex--;
+ state.gfxset.set = state.gfxdev[state.gfxset.devindex].setcount - 1;
+ }
+ state.bitmap_dirty = true;
+ }
+ if (machine.ui_input().pressed(IPT_UI_NEXT_GROUP))
+ {
+ if (state.gfxset.set < state.gfxdev[state.gfxset.devindex].setcount - 1)
+ state.gfxset.set++;
+ else if (state.gfxset.devindex < state.gfxset.devcount - 1)
+ {
+ state.gfxset.devindex++;
+ state.gfxset.set = 0;
+ }
+ state.bitmap_dirty = true;
+ }
+
+ // cache some info in locals
+ int dev = state.gfxset.devindex;
+ int set = state.gfxset.set;
+ ui_gfx_info &info = state.gfxdev[dev];
+ gfx_element &gfx = *info.interface->gfx(set);
+
+ // handle cells per line (minus,plus)
+ if (machine.ui_input().pressed(IPT_UI_ZOOM_OUT))
+ { info.columns[set] = xcells - 1; state.bitmap_dirty = true; }
+
+ if (machine.ui_input().pressed(IPT_UI_ZOOM_IN))
+ { info.columns[set] = xcells + 1; state.bitmap_dirty = true; }
+
+ // clamp within range
+ if (info.columns[set] < 2)
+ { info.columns[set] = 2; state.bitmap_dirty = true; }
+ if (info.columns[set] > 128)
+ { info.columns[set] = 128; state.bitmap_dirty = true; }
+
+ // handle rotation (R)
+ if (machine.ui_input().pressed(IPT_UI_ROTATE))
+ {
+ info.rotate[set] = orientation_add(ROT90, info.rotate[set]);
+ state.bitmap_dirty = true;
+ }
+
+ // handle navigation within the cells (up,down,pgup,pgdown)
+ if (machine.ui_input().pressed_repeat(IPT_UI_UP, 4))
+ { info.offset[set] -= xcells; state.bitmap_dirty = true; }
+ if (machine.ui_input().pressed_repeat(IPT_UI_DOWN, 4))
+ { info.offset[set] += xcells; state.bitmap_dirty = true; }
+ if (machine.ui_input().pressed_repeat(IPT_UI_PAGE_UP, 6))
+ { info.offset[set] -= xcells * ycells; state.bitmap_dirty = true; }
+ if (machine.ui_input().pressed_repeat(IPT_UI_PAGE_DOWN, 6))
+ { info.offset[set] += xcells * ycells; state.bitmap_dirty = true; }
+ if (machine.ui_input().pressed_repeat(IPT_UI_HOME, 4))
+ { info.offset[set] = 0; state.bitmap_dirty = true; }
+ if (machine.ui_input().pressed_repeat(IPT_UI_END, 4))
+ { info.offset[set] = gfx.elements(); state.bitmap_dirty = true; }
+
+ // clamp within range
+ if (info.offset[set] + xcells * ycells > ((gfx.elements() + xcells - 1) / xcells) * xcells)
+ {
+ info.offset[set] = ((gfx.elements() + xcells - 1) / xcells) * xcells - xcells * ycells;
+ state.bitmap_dirty = true;
+ }
+ if (info.offset[set] < 0)
+ { info.offset[set] = 0; state.bitmap_dirty = true; }
+
+ // handle color selection (left,right)
+ if (machine.ui_input().pressed_repeat(IPT_UI_LEFT, 4))
+ { info.color[set] -= 1; state.bitmap_dirty = true; }
+ if (machine.ui_input().pressed_repeat(IPT_UI_RIGHT, 4))
+ { info.color[set] += 1; state.bitmap_dirty = true; }
+
+ // clamp within range
+ if (info.color[set] >= (int)gfx.colors())
+ { info.color[set] = gfx.colors() - 1; state.bitmap_dirty = true; }
+ if (info.color[set] < 0)
+ { info.color[set] = 0; state.bitmap_dirty = true; }
+}
+
+
+//-------------------------------------------------
+// gfxset_update_bitmap - redraw the current
+// graphics view bitmap
+//-------------------------------------------------
+
+static void gfxset_update_bitmap(running_machine &machine, ui_gfx_state &state, int xcells, int ycells, gfx_element &gfx)
+{
+ int dev = state.gfxset.devindex;
+ int set = state.gfxset.set;
+ ui_gfx_info &info = state.gfxdev[dev];
+ int cellxpix, cellypix;
+ int x, y;
+
+ // compute the number of source pixels in a cell
+ cellxpix = 1 + ((info.rotate[set] & ORIENTATION_SWAP_XY) ? gfx.height() : gfx.width());
+ cellypix = 1 + ((info.rotate[set] & ORIENTATION_SWAP_XY) ? gfx.width() : gfx.height());
+
+ // realloc the bitmap if it is too small
+ if (state.bitmap == nullptr || state.texture == nullptr || state.bitmap->bpp() != 32 || state.bitmap->width() != cellxpix * xcells || state.bitmap->height() != cellypix * ycells)
+ {
+ // free the old stuff
+ machine.render().texture_free(state.texture);
+ global_free(state.bitmap);
+
+ // allocate new stuff
+ state.bitmap = global_alloc(bitmap_rgb32(cellxpix * xcells, cellypix * ycells));
+ state.texture = machine.render().texture_alloc();
+ state.texture->set_bitmap(*state.bitmap, state.bitmap->cliprect(), TEXFORMAT_ARGB32);
+
+ // force a redraw
+ state.bitmap_dirty = true;
+ }
+
+ // handle the redraw
+ if (state.bitmap_dirty)
+ {
+ // loop over rows
+ for (y = 0; y < ycells; y++)
+ {
+ rectangle cellbounds;
+
+ // make a rect that covers this row
+ cellbounds.set(0, state.bitmap->width() - 1, y * cellypix, (y + 1) * cellypix - 1);
+
+ // only display if there is data to show
+ if (info.offset[set] + y * xcells < gfx.elements())
+ {
+ // draw the individual cells
+ for (x = 0; x < xcells; x++)
+ {
+ int index = info.offset[set] + y * xcells + x;
+
+ // update the bounds for this cell
+ cellbounds.min_x = x * cellxpix;
+ cellbounds.max_x = (x + 1) * cellxpix - 1;
+
+ // only render if there is data
+ if (index < gfx.elements())
+ gfxset_draw_item(machine, gfx, index, *state.bitmap, cellbounds.min_x, cellbounds.min_y, info.color[set], info.rotate[set]);
+
+ // otherwise, fill with transparency
+ else
+ state.bitmap->fill(0, cellbounds);
+ }
+ }
+
+ // otherwise, fill with transparency
+ else
+ state.bitmap->fill(0, cellbounds);
+ }
+
+ // reset the texture to force an update
+ state.texture->set_bitmap(*state.bitmap, state.bitmap->cliprect(), TEXFORMAT_ARGB32);
+ state.bitmap_dirty = false;
+ }
+}
+
+
+//-------------------------------------------------
+// gfxset_draw_item - draw a single item into
+// the view
+//-------------------------------------------------
+
+static void gfxset_draw_item(running_machine &machine, gfx_element &gfx, int index, bitmap_rgb32 &bitmap, int dstx, int dsty, int color, int rotate)
+{
+ int width = (rotate & ORIENTATION_SWAP_XY) ? gfx.height() : gfx.width();
+ int height = (rotate & ORIENTATION_SWAP_XY) ? gfx.width() : gfx.height();
+ const rgb_t *palette = gfx.palette().palette()->entry_list_raw() + gfx.colorbase() + color * gfx.granularity();
+ int x, y;
+
+ // loop over rows in the cell
+ for (y = 0; y < height; y++)
+ {
+ UINT32 *dest = &bitmap.pix32(dsty + y, dstx);
+ const UINT8 *src = gfx.get_data(index);
+
+ // loop over columns in the cell
+ for (x = 0; x < width; x++)
+ {
+ int effx = x, effy = y;
+ const UINT8 *s;
+
+ // compute effective x,y values after rotation
+ if (!(rotate & ORIENTATION_SWAP_XY))
+ {
+ if (rotate & ORIENTATION_FLIP_X)
+ effx = gfx.width() - 1 - effx;
+ if (rotate & ORIENTATION_FLIP_Y)
+ effy = gfx.height() - 1 - effy;
+ }
+ else
+ {
+ int temp;
+ if (rotate & ORIENTATION_FLIP_X)
+ effx = gfx.height() - 1 - effx;
+ if (rotate & ORIENTATION_FLIP_Y)
+ effy = gfx.width() - 1 - effy;
+ temp = effx; effx = effy; effy = temp;
+ }
+
+ // get a pointer to the start of this source row
+ s = src + effy * gfx.rowbytes();
+
+ // extract the pixel
+ *dest++ = 0xff000000 | palette[s[effx]];
+ }
+ }
+}
+
+
+
+/***************************************************************************
+ TILEMAP VIEWER
+***************************************************************************/
+
+//-------------------------------------------------
+// tilemap_handler - handler for the tilemap
+// viewer
+//-------------------------------------------------
+
+static void tilemap_handler(running_machine &machine, render_container *container, ui_gfx_state &state)
+{
+ render_font *ui_font = mame_machine_manager::instance()->ui().get_font();
+ float chwidth, chheight;
+ render_bounds mapboxbounds;
+ render_bounds boxbounds;
+ int targwidth = machine.render().ui_target().width();
+ int targheight = machine.render().ui_target().height();
+ float titlewidth;
+ float x0, y0;
+ int mapboxwidth, mapboxheight;
+ int maxxscale, maxyscale;
+ UINT32 mapwidth, mapheight;
+ int x, pixelscale;
+ char title[100];
+
+ // get the size of the tilemap itself
+ tilemap_t *tilemap = machine.tilemap().find(state.tilemap.which);
+ mapwidth = tilemap->width();
+ mapheight = tilemap->height();
+ if (state.tilemap.rotate & ORIENTATION_SWAP_XY)
+ { UINT32 temp = mapwidth; mapwidth = mapheight; mapheight = temp; }
+
+ // add a half character padding for the box
+ chheight = mame_machine_manager::instance()->ui().get_line_height();
+ chwidth = ui_font->char_width(chheight, machine.render().ui_aspect(), '0');
+ boxbounds.x0 = 0.0f + 0.5f * chwidth;
+ boxbounds.x1 = 1.0f - 0.5f * chwidth;
+ boxbounds.y0 = 0.0f + 0.5f * chheight;
+ boxbounds.y1 = 1.0f - 0.5f * chheight;
+
+ // the tilemap box bounds starts a half character in from the box
+ mapboxbounds = boxbounds;
+ mapboxbounds.x0 += 0.5f * chwidth;
+ mapboxbounds.x1 -= 0.5f * chwidth;
+ mapboxbounds.y0 += 0.5f * chheight;
+ mapboxbounds.y1 -= 0.5f * chheight;
+
+ // add space on the top for a title and a half line of padding
+ mapboxbounds.y0 += 1.5f * chheight;
+
+ // convert back to pixels
+ mapboxwidth = (mapboxbounds.x1 - mapboxbounds.x0) * (float)targwidth;
+ mapboxheight = (mapboxbounds.y1 - mapboxbounds.y0) * (float)targheight;
+
+ // determine the maximum integral scaling factor
+ pixelscale = state.tilemap.zoom;
+ if (pixelscale == 0)
+ {
+ for (maxxscale = 1; mapwidth * (maxxscale + 1) < mapboxwidth; maxxscale++) { }
+ for (maxyscale = 1; mapheight * (maxyscale + 1) < mapboxheight; maxyscale++) { }
+ pixelscale = MIN(maxxscale, maxyscale);
+ }
+
+ // recompute the final box size
+ mapboxwidth = MIN(mapboxwidth, mapwidth * pixelscale);
+ mapboxheight = MIN(mapboxheight, mapheight * pixelscale);
+
+ // recompute the bounds, centered within the existing bounds
+ mapboxbounds.x0 += 0.5f * ((mapboxbounds.x1 - mapboxbounds.x0) - (float)mapboxwidth / (float)targwidth);
+ mapboxbounds.x1 = mapboxbounds.x0 + (float)mapboxwidth / (float)targwidth;
+ mapboxbounds.y0 += 0.5f * ((mapboxbounds.y1 - mapboxbounds.y0) - (float)mapboxheight / (float)targheight);
+ mapboxbounds.y1 = mapboxbounds.y0 + (float)mapboxheight / (float)targheight;
+
+ // now recompute the outer box against this new info
+ boxbounds.x0 = mapboxbounds.x0 - 0.5f * chwidth;
+ boxbounds.x1 = mapboxbounds.x1 + 0.5f * chwidth;
+ boxbounds.y0 = mapboxbounds.y0 - 2.0f * chheight;
+ boxbounds.y1 = mapboxbounds.y1 + 0.5f * chheight;
+
+ // figure out the title and expand the outer box to fit
+ sprintf(title, "TILEMAP %d/%d %dx%d OFFS %d,%d", state.tilemap.which, machine.tilemap().count() - 1, mapwidth, mapheight, state.tilemap.xoffs, state.tilemap.yoffs);
+ titlewidth = ui_font->string_width(chheight, machine.render().ui_aspect(), title);
+ if (boxbounds.x1 - boxbounds.x0 < titlewidth + chwidth)
+ {
+ boxbounds.x0 = 0.5f - 0.5f * (titlewidth + chwidth);
+ boxbounds.x1 = boxbounds.x0 + titlewidth + chwidth;
+ }
+
+ // go ahead and draw the outer box now
+ mame_machine_manager::instance()->ui().draw_outlined_box(container, boxbounds.x0, boxbounds.y0, boxbounds.x1, boxbounds.y1, UI_GFXVIEWER_BG_COLOR);
+
+ // draw the title
+ x0 = 0.5f - 0.5f * titlewidth;
+ y0 = boxbounds.y0 + 0.5f * chheight;
+ for (x = 0; title[x] != 0; x++)
+ {
+ container->add_char(x0, y0, chheight, machine.render().ui_aspect(), ARGB_WHITE, *ui_font, title[x]);
+ x0 += ui_font->char_width(chheight, machine.render().ui_aspect(), title[x]);
+ }
+
+ // update the bitmap
+ tilemap_update_bitmap(machine, state, mapboxwidth / pixelscale, mapboxheight / pixelscale);
+
+ // add the final quad
+ container->add_quad(mapboxbounds.x0, mapboxbounds.y0,
+ mapboxbounds.x1, mapboxbounds.y1,
+ ARGB_WHITE, state.texture,
+ PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(state.tilemap.rotate));
+
+ // handle keyboard input
+ tilemap_handle_keys(machine, state, mapboxwidth, mapboxheight);
+}
+
+
+//-------------------------------------------------
+// tilemap_handle_keys - handle keys for the
+// tilemap view
+//-------------------------------------------------
+
+static void tilemap_handle_keys(running_machine &machine, ui_gfx_state &state, int viswidth, int visheight)
+{
+ UINT32 mapwidth, mapheight;
+ int step;
+
+ // handle tilemap selection (open bracket,close bracket)
+ if (machine.ui_input().pressed(IPT_UI_PREV_GROUP) && state.tilemap.which > 0)
+ { state.tilemap.which--; state.bitmap_dirty = true; }
+ if (machine.ui_input().pressed(IPT_UI_NEXT_GROUP) && state.tilemap.which < machine.tilemap().count() - 1)
+ { state.tilemap.which++; state.bitmap_dirty = true; }
+
+ // cache some info in locals
+ tilemap_t *tilemap = machine.tilemap().find(state.tilemap.which);
+ mapwidth = tilemap->width();
+ mapheight = tilemap->height();
+
+ // handle zoom (minus,plus)
+ if (machine.ui_input().pressed(IPT_UI_ZOOM_OUT) && state.tilemap.zoom > 0)
+ {
+ state.tilemap.zoom--;
+ state.bitmap_dirty = true;
+ if (state.tilemap.zoom != 0)
+ machine.popmessage("Zoom = %d", state.tilemap.zoom);
+ else
+ machine.popmessage("Zoom Auto");
+ }
+ if (machine.ui_input().pressed(IPT_UI_ZOOM_IN) && state.tilemap.zoom < 8)
+ {
+ state.tilemap.zoom++;
+ state.bitmap_dirty = true;
+ machine.popmessage("Zoom = %d", state.tilemap.zoom);
+ }
+
+ // handle rotation (R)
+ if (machine.ui_input().pressed(IPT_UI_ROTATE))
+ {
+ state.tilemap.rotate = orientation_add(ROT90, state.tilemap.rotate);
+ state.bitmap_dirty = true;
+ }
+
+ // handle navigation (up,down,left,right)
+ step = 8;
+ if (machine.input().code_pressed(KEYCODE_LSHIFT)) step = 1;
+ if (machine.input().code_pressed(KEYCODE_LCONTROL)) step = 64;
+ if (machine.ui_input().pressed_repeat(IPT_UI_UP, 4))
+ { state.tilemap.yoffs -= step; state.bitmap_dirty = true; }
+ if (machine.ui_input().pressed_repeat(IPT_UI_DOWN, 4))
+ { state.tilemap.yoffs += step; state.bitmap_dirty = true; }
+ if (machine.ui_input().pressed_repeat(IPT_UI_LEFT, 6))
+ { state.tilemap.xoffs -= step; state.bitmap_dirty = true; }
+ if (machine.ui_input().pressed_repeat(IPT_UI_RIGHT, 6))
+ { state.tilemap.xoffs += step; state.bitmap_dirty = true; }
+
+ // clamp within range
+ while (state.tilemap.xoffs < 0)
+ state.tilemap.xoffs += mapwidth;
+ while (state.tilemap.xoffs >= mapwidth)
+ state.tilemap.xoffs -= mapwidth;
+ while (state.tilemap.yoffs < 0)
+ state.tilemap.yoffs += mapheight;
+ while (state.tilemap.yoffs >= mapheight)
+ state.tilemap.yoffs -= mapheight;
+}
+
+
+//-------------------------------------------------
+// tilemap_update_bitmap - update the bitmap
+// for the tilemap view
+//-------------------------------------------------
+
+static void tilemap_update_bitmap(running_machine &machine, ui_gfx_state &state, int width, int height)
+{
+ // swap the coordinates back if they were talking about a rotated surface
+ if (state.tilemap.rotate & ORIENTATION_SWAP_XY)
+ { UINT32 temp = width; width = height; height = temp; }
+
+ // realloc the bitmap if it is too small
+ if (state.bitmap == nullptr || state.texture == nullptr || state.bitmap->width() != width || state.bitmap->height() != height)
+ {
+ // free the old stuff
+ machine.render().texture_free(state.texture);
+ global_free(state.bitmap);
+
+ // allocate new stuff
+ state.bitmap = global_alloc(bitmap_rgb32(width, height));
+ state.texture = machine.render().texture_alloc();
+ state.texture->set_bitmap(*state.bitmap, state.bitmap->cliprect(), TEXFORMAT_RGB32);
+
+ // force a redraw
+ state.bitmap_dirty = true;
+ }
+
+ // handle the redraw
+ if (state.bitmap_dirty)
+ {
+ tilemap_t *tilemap = machine.tilemap().find(state.tilemap.which);
+ tilemap->draw_debug(*machine.first_screen(), *state.bitmap, state.tilemap.xoffs, state.tilemap.yoffs);
+
+ // reset the texture to force an update
+ state.texture->set_bitmap(*state.bitmap, state.bitmap->cliprect(), TEXFORMAT_RGB32);
+ state.bitmap_dirty = false;
+ }
+}
diff --git a/src/frontend/mame/ui/viewgfx.h b/src/frontend/mame/ui/viewgfx.h
new file mode 100644
index 00000000000..16c257476f0
--- /dev/null
+++ b/src/frontend/mame/ui/viewgfx.h
@@ -0,0 +1,32 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/***************************************************************************
+
+ ui/viewgfx.h
+
+ Internal graphics viewer.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UI_VIEWGFX_H__
+#define __UI_VIEWGFX_H__
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+// initialization
+void ui_gfx_init(running_machine &machine);
+
+// returns 'true' if the internal graphics viewer has relevance
+bool ui_gfx_is_relevant(running_machine &machine);
+
+// master handler
+UINT32 ui_gfx_ui_handler(running_machine &machine, render_container *container, UINT32 state);
+
+
+#endif /* __UI_VIEWGFX_H__ */