summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/ioport.cpp
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2021-12-09 07:42:12 +1100
committer Vas Crabb <vas@vastheman.com>2021-12-09 07:42:12 +1100
commit7d8c657fadc2a7b49a413eec9f4d3e7f7b34f6e4 (patch)
tree7d797bb486332e6a8dab5b0018a87e21bb5bb6dd /src/emu/ioport.cpp
parenta435da6f9bd16871e5e7c562bd3ce591e0a04379 (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.cpp95
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", "???");
}