diff options
author | 2021-12-09 07:42:12 +1100 | |
---|---|---|
committer | 2021-12-09 07:42:12 +1100 | |
commit | 7d8c657fadc2a7b49a413eec9f4d3e7f7b34f6e4 (patch) | |
tree | 7d797bb486332e6a8dab5b0018a87e21bb5bb6dd /src/emu/ioport.cpp | |
parent | a435da6f9bd16871e5e7c562bd3ce591e0a04379 (diff) |
Moved localised I/O port name lookup into I/O port manager.
Added pseudo format specifiers to controller port names: %p for player
and %% for literal percent symbol. This lets you get the localised
player identifier in overridden input names (see NES and Neo-Geo for
examples), and reduces the number of messages to translate.
For translators, the new messages are mostly previously existing
messages with wording adjusted for clarity (e.g. referring to "media"
rather than "ROMs" in several places, as things like disk and tape
images are included). It's also possible to localise the "???"
dipslayed for an input without a valid name, but that should never
actually appear in practice.
Diffstat (limited to 'src/emu/ioport.cpp')
-rw-r--r-- | src/emu/ioport.cpp | 95 |
1 files changed, 81 insertions, 14 deletions
diff --git a/src/emu/ioport.cpp b/src/emu/ioport.cpp index 7bc4c455b78..a9b86776247 100644 --- a/src/emu/ioport.cpp +++ b/src/emu/ioport.cpp @@ -101,6 +101,7 @@ #include "util/corestr.h" #include "util/ioprocsfilter.h" +#include "util/language.h" #include "util/unicode.h" #include "osdepend.h" @@ -307,6 +308,37 @@ inline bool input_seq_good(running_machine &machine, input_seq const &seq) return input_seq::end_code != machine.input().seq_clean(seq)[0]; } + +std::string substitute_player(std::string_view name, u8 player) +{ + using util::lang_translate; + + std::string result; + while (!name.empty()) + { + auto const found = name.find('%'); + if ((std::string_view::npos == found) || (name.length() == found + 1)) + { + result.append(name); + break; + } + switch (name[found + 1]) + { + case '%': + result.append(name.substr(0, found + 1)); + break; + case 'p': + result.append(name.substr(0, found)); + result.append(util::string_format(_("input-name", "P%1$u"), player + 1)); + break; + default: + result.append(name.substr(0, found + 2)); + } + name.remove_prefix(found + 2); + } + return result; +} + } // anonymous namespace @@ -391,6 +423,24 @@ input_type_entry::input_type_entry(ioport_type type, ioport_group group, int pla //------------------------------------------------- +// name - gets the display name for the input +// type +//------------------------------------------------- + +std::string input_type_entry::name() const +{ + using util::lang_translate; + + if (!m_name) + return std::string(); + else if ((group() < IPG_PLAYER1) || (group() > IPG_PLAYER10)) + return _("input-name", m_name); + else + return substitute_player(_("input-name", m_name), player()); +} + + +//------------------------------------------------- // replace_code - replace all instances of // oldcodewith newcode in all sequences //------------------------------------------------- @@ -685,16 +735,25 @@ ioport_field::~ioport_field() // field (this must never return nullptr) //------------------------------------------------- -const char *ioport_field::name() const +std::string ioport_field::name() const { - // if we have a non-default name, use that - if (m_live != nullptr && !m_live->name.empty()) - return m_live->name.c_str(); - if (m_name != nullptr) + using util::lang_translate; + + // if we have an overridden name, use that + if (m_live && !m_live->name.empty()) + return m_live->name; + + // if no specific name, use the generic name for the type + if (!m_name) + return manager().type_name(m_type, m_player); + + // return name for non-controller fields as-is + ioport_group const group = manager().type_group(m_type, m_player); + if ((group < IPG_PLAYER1) || (group > IPG_PLAYER10)) return m_name; - // otherwise, return the name associated with the type - return manager().type_name(m_type, m_player); + // substitute the player number in if necessary + return substitute_player(m_name, m_player); } @@ -750,8 +809,8 @@ void ioport_field::set_defseq(input_seq_type seqtype, const input_seq &newseq) ioport_type_class ioport_field::type_class() const noexcept { // inputs associated with specific players - ioport_group group = manager().type_group(m_type, m_player); - if (group >= IPG_PLAYER1 && group <= IPG_PLAYER10) + ioport_group const group = manager().type_group(m_type, m_player); + if ((group >= IPG_PLAYER1) && (group <= IPG_PLAYER10)) return INPUT_CLASS_CONTROLLER; // keys (names derived from character codes) @@ -1702,12 +1761,14 @@ time_t ioport_manager::initialize() if (&port.second->device() == &device) { for (ioport_field &field : port.second->fields()) + { if (field.type_class() == INPUT_CLASS_CONTROLLER) { if (players < field.player() + 1) players = field.player() + 1; field.set_player(field.player() + player_offset); } + } } } player_offset += players; @@ -1846,15 +1907,21 @@ ioport_manager::~ioport_manager() // type/player //------------------------------------------------- -const char *ioport_manager::type_name(ioport_type type, u8 player) const noexcept +std::string ioport_manager::type_name(ioport_type type, u8 player) const { + using util::lang_translate; + // if we have a machine, use the live state and quick lookup - input_type_entry *entry = m_type_to_entry[type][player]; - if (entry != nullptr && entry->name() != nullptr) - return entry->name(); + input_type_entry const *const entry = m_type_to_entry[type][player]; + if (entry) + { + std::string name = entry->name(); + if (!name.empty()) + return name; + } // if we find nothing, return a default string (not a null pointer) - return "???"; + return _("input-name", "???"); } |