summaryrefslogtreecommitdiffstatshomepage
path: root/src/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend')
-rw-r--r--src/frontend/mame/audit.cpp215
-rw-r--r--src/frontend/mame/audit.h23
-rw-r--r--src/frontend/mame/clifront.cpp2
-rw-r--r--src/frontend/mame/luaengine.cpp2
-rw-r--r--src/frontend/mame/mame.cpp40
-rw-r--r--src/frontend/mame/mame.h6
-rw-r--r--src/frontend/mame/ui/icorender.cpp508
-rw-r--r--src/frontend/mame/ui/inputmap.cpp17
-rw-r--r--src/frontend/mame/ui/inputmap.h2
-rw-r--r--src/frontend/mame/ui/keyboard.cpp98
-rw-r--r--src/frontend/mame/ui/keyboard.h33
-rw-r--r--src/frontend/mame/ui/mainmenu.cpp3
-rw-r--r--src/frontend/mame/ui/menu.cpp177
-rw-r--r--src/frontend/mame/ui/menu.h4
-rw-r--r--src/frontend/mame/ui/miscmenu.cpp37
-rw-r--r--src/frontend/mame/ui/miscmenu.h12
-rw-r--r--src/frontend/mame/ui/selgame.cpp65
-rw-r--r--src/frontend/mame/ui/selgame.h4
-rw-r--r--src/frontend/mame/ui/selmenu.cpp194
-rw-r--r--src/frontend/mame/ui/selmenu.h3
-rw-r--r--src/frontend/mame/ui/selsoft.cpp26
-rw-r--r--src/frontend/mame/ui/slider.h12
-rw-r--r--src/frontend/mame/ui/text.cpp4
-rw-r--r--src/frontend/mame/ui/text.h5
-rw-r--r--src/frontend/mame/ui/ui.cpp18
-rw-r--r--src/frontend/mame/ui/ui.h2
-rw-r--r--src/frontend/mame/ui/videoopt.cpp2
-rw-r--r--src/frontend/mame/ui/viewgfx.cpp10
-rw-r--r--src/frontend/mame/ui/widgets.cpp23
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 &current, 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 &current.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 &current, 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(&current.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(&current.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;
}
}