diff options
Diffstat (limited to 'src/frontend')
29 files changed, 631 insertions, 916 deletions
diff --git a/src/frontend/mame/audit.cpp b/src/frontend/mame/audit.cpp index f8d2cbdd9d4..6509b264e49 100644 --- a/src/frontend/mame/audit.cpp +++ b/src/frontend/mame/audit.cpp @@ -22,6 +22,111 @@ #include <algorithm> +//#define VERBOSE 1 +#define LOG_OUTPUT_FUNC osd_printf_verbose +#include "logmacro.h" + + +namespace { + +struct parent_rom +{ + parent_rom(device_type t, rom_entry const *r) : type(t), name(ROM_GETNAME(r)), hashes(ROM_GETHASHDATA(r)), length(rom_file_size(r)) { } + + std::reference_wrapper<std::remove_reference_t<device_type> > type; + std::string name; + util::hash_collection hashes; + uint64_t length; +}; + + +class parent_rom_vector : public std::vector<parent_rom> +{ +public: + using std::vector<parent_rom>::vector; + + std::add_pointer_t<device_type> find_shared_device(device_t ¤t, char const *name, util::hash_collection const &hashes, uint64_t length) const + { + // if we're examining a child device, it will always have a perfect match + if (current.owner()) + return ¤t.type(); + + // scan backwards through parents for a matching definition + bool const dumped(!hashes.flag(util::hash_collection::FLAG_NO_DUMP)); + std::add_pointer_t<device_type> best(nullptr); + for (const_reverse_iterator it = crbegin(); crend() != it; ++it) + { + if (it->length == length) + { + if (dumped) + { + if (it->hashes == hashes) + return &it->type.get(); + } + else if (it->name == name) + { + if (it->hashes.flag(util::hash_collection::FLAG_NO_DUMP)) + return &it->type.get(); + else if (!best) + best = &it->type.get(); + } + } + } + return best; + } + + std::pair<std::add_pointer_t<device_type>, bool> actual_matches_shared(device_t ¤t, media_auditor::audit_record const &record) + { + // no result if no matching file was found + if ((record.status() != media_auditor::audit_status::GOOD) && (record.status() != media_auditor::audit_status::FOUND_INVALID)) + return std::make_pair(nullptr, false); + + // if we're examining a child device, scan it first + bool matches_device_undumped(false); + if (current.owner()) + { + for (const rom_entry *region = rom_first_region(current); region; region = rom_next_region(region)) + { + for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom)) + { + if (rom_file_size(rom) == record.actual_length()) + { + util::hash_collection const hashes(ROM_GETHASHDATA(rom)); + if (hashes == record.actual_hashes()) + return std::make_pair(¤t.type(), empty()); + else if (hashes.flag(util::hash_collection::FLAG_NO_DUMP) && (rom->name() == record.name())) + matches_device_undumped = true; + } + } + } + } + + // look for a matching parent ROM + std::add_pointer_t<device_type> closest_bad(nullptr); + for (const_reverse_iterator it = crbegin(); crend() != it; ++it) + { + if (it->length == record.actual_length()) + { + if (it->hashes == record.actual_hashes()) + return std::make_pair(&it->type.get(), it->type.get() == front().type.get()); + else if (it->hashes.flag(util::hash_collection::FLAG_NO_DUMP) && (it->name == record.name())) + closest_bad = &it->type.get(); + } + } + + // fall back to the nearest bad dump + if (closest_bad) + return std::make_pair(closest_bad, front().type.get() == *closest_bad); + else if (matches_device_undumped) + return std::make_pair(¤t.type(), empty()); + else + return std::make_pair(nullptr, false); + } +}; + +} // anonymous namespace + + //************************************************************************** // CORE FUNCTIONS @@ -51,10 +156,29 @@ media_auditor::summary media_auditor::audit_media(const char *validation) // store validation for later m_validation = validation; - std::size_t found = 0; - std::size_t required = 0; - std::size_t shared_found = 0; - std::size_t shared_required = 0; + // first walk the parent chain for required ROMs + parent_rom_vector parentroms; + for (auto drvindex = m_enumerator.find(m_enumerator.driver().parent); 0 <= drvindex; drvindex = m_enumerator.find(m_enumerator.driver(drvindex).parent)) + { + game_driver const &parent(m_enumerator.driver(drvindex)); + LOG("Checking parent %s for ROM files\n", parent.type.shortname()); + std::vector<rom_entry> const roms(rom_build_entries(parent.rom)); + for (rom_entry const *region = rom_first_region(&roms.front()); region; region = rom_next_region(region)) + { + for (rom_entry const *rom = rom_first_file(region); rom; rom = rom_next_file(rom)) + { + LOG("Adding parent ROM %s\n", rom->name()); + parentroms.emplace_back(parent.type, rom); + } + } + } + + // count ROMs required/found + std::size_t found(0); + std::size_t required(0); + std::size_t shared_found(0); + std::size_t shared_required(0); + std::size_t parent_found(0); // iterate over devices and regions std::vector<std::string> searchpath; @@ -68,12 +192,20 @@ media_auditor::summary media_auditor::audit_media(const char *validation) for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom)) { if (searchpath.empty()) + { + LOG("Audit media for device %s(%s)\n", device.shortname(), device.tag()); searchpath = device.searchpath(); + } + // look for a matching parent or device ROM char const *const name(ROM_GETNAME(rom)); util::hash_collection const hashes(ROM_GETHASHDATA(rom)); - device_t *const shared_device(find_shared_device(device, name, hashes, rom_file_size(rom))); - const auto dumped(!hashes.flag(util::hash_collection::FLAG_NO_DUMP)); + bool const dumped(!hashes.flag(util::hash_collection::FLAG_NO_DUMP)); + std::add_pointer_t<device_type> const shared_device(parentroms.find_shared_device(device, name, hashes, rom_file_size(rom))); + if (shared_device) + LOG("File '%s' %s%sdumped shared with %s\n", name, ROM_ISOPTIONAL(rom) ? "optional " : "", dumped ? "" : "un", shared_device->shortname()); + else + LOG("File '%s' %s%sdumped\n", name, ROM_ISOPTIONAL(rom) ? "optional " : "", dumped ? "" : "un"); // count the number of files with hashes if (dumped && !ROM_ISOPTIONAL(rom)) @@ -83,7 +215,7 @@ media_auditor::summary media_auditor::audit_media(const char *validation) shared_required++; } - audit_record *record = nullptr; + audit_record *record(nullptr); if (ROMREGION_ISROMDATA(region)) record = &audit_one_rom(searchpath, rom); else if (ROMREGION_ISDISKDATA(region)) @@ -91,22 +223,32 @@ media_auditor::summary media_auditor::audit_media(const char *validation) if (record) { + // see if the actual content found belongs to a parent + auto const matchesshared(parentroms.actual_matches_shared(device, *record)); + if (matchesshared.first) + LOG("Actual ROM file shared with %sparent %s\n", matchesshared.second ? "immediate " : "", matchesshared.first->shortname()); + // count the number of files that are found. - if (!device.owner() && ((record->status() == audit_status::GOOD && dumped) || (record->status() == audit_status::FOUND_INVALID && !find_shared_device(device, name, record->actual_hashes(), record->actual_length())))) + if ((record->status() == audit_status::GOOD) || ((record->status() == audit_status::FOUND_INVALID) && !matchesshared.first)) { found++; if (shared_device) shared_found++; + if (matchesshared.second) + parent_found++; } record->set_shared_device(shared_device); } } } + + if (!searchpath.empty()) + LOG("Total required=%u (shared=%u) found=%u (shared=%u parent=%u)\n", required, shared_required, found, shared_found, parent_found); } // 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))) + if ((found == shared_found) && required && ((required != shared_required) || !parent_found)) { m_record_list.clear(); return NOTFOUND; @@ -341,7 +483,7 @@ media_auditor::summary media_auditor::summarize(const char *name, std::ostream * case audit_substatus::NOT_FOUND: if (output) { - device_t *const shared_device = record.shared_device(); + std::add_pointer_t<device_type> const shared_device = record.shared_device(); if (shared_device) util::stream_format(*output, "NOT FOUND (%s)\n", shared_device->shortname()); else @@ -500,59 +642,6 @@ void media_auditor::compute_status(audit_record &record, const rom_entry *rom, b //------------------------------------------------- -// 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 util::hash_collection &romhashes, uint64_t romlength) -{ - bool const dumped = !romhashes.flag(util::hash_collection::FLAG_NO_DUMP); - - // special case for non-root devices - device_t *highest_device = nullptr; - if (device.owner()) - { - 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 (rom_file_size(rom) == romlength) - { - util::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 (auto drvindex = m_enumerator.find(m_enumerator.driver().parent); drvindex >= 0; 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_file_size(rom) == romlength) - { - util::hash_collection hashes(ROM_GETHASHDATA(rom)); - if ((dumped && hashes == romhashes) || (!dumped && ROM_GETNAME(rom) == name)) - highest_device = &scandevice; - } - } - } - } - } - } - - return highest_device; -} - - -//------------------------------------------------- // audit_record - constructor //------------------------------------------------- diff --git a/src/frontend/mame/audit.h b/src/frontend/mame/audit.h index d336f6e5ae4..d1904820f03 100644 --- a/src/frontend/mame/audit.h +++ b/src/frontend/mame/audit.h @@ -107,7 +107,7 @@ public: uint64_t actual_length() const { return m_length; } const util::hash_collection &expected_hashes() const { return m_exphashes; } const util::hash_collection &actual_hashes() const { return m_hashes; } - device_t *shared_device() const { return m_shared_device; } + std::add_pointer_t<device_type> shared_device() const { return m_shared_device; } // setters void set_status(audit_status status, audit_substatus substatus) @@ -128,22 +128,22 @@ public: m_length = length; } - void set_shared_device(device_t *shared_device) + void set_shared_device(std::add_pointer_t<device_type> shared_device) { m_shared_device = shared_device; } private: // internal state - 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_t m_explength; // expected length of item - uint64_t m_length; // actual length of item - util::hash_collection m_exphashes; // expected hash data - util::hash_collection m_hashes; // actual hash information - device_t * m_shared_device; // device that shares the rom + 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_t m_explength; // expected length of item + uint64_t m_length; // actual length of item + util::hash_collection m_exphashes; // expected hash data + util::hash_collection m_hashes; // actual hash information + std::add_pointer_t<device_type> m_shared_device; // device that shares the ROM }; using record_list = std::list<audit_record>; @@ -166,7 +166,6 @@ private: audit_record &audit_one_rom(const std::vector<std::string> &searchpath, const rom_entry *rom); template <typename... T> audit_record &audit_one_disk(const rom_entry *rom, T &&... args); void compute_status(audit_record &record, const rom_entry *rom, bool found); - device_t *find_shared_device(device_t &device, const char *name, const util::hash_collection &romhashes, uint64_t romlength); // internal state record_list m_record_list; diff --git a/src/frontend/mame/clifront.cpp b/src/frontend/mame/clifront.cpp index 4785b718d68..978227bade0 100644 --- a/src/frontend/mame/clifront.cpp +++ b/src/frontend/mame/clifront.cpp @@ -343,7 +343,7 @@ int cli_frontend::execute(std::vector<std::string> &args) } util::archive_file::cache_clear(); - global_free(manager); + delete manager; return m_result; } diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp index 4f44c3ad9d4..9afe6827cfd 100644 --- a/src/frontend/mame/luaengine.cpp +++ b/src/frontend/mame/luaengine.cpp @@ -1570,7 +1570,7 @@ void lua_engine::initialize() * debugger.execution_state - accessor for active cpu run state */ - struct wrap_textbuf { wrap_textbuf(text_buffer *buf) { textbuf = buf; }; text_buffer *textbuf; }; + struct wrap_textbuf { wrap_textbuf(const text_buffer &buf) : textbuf(buf) { } std::reference_wrapper<const text_buffer> textbuf; }; auto debugger_type = sol().registry().create_simple_usertype<debugger_manager>("new", sol::no_constructor); debugger_type.set("command", [](debugger_manager &debug, const std::string &cmd) { debug.console().execute_command(cmd, false); }); diff --git a/src/frontend/mame/mame.cpp b/src/frontend/mame/mame.cpp index 908da0e2bf6..b996bae1dc0 100644 --- a/src/frontend/mame/mame.cpp +++ b/src/frontend/mame/mame.cpp @@ -10,38 +10,44 @@ #include "emu.h" #include "mame.h" + +#include "ui/inifile.h" +#include "ui/selgame.h" +#include "ui/simpleselgame.h" +#include "ui/ui.h" + +#include "cheat.h" +#include "clifront.h" #include "emuopts.h" +#include "luaengine.h" #include "mameopts.h" #include "pluginopts.h" -#include "osdepend.h" #include "validity.h" -#include "clifront.h" -#include "luaengine.h" -#include <ctime> -#include "ui/ui.h" -#include "ui/selgame.h" -#include "ui/simpleselgame.h" -#include "cheat.h" -#include "ui/inifile.h" + #include "xmlfile.h" +#include "osdepend.h" + +#include <ctime> + + //************************************************************************** // MACHINE MANAGER //************************************************************************** -mame_machine_manager* mame_machine_manager::m_manager = nullptr; +mame_machine_manager *mame_machine_manager::s_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)); + if (!s_manager) + s_manager = new mame_machine_manager(options, osd); - return m_manager; + return s_manager; } mame_machine_manager* mame_machine_manager::instance() { - return m_manager; + return s_manager; } //------------------------------------------------- @@ -51,7 +57,7 @@ mame_machine_manager* mame_machine_manager::instance() 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_lua(std::make_unique<lua_engine>()), m_new_driver_pending(nullptr), m_firstrun(true), m_autoboot_timer(nullptr) @@ -65,8 +71,8 @@ mame_machine_manager::mame_machine_manager(emu_options &options,osd_interface &o mame_machine_manager::~mame_machine_manager() { - global_free(m_lua); - m_manager = nullptr; + m_lua.reset(); + s_manager = nullptr; } diff --git a/src/frontend/mame/mame.h b/src/frontend/mame/mame.h index 041612de758..037d714b39c 100644 --- a/src/frontend/mame/mame.h +++ b/src/frontend/mame/mame.h @@ -35,7 +35,7 @@ public: ~mame_machine_manager(); plugin_options &plugins() const { return *m_plugins; } - lua_engine *lua() { return m_lua; } + lua_engine *lua() { return m_lua.get(); } virtual void update_machine() override; @@ -72,12 +72,12 @@ private: mame_machine_manager &operator=(mame_machine_manager &&) = delete; std::unique_ptr<plugin_options> m_plugins; // pointer to plugin options - lua_engine * m_lua; + std::unique_ptr<lua_engine> m_lua; const game_driver * m_new_driver_pending; // pointer to the next pending driver bool m_firstrun; - static mame_machine_manager* m_manager; + static mame_machine_manager *s_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 diff --git a/src/frontend/mame/ui/icorender.cpp b/src/frontend/mame/ui/icorender.cpp index bea85f9dd60..5bda0836838 100644 --- a/src/frontend/mame/ui/icorender.cpp +++ b/src/frontend/mame/ui/icorender.cpp @@ -19,6 +19,7 @@ #include "emu.h" #include "icorender.h" +#include "util/msdib.h" #include "util/png.h" #include <algorithm> @@ -26,11 +27,10 @@ #include <cstdint> #include <cstring> -// need to set LOG_OUTPUT_STREAM because there's no logerror outside devices -#define LOG_OUTPUT_STREAM std::cerr +// need to set LOG_OUTPUT_FUNC or LOG_OUTPUT_STREAM because there's no logerror outside devices +#define LOG_OUTPUT_FUNC osd_printf_verbose #define LOG_GENERAL (1U << 0) -#define LOG_DIB (1U << 1) //#define VERBOSE (LOG_GENERAL | LOG_DIB) @@ -41,16 +41,6 @@ namespace ui { namespace { -// DIB compression schemes -enum : uint32_t -{ - DIB_COMP_NONE = 0, - DIB_COMP_RLE8 = 1, - DIB_COMP_RLE4 = 2, - DIB_COMP_BITFIELDS = 3 -}; - - // ICO file header struct icon_dir_t { @@ -83,67 +73,6 @@ struct icon_dir_entry_t uint32_t offset; // offset to image data from start of file }; -// old-style DIB header -struct bitmap_core_header_t -{ - uint32_t size; // size of the header (12, 16 or 64) - int16_t width; // width of bitmap in pixels - int16_t height; // height of the image in pixels - uint16_t planes; // number of colour planes (must be 1) - uint16_t bpp; // bits per pixel -}; - -// new-style DIB header -struct bitmap_info_header_t -{ - uint32_t size; // size of the header - int32_t width; // width of bitmap in pixels - int32_t height; // height of bitmap in pixels - uint16_t planes; // number of colour planes (must be 1) - uint16_t bpp; // bits per pixel - uint32_t comp; // compression method - uint32_t rawsize; // size of bitmap data after decompression or 0 if uncompressed - int32_t hres; // horizontal resolution in pixels/metre - int32_t vres; // horizontal resolution in pixels/metre - uint32_t colors; // number of colours or 0 for 1 << bpp - uint32_t important; // number of important colours or 0 if all important - uint32_t red; // red field mask - must be contiguous - uint32_t green; // green field mask - must be contiguous - uint32_t blue; // blue field mask - must be contiguous - uint32_t alpha; // alpha field mask - must be contiguous -}; - - -bool dib_parse_mask(uint32_t mask, unsigned &shift, unsigned &bits) -{ - shift = count_leading_zeros(mask); - mask <<= shift; - bits = count_leading_ones(mask); - mask <<= shift; - shift = 32 - shift - bits; - return !mask; -} - - -void dib_truncate_channel(unsigned &shift, unsigned &bits) -{ - if (8U < bits) - { - unsigned const excess(bits - 8); - shift += excess; - bits -= excess; - } -} - - -uint8_t dib_splat_sample(uint8_t val, unsigned bits) -{ - assert(8U >= bits); - for (val <<= (8U - bits); bits && (8U > bits); bits <<= 1) - val |= val >> bits; - return val; -} - bool load_ico_png(util::core_file &fp, icon_dir_entry_t const &dir, bitmap_argb32 &bitmap) { @@ -151,10 +80,10 @@ bool load_ico_png(util::core_file &fp, icon_dir_entry_t const &dir, bitmap_argb3 if (9U >= dir.size) return false; fp.seek(dir.offset, SEEK_SET); - png_error const err(png_read_bitmap(fp, bitmap)); + util::png_error const err(util::png_read_bitmap(fp, bitmap)); switch (err) { - case PNGERR_NONE: + case util::png_error::NONE: // found valid PNG image assert(bitmap.valid()); if ((dir.get_width() == bitmap.width()) && ((dir.get_height() == bitmap.height()))) @@ -172,7 +101,7 @@ bool load_ico_png(util::core_file &fp, icon_dir_entry_t const &dir, bitmap_argb3 } return true; - case PNGERR_BAD_SIGNATURE: + case util::png_error::BAD_SIGNATURE: // doesn't look like PNG data - just fall back to DIB without the file header return false; @@ -190,426 +119,37 @@ bool load_ico_png(util::core_file &fp, icon_dir_entry_t const &dir, bitmap_argb3 bool load_ico_dib(util::core_file &fp, icon_dir_entry_t const &dir, bitmap_argb32 &bitmap) { - // check that these things haven't been padded somehow - static_assert(sizeof(bitmap_core_header_t) == 12U, "compiler has applied padding to bitmap_core_header_t"); - static_assert(sizeof(bitmap_info_header_t) == 56U, "compiler has applied padding to bitmap_info_header_t"); - - // ensure the header fits in the space for the image data - union { bitmap_core_header_t core; bitmap_info_header_t info; } header; - assert(&header.core.size == &header.info.size); - if (sizeof(header.core) > dir.size) - return false; - std::memset(&header, 0, sizeof(header)); fp.seek(dir.offset, SEEK_SET); - if (fp.read(&header.core.size, sizeof(header.core.size)) != sizeof(header.core.size)) - { - LOG( - "Error reading DIB header size from ICO file at offset %u (directory size %u)\n", - dir.offset, - dir.size); - return false; - } - header.core.size = little_endianize_int32(header.core.size); - if (dir.size < header.core.size) - { - LOG( - "ICO file image data at %u (%u bytes) is too small for DIB header (%u bytes)\n", - dir.offset, - dir.size, - header.core.size); - return false; - } - - // identify and read the header - convert OS/2 headers to Windows 3 format - unsigned palette_bytes(4U); - switch (header.core.size) + util::msdib_error const err(util::msdib_read_bitmap_data(fp, bitmap, dir.size, dir.get_height())); + switch (err) { - case 16U: - case 64U: - // extended OS/2 bitmap header with support for compression - LOG( - "ICO image data at %u (%u bytes) uses unsupported OS/2 DIB header (size %u)\n", - dir.offset, - dir.size, - header.core.size); - return false; - - case 12U: - // introduced in OS/2 and Windows 2.0 + case util::msdib_error::NONE: + // found valid DIB image + assert(bitmap.valid()); + if ((dir.get_width() == bitmap.width()) && ((dir.get_height() == bitmap.height()))) { - palette_bytes = 3U; - uint32_t const header_read(std::min<uint32_t>(header.core.size, sizeof(header.core)) - sizeof(header.core.size)); - if (fp.read(&header.core.width, header_read) != header_read) - { - LOG("Error reading DIB core header from ICO file image data at %u (%u bytes)\n", dir.offset, dir.size); - return false; - } - fp.seek(header.core.size - sizeof(header.core.size) - header_read, SEEK_CUR); - header.core.width = little_endianize_int16(header.core.width); - header.core.height = little_endianize_int16(header.core.height); - header.core.planes = little_endianize_int16(header.core.planes); - header.core.bpp = little_endianize_int16(header.core.bpp); - LOGMASKED( - LOG_DIB, - "Read DIB core header from ICO file image data at %u: %d*%d, %u planes, %u bpp\n", - dir.offset, - header.core.width, - header.core.height, - header.core.planes, - header.core.bpp); - - // this works because the core header only aliases the width/height of the info header - header.info.bpp = header.core.bpp; - header.info.planes = header.core.planes; - header.info.height = header.core.height; - header.info.width = header.core.width; - header.info.size = 40U; + LOG("Loaded %d*%d pixel DIB image from ICO file\n", bitmap.width(), bitmap.height()); } - break; - - default: - // the next version will be longer - if (124U >= header.core.size) + else { LOG( - "ICO image data at %u (%u bytes) uses unsupported DIB header format (size %u)\n", - dir.offset, - dir.size, - header.core.size); - return false; - } - // fall through - case 40U: - case 52U: - case 56U: - case 108U: - case 124U: - // the Windows 3 bitmap header with optional extensions - { - palette_bytes = 4U; - uint32_t const header_read(std::min<uint32_t>(header.info.size, sizeof(header.info)) - sizeof(header.info.size)); - if (fp.read(&header.info.width, header_read) != header_read) - { - LOG("Error reading DIB info header from ICO file image data at %u (%u bytes)\n", dir.offset, dir.size); - return false; - } - fp.seek(header.info.size - sizeof(header.info.size) - header_read, SEEK_CUR); - header.info.width = little_endianize_int32(header.info.width); - header.info.height = little_endianize_int32(header.info.height); - header.info.planes = little_endianize_int16(header.info.planes); - header.info.bpp = little_endianize_int16(header.info.bpp); - header.info.comp = little_endianize_int32(header.info.comp); - header.info.rawsize = little_endianize_int32(header.info.rawsize); - header.info.hres = little_endianize_int32(header.info.hres); - header.info.vres = little_endianize_int32(header.info.vres); - header.info.colors = little_endianize_int32(header.info.colors); - header.info.important = little_endianize_int32(header.info.important); - header.info.red = little_endianize_int32(header.info.red); - header.info.green = little_endianize_int32(header.info.green); - header.info.blue = little_endianize_int32(header.info.blue); - header.info.alpha = little_endianize_int32(header.info.alpha); - LOGMASKED( - LOG_DIB, - "Read DIB info header from ICO file image data at %u: %d*%d (%d*%d ppm), %u planes, %u bpp %u/%s%u colors\n", - dir.offset, - header.info.width, - header.info.height, - header.info.hres, - header.info.vres, - header.info.planes, - header.info.bpp, - header.info.important, - header.info.colors ? "" : "2^", - header.info.colors ? header.info.colors : header.info.bpp); - } - break; - } - - // check for unsupported planes/bit depth - if ((1U != header.info.planes) || !header.info.bpp || (32U < header.info.bpp) || ((8U < header.info.bpp) ? (header.info.bpp % 8) : (8 % header.info.bpp))) - { - LOG( - "ICO file DIB image data at %u uses unsupported planes/bits per pixel %u*%u\n", - dir.offset, - header.info.planes, - header.info.bpp); - return false; - } - - // check dimensions - if ((0 >= header.info.width) || (0 == header.info.height)) - { - LOG( - "ICO file DIB image data at %u has invalid dimensions %u*%u\n", - dir.offset, - header.info.width, - header.info.height); - return false; - } - bool const top_down(0 > header.info.height); - if (top_down) - header.info.height = -header.info.height; - bool have_and_mask((2 * dir.get_height()) == header.info.height); - if (!have_and_mask && (dir.get_height() != header.info.height)) - { - osd_printf_verbose( - "ICO file DIB image data at %lu height %ld doesn't match directory height %u with or without AND mask\n", - (unsigned long)dir.offset, - (long)header.info.height, - dir.get_height()); - return false; - } - if (have_and_mask) - header.info.height >>= 1; - - // ensure compression scheme is supported - bool indexed(true), no_palette(false); - switch (header.info.comp) - { - case DIB_COMP_NONE: - // uncompressed - direct colour with implied bitfields if more than eight bits/pixel - indexed = 8U >= header.info.bpp; - if (indexed) - { - if ((1U << header.info.bpp) < header.info.colors) - { - osd_printf_verbose( - "ICO file DIB image data at %lu has oversized palette with %lu entries for %u bits per pixel\n", - (unsigned long)dir.offset, - (unsigned long)header.info.colors, - (unsigned)header.info.bpp); - } - } - if (!indexed) - { - no_palette = true; - switch(header.info.bpp) - { - case 16U: - header.info.red = 0x00007c00; - header.info.green = 0x000003e0; - header.info.blue = 0x0000001f; - header.info.alpha = 0x00000000; - break; - case 24U: - case 32U: - header.info.red = 0x00ff0000; - header.info.green = 0x0000ff00; - header.info.blue = 0x000000ff; - header.info.alpha = 0x00000000; - break; - } - } - break; - - case DIB_COMP_BITFIELDS: - // uncompressed direct colour with explicitly-specified bitfields - indexed = false; - if (offsetof(bitmap_info_header_t, alpha) > header.info.size) - { - osd_printf_verbose( - "ICO file DIB image data at %lu specifies bit masks but is too small (size %lu)\n", - (unsigned long)dir.offset, - (unsigned long)header.info.size); - return false; + "Loaded %d*%d pixel DIB image from ICO file (directory indicated %u*%u)\n", + bitmap.width(), + bitmap.height(), + dir.get_width(), + dir.get_height()); } - break; + return true; default: - LOG("ICO file DIB image data at %u uses unsupported compression scheme %u\n", header.info.comp); - return false; - } - - // we can now calculate the size of the palette and row data - size_t const palette_entries( - indexed - ? ((1U == header.info.bpp) ? 2U : header.info.colors ? header.info.colors : (1U << header.info.bpp)) - : (no_palette ? 0U : header.info.colors)); - size_t const palette_size(palette_bytes * palette_entries); - size_t const row_bytes(((31 + (header.info.width * header.info.bpp)) >> 5) << 2); - size_t const mask_row_bytes(((31 + header.info.width) >> 5) << 2); - size_t const required_size( - header.info.size + - palette_size + - ((row_bytes + (have_and_mask ? mask_row_bytes : 0U)) * header.info.height)); - if (required_size > dir.size) - { + // invalid DIB data or I/O error LOG( - "ICO file image data at %u (%u bytes) smaller than calculated DIB data size (%u bytes)\n", + "Error %u reading DIB image data from ICO file at offset %u (directory size %u)\n", + unsigned(err), dir.offset, - dir.size, - required_size); + dir.size); return false; } - - // load the palette for indexed colour formats or the shifts for direct colour formats - unsigned red_shift(0), green_shift(0), blue_shift(0), alpha_shift(0); - unsigned red_bits(0), green_bits(0), blue_bits(0), alpha_bits(0); - std::unique_ptr<rgb_t []> palette; - if (indexed) - { - // read palette and convert - std::unique_ptr<uint8_t []> palette_data(new uint8_t [palette_size]); - if (fp.read(palette_data.get(), palette_size) != palette_size) - { - LOG("Error reading palette from ICO file DIB image data at %u (%u bytes)\n", dir.offset, dir.size); - return false; - } - size_t const palette_usable(std::min<size_t>(palette_entries, size_t(1) << header.info.bpp)); - palette.reset(new rgb_t [palette_usable]); - uint8_t const *ptr(palette_data.get()); - for (size_t i = 0; palette_usable > i; ++i, ptr += palette_bytes) - palette[i] = rgb_t(ptr[2], ptr[1], ptr[0]); - } - else - { - // skip over the palette if necessary - if (palette_entries) - fp.seek(palette_bytes * palette_entries, SEEK_CUR); - - // convert masks to shifts - bool const masks_contiguous( - dib_parse_mask(header.info.red, red_shift, red_bits) && - dib_parse_mask(header.info.green, green_shift, green_bits) && - dib_parse_mask(header.info.blue, blue_shift, blue_bits) && - dib_parse_mask(header.info.alpha, alpha_shift, alpha_bits)); - if (!masks_contiguous) - { - osd_printf_verbose( - "ICO file DIB image data at %lu specifies non-contiguous channel masks 0x%lx | 0x%lx | 0x%lx | 0x%lx\n", - (unsigned long)dir.offset, - (unsigned long)header.info.red, - (unsigned long)header.info.green, - (unsigned long)header.info.blue, - (unsigned long)header.info.alpha); - } - if ((32U != header.info.bpp) && ((header.info.red | header.info.green | header.info.blue | header.info.alpha) >> header.info.bpp)) - { - LOG( - "ICO file DIB image data at %lu specifies channel masks 0x%x | 0x%x | 0x%x | 0x%x that exceed %u bits per pixel\n", - dir.offset, - header.info.red, - header.info.green, - header.info.blue, - header.info.alpha, - header.info.bpp); - return false; - } - LOGMASKED( - LOG_DIB, - "DIB from ICO file image data at %1$u using channels: R((x >> %3$u) & 0x%4$0*2$x) G((x >> %5$u) & 0x%6$0*2$x) B((x >> %7$u) & 0x%8$0*2$x) A((x >> %9$u) & 0x%10$0*2$x)\n", - dir.offset, - (header.info.bpp + 3) >> 2, - red_shift, - (uint32_t(1) << red_bits) - 1, - green_shift, - (uint32_t(1) << green_bits) - 1, - blue_shift, - (uint32_t(1) << blue_bits) - 1, - alpha_shift, - (uint32_t(1) << alpha_bits) - 1); - - // the MAME bitmap only supports 8 bits/sample maximum - dib_truncate_channel(red_shift, red_bits); - dib_truncate_channel(green_shift, green_bits); - dib_truncate_channel(blue_shift, blue_bits); - dib_truncate_channel(alpha_shift, alpha_bits); - } - - // allocate the bitmap and process row data - std::unique_ptr<uint8_t []> row_data(new uint8_t [row_bytes]); - bitmap.allocate(header.info.width, header.info.height); - int const y_inc(top_down ? 1 : -1); - for (int32_t i = 0, y = top_down ? 0 : (header.info.height - 1); header.info.height > i; ++i, y += y_inc) - { - if (fp.read(row_data.get(), row_bytes) != row_bytes) - { - LOG("Error reading DIB row %d data from ICO image data at %u\n", i, dir.offset); - return false; - } - uint8_t *src(row_data.get()); - uint32_t *dest(&bitmap.pix(y)); - unsigned shift(0U); - for (int32_t x = 0; header.info.width > x; ++x, ++dest) - { - // extract or compose a pixel - uint32_t pix(0U); - if (8U >= header.info.bpp) - { - assert(8U > shift); - pix = *src >> (8U - header.info.bpp); - *src <<= header.info.bpp; - shift += header.info.bpp; - if (8U <= shift) - { - shift = 0U; - ++src; - } - } - else for (shift = 0; header.info.bpp > shift; shift += 8U, ++src) - { - pix |= uint32_t(*src) << shift; - } - - // convert to RGB - if (indexed) - { - if (palette_entries > pix) - { - *dest = palette[pix]; - } - else - { - *dest = rgb_t::transparent(); - osd_printf_verbose( - "ICO file DIB image data at %lu has out-of-range color %lu at (%ld, %ld) with %lu palette entries\n", - (unsigned long)dir.offset, - (unsigned long)pix, - (long)x, - (long)y, - (unsigned long)palette_entries); - } - } - else - { - uint8_t r(dib_splat_sample((pix >> red_shift) & ((uint32_t(1) << red_bits) - 1), red_bits)); - uint8_t g(dib_splat_sample((pix >> green_shift) & ((uint32_t(1) << green_bits) - 1), green_bits)); - uint8_t b(dib_splat_sample((pix >> blue_shift) & ((uint32_t(1) << blue_bits) - 1), blue_bits)); - uint8_t a(dib_splat_sample((pix >> alpha_shift) & ((uint32_t(1) << alpha_bits) - 1), alpha_bits)); - *dest = rgb_t(alpha_bits ? a : 255, r, g, b); - } - } - } - - // process the AND mask if present - if (have_and_mask) - { - for (int32_t i = 0, y = top_down ? 0 : (header.info.height - 1); header.info.height > i; ++i, y += y_inc) - { - if (fp.read(row_data.get(), mask_row_bytes) != mask_row_bytes) - { - LOG("Error reading DIB mask row %d data from ICO image data at %u\n", i, dir.offset); - return false; - } - uint8_t *src(row_data.get()); - uint32_t *dest(&bitmap.pix(y)); - unsigned shift(0U); - for (int32_t x = 0; header.info.width > x; ++x, ++dest) - { - assert(8U > shift); - rgb_t pix(*dest); - *dest = pix.set_a(BIT(*src, 7U - shift) ? 0U : pix.a()); - if (8U <= ++shift) - { - shift = 0U; - ++src; - } - } - } - } - - // we're done! - return true; } diff --git a/src/frontend/mame/ui/inputmap.cpp b/src/frontend/mame/ui/inputmap.cpp index 33cbd9223e0..bfb68e40da0 100644 --- a/src/frontend/mame/ui/inputmap.cpp +++ b/src/frontend/mame/ui/inputmap.cpp @@ -93,7 +93,7 @@ void menu_input_general::populate(float &customtop, float &custombottom) item.type = ioport_manager::type_is_analog(entry.type()) ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL; item.is_optional = false; item.name = entry.name(); - item.owner_name = nullptr; + item.owner = nullptr; // stop after one, unless we're analog if (item.type == INPUT_TYPE_DIGITAL) @@ -164,7 +164,7 @@ void menu_input_specific::populate(float &customtop, float &custombottom) item.type = field.is_analog() ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL; item.is_optional = field.optional(); item.name = field.name(); - item.owner_name = field.device().tag(); + item.owner = &field.device(); // stop after one, unless we're analog if (item.type == INPUT_TYPE_DIGITAL) @@ -180,7 +180,7 @@ void menu_input_specific::populate(float &customtop, float &custombottom) data.end(), [] (const input_item_data &i1, const input_item_data &i2) { - int cmp = strcmp(i1.owner_name, i2.owner_name); + int cmp = strcmp(i1.owner->tag(), i2.owner->tag()); if (cmp < 0) return true; if (cmp > 0) @@ -431,21 +431,24 @@ void menu_input::populate_sorted(float &customtop, float &custombottom) // build the menu std::string text, subtext; - std::string prev_owner; + const device_t *prev_owner = nullptr; bool first_entry = true; for (input_item_data &item : data) { // generate the name of the item itself, based off the base name and the type assert(nameformat[item.type] != nullptr); - if (item.owner_name && strcmp(item.owner_name, prev_owner.c_str()) != 0) + if (item.owner && (item.owner != prev_owner)) { if (first_entry) first_entry = false; else item_append(menu_item_type::SEPARATOR); - item_append(string_format("[root%s]", item.owner_name), "", 0, nullptr); - prev_owner.assign(item.owner_name); + if (item.owner->owner()) + item_append(string_format(_("%1$s [root%2$s]"), item.owner->type().fullname(), item.owner->tag()), "", 0, nullptr); + else + item_append(string_format(_("[root%1$s]"), item.owner->tag()), "", 0, nullptr); + prev_owner = item.owner; } text = string_format(nameformat[item.type], item.name); diff --git a/src/frontend/mame/ui/inputmap.h b/src/frontend/mame/ui/inputmap.h index d2e41780211..01649b0b1ef 100644 --- a/src/frontend/mame/ui/inputmap.h +++ b/src/frontend/mame/ui/inputmap.h @@ -55,7 +55,7 @@ protected: input_seq seq; // copy of the live sequence const input_seq * defseq = nullptr; // pointer to the default sequence const char * name = nullptr; // pointer to the base name of the item - const char * owner_name = nullptr; // pointer to the name of the owner of the item + const device_t * owner = nullptr; // pointer to the owner of the item ioport_group group = IPG_INVALID; // group type uint8_t type = 0U; // type of port bool is_optional = false; // true if this input is considered optional diff --git a/src/frontend/mame/ui/keyboard.cpp b/src/frontend/mame/ui/keyboard.cpp new file mode 100644 index 00000000000..3d58d28d2d9 --- /dev/null +++ b/src/frontend/mame/ui/keyboard.cpp @@ -0,0 +1,98 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + ui/keyboard.cpp + + Keyboard mode menu. + +***************************************************************************/ + +#include "emu.h" +#include "ui/keyboard.h" + +#include "natkeyboard.h" + + +namespace ui { + +namespace { + +constexpr uintptr_t ITEM_KBMODE = 0x00000100; +constexpr uintptr_t ITEM_KBDEV_FIRST = 0x00000200; + +} // anonymous namespace + + +menu_keyboard_mode::menu_keyboard_mode(mame_ui_manager &mui, render_container &container) : menu(mui, container) +{ +} + +void menu_keyboard_mode::populate(float &customtop, float &custombottom) +{ + natural_keyboard &natkbd(machine().ioport().natkeyboard()); + + if (natkbd.can_post()) + { + bool const natmode(natkbd.in_use()); + item_append( + _("Keyboard Mode"), + natmode ? _("Natural") : _("Emulated"), + natmode ? FLAG_LEFT_ARROW : FLAG_RIGHT_ARROW, + reinterpret_cast<void *>(ITEM_KBMODE)); + item_append(menu_item_type::SEPARATOR); + } + + uintptr_t ref(ITEM_KBDEV_FIRST); + for (size_t i = 0; natkbd.keyboard_count() > i; ++i, ++ref) + { + device_t &kbddev(natkbd.keyboard_device(i)); + bool const enabled(natkbd.keyboard_enabled(i)); + item_append( + util::string_format( + kbddev.owner() ? _("%1$s [root%2$s]") : _("[root%2$s]"), + kbddev.type().fullname(), + kbddev.tag()), + enabled ? _("Enabled") : _("Disabled"), + enabled ? FLAG_LEFT_ARROW : FLAG_RIGHT_ARROW, + reinterpret_cast<void *>(ref)); + } + item_append(menu_item_type::SEPARATOR); +} + +menu_keyboard_mode::~menu_keyboard_mode() +{ +} + +void menu_keyboard_mode::handle() +{ + event const *const menu_event(process(0)); + if (menu_event && uintptr_t(menu_event->itemref)) + { + natural_keyboard &natkbd(machine().ioport().natkeyboard()); + uintptr_t const ref(uintptr_t(menu_event->itemref)); + bool const left(IPT_UI_LEFT == menu_event->iptkey); + bool const right(IPT_UI_RIGHT == menu_event->iptkey); + if (ITEM_KBMODE == ref) + { + if ((left || right) && (natkbd.in_use() != right)) + { + natkbd.set_in_use(right); + reset(reset_options::REMEMBER_REF); + } + } + else if (ITEM_KBDEV_FIRST <= ref) + { + if ((left || right) && (natkbd.keyboard_enabled(ref - ITEM_KBDEV_FIRST) != right)) + { + if (right) + natkbd.enable_keyboard(ref - ITEM_KBDEV_FIRST); + else + natkbd.disable_keyboard(ref - ITEM_KBDEV_FIRST); + reset(reset_options::REMEMBER_REF); + } + } + } +} + +} // namespace ui diff --git a/src/frontend/mame/ui/keyboard.h b/src/frontend/mame/ui/keyboard.h new file mode 100644 index 00000000000..899385e74c2 --- /dev/null +++ b/src/frontend/mame/ui/keyboard.h @@ -0,0 +1,33 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + ui/keyboard.h + + Keyboard mode menu. + +***************************************************************************/ +#ifndef MAME_FRONTEND_UI_KEYBOARD_H +#define MAME_FRONTEND_UI_KEYBOARD_H + +#pragma once + +#include "ui/menu.h" + + +namespace ui { + +class menu_keyboard_mode : public menu +{ +public: + menu_keyboard_mode(mame_ui_manager &mui, render_container &container); + virtual ~menu_keyboard_mode(); + +private: + virtual void populate(float &customtop, float &custombottom) override; + virtual void handle() override; +}; + +} // namespace ui + +#endif // MAME_FRONTEND_UI_KEYBOARD_H diff --git a/src/frontend/mame/ui/mainmenu.cpp b/src/frontend/mame/ui/mainmenu.cpp index bd7f274da29..b1a0e238935 100644 --- a/src/frontend/mame/ui/mainmenu.cpp +++ b/src/frontend/mame/ui/mainmenu.cpp @@ -22,6 +22,7 @@ #include "ui/info_pty.h" #include "ui/inifile.h" #include "ui/inputmap.h" +#include "ui/keyboard.h" #include "ui/miscmenu.h" #include "ui/pluginopt.h" #include "ui/selgame.h" @@ -108,7 +109,7 @@ void menu_main::populate(float &customtop, float &custombottom) if (network_interface_iterator(machine().root_device()).first() != nullptr) item_append(_("Network Devices"), "", 0, (void*)NETWORK_DEVICES); - if (ui().machine_info().has_keyboard() && machine().ioport().natkeyboard().can_post()) + if (machine().ioport().natkeyboard().keyboard_count()) item_append(_("Keyboard Mode"), "", 0, (void *)KEYBOARD_MODE); item_append(_("Slider Controls"), "", 0, (void *)SLIDERS); diff --git a/src/frontend/mame/ui/menu.cpp b/src/frontend/mame/ui/menu.cpp index 7ce0beb0fb1..b0a84d3a95c 100644 --- a/src/frontend/mame/ui/menu.cpp +++ b/src/frontend/mame/ui/menu.cpp @@ -92,10 +92,17 @@ menu::global_state::global_state(running_machine &machine, ui_options const &opt { m_bgrnd_bitmap = std::make_unique<bitmap_argb32>(0, 0); emu_file backgroundfile(".", OPEN_FLAG_READ); - render_load_jpeg(*m_bgrnd_bitmap, backgroundfile, nullptr, "background.jpg"); + if (backgroundfile.open("background.jpg") == osd_file::error::NONE) + { + render_load_jpeg(*m_bgrnd_bitmap, backgroundfile); + backgroundfile.close(); + } - if (!m_bgrnd_bitmap->valid()) - render_load_png(*m_bgrnd_bitmap, backgroundfile, nullptr, "background.png"); + if (!m_bgrnd_bitmap->valid() && (backgroundfile.open("background.png") == osd_file::error::NONE)) + { + render_load_png(*m_bgrnd_bitmap, backgroundfile); + backgroundfile.close(); + } if (m_bgrnd_bitmap->valid()) m_bgrnd_texture->set_bitmap(*m_bgrnd_bitmap, m_bgrnd_bitmap->cliprect(), TEXFORMAT_ARGB32); @@ -904,110 +911,110 @@ void menu::handle_events(uint32_t flags, event &ev) { 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 (custom_mouse_down()) - return; + // if we are hovering over a valid item, select it with a single click + case ui_event::type::MOUSE_DOWN: + if (custom_mouse_down()) + return; - if ((flags & PROCESS_ONLYCHAR) == 0) + if ((flags & PROCESS_ONLYCHAR) == 0) + { + if (m_hover >= 0 && m_hover < m_items.size()) + m_selected = m_hover; + else if (m_hover == HOVER_ARROW_UP) { - if (m_hover >= 0 && m_hover < m_items.size()) - m_selected = m_hover; - else if (m_hover == HOVER_ARROW_UP) + if ((flags & FLAG_UI_DATS) != 0) { - if ((flags & FLAG_UI_DATS) != 0) - { - top_line -= m_visible_items - (last_item_visible() ? 1 : 0); - return; - } - m_selected -= m_visible_items; - if (m_selected < 0) - m_selected = 0; top_line -= m_visible_items - (last_item_visible() ? 1 : 0); + return; } - else if (m_hover == HOVER_ARROW_DOWN) + m_selected -= m_visible_items; + if (m_selected < 0) + m_selected = 0; + top_line -= m_visible_items - (last_item_visible() ? 1 : 0); + } + else if (m_hover == HOVER_ARROW_DOWN) + { + if ((flags & FLAG_UI_DATS) != 0) { - if ((flags & FLAG_UI_DATS) != 0) - { - top_line += m_visible_lines - 2; - return; - } - m_selected += m_visible_lines - 2 + is_first_selected(); - if (m_selected > m_items.size() - 1) - m_selected = m_items.size() - 1; top_line += m_visible_lines - 2; + return; } + m_selected += m_visible_lines - 2 + is_first_selected(); + if (m_selected > m_items.size() - 1) + m_selected = m_items.size() - 1; + top_line += m_visible_lines - 2; } - break; + } + 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 & PROCESS_ONLYCHAR) && m_hover >= 0 && m_hover < m_items.size()) + // if we are hovering over a valid item, fake a UI_SELECT with a double-click + case ui_event::type::MOUSE_DOUBLE_CLICK: + if (!(flags & PROCESS_ONLYCHAR) && m_hover >= 0 && m_hover < m_items.size()) + { + m_selected = m_hover; + ev.iptkey = IPT_UI_SELECT; + if (is_last_selected()) { - m_selected = m_hover; - ev.iptkey = IPT_UI_SELECT; - if (is_last_selected()) + ev.iptkey = IPT_UI_CANCEL; + stack_pop(); + } + stop = true; + } + break; + + // caught scroll event + case ui_event::type::MOUSE_WHEEL: + if (!(flags & PROCESS_ONLYCHAR)) + { + if (local_menu_event.zdelta > 0) + { + if ((flags & FLAG_UI_DATS) != 0) { - ev.iptkey = IPT_UI_CANCEL; - stack_pop(); + top_line -= local_menu_event.num_lines; + return; } - stop = true; + if (is_first_selected()) + select_last_item(); + else + { + m_selected -= local_menu_event.num_lines; + validate_selection(-1); + } + top_line -= (m_selected <= top_line && top_line != 0); + if (m_selected <= top_line && m_visible_items != m_visible_lines) + top_line -= local_menu_event.num_lines; } - break; - - // caught scroll event - case ui_event::MOUSE_WHEEL: - if (!(flags & PROCESS_ONLYCHAR)) + else { - if (local_menu_event.zdelta > 0) + if ((flags & FLAG_UI_DATS)) { - if ((flags & FLAG_UI_DATS) != 0) - { - top_line -= local_menu_event.num_lines; - return; - } - if (is_first_selected()) - select_last_item(); - else - { - m_selected -= local_menu_event.num_lines; - validate_selection(-1); - } - top_line -= (m_selected <= top_line && top_line != 0); - if (m_selected <= top_line && m_visible_items != m_visible_lines) - top_line -= local_menu_event.num_lines; + top_line += local_menu_event.num_lines; + return; } + if (is_last_selected()) + select_first_item(); else { - if ((flags & FLAG_UI_DATS)) - { - top_line += local_menu_event.num_lines; - return; - } - if (is_last_selected()) - select_first_item(); - else - { - m_selected += local_menu_event.num_lines; - validate_selection(1); - } - top_line += (m_selected >= top_line + m_visible_items + (top_line != 0)); - if (m_selected >= (top_line + m_visible_items + (top_line != 0))) - top_line += local_menu_event.num_lines; + m_selected += local_menu_event.num_lines; + validate_selection(1); } + top_line += (m_selected >= top_line + m_visible_items + (top_line != 0)); + if (m_selected >= (top_line + m_visible_items + (top_line != 0))) + top_line += local_menu_event.num_lines; } - break; + } + break; - // translate CHAR events into specials - case ui_event::IME_CHAR: - ev.iptkey = IPT_SPECIAL; - ev.unichar = local_menu_event.ch; - stop = true; - break; + // translate CHAR events into specials + case ui_event::type::IME_CHAR: + ev.iptkey = IPT_SPECIAL; + ev.unichar = local_menu_event.ch; + stop = true; + break; - // ignore everything else - default: - break; + // ignore everything else + default: + break; } } } @@ -1234,7 +1241,7 @@ uint32_t menu::ui_handler(render_container &container, mame_ui_manager &mui) // if we have no menus stacked up, start with the main menu if (!state->topmost_menu<menu>()) - state->stack_push(std::unique_ptr<menu>(global_alloc_clear<menu_main>(mui, container))); + state->stack_push(std::unique_ptr<menu>(make_unique_clear<menu_main>(mui, container))); // update the menu state if (state->topmost_menu<menu>()) diff --git a/src/frontend/mame/ui/menu.h b/src/frontend/mame/ui/menu.h index 800b0b6ca7b..5a7d4374bf6 100644 --- a/src/frontend/mame/ui/menu.h +++ b/src/frontend/mame/ui/menu.h @@ -100,12 +100,12 @@ public: template <typename T, typename... Params> static void stack_push(Params &&... args) { - stack_push(std::unique_ptr<menu>(global_alloc_clear<T>(std::forward<Params>(args)...))); + stack_push(std::unique_ptr<menu>(make_unique_clear<T>(std::forward<Params>(args)...))); } template <typename T, typename... Params> static void stack_push_special_main(Params &&... args) { - std::unique_ptr<menu> ptr(global_alloc_clear<T>(std::forward<Params>(args)...)); + std::unique_ptr<menu> ptr(make_unique_clear<T>(std::forward<Params>(args)...)); ptr->set_special_main_menu(true); stack_push(std::move(ptr)); } diff --git a/src/frontend/mame/ui/miscmenu.cpp b/src/frontend/mame/ui/miscmenu.cpp index 82b7916e3a5..f0ab531360e 100644 --- a/src/frontend/mame/ui/miscmenu.cpp +++ b/src/frontend/mame/ui/miscmenu.cpp @@ -23,7 +23,6 @@ #include "mameopts.h" #include "pluginopts.h" #include "drivenum.h" -#include "natkeyboard.h" #include "romload.h" #include "uiinput.h" @@ -41,42 +40,6 @@ namespace ui { ***************************************************************************/ /*------------------------------------------------- - menu_keyboard_mode - menu that --------------------------------------------------*/ - -menu_keyboard_mode::menu_keyboard_mode(mame_ui_manager &mui, render_container &container) : menu(mui, container) -{ -} - -void menu_keyboard_mode::populate(float &customtop, float &custombottom) -{ - bool natural = machine().ioport().natkeyboard().in_use(); - item_append(_("Keyboard Mode:"), natural ? _("Natural") : _("Emulated"), natural ? FLAG_LEFT_ARROW : FLAG_RIGHT_ARROW, nullptr); -} - -menu_keyboard_mode::~menu_keyboard_mode() -{ -} - -void menu_keyboard_mode::handle() -{ - bool natural = machine().ioport().natkeyboard().in_use(); - - /* process the menu */ - const event *menu_event = process(0); - - if (menu_event != nullptr) - { - if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) - { - machine().ioport().natkeyboard().set_in_use(!natural); - reset(reset_options::REMEMBER_REF); - } - } -} - - -/*------------------------------------------------- menu_bios_selection - populates the main bios selection menu -------------------------------------------------*/ diff --git a/src/frontend/mame/ui/miscmenu.h b/src/frontend/mame/ui/miscmenu.h index acff544dee6..c8d833ae4e2 100644 --- a/src/frontend/mame/ui/miscmenu.h +++ b/src/frontend/mame/ui/miscmenu.h @@ -7,7 +7,6 @@ Internal MAME menus for the user interface. ***************************************************************************/ - #ifndef MAME_FRONTEND_UI_MISCMENU_H #define MAME_FRONTEND_UI_MISCMENU_H @@ -24,17 +23,6 @@ namespace ui { -class menu_keyboard_mode : public menu -{ -public: - menu_keyboard_mode(mame_ui_manager &mui, render_container &container); - virtual ~menu_keyboard_mode(); - -private: - virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; -}; - class menu_network_devices : public menu { public: diff --git a/src/frontend/mame/ui/selgame.cpp b/src/frontend/mame/ui/selgame.cpp index 6944031e344..13a63965f65 100644 --- a/src/frontend/mame/ui/selgame.cpp +++ b/src/frontend/mame/ui/selgame.cpp @@ -786,32 +786,33 @@ void menu_select_game::inkey_select(const event *menu_event) else { // anything else is a driver - - // audit the game first to see if we're going to work driver_enumerator enumerator(machine().options(), *driver); enumerator.next(); + + // if there are software entries, show a software selection menu + for (software_list_device &swlistdev : software_list_device_iterator(enumerator.config()->root_device())) + { + if (!swlistdev.get_info().empty()) + { + menu::stack_push<menu_select_software>(ui(), container(), *driver); + return; + } + } + + // audit the system ROMs first to see if we're going to work media_auditor auditor(enumerator); media_auditor::summary const 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) { - for (software_list_device &swlistdev : software_list_device_iterator(enumerator.config()->root_device())) - { - if (!swlistdev.get_info().empty()) - { - menu::stack_push<menu_select_software>(ui(), container(), *driver); - return; - } - } - if (!select_bios(*driver, false)) launch_system(*driver); } else { // otherwise, display an error - set_error(reset_options::REMEMBER_REF, make_error_text(media_auditor::NOTFOUND != summary, auditor)); + set_error(reset_options::REMEMBER_REF, make_audit_fail_text(media_auditor::NOTFOUND != summary, auditor)); } } } @@ -858,23 +859,25 @@ void menu_select_game::inkey_select_favorite(const event *menu_event) } 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 const summary = auditor.audit_media(AUDIT_VALIDATE_FAST); - if (summary == media_auditor::CORRECT || summary == media_auditor::BEST_AVAILABLE || summary == media_auditor::NONE_NEEDED) + // if there are software entries, show a software selection menu + for (software_list_device &swlistdev : software_list_device_iterator(enumerator.config()->root_device())) { - for (software_list_device &swlistdev : software_list_device_iterator(enumerator.config()->root_device())) + if (!swlistdev.get_info().empty()) { - if (!swlistdev.get_info().empty()) - { - menu::stack_push<menu_select_software>(ui(), container(), *ui_swinfo->driver); - return; - } + menu::stack_push<menu_select_software>(ui(), container(), *ui_swinfo->driver); + return; } + } + + // audit the system ROMs first to see if we're going to work + media_auditor auditor(enumerator); + media_auditor::summary const summary = auditor.audit_media(AUDIT_VALIDATE_FAST); + if (summary == media_auditor::CORRECT || summary == media_auditor::BEST_AVAILABLE || summary == media_auditor::NONE_NEEDED) + { // if everything looks good, schedule the new driver if (!select_bios(*ui_swinfo->driver, false)) { @@ -885,7 +888,7 @@ void menu_select_game::inkey_select_favorite(const event *menu_event) else { // otherwise, display an error - set_error(reset_options::REMEMBER_REF, make_error_text(media_auditor::NOTFOUND != summary, auditor)); + set_error(reset_options::REMEMBER_REF, make_audit_fail_text(media_auditor::NOTFOUND != summary, auditor)); } } else @@ -907,7 +910,7 @@ void menu_select_game::inkey_select_favorite(const event *menu_event) else { // otherwise, display an error - set_error(reset_options::REMEMBER_POSITION, make_error_text(media_auditor::NOTFOUND != summary, auditor)); + set_error(reset_options::REMEMBER_POSITION, make_audit_fail_text(media_auditor::NOTFOUND != summary, auditor)); } } } @@ -1455,18 +1458,4 @@ void menu_select_game::filter_selected() } } - -std::string menu_select_game::make_error_text(bool summary, media_auditor const &auditor) -{ - std::ostringstream str; - str << _("The selected machine is missing one or more required ROM or CHD images. Please select a different machine.\n\n"); - if (summary) - { - auditor.summarize(nullptr, &str); - str << "\n"; - } - str << _("Press any key to continue."); - return str.str(); -} - } // namespace ui diff --git a/src/frontend/mame/ui/selgame.h b/src/frontend/mame/ui/selgame.h index da65fee98ce..13bfd1170ac 100644 --- a/src/frontend/mame/ui/selgame.h +++ b/src/frontend/mame/ui/selgame.h @@ -18,8 +18,6 @@ #include <functional> -class media_auditor; - namespace ui { class menu_select_game : public menu_select_launch @@ -86,8 +84,6 @@ private: bool load_available_machines(); void load_custom_filters(); - static std::string make_error_text(bool summary, media_auditor const &auditor); - // General info virtual void general_info(const game_driver *driver, std::string &buffer) override; diff --git a/src/frontend/mame/ui/selmenu.cpp b/src/frontend/mame/ui/selmenu.cpp index 92bdd3ada64..9a58691b988 100644 --- a/src/frontend/mame/ui/selmenu.cpp +++ b/src/frontend/mame/ui/selmenu.cpp @@ -20,6 +20,7 @@ #include "ui/starimg.ipp" #include "ui/toolbar.ipp" +#include "audit.h" #include "cheat.h" #include "mame.h" #include "mameopts.h" @@ -94,6 +95,62 @@ char const *const hover_msg[] = { __("Show DATs view"), }; + +void load_image(bitmap_argb32 &bitmap, emu_file &file, std::string const &base) +{ + if (file.open(base + ".png") == osd_file::error::NONE) + { + render_load_png(bitmap, file); + file.close(); + } + + if (!bitmap.valid() && (file.open(base + ".jpg") == osd_file::error::NONE)) + { + render_load_jpeg(bitmap, file); + file.close(); + } + + if (!bitmap.valid() && (file.open(base + ".bmp") == osd_file::error::NONE)) + { + render_load_msdib(bitmap, file); + file.close(); + } +} + + +void load_driver_image(bitmap_argb32 &bitmap, emu_file &file, game_driver const &driver) +{ + // try to load snapshot first from saved "0000.png" file + std::string fullname = driver.name; + load_image(bitmap, file, fullname + PATH_SEPARATOR + "0000"); + + // if fail, attempt to load from standard file + if (!bitmap.valid()) + load_image(bitmap, file, fullname); + + // if fail again, attempt to load from parent file + if (!bitmap.valid()) + { + // ignore BIOS sets + bool isclone = strcmp(driver.parent, "0") != 0; + if (isclone) + { + int const cx = driver_list::find(driver.parent); + if ((0 <= cx) && (driver_list::driver(cx).flags & machine_flags::IS_BIOS_ROOT)) + isclone = false; + } + + if (isclone) + { + fullname = driver.parent; + load_image(bitmap, file, fullname + PATH_SEPARATOR + "0000"); + + if (!bitmap.valid()) + load_image(bitmap, file, fullname); + } + } +} + } // anonymous namespace constexpr std::size_t menu_select_launch::MAX_VISIBLE_SEARCH; // stupid non-inline semantics @@ -392,9 +449,9 @@ menu_select_launch::cache::cache(running_machine &machine) // create a texture for snapshot m_snapx_texture.reset(render.texture_alloc(render_texture::hq_scale)); - std::memcpy(&m_no_avail_bitmap.pix32(0), no_avail_bmp, 256 * 256 * sizeof(uint32_t)); + std::memcpy(&m_no_avail_bitmap.pix(0), no_avail_bmp, 256 * 256 * sizeof(uint32_t)); - std::memcpy(&m_star_bitmap.pix32(0), favorite_star_bmp, 32 * 32 * sizeof(uint32_t)); + std::memcpy(&m_star_bitmap.pix(0), favorite_star_bmp, 32 * 32 * sizeof(uint32_t)); m_star_texture.reset(render.texture_alloc()); m_star_texture->set_bitmap(m_star_bitmap, m_star_bitmap.cliprect(), TEXFORMAT_ARGB32); @@ -410,7 +467,7 @@ menu_select_launch::cache::cache(running_machine &machine) m_toolbar_texture.emplace_back(render.texture_alloc(), render); m_sw_toolbar_texture.emplace_back(render.texture_alloc(), render); - std::memcpy(&m_toolbar_bitmap.back().pix32(0), toolbar_bitmap_bmp[i], 32 * 32 * sizeof(uint32_t)); + std::memcpy(&m_toolbar_bitmap.back().pix(0), toolbar_bitmap_bmp[i], 32 * 32 * sizeof(uint32_t)); if (m_toolbar_bitmap.back().valid()) m_toolbar_texture.back()->set_bitmap(m_toolbar_bitmap.back(), m_toolbar_bitmap.back().cliprect(), TEXFORMAT_ARGB32); else @@ -418,7 +475,7 @@ menu_select_launch::cache::cache(running_machine &machine) if ((i == 0U) || (i == 2U)) { - std::memcpy(&m_sw_toolbar_bitmap.back().pix32(0), toolbar_bitmap_bmp[i], 32 * 32 * sizeof(uint32_t)); + std::memcpy(&m_sw_toolbar_bitmap.back().pix(0), toolbar_bitmap_bmp[i], 32 * 32 * sizeof(uint32_t)); if (m_sw_toolbar_bitmap.back().valid()) m_sw_toolbar_texture.back()->set_bitmap(m_sw_toolbar_bitmap.back(), m_sw_toolbar_bitmap.back().cliprect(), TEXFORMAT_ARGB32); else @@ -1147,7 +1204,7 @@ bool menu_select_launch::scale_icon(bitmap_argb32 &&src, texture_and_bitmap &dst dst.bitmap.allocate(max_width, max_height); for (int y = 0; tmp.height() > y; ++y) for (int x = 0; tmp.width() > x; ++x) - dst.bitmap.pix32(y, x) = tmp.pix32(y, x); + dst.bitmap.pix(y, x) = tmp.pix(y, x); dst.texture->set_bitmap(dst.bitmap, dst.bitmap.cliprect(), TEXFORMAT_ARGB32); return true; } @@ -1604,7 +1661,7 @@ void menu_select_launch::handle_events(uint32_t flags, event &ev) 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: + case ui_event::type::MOUSE_DOWN: if (m_ui_error) { ev.iptkey = IPT_OTHER; @@ -1704,7 +1761,7 @@ void menu_select_launch::handle_events(uint32_t flags, event &ev) break; // if we are hovering over a valid item, fake a UI_SELECT with a double-click - case ui_event::MOUSE_DOUBLE_CLICK: + case ui_event::type::MOUSE_DOUBLE_CLICK: if (hover() >= 0 && hover() < item_count()) { set_selected_index(hover()); @@ -1720,7 +1777,7 @@ void menu_select_launch::handle_events(uint32_t flags, event &ev) break; // caught scroll event - case ui_event::MOUSE_WHEEL: + case ui_event::type::MOUSE_WHEEL: if (hover() >= 0 && hover() < item_count() - skip_main_items - 1) { if (local_menu_event.zdelta > 0) @@ -1750,7 +1807,7 @@ void menu_select_launch::handle_events(uint32_t flags, event &ev) break; // translate CHAR events into specials - case ui_event::IME_CHAR: + case ui_event::type::IME_CHAR: if (exclusive_input_pressed(ev.iptkey, IPT_UI_FOCUS_NEXT, 0) || exclusive_input_pressed(ev.iptkey, IPT_UI_FOCUS_PREV, 0)) { stop = true; @@ -1767,7 +1824,7 @@ void menu_select_launch::handle_events(uint32_t flags, event &ev) } break; - case ui_event::MOUSE_RDOWN: + case ui_event::type::MOUSE_RDOWN: if (hover() >= 0 && hover() < item_count() - skip_main_items - 1) { set_selected_index(hover()); @@ -1790,18 +1847,18 @@ void menu_select_launch::handle_events(uint32_t flags, event &ev) { switch (machine().ui_input().peek_event_type()) { - case ui_event::MOUSE_DOWN: - case ui_event::MOUSE_RDOWN: - case ui_event::MOUSE_DOUBLE_CLICK: - case ui_event::MOUSE_WHEEL: + case ui_event::type::MOUSE_DOWN: + case ui_event::type::MOUSE_RDOWN: + case ui_event::type::MOUSE_DOUBLE_CLICK: + case ui_event::type::MOUSE_WHEEL: stop = true; break; - case ui_event::NONE: - case ui_event::MOUSE_MOVE: - case ui_event::MOUSE_LEAVE: - case ui_event::MOUSE_UP: - case ui_event::MOUSE_RUP: - case ui_event::IME_CHAR: + case ui_event::type::NONE: + case ui_event::type::MOUSE_MOVE: + case ui_event::type::MOUSE_LEAVE: + case ui_event::type::MOUSE_UP: + case ui_event::type::MOUSE_RUP: + case ui_event::type::IME_CHAR: break; } } @@ -2225,41 +2282,16 @@ void menu_select_launch::arts_render(float origx1, float origy1, float origx2, f if (software->startempty == 1) { // Load driver snapshot - std::string fullname = std::string(software->driver->name) + ".png"; - render_load_png(tmp_bitmap, snapfile, nullptr, fullname.c_str()); - - if (!tmp_bitmap.valid()) - { - fullname.assign(software->driver->name).append(".jpg"); - render_load_jpeg(tmp_bitmap, snapfile, nullptr, fullname.c_str()); - } + load_driver_image(tmp_bitmap, snapfile, *software->driver); } else { // First attempt from name list - std::string pathname = software->listname; - std::string fullname = software->shortname + ".png"; - render_load_png(tmp_bitmap, snapfile, pathname.c_str(), fullname.c_str()); + load_image(tmp_bitmap, snapfile, software->listname + PATH_SEPARATOR + software->shortname); + // Second attempt from driver name + part name if (!tmp_bitmap.valid()) - { - fullname.assign(software->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(software->driver->name).append(software->part); - fullname.assign(software->shortname).append(".png"); - render_load_png(tmp_bitmap, snapfile, pathname.c_str(), fullname.c_str()); - - if (!tmp_bitmap.valid()) - { - fullname.assign(software->shortname).append(".jpg"); - render_load_jpeg(tmp_bitmap, snapfile, pathname.c_str(), fullname.c_str()); - } - } + load_image(tmp_bitmap, snapfile, software->driver->name + software->part + PATH_SEPARATOR + software->shortname); } m_cache->set_snapx_software(software); @@ -2284,51 +2316,7 @@ void menu_select_launch::arts_render(float origx1, float origy1, float origx2, f { emu_file snapfile(searchstr, OPEN_FLAG_READ); bitmap_argb32 tmp_bitmap; - - // 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 >= 0) && (driver_list::driver(cx).flags & machine_flags::IS_BIOS_ROOT)) - 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()); - } - } - } + load_driver_image(tmp_bitmap, snapfile, *driver); m_cache->set_snapx_driver(driver); m_switch_image = false; @@ -2412,7 +2400,7 @@ void menu_select_launch::arts_render_images(bitmap_argb32 &&tmp_bitmap, float or for (int x = 0; x < 256; x++) { for (int y = 0; y < 256; y++) - tmp_bitmap.pix32(y, x) = src.pix32(y, x); + tmp_bitmap.pix(y, x) = src.pix(y, x); } no_available = true; } @@ -2475,7 +2463,7 @@ void menu_select_launch::arts_render_images(bitmap_argb32 &&tmp_bitmap, float or 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); + snapx_bitmap.pix(y + y1, x + x1) = dest_bitmap.pix(y, x); // apply bitmap m_cache->snapx_texture()->set_bitmap(snapx_bitmap, snapx_bitmap.cliprect(), TEXFORMAT_ARGB32); @@ -2508,6 +2496,20 @@ void menu_select_launch::draw_snapx(float origx1, float origy1, float origx2, fl } +std::string menu_select_launch::make_audit_fail_text(bool found, media_auditor const &auditor) +{ + std::ostringstream str; + str << _("The selected machine is missing one or more required ROM or CHD images. Please select a different machine.\n\n"); + if (found) + { + auditor.summarize(nullptr, &str); + str << "\n"; + } + str << _("Press any key to continue."); + return str.str(); +} + + //------------------------------------------------- // get bios count //------------------------------------------------- diff --git a/src/frontend/mame/ui/selmenu.h b/src/frontend/mame/ui/selmenu.h index e3d532e9cc3..5a3bee798f7 100644 --- a/src/frontend/mame/ui/selmenu.h +++ b/src/frontend/mame/ui/selmenu.h @@ -20,6 +20,7 @@ #include <vector> +class media_auditor; struct ui_software_info; namespace ui { @@ -155,6 +156,8 @@ protected: return (uintptr_t(selected_ref) > skip_main_items) ? selected_ref : m_prev_selected; } + static std::string make_audit_fail_text(bool found, media_auditor const &auditor); + int m_available_items; int skip_main_items; void *m_prev_selected; diff --git a/src/frontend/mame/ui/selsoft.cpp b/src/frontend/mame/ui/selsoft.cpp index 84fa109bea6..5a14e3dac7f 100644 --- a/src/frontend/mame/ui/selsoft.cpp +++ b/src/frontend/mame/ui/selsoft.cpp @@ -468,8 +468,17 @@ void menu_select_software::build_software_list() void menu_select_software::inkey_select(const event *menu_event) { ui_software_info *ui_swinfo = (ui_software_info *)menu_event->itemref; + driver_enumerator drivlist(machine().options(), *ui_swinfo->driver); + media_auditor auditor(drivlist); + drivlist.next(); - if (ui_swinfo->startempty == 1) + // audit the system ROMs first to see if we're going to work + media_auditor::summary const sysaudit = auditor.audit_media(AUDIT_VALIDATE_FAST); + if (sysaudit != media_auditor::CORRECT && sysaudit != media_auditor::BEST_AVAILABLE && sysaudit != media_auditor::NONE_NEEDED) + { + set_error(reset_options::REMEMBER_REF, make_audit_fail_text(media_auditor::NOTFOUND != sysaudit, auditor)); + } + else if (ui_swinfo->startempty == 1) { if (!select_bios(*ui_swinfo->driver, true)) { @@ -479,16 +488,13 @@ void menu_select_software::inkey_select(const event *menu_event) } else { - // first validate - driver_enumerator drivlist(machine().options(), *ui_swinfo->driver); - media_auditor auditor(drivlist); - drivlist.next(); + // first audit the software software_list_device *swlist = software_list_device::find_by_name(*drivlist.config(), ui_swinfo->listname); const software_info *swinfo = swlist->find(ui_swinfo->shortname); - media_auditor::summary const summary = auditor.audit_software(*swlist, *swinfo, AUDIT_VALIDATE_FAST); + media_auditor::summary const swaudit = auditor.audit_software(*swlist, *swinfo, AUDIT_VALIDATE_FAST); - if (summary == media_auditor::CORRECT || summary == media_auditor::BEST_AVAILABLE || summary == media_auditor::NONE_NEEDED) + if (swaudit == media_auditor::CORRECT || swaudit == media_auditor::BEST_AVAILABLE || swaudit == media_auditor::NONE_NEEDED) { if (!select_bios(*ui_swinfo, false) && !select_part(*swinfo, *ui_swinfo)) { @@ -500,11 +506,11 @@ void menu_select_software::inkey_select(const event *menu_event) { // otherwise, display an error std::ostringstream str; - str << _("The selected software is missing one or more required files. Please select a different software.\n\n"); - if (media_auditor::NOTFOUND != summary) + str << _("The selected software is missing one or more required files. Please select a different software item.\n\n"); + if (media_auditor::NOTFOUND != swaudit) { auditor.summarize(nullptr, &str); - str << "\n"; + str << '\n'; } str << _("Press any key to continue."), set_error(reset_options::REMEMBER_POSITION, str.str()); diff --git a/src/frontend/mame/ui/slider.h b/src/frontend/mame/ui/slider.h index 7785518d093..56da6849e81 100644 --- a/src/frontend/mame/ui/slider.h +++ b/src/frontend/mame/ui/slider.h @@ -25,12 +25,12 @@ typedef std::function<std::int32_t (running_machine &, void *, int, std::string struct slider_state { slider_update update; // callback - void * arg; // argument - std::int32_t minval; // minimum value - std::int32_t defval; // default value - std::int32_t maxval; // maximum value - std::int32_t incval; // increment value - int id; + void * arg = nullptr; // argument + std::int32_t minval = 0; // minimum value + std::int32_t defval = 0; // default value + std::int32_t maxval = 0; // maximum value + std::int32_t incval = 0; // increment value + int id = 0; std::string description; // textual description }; diff --git a/src/frontend/mame/ui/text.cpp b/src/frontend/mame/ui/text.cpp index 6df9ff29049..0e61b1710db 100644 --- a/src/frontend/mame/ui/text.cpp +++ b/src/frontend/mame/ui/text.cpp @@ -295,7 +295,7 @@ float text_layout::actual_height() const void text_layout::start_new_line(text_layout::text_justify justify, float height) { // create a new line - std::unique_ptr<line> new_line(global_alloc_clear<line>(*this, justify, actual_height(), height * yscale())); + std::unique_ptr<line> new_line(std::make_unique<line>(*this, justify, actual_height(), height * yscale())); // update the current line m_current_line = new_line.get(); @@ -303,7 +303,7 @@ void text_layout::start_new_line(text_layout::text_justify justify, float height m_truncating = false; // append it - m_lines.push_back(std::move(new_line)); + m_lines.emplace_back(std::move(new_line)); } diff --git a/src/frontend/mame/ui/text.h b/src/frontend/mame/ui/text.h index c5755c39813..fdf000c850a 100644 --- a/src/frontend/mame/ui/text.h +++ b/src/frontend/mame/ui/text.h @@ -7,16 +7,17 @@ Text functionality for MAME's crude user interface ***************************************************************************/ +#ifndef MAME_FRONTEND_UI_TEXT_H +#define MAME_FRONTEND_UI_TEXT_H #pragma once -#ifndef MAME_FRONTEND_UI_TEXT_H -#define MAME_FRONTEND_UI_TEXT_H class render_font; class render_container; namespace ui { + /*************************************************************************** TYPE DEFINITIONS ***************************************************************************/ diff --git a/src/frontend/mame/ui/ui.cpp b/src/frontend/mame/ui/ui.cpp index ff16d117117..90efcb04b7c 100644 --- a/src/frontend/mame/ui/ui.cpp +++ b/src/frontend/mame/ui/ui.cpp @@ -164,7 +164,7 @@ static uint32_t const mouse_bitmap[32*32] = mame_ui_manager::mame_ui_manager(running_machine &machine) : ui_manager(machine) - , m_font(nullptr) + , m_font() , m_handler_callback(nullptr) , m_handler_callback_type(ui_callback_type::GENERAL) , m_handler_param(0) @@ -216,7 +216,7 @@ void mame_ui_manager::init() config_save_delegate(&mame_ui_manager::config_save, this)); // create mouse bitmap - uint32_t *dst = &m_mouse_bitmap.pix32(0); + uint32_t *dst = &m_mouse_bitmap.pix(0); memcpy(dst,mouse_bitmap,32*32*sizeof(uint32_t)); m_mouse_arrow_texture = machine().render().texture_alloc(); m_mouse_arrow_texture->set_bitmap(m_mouse_bitmap, m_mouse_bitmap.cliprect(), TEXFORMAT_ARGB32); @@ -244,11 +244,7 @@ void mame_ui_manager::exit() m_mouse_arrow_texture = nullptr; // free the font - if (m_font != nullptr) - { - machine().render().font_free(m_font); - m_font = nullptr; - } + m_font.reset(); } @@ -640,9 +636,9 @@ void mame_ui_manager::update_and_render(render_container &container) render_font *mame_ui_manager::get_font() { // allocate the font and messagebox string - if (m_font == nullptr) + if (!m_font) m_font = machine().render().font_alloc(machine().options().ui_font()); - return m_font; + return m_font.get(); } @@ -1008,7 +1004,7 @@ void mame_ui_manager::process_natural_keyboard() while (machine().ui_input().pop_event(&event)) { // if this was a UI_EVENT_CHAR event, post it - if (event.event_type == ui_event::IME_CHAR) + if (event.event_type == ui_event::type::IME_CHAR) machine().ioport().natkeyboard().post_char(event.ch); } @@ -1487,7 +1483,7 @@ std::vector<ui::menu_item>& mame_ui_manager::get_slider_list(void) std::unique_ptr<slider_state> mame_ui_manager::slider_alloc(int id, const char *title, int32_t minval, int32_t defval, int32_t maxval, int32_t incval, void *arg) { - auto state = make_unique_clear<slider_state>(); + auto state = std::make_unique<slider_state>(); state->minval = minval; state->defval = defval; diff --git a/src/frontend/mame/ui/ui.h b/src/frontend/mame/ui/ui.h index 8c0504464d3..af9ad03efcc 100644 --- a/src/frontend/mame/ui/ui.h +++ b/src/frontend/mame/ui/ui.h @@ -271,7 +271,7 @@ private: using device_feature_set = std::set<std::pair<std::string, std::string> >; // instance variables - render_font * m_font; + std::unique_ptr<render_font> m_font; handler_callback_func m_handler_callback; ui_callback_type m_handler_callback_type; uint32_t m_handler_param; diff --git a/src/frontend/mame/ui/videoopt.cpp b/src/frontend/mame/ui/videoopt.cpp index 58818328d41..2a876c5a1af 100644 --- a/src/frontend/mame/ui/videoopt.cpp +++ b/src/frontend/mame/ui/videoopt.cpp @@ -141,7 +141,7 @@ void menu_video_options::handle() // process the menu event const *const menu_event(process(0)); - if (menu_event && menu_event->itemref) + if (menu_event && uintptr_t(menu_event->itemref)) { switch (reinterpret_cast<uintptr_t>(menu_event->itemref)) { diff --git a/src/frontend/mame/ui/viewgfx.cpp b/src/frontend/mame/ui/viewgfx.cpp index 5b4d187bc95..bc6dee9cd47 100644 --- a/src/frontend/mame/ui/viewgfx.cpp +++ b/src/frontend/mame/ui/viewgfx.cpp @@ -994,18 +994,16 @@ static void gfxset_draw_item(running_machine &machine, gfx_element &gfx, int ind { int width = (rotate & ORIENTATION_SWAP_XY) ? gfx.height() : gfx.width(); int height = (rotate & ORIENTATION_SWAP_XY) ? gfx.width() : gfx.height(); - const rgb_t *palette = dpalette->palette()->entry_list_raw() + gfx.colorbase() + color * gfx.granularity(); - - int x, y; + rgb_t const *const palette = dpalette->palette()->entry_list_raw() + gfx.colorbase() + color * gfx.granularity(); // loop over rows in the cell - for (y = 0; y < height; y++) + for (int y = 0; y < height; y++) { - uint32_t *dest = &bitmap.pix32(dsty + y, dstx); + uint32_t *dest = &bitmap.pix(dsty + y, dstx); const uint8_t *src = gfx.get_data(index); // loop over columns in the cell - for (x = 0; x < width; x++) + for (int x = 0; x < width; x++) { int effx = x, effy = y; const uint8_t *s; diff --git a/src/frontend/mame/ui/widgets.cpp b/src/frontend/mame/ui/widgets.cpp index d8907303b36..59fda0f203c 100644 --- a/src/frontend/mame/ui/widgets.cpp +++ b/src/frontend/mame/ui/widgets.cpp @@ -36,7 +36,7 @@ widgets_manager::widgets_manager(running_machine &machine) for (unsigned x = 0; x < 256; ++x) { unsigned const alpha((x < 25) ? (0xff * x / 25) : (x >(256 - 25)) ? (0xff * (255 - x) / 25) : 0xff); - m_hilight_bitmap->pix32(0, x) = rgb_t(alpha, 0xff, 0xff, 0xff); + m_hilight_bitmap->pix(0, x) = rgb_t(alpha, 0xff, 0xff, 0xff); } m_hilight_texture.reset(render.texture_alloc()); m_hilight_texture->set_bitmap(*m_hilight_bitmap, m_hilight_bitmap->cliprect(), TEXFORMAT_ARGB32); @@ -49,7 +49,7 @@ widgets_manager::widgets_manager(running_machine &machine) unsigned const r = r1 + (y * (r2 - r1) / 128); unsigned const g = g1 + (y * (g2 - g1) / 128); unsigned const b = b1 + (y * (b2 - b1) / 128); - m_hilight_main_bitmap->pix32(y, 0) = rgb_t(r, g, b); + m_hilight_main_bitmap->pix(y, 0) = rgb_t(r, g, b); } m_hilight_main_texture.reset(render.texture_alloc()); m_hilight_main_texture->set_bitmap(*m_hilight_main_bitmap, m_hilight_main_bitmap->cliprect(), TEXFORMAT_ARGB32); @@ -67,18 +67,17 @@ widgets_manager::widgets_manager(running_machine &machine) void widgets_manager::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; + int const halfwidth = dest.width() / 2; + int const height = dest.height(); // 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++) + for (int y = 0; y < height; y++) { int linewidth = (y * (halfwidth - 1) + (height / 2)) * 255 * 2 / height; - uint32_t *target = &dest.pix32(y, halfwidth); + uint32_t *const target = &dest.pix(y, halfwidth); // don't antialias if height < 12 if (dest.height() < 12) @@ -89,25 +88,23 @@ void widgets_manager::render_triangle(bitmap_argb32 &dest, bitmap_argb32 &source } // loop while we still have data to generate - for (x = 0; linewidth > 0; x++) + for (int x = 0; linewidth > 0; x++) { int dalpha; - - // first column we only consume one pixel if (x == 0) { + // first column we only consume one pixel dalpha = std::min(0xff, linewidth); target[x] = rgb_t(dalpha, 0xff, 0xff, 0xff); } - - // remaining columns consume two pixels, one on each side else { + // remaining columns consume two pixels, one on each side dalpha = std::min(0x1fe, linewidth); target[x] = target[-x] = rgb_t(dalpha / 2, 0xff, 0xff, 0xff); } - // account for the weight we consumed */ + // account for the weight we consumed linewidth -= dalpha; } } |