diff options
Diffstat (limited to 'src/emu')
86 files changed, 2390 insertions, 1985 deletions
diff --git a/src/emu/config.cpp b/src/emu/config.cpp index 792da6f255d..c6b85bb6ae8 100644 --- a/src/emu/config.cpp +++ b/src/emu/config.cpp @@ -13,6 +13,7 @@ #include "drivenum.h" #include "emuopts.h" +#include "fileio.h" #include "xmlfile.h" diff --git a/src/emu/crsshair.cpp b/src/emu/crsshair.cpp index 3c6a6b807f0..d90cc9a7f5e 100644 --- a/src/emu/crsshair.cpp +++ b/src/emu/crsshair.cpp @@ -13,6 +13,7 @@ #include "config.h" #include "emuopts.h" +#include "fileio.h" #include "render.h" #include "rendutil.h" #include "screen.h" diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp index 20431072cff..781ce93e9a5 100644 --- a/src/emu/debug/debugcmd.cpp +++ b/src/emu/debug/debugcmd.cpp @@ -21,8 +21,10 @@ #include "debugger.h" #include "emuopts.h" +#include "fileio.h" #include "natkeyboard.h" #include "render.h" +#include "screen.h" #include "softlist.h" #include "corestr.h" @@ -30,6 +32,7 @@ #include <algorithm> #include <cctype> #include <fstream> +#include <sstream> @@ -231,6 +234,9 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu m_console.register_command("gtime", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_go_time, this, _1)); m_console.register_command("gt", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_go_time, this, _1)); m_console.register_command("gp", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_go_privilege, this, _1)); + m_console.register_command("gbt", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_go_branch, this, true, _1)); + m_console.register_command("gbf", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_go_branch, this, false, _1)); + m_console.register_command("gni", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_go_next_instruction, this, _1)); m_console.register_command("next", CMDFLAG_NONE, 0, 0, std::bind(&debugger_commands::execute_next, this, _1)); m_console.register_command("n", CMDFLAG_NONE, 0, 0, std::bind(&debugger_commands::execute_next, this, _1)); m_console.register_command("focus", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_focus, this, _1)); @@ -239,6 +245,7 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu m_console.register_command("suspend", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_suspend, this, _1)); m_console.register_command("resume", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_resume, this, _1)); m_console.register_command("cpulist", CMDFLAG_NONE, 0, 0, std::bind(&debugger_commands::execute_cpulist, this, _1)); + m_console.register_command("time", CMDFLAG_NONE, 0, 0, std::bind(&debugger_commands::execute_time, this, _1)); m_console.register_command("comadd", CMDFLAG_NONE, 1, 2, std::bind(&debugger_commands::execute_comment_add, this, _1)); m_console.register_command("//", CMDFLAG_NONE, 1, 2, std::bind(&debugger_commands::execute_comment_add, this, _1)); @@ -942,53 +949,51 @@ void debugger_commands::execute_print(const std::vector<std::string> ¶ms) mini_printf - safe printf to a buffer -------------------------------------------------*/ -int debugger_commands::mini_printf(char *buffer, const char *format, int params, u64 *param) +bool debugger_commands::mini_printf(std::ostream &stream, std::string_view format, int params, u64 *param) { - const char *f = format; - char *p = buffer; + auto f = format.begin(); - /* parse the string looking for % signs */ - for (;;) + // parse the string looking for % signs + while (f != format.end()) { char c = *f++; - if (!c) break; - /* escape sequences */ + // escape sequences if (c == '\\') { + if (f == format.end()) break; c = *f++; - if (!c) break; switch (c) { - case '\\': *p++ = c; break; - case 'n': *p++ = '\n'; break; + case '\\': stream << c; break; + case 'n': stream << '\n'; break; default: break; } continue; } - /* formatting */ + // formatting else if (c == '%') { int width = 0; int zerofill = 0; - /* parse out the width */ - for (;;) + // parse out the width + while (f != format.end() && *f >= '0' && *f <= '9') { c = *f++; - if (!c || c < '0' || c > '9') break; if (c == '0' && width == 0) zerofill = 1; width = width * 10 + (c - '0'); } - if (!c) break; + if (f == format.end()) break; - /* get the format */ + // get the format + c = *f++; switch (c) { case '%': - *p++ = c; + stream << c; break; case 'X': @@ -996,13 +1001,13 @@ int debugger_commands::mini_printf(char *buffer, const char *format, int params, if (params == 0) { m_console.printf("Not enough parameters for format!\n"); - return 0; + return false; } if (u32(*param >> 32) != 0) - p += sprintf(p, zerofill ? "%0*X" : "%*X", (width <= 8) ? 1 : width - 8, u32(*param >> 32)); + util::stream_format(stream, zerofill ? "%0*X" : "%*X", (width <= 8) ? 1 : width - 8, u32(*param >> 32)); else if (width > 8) - p += sprintf(p, zerofill ? "%0*X" : "%*X", width - 8, 0); - p += sprintf(p, zerofill ? "%0*X" : "%*X", (width < 8) ? width : 8, u32(*param)); + util::stream_format(stream, zerofill ? "%0*X" : "%*X", width - 8, 0); + util::stream_format(stream, zerofill ? "%0*X" : "%*X", (width < 8) ? width : 8, u32(*param)); param++; params--; break; @@ -1012,23 +1017,23 @@ int debugger_commands::mini_printf(char *buffer, const char *format, int params, if (params == 0) { m_console.printf("Not enough parameters for format!\n"); - return 0; + return false; } if (u32(*param >> 60) != 0) { - p += sprintf(p, zerofill ? "%0*o" : "%*o", (width <= 20) ? 1 : width - 20, u32(*param >> 60)); - p += sprintf(p, "%0*o", 10, u32(BIT(*param, 30, 30))); + util::stream_format(stream, zerofill ? "%0*o" : "%*o", (width <= 20) ? 1 : width - 20, u32(*param >> 60)); + util::stream_format(stream, "%0*o", 10, u32(BIT(*param, 30, 30))); } else { if (width > 20) - p += sprintf(p, zerofill ? "%0*o" : "%*o", width - 20, 0); + util::stream_format(stream, zerofill ? "%0*o" : "%*o", width - 20, 0); if (u32(BIT(*param, 30, 30)) != 0) - p += sprintf(p, zerofill ? "%0*o" : "%*o", (width <= 10) ? 1 : width - 10, u32(BIT(*param, 30, 30))); + util::stream_format(stream, zerofill ? "%0*o" : "%*o", (width <= 10) ? 1 : width - 10, u32(BIT(*param, 30, 30))); else if (width > 10) - p += sprintf(p, zerofill ? "%0*o" : "%*o", width - 10, 0); + util::stream_format(stream, zerofill ? "%0*o" : "%*o", width - 10, 0); } - p += sprintf(p, zerofill ? "%0*o" : "%*o", (width < 10) ? width : 10, u32(BIT(*param, 0, 30))); + util::stream_format(stream, zerofill ? "%0*o" : "%*o", (width < 10) ? width : 10, u32(BIT(*param, 0, 30))); param++; params--; break; @@ -1038,9 +1043,9 @@ int debugger_commands::mini_printf(char *buffer, const char *format, int params, if (params == 0) { m_console.printf("Not enough parameters for format!\n"); - return 0; + return false; } - p += sprintf(p, zerofill ? "%0*d" : "%*d", width, u32(*param)); + util::stream_format(stream, zerofill ? "%0*d" : "%*d", width, u32(*param)); param++; params--; break; @@ -1049,9 +1054,9 @@ int debugger_commands::mini_printf(char *buffer, const char *format, int params, if (params == 0) { m_console.printf("Not enough parameters for format!\n"); - return 0; + return false; } - p += sprintf(p, "%c", char(*param)); + stream << char(*param); param++; params--; break; @@ -1059,14 +1064,12 @@ int debugger_commands::mini_printf(char *buffer, const char *format, int params, } } - /* normal stuff */ + // normal stuff else - *p++ = c; + stream << c; } - /* NULL-terminate and exit */ - *p = 0; - return 1; + return true; } @@ -1114,9 +1117,9 @@ void debugger_commands::execute_printf(const std::vector<std::string> ¶ms) return; /* then do a printf */ - char buffer[1024]; - if (mini_printf(buffer, params[0].c_str(), params.size() - 1, &values[1])) - m_console.printf("%s\n", buffer); + std::ostringstream buffer; + if (mini_printf(buffer, params[0], params.size() - 1, &values[1])) + m_console.printf("%s\n", std::move(buffer).str()); } @@ -1133,9 +1136,9 @@ void debugger_commands::execute_logerror(const std::vector<std::string> ¶ms) return; /* then do a printf */ - char buffer[1024]; - if (mini_printf(buffer, params[0].c_str(), params.size() - 1, &values[1])) - m_machine.logerror("%s", buffer); + std::ostringstream buffer; + if (mini_printf(buffer, params[0], params.size() - 1, &values[1])) + m_machine.logerror("%s", std::move(buffer).str()); } @@ -1152,9 +1155,9 @@ void debugger_commands::execute_tracelog(const std::vector<std::string> ¶ms) return; /* then do a printf */ - char buffer[1024]; - if (mini_printf(buffer, params[0].c_str(), params.size() - 1, &values[1])) - m_console.get_visible_cpu()->debug()->trace_printf("%s", buffer); + std::ostringstream buffer; + if (mini_printf(buffer, params[0], params.size() - 1, &values[1])) + m_console.get_visible_cpu()->debug()->trace_printf("%s", std::move(buffer).str().c_str()); } @@ -1188,9 +1191,9 @@ void debugger_commands::execute_tracesym(const std::vector<std::string> ¶ms) } // then do a printf - char buffer[1024]; - if (mini_printf(buffer, format.str().c_str(), params.size(), values)) - m_console.get_visible_cpu()->debug()->trace_printf("%s", buffer); + std::ostringstream buffer; + if (mini_printf(buffer, format.str(), params.size(), values)) + m_console.get_visible_cpu()->debug()->trace_printf("%s", std::move(buffer).str().c_str()); } @@ -1357,6 +1360,62 @@ void debugger_commands::execute_go_privilege(const std::vector<std::string> &par m_console.get_visible_cpu()->debug()->go_privilege((condition.is_empty()) ? "1" : condition.original_string()); } + +/*------------------------------------------------- + execute_go_branch - execute gbt or gbf command +-------------------------------------------------*/ + +void debugger_commands::execute_go_branch(bool sense, const std::vector<std::string> ¶ms) +{ + parsed_expression condition(m_console.visible_symtable()); + if (params.size() > 0 && !debug_command_parameter_expression(params[0], condition)) + return; + + m_console.get_visible_cpu()->debug()->go_branch(sense, (condition.is_empty()) ? "1" : condition.original_string()); +} + + +/*------------------------------------------------- + execute_go_next_instruction - execute gni command +-------------------------------------------------*/ + +void debugger_commands::execute_go_next_instruction(const std::vector<std::string> ¶ms) +{ + u64 count = 1; + static constexpr u64 MAX_COUNT = 512; + + // if we have a parameter, use it instead */ + if (params.size() > 0 && !validate_number_parameter(params[0], count)) + return; + if (count == 0) + return; + if (count > MAX_COUNT) + { + m_console.printf("Too many instructions (must be %d or fewer)\n", MAX_COUNT); + return; + } + + device_state_interface *stateintf; + device_t *cpu = m_machine.debugger().console().get_visible_cpu(); + if (!cpu->interface(stateintf)) + { + m_console.printf("No state interface available for %s\n", cpu->name()); + return; + } + u32 pc = stateintf->pcbase(); + + debug_disasm_buffer buffer(*cpu); + while (count-- != 0) + { + // disassemble the current instruction and get the length + u32 result = buffer.disassemble_info(pc); + pc = buffer.next_pc_wrap(pc, result & util::disasm_interface::LENGTHMASK); + } + + cpu->debug()->go(pc); +} + + /*------------------------------------------------- execute_next - execute the next command -------------------------------------------------*/ @@ -1619,6 +1678,15 @@ void debugger_commands::execute_cpulist(const std::vector<std::string> ¶ms) } } +//------------------------------------------------- +// execute_time - execute the time command +//------------------------------------------------- + +void debugger_commands::execute_time(const std::vector<std::string> ¶ms) +{ + m_console.printf("%s\n", m_machine.time().as_string()); +} + /*------------------------------------------------- execute_comment - add a comment to a line -------------------------------------------------*/ @@ -2190,8 +2258,7 @@ void debugger_commands::execute_rplist(const std::vector<std::string> ¶ms) void debugger_commands::execute_statesave(const std::vector<std::string> ¶ms) { - const std::string &filename(params[0]); - m_machine.immediate_save(filename.c_str()); + m_machine.immediate_save(params[0]); m_console.printf("State save attempted. Please refer to window message popup for results.\n"); } @@ -2202,8 +2269,7 @@ void debugger_commands::execute_statesave(const std::vector<std::string> ¶ms void debugger_commands::execute_stateload(const std::vector<std::string> ¶ms) { - const std::string &filename(params[0]); - m_machine.immediate_load(filename.c_str()); + m_machine.immediate_load(params[0]); // clear all PC & memory tracks for (device_t &device : device_enumerator(m_machine.root_device())) @@ -3395,7 +3461,7 @@ void debugger_commands::execute_find(int spacenum, const std::vector<std::string data_size[data_count++] |= 0x10; // otherwise, validate as a number - else if (!validate_number_parameter(params[i], data_to_find[data_count++])) + else if (!validate_number_parameter(pdata, data_to_find[data_count++])) return; } } @@ -4258,7 +4324,7 @@ void debugger_commands::execute_unmount(const std::vector<std::string> ¶ms) void debugger_commands::execute_input(const std::vector<std::string> ¶ms) { - m_machine.natkeyboard().post_coded(params[0].c_str()); + m_machine.natkeyboard().post_coded(params[0]); } diff --git a/src/emu/debug/debugcmd.h b/src/emu/debug/debugcmd.h index fd0bcea673a..f93276d5d8d 100644 --- a/src/emu/debug/debugcmd.h +++ b/src/emu/debug/debugcmd.h @@ -99,7 +99,7 @@ private: u64 global_get(global_entry *global); void global_set(global_entry *global, u64 value); - int mini_printf(char *buffer, const char *format, int params, u64 *param); + bool mini_printf(std::ostream &stream, std::string_view format, int params, u64 *param); template <typename T> void execute_index_command(std::vector<std::string> const ¶ms, T &&apply, char const *unused_message); @@ -121,6 +121,8 @@ private: void execute_go_exception(const std::vector<std::string> ¶ms); void execute_go_time(const std::vector<std::string> ¶ms); void execute_go_privilege(const std::vector<std::string> ¶ms); + void execute_go_branch(bool sense, const std::vector<std::string> ¶ms); + void execute_go_next_instruction(const std::vector<std::string> ¶ms); void execute_focus(const std::vector<std::string> ¶ms); void execute_ignore(const std::vector<std::string> ¶ms); void execute_observe(const std::vector<std::string> ¶ms); @@ -128,6 +130,7 @@ private: void execute_resume(const std::vector<std::string> ¶ms); void execute_next(const std::vector<std::string> ¶ms); void execute_cpulist(const std::vector<std::string> ¶ms); + void execute_time(const std::vector<std::string> ¶ms); void execute_comment_add(const std::vector<std::string> ¶ms); void execute_comment_del(const std::vector<std::string> ¶ms); void execute_comment_save(const std::vector<std::string> ¶ms); diff --git a/src/emu/debug/debugcon.cpp b/src/emu/debug/debugcon.cpp index 32a4888c285..508c2377f54 100644 --- a/src/emu/debug/debugcon.cpp +++ b/src/emu/debug/debugcon.cpp @@ -16,6 +16,7 @@ #include "textbuf.h" #include "debugger.h" +#include "fileio.h" #include "corestr.h" @@ -86,10 +87,14 @@ debugger_console::debugger_console(running_machine &machine) } } +debugger_console::~debugger_console() +{ +} -/*------------------------------------------------- - exit - frees the console system --------------------------------------------------*/ + +//------------------------------------------------- +// exit - frees the console system +//------------------------------------------------- void debugger_console::exit() { @@ -114,41 +119,39 @@ void debugger_console::exit() inline bool debugger_console::debug_command::compare::operator()(const debug_command &a, const debug_command &b) const { - return core_stricmp(a.command.c_str(), b.command.c_str()) < 0; + return a.command < b.command; } inline bool debugger_console::debug_command::compare::operator()(const char *a, const debug_command &b) const { - return core_stricmp(a, b.command.c_str()) < 0; + return strcmp(a, b.command.c_str()) < 0; } inline bool debugger_console::debug_command::compare::operator()(const debug_command &a, const char *b) const { - return core_stricmp(a.command.c_str(), b) < 0; + return strcmp(a.command.c_str(), b) < 0; } -debugger_console::debug_command::debug_command(const char *_command, u32 _flags, int _minparams, int _maxparams, std::function<void (const std::vector<std::string> &)> &&_handler) +debugger_console::debug_command::debug_command(std::string_view _command, u32 _flags, int _minparams, int _maxparams, std::function<void (const std::vector<std::string> &)> &&_handler) : command(_command), params(nullptr), help(nullptr), handler(std::move(_handler)), flags(_flags), minparams(_minparams), maxparams(_maxparams) { } -/*------------------------------------------------------------ - execute_help_custom - execute the helpcustom command -------------------------------------------------------------*/ +//------------------------------------------------------------ +// execute_help_custom - execute the helpcustom command +//------------------------------------------------------------ void debugger_console::execute_help_custom(const std::vector<std::string> ¶ms) { - char buf[64]; for (const debug_command &cmd : m_commandlist) { if (cmd.flags & CMDFLAG_CUSTOM_HELP) { - snprintf(buf, 63, "%s help", cmd.command.c_str()); - buf[63] = 0; - char *temp_params[1] = { buf }; - internal_execute_command(true, 1, &temp_params[0]); + std::string buf = cmd.command + " help"; + std::vector<std::string_view> temp_params = { buf }; + internal_execute_command(true, temp_params); } } } @@ -202,159 +205,145 @@ symbol_table &debugger_console::visible_symtable() -/*------------------------------------------------- - trim_parameter - executes a - command --------------------------------------------------*/ +//------------------------------------------------- +// trim_parameter - trim spaces and quotes around +// a command parameter +//------------------------------------------------- -void debugger_console::trim_parameter(char **paramptr, bool keep_quotes) +std::string_view debugger_console::trim_parameter(std::string_view param, bool keep_quotes) { - char *param = *paramptr; - size_t len = strlen(param); + std::string_view::size_type len = param.length(); bool repeat; - /* loop until all adornments are gone */ + // loop until all adornments are gone do { repeat = false; - /* check for begin/end quotes */ + // check for begin/end quotes if (len >= 2 && param[0] == '"' && param[len - 1] == '"') { if (!keep_quotes) { - param[len - 1] = 0; - param++; + param = param.substr(1, len - 2); len -= 2; } } - /* check for start/end braces */ + // check for start/end braces else if (len >= 2 && param[0] == '{' && param[len - 1] == '}') { - param[len - 1] = 0; - param++; + param = param.substr(1, len - 2); len -= 2; repeat = true; } - /* check for leading spaces */ + // check for leading spaces else if (len >= 1 && param[0] == ' ') { - param++; + param.remove_prefix(1); len--; repeat = true; } - /* check for trailing spaces */ + // check for trailing spaces else if (len >= 1 && param[len - 1] == ' ') { - param[len - 1] = 0; + param.remove_suffix(1); len--; repeat = true; } } while (repeat); - *paramptr = param; + return param; } -/*------------------------------------------------- - internal_execute_command - executes a - command --------------------------------------------------*/ +//------------------------------------------------- +// internal_execute_command - executes a +// command +//------------------------------------------------- -CMDERR debugger_console::internal_execute_command(bool execute, int params, char **param) +CMDERR debugger_console::internal_execute_command(bool execute, std::vector<std::string_view> ¶ms) { // no params is an error - if (params == 0) + if (params.empty()) return CMDERR::none(); // the first parameter has the command and the real first parameter; separate them - char *p, *command; - for (p = param[0]; *p && isspace(u8(*p)); p++) { } - for (command = p; *p && !isspace(u8(*p)); p++) { } - if (*p != 0) - { - *p++ = 0; - for ( ; *p && isspace(u8(*p)); p++) { } - if (*p != 0) - param[0] = p; - else - params = 0; - } + std::string_view command_param = params[0]; + std::string_view::size_type pos = 0; + while (pos < command_param.length() && !isspace(u8(command_param[pos]))) + pos++; + const std::string command(strmakelower(command_param.substr(0, pos))); + while (pos < command_param.length() && isspace(u8(command_param[pos]))) + pos++; + if (pos == command_param.length() && params.size() == 1) + params.clear(); else - { - params = 0; - param[0] = nullptr; - } + params[0].remove_prefix(pos); // search the command list - size_t const len = strlen(command); - auto const found = m_commandlist.lower_bound(command); + auto const found = m_commandlist.lower_bound(command.c_str()); // error if not found - if ((m_commandlist.end() == found) || core_strnicmp(command, found->command.c_str(), len)) + if (m_commandlist.end() == found || std::string_view(command) != std::string_view(found->command).substr(0, command.length())) return CMDERR::unknown_command(0); - if (found->command.length() > len) + if (found->command.length() > command.length()) { auto const next = std::next(found); - if ((m_commandlist.end() != next) && !core_strnicmp(command, next->command.c_str(), len)) + if (m_commandlist.end() != next && std::string_view(command) == std::string_view(next->command).substr(0, command.length())) return CMDERR::ambiguous_command(0); } - // NUL-terminate and trim space around all the parameters - for (int i = 1; i < params; i++) - *param[i]++ = 0; - // now go back and trim quotes and braces and any spaces they reveal - for (int i = 0; i < params; i++) - trim_parameter(¶m[i], found->flags & CMDFLAG_KEEP_QUOTES); + for (std::string_view ¶m : params) + param = trim_parameter(param, found->flags & CMDFLAG_KEEP_QUOTES); // see if we have the right number of parameters - if (params < found->minparams) + if (params.size() < found->minparams) return CMDERR::not_enough_params(0); - if (params > found->maxparams) + if (params.size() > found->maxparams) return CMDERR::too_many_params(0); // execute the handler if (execute) { - std::vector<std::string> params_vec(param, param + params); + std::vector<std::string> params_vec(params.begin(), params.end()); found->handler(params_vec); } return CMDERR::none(); } -/*------------------------------------------------- - internal_parse_command - parses a command - and either executes or just validates it --------------------------------------------------*/ +//------------------------------------------------- +// internal_parse_command - parses a command +// and either executes or just validates it +//------------------------------------------------- -CMDERR debugger_console::internal_parse_command(const std::string &original_command, bool execute) +CMDERR debugger_console::internal_parse_command(std::string_view command, bool execute) { - char command[MAX_COMMAND_LENGTH], parens[MAX_COMMAND_LENGTH]; - char *params[MAX_COMMAND_PARAMS] = { nullptr }; - char *command_start; - char *p, c = 0; + std::string_view::size_type pos = 0; + std::string_view::size_type len = command.length(); - /* make a copy of the command */ - strcpy(command, original_command.c_str()); - - /* loop over all semicolon-separated stuff */ - for (p = command; *p != 0; ) + while (pos < len) { - int paramcount = 0, parendex = 0; + std::string parens; + std::vector<std::string_view> params; bool foundend = false, instring = false, isexpr = false; - /* find a semicolon or the end */ - for (params[paramcount++] = p; !foundend; p++) + // skip leading spaces + while (pos < len && isspace(u8(command[pos]))) + pos++; + std::string_view::size_type startpos = pos; + + // find a semicolon or the end + for (params.push_back(command.substr(pos)); !foundend && pos < len; pos++) { - c = *p; + char c = command[pos]; if (instring) { - if (c == '"' && p[-1] != '\\') + if (c == '"' && command[pos - 1] != '\\') instring = false; } else @@ -364,47 +353,42 @@ CMDERR debugger_console::internal_parse_command(const std::string &original_comm case '"': instring = true; break; case '(': case '[': - case '{': parens[parendex++] = c; break; - case ')': if (parendex == 0 || parens[--parendex] != '(') return CMDERR::unbalanced_parens(p - command); break; - case ']': if (parendex == 0 || parens[--parendex] != '[') return CMDERR::unbalanced_parens(p - command); break; - case '}': if (parendex == 0 || parens[--parendex] != '{') return CMDERR::unbalanced_parens(p - command); break; - case ',': if (parendex == 0) params[paramcount++] = p; break; - case ';': if (parendex == 0) foundend = true; break; - case '-': if (parendex == 0 && paramcount == 1 && p[1] == '-') isexpr = true; *p = c; break; - case '+': if (parendex == 0 && paramcount == 1 && p[1] == '+') isexpr = true; *p = c; break; - case '=': if (parendex == 0 && paramcount == 1) isexpr = true; *p = c; break; - case 0: foundend = true; break; - default: *p = c; break; + case '{': parens.push_back(c); break; + case ')': if (parens.empty() || parens.back() != '(') return CMDERR::unbalanced_parens(pos); parens.pop_back(); break; + case ']': if (parens.empty() || parens.back() != '[') return CMDERR::unbalanced_parens(pos); parens.pop_back(); break; + case '}': if (parens.empty() || parens.back() != '{') return CMDERR::unbalanced_parens(pos); parens.pop_back(); break; + case ',': if (parens.empty()) { params.back().remove_suffix(len - pos); params.push_back(command.substr(pos + 1)); } break; + case ';': if (parens.empty()) { params.back().remove_suffix(len - pos); foundend = true; } break; + case '-': if (parens.empty() && params.size() == 1 && pos > 0 && command[pos - 1] == '-') isexpr = true; break; + case '+': if (parens.empty() && params.size() == 1 && pos > 0 && command[pos - 1] == '+') isexpr = true; break; + case '=': if (parens.empty() && params.size() == 1) isexpr = true; break; + default: break; } } } - /* check for unbalanced parentheses or quotes */ + // check for unbalanced parentheses or quotes if (instring) - return CMDERR::unbalanced_quotes(p - command); - if (parendex != 0) - return CMDERR::unbalanced_parens(p - command); + return CMDERR::unbalanced_quotes(pos); + if (!parens.empty()) + return CMDERR::unbalanced_parens(pos); - /* NULL-terminate if we ended in a semicolon */ - p--; - if (c == ';') *p++ = 0; + // process the command + std::string_view command_or_expr = params[0]; - /* process the command */ - command_start = params[0]; - - /* allow for "do" commands */ - if (tolower(u8(command_start[0])) == 'd' && tolower(u8(command_start[1])) == 'o' && isspace(u8(command_start[2]))) + // allow for "do" commands + if (command_or_expr.length() > 3 && tolower(u8(command_or_expr[0])) == 'd' && tolower(u8(command_or_expr[1])) == 'o' && isspace(u8(command_or_expr[2]))) { isexpr = true; - command_start += 3; + command_or_expr.remove_prefix(3); } - /* if it smells like an assignment expression, treat it as such */ - if (isexpr && paramcount == 1) + // if it smells like an assignment expression, treat it as such + if (isexpr && params.size() == 1) { try { - parsed_expression(visible_symtable(), command_start).execute(); + parsed_expression(visible_symtable(), command_or_expr).execute(); } catch (expression_error &err) { @@ -413,29 +397,29 @@ CMDERR debugger_console::internal_parse_command(const std::string &original_comm } else { - const CMDERR result = internal_execute_command(execute, paramcount, ¶ms[0]); + const CMDERR result = internal_execute_command(execute, params); if (result.error_class() != CMDERR::NONE) - return CMDERR(result.error_class(), command_start - command); + return CMDERR(result.error_class(), startpos); } } return CMDERR::none(); } -/*------------------------------------------------- - execute_command - execute a command string --------------------------------------------------*/ +//------------------------------------------------- +// execute_command - execute a command string +//------------------------------------------------- -CMDERR debugger_console::execute_command(const std::string &command, bool echo) +CMDERR debugger_console::execute_command(std::string_view command, bool echo) { - /* echo if requested */ + // echo if requested if (echo) printf(">%s\n", command); - /* parse and execute */ + // parse and execute const CMDERR result = internal_parse_command(command, true); - /* display errors */ + // display errors if (result.error_class() != CMDERR::NONE) { if (!echo) @@ -444,7 +428,7 @@ CMDERR debugger_console::execute_command(const std::string &command, bool echo) printf("%s\n", cmderr_to_string(result)); } - /* update all views */ + // update all views if (echo) { m_machine.debug_view().update_all(); @@ -454,11 +438,11 @@ CMDERR debugger_console::execute_command(const std::string &command, bool echo) } -/*------------------------------------------------- - validate_command - validate a command string --------------------------------------------------*/ +//------------------------------------------------- +// validate_command - validate a command string +//------------------------------------------------- -CMDERR debugger_console::validate_command(const char *command) +CMDERR debugger_console::validate_command(std::string_view command) { return internal_parse_command(command, false); } @@ -468,7 +452,7 @@ CMDERR debugger_console::validate_command(const char *command) register_command - register a command handler -------------------------------------------------*/ -void debugger_console::register_command(const char *command, u32 flags, int minparams, int maxparams, std::function<void (const std::vector<std::string> &)> &&handler) +void debugger_console::register_command(std::string_view command, u32 flags, int minparams, int maxparams, std::function<void (const std::vector<std::string> &)> &&handler) { if (m_machine.phase() != machine_phase::INIT) throw emu_fatalerror("Can only call debugger_console::register_command() at init time!"); diff --git a/src/emu/debug/debugcon.h b/src/emu/debug/debugcon.h index 5271b0e5ae5..974a43e656a 100644 --- a/src/emu/debug/debugcon.h +++ b/src/emu/debug/debugcon.h @@ -23,8 +23,7 @@ CONSTANTS ***************************************************************************/ -#define MAX_COMMAND_LENGTH 4096 -#define MAX_COMMAND_PARAMS 128 +constexpr int MAX_COMMAND_PARAMS = 128; // flags for command parsing constexpr u32 CMDFLAG_NONE = 0x0000; @@ -79,11 +78,12 @@ class debugger_console { public: debugger_console(running_machine &machine); + ~debugger_console(); // command handling - CMDERR execute_command(const std::string &command, bool echo); - CMDERR validate_command(const char *command); - void register_command(const char *command, u32 flags, int minparams, int maxparams, std::function<void (const std::vector<std::string> &)> &&handler); + CMDERR execute_command(std::string_view command, bool echo); + CMDERR validate_command(std::string_view command); + void register_command(std::string_view command, u32 flags, int minparams, int maxparams, std::function<void (const std::vector<std::string> &)> &&handler); void source_script(const char *file); void process_source_file(); @@ -122,16 +122,16 @@ private: void execute_help_custom(const std::vector<std::string> ¶ms); void execute_condump(const std::vector<std::string>& params); - void trim_parameter(char **paramptr, bool keep_quotes); - CMDERR internal_execute_command(bool execute, int params, char **param); - CMDERR internal_parse_command(const std::string &original_command, bool execute); + [[nodiscard]] static std::string_view trim_parameter(std::string_view param, bool keep_quotes); + CMDERR internal_execute_command(bool execute, std::vector<std::string_view> ¶ms); + CMDERR internal_parse_command(std::string_view command, bool execute); void print_core(std::string_view text); // core text output void print_core_wrap(std::string_view text, int wrapcol); // core text output struct debug_command { - debug_command(const char *_command, u32 _flags, int _minparams, int _maxparams, std::function<void (const std::vector<std::string> &)> &&_handler); + debug_command(std::string_view _command, u32 _flags, int _minparams, int _maxparams, std::function<void (const std::vector<std::string> &)> &&_handler); struct compare { diff --git a/src/emu/debug/debugcpu.cpp b/src/emu/debug/debugcpu.cpp index 403d0b104ee..820d9e72688 100644 --- a/src/emu/debug/debugcpu.cpp +++ b/src/emu/debug/debugcpu.cpp @@ -19,6 +19,7 @@ #include "debugger.h" #include "emuopts.h" +#include "fileio.h" #include "screen.h" #include "uiinput.h" @@ -426,6 +427,7 @@ device_debug::device_debug(device_t &device) , m_instrhook(nullptr) , m_stepaddr(0) , m_stepsleft(0) + , m_delay_steps(0) , m_stopaddr(0) , m_stoptime(attotime::zero) , m_stopirq(0) @@ -458,14 +460,14 @@ device_debug::device_debug(device_t &device) // set up notifiers and clear the passthrough handlers if (m_memory) { int count = m_memory->max_space_count(); - m_phw.resize(count, nullptr); + m_phw.resize(count); for (int i=0; i != count; i++) if (m_memory->has_space(i)) { address_space &space = m_memory->space(i); - m_notifiers.push_back(space.add_change_notifier([this, &space](read_or_write mode) { reinstall(space, mode); })); + m_notifiers.emplace_back(space.add_change_notifier([this, &space] (read_or_write mode) { reinstall(space, mode); })); } else - m_notifiers.push_back(-1); + m_notifiers.emplace_back(); } // set up state-related stuff @@ -562,15 +564,14 @@ void device_debug::reinstall(address_space &space, read_or_write mode) int id = space.spacenum(); if (u32(mode) & u32(read_or_write::WRITE)) { - if (m_phw[id]) - m_phw[id]->remove(); + m_phw[id].remove(); if (m_track_mem) switch (space.data_width()) { - case 8: m_phw[id] = space.install_write_tap(0, space.addrmask(), "track_mem", [this, &space](offs_t address, u8 &data, u8 ) { write_tracking(space, address, data); }, m_phw[id]); break; - case 16: m_phw[id] = space.install_write_tap(0, space.addrmask(), "track_mem", [this, &space](offs_t address, u16 &data, u16) { write_tracking(space, address, data); }, m_phw[id]); break; - case 32: m_phw[id] = space.install_write_tap(0, space.addrmask(), "track_mem", [this, &space](offs_t address, u32 &data, u32) { write_tracking(space, address, data); }, m_phw[id]); break; - case 64: m_phw[id] = space.install_write_tap(0, space.addrmask(), "track_mem", [this, &space](offs_t address, u64 &data, u64) { write_tracking(space, address, data); }, m_phw[id]); break; + case 8: m_phw[id] = space.install_write_tap(0, space.addrmask(), "track_mem", [this, &space] (offs_t address, u8 &data, u8 ) { write_tracking(space, address, data); }, &m_phw[id]); break; + case 16: m_phw[id] = space.install_write_tap(0, space.addrmask(), "track_mem", [this, &space] (offs_t address, u16 &data, u16) { write_tracking(space, address, data); }, &m_phw[id]); break; + case 32: m_phw[id] = space.install_write_tap(0, space.addrmask(), "track_mem", [this, &space] (offs_t address, u32 &data, u32) { write_tracking(space, address, data); }, &m_phw[id]); break; + case 64: m_phw[id] = space.install_write_tap(0, space.addrmask(), "track_mem", [this, &space] (offs_t address, u64 &data, u64) { write_tracking(space, address, data); }, &m_phw[id]); break; } } } @@ -688,11 +689,11 @@ void device_debug::privilege_hook() if ((m_flags & DEBUG_FLAG_STOP_PRIVILEGE) != 0) { bool matched = true; - if (m_privilege_condition && !m_privilege_condition->is_empty()) + if (m_stop_condition && !m_stop_condition->is_empty()) { try { - matched = m_privilege_condition->execute(); + matched = m_stop_condition->execute(); } catch (expression_error &) { @@ -750,19 +751,53 @@ void device_debug::instruction_hook(offs_t curpc) // handle single stepping if (!debugcpu.is_stopped() && (m_flags & DEBUG_FLAG_STEPPING_ANY) != 0) { + bool do_step = true; + if ((m_flags & (DEBUG_FLAG_CALL_IN_PROGRESS | DEBUG_FLAG_TEST_IN_PROGRESS)) != 0) + { + if (curpc == m_stepaddr) + { + if ((~m_flags & (DEBUG_FLAG_TEST_IN_PROGRESS | DEBUG_FLAG_STEPPING_BRANCH_FALSE)) == 0) + { + debugcpu.set_execution_stopped(); + do_step = false; + } + + // reset the breakpoint + m_flags &= ~(DEBUG_FLAG_CALL_IN_PROGRESS | DEBUG_FLAG_TEST_IN_PROGRESS); + m_delay_steps = 0; + } + else if (m_delay_steps != 0) + { + m_delay_steps--; + if (m_delay_steps == 0) + { + // branch taken or subroutine entered (TODO: interrupt acknowledgment or interleaved multithreading can falsely trigger this) + if ((m_flags & DEBUG_FLAG_TEST_IN_PROGRESS) != 0 && (m_flags & (DEBUG_FLAG_STEPPING_OUT | DEBUG_FLAG_STEPPING_BRANCH_TRUE)) != 0) + { + debugcpu.set_execution_stopped(); + do_step = false; + } + if ((m_flags & DEBUG_FLAG_CALL_IN_PROGRESS) != 0) + do_step = false; + m_flags &= ~DEBUG_FLAG_TEST_IN_PROGRESS; + } + } + else + do_step = false; + } + // is this an actual step? - if (m_stepaddr == ~0 || curpc == m_stepaddr) + if (do_step) { - // decrement the count and reset the breakpoint + // decrement the count m_stepsleft--; - m_stepaddr = ~0; // if we hit 0, stop if (m_stepsleft == 0) debugcpu.set_execution_stopped(); // update every 100 steps until we are within 200 of the end - else if ((m_flags & DEBUG_FLAG_STEPPING_OUT) == 0 && (m_stepsleft < 200 || m_stepsleft % 100 == 0)) + else if ((m_flags & (DEBUG_FLAG_STEPPING_OUT | DEBUG_FLAG_STEPPING_BRANCH_TRUE | DEBUG_FLAG_STEPPING_BRANCH_FALSE)) == 0 && (m_stepsleft < 200 || m_stepsleft % 100 == 0)) { machine.debug_view().update_all(); machine.debug_view().flush_osd_updates(); @@ -849,7 +884,7 @@ void device_debug::instruction_hook(offs_t curpc) } // handle step out/over on the instruction we are about to execute - if ((m_flags & (DEBUG_FLAG_STEPPING_OVER | DEBUG_FLAG_STEPPING_OUT)) != 0 && m_stepaddr == ~0) + if ((m_flags & (DEBUG_FLAG_STEPPING_OVER | DEBUG_FLAG_STEPPING_OUT | DEBUG_FLAG_STEPPING_BRANCH)) != 0 && (m_flags & (DEBUG_FLAG_CALL_IN_PROGRESS | DEBUG_FLAG_TEST_IN_PROGRESS)) == 0) prepare_for_step_overout(m_state->pcbase()); // no longer in debugger code @@ -928,7 +963,7 @@ void device_debug::single_step(int numsteps) m_device.machine().rewind_capture(); m_stepsleft = numsteps; - m_stepaddr = ~0; + m_delay_steps = 0; m_flags |= DEBUG_FLAG_STEPPING; m_device.machine().debugger().cpu().set_execution_running(); } @@ -945,7 +980,7 @@ void device_debug::single_step_over(int numsteps) m_device.machine().rewind_capture(); m_stepsleft = numsteps; - m_stepaddr = ~0; + m_delay_steps = 0; m_flags |= DEBUG_FLAG_STEPPING_OVER; m_device.machine().debugger().cpu().set_execution_running(); } @@ -961,8 +996,9 @@ void device_debug::single_step_out() assert(m_exec != nullptr); m_device.machine().rewind_capture(); + m_stop_condition.reset(); m_stepsleft = 100; - m_stepaddr = ~0; + m_delay_steps = 0; m_flags |= DEBUG_FLAG_STEPPING_OUT; m_device.machine().debugger().cpu().set_execution_running(); } @@ -1060,13 +1096,30 @@ void device_debug::go_privilege(const char *condition) { assert(m_exec != nullptr); m_device.machine().rewind_invalidate(); - m_privilege_condition = std::make_unique<parsed_expression>(*m_symtable, condition); + m_stop_condition = std::make_unique<parsed_expression>(*m_symtable, condition); m_flags |= DEBUG_FLAG_STOP_PRIVILEGE; m_device.machine().debugger().cpu().set_execution_running(); } //------------------------------------------------- +// go_branch - execute until branch taken or +// not taken +//------------------------------------------------- + +void device_debug::go_branch(bool sense, const char *condition) +{ + assert(m_exec != nullptr); + m_device.machine().rewind_invalidate(); + m_stop_condition = std::make_unique<parsed_expression>(*m_symtable, condition); + m_stepsleft = 100; + m_delay_steps = 0; + m_flags |= sense ? DEBUG_FLAG_STEPPING_BRANCH_TRUE : DEBUG_FLAG_STEPPING_BRANCH_FALSE; + m_device.machine().debugger().cpu().set_execution_running(); +} + + +//------------------------------------------------- // halt_on_next_instruction_impl - halt in the // debugger on the next instruction, internal // implementation which is necessary solely due @@ -1385,7 +1438,6 @@ void device_debug::set_track_pc(bool value) // track_pc_visited - returns a boolean stating // if this PC has been visited or not. CRC32 is // done in this function on currently active CPU. -// TODO: Take a CPU context as input //------------------------------------------------- bool device_debug::track_pc_visited(offs_t pc) const @@ -1399,7 +1451,6 @@ bool device_debug::track_pc_visited(offs_t pc) const //------------------------------------------------- // set_track_pc_visited - set this pc as visited. -// TODO: Take a CPU context as input //------------------------------------------------- void device_debug::set_track_pc_visited(offs_t pc) @@ -1625,12 +1676,32 @@ void device_debug::prepare_for_step_overout(offs_t pc) // disassemble the current instruction and get the flags u32 dasmresult = buffer.disassemble_info(pc); + if ((dasmresult & util::disasm_interface::SUPPORTED) == 0) + return; + + bool step_out = (m_flags & DEBUG_FLAG_STEPPING_OUT) != 0 && (dasmresult & util::disasm_interface::STEP_OUT) != 0; + bool test_cond = (dasmresult & util::disasm_interface::STEP_COND) != 0 && ((m_flags & (DEBUG_FLAG_STEPPING_BRANCH_TRUE | DEBUG_FLAG_STEPPING_BRANCH_FALSE)) != 0 || step_out); + if (test_cond && m_stop_condition && !m_stop_condition->is_empty()) + { + try + { + test_cond = m_stop_condition->execute(); + } + catch (expression_error &) + { + test_cond = false; + } + } // if flags are supported and it's a call-style opcode, set a temp breakpoint after that instruction - if ((dasmresult & util::disasm_interface::SUPPORTED) != 0 && (dasmresult & util::disasm_interface::STEP_OVER) != 0) + // (TODO: this completely fails for subroutines that consume inline operands or use alternate returns) + if ((dasmresult & util::disasm_interface::STEP_OVER) != 0 || test_cond) { int extraskip = (dasmresult & util::disasm_interface::OVERINSTMASK) >> util::disasm_interface::OVERINSTSHIFT; pc = buffer.next_pc_wrap(pc, dasmresult & util::disasm_interface::LENGTHMASK); + m_delay_steps = extraskip + 1; + if (m_stepsleft < m_delay_steps) + m_stepsleft = m_delay_steps; // if we need to skip additional instructions, advance as requested while (extraskip-- > 0) { @@ -1638,13 +1709,17 @@ void device_debug::prepare_for_step_overout(offs_t pc) pc = buffer.next_pc_wrap(pc, result & util::disasm_interface::LENGTHMASK); } m_stepaddr = pc; + if ((dasmresult & util::disasm_interface::STEP_OVER) != 0) + m_flags |= DEBUG_FLAG_CALL_IN_PROGRESS; + if (test_cond) + m_flags |= DEBUG_FLAG_TEST_IN_PROGRESS; } // if we're stepping out and this isn't a step out instruction, reset the steps until stop to a high number - // (TODO: this doesn't work with conditional return instructions) - if ((m_flags & DEBUG_FLAG_STEPPING_OUT) != 0) + if ((m_flags & (DEBUG_FLAG_STEPPING_OUT | DEBUG_FLAG_STEPPING_BRANCH_TRUE | DEBUG_FLAG_STEPPING_BRANCH_FALSE)) != 0) { - if ((dasmresult & util::disasm_interface::SUPPORTED) != 0 && (dasmresult & util::disasm_interface::STEP_OUT) == 0) + // make sure to also reset the number of steps for conditionals that may be single-instruction loops + if (test_cond || !step_out) m_stepsleft = 100; else { diff --git a/src/emu/debug/debugcpu.h b/src/emu/debug/debugcpu.h index 9e3d23d8d7f..d9fc3f64eae 100644 --- a/src/emu/debug/debugcpu.h +++ b/src/emu/debug/debugcpu.h @@ -82,6 +82,7 @@ public: void go_exception(int exception, const char *condition); void go_milliseconds(u64 milliseconds); void go_privilege(const char *condition); + void go_branch(bool sense, const char *condition); void go_next_device(); template <typename Format, typename... Params> @@ -184,15 +185,16 @@ private: debug_instruction_hook_func m_instrhook; // per-instruction callback hook // stepping information - offs_t m_stepaddr; // step target address for DEBUG_FLAG_STEPPING_OVER + offs_t m_stepaddr; // step target address for DEBUG_FLAG_STEPPING_OVER or DEBUG_FLAG_STEPPING_BRANCH int m_stepsleft; // number of steps left until done + int m_delay_steps; // number of steps until target address check // execution information offs_t m_stopaddr; // stop address for DEBUG_FLAG_STOP_PC attotime m_stoptime; // stop time for DEBUG_FLAG_STOP_TIME int m_stopirq; // stop IRQ number for DEBUG_FLAG_STOP_INTERRUPT int m_stopexception; // stop exception number for DEBUG_FLAG_STOP_EXCEPTION - std::unique_ptr<parsed_expression> m_privilege_condition; // expression to evaluate on privilege change + std::unique_ptr<parsed_expression> m_stop_condition; // expression to evaluate on privilege change std::unique_ptr<parsed_expression> m_exception_condition; // expression to evaluate on exception hit attotime m_endexectime; // ending time of the current execution u64 m_total_cycles; // current total cycles @@ -239,10 +241,10 @@ private: // (0 = not tracing over, // ~0 = not currently tracing over) }; - std::unique_ptr<tracer> m_trace; // tracer state + std::unique_ptr<tracer> m_trace; // tracer state - std::vector<memory_passthrough_handler *> m_phw; // passthrough handler reference for each space, write mode - std::vector<int> m_notifiers; // notifiers for each space + std::vector<memory_passthrough_handler> m_phw; // passthrough handler reference for each space, write mode + std::vector<util::notifier_subscription> m_notifiers; // notifiers for each space // pc tracking class dasm_pc_tag @@ -322,12 +324,17 @@ private: static constexpr u32 DEBUG_FLAG_SUSPENDED = 0x00004000; // CPU currently suspended static constexpr u32 DEBUG_FLAG_LIVE_BP = 0x00010000; // there are live breakpoints for this CPU static constexpr u32 DEBUG_FLAG_STOP_PRIVILEGE = 0x00020000; // run until execution level changes + static constexpr u32 DEBUG_FLAG_STEPPING_BRANCH_TRUE = 0x0040000; // run until true branch + static constexpr u32 DEBUG_FLAG_STEPPING_BRANCH_FALSE = 0x0080000; // run until false branch + static constexpr u32 DEBUG_FLAG_CALL_IN_PROGRESS = 0x01000000; // CPU is in the middle of a subroutine call + static constexpr u32 DEBUG_FLAG_TEST_IN_PROGRESS = 0x02000000; // CPU is performing a conditional test and branch - static constexpr u32 DEBUG_FLAG_STEPPING_ANY = DEBUG_FLAG_STEPPING | DEBUG_FLAG_STEPPING_OVER | DEBUG_FLAG_STEPPING_OUT; + static constexpr u32 DEBUG_FLAG_STEPPING_BRANCH = DEBUG_FLAG_STEPPING_BRANCH_TRUE | DEBUG_FLAG_STEPPING_BRANCH_FALSE; + static constexpr u32 DEBUG_FLAG_STEPPING_ANY = DEBUG_FLAG_STEPPING | DEBUG_FLAG_STEPPING_OVER | DEBUG_FLAG_STEPPING_OUT | DEBUG_FLAG_STEPPING_BRANCH; static constexpr u32 DEBUG_FLAG_TRACING_ANY = DEBUG_FLAG_TRACING | DEBUG_FLAG_TRACING_OVER; static constexpr u32 DEBUG_FLAG_TRANSIENT = DEBUG_FLAG_STEPPING_ANY | DEBUG_FLAG_STOP_PC | DEBUG_FLAG_STOP_INTERRUPT | DEBUG_FLAG_STOP_EXCEPTION | DEBUG_FLAG_STOP_VBLANK | - DEBUG_FLAG_STOP_TIME | DEBUG_FLAG_STOP_PRIVILEGE; + DEBUG_FLAG_STOP_TIME | DEBUG_FLAG_STOP_PRIVILEGE | DEBUG_FLAG_CALL_IN_PROGRESS | DEBUG_FLAG_TEST_IN_PROGRESS; }; //************************************************************************** diff --git a/src/emu/debug/debughlp.cpp b/src/emu/debug/debughlp.cpp index 87bf8f0f18f..a62704c5472 100644 --- a/src/emu/debug/debughlp.cpp +++ b/src/emu/debug/debughlp.cpp @@ -81,6 +81,7 @@ const help_item f_static_help_list[] = " stateload[sl] <filename> -- load a state file for the current driver\n" " snap [<filename>] -- save a screen snapshot.\n" " source <filename> -- reads commands from <filename> and executes them one by one\n" + " time -- prints current machine time to the console\n" " cls -- clears the console text buffer\n" " quit -- exits MAME and the debugger\n" }, @@ -132,6 +133,9 @@ const help_item f_static_help_list[] = " o[ver] [<count>=1] -- single steps over <count> instructions (F10)\n" " out -- single steps until the current subroutine/exception handler is exited (Shift-F11)\n" " g[o] [<address>] -- resumes execution, sets temp breakpoint at <address> (F5)\n" + " gbf [<condition>] -- resumes execution until next false branch\n" + " gbt [<condition>] -- resumes execution until next true branch\n" + " gn[i] [<count>] -- resumes execution, sets temp breakpoint <count> instructions ahead\n" " ge[x] [<exception>[,<condition>]] -- resumes execution, setting temp breakpoint if <exception> is raised\n" " gi[nt] [<irqline>] -- resumes execution, setting temp breakpoint if <irqline> is taken (F7)\n" " gt[ime] <milliseconds> -- resumes execution until the given delay has elapsed\n" @@ -578,6 +582,13 @@ const help_item f_static_help_list[] = " Reads in debugger commands from break_and_trace.cmd and executes them.\n" }, { + "time", + "\n" + " time\n" + "\n" + "The time command prints the current machine time to the console.\n" + }, + { "quit", "\n" " quit\n" @@ -920,6 +931,66 @@ const help_item f_static_help_list[] = " Resume execution, stopping at address 1234 unless something else stops us first.\n" }, { + "gbf", + "\n" + " gbf [<condition>]\n" + "\n" + "The gbf command resumes execution of the current code. Control will not be returned to the " + "debugger until a conditional branch or skip instruction tests false and falls through to the " + "next instruction, or the instruction that follows its delay slot. The optional conditional " + "expression, if provided, will be evaluated at (not after) each conditional branch; execution " + "will not halt regardless of consequent program flow unless its result is true (non-zero).\n" + "\n" + "Examples:\n" + "\n" + "gbf\n" + " Resume execution until the next break/watchpoint or until the next false branch.\n" + "\n" + "gbf {pc != 1234}\n" + " Resume execution until the next false branch, disregarding the instruction at address 1234.\n" + }, + { + "gbt", + "\n" + " gbt [<condition>]\n" + "\n" + "The gbt command resumes execution of the current code. Control will not be returned to the " + "debugger until a conditional branch or skip instruction tests true and program flow transfers " + "to any instruction other than the next one following the delay slot (if any). The optional " + "conditional expression, if provided, will be evaluated at (not after) each conditional " + "branch; execution will not halt regardless of consequent program flow unless its result is " + "true (non-zero).\n" + "\n" + "Examples:\n" + "\n" + "gbt\n" + " Resume execution until the next break/watchpoint or until the next true branch.\n" + "\n" + "gbt {pc != 1234}\n" + " Resume execution until the next true branch, disregarding the instruction at address 1234.\n" + }, + { + "gni", + "\n" + " gn[i] [<count>]\n" + "\n" + "The gni command resumes execution of the current code. Control will not be returned to the " + "debugger until a breakpoint or watchpoint is hit, or until you manually break in using the " + "assigned key. Before executing, the gni command sets a temporary unconditional breakpoint " + "<count> instructions sequentially past the current one, which is automatically removed when " + "hit. If <count> is omitted, its default value is 1. If <count> is specified as zero, the " + "command does nothing. <count> is not permitted to exceed 512 decimal." + "\n" + "Examples:\n" + "\n" + "gni\n" + " Resume execution, stopping at the address of the next instruction unless something else " + "stops us first.\n" + "\n" + "gni 2\n" + " Resume execution, stopping at two instructions past the current one.\n" + }, + { "gex", "\n" " ge[x] [<exception>,[<condition>]]\n" diff --git a/src/emu/debug/debugvw.cpp b/src/emu/debug/debugvw.cpp index 5bcc3d057b8..54fe57ecf5a 100644 --- a/src/emu/debug/debugvw.cpp +++ b/src/emu/debug/debugvw.cpp @@ -503,11 +503,11 @@ bool debug_view_expression::recompute() std::string oldstring(m_parsed.original_string()); try { - m_parsed.parse(m_string.c_str()); + m_parsed.parse(m_string); } catch (expression_error &) { - m_parsed.parse(oldstring.c_str()); + m_parsed.parse(oldstring); } } diff --git a/src/emu/debug/dvmemory.cpp b/src/emu/debug/dvmemory.cpp index 02fcde9cbc3..1f1adcb138d 100644 --- a/src/emu/debug/dvmemory.cpp +++ b/src/emu/debug/dvmemory.cpp @@ -20,6 +20,20 @@ //************************************************************************** +// HELPER FUNCTIONS +//************************************************************************** + +namespace { + +constexpr u8 sanitise_character(u8 ch) +{ + // assume ISO-8859-1 (low 256 Unicode codepoints) - tab, soft hyphen, C0 and C1 cause problems + return ('\t' == ch) ? ' ' : (0xadU == ch) ? '-' : ((' ' > ch) || (('~' < ch) && (0xa0U > ch))) ? '.' : ch; +} + +} // anonymous namespace + +//************************************************************************** // GLOBAL VARIABLES //************************************************************************** @@ -301,7 +315,7 @@ void debug_view_memory::generate_row(debug_view_char *destmin, debug_view_char * if (dest >= destmin && dest < destmax) dest->byte = addrtext[ch]; - // generate the data and the ascii string + // generate the data and the ASCII string std::string chunkascii; if (m_shift_bits != 0) { @@ -323,7 +337,7 @@ void debug_view_memory::generate_row(debug_view_char *destmin, debug_view_char * for (int i = 0; i < m_bytes_per_chunk; i++) { u8 chval = chunkdata >> (8 * (m_bytes_per_chunk - i - 1)); - chunkascii += char((ismapped && isprint(chval)) ? chval : '.'); + chunkascii += char(ismapped ? sanitise_character(chval) : '.'); } } } @@ -380,7 +394,7 @@ void debug_view_memory::generate_row(debug_view_char *destmin, debug_view_char * for (int i = 0; i < m_bytes_per_chunk; i++) { u8 chval = chunkdata >> (8 * (m_bytes_per_chunk - i - 1)); - chunkascii += char((ismapped && isprint(chval)) ? chval : '.'); + chunkascii += char(ismapped ? sanitise_character(chval) : '.'); } } } @@ -526,16 +540,8 @@ void debug_view_memory::view_char(int chval) if (hexchar == nullptr || (m_shift_bits == 3 && chval >= '8')) break; - const debug_view_memory_source &source = downcast<const debug_view_memory_source &>(*m_source); - offs_t address = (source.m_space != nullptr) ? source.m_space->byte_to_address(pos.m_address) : pos.m_address; - u64 data; - bool ismapped = read(m_bytes_per_chunk, address, data); - if (!ismapped) - break; - - data &= ~(util::make_bitmask<u64>(m_shift_bits) << pos.m_shift); - data |= u64(hexchar - hexvals) << pos.m_shift; - write(m_bytes_per_chunk, address, data); + if (!write_digit(pos.m_address, pos.m_shift, hexchar - hexvals)) + break; // TODO: alert OSD? } // fall through to the right-arrow press [[fallthrough]]; @@ -984,6 +990,41 @@ void debug_view_memory::write(u8 size, offs_t offs, u64 data) //------------------------------------------------- +// write_digit - write one hex or octal digit +// at the given address and bit position +//------------------------------------------------- + +bool debug_view_memory::write_digit(offs_t offs, u8 pos, u8 digit) +{ + const debug_view_memory_source &source = downcast<const debug_view_memory_source &>(*m_source); + offs_t address = (source.m_space != nullptr) ? source.m_space->byte_to_address(offs) : offs; + u64 data; + bool ismapped = read(m_bytes_per_chunk, address, data); + if (!ismapped) + return false; + + // clamp to chunk size + if (m_bytes_per_chunk * 8 < pos + m_shift_bits) + { + assert(m_bytes_per_chunk * 8 > pos); + digit &= util::make_bitmask<u8>(m_bytes_per_chunk * 8 - pos); + } + + u64 write_data = (data & ~(util::make_bitmask<u64>(m_shift_bits) << pos)) | (u64(digit) << pos); + write(m_bytes_per_chunk, address, write_data); + + // verify that data reads back as it was written + if (source.m_space != nullptr) + { + read(m_bytes_per_chunk, address, data); + return data == write_data; + } + else + return true; +} + + +//------------------------------------------------- // set_expression - set the expression string // describing the home address //------------------------------------------------- diff --git a/src/emu/debug/dvmemory.h b/src/emu/debug/dvmemory.h index f2c738a6ff4..6f1ffab4e9e 100644 --- a/src/emu/debug/dvmemory.h +++ b/src/emu/debug/dvmemory.h @@ -127,6 +127,7 @@ private: // memory access bool read(u8 size, offs_t offs, u64 &data); void write(u8 size, offs_t offs, u64 data); + bool write_digit(offs_t offs, u8 pos, u8 digit); bool read(u8 size, offs_t offs, extFloat80_t &data); bool read_chunk(offs_t address, int chunknum, u64 &chunkdata); void generate_row(debug_view_char *destmin, debug_view_char *destmax, debug_view_char *destrow, offs_t address); diff --git a/src/emu/debug/express.cpp b/src/emu/debug/express.cpp index 8363928e5cb..f9074147b7b 100644 --- a/src/emu/debug/express.cpp +++ b/src/emu/debug/express.cpp @@ -387,10 +387,10 @@ void symbol_table::set_memory_modified_func(memory_modified_func modified) // add - add a new u64 pointer symbol //------------------------------------------------- -void symbol_table::add(const char *name, read_write rw, u64 *ptr) +symbol_entry &symbol_table::add(const char *name, read_write rw, u64 *ptr) { m_symlist.erase(name); - m_symlist.emplace(name, std::make_unique<integer_symbol_entry>(*this, name, rw, ptr)); + return *m_symlist.emplace(name, std::make_unique<integer_symbol_entry>(*this, name, rw, ptr)).first->second; } @@ -398,10 +398,10 @@ void symbol_table::add(const char *name, read_write rw, u64 *ptr) // add - add a new value symbol //------------------------------------------------- -void symbol_table::add(const char *name, u64 value) +symbol_entry &symbol_table::add(const char *name, u64 value) { m_symlist.erase(name); - m_symlist.emplace(name, std::make_unique<integer_symbol_entry>(*this, name, value)); + return *m_symlist.emplace(name, std::make_unique<integer_symbol_entry>(*this, name, value)).first->second; } @@ -409,10 +409,10 @@ void symbol_table::add(const char *name, u64 value) // add - add a new register symbol //------------------------------------------------- -void symbol_table::add(const char *name, getter_func getter, setter_func setter, const std::string &format_string) +symbol_entry &symbol_table::add(const char *name, getter_func getter, setter_func setter, const std::string &format_string) { m_symlist.erase(name); - m_symlist.emplace(name, std::make_unique<integer_symbol_entry>(*this, name, getter, setter, format_string)); + return *m_symlist.emplace(name, std::make_unique<integer_symbol_entry>(*this, name, getter, setter, format_string)).first->second; } @@ -420,10 +420,10 @@ void symbol_table::add(const char *name, getter_func getter, setter_func setter, // add - add a new function symbol //------------------------------------------------- -void symbol_table::add(const char *name, int minparams, int maxparams, execute_func execute) +symbol_entry &symbol_table::add(const char *name, int minparams, int maxparams, execute_func execute) { m_symlist.erase(name); - m_symlist.emplace(name, std::make_unique<function_symbol_entry>(*this, name, minparams, maxparams, execute)); + return *m_symlist.emplace(name, std::make_unique<function_symbol_entry>(*this, name, minparams, maxparams, execute)).first->second; } diff --git a/src/emu/debug/express.h b/src/emu/debug/express.h index 23284193f47..74b52710959 100644 --- a/src/emu/debug/express.h +++ b/src/emu/debug/express.h @@ -175,15 +175,16 @@ public: // getters const std::unordered_map<std::string, std::unique_ptr<symbol_entry>> &entries() const { return m_symlist; } symbol_table *parent() const { return m_parent; } + running_machine &machine() { return m_machine; } // setters void set_memory_modified_func(memory_modified_func modified); // symbol access - void add(const char *name, read_write rw, u64 *ptr = nullptr); - void add(const char *name, u64 constvalue); - void add(const char *name, getter_func getter, setter_func setter = nullptr, const std::string &format_string = ""); - void add(const char *name, int minparams, int maxparams, execute_func execute); + symbol_entry &add(const char *name, read_write rw, u64 *ptr = nullptr); + symbol_entry &add(const char *name, u64 constvalue); + symbol_entry &add(const char *name, getter_func getter, setter_func setter = nullptr, const std::string &format_string = ""); + symbol_entry &add(const char *name, int minparams, int maxparams, execute_func execute); symbol_entry *find(const char *name) const { if (name) { auto search = m_symlist.find(name); if (search != m_symlist.end()) return search->second.get(); else return nullptr; } else return nullptr; } symbol_entry *find_deep(const char *name); diff --git a/src/emu/debug/points.cpp b/src/emu/debug/points.cpp index c44bc3f7563..a19f0ab5619 100644 --- a/src/emu/debug/points.cpp +++ b/src/emu/debug/points.cpp @@ -22,18 +22,19 @@ // debug_breakpoint - constructor //------------------------------------------------- -debug_breakpoint::debug_breakpoint(device_debug* debugInterface, - symbol_table &symbols, - int index, - offs_t address, - const char *condition, - const char *action) - : m_debugInterface(debugInterface), - m_index(index), - m_enabled(true), - m_address(address), - m_condition(symbols, (condition != nullptr) ? condition : "1"), - m_action((action != nullptr) ? action : "") +debug_breakpoint::debug_breakpoint( + device_debug *debugInterface, + symbol_table &symbols, + int index, + offs_t address, + const char *condition, + const char *action) : + m_debugInterface(debugInterface), + m_index(index), + m_enabled(true), + m_address(address), + m_condition(symbols, condition ? condition : "1"), + m_action(action ? action : "") { } @@ -59,7 +60,7 @@ bool debug_breakpoint::hit(offs_t pc) { return (m_condition.execute() != 0); } - catch (expression_error &) + catch (expression_error const &) { return false; } @@ -78,27 +79,28 @@ bool debug_breakpoint::hit(offs_t pc) // debug_watchpoint - constructor //------------------------------------------------- -debug_watchpoint::debug_watchpoint(device_debug* debugInterface, - symbol_table &symbols, - int index, - address_space &space, - read_or_write type, - offs_t address, - offs_t length, - const char *condition, - const char *action) - : m_debugInterface(debugInterface), - m_phr(nullptr), - m_phw(nullptr), - m_space(space), - m_index(index), - m_enabled(true), - m_type(type), - m_address(address & space.addrmask()), - m_length(length), - m_condition(symbols, (condition != nullptr) ? condition : "1"), - m_action((action != nullptr) ? action : ""), - m_installing(false) +debug_watchpoint::debug_watchpoint( + device_debug* debugInterface, + symbol_table &symbols, + int index, + address_space &space, + read_or_write type, + offs_t address, + offs_t length, + const char *condition, + const char *action) : + m_debugInterface(debugInterface), + m_phr(nullptr), + m_phw(nullptr), + m_space(space), + m_index(index), + m_enabled(true), + m_type(type), + m_address(address & space.addrmask()), + m_length(length), + m_condition(symbols, condition ? condition : "1"), + m_action(action ? action : ""), + m_installing(false) { std::fill(std::begin(m_start_address), std::end(m_start_address), 0); std::fill(std::begin(m_end_address), std::end(m_end_address), 0); @@ -170,21 +172,21 @@ debug_watchpoint::debug_watchpoint(device_debug* debugInterface, } install(read_or_write::READWRITE); - m_notifier = m_space.add_change_notifier([this](read_or_write mode) { - if (m_enabled) - { - install(mode); - } - }); + m_notifier = m_space.add_change_notifier( + [this] (read_or_write mode) + { + if (m_enabled) + { + install(mode); + } + }); } debug_watchpoint::~debug_watchpoint() { - m_space.remove_change_notifier(m_notifier); - if (m_phr) - m_phr->remove(); - if (m_phw) - m_phw->remove(); + m_notifier.reset(); + m_phr.remove(); + m_phw.remove(); } void debug_watchpoint::setEnabled(bool value) @@ -197,10 +199,8 @@ void debug_watchpoint::setEnabled(bool value) else { m_installing = true; - if(m_phr) - m_phr->remove(); - if(m_phw) - m_phw->remove(); + m_phr.remove(); + m_phw.remove(); m_installing = false; } } @@ -211,24 +211,28 @@ void debug_watchpoint::install(read_or_write mode) if (m_installing) return; m_installing = true; - if ((u32(mode) & u32(read_or_write::READ)) && m_phr) - m_phr->remove(); - if ((u32(mode) & u32(read_or_write::WRITE)) && m_phw) - m_phw->remove(); + if (u32(mode) & u32(read_or_write::READ)) + m_phr.remove(); + if (u32(mode) & u32(read_or_write::WRITE)) + m_phw.remove(); std::string name = util::string_format("wp@%x", m_address); switch (m_space.data_width()) { case 8: if (u32(m_type) & u32(mode) & u32(read_or_write::READ)) - m_phr = m_space.install_read_tap(m_start_address[0], m_end_address[0], name, - [this](offs_t offset, u8 &data, u8 mem_mask) { - triggered(read_or_write::READ, offset, data, mem_mask); - }, m_phr); + m_phr = m_space.install_read_tap( + m_start_address[0], m_end_address[0], name, + [this](offs_t offset, u8 &data, u8 mem_mask) { + triggered(read_or_write::READ, offset, data, mem_mask); + }, + &m_phr); if (u32(m_type) & u32(mode) & u32(read_or_write::WRITE)) - m_phw = m_space.install_write_tap(m_start_address[0], m_end_address[0], name, - [this](offs_t offset, u8 &data, u8 mem_mask) { - triggered(read_or_write::WRITE, offset, data, mem_mask); - }, m_phw); + m_phw = m_space.install_write_tap( + m_start_address[0], m_end_address[0], name, + [this](offs_t offset, u8 &data, u8 mem_mask) { + triggered(read_or_write::WRITE, offset, data, mem_mask); + }, + &m_phw); break; case 16: @@ -237,17 +241,21 @@ void debug_watchpoint::install(read_or_write mode) { u16 mask = m_masks[i]; if (u32(m_type) & u32(mode) & u32(read_or_write::READ)) - m_phr = m_space.install_read_tap(m_start_address[i], m_end_address[i], name, - [this, mask](offs_t offset, u16 &data, u16 mem_mask) { - if (mem_mask & mask) - triggered(read_or_write::READ, offset, data, mem_mask); - }, m_phr); + m_phr = m_space.install_read_tap( + m_start_address[i], m_end_address[i], name, + [this, mask](offs_t offset, u16 &data, u16 mem_mask) { + if (mem_mask & mask) + triggered(read_or_write::READ, offset, data, mem_mask); + }, + &m_phr); if (u32(m_type) & u32(mode) & u32(read_or_write::WRITE)) - m_phw = m_space.install_write_tap(m_start_address[i], m_end_address[i], name, - [this, mask](offs_t offset, u16 &data, u16 mem_mask) { - if (mem_mask & mask) - triggered(read_or_write::WRITE, offset, data, mem_mask); - }, m_phw); + m_phw = m_space.install_write_tap( + m_start_address[i], m_end_address[i], name, + [this, mask](offs_t offset, u16 &data, u16 mem_mask) { + if (mem_mask & mask) + triggered(read_or_write::WRITE, offset, data, mem_mask); + }, + &m_phw); } break; @@ -257,17 +265,21 @@ void debug_watchpoint::install(read_or_write mode) { u32 mask = m_masks[i]; if (u32(m_type) & u32(mode) & u32(read_or_write::READ)) - m_phr = m_space.install_read_tap(m_start_address[i], m_end_address[i], name, - [this, mask](offs_t offset, u32 &data, u32 mem_mask) { - if (mem_mask & mask) - triggered(read_or_write::READ, offset, data, mem_mask); - }, m_phr); + m_phr = m_space.install_read_tap( + m_start_address[i], m_end_address[i], name, + [this, mask](offs_t offset, u32 &data, u32 mem_mask) { + if (mem_mask & mask) + triggered(read_or_write::READ, offset, data, mem_mask); + }, + &m_phr); if (u32(m_type) & u32(mode) & u32(read_or_write::WRITE)) - m_phw = m_space.install_write_tap(m_start_address[i], m_end_address[i], name, - [this, mask](offs_t offset, u32 &data, u32 mem_mask) { - if (mem_mask & mask) - triggered(read_or_write::WRITE, offset, data, mem_mask); - }, m_phw); + m_phw = m_space.install_write_tap( + m_start_address[i], m_end_address[i], name, + [this, mask](offs_t offset, u32 &data, u32 mem_mask) { + if (mem_mask & mask) + triggered(read_or_write::WRITE, offset, data, mem_mask); + }, + &m_phw); } break; @@ -277,17 +289,20 @@ void debug_watchpoint::install(read_or_write mode) { u64 mask = m_masks[i]; if (u32(m_type) & u32(mode) & u32(read_or_write::READ)) - m_phr = m_space.install_read_tap(m_start_address[i], m_end_address[i], name, - [this, mask](offs_t offset, u64 &data, u64 mem_mask) { - if (mem_mask & mask) - triggered(read_or_write::READ, offset, data, mem_mask); - }, m_phr); + m_phr = m_space.install_read_tap( + m_start_address[i], m_end_address[i], name, + [this, mask](offs_t offset, u64 &data, u64 mem_mask) { + if (mem_mask & mask) + triggered(read_or_write::READ, offset, data, mem_mask); + }, + &m_phr); if (u32(m_type) & u32(mode) & u32(read_or_write::WRITE)) m_phw = m_space.install_write_tap(m_start_address[i], m_end_address[i], name, - [this, mask](offs_t offset, u64 &data, u64 mem_mask) { - if (mem_mask & mask) - triggered(read_or_write::WRITE, offset, data, mem_mask); - }, m_phw); + [this, mask](offs_t offset, u64 &data, u64 mem_mask) { + if (mem_mask & mask) + triggered(read_or_write::WRITE, offset, data, mem_mask); + }, + &m_phw); } break; } diff --git a/src/emu/debug/points.h b/src/emu/debug/points.h index 84cdad7720b..62ad953626c 100644 --- a/src/emu/debug/points.h +++ b/src/emu/debug/points.h @@ -102,8 +102,8 @@ private: void triggered(read_or_write type, offs_t address, u64 data, u64 mem_mask); device_debug * m_debugInterface; // the interface we were created from - memory_passthrough_handler *m_phr; // passthrough handler reference, read access - memory_passthrough_handler *m_phw; // passthrough handler reference, write access + memory_passthrough_handler m_phr; // passthrough handler reference, read access + memory_passthrough_handler m_phw; // passthrough handler reference, write access address_space & m_space; // address space int m_index; // user reported index bool m_enabled; // enabled? @@ -112,7 +112,7 @@ private: offs_t m_length; // length of watch area parsed_expression m_condition; // condition std::string m_action; // action - int m_notifier; // address map change notifier id + util::notifier_subscription m_notifier; // address map change notifier ID offs_t m_start_address[3]; // the start addresses of the checks to install offs_t m_end_address[3]; // the end addresses diff --git a/src/emu/devcb.h b/src/emu/devcb.h index d27d3beb74d..7638f901296 100644 --- a/src/emu/devcb.h +++ b/src/emu/devcb.h @@ -82,16 +82,10 @@ protected: template <typename T, typename U> using mask_t = std::make_unsigned_t<intermediate_t<T, U> >; // Detecting candidates for transform functions - template <typename Input, typename Result, typename Func, typename Enable = void> struct is_transform_form1 : public std::false_type { }; - template <typename Input, typename Result, typename Func, typename Enable = void> struct is_transform_form2 : public std::false_type { }; - template <typename Input, typename Result, typename Func, typename Enable = void> struct is_transform_form3 : public std::false_type { }; - template <typename Input, typename Result, typename Func, typename Enable = void> struct is_transform_form4 : public std::false_type { }; - template <typename Input, typename Result, typename Func, typename Enable = void> struct is_transform_form5 : public std::false_type { }; - template <typename Input, typename Result, typename Func, typename Enable = void> struct is_transform_form6 : public std::false_type { }; - template <typename Input, typename Result, typename Func> struct is_transform_form3<Input, Result, Func, std::enable_if_t<std::is_convertible<std::invoke_result_t<Func, offs_t &, Input, std::make_unsigned_t<Input> &>, Result>::value> > : public std::true_type { }; - template <typename Input, typename Result, typename Func> struct is_transform_form4<Input, Result, Func, std::enable_if_t<std::is_convertible<std::invoke_result_t<Func, offs_t &, Input>, Result>::value> > : public std::true_type { }; - template <typename Input, typename Result, typename Func> struct is_transform_form6<Input, Result, Func, std::enable_if_t<std::is_convertible<std::invoke_result_t<Func, Input>, Result>::value> > : public std::true_type { }; - template <typename Input, typename Result, typename Func> struct is_transform : public std::bool_constant<is_transform_form1<Input, Result, Func>::value || is_transform_form2<Input, Result, Func>::value || is_transform_form3<Input, Result, Func>::value || is_transform_form4<Input, Result, Func>::value || is_transform_form5<Input, Result, Func>::value || is_transform_form6<Input, Result, Func>::value> { }; + template <typename Input, typename Result, typename Func> using is_transform_form3 = std::is_invocable_r<Result, Func, offs_t &, Input, std::make_unsigned_t<Input> &>; + template <typename Input, typename Result, typename Func> using is_transform_form4 = std::is_invocable_r<Result, Func, offs_t &, Input>; + template <typename Input, typename Result, typename Func> using is_transform_form6 = std::is_invocable_r<Result, Func, Input>; + template <typename Input, typename Result, typename Func> using is_transform = std::bool_constant<is_transform_form3<Input, Result, Func>::value || is_transform_form4<Input, Result, Func>::value || is_transform_form6<Input, Result, Func>::value>; // Determining the result type of a transform function template <typename Input, typename Result, typename Func, typename Enable = void> struct transform_result; @@ -137,12 +131,18 @@ protected: auto rshift(unsigned val) { auto trans(static_cast<Impl &>(*this).transform([val] (offs_t offset, T data, std::make_unsigned_t<T> &mem_mask) { mem_mask >>= val; return data >> val; })); - return inherited_mask() ? std::move(trans) : std::move(trans.mask(m_mask >> val)); + if (inherited_mask()) + return trans; + else + return std::move(trans.mask(m_mask >> val)); } auto lshift(unsigned val) { auto trans(static_cast<Impl &>(*this).transform([val] (offs_t offset, T data, std::make_unsigned_t<T> &mem_mask) { mem_mask <<= val; return data << val; })); - return inherited_mask() ? std::move(trans) : std::move(trans.mask(m_mask << val)); + if (inherited_mask()) + return trans; + else + return std::move(trans.mask(m_mask << val)); } auto bit(unsigned val) { return std::move(rshift(val).mask(T(1U))); } @@ -211,13 +211,10 @@ class devcb_read_base : public devcb_base { protected: // Detecting candidates for read functions - template <typename Result, typename Func, typename Enable = void> struct is_read_form1 : public std::false_type { }; - template <typename Result, typename Func, typename Enable = void> struct is_read_form2 : public std::false_type { }; - template <typename Result, typename Func, typename Enable = void> struct is_read_form3 : public std::false_type { }; - template <typename Result, typename Func> struct is_read_form1<Result, Func, std::enable_if_t<std::is_convertible<std::invoke_result_t<Func, offs_t, Result>, Result>::value> > : public std::true_type { }; - template <typename Result, typename Func> struct is_read_form2<Result, Func, std::enable_if_t<std::is_convertible<std::invoke_result_t<Func, offs_t>, Result>::value> > : public std::true_type { }; - template <typename Result, typename Func> struct is_read_form3<Result, Func, std::enable_if_t<std::is_convertible<std::invoke_result_t<Func>, Result>::value> > : public std::true_type { }; - template <typename Result, typename Func> struct is_read : public std::bool_constant<is_read_form1<Result, Func>::value || is_read_form2<Result, Func>::value || is_read_form3<Result, Func>::value> { }; + template <typename Result, typename Func> using is_read_form1 = std::is_invocable_r<Result, Func, offs_t, Result>; + template <typename Result, typename Func> using is_read_form2 = std::is_invocable_r<Result, Func, offs_t>; + template <typename Result, typename Func> using is_read_form3 = std::is_invocable_r<Result, Func>; + template <typename Result, typename Func> using is_read = std::bool_constant<is_read_form1<Result, Func>::value || is_read_form2<Result, Func>::value || is_read_form3<Result, Func>::value>; // Determining the result type of a read function template <typename Result, typename Func, typename Enable = void> struct read_result; @@ -275,13 +272,10 @@ class devcb_write_base : public devcb_base { protected: // Detecting candidates for write functions - template <typename Input, typename Func, typename Enable = void> struct is_write_form1 : public std::false_type { }; - template <typename Input, typename Func, typename Enable = void> struct is_write_form2 : public std::false_type { }; - template <typename Input, typename Func, typename Enable = void> struct is_write_form3 : public std::false_type { }; - template <typename Input, typename Func> struct is_write_form1<Input, Func, void_t<std::invoke_result_t<Func, offs_t, Input, std::make_unsigned_t<Input>> > > : public std::true_type { }; - template <typename Input, typename Func> struct is_write_form2<Input, Func, void_t<std::invoke_result_t<Func, offs_t, Input> > > : public std::true_type { }; - template <typename Input, typename Func> struct is_write_form3<Input, Func, void_t<std::invoke_result_t<Func, Input> > > : public std::true_type { }; - template <typename Input, typename Func> struct is_write : public std::bool_constant<is_write_form1<Input, Func>::value || is_write_form2<Input, Func>::value || is_write_form3<Input, Func>::value> { }; + template <typename Input, typename Func> using is_write_form1 = std::is_invocable<Func, offs_t, Input, std::make_unsigned_t<Input> >; + template <typename Input, typename Func> using is_write_form2 = std::is_invocable<Func, offs_t, Input>; + template <typename Input, typename Func> using is_write_form3 = std::is_invocable<Func, Input>; + template <typename Input, typename Func> using is_write = std::bool_constant<is_write_form1<Input, Func>::value || is_write_form2<Input, Func>::value || is_write_form3<Input, Func>::value>; // Detecting candidates for write delegates template <typename T, typename Enable = void> struct is_write_method : public std::false_type { }; @@ -494,7 +488,7 @@ private: assert(this->m_consumed); this->built(); chain( - [src = std::forward<U>(f), cb = std::move(this->m_cb), exor = this->exor(), mask = this->mask()] (offs_t &offset, input_mask_t &mem_mask) + [src = std::forward<U>(f), cb = std::move(m_cb), exor = this->exor(), mask = this->mask()] (offs_t &offset, input_mask_t &mem_mask) { typename Source::input_mask_t source_mask(mem_mask); auto const data(src(offset, source_mask)); @@ -549,7 +543,7 @@ private: assert(this->m_consumed); this->built(); chain( - [cb = std::move(this->m_cb), exor = this->exor(), mask = this->mask()] (offs_t offset, input_mask_t mem_mask) + [cb = std::move(m_cb), exor = this->exor(), mask = this->mask()] (offs_t offset, input_mask_t mem_mask) { return (devcb_read::invoke_read<Result>(cb, offset, mem_mask & mask) ^ exor) & mask; }); } @@ -615,7 +609,7 @@ private: this->built(); m_delegate.resolve(); chain( - [cb = std::move(this->m_delegate), exor = this->exor(), mask = this->mask()] (offs_t offset, input_mask_t mem_mask) + [cb = std::move(m_delegate), exor = this->exor(), mask = this->mask()] (offs_t offset, input_mask_t mem_mask) { return (devcb_read::invoke_read<Result>(cb, offset, mem_mask & mask) ^ exor) & mask; }); } @@ -1079,7 +1073,7 @@ private: assert(this->m_consumed); this->built(); return m_src.build( - [f = std::move(chain), cb = std::move(this->m_cb), exor = this->exor(), mask = this->mask()] (offs_t &offset, input_t data, std::make_unsigned_t<input_t> &mem_mask) + [f = std::move(chain), cb = std::move(m_cb), exor = this->exor(), mask = this->mask()] (offs_t &offset, input_t data, std::make_unsigned_t<input_t> &mem_mask) { auto const trans(devcb_write::invoke_transform<input_t, output_t>(cb, offset, data, mem_mask)); output_t out_mask(mem_mask & mask); @@ -1139,7 +1133,7 @@ private: assert(this->m_consumed); this->built(); return - [sink = m_sink.build(), cb = std::move(this->m_cb), in_exor = m_in_exor, in_mask = m_in_mask, exor = this->exor(), mask = this->mask()] (offs_t offset, input_t data, std::make_unsigned_t<input_t> mem_mask) + [sink = m_sink.build(), cb = std::move(m_cb), in_exor = m_in_exor, in_mask = m_in_mask, exor = this->exor(), mask = this->mask()] (offs_t offset, input_t data, std::make_unsigned_t<input_t> mem_mask) { data = (data ^ in_exor) & in_mask; mem_mask &= in_mask; @@ -1160,7 +1154,7 @@ private: assert(this->m_consumed); this->built(); return - [f = std::move(chain), sink = m_sink.build(), cb = std::move(this->m_cb), in_exor = m_in_exor, in_mask = m_in_mask, exor = this->exor(), mask = this->mask()] (offs_t offset, input_t data, std::make_unsigned_t<input_t> mem_mask) + [f = std::move(chain), sink = m_sink.build(), cb = std::move(m_cb), in_exor = m_in_exor, in_mask = m_in_mask, exor = this->exor(), mask = this->mask()] (offs_t offset, input_t data, std::make_unsigned_t<input_t> mem_mask) { data = (data ^ in_exor) & in_mask; mem_mask &= in_mask; @@ -1197,7 +1191,7 @@ private: assert(this->m_consumed); this->built(); return - [cb = std::move(this->m_cb)] (offs_t offset, input_t data, std::make_unsigned_t<input_t> mem_mask) + [cb = std::move(m_cb)] (offs_t offset, input_t data, std::make_unsigned_t<input_t> mem_mask) { devcb_write::invoke_write<Input>(cb, offset, data, mem_mask); }; } @@ -1247,7 +1241,7 @@ private: assert(this->m_consumed); this->built(); return - [cb = std::move(this->m_cb), exor = this->exor(), mask = this->mask()] (offs_t offset, input_t data, std::make_unsigned_t<input_t> mem_mask) + [cb = std::move(m_cb), exor = this->exor(), mask = this->mask()] (offs_t offset, input_t data, std::make_unsigned_t<input_t> mem_mask) { devcb_write::invoke_write<Input>(cb, offset, (data ^ exor) & mask, mem_mask & mask); }; } }; @@ -1291,7 +1285,7 @@ private: this->built(); m_delegate.resolve(); return - [cb = std::move(this->m_delegate)] (offs_t offset, input_t data, std::make_unsigned_t<input_t> mem_mask) + [cb = std::move(m_delegate)] (offs_t offset, input_t data, std::make_unsigned_t<input_t> mem_mask) { devcb_write::invoke_write<Input>(cb, offset, data, mem_mask); }; } @@ -1357,7 +1351,7 @@ private: this->built(); m_delegate.resolve(); return - [cb = std::move(this->m_delegate), exor = this->exor(), mask = this->mask()] (offs_t offset, input_t data, std::make_unsigned_t<input_t> mem_mask) + [cb = std::move(m_delegate), exor = this->exor(), mask = this->mask()] (offs_t offset, input_t data, std::make_unsigned_t<input_t> mem_mask) { devcb_write::invoke_write<Input>(cb, offset, (data ^ exor) & mask, mem_mask & mask); }; } }; diff --git a/src/emu/device.cpp b/src/emu/device.cpp index c9097a59d4f..6a4b0d4b685 100644 --- a/src/emu/device.cpp +++ b/src/emu/device.cpp @@ -365,7 +365,7 @@ void device_t::reset() // unscaled clock //------------------------------------------------- -void device_t::set_unscaled_clock(u32 clock) +void device_t::set_unscaled_clock(u32 clock, bool sync_on_new_clock_domain) { // do nothing if no actual change if (clock == m_unscaled_clock) @@ -381,7 +381,7 @@ void device_t::set_unscaled_clock(u32 clock) // if the device has already started, make sure it knows about the new clock if (m_started) - notify_clock_changed(); + notify_clock_changed(sync_on_new_clock_domain); } @@ -464,9 +464,9 @@ u64 device_t::attotime_to_clocks(const attotime &duration) const noexcept // callback //------------------------------------------------- -emu_timer *device_t::timer_alloc(device_timer_id id, void *ptr) +emu_timer *device_t::timer_alloc(device_timer_id id) { - return machine().scheduler().timer_alloc(*this, id, ptr); + return machine().scheduler().timer_alloc(*this, id); } @@ -475,9 +475,9 @@ emu_timer *device_t::timer_alloc(device_timer_id id, void *ptr) // call our device callback //------------------------------------------------- -void device_t::timer_set(const attotime &duration, device_timer_id id, int param, void *ptr) +void device_t::timer_set(const attotime &duration, device_timer_id id, int param) { - machine().scheduler().timer_set(duration, *this, id, param, ptr); + machine().scheduler().timer_set(duration, *this, id, param); } @@ -609,7 +609,6 @@ void device_t::start() } // register our save states - save_item(NAME(m_clock)); save_item(NAME(m_unscaled_clock)); save_item(NAME(m_clock_scale)); @@ -688,6 +687,21 @@ void device_t::pre_save() void device_t::post_load() { + // recompute clock-related parameters if something changed + u32 const scaled_clock = m_unscaled_clock * m_clock_scale; + if (m_clock != scaled_clock) + { + m_clock = scaled_clock; + m_attoseconds_per_clock = (scaled_clock == 0) ? 0 : HZ_TO_ATTOSECONDS(scaled_clock); + + // recalculate all derived clocks + for (device_t &child : subdevices()) + child.calculate_derived_clock(); + + // make sure the device knows about the new clock + notify_clock_changed(); + } + // notify the interface for (device_interface &intf : interfaces()) intf.interface_post_load(); @@ -702,11 +716,11 @@ void device_t::post_load() // that the clock has changed //------------------------------------------------- -void device_t::notify_clock_changed() +void device_t::notify_clock_changed(bool sync_on_new_clock_domain) { // first notify interfaces for (device_interface &intf : interfaces()) - intf.interface_clock_changed(); + intf.interface_clock_changed(sync_on_new_clock_domain); // then notify the device device_clock_changed(); @@ -872,7 +886,7 @@ void device_t::device_debug_setup() // fires //------------------------------------------------- -void device_t::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +void device_t::device_timer(emu_timer &timer, device_timer_id id, int param) { // do nothing by default } @@ -1188,7 +1202,7 @@ void device_interface::interface_post_load() // implementation //------------------------------------------------- -void device_interface::interface_clock_changed() +void device_interface::interface_clock_changed(bool sync_on_new_clock_domain) { // do nothing by default } diff --git a/src/emu/device.h b/src/emu/device.h index 77c12cb2d56..4ea1a940320 100644 --- a/src/emu/device.h +++ b/src/emu/device.h @@ -210,7 +210,7 @@ private: assert(!owner); assert(!clock); - return make_unique_clear<DriverClass>(mconfig, type, tag); + return std::make_unique<DriverClass>(mconfig, type, tag); } create_func const m_creator; @@ -696,19 +696,20 @@ public: // clock/timing accessors u32 clock() const { return m_clock; } u32 unscaled_clock() const { return m_unscaled_clock; } - void set_unscaled_clock(u32 clock); - void set_unscaled_clock(const XTAL &xtal) { set_unscaled_clock(xtal.value()); } - void set_unscaled_clock_int(u32 clock) { set_unscaled_clock(clock); } // non-overloaded name because binding to overloads is ugly + void set_unscaled_clock(u32 clock, bool sync_on_new_clock_domain = false); + void set_unscaled_clock(const XTAL &xtal, bool sync_on_new_clock_domain = false) { set_unscaled_clock(xtal.value(), sync_on_new_clock_domain); } + void set_unscaled_clock_int(u32 clock) { set_unscaled_clock(clock, false); } // non-overloaded name because binding to overloads is ugly + void set_unscaled_clock_int_sync(u32 clock) { set_unscaled_clock(clock, true); } // non-overloaded name because binding to overloads is ugly double clock_scale() const { return m_clock_scale; } void set_clock_scale(double clockscale); attotime clocks_to_attotime(u64 clocks) const noexcept; u64 attotime_to_clocks(const attotime &duration) const noexcept; // timer interfaces - emu_timer *timer_alloc(device_timer_id id = 0, void *ptr = nullptr); - void timer_set(const attotime &duration, device_timer_id id = 0, int param = 0, void *ptr = nullptr); - void synchronize(device_timer_id id = 0, int param = 0, void *ptr = nullptr) { timer_set(attotime::zero, id, param, ptr); } - void timer_expired(emu_timer &timer, device_timer_id id, int param, void *ptr) { device_timer(timer, id, param, ptr); } + emu_timer *timer_alloc(device_timer_id id = 0); + void timer_set(const attotime &duration, device_timer_id id = 0, int param = 0); + void synchronize(device_timer_id id = 0, int param = 0) { timer_set(attotime::zero, id, param); } + void timer_expired(emu_timer &timer, device_timer_id id, int param) { device_timer(timer, id, param); } /// \brief Register data for save states /// @@ -834,7 +835,7 @@ protected: void debug_setup(); void pre_save(); void post_load(); - void notify_clock_changed(); + void notify_clock_changed(bool sync_on_new_clock_domain = false); finder_base *register_auto_finder(finder_base &autodev); void register_callback(devcb_base &callback); @@ -976,7 +977,7 @@ protected: virtual void device_clock_changed(); virtual void device_debug_setup(); - virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); + virtual void device_timer(emu_timer &timer, device_timer_id id, int param); //------------------- end derived class overrides @@ -1182,7 +1183,7 @@ public: /// \sa interface_pre_save device_t::device_post_load virtual void interface_post_load() ATTR_COLD; - virtual void interface_clock_changed(); + virtual void interface_clock_changed(bool sync_on_new_clock_domain); virtual void interface_debug_setup(); private: diff --git a/src/emu/diexec.cpp b/src/emu/diexec.cpp index 49dee5f650e..0e9074fe3b2 100644 --- a/src/emu/diexec.cpp +++ b/src/emu/diexec.cpp @@ -164,7 +164,7 @@ void device_execute_interface::spin_until_time(const attotime &duration) suspend_until_trigger(TRIGGER_SUSPENDTIME + timetrig, true); // then set a timer for it - m_scheduler->timer_set(duration, timer_expired_delegate(FUNC(device_execute_interface::timed_trigger_callback),this), TRIGGER_SUSPENDTIME + timetrig, this); + m_scheduler->timer_set(duration, timer_expired_delegate(FUNC(device_execute_interface::timed_trigger_callback),this), TRIGGER_SUSPENDTIME + timetrig); timetrig = (timetrig + 1) % 256; } @@ -475,7 +475,7 @@ void device_execute_interface::interface_post_reset() // information for this device //------------------------------------------------- -void device_execute_interface::interface_clock_changed() +void device_execute_interface::interface_clock_changed(bool sync_on_new_clock_domain) { // a clock of zero disables the device if (device().clock() == 0) @@ -492,6 +492,10 @@ void device_execute_interface::interface_clock_changed() m_cycles_per_second = clocks_to_cycles(device().clock()); m_attoseconds_per_cycle = HZ_TO_ATTOSECONDS(m_cycles_per_second); + // resynchronize the localtime to the clock domain when asked to + if (sync_on_new_clock_domain) + m_localtime = attotime::from_ticks(m_localtime.as_ticks(device().clock())+1, device().clock()); + // update the device's divisor s64 attos = m_attoseconds_per_cycle; m_divshift = 0; @@ -682,7 +686,7 @@ if (TEMPLOG) printf("setline(%s,%d,%d,%d)\n", m_execute->device().tag(), m_linen if (event_index >= std::size(m_queue)) { m_qindex--; - empty_event_queue(nullptr,0); + empty_event_queue(0); event_index = m_qindex++; m_execute->device().logerror("Exceeded pending input line event queue on device '%s'!\n", m_execute->device().tag()); } @@ -696,7 +700,7 @@ if (TEMPLOG) printf("setline(%s,%d,%d,%d)\n", m_execute->device().tag(), m_linen // if this is the first one, set the timer if (event_index == 0) - m_execute->scheduler().synchronize(timer_expired_delegate(FUNC(device_execute_interface::device_input::empty_event_queue),this), 0, this); + m_execute->scheduler().synchronize(timer_expired_delegate(FUNC(device_execute_interface::device_input::empty_event_queue),this)); } } diff --git a/src/emu/diexec.h b/src/emu/diexec.h index 065248a9046..1490c20389d 100644 --- a/src/emu/diexec.h +++ b/src/emu/diexec.h @@ -216,7 +216,7 @@ protected: virtual void interface_post_start() override; virtual void interface_pre_reset() override; virtual void interface_post_reset() override; - virtual void interface_clock_changed() override; + virtual void interface_clock_changed(bool sync_on_new_clock_domain) override; // for use by devcpu for now... int current_input_state(unsigned i) const { return m_input[i].m_curstate; } diff --git a/src/emu/diimage.cpp b/src/emu/diimage.cpp index 031ed46eb30..4e5ca05e002 100644 --- a/src/emu/diimage.cpp +++ b/src/emu/diimage.cpp @@ -11,6 +11,7 @@ #include "emu.h" #include "emuopts.h" +#include "fileio.h" #include "romload.h" #include "softlist.h" #include "softlist_dev.h" @@ -25,35 +26,7 @@ #include <cctype> #include <cstring> #include <regex> - - -//************************************************************************** -// DEVICE CONFIG IMAGE INTERFACE -//************************************************************************** -const image_device_type_info device_image_interface::m_device_info_array[] = - { - { IO_UNKNOWN, "unknown", "unkn" }, /* 0 */ - { IO_CARTSLOT, "cartridge", "cart" }, /* 1 */ - { IO_FLOPPY, "floppydisk", "flop" }, /* 2 */ - { IO_HARDDISK, "harddisk", "hard" }, /* 3 */ - { IO_CYLINDER, "cylinder", "cyln" }, /* 4 */ - { IO_CASSETTE, "cassette", "cass" }, /* 5 */ - { IO_PUNCHCARD, "punchcard", "pcrd" }, /* 6 */ - { IO_PUNCHTAPE, "punchtape", "ptap" }, /* 7 */ - { IO_PRINTER, "printout", "prin" }, /* 8 */ - { IO_SERIAL, "serial", "serl" }, /* 9 */ - { IO_PARALLEL, "parallel", "parl" }, /* 10 */ - { IO_SNAPSHOT, "snapshot", "dump" }, /* 11 */ - { IO_QUICKLOAD, "quickload", "quik" }, /* 12 */ - { IO_MEMCARD, "memcard", "memc" }, /* 13 */ - { IO_CDROM, "cdrom", "cdrm" }, /* 14 */ - { IO_MAGTAPE, "magtape", "magt" }, /* 15 */ - { IO_ROM, "romimage", "rom" }, /* 16 */ - { IO_MIDIIN, "midiin", "min" }, /* 17 */ - { IO_MIDIOUT, "midiout", "mout" }, /* 18 */ - { IO_PICTURE, "picture", "pic" }, /* 19 */ - { IO_VIDEO, "vidfile", "vid" } /* 20 */ - }; +#include <sstream> //************************************************************************** @@ -103,6 +76,7 @@ device_image_interface::device_image_interface(const machine_config &mconfig, de , m_create_format(0) , m_create_args(nullptr) , m_user_loadable(true) + , m_must_be_loaded(false) , m_is_loading(false) , m_is_reset_and_loading(false) { @@ -132,56 +106,6 @@ void device_image_interface::interface_config_complete() //------------------------------------------------- -// find_device_type - search through list of -// device types to extract data -//------------------------------------------------- - -const image_device_type_info *device_image_interface::find_device_type(iodevice_t type) -{ - for (const image_device_type_info &info : m_device_info_array) - { - if (info.m_type == type) - return &info; - } - return nullptr; -} - -//------------------------------------------------- -// device_typename - retrieves device type name -//------------------------------------------------- - -const char *device_image_interface::device_typename(iodevice_t type) -{ - const image_device_type_info *info = find_device_type(type); - return (info != nullptr) ? info->m_name : "unknown"; -} - -//------------------------------------------------- -// device_brieftypename - retrieves device -// brief type name -//------------------------------------------------- - -const char *device_image_interface::device_brieftypename(iodevice_t type) -{ - const image_device_type_info *info = find_device_type(type); - return (info != nullptr) ? info->m_shortname : "unk"; -} - -//------------------------------------------------- -// device_typeid - retrieves device type id -//------------------------------------------------- - -iodevice_t device_image_interface::device_typeid(const char *name) -{ - for (const image_device_type_info &info : m_device_info_array) - { - if (!core_stricmp(name, info.m_name) || !core_stricmp(name, info.m_shortname)) - return info.m_type; - } - return (iodevice_t)-1; -} - -//------------------------------------------------- // set_image_filename - specifies the filename of // an image //------------------------------------------------- @@ -231,10 +155,10 @@ bool device_image_interface::is_filetype(std::string_view candidate_filetype) co // image creation by name //------------------------------------------------- -const image_device_format *device_image_interface::device_get_named_creatable_format(const std::string &format_name) noexcept +const image_device_format *device_image_interface::device_get_named_creatable_format(std::string_view format_name) const noexcept { - for (auto &format : m_formatlist) - if (format->name() == format_name) + for (const auto &format : m_formatlist) + if (std::string_view(format->name()) == format_name) return format.get(); return nullptr; } @@ -266,11 +190,10 @@ void device_image_interface::add_format(std::string &&name, std::string &&descri ****************************************************************************/ //------------------------------------------------- -// image_clear_error - clear out any specified -// error +// clear_error - clear out any specified error //------------------------------------------------- -void device_image_interface::clear_error() +void device_image_interface::clear_error() noexcept { m_err.clear(); m_err_message.clear(); @@ -370,7 +293,7 @@ const software_info *device_image_interface::software_entry() const noexcept // get_software_region //------------------------------------------------- -u8 *device_image_interface::get_software_region(const char *tag) +u8 *device_image_interface::get_software_region(std::string_view tag) { if (!loaded_through_softlist()) return nullptr; @@ -385,7 +308,7 @@ u8 *device_image_interface::get_software_region(const char *tag) // image_get_software_region_length //------------------------------------------------- -u32 device_image_interface::get_software_region_length(const char *tag) +u32 device_image_interface::get_software_region_length(std::string_view tag) { std::string full_tag = util::string_format("%s:%s", device().tag(), tag); memory_region *region = device().machine().root_device().memregion(full_tag); @@ -397,7 +320,7 @@ u32 device_image_interface::get_software_region_length(const char *tag) // image_get_feature //------------------------------------------------- -const char *device_image_interface::get_feature(const char *feature_name) const +const char *device_image_interface::get_feature(std::string_view feature_name) const { return !m_software_part_ptr ? nullptr : m_software_part_ptr->feature(feature_name); } @@ -407,7 +330,7 @@ const char *device_image_interface::get_feature(const char *feature_name) const // load_software_region - //------------------------------------------------- -bool device_image_interface::load_software_region(const char *tag, std::unique_ptr<u8[]> &ptr) +bool device_image_interface::load_software_region(std::string_view tag, std::unique_ptr<u8[]> &ptr) { size_t size = get_software_region_length(tag); @@ -428,43 +351,25 @@ bool device_image_interface::load_software_region(const char *tag, std::unique_p // to be loaded // **************************************************************************** -bool device_image_interface::run_hash(util::core_file &file, u32 skip_bytes, util::hash_collection &hashes, const char *types) +std::error_condition device_image_interface::run_hash(util::random_read &file, u32 skip_bytes, util::hash_collection &hashes, const char *types) { // reset the hash; we want to override existing data hashes.reset(); // figure out the size, and "cap" the skip bytes u64 size; - if (file.length(size)) - return false; + std::error_condition filerr = file.length(size); + if (filerr) + return filerr; skip_bytes = u32(std::min<u64>(skip_bytes, size)); - // seek to the beginning - file.seek(skip_bytes, SEEK_SET); // TODO: check error return - u64 position = skip_bytes; - - // keep on reading hashes - hashes.begin(types); - while (position < size) - { - uint8_t buffer[8192]; - - // read bytes - const size_t count = size_t(std::min<u64>(size - position, sizeof(buffer))); - size_t actual_count; - const std::error_condition filerr = file.read(buffer, count, actual_count); - if (filerr || !actual_count) - return false; - position += actual_count; - - // and compute the hashes - hashes.buffer(buffer, actual_count); - } - hashes.end(); + // and compute the hashes + size_t actual_count; + filerr = hashes.compute(file, skip_bytes, size - skip_bytes, actual_count, types); + if (filerr) + return filerr; - // cleanup - file.seek(0, SEEK_SET); // TODO: check error return - return true; + return std::error_condition(); } @@ -477,7 +382,7 @@ bool device_image_interface::image_checkhash() { // do not cause a linear read of 600 megs please // TODO: use SHA1 in the CHD header as the hash - if (image_type() == IO_CDROM) + if (image_is_chd_type()) return true; // Skip calculating the hash when we have an image mounted through a software list @@ -485,18 +390,18 @@ bool device_image_interface::image_checkhash() return true; // run the hash - if (!run_hash(*m_file, unhashed_header_length(), m_hash, util::hash_collection::HASH_TYPES_ALL)) + if (run_hash(*m_file, unhashed_header_length(), m_hash, util::hash_collection::HASH_TYPES_ALL)) return false; } return true; } -util::hash_collection device_image_interface::calculate_hash_on_file(util::core_file &file) const +util::hash_collection device_image_interface::calculate_hash_on_file(util::random_read &file) const { // calculate the hash util::hash_collection hash; - if (!run_hash(file, unhashed_header_length(), hash, util::hash_collection::HASH_TYPES_ALL)) + if (run_hash(file, unhashed_header_length(), hash, util::hash_collection::HASH_TYPES_ALL)) hash.reset(); return hash; } @@ -514,33 +419,6 @@ u32 device_image_interface::crc() } -//------------------------------------------------- -// support_command_line_image_creation - do we -// want to support image creation from the front -// end command line? -//------------------------------------------------- - -bool device_image_interface::support_command_line_image_creation() const noexcept -{ - bool result; - switch (image_type()) - { - case IO_PRINTER: - case IO_SERIAL: - case IO_PARALLEL: - // going by the assumption that these device image types should support this - // behavior; ideally we'd get rid of IO_* and just push this to the specific - // devices - result = true; - break; - default: - result = false; - break; - } - return result; -} - - // **************************************************************************** // Battery functions // @@ -619,34 +497,6 @@ void device_image_interface::battery_save(const void *buffer, int length) } -//------------------------------------------------- -// uses_file_extension - update configuration -// based on completed device setup -//------------------------------------------------- - -bool device_image_interface::uses_file_extension(const char *file_extension) const -{ - bool result = false; - - if (file_extension[0] == '.') - file_extension++; - - /* find the extensions */ - std::string extensions(file_extensions()); - char *ext = strtok((char*)extensions.c_str(),","); - while (ext != nullptr) - { - if (!core_stricmp(ext, file_extension)) - { - result = true; - break; - } - ext = strtok (nullptr, ","); - } - return result; -} - - // *************************************************************************** // IMAGE LOADING // *************************************************************************** @@ -816,7 +666,24 @@ bool device_image_interface::load_software(software_list_device &swlist, std::st else filerr = m_mame_file->open(romp->name()); if (filerr) + { m_mame_file.reset(); + std::ostringstream msg; + util::stream_format(msg, + "%s: error opening image file %s: %s (%s:%d)", + device().tag(), romp->name(), + filerr.message(), + filerr.category().name(), + filerr.value()); + if (!searchpath.empty()) + { + msg << " (tried in"; + for (auto const &path : searchpath) + msg << ' ' << path; + msg << ')'; + } + osd_printf_error("%s\n", std::move(msg).str()); + } warningcount += verify_length_and_hash(m_mame_file.get(), romp->name(), romp->get_length(), util::hash_collection(romp->hashdata())); @@ -1137,12 +1004,10 @@ const util::option_guide &device_image_interface::create_option_guide() const void device_image_interface::update_names() { - const char *inst_name = custom_instance_name(); - const char *brief_name = custom_brief_instance_name(); - if (inst_name == nullptr) - inst_name = device_typename(image_type()); - if (brief_name == nullptr) - brief_name = device_brieftypename(image_type()); + const char *inst_name = image_type_name(); + const char *brief_name = image_brief_type_name(); + assert(inst_name != nullptr); + assert(brief_name != nullptr); // count instances of the general image type, or device type if custom int count = 0; @@ -1151,19 +1016,21 @@ void device_image_interface::update_names() { if (this == &image) index = count; - const char *other_name = image.custom_instance_name(); - if (!other_name) - other_name = device_typename(image.image_type()); + const char *other_name = image.image_type_name(); + const char *other_brief_name = image.image_brief_type_name(); + assert(other_name != nullptr); + assert(other_brief_name != nullptr); - if (other_name == inst_name || !strcmp(other_name, inst_name)) + if (other_name == inst_name || !strcmp(other_name, inst_name) || + other_brief_name == brief_name || !strcmp(other_brief_name, brief_name)) count++; } - m_canonical_instance_name = string_format("%s%d", inst_name, index + 1); + m_canonical_instance_name = util::string_format("%s%d", inst_name, index + 1); if (count > 1) { m_instance_name = m_canonical_instance_name; - m_brief_instance_name = string_format("%s%d", brief_name, index + 1); + m_brief_instance_name = util::string_format("%s%d", brief_name, index + 1); } else { diff --git a/src/emu/diimage.h b/src/emu/diimage.h index 67d20c43402..08d48020cc3 100644 --- a/src/emu/diimage.h +++ b/src/emu/diimage.h @@ -29,33 +29,6 @@ // TYPE DEFINITIONS //************************************************************************** -enum iodevice_t -{ - /* List of all supported devices. Refer to the device by these names only */ - IO_UNKNOWN, - IO_CARTSLOT, /* 1 - Cartridge Port, as found on most console and on some computers */ - IO_FLOPPY, /* 2 - Floppy Disk unit */ - IO_HARDDISK, /* 3 - Hard Disk unit */ - IO_CYLINDER, /* 4 - Magnetically-Coated Cylinder */ - IO_CASSETTE, /* 5 - Cassette Recorder (common on early home computers) */ - IO_PUNCHCARD, /* 6 - Card Puncher/Reader */ - IO_PUNCHTAPE, /* 7 - Tape Puncher/Reader (reels instead of punchcards) */ - IO_PRINTER, /* 8 - Printer device */ - IO_SERIAL, /* 9 - Generic Serial Port */ - IO_PARALLEL, /* 10 - Generic Parallel Port */ - IO_SNAPSHOT, /* 11 - Complete 'snapshot' of the state of the computer */ - IO_QUICKLOAD, /* 12 - Allow to load program/data into memory, without matching any actual device */ - IO_MEMCARD, /* 13 - Memory card */ - IO_CDROM, /* 14 - optical CD-ROM disc */ - IO_MAGTAPE, /* 15 - Magnetic tape */ - IO_ROM, /* 16 - Individual ROM image - the Amstrad CPC has a few applications that were sold on 16kB ROMs */ - IO_MIDIIN, /* 17 - MIDI In port */ - IO_MIDIOUT, /* 18 - MIDI Out port */ - IO_PICTURE, /* 19 - A single-frame image */ - IO_VIDEO, /* 20 - A video file */ - IO_COUNT /* 21 - Total Number of IO_devices for searching */ -}; - enum class image_error : int { INTERNAL = 1, @@ -69,13 +42,6 @@ const std::error_category &image_category() noexcept; inline std::error_condition make_error_condition(image_error e) noexcept { return std::error_condition(int(e), image_category()); } namespace std { template <> struct is_error_condition_enum<image_error> : public std::true_type { }; } -struct image_device_type_info -{ - iodevice_t m_type; - const char *m_name; - const char *m_shortname; -}; - class image_device_format { public: @@ -124,35 +90,30 @@ public: device_image_interface(const machine_config &mconfig, device_t &device); virtual ~device_image_interface(); - static const char *device_typename(iodevice_t type); - static const char *device_brieftypename(iodevice_t type); - static iodevice_t device_typeid(const char *name); - virtual image_init_result call_load() { return image_init_result::PASS; } virtual image_init_result call_create(int format_type, util::option_resolution *format_options) { return image_init_result::PASS; } virtual void call_unload() { } virtual std::string call_display() { return std::string(); } virtual u32 unhashed_header_length() const noexcept { return 0; } virtual bool core_opens_image_file() const noexcept { return true; } - virtual iodevice_t image_type() const noexcept = 0; + virtual bool image_is_chd_type() const noexcept { return false; } virtual bool is_readable() const noexcept = 0; virtual bool is_writeable() const noexcept = 0; virtual bool is_creatable() const noexcept = 0; - virtual bool must_be_loaded() const noexcept = 0; virtual bool is_reset_on_load() const noexcept = 0; - virtual bool support_command_line_image_creation() const noexcept; + virtual bool support_command_line_image_creation() const noexcept { return false; } virtual const char *image_interface() const noexcept { return nullptr; } virtual const char *file_extensions() const noexcept = 0; virtual const util::option_guide &create_option_guide() const; - virtual const char *custom_instance_name() const noexcept { return nullptr; } - virtual const char *custom_brief_instance_name() const noexcept { return nullptr; } + virtual const char *image_type_name() const noexcept = 0; + virtual const char *image_brief_type_name() const noexcept = 0; const image_device_format *device_get_indexed_creatable_format(int index) const noexcept { return (index < m_formatlist.size()) ? m_formatlist.at(index).get() : nullptr; } - const image_device_format *device_get_named_creatable_format(const std::string &format_name) noexcept; + const image_device_format *device_get_named_creatable_format(std::string_view format_name) const noexcept; const util::option_guide &device_get_creation_option_guide() const { return create_option_guide(); } std::string_view error(); - void seterror(std::error_condition err, const char *message); + void seterror(std::error_condition err, const char *message = nullptr); void message(const char *format, ...) ATTR_PRINTF(2,3); bool exists() const noexcept { return !m_image_name.empty(); } @@ -165,7 +126,7 @@ public: bool is_filetype(std::string_view candidate_filetype) const; bool is_open() const noexcept { return bool(m_file); } - util::core_file &image_core_file() const noexcept { return *m_file; } + util::core_file &image_core_file() const noexcept { assert(is_open()); return *m_file; } bool is_readonly() const noexcept { return m_readonly; } // image file I/O wrappers @@ -204,28 +165,11 @@ public: m_file->tell(result); return result; } - int fgetc() - { - char ch; - if (fread(&ch, 1) != 1) - ch = '\0'; - return ch; - } - char *fgets(char *buffer, u32 length) - { - check_for_file(); - return m_file->gets(buffer, length); - } bool image_feof() { check_for_file(); return m_file->eof(); } - const void *ptr() - { - check_for_file(); - return m_file->buffer(); - } // allocate and read into buffers u32 fread(std::unique_ptr<u8 []> &ptr, u32 length) { ptr = std::make_unique<u8 []>(length); return fread(ptr.get(), length); } @@ -243,25 +187,22 @@ public: const std::string &working_directory() const { return m_working_directory; } // access to software list properties and ROM data areas - u8 *get_software_region(const char *tag); - u32 get_software_region_length(const char *tag); - const char *get_feature(const char *feature_name) const; - bool load_software_region(const char *tag, std::unique_ptr<u8[]> &ptr); + u8 *get_software_region(std::string_view tag); + u32 get_software_region_length(std::string_view tag); + const char *get_feature(std::string_view feature_name) const; + bool load_software_region(std::string_view tag, std::unique_ptr<u8[]> &ptr); u32 crc(); util::hash_collection& hash() { return m_hash; } - util::hash_collection calculate_hash_on_file(util::core_file &file) const; + util::hash_collection calculate_hash_on_file(util::random_read &file) const; void battery_load(void *buffer, int length, int fill); void battery_load(void *buffer, int length, const void *def_buffer); void battery_save(const void *buffer, int length); - const char *image_type_name() const { return device_typename(image_type()); } - const std::string &instance_name() const { return m_instance_name; } const std::string &brief_instance_name() const { return m_brief_instance_name; } const std::string &canonical_instance_name() const { return m_canonical_instance_name; } - bool uses_file_extension(const char *file_extension) const; const formatlist_type &formatlist() const { return m_formatlist; } // loads an image file @@ -277,9 +218,11 @@ public: bool load_software(software_list_device &swlist, std::string_view swname, const rom_entry *entry); std::error_condition reopen_for_write(std::string_view path); - void set_user_loadable(bool user_loadable) { m_user_loadable = user_loadable; } + void set_user_loadable(bool user_loadable) noexcept { m_user_loadable = user_loadable; } + void set_must_be_loaded(bool must_be_loaded) noexcept { m_must_be_loaded = must_be_loaded; } bool user_loadable() const noexcept { return m_user_loadable; } + bool must_be_loaded() const noexcept { return m_must_be_loaded; } bool is_reset_and_loading() const noexcept { return m_is_reset_and_loading; } const std::string &full_software_name() const noexcept { return m_full_software_name; } @@ -297,7 +240,7 @@ protected: void set_image_filename(std::string_view filename); - void clear_error(); + void clear_error() noexcept; void check_for_file() const { if (!m_file) throw emu_fatalerror("%s(%s): Illegal operation on unmounted image", device().shortname(), device().tag()); } @@ -311,12 +254,6 @@ protected: void add_format(std::unique_ptr<image_device_format> &&format); void add_format(std::string &&name, std::string &&description, std::string &&extensions, std::string &&optspec); - // derived class overrides - - // configuration - static const image_device_type_info *find_device_type(iodevice_t type); - static const image_device_type_info m_device_info_array[]; - // error related info std::error_condition m_err; std::string m_err_message; @@ -340,7 +277,7 @@ private: bool load_software_part(std::string_view identifier); bool init_phase() const; - static bool run_hash(util::core_file &file, u32 skip_bytes, util::hash_collection &hashes, const char *types); + static std::error_condition run_hash(util::random_read &file, u32 skip_bytes, util::hash_collection &hashes, const char *types); // loads an image or software items and resets - called internally when we // load an is_reset_on_load() item @@ -370,6 +307,8 @@ private: // we want to disable command line cart loading... bool m_user_loadable; + bool m_must_be_loaded; + bool m_is_loading; bool m_is_reset_and_loading; diff --git a/src/emu/dinetwork.cpp b/src/emu/dinetwork.cpp index 69cc7e9235f..3ad9f4c925b 100644 --- a/src/emu/dinetwork.cpp +++ b/src/emu/dinetwork.cpp @@ -3,11 +3,13 @@ #include "emu.h" #include "osdnet.h" -device_network_interface::device_network_interface(const machine_config &mconfig, device_t &device, float bandwidth) +device_network_interface::device_network_interface(const machine_config &mconfig, device_t &device, u32 bandwidth, u32 mtu) : device_interface(device, "network") { m_promisc = false; - m_bandwidth = bandwidth; + // Convert to Mibps to Bps + m_bandwidth = bandwidth << (20 - 3); + m_mtu = mtu; set_mac("\0\0\0\0\0\0"); m_intf = -1; m_loopback_control = false; @@ -44,7 +46,7 @@ int device_network_interface::send(u8 *buf, int len, int fcs) if (result) { // schedule receive complete callback - m_recv_timer->adjust(attotime::from_ticks(len, m_bandwidth * 1'000'000 / 8), result); + m_recv_timer->adjust(attotime::from_ticks(len, m_bandwidth), result); } } else if (m_dev) @@ -56,7 +58,7 @@ int device_network_interface::send(u8 *buf, int len, int fcs) } // schedule transmit complete callback - m_send_timer->adjust(attotime::from_ticks(len, m_bandwidth * 1'000'000 / 8), result); + m_send_timer->adjust(attotime::from_ticks(len, m_bandwidth), result); return result; } @@ -84,7 +86,7 @@ void device_network_interface::recv_cb(u8 *buf, int len) m_dev->stop(); // schedule receive complete callback - m_recv_timer->adjust(attotime::from_ticks(len, m_bandwidth * 1'000'000 / 8), result); + m_recv_timer->adjust(attotime::from_ticks(len, m_bandwidth), result); } } @@ -113,7 +115,8 @@ void device_network_interface::set_interface(int id) { if(m_dev) m_dev->stop(); - m_dev.reset(open_netdev(id, this, (int)(m_bandwidth*1000000/8.0f/1500))); + // Set device polling time to transfer time for one mtu + m_dev.reset(open_netdev(id, this, (int)(m_bandwidth / m_mtu))); if(!m_dev) { device().logerror("Network interface %d not found\n", id); id = -1; diff --git a/src/emu/dinetwork.h b/src/emu/dinetwork.h index 99909e93905..c2629f665fc 100644 --- a/src/emu/dinetwork.h +++ b/src/emu/dinetwork.h @@ -8,7 +8,7 @@ class osd_netdev; class device_network_interface : public device_interface { public: - device_network_interface(const machine_config &mconfig, device_t &device, float bandwidth); + device_network_interface(const machine_config &mconfig, device_t &device, u32 bandwidth, u32 mtu = 1500); virtual ~device_network_interface(); void interface_pre_start() override; @@ -39,7 +39,10 @@ protected: bool m_promisc; char m_mac[6]; - float m_bandwidth; + // bandwidth in bytes per second + u32 m_bandwidth; + // maximum transmission unit, used for device polling time + u32 m_mtu; std::unique_ptr<osd_netdev> m_dev; int m_intf; bool m_loopback_control; diff --git a/src/emu/dinvram.h b/src/emu/dinvram.h index fb02a9c6e14..0549e183c6a 100644 --- a/src/emu/dinvram.h +++ b/src/emu/dinvram.h @@ -35,15 +35,15 @@ public: // public accessors... for now void nvram_reset() { nvram_default(); } - void nvram_load(emu_file &file) { nvram_read(file); } - void nvram_save(emu_file &file) { nvram_write(file); } + bool nvram_load(util::read_stream &file) { return nvram_read(file); } + bool nvram_save(util::write_stream &file) { return nvram_write(file); } bool nvram_can_save() { return nvram_can_write(); } protected: // derived class overrides virtual void nvram_default() = 0; - virtual void nvram_read(emu_file &file) = 0; - virtual void nvram_write(emu_file &file) = 0; + virtual bool nvram_read(util::read_stream &file) = 0; + virtual bool nvram_write(util::write_stream &file) = 0; virtual bool nvram_can_write() { return true; } }; diff --git a/src/emu/dislot.cpp b/src/emu/dislot.cpp index e30cd41d46f..6f7bb4b592f 100644 --- a/src/emu/dislot.cpp +++ b/src/emu/dislot.cpp @@ -72,6 +72,42 @@ device_slot_interface::slot_option &device_slot_interface::option_add_internal(c } +device_slot_interface::slot_option &device_slot_interface::option_replace(const char *name, const device_type &devtype) +{ + if (!name || !*name) + throw emu_fatalerror("slot '%s' attempt to replace option without name\n", device().tag()); + + auto search = m_options.find(name); + if (search == m_options.end()) + throw emu_fatalerror("slot '%s' attempt to replace nonexistent option '%s'\n", device().tag(), name); + + return (search->second = std::make_unique<slot_option>(name, devtype, true))->clock(m_default_clock); +} + + +device_slot_interface::slot_option &device_slot_interface::option_replace_internal(const char *name, const device_type &devtype) +{ + if (!name || !*name) + throw emu_fatalerror("slot '%s' attempt to replace option without name\n", device().tag()); + + auto search = m_options.find(name); + if (search == m_options.end()) + throw emu_fatalerror("slot '%s' attempt to replace nonexistent option '%s'\n", device().tag(), name); + + return (search->second = std::make_unique<slot_option>(name, devtype, false))->clock(m_default_clock); +} + + +void device_slot_interface::option_remove(const char *name) +{ + if (!name || !*name) + throw emu_fatalerror("slot '%s' attempt to remove option without name\n", device().tag()); + + if (m_options.erase(name) == 0) + throw emu_fatalerror("slot '%s' attempt to remove nonexistent option '%s'\n", device().tag(), name); +} + + device_slot_interface::slot_option *device_slot_interface::config_option(const char *name) { auto const search = m_options.find(name); diff --git a/src/emu/dislot.h b/src/emu/dislot.h index 97d314028a2..dd2fde5fac1 100644 --- a/src/emu/dislot.h +++ b/src/emu/dislot.h @@ -132,6 +132,10 @@ public: /// configuration. slot_option &option_add_internal(const char *option, const device_type &devtype); + slot_option &option_replace(const char *option, const device_type &devtype); + slot_option &option_replace_internal(const char *option, const device_type &devtype); + void option_remove(const char *option); + void set_option_default_bios(const char *option, const char *default_bios) { config_option(option)->default_bios(default_bios); } template <typename T> void set_option_machine_config(const char *option, T &&machine_config) { config_option(option)->machine_config(std::forward<T>(machine_config)); } void set_option_device_input_defaults(const char *option, const input_device_default *default_input) { config_option(option)->input_device_defaults(default_input); } diff --git a/src/emu/drivers/empty.cpp b/src/emu/drivers/empty.cpp index 23cf5443013..6b60367403b 100644 --- a/src/emu/drivers/empty.cpp +++ b/src/emu/drivers/empty.cpp @@ -10,7 +10,7 @@ #include "emu.h" #include "emuopts.h" -#include "render.h" +#include "screen.h" //************************************************************************** // DRIVER STATE diff --git a/src/emu/drivers/testcpu.cpp b/src/emu/drivers/testcpu.cpp index 574e6fc88b3..1cdb945db88 100644 --- a/src/emu/drivers/testcpu.cpp +++ b/src/emu/drivers/testcpu.cpp @@ -38,7 +38,7 @@ public: } // timer callback; used to wrest control of the system - virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override + virtual void device_timer(emu_timer &timer, device_timer_id id, int param) override { static const u32 sample_instructions[] = { diff --git a/src/emu/emu.h b/src/emu/emu.h index d648ee932de..f4fa0c21888 100644 --- a/src/emu/emu.h +++ b/src/emu/emu.h @@ -18,6 +18,9 @@ #ifndef __EMU_H__ #define __EMU_H__ +// get forward declarations before anything else +#include "emufwd.h" + #include <list> #include <forward_list> #include <vector> @@ -34,17 +37,13 @@ #include "attotime.h" #include "profiler.h" -// http interface helpers -#include "http.h" - // commonly-referenced utilities imported from lib/util -#include "corealloc.h" +#include "corefile.h" +#include "delegate.h" +#include "hash.h" #include "palette.h" // emulator-specific utilities -#include "hash.h" -#include "fileio.h" -#include "delegate.h" #include "devdelegate.h" // memory and address spaces diff --git a/src/emu/emucore.h b/src/emu/emucore.h index 768fa8c7280..8074fb0fe73 100644 --- a/src/emu/emucore.h +++ b/src/emu/emucore.h @@ -13,35 +13,38 @@ #pragma once -// standard C includes -#include <cassert> -#include <cmath> -#include <cstdio> -#include <cstring> -#include <cstdlib> -#include <cstdarg> - // some cleanups for Solaris for things defined in stdlib.h #if defined(__sun__) && defined(__svr4__) #undef si_status #undef WWORD #endif -// standard C++ includes -#include <exception> -#include <string> -#include <type_traits> -#include <typeinfo> +// centralised forward declarations +#include "emufwd.h" -// core system includes -#include "osdcomm.h" +// common stuff from lib/util +#include "corealloc.h" #include "coretmpl.h" #include "bitmap.h" #include "endianness.h" #include "strformat.h" #include "vecstream.h" -#include "emufwd.h" +// common stuff from osd +#include "osdcomm.h" + +// standard C++ includes +#include <exception> +#include <string> +#include <type_traits> +#include <typeinfo> + +// standard C includes +#include <cassert> +#include <cmath> +#include <cstdio> +#include <cstdlib> +#include <cstring> //************************************************************************** @@ -421,4 +424,11 @@ inline u64 d2u(double d) return u.vv; } + +//************************************************************************** +// USEFUL UTILITIES +//************************************************************************** + +using util::make_unique_clear; + #endif // MAME_EMU_EMUCORE_H diff --git a/src/emu/emufwd.h b/src/emu/emufwd.h index 8b8e59b9250..6d0528015c4 100644 --- a/src/emu/emufwd.h +++ b/src/emu/emufwd.h @@ -152,6 +152,12 @@ class memory_view; // declared in emuopts.h class emu_options; +// declared in fileio.h +class emu_file; + +// declared in http.h +class http_manager; + // declared in gamedrv.h class game_driver; diff --git a/src/emu/emumem.cpp b/src/emu/emumem.cpp index 3982debf2cc..b08657c9087 100644 --- a/src/emu/emumem.cpp +++ b/src/emu/emumem.cpp @@ -865,62 +865,62 @@ void address_space_installer::populate_map_entry(const address_map_entry &entry, -memory_passthrough_handler *address_space_installer::install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tap, memory_passthrough_handler *mph) +memory_passthrough_handler address_space_installer::install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tap, memory_passthrough_handler *mph) { fatalerror("Trying to install a 8-bits wide bus read tap in a %d-bits wide bus\n", data_width()); } -memory_passthrough_handler *address_space_installer::install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tap, memory_passthrough_handler *mph) +memory_passthrough_handler address_space_installer::install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tap, memory_passthrough_handler *mph) { fatalerror("Trying to install a 16-bits wide bus read tap in a %d-bits wide bus\n", data_width()); } -memory_passthrough_handler *address_space_installer::install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tap, memory_passthrough_handler *mph) +memory_passthrough_handler address_space_installer::install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tap, memory_passthrough_handler *mph) { fatalerror("Trying to install a 32-bits wide bus read tap in a %d-bits wide bus\n", data_width()); } -memory_passthrough_handler *address_space_installer::install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tap, memory_passthrough_handler *mph) +memory_passthrough_handler address_space_installer::install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tap, memory_passthrough_handler *mph) { fatalerror("Trying to install a 64-bits wide bus read tap in a %d-bits wide bus\n", data_width()); } -memory_passthrough_handler *address_space_installer::install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tap, memory_passthrough_handler *mph) +memory_passthrough_handler address_space_installer::install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tap, memory_passthrough_handler *mph) { fatalerror("Trying to install a 8-bits wide bus write tap in a %d-bits wide bus\n", data_width()); } -memory_passthrough_handler *address_space_installer::install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tap, memory_passthrough_handler *mph) +memory_passthrough_handler address_space_installer::install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tap, memory_passthrough_handler *mph) { fatalerror("Trying to install a 16-bits wide bus write tap in a %d-bits wide bus\n", data_width()); } -memory_passthrough_handler *address_space_installer::install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tap, memory_passthrough_handler *mph) +memory_passthrough_handler address_space_installer::install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tap, memory_passthrough_handler *mph) { fatalerror("Trying to install a 32-bits wide bus write tap in a %d-bits wide bus\n", data_width()); } -memory_passthrough_handler *address_space_installer::install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tap, memory_passthrough_handler *mph) +memory_passthrough_handler address_space_installer::install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tap, memory_passthrough_handler *mph) { fatalerror("Trying to install a 64-bits wide bus write tap in a %d-bits wide bus\n", data_width()); } -memory_passthrough_handler *address_space_installer::install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tapr, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tapw, memory_passthrough_handler *mph) +memory_passthrough_handler address_space_installer::install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tapr, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tapw, memory_passthrough_handler *mph) { fatalerror("Trying to install a 8-bits wide bus read/write tap in a %d-bits wide bus\n", data_width()); } -memory_passthrough_handler *address_space_installer::install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tapr, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tapw, memory_passthrough_handler *mph) +memory_passthrough_handler address_space_installer::install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tapr, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tapw, memory_passthrough_handler *mph) { fatalerror("Trying to install a 16-bits wide bus read/write tap in a %d-bits wide bus\n", data_width()); } -memory_passthrough_handler *address_space_installer::install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tapr, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tap, memory_passthrough_handler *mph) +memory_passthrough_handler address_space_installer::install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tapr, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tap, memory_passthrough_handler *mph) { fatalerror("Tryingw to install a 32-bits wide bus read/write tap in a %d-bits wide bus\n", data_width()); } -memory_passthrough_handler *address_space_installer::install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tapr, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tapw, memory_passthrough_handler *mph) +memory_passthrough_handler address_space_installer::install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tapr, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tapw, memory_passthrough_handler *mph) { fatalerror("Trying to install a 64-bits wide bus read/write tap in a %d-bits wide bus\n", data_width()); } diff --git a/src/emu/emumem.h b/src/emu/emumem.h index 3d4d664469e..c805de6155c 100644 --- a/src/emu/emumem.h +++ b/src/emu/emumem.h @@ -17,6 +17,8 @@ #ifndef MAME_EMU_EMUMEM_H #define MAME_EMU_EMUMEM_H +#include "notifier.h" + #include <optional> #include <set> #include <type_traits> @@ -50,6 +52,14 @@ enum class read_or_write }; +//************************************************************************** +// FORWARD DECLARATIONS +//************************************************************************** + +class handler_entry; +template<int Width, int AddrShift> class handler_entry_read_passthrough; +template<int Width, int AddrShift> class handler_entry_write_passthrough; + //************************************************************************** // TYPE DEFINITIONS @@ -90,7 +100,7 @@ struct memory_entry_context { struct memory_entry { offs_t start, end; - class handler_entry *entry; + handler_entry *entry; std::vector<memory_entry_context> context; }; @@ -465,6 +475,29 @@ constexpr int handler_entry_dispatch_lowbits(int highbits, int width, int ashift width + ashift; } + +// =====================-> Passthrough handler management structure + +class memory_passthrough_handler_impl +{ +public: + memory_passthrough_handler_impl(address_space &space) : m_space(space) {} + memory_passthrough_handler_impl(memory_passthrough_handler_impl const &) = delete; + + void remove(); + +private: + address_space &m_space; + std::unordered_set<handler_entry *> m_handlers; + + void add_handler(handler_entry *handler) { m_handlers.insert(handler); } + void remove_handler(handler_entry *handler) { m_handlers.erase(m_handlers.find(handler)); } + + friend address_space; + template<int Width, int AddrShift> friend class ::handler_entry_read_passthrough; + template<int Width, int AddrShift> friend class ::handler_entry_write_passthrough; +}; + } // namespace emu::detail @@ -561,8 +594,6 @@ protected: // Provides the populate/read/get_ptr/lookup API -template<int Width, int AddrShift> class handler_entry_read_passthrough; - template<int Width, int AddrShift> class handler_entry_read : public handler_entry { public: @@ -596,7 +627,7 @@ public: virtual void populate_nomirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, handler_entry_read<Width, AddrShift> *handler); virtual void populate_mirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, offs_t mirror, handler_entry_read<Width, AddrShift> *handler); - inline void populate_mismatched(offs_t start, offs_t end, offs_t mirror, const memory_units_descriptor<Width, AddrShift> &descriptor) { + void populate_mismatched(offs_t start, offs_t end, offs_t mirror, const memory_units_descriptor<Width, AddrShift> &descriptor) { start &= ~NATIVE_MASK; end |= NATIVE_MASK; std::vector<mapping> mappings; @@ -609,7 +640,7 @@ public: virtual void populate_mismatched_nomirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, const memory_units_descriptor<Width, AddrShift> &descriptor, u8 rkey, std::vector<mapping> &mappings); virtual void populate_mismatched_mirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, offs_t mirror, const memory_units_descriptor<Width, AddrShift> &descriptor, std::vector<mapping> &mappings); - inline void populate_passthrough(offs_t start, offs_t end, offs_t mirror, handler_entry_read_passthrough<Width, AddrShift> *handler) { + void populate_passthrough(offs_t start, offs_t end, offs_t mirror, handler_entry_read_passthrough<Width, AddrShift> *handler) { start &= ~NATIVE_MASK; end |= NATIVE_MASK; std::vector<mapping> mappings; @@ -636,8 +667,6 @@ public: // Provides the populate/write/get_ptr/lookup API -template<int Width, int AddrShift> class handler_entry_write_passthrough; - template<int Width, int AddrShift> class handler_entry_write : public handler_entry { public: @@ -711,20 +740,21 @@ public: // =====================-> Passthrough handler management structure class memory_passthrough_handler { - template<int Width, int AddrShift> friend class handler_entry_read_passthrough; - template<int Width, int AddrShift> friend class handler_entry_write_passthrough; - public: - memory_passthrough_handler(address_space &space) : m_space(space) {} + memory_passthrough_handler() : m_impl() {} + memory_passthrough_handler(std::shared_ptr<emu::detail::memory_passthrough_handler_impl> const &impl) : m_impl(impl) {} - inline void remove(); + void remove() + { + auto impl(m_impl.lock()); + if (impl) + impl->remove(); + } private: - address_space &m_space; - std::unordered_set<handler_entry *> m_handlers; + std::weak_ptr<emu::detail::memory_passthrough_handler_impl> m_impl; - void add_handler(handler_entry *handler) { m_handlers.insert(handler); } - void remove_handler(handler_entry *handler) { m_handlers.erase(m_handlers.find(handler)); } + friend class address_space; }; // =====================-> Forward declaration for address_space @@ -1543,6 +1573,8 @@ private: handler_entry_read <Width, AddrShift> *m_root_read; // decode tree roots handler_entry_write<Width, AddrShift> *m_root_write; + util::notifier_subscription m_subscription; + NativeType read_native(offs_t address, NativeType mask = ~NativeType(0)); void write_native(offs_t address, NativeType data, NativeType mask = ~NativeType(0)); std::pair<NativeType, u16> read_native_flags(offs_t address, NativeType mask = ~NativeType(0)); @@ -1687,32 +1719,32 @@ public: virtual void install_device_delegate(offs_t addrstart, offs_t addrend, device_t &device, address_map_constructor &map, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; // install taps without mirroring - memory_passthrough_handler *install_read_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_read_tap(addrstart, addrend, 0, name, tap, mph); } - memory_passthrough_handler *install_read_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_read_tap(addrstart, addrend, 0, name, tap, mph); } - memory_passthrough_handler *install_read_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_read_tap(addrstart, addrend, 0, name, tap, mph); } - memory_passthrough_handler *install_read_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_read_tap(addrstart, addrend, 0, name, tap, mph); } - memory_passthrough_handler *install_write_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_write_tap(addrstart, addrend, 0, name, tap, mph); } - memory_passthrough_handler *install_write_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_write_tap(addrstart, addrend, 0, name, tap, mph); } - memory_passthrough_handler *install_write_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_write_tap(addrstart, addrend, 0, name, tap, mph); } - memory_passthrough_handler *install_write_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_write_tap(addrstart, addrend, 0, name, tap, mph); } - memory_passthrough_handler *install_readwrite_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tapr, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr) { return install_readwrite_tap(addrstart, addrend, 0, name, tapr, tapw, mph); } - memory_passthrough_handler *install_readwrite_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tapr, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr) { return install_readwrite_tap(addrstart, addrend, 0, name, tapr, tapw, mph); } - memory_passthrough_handler *install_readwrite_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tapr, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr) { return install_readwrite_tap(addrstart, addrend, 0, name, tapr, tapw, mph); } - memory_passthrough_handler *install_readwrite_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tapr, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr) { return install_readwrite_tap(addrstart, addrend, 0, name, tapr, tapw, mph); } + memory_passthrough_handler install_read_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_read_tap(addrstart, addrend, 0, name, tap, mph); } + memory_passthrough_handler install_read_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_read_tap(addrstart, addrend, 0, name, tap, mph); } + memory_passthrough_handler install_read_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_read_tap(addrstart, addrend, 0, name, tap, mph); } + memory_passthrough_handler install_read_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_read_tap(addrstart, addrend, 0, name, tap, mph); } + memory_passthrough_handler install_write_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_write_tap(addrstart, addrend, 0, name, tap, mph); } + memory_passthrough_handler install_write_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_write_tap(addrstart, addrend, 0, name, tap, mph); } + memory_passthrough_handler install_write_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_write_tap(addrstart, addrend, 0, name, tap, mph); } + memory_passthrough_handler install_write_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_write_tap(addrstart, addrend, 0, name, tap, mph); } + memory_passthrough_handler install_readwrite_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tapr, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr) { return install_readwrite_tap(addrstart, addrend, 0, name, tapr, tapw, mph); } + memory_passthrough_handler install_readwrite_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tapr, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr) { return install_readwrite_tap(addrstart, addrend, 0, name, tapr, tapw, mph); } + memory_passthrough_handler install_readwrite_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tapr, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr) { return install_readwrite_tap(addrstart, addrend, 0, name, tapr, tapw, mph); } + memory_passthrough_handler install_readwrite_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tapr, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr) { return install_readwrite_tap(addrstart, addrend, 0, name, tapr, tapw, mph); } // install taps with mirroring - virtual memory_passthrough_handler *install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tap, memory_passthrough_handler *mph = nullptr); - virtual memory_passthrough_handler *install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tap, memory_passthrough_handler *mph = nullptr); - virtual memory_passthrough_handler *install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tap, memory_passthrough_handler *mph = nullptr); - virtual memory_passthrough_handler *install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tap, memory_passthrough_handler *mph = nullptr); - virtual memory_passthrough_handler *install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tap, memory_passthrough_handler *mph = nullptr); - virtual memory_passthrough_handler *install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tap, memory_passthrough_handler *mph = nullptr); - virtual memory_passthrough_handler *install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tap, memory_passthrough_handler *mph = nullptr); - virtual memory_passthrough_handler *install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tap, memory_passthrough_handler *mph = nullptr); - virtual memory_passthrough_handler *install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tapr, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr); - virtual memory_passthrough_handler *install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tapr, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr); - virtual memory_passthrough_handler *install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tapr, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr); - virtual memory_passthrough_handler *install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tapr, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr); + virtual memory_passthrough_handler install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tap, memory_passthrough_handler *mph = nullptr); + virtual memory_passthrough_handler install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tap, memory_passthrough_handler *mph = nullptr); + virtual memory_passthrough_handler install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tap, memory_passthrough_handler *mph = nullptr); + virtual memory_passthrough_handler install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tap, memory_passthrough_handler *mph = nullptr); + virtual memory_passthrough_handler install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tap, memory_passthrough_handler *mph = nullptr); + virtual memory_passthrough_handler install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tap, memory_passthrough_handler *mph = nullptr); + virtual memory_passthrough_handler install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tap, memory_passthrough_handler *mph = nullptr); + virtual memory_passthrough_handler install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tap, memory_passthrough_handler *mph = nullptr); + virtual memory_passthrough_handler install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tapr, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr); + virtual memory_passthrough_handler install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tapr, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr); + virtual memory_passthrough_handler install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tapr, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr); + virtual memory_passthrough_handler install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tapr, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr); // install views void install_view(offs_t addrstart, offs_t addrend, memory_view &view) { install_view(addrstart, addrend, 0, view); } @@ -1918,11 +1950,6 @@ class address_space : public address_space_installer template<int Width, int AddrShift> friend class handler_entry_read_unmapped; template<int Width, int AddrShift> friend class handler_entry_write_unmapped; - struct notifier_t { - std::function<void (read_or_write)> m_notifier; - int m_id; - }; - protected: // construction/destruction address_space(memory_manager &manager, device_memory_interface &memory, int spacenum); @@ -1962,15 +1989,14 @@ public: v.set(this, get_specific_info()); } - int add_change_notifier(std::function<void (read_or_write)> n); - void remove_change_notifier(int id); + util::notifier_subscription add_change_notifier(delegate<void (read_or_write)> &&n); + template <typename T> util::notifier_subscription add_change_notifier(T &&n) { return add_change_notifier(delegate<void (read_or_write)>(std::forward<T>(n))); } void invalidate_caches(read_or_write mode) { if(u32(mode) & ~m_in_notification) { u32 old = m_in_notification; m_in_notification |= u32(mode); - for(const auto &n : m_notifiers) - n.m_notifier(mode); + m_notifiers(mode); m_in_notification = old; } } @@ -1981,7 +2007,7 @@ public: u64 unmap() const { return m_unmap; } - memory_passthrough_handler *make_mph(); + std::shared_ptr<emu::detail::memory_passthrough_handler_impl> make_mph(memory_passthrough_handler *mph); // debug helpers virtual std::string get_handler_string(read_or_write readorwrite, offs_t byteaddress) const = 0; @@ -2088,10 +2114,9 @@ protected: handler_entry *m_nop_r; handler_entry *m_nop_w; - std::vector<std::unique_ptr<memory_passthrough_handler>> m_mphs; + std::vector<std::shared_ptr<emu::detail::memory_passthrough_handler_impl>> m_mphs; - std::vector<notifier_t> m_notifiers; // notifier list for address map change - int m_notifier_id; // next notifier id + util::notifier<read_or_write> m_notifiers; // notifier list for address map change u32 m_in_notification; // notification(s) currently being done }; @@ -2397,7 +2422,7 @@ write_native(offs_t address, typename emu::detail::handler_entry_size<Width>::uX m_cache_w->write(address, data, mask); } -void memory_passthrough_handler::remove() +inline void emu::detail::memory_passthrough_handler_impl::remove() { m_space.remove_passthrough(m_handlers); } @@ -2421,18 +2446,19 @@ set(address_space *space, std::pair<void *, void *> rw) m_space = space; m_addrmask = space->addrmask(); - space->add_change_notifier([this](read_or_write mode) { - if(u32(mode) & u32(read_or_write::READ)) { - m_addrend_r = 0; - m_addrstart_r = 1; - m_cache_r = nullptr; - } - if(u32(mode) & u32(read_or_write::WRITE)) { - m_addrend_w = 0; - m_addrstart_w = 1; - m_cache_w = nullptr; - } - }); + m_subscription = space->add_change_notifier( + [this] (read_or_write mode) { + if(u32(mode) & u32(read_or_write::READ)) { + m_addrend_r = 0; + m_addrstart_r = 1; + m_cache_r = nullptr; + } + if(u32(mode) & u32(read_or_write::WRITE)) { + m_addrend_w = 0; + m_addrstart_w = 1; + m_cache_w = nullptr; + } + }); m_root_read = (handler_entry_read <Width, AddrShift> *)(rw.first); m_root_write = (handler_entry_write<Width, AddrShift> *)(rw.second); diff --git a/src/emu/emumem_aspace.cpp b/src/emu/emumem_aspace.cpp index 5aeea17c11a..cf7302ce104 100644 --- a/src/emu/emumem_aspace.cpp +++ b/src/emu/emumem_aspace.cpp @@ -292,9 +292,9 @@ public: using address_space::install_write_tap; using address_space::install_readwrite_tap; - virtual memory_passthrough_handler *install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph) override; - virtual memory_passthrough_handler *install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph) override; - virtual memory_passthrough_handler *install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tapr, std::function<void (offs_t offset, uX &data, uX mem_mask)> tapw, memory_passthrough_handler *mph) override; + virtual memory_passthrough_handler install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph) override; + virtual memory_passthrough_handler install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph) override; + virtual memory_passthrough_handler install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tapr, std::function<void (offs_t offset, uX &data, uX mem_mask)> tapw, memory_passthrough_handler *mph) override; // construction/destruction address_space_specific(memory_manager &manager, device_memory_interface &memory, int spacenum, int address_width) @@ -810,7 +810,6 @@ address_space::address_space(memory_manager &manager, device_memory_interface &m m_spacenum(spacenum), m_log_unmap(true), m_name(memory.space_config(spacenum)->name()), - m_notifier_id(0), m_in_notification(0) { } @@ -1084,73 +1083,78 @@ template<int Level, int Width, int AddrShift, endianness_t Endian> void address_ view.make_subdispatch(""); // Must be called after populate } -memory_passthrough_handler *address_space::make_mph() +std::shared_ptr<emu::detail::memory_passthrough_handler_impl> address_space::make_mph(memory_passthrough_handler *mph) { - m_mphs.emplace_back(std::make_unique<memory_passthrough_handler>(*this)); - return m_mphs.back().get(); + if (mph) + { + auto impl(mph->m_impl.lock()); + if (impl) + { + assert(&impl->m_space == this); + return impl; + } + } + return m_mphs.emplace_back(std::make_shared<emu::detail::memory_passthrough_handler_impl>(*this)); } //------------------------------------------------- // install_read_tap - install a read tap on the bus //------------------------------------------------- -template<int Level, int Width, int AddrShift, endianness_t Endian> memory_passthrough_handler *address_space_specific<Level, Width, AddrShift, Endian>::install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph) +template<int Level, int Width, int AddrShift, endianness_t Endian> memory_passthrough_handler address_space_specific<Level, Width, AddrShift, Endian>::install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph) { offs_t nstart, nend, nmask, nmirror; check_optimize_mirror("install_read_tap", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror); - if (!mph) - mph = make_mph(); + auto impl = make_mph(mph); - auto handler = new handler_entry_read_tap<Width, AddrShift>(this, *mph, name, tap); + auto handler = new handler_entry_read_tap<Width, AddrShift>(this, *impl, name, tap); m_root_read->populate_passthrough(nstart, nend, nmirror, handler); handler->unref(); invalidate_caches(read_or_write::READ); - return mph; + return impl; } //------------------------------------------------- // install_write_tap - install a write tap on the bus //------------------------------------------------- -template<int Level, int Width, int AddrShift, endianness_t Endian> memory_passthrough_handler *address_space_specific<Level, Width, AddrShift, Endian>::install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph) +template<int Level, int Width, int AddrShift, endianness_t Endian> memory_passthrough_handler address_space_specific<Level, Width, AddrShift, Endian>::install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph) { offs_t nstart, nend, nmask, nmirror; check_optimize_mirror("install_write_tap", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror); - if (!mph) - mph = make_mph(); + auto impl = make_mph(mph); - auto handler = new handler_entry_write_tap<Width, AddrShift>(this, *mph, name, tap); + auto handler = new handler_entry_write_tap<Width, AddrShift>(this, *impl, name, tap); m_root_write->populate_passthrough(nstart, nend, nmirror, handler); handler->unref(); invalidate_caches(read_or_write::WRITE); - return mph; + return impl; } //------------------------------------------------- // install_write_tap - install a read and a write tap on the bus //------------------------------------------------- -template<int Level, int Width, int AddrShift, endianness_t Endian> memory_passthrough_handler *address_space_specific<Level, Width, AddrShift, Endian>::install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tapr, std::function<void (offs_t offset, uX &data, uX mem_mask)> tapw, memory_passthrough_handler *mph) +template<int Level, int Width, int AddrShift, endianness_t Endian> memory_passthrough_handler address_space_specific<Level, Width, AddrShift, Endian>::install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tapr, std::function<void (offs_t offset, uX &data, uX mem_mask)> tapw, memory_passthrough_handler *mph) { offs_t nstart, nend, nmask, nmirror; check_optimize_mirror("install_readwrite_tap", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror); - if (!mph) - mph = make_mph(); + auto impl = make_mph(mph); - auto rhandler = new handler_entry_read_tap <Width, AddrShift>(this, *mph, name, tapr); + auto rhandler = new handler_entry_read_tap <Width, AddrShift>(this, *impl, name, tapr); m_root_read ->populate_passthrough(nstart, nend, nmirror, rhandler); rhandler->unref(); - auto whandler = new handler_entry_write_tap<Width, AddrShift>(this, *mph, name, tapw); + auto whandler = new handler_entry_write_tap<Width, AddrShift>(this, *impl, name, tapw); m_root_write->populate_passthrough(nstart, nend, nmirror, whandler); whandler->unref(); invalidate_caches(read_or_write::READWRITE); - return mph; + return impl; } @@ -1291,19 +1295,7 @@ template<int Level, int Width, int AddrShift, endianness_t Endian> void address_ // MEMORY MAPPING HELPERS //************************************************************************** -int address_space::add_change_notifier(std::function<void (read_or_write)> n) +util::notifier_subscription address_space::add_change_notifier(delegate<void (read_or_write)> &&n) { - int id = m_notifier_id++; - m_notifiers.emplace_back(notifier_t{ std::move(n), id }); - return id; -} - -void address_space::remove_change_notifier(int id) -{ - for(auto i = m_notifiers.begin(); i != m_notifiers.end(); i++) - if (i->m_id == id) { - m_notifiers.erase(i); - return; - } - fatalerror("Unknown notifier id %d, double remove?\n", id); + return m_notifiers.subscribe(std::move(n)); } diff --git a/src/emu/emumem_hep.h b/src/emu/emumem_hep.h index 60fc422b72e..a98b44c267d 100644 --- a/src/emu/emumem_hep.h +++ b/src/emu/emumem_hep.h @@ -10,7 +10,7 @@ template<int Width, int AddrShift> class handler_entry_read_passthrough : public public: using uX = typename emu::detail::handler_entry_size<Width>::uX; - handler_entry_read_passthrough(address_space *space, memory_passthrough_handler &mph) : handler_entry_read<Width, AddrShift>(space, handler_entry::F_PASSTHROUGH), m_mph(mph), m_next(nullptr) {} + handler_entry_read_passthrough(address_space *space, emu::detail::memory_passthrough_handler_impl &mph) : handler_entry_read<Width, AddrShift>(space, handler_entry::F_PASSTHROUGH), m_mph(mph), m_next(nullptr) {} ~handler_entry_read_passthrough(); virtual handler_entry_read_passthrough<Width, AddrShift> *instantiate(handler_entry_read<Width, AddrShift> *next) const = 0; @@ -20,10 +20,10 @@ public: void detach(const std::unordered_set<handler_entry *> &handlers) override; protected: - memory_passthrough_handler &m_mph; + emu::detail::memory_passthrough_handler_impl &m_mph; handler_entry_read<Width, AddrShift> *m_next; - handler_entry_read_passthrough(address_space *space, memory_passthrough_handler &mph, handler_entry_read<Width, AddrShift> *next) : handler_entry_read<Width, AddrShift>(space, handler_entry::F_PASSTHROUGH), m_mph(mph), m_next(next) { next->ref(); mph.add_handler(this); } + handler_entry_read_passthrough(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, handler_entry_read<Width, AddrShift> *next) : handler_entry_read<Width, AddrShift>(space, handler_entry::F_PASSTHROUGH), m_mph(mph), m_next(next) { next->ref(); mph.add_handler(this); } }; template<int Width, int AddrShift> class handler_entry_write_passthrough : public handler_entry_write<Width, AddrShift> @@ -31,7 +31,7 @@ template<int Width, int AddrShift> class handler_entry_write_passthrough : publi public: using uX = typename emu::detail::handler_entry_size<Width>::uX; - handler_entry_write_passthrough(address_space *space, memory_passthrough_handler &mph) : handler_entry_write<Width, AddrShift>(space, handler_entry::F_PASSTHROUGH), m_mph(mph), m_next(nullptr) {} + handler_entry_write_passthrough(address_space *space, emu::detail::memory_passthrough_handler_impl &mph) : handler_entry_write<Width, AddrShift>(space, handler_entry::F_PASSTHROUGH), m_mph(mph), m_next(nullptr) {} ~handler_entry_write_passthrough(); virtual handler_entry_write_passthrough<Width, AddrShift> *instantiate(handler_entry_write<Width, AddrShift> *next) const = 0; @@ -41,8 +41,8 @@ public: void detach(const std::unordered_set<handler_entry *> &handlers) override; protected: - memory_passthrough_handler &m_mph; + emu::detail::memory_passthrough_handler_impl &m_mph; handler_entry_write<Width, AddrShift> *m_next; - handler_entry_write_passthrough(address_space *space, memory_passthrough_handler &mph, handler_entry_write<Width, AddrShift> *next) : handler_entry_write<Width, AddrShift>(space, handler_entry::F_PASSTHROUGH), m_mph(mph), m_next(next) { next->ref(); mph.add_handler(this); } + handler_entry_write_passthrough(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, handler_entry_write<Width, AddrShift> *next) : handler_entry_write<Width, AddrShift>(space, handler_entry::F_PASSTHROUGH), m_mph(mph), m_next(next) { next->ref(); mph.add_handler(this); } }; diff --git a/src/emu/emumem_het.h b/src/emu/emumem_het.h index 2914605772b..a148e3d3533 100644 --- a/src/emu/emumem_het.h +++ b/src/emu/emumem_het.h @@ -14,7 +14,7 @@ template<int Width, int AddrShift> class handler_entry_read_tap : public handler public: using uX = typename emu::detail::handler_entry_size<Width>::uX; - handler_entry_read_tap(address_space *space, memory_passthrough_handler &mph, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap) : handler_entry_read_passthrough<Width, AddrShift>(space, mph), m_name(name), m_tap(std::move(tap)) {} + handler_entry_read_tap(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap) : handler_entry_read_passthrough<Width, AddrShift>(space, mph), m_name(name), m_tap(std::move(tap)) {} ~handler_entry_read_tap() = default; uX read(offs_t offset, uX mem_mask) const override; @@ -28,7 +28,7 @@ protected: std::string m_name; std::function<void (offs_t offset, uX &data, uX mem_mask)> m_tap; - handler_entry_read_tap(address_space *space, memory_passthrough_handler &mph, handler_entry_read<Width, AddrShift> *next, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap) : handler_entry_read_passthrough<Width, AddrShift>(space, mph, next), m_name(name), m_tap(tap) {} + handler_entry_read_tap(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, handler_entry_read<Width, AddrShift> *next, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap) : handler_entry_read_passthrough<Width, AddrShift>(space, mph, next), m_name(name), m_tap(tap) {} }; template<int Width, int AddrShift> class handler_entry_write_tap : public handler_entry_write_passthrough<Width, AddrShift> @@ -36,7 +36,7 @@ template<int Width, int AddrShift> class handler_entry_write_tap : public handle public: using uX = typename emu::detail::handler_entry_size<Width>::uX; - handler_entry_write_tap(address_space *space, memory_passthrough_handler &mph, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap) : handler_entry_write_passthrough<Width, AddrShift>(space, mph), m_name(name), m_tap(std::move(tap)) {} + handler_entry_write_tap(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap) : handler_entry_write_passthrough<Width, AddrShift>(space, mph), m_name(name), m_tap(std::move(tap)) {} ~handler_entry_write_tap() = default; void write(offs_t offset, uX data, uX mem_mask) const override; @@ -50,7 +50,7 @@ protected: std::string m_name; std::function<void (offs_t offset, uX &data, uX mem_mask)> m_tap; - handler_entry_write_tap(address_space *space, memory_passthrough_handler &mph, handler_entry_write<Width, AddrShift> *next, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap) : handler_entry_write_passthrough<Width, AddrShift>(space, mph, next), m_name(name), m_tap(tap) {} + handler_entry_write_tap(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, handler_entry_write<Width, AddrShift> *next, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap) : handler_entry_write_passthrough<Width, AddrShift>(space, mph, next), m_name(name), m_tap(tap) {} }; #endif // MAME_EMU_EMUMEM_HET_H diff --git a/src/emu/emumem_mview.cpp b/src/emu/emumem_mview.cpp index 06007c7d0b5..b916e3f951f 100644 --- a/src/emu/emumem_mview.cpp +++ b/src/emu/emumem_mview.cpp @@ -126,9 +126,9 @@ public: using address_space_installer::install_write_tap; using address_space_installer::install_readwrite_tap; - virtual memory_passthrough_handler *install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph) override; - virtual memory_passthrough_handler *install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph) override; - virtual memory_passthrough_handler *install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tapr, std::function<void (offs_t offset, uX &data, uX mem_mask)> tapw, memory_passthrough_handler *mph) override; + virtual memory_passthrough_handler install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph) override; + virtual memory_passthrough_handler install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph) override; + virtual memory_passthrough_handler install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tapr, std::function<void (offs_t offset, uX &data, uX mem_mask)> tapw, memory_passthrough_handler *mph) override; virtual void unmap_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, u16 flags, read_or_write readorwrite, bool quiet) override; virtual void install_ram_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, u16 flags, read_or_write readorwrite, void *baseptr) override; @@ -898,65 +898,62 @@ template<int Level, int Width, int AddrShift> void memory_view_entry_specific<Le view.make_subdispatch(key()); // Must be called after populate } -template<int Level, int Width, int AddrShift> memory_passthrough_handler *memory_view_entry_specific<Level, Width, AddrShift>::install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph) +template<int Level, int Width, int AddrShift> memory_passthrough_handler memory_view_entry_specific<Level, Width, AddrShift>::install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph) { offs_t nstart, nend, nmask, nmirror; check_range_optimize_mirror("install_read_tap", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror); - if (!mph) - mph = m_view.m_space->make_mph(); + auto impl = m_view.m_space->make_mph(mph); r()->select_u(m_id); w()->select_u(m_id); - auto handler = new handler_entry_read_tap<Width, AddrShift>(m_view.m_space, *mph, name, tap); + auto handler = new handler_entry_read_tap<Width, AddrShift>(m_view.m_space, *impl, name, tap); r()->populate_passthrough(nstart, nend, nmirror, handler); handler->unref(); invalidate_caches(read_or_write::READ); - return mph; + return impl; } -template<int Level, int Width, int AddrShift> memory_passthrough_handler *memory_view_entry_specific<Level, Width, AddrShift>::install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph) +template<int Level, int Width, int AddrShift> memory_passthrough_handler memory_view_entry_specific<Level, Width, AddrShift>::install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph) { offs_t nstart, nend, nmask, nmirror; check_range_optimize_mirror("install_write_tap", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror); - if (!mph) - mph = m_view.m_space->make_mph(); + auto impl = m_view.m_space->make_mph(mph); r()->select_u(m_id); w()->select_u(m_id); - auto handler = new handler_entry_write_tap<Width, AddrShift>(m_view.m_space, *mph, name, tap); + auto handler = new handler_entry_write_tap<Width, AddrShift>(m_view.m_space, *impl, name, tap); w()->populate_passthrough(nstart, nend, nmirror, handler); handler->unref(); invalidate_caches(read_or_write::WRITE); - return mph; + return impl; } -template<int Level, int Width, int AddrShift> memory_passthrough_handler *memory_view_entry_specific<Level, Width, AddrShift>::install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tapr, std::function<void (offs_t offset, uX &data, uX mem_mask)> tapw, memory_passthrough_handler *mph) +template<int Level, int Width, int AddrShift> memory_passthrough_handler memory_view_entry_specific<Level, Width, AddrShift>::install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tapr, std::function<void (offs_t offset, uX &data, uX mem_mask)> tapw, memory_passthrough_handler *mph) { offs_t nstart, nend, nmask, nmirror; check_range_optimize_mirror("install_readwrite_tap", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror); - if (!mph) - mph = m_view.m_space->make_mph(); + auto impl = m_view.m_space->make_mph(mph); r()->select_u(m_id); w()->select_u(m_id); - auto rhandler = new handler_entry_read_tap <Width, AddrShift>(m_view.m_space, *mph, name, tapr); + auto rhandler = new handler_entry_read_tap <Width, AddrShift>(m_view.m_space, *impl, name, tapr); r() ->populate_passthrough(nstart, nend, nmirror, rhandler); rhandler->unref(); - auto whandler = new handler_entry_write_tap<Width, AddrShift>(m_view.m_space, *mph, name, tapw); + auto whandler = new handler_entry_write_tap<Width, AddrShift>(m_view.m_space, *impl, name, tapw); w()->populate_passthrough(nstart, nend, nmirror, whandler); whandler->unref(); invalidate_caches(read_or_write::READWRITE); - return mph; + return impl; } template<int Level, int Width, int AddrShift> void memory_view_entry_specific<Level, Width, AddrShift>::install_device_delegate(offs_t addrstart, offs_t addrend, device_t &device, address_map_constructor &delegate, u64 unitmask, int cswidth, u16 flags) diff --git a/src/emu/emuopts.cpp b/src/emu/emuopts.cpp index 8959c00da03..5a1722df737 100644 --- a/src/emu/emuopts.cpp +++ b/src/emu/emuopts.cpp @@ -528,7 +528,7 @@ void emu_options::update_slot_and_image_options() if (add_and_remove_slot_options()) changed = true; - // second, we perform an analgous operation with m_image_options + // second, we perform an analogous operation with m_image_options if (add_and_remove_image_options()) changed = true; @@ -1220,8 +1220,8 @@ void slot_option::set_bios(std::string &&text) { if (!m_specified) { - m_specified = true; m_specified_value = value(); + m_specified = true; } m_specified_bios = std::move(text); } diff --git a/src/emu/fileio.cpp b/src/emu/fileio.cpp index 6d5d6b8a806..a1bf4adbcb4 100644 --- a/src/emu/fileio.cpp +++ b/src/emu/fileio.cpp @@ -107,7 +107,7 @@ path_iterator &path_iterator::operator=(path_iterator const &that) // multipath sequence //------------------------------------------------- -bool path_iterator::next(std::string &buffer, const char *name) +bool path_iterator::next(std::string &buffer) { // if none left, return false to indicate we are done if (!m_is_first && (m_searchpath.cend() == m_current)) @@ -120,10 +120,6 @@ bool path_iterator::next(std::string &buffer, const char *name) if (m_searchpath.cend() != m_current) ++m_current; - // append the name if we have one - if (name) - util::path_append(buffer, name); - // bump the index and return true m_is_first = false; return true; @@ -160,9 +156,13 @@ const osd::directory::entry *file_enumerator::next(const char *subdir) while (!m_curdir) { // if we fail to get anything more, we're done - if (!m_iterator.next(m_pathbuffer, subdir)) + if (!m_iterator.next(m_pathbuffer)) return nullptr; + // append the subdir if we have one + if (subdir) + util::path_append(m_pathbuffer, subdir); + // open the path m_curdir = osd::directory::open(m_pathbuffer); } @@ -259,7 +259,7 @@ util::hash_collection &emu_file::hashes(std::string_view types) // determine which hashes we need std::string needed; for (char scan : types) - if (already_have.find_first_of(scan) == -1) + if (already_have.find_first_of(scan) == std::string::npos) needed.push_back(scan); // if we need nothing, skip it @@ -279,15 +279,14 @@ util::hash_collection &emu_file::hashes(std::string_view types) return m_hashes; } - // read the data if we can - const u8 *filedata = (const u8 *)m_file->buffer(); - if (filedata == nullptr) + std::uint64_t length; + if (m_file->length(length)) return m_hashes; - // compute the hash - std::uint64_t length; - if (!m_file->length(length)) - m_hashes.compute(filedata, length, needed.c_str()); + // hash the data + std::size_t actual; + (void)m_hashes.compute(*m_file, 0U, length, actual, needed.c_str()); // FIXME: need better interface to report errors + return m_hashes; } @@ -805,7 +804,7 @@ std::error_condition emu_file::load_zipped_file() m_zipdata.resize(m_ziplength); // read the data into our buffer and return - auto const ziperr = m_zipfile->decompress(&m_zipdata[0], m_zipdata.size()); + auto const ziperr = m_zipfile->decompress(m_zipdata.data(), m_zipdata.size()); if (ziperr) { m_zipdata.clear(); @@ -813,7 +812,7 @@ std::error_condition emu_file::load_zipped_file() } // convert to RAM file - std::error_condition const filerr = util::core_file::open_ram(&m_zipdata[0], m_zipdata.size(), m_openflags, m_file); + std::error_condition const filerr = util::core_file::open_ram(m_zipdata.data(), m_zipdata.size(), m_openflags, m_file); if (filerr) { m_zipdata.clear(); diff --git a/src/emu/fileio.h b/src/emu/fileio.h index 91aedad173e..7398e649c6e 100644 --- a/src/emu/fileio.h +++ b/src/emu/fileio.h @@ -61,7 +61,7 @@ public: path_iterator &operator=(path_iterator const &that); // main interface - bool next(std::string &buffer, const char *name = nullptr); + bool next(std::string &buffer); void reset(); private: diff --git a/src/emu/hashfile.cpp b/src/emu/hashfile.cpp index a6107e5e630..8436ad339fb 100644 --- a/src/emu/hashfile.cpp +++ b/src/emu/hashfile.cpp @@ -13,6 +13,7 @@ #include "drivenum.h" #include "emuopts.h" +#include "fileio.h" #include "hash.h" diff --git a/src/emu/http.cpp b/src/emu/http.cpp index f36244e31ac..8c95e731552 100644 --- a/src/emu/http.cpp +++ b/src/emu/http.cpp @@ -9,6 +9,9 @@ ***************************************************************************/ #include "emu.h" +#include "http.h" +#include "server_http.hpp" +#include "server_ws.hpp" #ifdef __sun #define ASIO_DISABLE_DEV_POLL diff --git a/src/emu/http.h b/src/emu/http.h index b0adf1e2b3d..e7c26d7980f 100644 --- a/src/emu/http.h +++ b/src/emu/http.h @@ -10,18 +10,12 @@ #pragma once -#ifndef __EMU_H__ -#error Dont include this file directly; include emu.h instead. -#endif - #ifndef MAME_EMU_HTTP_H #define MAME_EMU_HTTP_H #include <mutex> #include <thread> #include <ctime> -#include "server_http.hpp" -#include "server_ws.hpp" //************************************************************************** // TYPE DEFINITIONS @@ -33,6 +27,13 @@ namespace asio class io_context; } +namespace webpp +{ + class http_server; + class ws_server; + struct Connection; +} + class http_manager { DISABLE_COPYING(http_manager); diff --git a/src/emu/image.cpp b/src/emu/image.cpp index 5e58758eb89..e7f070eb9ea 100644 --- a/src/emu/image.cpp +++ b/src/emu/image.cpp @@ -14,6 +14,7 @@ #include "config.h" #include "drivenum.h" #include "emuopts.h" +#include "fileio.h" #include "softlist.h" #include "corestr.h" diff --git a/src/emu/image.h b/src/emu/image.h index daf48b1f21d..95dca8a92b9 100644 --- a/src/emu/image.h +++ b/src/emu/image.h @@ -36,7 +36,7 @@ private: void options_extract(); int write_config(emu_options &options, const char *filename, const game_driver *gamedrv); - bool try_change_working_directory(std::string &working_directory, const std::string &subdir);; + bool try_change_working_directory(std::string &working_directory, const std::string &subdir); // internal state running_machine & m_machine; // reference to our machine diff --git a/src/emu/inpttype.ipp b/src/emu/inpttype.ipp index aca3973673a..03f6e3e1dab 100644 --- a/src/emu/inpttype.ipp +++ b/src/emu/inpttype.ipp @@ -19,83 +19,83 @@ namespace { #define CORE_INPUT_TYPES_P1 \ CORE_INPUT_TYPES_BEGIN(p1) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICK_UP, N_p("input-name", "P1 Up"), input_seq(KEYCODE_UP, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICK_DOWN, N_p("input-name", "P1 Down"), input_seq(KEYCODE_DOWN, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICK_LEFT, N_p("input-name", "P1 Left"), input_seq(KEYCODE_LEFT, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICK_RIGHT, N_p("input-name", "P1 Right"), input_seq(KEYCODE_RIGHT, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKRIGHT_UP, N_p("input-name", "P1 Right Stick/Up"), input_seq(KEYCODE_I, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKRIGHT_DOWN, N_p("input-name", "P1 Right Stick/Down"), input_seq(KEYCODE_K, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKRIGHT_LEFT, N_p("input-name", "P1 Right Stick/Left"), input_seq(KEYCODE_J, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKRIGHT_RIGHT, N_p("input-name", "P1 Right Stick/Right"), input_seq(KEYCODE_L, input_seq::or_code, JOYCODE_BUTTON4_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKLEFT_UP, N_p("input-name", "P1 Left Stick/Up"), input_seq(KEYCODE_E, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKLEFT_DOWN, N_p("input-name", "P1 Left Stick/Down"), input_seq(KEYCODE_D, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKLEFT_LEFT, N_p("input-name", "P1 Left Stick/Left"), input_seq(KEYCODE_S, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKLEFT_RIGHT, N_p("input-name", "P1 Left Stick/Right"), input_seq(KEYCODE_F, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON1, N_p("input-name", "P1 Button 1"), input_seq(KEYCODE_LCONTROL, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(0), input_seq::or_code, MOUSECODE_BUTTON1_INDEXED(0), input_seq::or_code, GUNCODE_BUTTON1_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON2, N_p("input-name", "P1 Button 2"), input_seq(KEYCODE_LALT, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(0), input_seq::or_code, MOUSECODE_BUTTON3_INDEXED(0), input_seq::or_code, GUNCODE_BUTTON2_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON3, N_p("input-name", "P1 Button 3"), input_seq(KEYCODE_SPACE, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(0), input_seq::or_code, MOUSECODE_BUTTON2_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON4, N_p("input-name", "P1 Button 4"), input_seq(KEYCODE_LSHIFT, input_seq::or_code, JOYCODE_BUTTON4_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON5, N_p("input-name", "P1 Button 5"), input_seq(KEYCODE_Z, input_seq::or_code, JOYCODE_BUTTON5_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON6, N_p("input-name", "P1 Button 6"), input_seq(KEYCODE_X, input_seq::or_code, JOYCODE_BUTTON6_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON7, N_p("input-name", "P1 Button 7"), input_seq(KEYCODE_C, input_seq::or_code, JOYCODE_BUTTON7_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON8, N_p("input-name", "P1 Button 8"), input_seq(KEYCODE_V, input_seq::or_code, JOYCODE_BUTTON8_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON9, N_p("input-name", "P1 Button 9"), input_seq(KEYCODE_B, input_seq::or_code, JOYCODE_BUTTON9_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON10, N_p("input-name", "P1 Button 10"), input_seq(KEYCODE_N, input_seq::or_code, JOYCODE_BUTTON10_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON11, N_p("input-name", "P1 Button 11"), input_seq(KEYCODE_M, input_seq::or_code, JOYCODE_BUTTON11_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON12, N_p("input-name", "P1 Button 12"), input_seq(KEYCODE_COMMA, input_seq::or_code, JOYCODE_BUTTON12_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON13, N_p("input-name", "P1 Button 13"), input_seq(KEYCODE_STOP, input_seq::or_code, JOYCODE_BUTTON13_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON14, N_p("input-name", "P1 Button 14"), input_seq(KEYCODE_SLASH, input_seq::or_code, JOYCODE_BUTTON14_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON15, N_p("input-name", "P1 Button 15"), input_seq(KEYCODE_RSHIFT, input_seq::or_code, JOYCODE_BUTTON15_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON16, N_p("input-name", "P1 Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, START, N_p("input-name", "P1 Start"), input_seq(KEYCODE_1, input_seq::or_code, JOYCODE_START_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, SELECT, N_p("input-name", "P1 Select"), input_seq(KEYCODE_5, input_seq::or_code, JOYCODE_SELECT_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq(KEYCODE_UP, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq(KEYCODE_DOWN, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq(KEYCODE_LEFT, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq(KEYCODE_RIGHT, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKRIGHT_UP, N_p("input-name", "%p Right Stick/Up"), input_seq(KEYCODE_I, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKRIGHT_DOWN, N_p("input-name", "%p Right Stick/Down"), input_seq(KEYCODE_K, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKRIGHT_LEFT, N_p("input-name", "%p Right Stick/Left"), input_seq(KEYCODE_J, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKRIGHT_RIGHT, N_p("input-name", "%p Right Stick/Right"), input_seq(KEYCODE_L, input_seq::or_code, JOYCODE_BUTTON4_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKLEFT_UP, N_p("input-name", "%p Left Stick/Up"), input_seq(KEYCODE_E, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKLEFT_DOWN, N_p("input-name", "%p Left Stick/Down"), input_seq(KEYCODE_D, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKLEFT_LEFT, N_p("input-name", "%p Left Stick/Left"), input_seq(KEYCODE_S, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKLEFT_RIGHT, N_p("input-name", "%p Left Stick/Right"), input_seq(KEYCODE_F, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON1, N_p("input-name", "%p Button 1"), input_seq(KEYCODE_LCONTROL, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(0), input_seq::or_code, MOUSECODE_BUTTON1_INDEXED(0), input_seq::or_code, GUNCODE_BUTTON1_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON2, N_p("input-name", "%p Button 2"), input_seq(KEYCODE_LALT, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(0), input_seq::or_code, MOUSECODE_BUTTON3_INDEXED(0), input_seq::or_code, GUNCODE_BUTTON2_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON3, N_p("input-name", "%p Button 3"), input_seq(KEYCODE_SPACE, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(0), input_seq::or_code, MOUSECODE_BUTTON2_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON4, N_p("input-name", "%p Button 4"), input_seq(KEYCODE_LSHIFT, input_seq::or_code, JOYCODE_BUTTON4_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON5, N_p("input-name", "%p Button 5"), input_seq(KEYCODE_Z, input_seq::or_code, JOYCODE_BUTTON5_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON6, N_p("input-name", "%p Button 6"), input_seq(KEYCODE_X, input_seq::or_code, JOYCODE_BUTTON6_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON7, N_p("input-name", "%p Button 7"), input_seq(KEYCODE_C, input_seq::or_code, JOYCODE_BUTTON7_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON8, N_p("input-name", "%p Button 8"), input_seq(KEYCODE_V, input_seq::or_code, JOYCODE_BUTTON8_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON9, N_p("input-name", "%p Button 9"), input_seq(KEYCODE_B, input_seq::or_code, JOYCODE_BUTTON9_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON10, N_p("input-name", "%p Button 10"), input_seq(KEYCODE_N, input_seq::or_code, JOYCODE_BUTTON10_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON11, N_p("input-name", "%p Button 11"), input_seq(KEYCODE_M, input_seq::or_code, JOYCODE_BUTTON11_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON12, N_p("input-name", "%p Button 12"), input_seq(KEYCODE_COMMA, input_seq::or_code, JOYCODE_BUTTON12_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON13, N_p("input-name", "%p Button 13"), input_seq(KEYCODE_STOP, input_seq::or_code, JOYCODE_BUTTON13_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON14, N_p("input-name", "%p Button 14"), input_seq(KEYCODE_SLASH, input_seq::or_code, JOYCODE_BUTTON14_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON15, N_p("input-name", "%p Button 15"), input_seq(KEYCODE_RSHIFT, input_seq::or_code, JOYCODE_BUTTON15_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON16, N_p("input-name", "%p Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, START, N_p("input-name", "%p Start"), input_seq(KEYCODE_1, input_seq::or_code, JOYCODE_START_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, SELECT, N_p("input-name", "%p Select"), input_seq(KEYCODE_5, input_seq::or_code, JOYCODE_SELECT_INDEXED(0)) ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_P1_MAHJONG \ CORE_INPUT_TYPES_BEGIN(p1_mahjong) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_A, N_p("input-name", "P1 Mahjong A"), input_seq(KEYCODE_A) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_B, N_p("input-name", "P1 Mahjong B"), input_seq(KEYCODE_B) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_C, N_p("input-name", "P1 Mahjong C"), input_seq(KEYCODE_C) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_D, N_p("input-name", "P1 Mahjong D"), input_seq(KEYCODE_D) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_E, N_p("input-name", "P1 Mahjong E"), input_seq(KEYCODE_E) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_F, N_p("input-name", "P1 Mahjong F"), input_seq(KEYCODE_F) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_G, N_p("input-name", "P1 Mahjong G"), input_seq(KEYCODE_G) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_H, N_p("input-name", "P1 Mahjong H"), input_seq(KEYCODE_H) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_I, N_p("input-name", "P1 Mahjong I"), input_seq(KEYCODE_I) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_J, N_p("input-name", "P1 Mahjong J"), input_seq(KEYCODE_J) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_K, N_p("input-name", "P1 Mahjong K"), input_seq(KEYCODE_K) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_L, N_p("input-name", "P1 Mahjong L"), input_seq(KEYCODE_L) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_M, N_p("input-name", "P1 Mahjong M"), input_seq(KEYCODE_M) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_N, N_p("input-name", "P1 Mahjong N"), input_seq(KEYCODE_N) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_O, N_p("input-name", "P1 Mahjong O"), input_seq(KEYCODE_O) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_P, N_p("input-name", "P1 Mahjong P"), input_seq(KEYCODE_COLON) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_Q, N_p("input-name", "P1 Mahjong Q"), input_seq(KEYCODE_Q) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_KAN, N_p("input-name", "P1 Mahjong Kan"), input_seq(KEYCODE_LCONTROL) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_PON, N_p("input-name", "P1 Mahjong Pon"), input_seq(KEYCODE_LALT) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_CHI, N_p("input-name", "P1 Mahjong Chi"), input_seq(KEYCODE_SPACE) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_REACH, N_p("input-name", "P1 Mahjong Reach"), input_seq(KEYCODE_LSHIFT) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_RON, N_p("input-name", "P1 Mahjong Ron"), input_seq(KEYCODE_Z) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_FLIP_FLOP, N_p("input-name", "P1 Mahjong Flip Flop"), input_seq(KEYCODE_Y) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_BET, N_p("input-name", "P1 Mahjong Bet"), input_seq(KEYCODE_3) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_SCORE, N_p("input-name", "P1 Mahjong Take Score"), input_seq(KEYCODE_RCONTROL) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_DOUBLE_UP, N_p("input-name", "P1 Mahjong Double Up"), input_seq(KEYCODE_RSHIFT) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_BIG, N_p("input-name", "P1 Mahjong Big"), input_seq(KEYCODE_ENTER) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_SMALL, N_p("input-name", "P1 Mahjong Small"), input_seq(KEYCODE_BACKSPACE) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_LAST_CHANCE, N_p("input-name", "P1 Mahjong Last Chance"), input_seq(KEYCODE_RALT) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_A, N_p("input-name", "%p Mahjong A"), input_seq(KEYCODE_A_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_B, N_p("input-name", "%p Mahjong B"), input_seq(KEYCODE_B_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_C, N_p("input-name", "%p Mahjong C"), input_seq(KEYCODE_C_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_D, N_p("input-name", "%p Mahjong D"), input_seq(KEYCODE_D_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_E, N_p("input-name", "%p Mahjong E"), input_seq(KEYCODE_E_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_F, N_p("input-name", "%p Mahjong F"), input_seq(KEYCODE_F_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_G, N_p("input-name", "%p Mahjong G"), input_seq(KEYCODE_G_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_H, N_p("input-name", "%p Mahjong H"), input_seq(KEYCODE_H_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_I, N_p("input-name", "%p Mahjong I"), input_seq(KEYCODE_I_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_J, N_p("input-name", "%p Mahjong J"), input_seq(KEYCODE_J_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_K, N_p("input-name", "%p Mahjong K"), input_seq(KEYCODE_K_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_L, N_p("input-name", "%p Mahjong L"), input_seq(KEYCODE_L_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_M, N_p("input-name", "%p Mahjong M"), input_seq(KEYCODE_M_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_N, N_p("input-name", "%p Mahjong N"), input_seq(KEYCODE_N_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_O, N_p("input-name", "%p Mahjong O"), input_seq(KEYCODE_O_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_P, N_p("input-name", "%p Mahjong P"), input_seq(KEYCODE_COLON_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_Q, N_p("input-name", "%p Mahjong Q"), input_seq(KEYCODE_Q_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_KAN, N_p("input-name", "%p Mahjong Kan"), input_seq(KEYCODE_LCONTROL_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_PON, N_p("input-name", "%p Mahjong Pon"), input_seq(KEYCODE_LALT_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_CHI, N_p("input-name", "%p Mahjong Chi"), input_seq(KEYCODE_SPACE_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_REACH, N_p("input-name", "%p Mahjong Reach"), input_seq(KEYCODE_LSHIFT_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_RON, N_p("input-name", "%p Mahjong Ron"), input_seq(KEYCODE_Z_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_FLIP_FLOP, N_p("input-name", "%p Mahjong Flip Flop"), input_seq(KEYCODE_Y_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_BET, N_p("input-name", "%p Mahjong Bet"), input_seq(KEYCODE_3_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_SCORE, N_p("input-name", "%p Mahjong Take Score"), input_seq(KEYCODE_RCONTROL_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_DOUBLE_UP, N_p("input-name", "%p Mahjong Double Up"), input_seq(KEYCODE_RSHIFT_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_BIG, N_p("input-name", "%p Mahjong Big"), input_seq(KEYCODE_ENTER_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_SMALL, N_p("input-name", "%p Mahjong Small"), input_seq(KEYCODE_BACKSPACE_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_LAST_CHANCE, N_p("input-name", "%p Mahjong Last Chance"), input_seq(KEYCODE_RALT_INDEXED(0)) ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_P1_HANAFUDA \ CORE_INPUT_TYPES_BEGIN(p1_hanafuda) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_A, N_p("input-name", "P1 Hanafuda A/1"), input_seq(KEYCODE_A) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_B, N_p("input-name", "P1 Hanafuda B/2"), input_seq(KEYCODE_B) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_C, N_p("input-name", "P1 Hanafuda C/3"), input_seq(KEYCODE_C) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_D, N_p("input-name", "P1 Hanafuda D/4"), input_seq(KEYCODE_D) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_E, N_p("input-name", "P1 Hanafuda E/5"), input_seq(KEYCODE_E) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_F, N_p("input-name", "P1 Hanafuda F/6"), input_seq(KEYCODE_F) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_G, N_p("input-name", "P1 Hanafuda G/7"), input_seq(KEYCODE_G) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_H, N_p("input-name", "P1 Hanafuda H/8"), input_seq(KEYCODE_H) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_YES, N_p("input-name", "P1 Hanafuda Yes"), input_seq(KEYCODE_M) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_NO, N_p("input-name", "P1 Hanafuda No"), input_seq(KEYCODE_N) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_A, N_p("input-name", "%p Hanafuda A/1"), input_seq(KEYCODE_A_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_B, N_p("input-name", "%p Hanafuda B/2"), input_seq(KEYCODE_B_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_C, N_p("input-name", "%p Hanafuda C/3"), input_seq(KEYCODE_C_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_D, N_p("input-name", "%p Hanafuda D/4"), input_seq(KEYCODE_D_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_E, N_p("input-name", "%p Hanafuda E/5"), input_seq(KEYCODE_E_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_F, N_p("input-name", "%p Hanafuda F/6"), input_seq(KEYCODE_F_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_G, N_p("input-name", "%p Hanafuda G/7"), input_seq(KEYCODE_G_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_H, N_p("input-name", "%p Hanafuda H/8"), input_seq(KEYCODE_H_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_YES, N_p("input-name", "%p Hanafuda Yes"), input_seq(KEYCODE_M_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_NO, N_p("input-name", "%p Hanafuda No"), input_seq(KEYCODE_N_INDEXED(0)) ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_GAMBLE \ @@ -137,355 +137,421 @@ namespace { #define CORE_INPUT_TYPES_P2 \ CORE_INPUT_TYPES_BEGIN(p2) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICK_UP, N_p("input-name", "P2 Up"), input_seq(KEYCODE_R, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICK_DOWN, N_p("input-name", "P2 Down"), input_seq(KEYCODE_F, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICK_LEFT, N_p("input-name", "P2 Left"), input_seq(KEYCODE_D, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICK_RIGHT, N_p("input-name", "P2 Right"), input_seq(KEYCODE_G, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKRIGHT_UP, N_p("input-name", "P2 Right Stick/Up"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKRIGHT_DOWN, N_p("input-name", "P2 Right Stick/Down"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKRIGHT_LEFT, N_p("input-name", "P2 Right Stick/Left"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKRIGHT_RIGHT, N_p("input-name", "P2 Right Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKLEFT_UP, N_p("input-name", "P2 Left Stick/Up"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKLEFT_DOWN, N_p("input-name", "P2 Left Stick/Down"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKLEFT_LEFT, N_p("input-name", "P2 Left Stick/Left"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKLEFT_RIGHT, N_p("input-name", "P2 Left Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON1, N_p("input-name", "P2 Button 1"), input_seq(KEYCODE_A, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(1), input_seq::or_code, MOUSECODE_BUTTON1_INDEXED(1), input_seq::or_code, GUNCODE_BUTTON1_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON2, N_p("input-name", "P2 Button 2"), input_seq(KEYCODE_S, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(1), input_seq::or_code, MOUSECODE_BUTTON3_INDEXED(1), input_seq::or_code, GUNCODE_BUTTON2_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON3, N_p("input-name", "P2 Button 3"), input_seq(KEYCODE_Q, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(1), input_seq::or_code, MOUSECODE_BUTTON2_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON4, N_p("input-name", "P2 Button 4"), input_seq(KEYCODE_W, input_seq::or_code, JOYCODE_BUTTON4_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON5, N_p("input-name", "P2 Button 5"), input_seq(KEYCODE_E, input_seq::or_code, JOYCODE_BUTTON5_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON6, N_p("input-name", "P2 Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON7, N_p("input-name", "P2 Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON8, N_p("input-name", "P2 Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON9, N_p("input-name", "P2 Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON10, N_p("input-name", "P2 Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON11, N_p("input-name", "P2 Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON12, N_p("input-name", "P2 Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON13, N_p("input-name", "P2 Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON14, N_p("input-name", "P2 Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON15, N_p("input-name", "P2 Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON16, N_p("input-name", "P2 Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, START, N_p("input-name", "P2 Start"), input_seq(KEYCODE_2, input_seq::or_code, JOYCODE_START_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, SELECT, N_p("input-name", "P2 Select"), input_seq(KEYCODE_6, input_seq::or_code, JOYCODE_SELECT_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq(KEYCODE_R, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq(KEYCODE_F, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq(KEYCODE_D, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq(KEYCODE_G, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKRIGHT_UP, N_p("input-name", "%p Right Stick/Up"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKRIGHT_DOWN, N_p("input-name", "%p Right Stick/Down"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKRIGHT_LEFT, N_p("input-name", "%p Right Stick/Left"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKRIGHT_RIGHT, N_p("input-name", "%p Right Stick/Right"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKLEFT_UP, N_p("input-name", "%p Left Stick/Up"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKLEFT_DOWN, N_p("input-name", "%p Left Stick/Down"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKLEFT_LEFT, N_p("input-name", "%p Left Stick/Left"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKLEFT_RIGHT, N_p("input-name", "%p Left Stick/Right"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON1, N_p("input-name", "%p Button 1"), input_seq(KEYCODE_A, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(1), input_seq::or_code, MOUSECODE_BUTTON1_INDEXED(1), input_seq::or_code, GUNCODE_BUTTON1_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON2, N_p("input-name", "%p Button 2"), input_seq(KEYCODE_S, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(1), input_seq::or_code, MOUSECODE_BUTTON3_INDEXED(1), input_seq::or_code, GUNCODE_BUTTON2_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON3, N_p("input-name", "%p Button 3"), input_seq(KEYCODE_Q, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(1), input_seq::or_code, MOUSECODE_BUTTON2_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON4, N_p("input-name", "%p Button 4"), input_seq(KEYCODE_W, input_seq::or_code, JOYCODE_BUTTON4_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON5, N_p("input-name", "%p Button 5"), input_seq(KEYCODE_E, input_seq::or_code, JOYCODE_BUTTON5_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON6, N_p("input-name", "%p Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON7, N_p("input-name", "%p Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON8, N_p("input-name", "%p Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON9, N_p("input-name", "%p Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON10, N_p("input-name", "%p Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON11, N_p("input-name", "%p Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON12, N_p("input-name", "%p Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON13, N_p("input-name", "%p Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON14, N_p("input-name", "%p Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON15, N_p("input-name", "%p Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON16, N_p("input-name", "%p Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, START, N_p("input-name", "%p Start"), input_seq(KEYCODE_2, input_seq::or_code, JOYCODE_START_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, SELECT, N_p("input-name", "%p Select"), input_seq(KEYCODE_6, input_seq::or_code, JOYCODE_SELECT_INDEXED(1)) ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_P2_MAHJONG \ CORE_INPUT_TYPES_BEGIN(p2_mahjong) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_A, N_p("input-name", "P2 Mahjong A"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_B, N_p("input-name", "P2 Mahjong B"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_C, N_p("input-name", "P2 Mahjong C"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_D, N_p("input-name", "P2 Mahjong D"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_E, N_p("input-name", "P2 Mahjong E"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_F, N_p("input-name", "P2 Mahjong F"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_G, N_p("input-name", "P2 Mahjong G"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_H, N_p("input-name", "P2 Mahjong H"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_I, N_p("input-name", "P2 Mahjong I"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_J, N_p("input-name", "P2 Mahjong J"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_K, N_p("input-name", "P2 Mahjong K"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_L, N_p("input-name", "P2 Mahjong L"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_M, N_p("input-name", "P2 Mahjong M"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_N, N_p("input-name", "P2 Mahjong N"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_O, N_p("input-name", "P2 Mahjong O"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_P, N_p("input-name", "P2 Mahjong P"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_Q, N_p("input-name", "P2 Mahjong Q"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_KAN, N_p("input-name", "P2 Mahjong Kan"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_PON, N_p("input-name", "P2 Mahjong Pon"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_CHI, N_p("input-name", "P2 Mahjong Chi"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_REACH, N_p("input-name", "P2 Mahjong Reach"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_RON, N_p("input-name", "P2 Mahjong Ron"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_BET, N_p("input-name", "P2 Mahjong Bet"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_LAST_CHANCE, N_p("input-name", "P2 Mahjong Last Chance"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_SCORE, N_p("input-name", "P2 Mahjong Take Score"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_DOUBLE_UP, N_p("input-name", "P2 Mahjong Double Up"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_FLIP_FLOP, N_p("input-name", "P2 Mahjong Flip Flop"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_BIG, N_p("input-name", "P2 Mahjong Big"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_SMALL, N_p("input-name", "P2 Mahjong Small"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_A, N_p("input-name", "%p Mahjong A"), input_seq(KEYCODE_A_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_B, N_p("input-name", "%p Mahjong B"), input_seq(KEYCODE_B_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_C, N_p("input-name", "%p Mahjong C"), input_seq(KEYCODE_C_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_D, N_p("input-name", "%p Mahjong D"), input_seq(KEYCODE_D_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_E, N_p("input-name", "%p Mahjong E"), input_seq(KEYCODE_E_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_F, N_p("input-name", "%p Mahjong F"), input_seq(KEYCODE_F_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_G, N_p("input-name", "%p Mahjong G"), input_seq(KEYCODE_G_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_H, N_p("input-name", "%p Mahjong H"), input_seq(KEYCODE_H_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_I, N_p("input-name", "%p Mahjong I"), input_seq(KEYCODE_I_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_J, N_p("input-name", "%p Mahjong J"), input_seq(KEYCODE_J_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_K, N_p("input-name", "%p Mahjong K"), input_seq(KEYCODE_K_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_L, N_p("input-name", "%p Mahjong L"), input_seq(KEYCODE_L_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_M, N_p("input-name", "%p Mahjong M"), input_seq(KEYCODE_M_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_N, N_p("input-name", "%p Mahjong N"), input_seq(KEYCODE_N_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_O, N_p("input-name", "%p Mahjong O"), input_seq(KEYCODE_O_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_P, N_p("input-name", "%p Mahjong P"), input_seq(KEYCODE_COLON_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_Q, N_p("input-name", "%p Mahjong Q"), input_seq(KEYCODE_Q_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_KAN, N_p("input-name", "%p Mahjong Kan"), input_seq(KEYCODE_LCONTROL_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_PON, N_p("input-name", "%p Mahjong Pon"), input_seq(KEYCODE_LALT_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_CHI, N_p("input-name", "%p Mahjong Chi"), input_seq(KEYCODE_SPACE_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_REACH, N_p("input-name", "%p Mahjong Reach"), input_seq(KEYCODE_LSHIFT_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_RON, N_p("input-name", "%p Mahjong Ron"), input_seq(KEYCODE_Z_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_FLIP_FLOP, N_p("input-name", "%p Mahjong Flip Flop"), input_seq(KEYCODE_Y_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_BET, N_p("input-name", "%p Mahjong Bet"), input_seq(KEYCODE_3_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_SCORE, N_p("input-name", "%p Mahjong Take Score"), input_seq(KEYCODE_RCONTROL_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_DOUBLE_UP, N_p("input-name", "%p Mahjong Double Up"), input_seq(KEYCODE_RSHIFT_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_BIG, N_p("input-name", "%p Mahjong Big"), input_seq(KEYCODE_ENTER_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_SMALL, N_p("input-name", "%p Mahjong Small"), input_seq(KEYCODE_BACKSPACE_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_LAST_CHANCE, N_p("input-name", "%p Mahjong Last Chance"), input_seq(KEYCODE_RALT_INDEXED(1)) ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_P2_HANAFUDA \ CORE_INPUT_TYPES_BEGIN(p2_hanafuda) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_A, N_p("input-name", "P2 Hanafuda A/1"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_B, N_p("input-name", "P2 Hanafuda B/2"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_C, N_p("input-name", "P2 Hanafuda C/3"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_D, N_p("input-name", "P2 Hanafuda D/4"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_E, N_p("input-name", "P2 Hanafuda E/5"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_F, N_p("input-name", "P2 Hanafuda F/6"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_G, N_p("input-name", "P2 Hanafuda G/7"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_H, N_p("input-name", "P2 Hanafuda H/8"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_YES, N_p("input-name", "P2 Hanafuda Yes"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_NO, N_p("input-name", "P2 Hanafuda No"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_A, N_p("input-name", "%p Hanafuda A/1"), input_seq(KEYCODE_A_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_B, N_p("input-name", "%p Hanafuda B/2"), input_seq(KEYCODE_B_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_C, N_p("input-name", "%p Hanafuda C/3"), input_seq(KEYCODE_C_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_D, N_p("input-name", "%p Hanafuda D/4"), input_seq(KEYCODE_D_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_E, N_p("input-name", "%p Hanafuda E/5"), input_seq(KEYCODE_E_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_F, N_p("input-name", "%p Hanafuda F/6"), input_seq(KEYCODE_F_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_G, N_p("input-name", "%p Hanafuda G/7"), input_seq(KEYCODE_G_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_H, N_p("input-name", "%p Hanafuda H/8"), input_seq(KEYCODE_H_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_YES, N_p("input-name", "%p Hanafuda Yes"), input_seq(KEYCODE_M_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_NO, N_p("input-name", "%p Hanafuda No"), input_seq(KEYCODE_N_INDEXED(1)) ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_P3 \ CORE_INPUT_TYPES_BEGIN(p3) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICK_UP, N_p("input-name", "P3 Up"), input_seq(KEYCODE_I, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICK_DOWN, N_p("input-name", "P3 Down"), input_seq(KEYCODE_K, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICK_LEFT, N_p("input-name", "P3 Left"), input_seq(KEYCODE_J, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICK_RIGHT, N_p("input-name", "P3 Right"), input_seq(KEYCODE_L, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKRIGHT_UP, N_p("input-name", "P3 Right Stick/Up"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKRIGHT_DOWN, N_p("input-name", "P3 Right Stick/Down"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKRIGHT_LEFT, N_p("input-name", "P3 Right Stick/Left"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKRIGHT_RIGHT, N_p("input-name", "P3 Right Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKLEFT_UP, N_p("input-name", "P3 Left Stick/Up"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKLEFT_DOWN, N_p("input-name", "P3 Left Stick/Down"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKLEFT_LEFT, N_p("input-name", "P3 Left Stick/Left"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKLEFT_RIGHT, N_p("input-name", "P3 Left Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON1, N_p("input-name", "P3 Button 1"), input_seq(KEYCODE_RCONTROL, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(2), input_seq::or_code, GUNCODE_BUTTON1_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON2, N_p("input-name", "P3 Button 2"), input_seq(KEYCODE_RSHIFT, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(2), input_seq::or_code, GUNCODE_BUTTON2_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON3, N_p("input-name", "P3 Button 3"), input_seq(KEYCODE_ENTER, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON4, N_p("input-name", "P3 Button 4"), input_seq(JOYCODE_BUTTON4_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON5, N_p("input-name", "P3 Button 5"), input_seq(JOYCODE_BUTTON5_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON6, N_p("input-name", "P3 Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON7, N_p("input-name", "P3 Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON8, N_p("input-name", "P3 Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON9, N_p("input-name", "P3 Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON10, N_p("input-name", "P3 Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON11, N_p("input-name", "P3 Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON12, N_p("input-name", "P3 Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON13, N_p("input-name", "P3 Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON14, N_p("input-name", "P3 Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON15, N_p("input-name", "P3 Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON16, N_p("input-name", "P3 Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, START, N_p("input-name", "P3 Start"), input_seq(KEYCODE_3, input_seq::or_code, JOYCODE_START_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, SELECT, N_p("input-name", "P3 Select"), input_seq(KEYCODE_7, input_seq::or_code, JOYCODE_SELECT_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq(KEYCODE_I, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq(KEYCODE_K, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq(KEYCODE_J, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq(KEYCODE_L, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKRIGHT_UP, N_p("input-name", "%p Right Stick/Up"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKRIGHT_DOWN, N_p("input-name", "%p Right Stick/Down"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKRIGHT_LEFT, N_p("input-name", "%p Right Stick/Left"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKRIGHT_RIGHT, N_p("input-name", "%p Right Stick/Right"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKLEFT_UP, N_p("input-name", "%p Left Stick/Up"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKLEFT_DOWN, N_p("input-name", "%p Left Stick/Down"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKLEFT_LEFT, N_p("input-name", "%p Left Stick/Left"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKLEFT_RIGHT, N_p("input-name", "%p Left Stick/Right"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON1, N_p("input-name", "%p Button 1"), input_seq(KEYCODE_RCONTROL, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(2), input_seq::or_code, GUNCODE_BUTTON1_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON2, N_p("input-name", "%p Button 2"), input_seq(KEYCODE_RSHIFT, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(2), input_seq::or_code, GUNCODE_BUTTON2_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON3, N_p("input-name", "%p Button 3"), input_seq(KEYCODE_ENTER, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON4, N_p("input-name", "%p Button 4"), input_seq(JOYCODE_BUTTON4_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON5, N_p("input-name", "%p Button 5"), input_seq(JOYCODE_BUTTON5_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON6, N_p("input-name", "%p Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON7, N_p("input-name", "%p Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON8, N_p("input-name", "%p Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON9, N_p("input-name", "%p Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON10, N_p("input-name", "%p Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON11, N_p("input-name", "%p Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON12, N_p("input-name", "%p Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON13, N_p("input-name", "%p Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON14, N_p("input-name", "%p Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON15, N_p("input-name", "%p Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON16, N_p("input-name", "%p Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, START, N_p("input-name", "%p Start"), input_seq(KEYCODE_3, input_seq::or_code, JOYCODE_START_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, SELECT, N_p("input-name", "%p Select"), input_seq(KEYCODE_7, input_seq::or_code, JOYCODE_SELECT_INDEXED(2)) ) \ + CORE_INPUT_TYPES_END() + +#define CORE_INPUT_TYPES_P3_MAHJONG \ + CORE_INPUT_TYPES_BEGIN(p3_mahjong) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_A, N_p("input-name", "%p Mahjong A"), input_seq(KEYCODE_A_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_B, N_p("input-name", "%p Mahjong B"), input_seq(KEYCODE_B_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_C, N_p("input-name", "%p Mahjong C"), input_seq(KEYCODE_C_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_D, N_p("input-name", "%p Mahjong D"), input_seq(KEYCODE_D_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_E, N_p("input-name", "%p Mahjong E"), input_seq(KEYCODE_E_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_F, N_p("input-name", "%p Mahjong F"), input_seq(KEYCODE_F_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_G, N_p("input-name", "%p Mahjong G"), input_seq(KEYCODE_G_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_H, N_p("input-name", "%p Mahjong H"), input_seq(KEYCODE_H_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_I, N_p("input-name", "%p Mahjong I"), input_seq(KEYCODE_I_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_J, N_p("input-name", "%p Mahjong J"), input_seq(KEYCODE_J_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_K, N_p("input-name", "%p Mahjong K"), input_seq(KEYCODE_K_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_L, N_p("input-name", "%p Mahjong L"), input_seq(KEYCODE_L_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_M, N_p("input-name", "%p Mahjong M"), input_seq(KEYCODE_M_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_N, N_p("input-name", "%p Mahjong N"), input_seq(KEYCODE_N_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_O, N_p("input-name", "%p Mahjong O"), input_seq(KEYCODE_O_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_P, N_p("input-name", "%p Mahjong P"), input_seq(KEYCODE_COLON_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_Q, N_p("input-name", "%p Mahjong Q"), input_seq(KEYCODE_Q_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_KAN, N_p("input-name", "%p Mahjong Kan"), input_seq(KEYCODE_LCONTROL_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_PON, N_p("input-name", "%p Mahjong Pon"), input_seq(KEYCODE_LALT_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_CHI, N_p("input-name", "%p Mahjong Chi"), input_seq(KEYCODE_SPACE_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_REACH, N_p("input-name", "%p Mahjong Reach"), input_seq(KEYCODE_LSHIFT_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_RON, N_p("input-name", "%p Mahjong Ron"), input_seq(KEYCODE_Z_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_FLIP_FLOP, N_p("input-name", "%p Mahjong Flip Flop"), input_seq(KEYCODE_Y_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_BET, N_p("input-name", "%p Mahjong Bet"), input_seq(KEYCODE_3_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_SCORE, N_p("input-name", "%p Mahjong Take Score"), input_seq(KEYCODE_RCONTROL_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_DOUBLE_UP, N_p("input-name", "%p Mahjong Double Up"), input_seq(KEYCODE_RSHIFT_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_BIG, N_p("input-name", "%p Mahjong Big"), input_seq(KEYCODE_ENTER_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_SMALL, N_p("input-name", "%p Mahjong Small"), input_seq(KEYCODE_BACKSPACE_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, MAHJONG_LAST_CHANCE, N_p("input-name", "%p Mahjong Last Chance"), input_seq(KEYCODE_RALT_INDEXED(2)) ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_P4 \ CORE_INPUT_TYPES_BEGIN(p4) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICK_UP, N_p("input-name", "P4 Up"), input_seq(KEYCODE_8_PAD, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICK_DOWN, N_p("input-name", "P4 Down"), input_seq(KEYCODE_2_PAD, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICK_LEFT, N_p("input-name", "P4 Left"), input_seq(KEYCODE_4_PAD, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICK_RIGHT, N_p("input-name", "P4 Right"), input_seq(KEYCODE_6_PAD, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKRIGHT_UP, N_p("input-name", "P4 Right Stick/Up"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKRIGHT_DOWN, N_p("input-name", "P4 Right Stick/Down"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKRIGHT_LEFT, N_p("input-name", "P4 Right Stick/Left"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKRIGHT_RIGHT, N_p("input-name", "P4 Right Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKLEFT_UP, N_p("input-name", "P4 Left Stick/Up"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKLEFT_DOWN, N_p("input-name", "P4 Left Stick/Down"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKLEFT_LEFT, N_p("input-name", "P4 Left Stick/Left"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKLEFT_RIGHT, N_p("input-name", "P4 Left Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON1, N_p("input-name", "P4 Button 1"), input_seq(KEYCODE_0_PAD, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON2, N_p("input-name", "P4 Button 2"), input_seq(KEYCODE_DEL_PAD, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON3, N_p("input-name", "P4 Button 3"), input_seq(KEYCODE_ENTER_PAD, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON4, N_p("input-name", "P4 Button 4"), input_seq(JOYCODE_BUTTON4_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON5, N_p("input-name", "P4 Button 5"), input_seq(JOYCODE_BUTTON5_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON6, N_p("input-name", "P4 Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON7, N_p("input-name", "P4 Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON8, N_p("input-name", "P4 Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON9, N_p("input-name", "P4 Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON10, N_p("input-name", "P4 Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON11, N_p("input-name", "P4 Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON12, N_p("input-name", "P4 Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON13, N_p("input-name", "P4 Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON14, N_p("input-name", "P4 Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON15, N_p("input-name", "P4 Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON16, N_p("input-name", "P4 Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, START, N_p("input-name", "P4 Start"), input_seq(KEYCODE_4, input_seq::or_code, JOYCODE_START_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, SELECT, N_p("input-name", "P4 Select"), input_seq(KEYCODE_8, input_seq::or_code, JOYCODE_SELECT_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq(KEYCODE_8_PAD, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq(KEYCODE_2_PAD, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq(KEYCODE_4_PAD, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq(KEYCODE_6_PAD, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKRIGHT_UP, N_p("input-name", "%p Right Stick/Up"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKRIGHT_DOWN, N_p("input-name", "%p Right Stick/Down"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKRIGHT_LEFT, N_p("input-name", "%p Right Stick/Left"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKRIGHT_RIGHT, N_p("input-name", "%p Right Stick/Right"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKLEFT_UP, N_p("input-name", "%p Left Stick/Up"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKLEFT_DOWN, N_p("input-name", "%p Left Stick/Down"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKLEFT_LEFT, N_p("input-name", "%p Left Stick/Left"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKLEFT_RIGHT, N_p("input-name", "%p Left Stick/Right"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON1, N_p("input-name", "%p Button 1"), input_seq(KEYCODE_0_PAD, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON2, N_p("input-name", "%p Button 2"), input_seq(KEYCODE_DEL_PAD, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON3, N_p("input-name", "%p Button 3"), input_seq(KEYCODE_ENTER_PAD, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON4, N_p("input-name", "%p Button 4"), input_seq(JOYCODE_BUTTON4_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON5, N_p("input-name", "%p Button 5"), input_seq(JOYCODE_BUTTON5_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON6, N_p("input-name", "%p Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON7, N_p("input-name", "%p Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON8, N_p("input-name", "%p Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON9, N_p("input-name", "%p Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON10, N_p("input-name", "%p Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON11, N_p("input-name", "%p Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON12, N_p("input-name", "%p Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON13, N_p("input-name", "%p Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON14, N_p("input-name", "%p Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON15, N_p("input-name", "%p Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON16, N_p("input-name", "%p Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, START, N_p("input-name", "%p Start"), input_seq(KEYCODE_4, input_seq::or_code, JOYCODE_START_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, SELECT, N_p("input-name", "%p Select"), input_seq(KEYCODE_8, input_seq::or_code, JOYCODE_SELECT_INDEXED(3)) ) \ + CORE_INPUT_TYPES_END() + +#define CORE_INPUT_TYPES_P4_MAHJONG \ + CORE_INPUT_TYPES_BEGIN(p4_mahjong) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_A, N_p("input-name", "%p Mahjong A"), input_seq(KEYCODE_A_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_B, N_p("input-name", "%p Mahjong B"), input_seq(KEYCODE_B_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_C, N_p("input-name", "%p Mahjong C"), input_seq(KEYCODE_C_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_D, N_p("input-name", "%p Mahjong D"), input_seq(KEYCODE_D_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_E, N_p("input-name", "%p Mahjong E"), input_seq(KEYCODE_E_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_F, N_p("input-name", "%p Mahjong F"), input_seq(KEYCODE_F_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_G, N_p("input-name", "%p Mahjong G"), input_seq(KEYCODE_G_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_H, N_p("input-name", "%p Mahjong H"), input_seq(KEYCODE_H_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_I, N_p("input-name", "%p Mahjong I"), input_seq(KEYCODE_I_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_J, N_p("input-name", "%p Mahjong J"), input_seq(KEYCODE_J_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_K, N_p("input-name", "%p Mahjong K"), input_seq(KEYCODE_K_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_L, N_p("input-name", "%p Mahjong L"), input_seq(KEYCODE_L_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_M, N_p("input-name", "%p Mahjong M"), input_seq(KEYCODE_M_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_N, N_p("input-name", "%p Mahjong N"), input_seq(KEYCODE_N_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_O, N_p("input-name", "%p Mahjong O"), input_seq(KEYCODE_O_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_P, N_p("input-name", "%p Mahjong P"), input_seq(KEYCODE_COLON_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_Q, N_p("input-name", "%p Mahjong Q"), input_seq(KEYCODE_Q_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_KAN, N_p("input-name", "%p Mahjong Kan"), input_seq(KEYCODE_LCONTROL_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_PON, N_p("input-name", "%p Mahjong Pon"), input_seq(KEYCODE_LALT_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_CHI, N_p("input-name", "%p Mahjong Chi"), input_seq(KEYCODE_SPACE_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_REACH, N_p("input-name", "%p Mahjong Reach"), input_seq(KEYCODE_LSHIFT_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_RON, N_p("input-name", "%p Mahjong Ron"), input_seq(KEYCODE_Z_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_FLIP_FLOP, N_p("input-name", "%p Mahjong Flip Flop"), input_seq(KEYCODE_Y_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_BET, N_p("input-name", "%p Mahjong Bet"), input_seq(KEYCODE_3_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_SCORE, N_p("input-name", "%p Mahjong Take Score"), input_seq(KEYCODE_RCONTROL_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_DOUBLE_UP, N_p("input-name", "%p Mahjong Double Up"), input_seq(KEYCODE_RSHIFT_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_BIG, N_p("input-name", "%p Mahjong Big"), input_seq(KEYCODE_ENTER_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_SMALL, N_p("input-name", "%p Mahjong Small"), input_seq(KEYCODE_BACKSPACE_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, MAHJONG_LAST_CHANCE, N_p("input-name", "%p Mahjong Last Chance"), input_seq(KEYCODE_RALT_INDEXED(3)) ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_P5 \ CORE_INPUT_TYPES_BEGIN(p5) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICK_UP, N_p("input-name", "P5 Up"), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICK_DOWN, N_p("input-name", "P5 Down"), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICK_LEFT, N_p("input-name", "P5 Left"), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICK_RIGHT, N_p("input-name", "P5 Right"), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKRIGHT_UP, N_p("input-name", "P5 Right Stick/Up"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKRIGHT_DOWN, N_p("input-name", "P5 Right Stick/Down"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKRIGHT_LEFT, N_p("input-name", "P5 Right Stick/Left"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKRIGHT_RIGHT, N_p("input-name", "P5 Right Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKLEFT_UP, N_p("input-name", "P5 Left Stick/Up"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKLEFT_DOWN, N_p("input-name", "P5 Left Stick/Down"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKLEFT_LEFT, N_p("input-name", "P5 Left Stick/Left"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKLEFT_RIGHT, N_p("input-name", "P5 Left Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON1, N_p("input-name", "P5 Button 1"), input_seq(JOYCODE_BUTTON1_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON2, N_p("input-name", "P5 Button 2"), input_seq(JOYCODE_BUTTON2_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON3, N_p("input-name", "P5 Button 3"), input_seq(JOYCODE_BUTTON3_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON4, N_p("input-name", "P5 Button 4"), input_seq(JOYCODE_BUTTON4_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON5, N_p("input-name", "P5 Button 5"), input_seq(JOYCODE_BUTTON5_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON6, N_p("input-name", "P5 Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON7, N_p("input-name", "P5 Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON8, N_p("input-name", "P5 Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON9, N_p("input-name", "P5 Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON10, N_p("input-name", "P5 Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON11, N_p("input-name", "P5 Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON12, N_p("input-name", "P5 Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON13, N_p("input-name", "P5 Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON14, N_p("input-name", "P5 Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON15, N_p("input-name", "P5 Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON16, N_p("input-name", "P5 Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, START, N_p("input-name", "P5 Start"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, SELECT, N_p("input-name", "P5 Select"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(4)) ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(4)) ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(4)) ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(4)) ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKRIGHT_UP, N_p("input-name", "%p Right Stick/Up"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKRIGHT_DOWN, N_p("input-name", "%p Right Stick/Down"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKRIGHT_LEFT, N_p("input-name", "%p Right Stick/Left"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKRIGHT_RIGHT, N_p("input-name", "%p Right Stick/Right"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKLEFT_UP, N_p("input-name", "%p Left Stick/Up"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKLEFT_DOWN, N_p("input-name", "%p Left Stick/Down"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKLEFT_LEFT, N_p("input-name", "%p Left Stick/Left"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKLEFT_RIGHT, N_p("input-name", "%p Left Stick/Right"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON1, N_p("input-name", "%p Button 1"), input_seq(JOYCODE_BUTTON1_INDEXED(4)) ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON2, N_p("input-name", "%p Button 2"), input_seq(JOYCODE_BUTTON2_INDEXED(4)) ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON3, N_p("input-name", "%p Button 3"), input_seq(JOYCODE_BUTTON3_INDEXED(4)) ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON4, N_p("input-name", "%p Button 4"), input_seq(JOYCODE_BUTTON4_INDEXED(4)) ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON5, N_p("input-name", "%p Button 5"), input_seq(JOYCODE_BUTTON5_INDEXED(4)) ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON6, N_p("input-name", "%p Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(4)) ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON7, N_p("input-name", "%p Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(4)) ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON8, N_p("input-name", "%p Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(4)) ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON9, N_p("input-name", "%p Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(4)) ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON10, N_p("input-name", "%p Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(4)) ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON11, N_p("input-name", "%p Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(4)) ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON12, N_p("input-name", "%p Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(4)) ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON13, N_p("input-name", "%p Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(4)) ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON14, N_p("input-name", "%p Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(4)) ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON15, N_p("input-name", "%p Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(4)) ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON16, N_p("input-name", "%p Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(4)) ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, START, N_p("input-name", "%p Start"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, SELECT, N_p("input-name", "%p Select"), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_P6 \ CORE_INPUT_TYPES_BEGIN(p6) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICK_UP, N_p("input-name", "P6 Up"), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICK_DOWN, N_p("input-name", "P6 Down"), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICK_LEFT, N_p("input-name", "P6 Left"), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICK_RIGHT, N_p("input-name", "P6 Right"), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKRIGHT_UP, N_p("input-name", "P6 Right Stick/Up"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKRIGHT_DOWN, N_p("input-name", "P6 Right Stick/Down"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKRIGHT_LEFT, N_p("input-name", "P6 Right Stick/Left"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKRIGHT_RIGHT, N_p("input-name", "P6 Right Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKLEFT_UP, N_p("input-name", "P6 Left Stick/Up"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKLEFT_DOWN, N_p("input-name", "P6 Left Stick/Down"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKLEFT_LEFT, N_p("input-name", "P6 Left Stick/Left"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKLEFT_RIGHT, N_p("input-name", "P6 Left Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON1, N_p("input-name", "P6 Button 1"), input_seq(JOYCODE_BUTTON1_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON2, N_p("input-name", "P6 Button 2"), input_seq(JOYCODE_BUTTON2_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON3, N_p("input-name", "P6 Button 3"), input_seq(JOYCODE_BUTTON3_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON4, N_p("input-name", "P6 Button 4"), input_seq(JOYCODE_BUTTON4_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON5, N_p("input-name", "P6 Button 5"), input_seq(JOYCODE_BUTTON5_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON6, N_p("input-name", "P6 Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON7, N_p("input-name", "P6 Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON8, N_p("input-name", "P6 Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON9, N_p("input-name", "P6 Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON10, N_p("input-name", "P6 Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON11, N_p("input-name", "P6 Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON12, N_p("input-name", "P6 Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON13, N_p("input-name", "P6 Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON14, N_p("input-name", "P6 Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON15, N_p("input-name", "P6 Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON16, N_p("input-name", "P6 Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, START, N_p("input-name", "P6 Start"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, SELECT, N_p("input-name", "P6 Select"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(5)) ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(5)) ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(5)) ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(5)) ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKRIGHT_UP, N_p("input-name", "%p Right Stick/Up"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKRIGHT_DOWN, N_p("input-name", "%p Right Stick/Down"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKRIGHT_LEFT, N_p("input-name", "%p Right Stick/Left"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKRIGHT_RIGHT, N_p("input-name", "%p Right Stick/Right"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKLEFT_UP, N_p("input-name", "%p Left Stick/Up"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKLEFT_DOWN, N_p("input-name", "%p Left Stick/Down"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKLEFT_LEFT, N_p("input-name", "%p Left Stick/Left"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKLEFT_RIGHT, N_p("input-name", "%p Left Stick/Right"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON1, N_p("input-name", "%p Button 1"), input_seq(JOYCODE_BUTTON1_INDEXED(5)) ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON2, N_p("input-name", "%p Button 2"), input_seq(JOYCODE_BUTTON2_INDEXED(5)) ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON3, N_p("input-name", "%p Button 3"), input_seq(JOYCODE_BUTTON3_INDEXED(5)) ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON4, N_p("input-name", "%p Button 4"), input_seq(JOYCODE_BUTTON4_INDEXED(5)) ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON5, N_p("input-name", "%p Button 5"), input_seq(JOYCODE_BUTTON5_INDEXED(5)) ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON6, N_p("input-name", "%p Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(5)) ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON7, N_p("input-name", "%p Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(5)) ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON8, N_p("input-name", "%p Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(5)) ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON9, N_p("input-name", "%p Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(5)) ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON10, N_p("input-name", "%p Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(5)) ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON11, N_p("input-name", "%p Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(5)) ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON12, N_p("input-name", "%p Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(5)) ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON13, N_p("input-name", "%p Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(5)) ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON14, N_p("input-name", "%p Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(5)) ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON15, N_p("input-name", "%p Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(5)) ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON16, N_p("input-name", "%p Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(5)) ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, START, N_p("input-name", "%p Start"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, SELECT, N_p("input-name", "%p Select"), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_P7 \ CORE_INPUT_TYPES_BEGIN(p7) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICK_UP, N_p("input-name", "P7 Up"), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICK_DOWN, N_p("input-name", "P7 Down"), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICK_LEFT, N_p("input-name", "P7 Left"), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICK_RIGHT, N_p("input-name", "P7 Right"), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKRIGHT_UP, N_p("input-name", "P7 Right Stick/Up"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKRIGHT_DOWN, N_p("input-name", "P7 Right Stick/Down"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKRIGHT_LEFT, N_p("input-name", "P7 Right Stick/Left"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKRIGHT_RIGHT, N_p("input-name", "P7 Right Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKLEFT_UP, N_p("input-name", "P7 Left Stick/Up"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKLEFT_DOWN, N_p("input-name", "P7 Left Stick/Down"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKLEFT_LEFT, N_p("input-name", "P7 Left Stick/Left"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKLEFT_RIGHT, N_p("input-name", "P7 Left Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON1, N_p("input-name", "P7 Button 1"), input_seq(JOYCODE_BUTTON1_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON2, N_p("input-name", "P7 Button 2"), input_seq(JOYCODE_BUTTON2_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON3, N_p("input-name", "P7 Button 3"), input_seq(JOYCODE_BUTTON3_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON4, N_p("input-name", "P7 Button 4"), input_seq(JOYCODE_BUTTON4_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON5, N_p("input-name", "P7 Button 5"), input_seq(JOYCODE_BUTTON5_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON6, N_p("input-name", "P7 Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON7, N_p("input-name", "P7 Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON8, N_p("input-name", "P7 Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON9, N_p("input-name", "P7 Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON10, N_p("input-name", "P7 Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON11, N_p("input-name", "P7 Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON12, N_p("input-name", "P7 Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON13, N_p("input-name", "P7 Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON14, N_p("input-name", "P7 Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON15, N_p("input-name", "P7 Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON16, N_p("input-name", "P7 Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, START, N_p("input-name", "P7 Start"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, SELECT, N_p("input-name", "P7 Select"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(6)) ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(6)) ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(6)) ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(6)) ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKRIGHT_UP, N_p("input-name", "%p Right Stick/Up"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKRIGHT_DOWN, N_p("input-name", "%p Right Stick/Down"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKRIGHT_LEFT, N_p("input-name", "%p Right Stick/Left"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKRIGHT_RIGHT, N_p("input-name", "%p Right Stick/Right"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKLEFT_UP, N_p("input-name", "%p Left Stick/Up"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKLEFT_DOWN, N_p("input-name", "%p Left Stick/Down"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKLEFT_LEFT, N_p("input-name", "%p Left Stick/Left"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKLEFT_RIGHT, N_p("input-name", "%p Left Stick/Right"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON1, N_p("input-name", "%p Button 1"), input_seq(JOYCODE_BUTTON1_INDEXED(6)) ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON2, N_p("input-name", "%p Button 2"), input_seq(JOYCODE_BUTTON2_INDEXED(6)) ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON3, N_p("input-name", "%p Button 3"), input_seq(JOYCODE_BUTTON3_INDEXED(6)) ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON4, N_p("input-name", "%p Button 4"), input_seq(JOYCODE_BUTTON4_INDEXED(6)) ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON5, N_p("input-name", "%p Button 5"), input_seq(JOYCODE_BUTTON5_INDEXED(6)) ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON6, N_p("input-name", "%p Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(6)) ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON7, N_p("input-name", "%p Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(6)) ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON8, N_p("input-name", "%p Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(6)) ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON9, N_p("input-name", "%p Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(6)) ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON10, N_p("input-name", "%p Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(6)) ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON11, N_p("input-name", "%p Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(6)) ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON12, N_p("input-name", "%p Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(6)) ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON13, N_p("input-name", "%p Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(6)) ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON14, N_p("input-name", "%p Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(6)) ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON15, N_p("input-name", "%p Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(6)) ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON16, N_p("input-name", "%p Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(6)) ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, START, N_p("input-name", "%p Start"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, SELECT, N_p("input-name", "%p Select"), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_P8 \ CORE_INPUT_TYPES_BEGIN(p8) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICK_UP, N_p("input-name", "P8 Up"), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICK_DOWN, N_p("input-name", "P8 Down"), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICK_LEFT, N_p("input-name", "P8 Left"), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICK_RIGHT, N_p("input-name", "P8 Right"), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKRIGHT_UP, N_p("input-name", "P8 Right Stick/Up"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKRIGHT_DOWN, N_p("input-name", "P8 Right Stick/Down"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKRIGHT_LEFT, N_p("input-name", "P8 Right Stick/Left"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKRIGHT_RIGHT, N_p("input-name", "P8 Right Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKLEFT_UP, N_p("input-name", "P8 Left Stick/Up"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKLEFT_DOWN, N_p("input-name", "P8 Left Stick/Down"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKLEFT_LEFT, N_p("input-name", "P8 Left Stick/Left"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKLEFT_RIGHT, N_p("input-name", "P8 Left Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON1, N_p("input-name", "P8 Button 1"), input_seq(JOYCODE_BUTTON1_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON2, N_p("input-name", "P8 Button 2"), input_seq(JOYCODE_BUTTON2_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON3, N_p("input-name", "P8 Button 3"), input_seq(JOYCODE_BUTTON3_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON4, N_p("input-name", "P8 Button 4"), input_seq(JOYCODE_BUTTON4_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON5, N_p("input-name", "P8 Button 5"), input_seq(JOYCODE_BUTTON5_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON6, N_p("input-name", "P8 Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON7, N_p("input-name", "P8 Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON8, N_p("input-name", "P8 Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON9, N_p("input-name", "P8 Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON10, N_p("input-name", "P8 Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON11, N_p("input-name", "P8 Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON12, N_p("input-name", "P8 Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON13, N_p("input-name", "P8 Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON14, N_p("input-name", "P8 Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON15, N_p("input-name", "P8 Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON16, N_p("input-name", "P8 Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, START, N_p("input-name", "P8 Start"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, SELECT, N_p("input-name", "P8 Select"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(7)) ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(7)) ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(7)) ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(7)) ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKRIGHT_UP, N_p("input-name", "%p Right Stick/Up"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKRIGHT_DOWN, N_p("input-name", "%p Right Stick/Down"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKRIGHT_LEFT, N_p("input-name", "%p Right Stick/Left"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKRIGHT_RIGHT, N_p("input-name", "%p Right Stick/Right"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKLEFT_UP, N_p("input-name", "%p Left Stick/Up"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKLEFT_DOWN, N_p("input-name", "%p Left Stick/Down"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKLEFT_LEFT, N_p("input-name", "%p Left Stick/Left"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKLEFT_RIGHT, N_p("input-name", "%p Left Stick/Right"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON1, N_p("input-name", "%p Button 1"), input_seq(JOYCODE_BUTTON1_INDEXED(7)) ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON2, N_p("input-name", "%p Button 2"), input_seq(JOYCODE_BUTTON2_INDEXED(7)) ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON3, N_p("input-name", "%p Button 3"), input_seq(JOYCODE_BUTTON3_INDEXED(7)) ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON4, N_p("input-name", "%p Button 4"), input_seq(JOYCODE_BUTTON4_INDEXED(7)) ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON5, N_p("input-name", "%p Button 5"), input_seq(JOYCODE_BUTTON5_INDEXED(7)) ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON6, N_p("input-name", "%p Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(7)) ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON7, N_p("input-name", "%p Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(7)) ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON8, N_p("input-name", "%p Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(7)) ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON9, N_p("input-name", "%p Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(7)) ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON10, N_p("input-name", "%p Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(7)) ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON11, N_p("input-name", "%p Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(7)) ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON12, N_p("input-name", "%p Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(7)) ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON13, N_p("input-name", "%p Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(7)) ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON14, N_p("input-name", "%p Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(7)) ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON15, N_p("input-name", "%p Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(7)) ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON16, N_p("input-name", "%p Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(7)) ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, START, N_p("input-name", "%p Start"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, SELECT, N_p("input-name", "%p Select"), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_P9 \ CORE_INPUT_TYPES_BEGIN(p9) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICK_UP, N_p("input-name", "P9 Up"), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICK_DOWN, N_p("input-name", "P9 Down"), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICK_LEFT, N_p("input-name", "P9 Left"), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICK_RIGHT, N_p("input-name", "P9 Right"), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICKRIGHT_UP, N_p("input-name", "P9 Right Stick/Up"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICKRIGHT_DOWN, N_p("input-name", "P9 Right Stick/Down"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICKRIGHT_LEFT, N_p("input-name", "P9 Right Stick/Left"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICKRIGHT_RIGHT, N_p("input-name", "P9 Right Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICKLEFT_UP, N_p("input-name", "P9 Left Stick/Up"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICKLEFT_DOWN, N_p("input-name", "P9 Left Stick/Down"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICKLEFT_LEFT, N_p("input-name", "P9 Left Stick/Left"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICKLEFT_RIGHT, N_p("input-name", "P9 Left Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON1, N_p("input-name", "P9 Button 1"), input_seq(JOYCODE_BUTTON1_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON2, N_p("input-name", "P9 Button 2"), input_seq(JOYCODE_BUTTON2_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON3, N_p("input-name", "P9 Button 3"), input_seq(JOYCODE_BUTTON3_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON4, N_p("input-name", "P9 Button 4"), input_seq(JOYCODE_BUTTON4_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON5, N_p("input-name", "P9 Button 5"), input_seq(JOYCODE_BUTTON5_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON6, N_p("input-name", "P9 Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON7, N_p("input-name", "P9 Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON8, N_p("input-name", "P9 Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON9, N_p("input-name", "P9 Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON10, N_p("input-name", "P9 Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON11, N_p("input-name", "P9 Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON12, N_p("input-name", "P9 Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON13, N_p("input-name", "P9 Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON14, N_p("input-name", "P9 Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON15, N_p("input-name", "P9 Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON16, N_p("input-name", "P9 Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, START, N_p("input-name", "P9 Start"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, SELECT, N_p("input-name", "P9 Select"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(8)) ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(8)) ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(8)) ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(8)) ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICKRIGHT_UP, N_p("input-name", "%p Right Stick/Up"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICKRIGHT_DOWN, N_p("input-name", "%p Right Stick/Down"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICKRIGHT_LEFT, N_p("input-name", "%p Right Stick/Left"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICKRIGHT_RIGHT, N_p("input-name", "%p Right Stick/Right"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICKLEFT_UP, N_p("input-name", "%p Left Stick/Up"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICKLEFT_DOWN, N_p("input-name", "%p Left Stick/Down"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICKLEFT_LEFT, N_p("input-name", "%p Left Stick/Left"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICKLEFT_RIGHT, N_p("input-name", "%p Left Stick/Right"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON1, N_p("input-name", "%p Button 1"), input_seq(JOYCODE_BUTTON1_INDEXED(8)) ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON2, N_p("input-name", "%p Button 2"), input_seq(JOYCODE_BUTTON2_INDEXED(8)) ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON3, N_p("input-name", "%p Button 3"), input_seq(JOYCODE_BUTTON3_INDEXED(8)) ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON4, N_p("input-name", "%p Button 4"), input_seq(JOYCODE_BUTTON4_INDEXED(8)) ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON5, N_p("input-name", "%p Button 5"), input_seq(JOYCODE_BUTTON5_INDEXED(8)) ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON6, N_p("input-name", "%p Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(8)) ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON7, N_p("input-name", "%p Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(8)) ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON8, N_p("input-name", "%p Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(8)) ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON9, N_p("input-name", "%p Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(8)) ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON10, N_p("input-name", "%p Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(8)) ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON11, N_p("input-name", "%p Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(8)) ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON12, N_p("input-name", "%p Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(8)) ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON13, N_p("input-name", "%p Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(8)) ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON14, N_p("input-name", "%p Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(8)) ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON15, N_p("input-name", "%p Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(8)) ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON16, N_p("input-name", "%p Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(8)) ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, START, N_p("input-name", "%p Start"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, SELECT, N_p("input-name", "%p Select"), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_P10 \ CORE_INPUT_TYPES_BEGIN(p10) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICK_UP, N_p("input-name", "P10 Up"), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICK_DOWN, N_p("input-name", "P10 Down"), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICK_LEFT, N_p("input-name", "P10 Left"), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICK_RIGHT, N_p("input-name", "P10 Right"), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICKRIGHT_UP, N_p("input-name", "P10 Right Stick/Up"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICKRIGHT_DOWN, N_p("input-name", "P10 Right Stick/Down"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICKRIGHT_LEFT, N_p("input-name", "P10 Right Stick/Left"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICKRIGHT_RIGHT, N_p("input-name", "P10 Right Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICKLEFT_UP, N_p("input-name", "P10 Left Stick/Up"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICKLEFT_DOWN, N_p("input-name", "P10 Left Stick/Down"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICKLEFT_LEFT, N_p("input-name", "P10 Left Stick/Left"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICKLEFT_RIGHT, N_p("input-name", "P10 Left Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON1, N_p("input-name", "P10 Button 1"), input_seq(JOYCODE_BUTTON1_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON2, N_p("input-name", "P10 Button 2"), input_seq(JOYCODE_BUTTON2_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON3, N_p("input-name", "P10 Button 3"), input_seq(JOYCODE_BUTTON3_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON4, N_p("input-name", "P10 Button 4"), input_seq(JOYCODE_BUTTON4_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON5, N_p("input-name", "P10 Button 5"), input_seq(JOYCODE_BUTTON5_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON6, N_p("input-name", "P10 Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON7, N_p("input-name", "P10 Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON8, N_p("input-name", "P10 Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON9, N_p("input-name", "P10 Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON10, N_p("input-name", "P10 Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON11, N_p("input-name", "P10 Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON12, N_p("input-name", "P10 Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON13, N_p("input-name", "P10 Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON14, N_p("input-name", "P10 Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON15, N_p("input-name", "P10 Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON16, N_p("input-name", "P10 Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, START, N_p("input-name", "P10 Start"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, SELECT, N_p("input-name", "P10 Select"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(9)) ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(9)) ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(9)) ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(9)) ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICKRIGHT_UP, N_p("input-name", "%p Right Stick/Up"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICKRIGHT_DOWN, N_p("input-name", "%p Right Stick/Down"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICKRIGHT_LEFT, N_p("input-name", "%p Right Stick/Left"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICKRIGHT_RIGHT, N_p("input-name", "%p Right Stick/Right"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICKLEFT_UP, N_p("input-name", "%p Left Stick/Up"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICKLEFT_DOWN, N_p("input-name", "%p Left Stick/Down"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICKLEFT_LEFT, N_p("input-name", "%p Left Stick/Left"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICKLEFT_RIGHT, N_p("input-name", "%p Left Stick/Right"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON1, N_p("input-name", "%p Button 1"), input_seq(JOYCODE_BUTTON1_INDEXED(9)) ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON2, N_p("input-name", "%p Button 2"), input_seq(JOYCODE_BUTTON2_INDEXED(9)) ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON3, N_p("input-name", "%p Button 3"), input_seq(JOYCODE_BUTTON3_INDEXED(9)) ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON4, N_p("input-name", "%p Button 4"), input_seq(JOYCODE_BUTTON4_INDEXED(9)) ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON5, N_p("input-name", "%p Button 5"), input_seq(JOYCODE_BUTTON5_INDEXED(9)) ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON6, N_p("input-name", "%p Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(9)) ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON7, N_p("input-name", "%p Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(9)) ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON8, N_p("input-name", "%p Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(9)) ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON9, N_p("input-name", "%p Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(9)) ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON10, N_p("input-name", "%p Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(9)) ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON11, N_p("input-name", "%p Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(9)) ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON12, N_p("input-name", "%p Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(9)) ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON13, N_p("input-name", "%p Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(9)) ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON14, N_p("input-name", "%p Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(9)) ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON15, N_p("input-name", "%p Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(9)) ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON16, N_p("input-name", "%p Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(9)) ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, START, N_p("input-name", "%p Start"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, SELECT, N_p("input-name", "%p Select"), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_START \ @@ -547,44 +613,44 @@ namespace { #define CORE_INPUT_TYPES_PEDAL \ CORE_INPUT_TYPES_BEGIN(pedal) \ - INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, PEDAL, N_p("input-name", "P1 Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(0)), input_seq(), input_seq(KEYCODE_LCONTROL, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(0)) ) \ - INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, PEDAL, N_p("input-name", "P2 Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(1)), input_seq(), input_seq(KEYCODE_A, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(1)) ) \ - INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, PEDAL, N_p("input-name", "P3 Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(2)), input_seq(), input_seq(KEYCODE_RCONTROL, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(2)) ) \ - INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, PEDAL, N_p("input-name", "P4 Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(3)), input_seq(), input_seq(KEYCODE_0_PAD, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(3)) ) \ - INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, PEDAL, N_p("input-name", "P5 Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(4)), input_seq(), input_seq(JOYCODE_BUTTON1_INDEXED(4)) ) \ - INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, PEDAL, N_p("input-name", "P6 Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(5)), input_seq(), input_seq(JOYCODE_BUTTON1_INDEXED(5)) ) \ - INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, PEDAL, N_p("input-name", "P7 Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(6)), input_seq(), input_seq(JOYCODE_BUTTON1_INDEXED(6)) ) \ - INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, PEDAL, N_p("input-name", "P8 Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(7)), input_seq(), input_seq(JOYCODE_BUTTON1_INDEXED(7)) ) \ - INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, PEDAL, N_p("input-name", "P9 Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(8)), input_seq(), input_seq(JOYCODE_BUTTON1_INDEXED(8)) ) \ - INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, PEDAL, N_p("input-name", "P10 Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(9)), input_seq(), input_seq(JOYCODE_BUTTON1_INDEXED(9)) ) \ + INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(0)), input_seq(), input_seq(KEYCODE_LCONTROL, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(0)) ) \ + INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(1)), input_seq(), input_seq(KEYCODE_A, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(1)) ) \ + INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(2)), input_seq(), input_seq(KEYCODE_RCONTROL, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(2)) ) \ + INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(3)), input_seq(), input_seq(KEYCODE_0_PAD, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(3)) ) \ + INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(4)), input_seq(), input_seq(JOYCODE_BUTTON1_INDEXED(4)) ) \ + INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(5)), input_seq(), input_seq(JOYCODE_BUTTON1_INDEXED(5)) ) \ + INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(6)), input_seq(), input_seq(JOYCODE_BUTTON1_INDEXED(6)) ) \ + INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(7)), input_seq(), input_seq(JOYCODE_BUTTON1_INDEXED(7)) ) \ + INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(8)), input_seq(), input_seq(JOYCODE_BUTTON1_INDEXED(8)) ) \ + INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(9)), input_seq(), input_seq(JOYCODE_BUTTON1_INDEXED(9)) ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_PEDAL2 \ CORE_INPUT_TYPES_BEGIN(pedal2) \ - INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, PEDAL2, N_p("input-name", "P1 Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(0)), input_seq(), input_seq(KEYCODE_LALT, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(0)) ) \ - INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, PEDAL2, N_p("input-name", "P2 Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(1)), input_seq(), input_seq(KEYCODE_S, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(1)) ) \ - INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, PEDAL2, N_p("input-name", "P3 Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(2)), input_seq(), input_seq(KEYCODE_RSHIFT, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(2)) ) \ - INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, PEDAL2, N_p("input-name", "P4 Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(3)), input_seq(), input_seq(KEYCODE_DEL_PAD, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(3)) ) \ - INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, PEDAL2, N_p("input-name", "P5 Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(4)), input_seq(), input_seq(JOYCODE_BUTTON2_INDEXED(4)) ) \ - INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, PEDAL2, N_p("input-name", "P6 Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(5)), input_seq(), input_seq(JOYCODE_BUTTON2_INDEXED(5)) ) \ - INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, PEDAL2, N_p("input-name", "P7 Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(6)), input_seq(), input_seq(JOYCODE_BUTTON2_INDEXED(6)) ) \ - INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, PEDAL2, N_p("input-name", "P8 Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(7)), input_seq(), input_seq(JOYCODE_BUTTON2_INDEXED(7)) ) \ - INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, PEDAL2, N_p("input-name", "P9 Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(8)), input_seq(), input_seq(JOYCODE_BUTTON2_INDEXED(8)) ) \ - INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, PEDAL2, N_p("input-name", "P10 Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(9)), input_seq(), input_seq(JOYCODE_BUTTON2_INDEXED(9)) ) \ + INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(0)), input_seq(), input_seq(KEYCODE_LALT, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(0)) ) \ + INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(1)), input_seq(), input_seq(KEYCODE_S, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(1)) ) \ + INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(2)), input_seq(), input_seq(KEYCODE_RSHIFT, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(2)) ) \ + INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(3)), input_seq(), input_seq(KEYCODE_DEL_PAD, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(3)) ) \ + INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(4)), input_seq(), input_seq(JOYCODE_BUTTON2_INDEXED(4)) ) \ + INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(5)), input_seq(), input_seq(JOYCODE_BUTTON2_INDEXED(5)) ) \ + INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(6)), input_seq(), input_seq(JOYCODE_BUTTON2_INDEXED(6)) ) \ + INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(7)), input_seq(), input_seq(JOYCODE_BUTTON2_INDEXED(7)) ) \ + INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(8)), input_seq(), input_seq(JOYCODE_BUTTON2_INDEXED(8)) ) \ + INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(9)), input_seq(), input_seq(JOYCODE_BUTTON2_INDEXED(9)) ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_PEDAL3 \ CORE_INPUT_TYPES_BEGIN(pedal3) \ - INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, PEDAL3, N_p("input-name", "P1 Pedal 3"), input_seq(), input_seq(), input_seq(KEYCODE_SPACE, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(0)) ) \ - INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, PEDAL3, N_p("input-name", "P2 Pedal 3"), input_seq(), input_seq(), input_seq(KEYCODE_Q, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(1)) ) \ - INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, PEDAL3, N_p("input-name", "P3 Pedal 3"), input_seq(), input_seq(), input_seq(KEYCODE_ENTER, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(2)) ) \ - INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, PEDAL3, N_p("input-name", "P4 Pedal 3"), input_seq(), input_seq(), input_seq(KEYCODE_ENTER_PAD, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(3)) ) \ - INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, PEDAL3, N_p("input-name", "P5 Pedal 3"), input_seq(), input_seq(), input_seq(JOYCODE_BUTTON3_INDEXED(4)) ) \ - INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, PEDAL3, N_p("input-name", "P6 Pedal 3"), input_seq(), input_seq(), input_seq(JOYCODE_BUTTON3_INDEXED(5)) ) \ - INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, PEDAL3, N_p("input-name", "P7 Pedal 3"), input_seq(), input_seq(), input_seq(JOYCODE_BUTTON3_INDEXED(6)) ) \ - INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, PEDAL3, N_p("input-name", "P8 Pedal 3"), input_seq(), input_seq(), input_seq(JOYCODE_BUTTON3_INDEXED(7)) ) \ - INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, PEDAL3, N_p("input-name", "P9 Pedal 3"), input_seq(), input_seq(), input_seq(JOYCODE_BUTTON3_INDEXED(8)) ) \ - INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, PEDAL3, N_p("input-name", "P10 Pedal 3"), input_seq(), input_seq(), input_seq(JOYCODE_BUTTON3_INDEXED(9)) ) \ + INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq(KEYCODE_SPACE, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(0)) ) \ + INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq(KEYCODE_Q, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(1)) ) \ + INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq(KEYCODE_ENTER, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(2)) ) \ + INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq(KEYCODE_ENTER_PAD, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(3)) ) \ + INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq(JOYCODE_BUTTON3_INDEXED(4)) ) \ + INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq(JOYCODE_BUTTON3_INDEXED(5)) ) \ + INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq(JOYCODE_BUTTON3_INDEXED(6)) ) \ + INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq(JOYCODE_BUTTON3_INDEXED(7)) ) \ + INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq(JOYCODE_BUTTON3_INDEXED(8)) ) \ + INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq(JOYCODE_BUTTON3_INDEXED(9)) ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_PADDLE \ @@ -920,7 +986,9 @@ CORE_INPUT_TYPES_P2 CORE_INPUT_TYPES_P2_MAHJONG CORE_INPUT_TYPES_P2_HANAFUDA CORE_INPUT_TYPES_P3 +CORE_INPUT_TYPES_P3_MAHJONG CORE_INPUT_TYPES_P4 +CORE_INPUT_TYPES_P4_MAHJONG CORE_INPUT_TYPES_P5 CORE_INPUT_TYPES_P6 CORE_INPUT_TYPES_P7 @@ -978,7 +1046,9 @@ constexpr size_t core_input_types_count() CORE_INPUT_TYPES_P2_MAHJONG CORE_INPUT_TYPES_P2_HANAFUDA CORE_INPUT_TYPES_P3 + CORE_INPUT_TYPES_P3_MAHJONG CORE_INPUT_TYPES_P4 + CORE_INPUT_TYPES_P4_MAHJONG CORE_INPUT_TYPES_P5 CORE_INPUT_TYPES_P6 CORE_INPUT_TYPES_P7 @@ -1034,7 +1104,9 @@ ATTR_COLD inline void emplace_core_types(std::vector<input_type_entry> &typelist emplace_core_types_p2_mahjong(typelist); emplace_core_types_p2_hanafuda(typelist); emplace_core_types_p3(typelist); + emplace_core_types_p3_mahjong(typelist); emplace_core_types_p4(typelist); + emplace_core_types_p4_mahjong(typelist); emplace_core_types_p5(typelist); emplace_core_types_p6(typelist); emplace_core_types_p7(typelist); diff --git a/src/emu/input.cpp b/src/emu/input.cpp index 5c49d1c2dab..169f76aabe3 100644 --- a/src/emu/input.cpp +++ b/src/emu/input.cpp @@ -860,7 +860,7 @@ std::string input_manager::code_to_token(input_code code) const std::string str(devclass); if (!devindex.empty()) str.append("_").append(devindex); - if (devcode[0] != 0) + if (!devcode.empty()) str.append("_").append(devcode); if (modifier != nullptr) str.append("_").append(modifier); @@ -1150,7 +1150,7 @@ input_seq input_manager::seq_clean(const input_seq &seq) const { // if this is a code item which is not valid, don't copy it and remove any preceding ORs/NOTs input_code code = seq[codenum]; - if (!code.internal() && code_name(code).empty()) + if (!code.internal() && (((code.device_index() > 0) && !m_class[code.device_class()]->multi()) || !item_from_code(code))) { while (clean_index > 0 && clean_codes[clean_index - 1].internal()) { diff --git a/src/emu/ioport.cpp b/src/emu/ioport.cpp index 0ea7974caf5..5999a75abe5 100644 --- a/src/emu/ioport.cpp +++ b/src/emu/ioport.cpp @@ -93,6 +93,7 @@ #include "emu.h" #include "emuopts.h" #include "config.h" +#include "fileio.h" #include "xmlfile.h" #include "profiler.h" #include "ui/uimain.h" @@ -101,6 +102,7 @@ #include "util/corestr.h" #include "util/ioprocsfilter.h" +#include "util/language.h" #include "util/unicode.h" #include "osdepend.h" @@ -307,6 +309,148 @@ 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; +} + + + +// ======================> inp_header + +// header at the front of INP files +class inp_header +{ +public: + // parameters + static constexpr unsigned MAJVERSION = 3; + static constexpr unsigned MINVERSION = 0; + + bool read(emu_file &f) + { + return f.read(m_data, sizeof(m_data)) == sizeof(m_data); + } + bool write(emu_file &f) const + { + return f.write(m_data, sizeof(m_data)) == sizeof(m_data); + } + + bool check_magic() const + { + return 0 == std::memcmp(MAGIC, m_data + OFFS_MAGIC, OFFS_BASETIME - OFFS_MAGIC); + } + u64 get_basetime() const + { + return + (u64(m_data[OFFS_BASETIME + 0]) << (0 * 8)) | + (u64(m_data[OFFS_BASETIME + 1]) << (1 * 8)) | + (u64(m_data[OFFS_BASETIME + 2]) << (2 * 8)) | + (u64(m_data[OFFS_BASETIME + 3]) << (3 * 8)) | + (u64(m_data[OFFS_BASETIME + 4]) << (4 * 8)) | + (u64(m_data[OFFS_BASETIME + 5]) << (5 * 8)) | + (u64(m_data[OFFS_BASETIME + 6]) << (6 * 8)) | + (u64(m_data[OFFS_BASETIME + 7]) << (7 * 8)); + } + unsigned get_majversion() const + { + return m_data[OFFS_MAJVERSION]; + } + unsigned get_minversion() const + { + return m_data[OFFS_MINVERSION]; + } + std::string get_sysname() const + { + return get_string<OFFS_SYSNAME, OFFS_APPDESC>(); + } + std::string get_appdesc() const + { + return get_string<OFFS_APPDESC, OFFS_END>(); + } + + void set_magic() + { + std::memcpy(m_data + OFFS_MAGIC, MAGIC, OFFS_BASETIME - OFFS_MAGIC); + } + void set_basetime(u64 time) + { + m_data[OFFS_BASETIME + 0] = u8((time >> (0 * 8)) & 0x00ff); + m_data[OFFS_BASETIME + 1] = u8((time >> (1 * 8)) & 0x00ff); + m_data[OFFS_BASETIME + 2] = u8((time >> (2 * 8)) & 0x00ff); + m_data[OFFS_BASETIME + 3] = u8((time >> (3 * 8)) & 0x00ff); + m_data[OFFS_BASETIME + 4] = u8((time >> (4 * 8)) & 0x00ff); + m_data[OFFS_BASETIME + 5] = u8((time >> (5 * 8)) & 0x00ff); + m_data[OFFS_BASETIME + 6] = u8((time >> (6 * 8)) & 0x00ff); + m_data[OFFS_BASETIME + 7] = u8((time >> (7 * 8)) & 0x00ff); + } + void set_version() + { + m_data[OFFS_MAJVERSION] = MAJVERSION; + m_data[OFFS_MINVERSION] = MINVERSION; + } + void set_sysname(std::string const &name) + { + set_string<OFFS_SYSNAME, OFFS_APPDESC>(name); + } + void set_appdesc(std::string const &desc) + { + set_string<OFFS_APPDESC, OFFS_END>(desc); + } + +private: + template <std::size_t BEGIN, std::size_t END> void set_string(std::string const &str) + { + std::size_t const used = (std::min<std::size_t>)(str.size() + 1, END - BEGIN); + std::memcpy(m_data + BEGIN, str.c_str(), used); + if ((END - BEGIN) > used) + std::memset(m_data + BEGIN + used, 0, (END - BEGIN) - used); + } + template <std::size_t BEGIN, std::size_t END> std::string get_string() const + { + char const *const begin = reinterpret_cast<char const *>(m_data + BEGIN); + return std::string(begin, std::find(begin, reinterpret_cast<char const *>(m_data + END), '\0')); + } + + static constexpr std::size_t OFFS_MAGIC = 0x00; // 0x08 bytes + static constexpr std::size_t OFFS_BASETIME = 0x08; // 0x08 bytes (little-endian binary integer) + static constexpr std::size_t OFFS_MAJVERSION = 0x10; // 0x01 bytes (binary integer) + static constexpr std::size_t OFFS_MINVERSION = 0x11; // 0x01 bytes (binary integer) + // 0x02 bytes reserved + static constexpr std::size_t OFFS_SYSNAME = 0x14; // 0x0c bytes (ASCII) + static constexpr std::size_t OFFS_APPDESC = 0x20; // 0x20 bytes (ASCII) + static constexpr std::size_t OFFS_END = 0x40; + + static u8 const MAGIC[OFFS_BASETIME - OFFS_MAGIC]; + + u8 m_data[OFFS_END]; +}; + } // anonymous namespace @@ -391,6 +535,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 //------------------------------------------------- @@ -662,6 +824,20 @@ ioport_field::ioport_field(ioport_port &port, ioport_type type, ioport_value def } } + +//------------------------------------------------- +// ~ioport_field - destructor +//------------------------------------------------- + +ioport_field::~ioport_field() +{ +} + + +//------------------------------------------------- +// set_value - programmatically set field value +//------------------------------------------------- + void ioport_field::set_value(ioport_value value) { if (is_analog()) @@ -672,11 +848,15 @@ void ioport_field::set_value(ioport_value value) //------------------------------------------------- -// ~ioport_field - destructor +// clear_value - clear programmatic override //------------------------------------------------- -ioport_field::~ioport_field() +void ioport_field::clear_value() { + if (is_analog()) + live().analog->clear_value(); + else + m_digital_value = false; } @@ -685,16 +865,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 +939,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) @@ -1657,8 +1846,6 @@ ioport_manager::ioport_manager(running_machine &machine) , m_safe_to_read(false) , m_last_frame_time(attotime::zero) , m_last_delta_nsec(0) - , m_record_file(machine.options().input_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS) - , m_playback_file(machine.options().input_directory(), OPEN_FLAG_READ) , m_playback_accumulated_speed(0) , m_playback_accumulated_frames(0) , m_deselected_card_config() @@ -1702,12 +1889,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 +2035,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", "???"); } @@ -2313,7 +2508,10 @@ bool ioport_manager::load_controller_config( for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype) { if (input_seq_good(machine(), newseq[seqtype].first)) + { + field.live().seq[seqtype] = newseq[seqtype].first; field.set_defseq(seqtype, newseq[seqtype].first); + } } // fetch configurable attributes @@ -2723,7 +2921,8 @@ time_t ioport_manager::playback_init() return 0; // open the playback file - std::error_condition const filerr = m_playback_file.open(filename); + m_playback_file = std::make_unique<emu_file>(machine().options().input_directory(), OPEN_FLAG_READ); + std::error_condition const filerr = m_playback_file->open(filename); // return an explicit error if file isn't found in given path if (filerr == std::errc::no_such_file_or_directory) @@ -2735,7 +2934,7 @@ time_t ioport_manager::playback_init() // read the header and verify that it is a modern version; if not, print an error inp_header header; - if (!header.read(m_playback_file)) + if (!header.read(*m_playback_file)) fatalerror("Input file is corrupt or invalid (missing header)\n"); if (!header.check_magic()) fatalerror("Input file invalid or in an older, unsupported format\n"); @@ -2755,7 +2954,7 @@ time_t ioport_manager::playback_init() osd_printf_info("Input file is for machine '%s', not for current machine '%s'\n", sysname, machine().system().name); // enable compression - m_playback_stream = util::zlib_read(m_playback_file, 16386); + m_playback_stream = util::zlib_read(*m_playback_file, 16386); return basetime; } @@ -2771,7 +2970,7 @@ void ioport_manager::playback_end(const char *message) { // close the file m_playback_stream.reset(); - m_playback_file.close(); + m_playback_file.reset(); // pop a message if (message != nullptr) @@ -2893,7 +3092,8 @@ void ioport_manager::record_init() return; // open the record file - std::error_condition const filerr = m_record_file.open(filename); + m_record_file = std::make_unique<emu_file>(machine().options().input_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); + std::error_condition const filerr = m_record_file->open(filename); if (filerr) throw emu_fatalerror("ioport_manager::record_init: Failed to open file for recording (%s:%d %s)", filerr.category().name(), filerr.value(), filerr.message()); @@ -2910,10 +3110,10 @@ void ioport_manager::record_init() header.set_appdesc(util::string_format("%s %s", emulator_info::get_appname(), emulator_info::get_build_version())); // write it - header.write(m_record_file); + header.write(*m_record_file); // enable compression - m_record_stream = util::zlib_write(m_record_file, 6, 16384); + m_record_stream = util::zlib_write(*m_record_file, 6, 16384); } @@ -2928,7 +3128,7 @@ void ioport_manager::record_end(const char *message) { // close the file m_record_stream.reset(); // TODO: check for errors flushing the last compressed block before doing this - m_record_file.close(); + m_record_file.reset(); // pop a message if (message != nullptr) @@ -3260,6 +3460,7 @@ analog_field::analog_field(ioport_field &field) m_adjdefvalue(field.defvalue() & field.mask()), m_adjmin(field.minval() & field.mask()), m_adjmax(field.maxval() & field.mask()), + m_adjoverride(field.defvalue() & field.mask()), m_sensitivity(field.sensitivity()), m_reverse(field.analog_reverse()), m_delta(field.delta()), @@ -3267,7 +3468,6 @@ analog_field::analog_field(ioport_field &field) m_accum(0), m_previous(0), m_previousanalog(0), - m_prog_analog_value(0), m_minimum(INPUT_ABSOLUTE_MIN), m_maximum(INPUT_ABSOLUTE_MAX), m_center(0), @@ -3283,7 +3483,7 @@ analog_field::analog_field(ioport_field &field) m_single_scale(false), m_interpolate(false), m_lastdigital(false), - m_was_written(false) + m_use_adjoverride(false) { // compute the shift amount and number of bits for (ioport_value mask = field.mask(); !(mask & 1); mask >>= 1) @@ -3523,16 +3723,28 @@ s32 analog_field::apply_settings(s32 value) const //------------------------------------------------- -// set_value - take a new value to be used -// at next frame update +// set_value - override the value that will be +// read from the field //------------------------------------------------- void analog_field::set_value(s32 value) { - m_was_written = true; - m_prog_analog_value = value; + m_use_adjoverride = true; + m_adjoverride = std::clamp(value, m_adjmin, m_adjmax); +} + + +//------------------------------------------------- +// clear_value - clear programmatic override +//------------------------------------------------- + +void analog_field::clear_value() +{ + m_use_adjoverride = false; + m_adjoverride = m_adjdefvalue; } + //------------------------------------------------- // frame_update - update the internals of a // single analog field periodically @@ -3551,13 +3763,6 @@ void analog_field::frame_update(running_machine &machine) input_item_class itemclass; s32 rawvalue = machine.input().seq_axis_value(m_field.seq(SEQ_TYPE_STANDARD), itemclass); - // use programmatically set value if available - if (m_was_written) - { - m_was_written = false; - rawvalue = m_prog_analog_value; - } - // if we got an absolute input, it overrides everything else if (itemclass == ITEM_CLASS_ABSOLUTE) { @@ -3703,6 +3908,13 @@ void analog_field::read(ioport_value &result) if (!m_field.enabled()) return; + // if set programmatically, only use the override value + if (m_use_adjoverride) + { + result = m_adjoverride; + return; + } + // start with the raw value s32 value = m_accum; diff --git a/src/emu/ioport.h b/src/emu/ioport.h index c767d44c250..76f61debcac 100644 --- a/src/emu/ioport.h +++ b/src/emu/ioport.h @@ -662,116 +662,6 @@ typedef device_delegate<void (ioport_field &, u32, ioport_value, ioport_value)> typedef device_delegate<float (float)> ioport_field_crossmap_delegate; -// ======================> inp_header - -// header at the front of INP files -class inp_header -{ -public: - // parameters - static constexpr unsigned MAJVERSION = 3; - static constexpr unsigned MINVERSION = 0; - - bool read(emu_file &f) - { - return f.read(m_data, sizeof(m_data)) == sizeof(m_data); - } - bool write(emu_file &f) const - { - return f.write(m_data, sizeof(m_data)) == sizeof(m_data); - } - - bool check_magic() const - { - return 0 == std::memcmp(MAGIC, m_data + OFFS_MAGIC, OFFS_BASETIME - OFFS_MAGIC); - } - u64 get_basetime() const - { - return - (u64(m_data[OFFS_BASETIME + 0]) << (0 * 8)) | - (u64(m_data[OFFS_BASETIME + 1]) << (1 * 8)) | - (u64(m_data[OFFS_BASETIME + 2]) << (2 * 8)) | - (u64(m_data[OFFS_BASETIME + 3]) << (3 * 8)) | - (u64(m_data[OFFS_BASETIME + 4]) << (4 * 8)) | - (u64(m_data[OFFS_BASETIME + 5]) << (5 * 8)) | - (u64(m_data[OFFS_BASETIME + 6]) << (6 * 8)) | - (u64(m_data[OFFS_BASETIME + 7]) << (7 * 8)); - } - unsigned get_majversion() const - { - return m_data[OFFS_MAJVERSION]; - } - unsigned get_minversion() const - { - return m_data[OFFS_MINVERSION]; - } - std::string get_sysname() const - { - return get_string<OFFS_SYSNAME, OFFS_APPDESC>(); - } - std::string get_appdesc() const - { - return get_string<OFFS_APPDESC, OFFS_END>(); - } - - void set_magic() - { - std::memcpy(m_data + OFFS_MAGIC, MAGIC, OFFS_BASETIME - OFFS_MAGIC); - } - void set_basetime(u64 time) - { - m_data[OFFS_BASETIME + 0] = u8((time >> (0 * 8)) & 0x00ff); - m_data[OFFS_BASETIME + 1] = u8((time >> (1 * 8)) & 0x00ff); - m_data[OFFS_BASETIME + 2] = u8((time >> (2 * 8)) & 0x00ff); - m_data[OFFS_BASETIME + 3] = u8((time >> (3 * 8)) & 0x00ff); - m_data[OFFS_BASETIME + 4] = u8((time >> (4 * 8)) & 0x00ff); - m_data[OFFS_BASETIME + 5] = u8((time >> (5 * 8)) & 0x00ff); - m_data[OFFS_BASETIME + 6] = u8((time >> (6 * 8)) & 0x00ff); - m_data[OFFS_BASETIME + 7] = u8((time >> (7 * 8)) & 0x00ff); - } - void set_version() - { - m_data[OFFS_MAJVERSION] = MAJVERSION; - m_data[OFFS_MINVERSION] = MINVERSION; - } - void set_sysname(std::string const &name) - { - set_string<OFFS_SYSNAME, OFFS_APPDESC>(name); - } - void set_appdesc(std::string const &desc) - { - set_string<OFFS_APPDESC, OFFS_END>(desc); - } - -private: - template <std::size_t BEGIN, std::size_t END> void set_string(std::string const &str) - { - std::size_t const used = (std::min<std::size_t>)(str.size() + 1, END - BEGIN); - std::memcpy(m_data + BEGIN, str.c_str(), used); - if ((END - BEGIN) > used) - std::memset(m_data + BEGIN + used, 0, (END - BEGIN) - used); - } - template <std::size_t BEGIN, std::size_t END> std::string get_string() const - { - char const *const begin = reinterpret_cast<char const *>(m_data + BEGIN); - return std::string(begin, std::find(begin, reinterpret_cast<char const *>(m_data + END), '\0')); - } - - static constexpr std::size_t OFFS_MAGIC = 0x00; // 0x08 bytes - static constexpr std::size_t OFFS_BASETIME = 0x08; // 0x08 bytes (little-endian binary integer) - static constexpr std::size_t OFFS_MAJVERSION = 0x10; // 0x01 bytes (binary integer) - static constexpr std::size_t OFFS_MINVERSION = 0x11; // 0x01 bytes (binary integer) - // 0x02 bytes reserved - static constexpr std::size_t OFFS_SYSNAME = 0x14; // 0x0c bytes (ASCII) - static constexpr std::size_t OFFS_APPDESC = 0x20; // 0x20 bytes (ASCII) - static constexpr std::size_t OFFS_END = 0x40; - - static u8 const MAGIC[OFFS_BASETIME - OFFS_MAGIC]; - - u8 m_data[OFFS_END]; -}; - - // ======================> input_device_default // device defined default input settings @@ -798,7 +688,7 @@ public: ioport_group group() const noexcept { return m_group; } u8 player() const noexcept { return m_player; } const char *token() const noexcept { return m_token; } - const char *name() const noexcept { return m_name; } + std::string name() const; input_seq &defseq(input_seq_type seqtype = SEQ_TYPE_STANDARD) noexcept { return m_defseq[seqtype]; } const input_seq &defseq(input_seq_type seqtype = SEQ_TYPE_STANDARD) const noexcept { return m_defseq[seqtype]; } const input_seq &seq(input_seq_type seqtype = SEQ_TYPE_STANDARD) const noexcept { return m_seq[seqtype]; } @@ -1026,6 +916,7 @@ public: u8 player() const { return m_player; } bool digital_value() const { return m_digital_value; } void set_value(ioport_value value); + void clear_value(); bool optional() const { return ((m_flags & FIELD_FLAG_OPTIONAL) != 0); } bool cocktail() const { return ((m_flags & FIELD_FLAG_COCKTAIL) != 0); } @@ -1037,7 +928,7 @@ public: bool analog_invert() const { return ((m_flags & ANALOG_FLAG_INVERT) != 0); } u8 impulse() const noexcept { return m_impulse; } - const char *name() const; + std::string name() const; const char *specific_name() const noexcept { return m_name; } const input_seq &seq(input_seq_type seqtype = SEQ_TYPE_STANDARD) const noexcept; const input_seq &defseq(input_seq_type seqtype = SEQ_TYPE_STANDARD) const noexcept; @@ -1262,8 +1153,9 @@ public: float crosshair_read(); void frame_update(running_machine &machine); - // setters + // programmatic override (for script bindings) void set_value(s32 value); + void clear_value(); private: // helpers @@ -1280,6 +1172,7 @@ private: s32 m_adjdefvalue; // adjusted default value from the config s32 m_adjmin; // adjusted minimum value from the config s32 m_adjmax; // adjusted maximum value from the config + s32 m_adjoverride; // programmatically set adjusted value // live values of configurable parameters s32 m_sensitivity; // current live sensitivity (100=normal) @@ -1291,7 +1184,6 @@ private: s32 m_accum; // accumulated value (including relative adjustments) s32 m_previous; // previous adjusted value s32 m_previousanalog; // previous analog value - s32 m_prog_analog_value; // programmatically set analog value // parameters for modifying live values s32 m_minimum; // minimum adjusted value @@ -1313,7 +1205,7 @@ private: bool m_single_scale; // scale joystick differently if default is between min/max bool m_interpolate; // should we do linear interpolation for mid-frame reads? bool m_lastdigital; // was the last modification caused by a digital form? - bool m_was_written; // was the last modification caused programmatically? + bool m_use_adjoverride; // override what will be read from the field }; @@ -1382,7 +1274,7 @@ public: // type helpers const std::vector<input_type_entry> &types() const noexcept { return m_typelist; } bool type_pressed(ioport_type type, int player = 0); - const char *type_name(ioport_type type, u8 player) const noexcept; + std::string type_name(ioport_type type, u8 player) const; ioport_group type_group(ioport_type type, int player) const noexcept; const input_seq &type_seq(ioport_type type, int player = 0, input_seq_type seqtype = SEQ_TYPE_STANDARD) const noexcept; void set_type_seq(ioport_type type, int player, input_seq_type seqtype, const input_seq &newseq) noexcept; @@ -1449,8 +1341,8 @@ private: attoseconds_t m_last_delta_nsec; // nanoseconds that passed since the previous callback // playback/record information - emu_file m_record_file; // recording file (closed if not recording) - emu_file m_playback_file; // playback file (closed if not recording) + std::unique_ptr<emu_file> m_record_file; // recording file (nullptr if not recording) + std::unique_ptr<emu_file> m_playback_file; // playback file (nullptr if not recording) util::write_stream::ptr m_record_stream; // recording stream (nullptr if not recording) util::read_stream::ptr m_playback_stream; // playback stream (nullptr if not recording) u64 m_playback_accumulated_speed; // accumulated speed during playback diff --git a/src/emu/layout/nes_rob.lay b/src/emu/layout/nes_rob.lay new file mode 100644 index 00000000000..2cff2a814ad --- /dev/null +++ b/src/emu/layout/nes_rob.lay @@ -0,0 +1,63 @@ +<?xml version="1.0"?> +<!-- +license:CC0 +--> +<mamelayout version="2"> + +<!-- define elements --> + + <element name="text_m1"><text align="1" string="motor 1:"><color red="0.8" green="0.8" blue="0.8" /></text></element> + <element name="text_m2"><text align="1" string="motor 2:"><color red="0.8" green="0.8" blue="0.8" /></text></element> + <element name="text_m3"><text align="1" string="motor 3:"><color red="0.8" green="0.8" blue="0.8" /></text></element> + + <element name="mstatus0"> + <text state="1" align="1" string="DOWN"><color red="1.0" green="1.0" blue="0.2" /></text> + <text state="0" align="1" string="DOWN"><color red="0.2" green="0.2" blue="0.2" /></text> + </element> + <element name="mstatus1"> + <text state="1" align="1" string="UP"><color red="1.0" green="1.0" blue="0.2" /></text> + <text state="0" align="1" string="UP"><color red="0.2" green="0.2" blue="0.2" /></text> + </element> + <element name="mstatus2"> + <text state="1" align="1" string="CLOSE"><color red="1.0" green="1.0" blue="0.2" /></text> + <text state="0" align="1" string="CLOSE"><color red="0.2" green="0.2" blue="0.2" /></text> + </element> + <element name="mstatus3"> + <text state="1" align="1" string="OPEN"><color red="1.0" green="1.0" blue="0.2" /></text> + <text state="0" align="1" string="OPEN"><color red="0.2" green="0.2" blue="0.2" /></text> + </element> + <element name="mstatus4"> + <text state="1" align="1" string="RIGHT"><color red="1.0" green="1.0" blue="0.2" /></text> + <text state="0" align="1" string="RIGHT"><color red="0.2" green="0.2" blue="0.2" /></text> + </element> + <element name="mstatus5"> + <text state="1" align="1" string="LEFT"><color red="1.0" green="1.0" blue="0.2" /></text> + <text state="0" align="1" string="LEFT"><color red="0.2" green="0.2" blue="0.2" /></text> + </element> + + <element name="led" defstate="0"> + <disk state="1"><color red="1.0" green="0.1" blue="0.15" /></disk> + <disk state="0"><color red="0.15" green="0.015" blue="0.017" /></disk> + </element> + + +<!-- build screen --> + + <view name="Internal Layout"> + <bounds left="4.5" right="17" top="7" bottom="14.25" /> + + <element ref="text_m1"><bounds x="5.5" y="10" width="5" height="1" /></element> + <element ref="text_m2"><bounds x="5.5" y="11.25" width="5" height="1" /></element> + <element ref="text_m3"><bounds x="5.5" y="12.5" width="5" height="1" /></element> + + <element name="rob_motor.1" ref="mstatus1"><bounds x="10" y="10" width="5" height="1" /></element> + <element name="rob_motor.0" ref="mstatus0"><bounds x="13.5" y="10" width="5" height="1" /></element> + <element name="rob_motor.5" ref="mstatus5"><bounds x="10" y="11.25" width="5" height="1" /></element> + <element name="rob_motor.4" ref="mstatus4"><bounds x="13.5" y="11.25" width="5" height="1" /></element> + <element name="rob_motor.2" ref="mstatus2"><bounds x="10" y="12.5" width="5" height="1" /></element> + <element name="rob_motor.3" ref="mstatus3"><bounds x="13.5" y="12.5" width="5" height="1" /></element> + + <element name="rob_led" ref="led"><bounds x="10" y="8" width="1" height="1" /></element> + + </view> +</mamelayout> diff --git a/src/emu/machine.cpp b/src/emu/machine.cpp index 7e9d8091359..6613c5654bf 100644 --- a/src/emu/machine.cpp +++ b/src/emu/machine.cpp @@ -6,91 +6,39 @@ Controls execution of the core MAME system. -**************************************************************************** - - Since there has been confusion in the past over the order of - initialization and other such things, here it is, all spelled out - as of January, 2008: - - main() - - does platform-specific init - - calls mame_execute() [mame.c] - - mame_execute() [mame.c] - - calls mame_validitychecks() [validity.c] to perform validity checks on all compiled drivers - - begins resource tracking (level 1) - - calls create_machine [mame.c] to initialize the running_machine structure - - calls init_machine() [mame.c] - - init_machine() [mame.c] - - calls fileio_init() [fileio.c] to initialize file I/O info - - calls config_init() [config.c] to initialize configuration system - - calls input_init() [input.c] to initialize the input system - - calls output_init() [output.c] to initialize the output system - - calls state_init() [state.c] to initialize save state system - - calls state_save_allow_registration() [state.c] to allow registrations - - calls palette_init() [palette.c] to initialize palette system - - calls render_init() [render.c] to initialize the rendering system - - calls ui_init() [ui.c] to initialize the user interface - - calls generic_machine_init() [machine/generic.c] to initialize generic machine structures - - calls timer_init() [timer.c] to reset the timer system - - calls osd_init() [osdepend.h] to do platform-specific initialization - - calls input_port_init() [inptport.c] to set up the input ports - - calls rom_init() [romload.c] to load the game's ROMs - - calls memory_init() [memory.c] to process the game's memory maps - - calls the driver's DRIVER_INIT callback - - calls device_list_start() [devintrf.c] to start any devices - - calls video_init() [video.c] to start the video system - - calls tilemap_init() [tilemap.c] to start the tilemap system - - calls crosshair_init() [crsshair.c] to configure the crosshairs - - calls sound_init() [sound.c] to start the audio system - - calls debugger_init() [debugger.c] to set up the debugger - - calls the driver's MACHINE_START, SOUND_START, and VIDEO_START callbacks - - calls cheat_init() [cheat.c] to initialize the cheat system - - calls image_init() [image.c] to initialize the image system - - - calls config_load_settings() [config.c] to load the configuration file - - calls nvram_load [machine/generic.c] to load NVRAM - - calls ui_display_startup_screens() [ui.c] to display the startup screens - - begins resource tracking (level 2) - - calls soft_reset() [mame.c] to reset all systems - - -------------------( at this point, we're up and running )---------------------- - - - calls scheduler->timeslice() [schedule.c] over and over until we exit - - ends resource tracking (level 2), freeing all auto_mallocs and timers - - calls the nvram_save() [machine/generic.c] to save NVRAM - - calls config_save_settings() [config.c] to save the game's configuration - - calls all registered exit routines [mame.c] - - ends resource tracking (level 1), freeing all auto_mallocs and timers - - - exits the program - ***************************************************************************/ #include "emu.h" -#include "emuopts.h" -#include "osdepend.h" + #include "config.h" -#include "debugger.h" -#include "render.h" -#include "uiinput.h" #include "crsshair.h" -#include "unzip.h" -#include "debug/debugvw.h" #include "debug/debugcpu.h" +#include "debug/debugvw.h" +#include "debugger.h" #include "dirtc.h" +#include "emuopts.h" +#include "fileio.h" +#include "http.h" #include "image.h" +#include "natkeyboard.h" #include "network.h" +#include "render.h" #include "romload.h" #include "tilemap.h" -#include "natkeyboard.h" +#include "uiinput.h" + #include "ui/uimain.h" + #include "corestr.h" -#include <ctime> +#include "unzip.h" + +#include "osdepend.h" + #include <rapidjson/writer.h> #include <rapidjson/stringbuffer.h> +#include <ctime> + #if defined(__EMSCRIPTEN__) #include <emscripten.h> #endif @@ -497,7 +445,7 @@ void running_machine::schedule_soft_reset() //------------------------------------------------- // get_statename - allow to specify a subfolder of // the state directory for state loading/saving, -// very useful for MESS and consoles or computers +// very useful for consoles or computers // where you can have separate folders for diff // software //------------------------------------------------- @@ -645,10 +593,10 @@ void running_machine::schedule_save(std::string &&filename) // immediate_save - save state. //------------------------------------------------- -void running_machine::immediate_save(const char *filename) +void running_machine::immediate_save(std::string_view filename) { // specify the filename to save or load - set_saveload_filename(filename); + set_saveload_filename(std::string(filename)); // set up some parameters for handle_saveload() m_saveload_schedule = saveload_schedule::SAVE; @@ -682,10 +630,10 @@ void running_machine::schedule_load(std::string &&filename) // immediate_load - load state. //------------------------------------------------- -void running_machine::immediate_load(const char *filename) +void running_machine::immediate_load(std::string_view filename) { // specify the filename to save or load - set_saveload_filename(filename); + set_saveload_filename(std::string(filename)); // set up some parameters for handle_saveload() m_saveload_schedule = saveload_schedule::LOAD; @@ -997,7 +945,7 @@ void running_machine::handle_saveload() // of the system //------------------------------------------------- -void running_machine::soft_reset(void *ptr, s32 param) +void running_machine::soft_reset(s32 param) { logerror("Soft reset\n"); @@ -1028,6 +976,17 @@ void running_machine::logfile_callback(const char *buffer) //------------------------------------------------- +// steal_debuglogfile - relinquish ownership of +// the debug.log file +//------------------------------------------------- + +std::unique_ptr<emu_file> running_machine::steal_debuglogfile() +{ + return std::move(m_debuglogfile); +} + + +//------------------------------------------------- // start_all_devices - start any unstarted devices //------------------------------------------------- @@ -1176,7 +1135,8 @@ void running_machine::nvram_load() emu_file file(options().nvram_directory(), OPEN_FLAG_READ); if (!file.open(nvram_filename(nvram.device()))) { - nvram.nvram_load(file); + if (!nvram.nvram_load(file)) + osd_printf_error("Error reading NVRAM file %s\n", file.filename()); file.close(); } else @@ -1198,7 +1158,8 @@ void running_machine::nvram_save() emu_file file(options().nvram_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); if (!file.open(nvram_filename(nvram.device()))) { - nvram.nvram_save(file); + if (!nvram.nvram_save(file)) + osd_printf_error("Error writing NVRAM file %s\n", file.filename()); file.close(); } } diff --git a/src/emu/machine.h b/src/emu/machine.h index f3aef08d265..4bef86ce3a7 100644 --- a/src/emu/machine.h +++ b/src/emu/machine.h @@ -177,8 +177,8 @@ public: void export_http_api(); // TODO: Do saves and loads still require scheduling? - void immediate_save(const char *filename); - void immediate_load(const char *filename); + void immediate_save(std::string_view filename); + void immediate_load(std::string_view filename); // rewind operations bool rewind_capture(); @@ -217,7 +217,7 @@ public: bool debug_enabled() { return (debug_flags & DEBUG_FLAG_ENABLED) != 0; } // used by debug_console to take ownership of the debug.log file - std::unique_ptr<emu_file> steal_debuglogfile() { return std::move(m_debuglogfile); } + std::unique_ptr<emu_file> steal_debuglogfile(); private: class side_effects_disabler { @@ -248,7 +248,7 @@ private: void start(); void set_saveload_filename(std::string &&filename); void handle_saveload(); - void soft_reset(void *ptr = nullptr, s32 param = 0); + void soft_reset(s32 param = 0); std::string nvram_filename(device_t &device) const; void nvram_load(); void nvram_save(); diff --git a/src/emu/main.cpp b/src/emu/main.cpp index e5467238238..6ce109ae1ef 100644 --- a/src/emu/main.cpp +++ b/src/emu/main.cpp @@ -10,6 +10,7 @@ #include "emu.h" #include "emuopts.h" +#include "http.h" machine_manager::machine_manager(emu_options& options, osd_interface& osd) : m_osd(osd), @@ -18,8 +19,17 @@ machine_manager::machine_manager(emu_options& options, osd_interface& osd) { } +machine_manager::~machine_manager() +{ +} + void machine_manager::start_http_server() { m_http = std::make_unique<http_manager>(options().http(), options().http_port(), options().http_root()); } + +http_manager *machine_manager::http() +{ + return m_http.get(); +} diff --git a/src/emu/main.h b/src/emu/main.h index 3c75205de14..89399e21690 100644 --- a/src/emu/main.h +++ b/src/emu/main.h @@ -71,7 +71,7 @@ protected: // construction/destruction machine_manager(emu_options& options, osd_interface& osd); public: - virtual ~machine_manager() { } + virtual ~machine_manager(); osd_interface &osd() const { return m_osd; } emu_options &options() const { return m_options; } @@ -88,7 +88,7 @@ public: virtual void update_machine() { } - http_manager *http() { return m_http.get(); } + http_manager *http(); void start_http_server(); protected: diff --git a/src/emu/mconfig.cpp b/src/emu/mconfig.cpp index fb97c3138a3..2c8c1aa011b 100644 --- a/src/emu/mconfig.cpp +++ b/src/emu/mconfig.cpp @@ -257,24 +257,23 @@ std::pair<const char *, device_t *> machine_config::resolve_owner(const char *ta device_t *owner(m_current_device); // if the device path is absolute, start from the root - if (tag[0] == ':') - { - tag++; - owner = m_root_device.get(); - } + if (!*tag || (':' == *tag) || ('^' == *tag)) + throw emu_fatalerror("Attempting to add device with tag containing parent references '%s'\n", orig_tag); // go down the path until we're done with it - while (strchr(tag, ':')) + char const *next; + while ((next = strchr(tag, ':')) != nullptr) { - const char *next = strchr(tag, ':'); assert(next != tag); std::string_view part(tag, next - tag); owner = owner->subdevices().find(part); if (!owner) - throw emu_fatalerror("Could not find %s when looking up path for device %s\n", part, orig_tag); - tag = next+1; + throw emu_fatalerror("Could not find '%s' when looking up path for device '%s'\n", part, orig_tag); + tag = next + 1; + if ('^' == *tag) + throw emu_fatalerror("Attempting to add device with tag containing parent references '%s'\n", orig_tag); } - assert(tag[0] != '\0'); + assert(*tag != '\0'); return std::make_pair(tag, owner); } @@ -296,7 +295,7 @@ std::tuple<const char *, device_t *, device_t *> machine_config::prepare_replace if (old_device) remove_references(*old_device); else - osd_printf_warning("Warning: attempting to replace non-existent device '%s'\n", tag); + throw emu_fatalerror("Attempting to replace non-existent device '%s'\n", tag); return std::make_tuple(owner.first, owner.second, old_device); } diff --git a/src/emu/mconfig.h b/src/emu/mconfig.h index c600ca06665..c6cacde581f 100644 --- a/src/emu/mconfig.h +++ b/src/emu/mconfig.h @@ -133,7 +133,7 @@ public: /// replace an existing device. /// \return A device replacement helper to pass to a device type /// when replacing an existing device. - emu::detail::machine_config_replace replace() { return emu::detail::machine_config_replace(*this); }; + emu::detail::machine_config_replace replace() { return emu::detail::machine_config_replace(*this); } /// \brief Set internal layout for current device /// diff --git a/src/emu/memarray.cpp b/src/emu/memarray.cpp index 22bfa17b80a..660e07ad9a1 100644 --- a/src/emu/memarray.cpp +++ b/src/emu/memarray.cpp @@ -90,11 +90,6 @@ void memory_array::set(void *base, u32 bytes, int membits, endianness_t endianne // set - additional setter variants //------------------------------------------------- -void memory_array::set(const address_space &space, void *base, u32 bytes, int bpe) -{ - set(base, bytes, space.data_width(), space.endianness(), bpe); -} - void memory_array::set(const memory_share &share, int bpe) { set(share.ptr(), share.bytes(), share.bitwidth(), share.endianness(), bpe); diff --git a/src/emu/memarray.h b/src/emu/memarray.h index f9a7e406a8e..fc7e47c4b3c 100644 --- a/src/emu/memarray.h +++ b/src/emu/memarray.h @@ -42,14 +42,12 @@ public: memory_array(); memory_array(void *base, u32 bytes, int membits, endianness_t endianness, int bpe) { set(base, bytes, membits, endianness, bpe); } template <typename _Type> memory_array(std::vector<_Type> &array, endianness_t endianness, int bpe) { set(array, endianness, bpe); } - memory_array(const address_space &space, void *base, u32 bytes, int bpe) { set(space, base, bytes, bpe); } memory_array(const memory_share &share, int bpe) { set(share, bpe); } memory_array(const memory_array &array) { set(array); } // configuration void set(void *base, u32 bytes, int membits, endianness_t endianness, int bpe); template <typename _Type> void set(std::vector<_Type> &array, endianness_t endianness, int bpe) { set(&array[0], array.size(), 8*sizeof(_Type), endianness, bpe); } - void set(const address_space &space, void *base, u32 bytes, int bpe); void set(const memory_share &share, int bpe); void set(const memory_array &array); diff --git a/src/emu/natkeyboard.cpp b/src/emu/natkeyboard.cpp index e5dcdc93dbc..5a36e6b8e13 100644 --- a/src/emu/natkeyboard.cpp +++ b/src/emu/natkeyboard.cpp @@ -864,7 +864,7 @@ void natural_keyboard::internal_post(char32_t ch) // when posting a string of characters //------------------------------------------------- -void natural_keyboard::timer(void *ptr, int param) +void natural_keyboard::timer(s32 param) { if (!m_queue_chars.isnull()) { diff --git a/src/emu/natkeyboard.h b/src/emu/natkeyboard.h index c3454ee8dd4..dc89b0eb156 100644 --- a/src/emu/natkeyboard.h +++ b/src/emu/natkeyboard.h @@ -109,7 +109,7 @@ private: bool can_post_alternate(char32_t ch); attotime choose_delay(char32_t ch); void internal_post(char32_t ch); - void timer(void *ptr, int param); + void timer(s32 param); std::string unicode_to_string(char32_t ch) const; const keycode_map_entry *find_code(char32_t ch) const; diff --git a/src/emu/recording.cpp b/src/emu/recording.cpp index 9e3c1f3f4ae..611e5ae327b 100644 --- a/src/emu/recording.cpp +++ b/src/emu/recording.cpp @@ -9,7 +9,10 @@ ***************************************************************************/ #include "emu.h" + +#include "fileio.h" #include "screen.h" + #include "aviio.h" #include "png.h" diff --git a/src/emu/render.cpp b/src/emu/render.cpp index 1f9918539d5..b9a96e81fad 100644 --- a/src/emu/render.cpp +++ b/src/emu/render.cpp @@ -41,6 +41,7 @@ #include "corestr.h" #include "emuopts.h" +#include "fileio.h" #include "rendfont.h" #include "rendlay.h" #include "rendutil.h" @@ -1197,63 +1198,103 @@ void render_target::compute_visible_area(s32 target_width, s32 target_height, fl // apply orientation if required if (target_orientation & ORIENTATION_SWAP_XY) - src_aspect = 1.0 / src_aspect; + src_aspect = 1.0f / src_aspect; - // get target aspect - float target_aspect = (float)target_width / (float)target_height * target_pixel_aspect; + // we need the ratio of target to source aspect + float aspect_ratio = m_keepaspect ? (float)target_width / (float)target_height * target_pixel_aspect / src_aspect : 1.0f; + + // first compute (a, b) scale factors to fit the screen + float a = (float)target_width / src_width; + float b = (float)target_height / src_height; // apply automatic axial stretching if required int scale_mode = m_scale_mode; - if (m_scale_mode == SCALE_FRACTIONAL_AUTO) - { - bool is_rotated = (m_manager.machine().system().flags & ORIENTATION_SWAP_XY) ^ (target_orientation & ORIENTATION_SWAP_XY); - scale_mode = is_rotated ? SCALE_FRACTIONAL_Y : SCALE_FRACTIONAL_X; - } + if (scale_mode == SCALE_FRACTIONAL_AUTO) + scale_mode = (m_manager.machine().system().flags & ORIENTATION_SWAP_XY) ^ (target_orientation & ORIENTATION_SWAP_XY) ? + SCALE_FRACTIONAL_Y : SCALE_FRACTIONAL_X; - // first compute scale factors to fit the screen - float xscale = (float)target_width / src_width; - float yscale = (float)target_height / src_height; + // determine the scaling method for each axis + bool a_is_fract = (scale_mode == SCALE_FRACTIONAL_X || scale_mode == SCALE_FRACTIONAL); + bool b_is_fract = (scale_mode == SCALE_FRACTIONAL_Y || scale_mode == SCALE_FRACTIONAL); - // apply aspect correction - if (m_keepaspect) - { - if (target_aspect > src_aspect) - xscale *= src_aspect / target_aspect; - else - yscale *= target_aspect / src_aspect; - } + // check if we have user defined scale factors, if so use them instead, but only on integer axes + int a_user = a_is_fract ? 0 : m_int_scale_x; + int b_user = b_is_fract ? 0 : m_int_scale_y; - bool x_fits = render_round_nearest(xscale) * src_width <= target_width; - bool y_fits = render_round_nearest(yscale) * src_height <= target_height; + // we allow overscan either explicitely or if integer scale factors are forced by user + bool int_overscan = m_int_overscan || (m_keepaspect && (a_user != 0 || b_user != 0)); + float a_max = std::max(a, (float)a_user); + float b_max = std::max(b, (float)b_user); - // compute integer scale factors - float integer_x = std::max(1.0f, float(m_int_overscan || x_fits ? render_round_nearest(xscale) : floor(xscale))); - float integer_y = std::max(1.0f, float(m_int_overscan || y_fits ? render_round_nearest(yscale) : floor(yscale))); - // check if we have user defined scale factors, if so use them instead - integer_x = m_int_scale_x > 0 ? m_int_scale_x : integer_x; - integer_y = m_int_scale_y > 0 ? m_int_scale_y : integer_y; + // get the usable bounding box considering the type of scaling for each axis + float usable_aspect = (a_is_fract ? a : std::max(1.0f, floorf(a))) * src_width / + ((b_is_fract ? b : std::max(1.0f, floorf(b))) * src_height) * target_pixel_aspect; - // now apply desired scale mode - if (scale_mode == SCALE_FRACTIONAL_X) + // depending on the relative shape between target and source, let's define 'a' and 'b' so that: + // * a is the leader axis (first to hit a boundary) + // * b is the follower axis + if (usable_aspect > src_aspect) { - if (m_keepaspect) xscale *= integer_y / yscale; - yscale = integer_y; + std::swap(a, b); + std::swap(a_user, b_user); + std::swap(a_is_fract, b_is_fract); + std::swap(a_max, b_max); + aspect_ratio = 1.0f / aspect_ratio; } - else if (scale_mode == SCALE_FRACTIONAL_Y) - { - if (m_keepaspect) yscale *= integer_x / xscale; - xscale = integer_x; - } - else + + // now find an (a, b) pair that best fits our boundaries and scale options + float a_best = 1.0f, b_best = 1.0f; + float diff = 1000; + + // fill (a0, a1) range + float u = a_user == 0 ? a : (float)a_user; + float a_range[] = {a_is_fract ? u : std::max(1.0f, floorf(u)), a_is_fract ? u : std::max(1.0f, roundf(u))}; + + for (float aa : a_range) { - xscale = integer_x; - yscale = integer_y; + // apply aspect correction to 'b' axis if needed, considering resulting 'a' borders + float ba = b * (m_keepaspect ? aspect_ratio * (aa / a) : 1.0f); + + // fill (b0, b1) range + float v = b_user == 0 ? ba : (float)b_user; + float b_range[] = {b_is_fract ? v : std::max(1.0f, floorf(v)), b_is_fract ? v : std::max(1.0f, roundf(v))}; + + for (float bb : b_range) + { + // we may need to propagate proportions back to 'a' axis + float ab = aa; + if (m_keepaspect && a_user == 0) + { + if (a_is_fract) ab *= (bb / ba); + else if (b_user != 0) ab = std::max(1.0f, roundf(ab * (bb / ba))); + } + + // if overscan isn't allowed, discard values that exceed the usable bounding box, except a minimum of 1.0f + if (!int_overscan && ((ab > a_max && bb > 1.0f) || (bb > b_max && ab > 1.0f))) + continue; + + // score the result + float new_diff = fabsf(aspect_ratio * (a / b) - (ab / bb)); + + if (new_diff <= diff) + { + diff = new_diff; + a_best = ab; + b_best = bb; + } + } } + a = a_best; + b = b_best; + + // restore orientation + if (usable_aspect > src_aspect) + std::swap(a, b); // set the final width/height - visible_width = render_round_nearest(src_width * xscale); - visible_height = render_round_nearest(src_height * yscale); + visible_width = render_round_nearest(src_width * a); + visible_height = render_round_nearest(src_height * b); break; } } @@ -1338,10 +1379,6 @@ void render_target::compute_minimum_size(s32 &minwidth, s32 &minheight) render_primitive_list &render_target::get_primitives() { - // remember the base values if this is the first frame - if (!m_base_view) - m_base_view = ¤t_view(); - // switch to the next primitive list render_primitive_list &list = m_primlist[m_listindex]; m_listindex = (m_listindex + 1) % std::size(m_primlist); @@ -2313,11 +2350,11 @@ void render_target::add_container_primitives(render_primitive_list &list, const // clip the primitive if (!m_transform_container && PRIMFLAG_GET_VECTOR(curitem.flags())) { - clipped = render_clip_line(&prim->bounds, &root_cliprect); + clipped = render_clip_line(prim->bounds, root_cliprect); } else { - clipped = render_clip_line(&prim->bounds, &cliprect); + clipped = render_clip_line(prim->bounds, cliprect); } break; @@ -2350,7 +2387,7 @@ void render_target::add_container_primitives(render_primitive_list &list, const prim->texcoords = oriented_texcoords[finalorient]; // apply clipping - clipped = render_clip_quad(&prim->bounds, &cliprect, &prim->texcoords); + clipped = render_clip_quad(prim->bounds, cliprect, &prim->texcoords); // apply the final orientation from the quad flags and then build up the final flags prim->flags |= (curitem.flags() & ~(PRIMFLAG_TEXORIENT_MASK | PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)) @@ -2410,7 +2447,7 @@ void render_target::add_container_primitives(render_primitive_list &list, const prim->texcoords = oriented_texcoords[finalorient]; // apply clipping - clipped = render_clip_quad(&prim->bounds, &cliprect, &prim->texcoords); + clipped = render_clip_quad(prim->bounds, cliprect, &prim->texcoords); // apply the final orientation from the quad flags and then build up the final flags prim->flags |= (curitem.flags() & ~(PRIMFLAG_TEXORIENT_MASK | PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)) @@ -2426,7 +2463,7 @@ void render_target::add_container_primitives(render_primitive_list &list, const | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA); // apply clipping - clipped = render_clip_quad(&prim->bounds, &cliprect, nullptr); + clipped = render_clip_quad(prim->bounds, cliprect, nullptr); } } break; @@ -2551,7 +2588,7 @@ void render_target::add_element_primitives(render_primitive_list &list, const ob } // add to the list or free if we're clipped out - bool const clipped = render_clip_quad(&prim->bounds, &cliprect, &prim->texcoords); + bool const clipped = render_clip_quad(prim->bounds, cliprect, &prim->texcoords); list.append_or_return(*prim, clipped); } } @@ -2613,10 +2650,18 @@ int render_target::view_index(layout_view &targetview) const // config_load - process config information //------------------------------------------------- -void render_target::config_load(util::xml::data_node const &targetnode) +void render_target::config_load(util::xml::data_node const *targetnode) { + // remember the view selected via command line and INI options + if (!m_base_view) + m_base_view = ¤t_view(); + + // bail if no configuration + if (!targetnode) + return; + // find the view - const char *viewname = targetnode.get_attribute_string("view", nullptr); + const char *viewname = targetnode->get_attribute_string("view", nullptr); if (viewname != nullptr) for (int viewnum = 0; viewnum < 1000; viewnum++) { @@ -2631,12 +2676,12 @@ void render_target::config_load(util::xml::data_node const &targetnode) } // modify the artwork config - int const zoom = targetnode.get_attribute_int("zoom", -1); + int const zoom = targetnode->get_attribute_int("zoom", -1); if (zoom == 0 || zoom == 1) set_zoom_to_screen(zoom); // apply orientation - int rotate = targetnode.get_attribute_int("rotate", -1); + int rotate = targetnode->get_attribute_int("rotate", -1); if (rotate != -1) { if (rotate == 90) @@ -2660,7 +2705,7 @@ void render_target::config_load(util::xml::data_node const &targetnode) } // apply per-view settings - for (util::xml::data_node const *viewnode = targetnode.get_child("view"); viewnode; viewnode = viewnode->get_next_sibling("view")) + for (util::xml::data_node const *viewnode = targetnode->get_child("view"); viewnode; viewnode = viewnode->get_next_sibling("view")) { char const *const viewname = viewnode->get_attribute_string("name", nullptr); if (!viewname) @@ -3297,8 +3342,20 @@ void render_manager::resolve_tags() void render_manager::config_load(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode) { // we only care about system-specific configuration with matching nodes - if ((cfg_type != config_type::SYSTEM) || !parentnode) + if (cfg_type == config_type::DEFAULT) + { + // let the targets stabilise themselves + for (render_target &target : m_targetlist) + { + if (!target.hidden()) + target.config_load(nullptr); + } return; + } + else if ((cfg_type != config_type::SYSTEM) || !parentnode) + { + return; + } // check the UI target util::xml::data_node const *const uinode = parentnode->get_child("interface"); @@ -3314,7 +3371,7 @@ void render_manager::config_load(config_type cfg_type, config_level cfg_level, u { render_target *const target = target_by_index(targetnode->get_attribute_int("index", -1)); if (target && !target->hidden()) - target->config_load(*targetnode); + target->config_load(targetnode); } // iterate over screen nodes diff --git a/src/emu/render.h b/src/emu/render.h index d4f99377d70..27205206d1f 100644 --- a/src/emu/render.h +++ b/src/emu/render.h @@ -47,18 +47,11 @@ #define MAME_EMU_RENDER_H #include "rendertypes.h" -#include "screen.h" -#include <array> #include <cmath> -#include <functional> -#include <map> +#include <list> #include <memory> #include <mutex> -#include <string> -#include <string_view> -#include <tuple> -#include <unordered_map> #include <utility> #include <vector> @@ -586,7 +579,7 @@ private: std::pair<float, float> map_point_internal(s32 target_x, s32 target_y); // config callbacks - void config_load(util::xml::data_node const &targetnode); + void config_load(util::xml::data_node const *targetnode); bool config_save(util::xml::data_node &targetnode); // view lookups diff --git a/src/emu/rendertypes.h b/src/emu/rendertypes.h index 43f2ebb85e7..b3eed6ad9bd 100644 --- a/src/emu/rendertypes.h +++ b/src/emu/rendertypes.h @@ -20,6 +20,16 @@ //************************************************************************** +// texture formats +enum texture_format +{ + TEXFORMAT_UNDEFINED = 0, // require a format to be specified + TEXFORMAT_PALETTE16, // 16bpp palettized, no alpha + TEXFORMAT_RGB32, // 32bpp 8-8-8 RGB + TEXFORMAT_ARGB32, // 32bpp 8-8-8-8 ARGB + TEXFORMAT_YUY16 // 16bpp 8-8 Y/Cb, Y/Cr in sequence +}; + // blending modes enum { diff --git a/src/emu/rendfont.cpp b/src/emu/rendfont.cpp index ae295e39e2d..3d79f0e6ac2 100644 --- a/src/emu/rendfont.cpp +++ b/src/emu/rendfont.cpp @@ -10,7 +10,10 @@ #include "emu.h" #include "rendfont.h" + #include "emuopts.h" +#include "fileio.h" + #include "corestr.h" #include "coreutil.h" @@ -121,13 +124,15 @@ public: static constexpr unsigned MAJVERSION = 1; static constexpr unsigned MINVERSION = 0; - bool read(emu_file &f) + bool read(util::read_stream &f) { - return f.read(m_data, sizeof(m_data)) == sizeof(m_data); + std::size_t actual(0); + return !f.read(m_data, sizeof(m_data), actual) && actual == sizeof(m_data); } - bool write(emu_file &f) + bool write(util::write_stream &f) { - return f.write(m_data, sizeof(m_data)) == sizeof(m_data); + std::size_t actual(0); + return !f.write(m_data, sizeof(m_data), actual) && actual == sizeof(m_data); } bool check_magic() const @@ -593,10 +598,9 @@ render_font::render_font(render_manager &manager, const char *filename) } // load the compiled in data instead - emu_file ramfile(OPEN_FLAG_READ); - std::error_condition const filerr(ramfile.open_ram(font_uismall, sizeof(font_uismall))); - if (!filerr) - load_cached(ramfile, 0, 0); + util::random_read::ptr ramfile = util::ram_read(font_uismall, sizeof(font_uismall)); + if (ramfile) + load_cached(*ramfile, 0, 0); render_font_command_glyph(); } @@ -906,11 +910,11 @@ float render_font::utf8string_width(float height, float aspect, std::string_view // and create a new cached version //------------------------------------------------- -bool render_font::load_cached_bdf(const char *filename) +bool render_font::load_cached_bdf(std::string_view filename) { std::error_condition filerr; u32 chunk; - u64 bytes; + std::size_t bytes; // first try to open the BDF itself emu_file file(m_manager.machine().options().font_path(), OPEN_FLAG_READ); @@ -943,9 +947,7 @@ bool render_font::load_cached_bdf(const char *filename) u32 const hash(core_crc32(0, reinterpret_cast<u8 const *>(&m_rawdata[0]), bytes)); // create the cached filename, changing the 'F' to a 'C' on the extension - std::string cachedname(filename); - if ((4U < cachedname.length()) && !core_stricmp(&cachedname[cachedname.length() - 4], ".bdf")) - cachedname.erase(cachedname.length() - 4); + std::string cachedname(filename, 0, filename.length() - ((4U < filename.length()) && core_filename_ends_with(filename, ".bdf") ? 4 : 0)); cachedname.append(".bdc"); // attempt to open the cached version of the font @@ -978,11 +980,25 @@ bool render_font::load_cached_bdf(const char *filename) m_rawdata[m_rawsize] = '\0'; // load the BDF - bool const result = load_bdf(); + bool result = load_bdf(); // if we loaded okay, create a cached one if (result) - save_cached(cachedname.c_str(), m_rawsize, hash); + { + osd_printf_info("Generating cached BDF font...\n"); + + // attempt to open the file + emu_file cachefile(m_manager.machine().options().font_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE); + filerr = cachefile.open(cachedname); + if (filerr) + result = false; + else + { + result = save_cached(cachefile, m_rawsize, hash); + if (!result) + cachefile.remove_on_close(); + } + } else m_rawdata.clear(); @@ -1324,7 +1340,7 @@ bool render_font::load_bdf() // some progress for big fonts if (0 == (++charcount % 256)) - osd_printf_warning("Loading BDF font... (%d characters loaded)\n", charcount); + osd_printf_info("Loading BDF font... (%d characters loaded)\n", charcount); } } @@ -1344,12 +1360,17 @@ bool render_font::load_bdf() // load_cached - load a font in cached format //------------------------------------------------- -bool render_font::load_cached(emu_file &file, u64 length, u32 hash) +bool render_font::load_cached(util::random_read &file, u64 length, u32 hash) { // get the file size, read the header, and check that it looks good - u64 const filesize(file.size()); + u64 filesize; bdc_header header; - if (!header.read(file)) + if (file.length(filesize)) + { + LOG("render_font::load_cached: error determining size of BDC file\n"); + return false; + } + else if (!header.read(file)) { osd_printf_warning("render_font::load_cached: error reading BDC header\n"); return false; @@ -1371,14 +1392,20 @@ bool render_font::load_cached(emu_file &file, u64 length, u32 hash) m_yoffs = header.get_y_offset(); m_defchar = header.get_default_character(); u32 const numchars(header.get_glyph_count()); - if ((file.tell() + (u64(numchars) * bdc_table_entry::size())) > filesize) + u64 filepos; + if (file.tell(filepos)) + { + LOG("render_font::load_cached: failed to determine position in BDC file\n"); + return false; + } + else if ((filepos + (u64(numchars) * bdc_table_entry::size())) > filesize) { LOG("render_font::load_cached: BDC file is too small to hold glyph table\n"); return false; } // now read the rest of the data - u64 const remaining(filesize - file.tell()); + u64 const remaining(filesize - filepos); try { m_rawdata.resize(std::size_t(remaining)); @@ -1390,7 +1417,8 @@ bool render_font::load_cached(emu_file &file, u64 length, u32 hash) for (u64 bytes_read = 0; remaining > bytes_read; ) { u32 const chunk((std::min)(u64(std::numeric_limits<u32>::max()), remaining)); - if (file.read(&m_rawdata[bytes_read], chunk) != chunk) + std::size_t bytes(0); + if (file.read(&m_rawdata[bytes_read], chunk, bytes) || bytes != chunk) { osd_printf_error("render_font::load_cached: error reading BDC data\n"); m_rawdata.clear(); @@ -1450,16 +1478,8 @@ bool render_font::load_cached(emu_file &file, u64 length, u32 hash) // save_cached - save a font in cached format //------------------------------------------------- -bool render_font::save_cached(const char *filename, u64 length, u32 hash) +bool render_font::save_cached(util::random_write &file, u64 length, u32 hash) { - osd_printf_warning("Generating cached BDF font...\n"); - - // attempt to open the file - emu_file file(m_manager.machine().options().font_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE); - std::error_condition const filerr = file.open(filename); - if (filerr) - return false; - // count glyphs unsigned numchars = 0; for (glyph const *const page : m_glyphs) @@ -1474,8 +1494,6 @@ bool render_font::save_cached(const char *filename, u64 length, u32 hash) try { - u32 bytes_written; - { LOG("render_font::save_cached: writing header\n"); bdc_header hdr; @@ -1490,7 +1508,9 @@ bool render_font::save_cached(const char *filename, u64 length, u32 hash) if (!hdr.write(file)) throw emu_fatalerror("Error writing cached file"); } - u64 const table_offs(file.tell()); + u64 table_offs; + if (file.tell(table_offs)) + throw emu_fatalerror("Error writing cached file"); // allocate an array to hold the character data std::vector<u8> chartable(std::size_t(numchars) * bdc_table_entry::size(), 0); @@ -1499,8 +1519,8 @@ bool render_font::save_cached(const char *filename, u64 length, u32 hash) std::vector<u8> tempbuffer(65536); // write the empty table to the beginning of the file - bytes_written = file.write(&chartable[0], chartable.size()); - if (bytes_written != chartable.size()) + std::size_t bytes_written(0); + if (file.write(&chartable[0], chartable.size(), bytes_written) || bytes_written != chartable.size()) throw emu_fatalerror("Error writing cached file"); // loop over all characters @@ -1543,8 +1563,7 @@ bool render_font::save_cached(const char *filename, u64 length, u32 hash) *dest++ = accum; // write the data - bytes_written = file.write(&tempbuffer[0], dest - &tempbuffer[0]); - if (bytes_written != dest - &tempbuffer[0]) + if (file.write(&tempbuffer[0], dest - &tempbuffer[0], bytes_written) || bytes_written != dest - &tempbuffer[0]) throw emu_fatalerror("Error writing cached file"); // free the bitmap and texture @@ -1568,13 +1587,13 @@ bool render_font::save_cached(const char *filename, u64 length, u32 hash) if (!chartable.empty()) { LOG("render_font::save_cached: writing character table\n"); - file.seek(table_offs, SEEK_SET); + if (file.seek(table_offs, SEEK_SET)) + return false; u8 const *bytes(&chartable[0]); for (u64 remaining = chartable.size(); remaining; ) { u32 const chunk((std::min<u64>)(std::numeric_limits<u32>::max(), remaining)); - bytes_written = file.write(bytes, chunk); - if (chunk != bytes_written) + if (file.write(bytes, chunk, bytes_written) || chunk != bytes_written) throw emu_fatalerror("Error writing cached file"); bytes += chunk; remaining -= chunk; @@ -1586,7 +1605,6 @@ bool render_font::save_cached(const char *filename, u64 length, u32 hash) } catch (...) { - file.remove_on_close(); return false; } } @@ -1595,13 +1613,13 @@ bool render_font::save_cached(const char *filename, u64 length, u32 hash) void render_font::render_font_command_glyph() { // FIXME: this is copy/pasta from the BDC loading, and it shouldn't be injected into every font - emu_file file(OPEN_FLAG_READ); - if (!file.open_ram(font_uicmd14, sizeof(font_uicmd14))) + util::random_read::ptr file = util::ram_read(font_uicmd14, sizeof(font_uicmd14)); + if (file) { // get the file size, read the header, and check that it looks good - u64 const filesize(file.size()); + u64 const filesize = sizeof(font_uicmd14); bdc_header header; - if (!header.read(file)) + if (!header.read(*file)) { osd_printf_warning("render_font::render_font_command_glyph: error reading BDC header\n"); return; @@ -1616,14 +1634,20 @@ void render_font::render_font_command_glyph() m_height_cmd = header.get_height(); m_yoffs_cmd = header.get_y_offset(); u32 const numchars(header.get_glyph_count()); - if ((file.tell() + (u64(numchars) * bdc_table_entry::size())) > filesize) + u64 filepos; + if (file->tell(filepos)) + { + LOG("render_font::render_font_command_glyph: failed to determine position in BDC file\n"); + return; + } + else if ((filepos + (u64(numchars) * bdc_table_entry::size())) > filesize) { LOG("render_font::render_font_command_glyph: BDC file is too small to hold glyph table\n"); return; } // now read the rest of the data - u64 const remaining(filesize - file.tell()); + u64 const remaining(filesize - filepos); try { m_rawdata_cmd.resize(std::size_t(remaining)); @@ -1635,7 +1659,8 @@ void render_font::render_font_command_glyph() for (u64 bytes_read = 0; remaining > bytes_read; ) { u32 const chunk((std::min)(u64(std::numeric_limits<u32>::max()), remaining)); - if (file.read(&m_rawdata_cmd[bytes_read], chunk) != chunk) + std::size_t bytes(0); + if (file->read(&m_rawdata_cmd[bytes_read], chunk, bytes) || bytes != chunk) { osd_printf_error("render_font::render_font_command_glyph: error reading BDC data\n"); m_rawdata_cmd.clear(); diff --git a/src/emu/rendfont.h b/src/emu/rendfont.h index 15f6754657b..2d812860ae4 100644 --- a/src/emu/rendfont.h +++ b/src/emu/rendfont.h @@ -82,10 +82,10 @@ private: // helpers glyph &get_char(char32_t chnum); void char_expand(char32_t chnum, glyph &ch); - bool load_cached_bdf(const char *filename); + bool load_cached_bdf(std::string_view filename); bool load_bdf(); - bool load_cached(emu_file &file, u64 length, u32 hash); - bool save_cached(const char *filename, u64 length, u32 hash); + bool load_cached(util::random_read &file, u64 length, u32 hash); + bool save_cached(util::random_write &file, u64 length, u32 hash); void render_font_command_glyph(); diff --git a/src/emu/rendlay.cpp b/src/emu/rendlay.cpp index 28011b8372c..ffe680fa625 100644 --- a/src/emu/rendlay.cpp +++ b/src/emu/rendlay.cpp @@ -13,6 +13,7 @@ #include "rendlay.h" #include "emuopts.h" +#include "fileio.h" #include "rendfont.h" #include "rendutil.h" #include "video/rgbutil.h" @@ -1249,7 +1250,6 @@ layout_element::make_component_map const layout_element::s_make_component{ { "simplecounter", &make_component<simplecounter_component> }, { "reel", &make_component<reel_component> }, { "led7seg", &make_component<led7seg_component> }, - { "led8seg_gts1", &make_component<led8seg_gts1_component> }, { "led14seg", &make_component<led14seg_component> }, { "led14segsc", &make_component<led14segsc_component> }, { "led16seg", &make_component<led16seg_component> }, @@ -2109,7 +2109,7 @@ protected: } else if (c.a) { - // compute premultiplied colors + // compute premultiplied color u32 const a(c.a * 255.0F); u32 const r(u32(c.r * (255.0F * 255.0F)) * a); u32 const g(u32(c.g * (255.0F * 255.0F)) * a); @@ -2145,9 +2145,9 @@ public: render_color const c(color(state)); u32 const f(rgb_t(u8(c.r * 255), u8(c.g * 255), u8(c.b * 255))); u32 const a(c.a * 255.0F); - u32 const r(c.r * c.a * (255.0F * 255.0F * 255.0F)); - u32 const g(c.g * c.a * (255.0F * 255.0F * 255.0F)); - u32 const b(c.b * c.a * (255.0F * 255.0F * 255.0F)); + u32 const r(c.r * (255.0F * 255.0F) * a); + u32 const g(c.g * (255.0F * 255.0F) * a); + u32 const b(c.b * (255.0F * 255.0F) * a); u32 const inva(255 - a); if (!a) return; @@ -2519,74 +2519,6 @@ protected: }; -// 8-segment fluorescent (Gottlieb System 1) -class layout_element::led8seg_gts1_component : public component -{ -public: - // construction/destruction - led8seg_gts1_component(environment &env, util::xml::data_node const &compnode) - : component(env, compnode) - { - } - -protected: - // overrides - virtual int maxstate() const override { return 255; } - - virtual void draw_aligned(running_machine &machine, bitmap_argb32 &dest, const rectangle &bounds, int state) override - { - rgb_t const onpen = rgb_t(0xff, 0xff, 0xff, 0xff); - rgb_t const offpen = rgb_t(0x20, 0xff, 0xff, 0xff); - rgb_t const backpen = rgb_t(0x00, 0x00, 0x00, 0x00); - - // sizes for computation - int const bmwidth = 250; - int const bmheight = 400; - int const segwidth = 40; - int const skewwidth = 40; - - // allocate a temporary bitmap for drawing - bitmap_argb32 tempbitmap(bmwidth + skewwidth, bmheight); - tempbitmap.fill(backpen); - - // top bar - draw_segment_horizontal(tempbitmap, 0 + 2*segwidth/3, bmwidth - 2*segwidth/3, 0 + segwidth/2, segwidth, (state & (1 << 0)) ? onpen : offpen); - - // top-right bar - draw_segment_vertical(tempbitmap, 0 + 2*segwidth/3, bmheight/2 - segwidth/3, bmwidth - segwidth/2, segwidth, (state & (1 << 1)) ? onpen : offpen); - - // bottom-right bar - draw_segment_vertical(tempbitmap, bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, bmwidth - segwidth/2, segwidth, (state & (1 << 2)) ? onpen : offpen); - - // bottom bar - draw_segment_horizontal(tempbitmap, 0 + 2*segwidth/3, bmwidth - 2*segwidth/3, bmheight - segwidth/2, segwidth, (state & (1 << 3)) ? onpen : offpen); - - // bottom-left bar - draw_segment_vertical(tempbitmap, bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, 0 + segwidth/2, segwidth, (state & (1 << 4)) ? onpen : offpen); - - // top-left bar - draw_segment_vertical(tempbitmap, 0 + 2*segwidth/3, bmheight/2 - segwidth/3, 0 + segwidth/2, segwidth, (state & (1 << 5)) ? onpen : offpen); - - // horizontal bars - draw_segment_horizontal(tempbitmap, 0 + 2*segwidth/3, 2*bmwidth/3 - 2*segwidth/3, bmheight/2, segwidth, (state & (1 << 6)) ? onpen : offpen); - draw_segment_horizontal(tempbitmap, 0 + 2*segwidth/3 + bmwidth/2, bmwidth - 2*segwidth/3, bmheight/2, segwidth, (state & (1 << 6)) ? onpen : offpen); - - // vertical bars - draw_segment_vertical(tempbitmap, 0 + segwidth/3 - 8, bmheight/2 - segwidth/3 + 2, 2*bmwidth/3 - segwidth/2 - 4, segwidth + 8, backpen); - draw_segment_vertical(tempbitmap, 0 + segwidth/3, bmheight/2 - segwidth/3, 2*bmwidth/3 - segwidth/2 - 4, segwidth, (state & (1 << 7)) ? onpen : offpen); - - draw_segment_vertical(tempbitmap, bmheight/2 + segwidth/3 - 2, bmheight - segwidth/3 + 8, 2*bmwidth/3 - segwidth/2 - 4, segwidth + 8, backpen); - draw_segment_vertical(tempbitmap, bmheight/2 + segwidth/3, bmheight - segwidth/3, 2*bmwidth/3 - segwidth/2 - 4, segwidth, (state & (1 << 7)) ? onpen : offpen); - - // apply skew - apply_skew(tempbitmap, 40); - - // resample to the target size - render_resample_argb_bitmap_hq(dest, tempbitmap, color(state)); - } -}; - - // 14-segment LCD class layout_element::led14seg_component : public component { @@ -3177,7 +3109,7 @@ protected: // shift the reels a bit based on this param, allows fine tuning int use_state = (state + m_stateoffset) % max_state_used; - // compute premultiplied colors + // compute premultiplied color render_color const c(color(state)); u32 const r = c.r * 255.0f; u32 const g = c.g * 255.0f; @@ -3329,7 +3261,7 @@ private: // shift the reels a bit based on this param, allows fine tuning int use_state = (state + m_stateoffset) % max_state_used; - // compute premultiplied colors + // compute premultiplied color render_color const c(color(state)); u32 const r = c.r * 255.0f; u32 const g = c.g * 255.0f; @@ -3747,7 +3679,7 @@ void layout_element::component::draw_text( int align, const render_color &color) { - // compute premultiplied colors + // compute premultiplied color u32 const r(color.r * 255.0f); u32 const g(color.g * 255.0f); u32 const b(color.b * 255.0f); diff --git a/src/emu/rendlay.h b/src/emu/rendlay.h index da9edfcf752..29b38fdd5d0 100644 --- a/src/emu/rendlay.h +++ b/src/emu/rendlay.h @@ -16,6 +16,16 @@ #include "rendertypes.h" #include "screen.h" +#include <array> +#include <functional> +#include <map> +#include <memory> +#include <string> +#include <string_view> +#include <tuple> +#include <unordered_map> +#include <vector> + //************************************************************************** // TYPE DEFINITIONS @@ -113,16 +123,16 @@ private: virtual void draw_aligned(running_machine &machine, bitmap_argb32 &dest, const rectangle &bounds, int state); // drawing helpers - void draw_text(render_font &font, bitmap_argb32 &dest, const rectangle &bounds, std::string_view str, int align, const render_color &color); - void draw_segment_horizontal_caps(bitmap_argb32 &dest, int minx, int maxx, int midy, int width, int caps, rgb_t color); - void draw_segment_horizontal(bitmap_argb32 &dest, int minx, int maxx, int midy, int width, rgb_t color); - void draw_segment_vertical_caps(bitmap_argb32 &dest, int miny, int maxy, int midx, int width, int caps, rgb_t color); - void draw_segment_vertical(bitmap_argb32 &dest, int miny, int maxy, int midx, int width, rgb_t color); - void draw_segment_diagonal_1(bitmap_argb32 &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color); - void draw_segment_diagonal_2(bitmap_argb32 &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color); - void draw_segment_decimal(bitmap_argb32 &dest, int midx, int midy, int width, rgb_t color); - void draw_segment_comma(bitmap_argb32 &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color); - void apply_skew(bitmap_argb32 &dest, int skewwidth); + static void draw_text(render_font &font, bitmap_argb32 &dest, const rectangle &bounds, std::string_view str, int align, const render_color &color); + static void draw_segment_horizontal_caps(bitmap_argb32 &dest, int minx, int maxx, int midy, int width, int caps, rgb_t color); + static void draw_segment_horizontal(bitmap_argb32 &dest, int minx, int maxx, int midy, int width, rgb_t color); + static void draw_segment_vertical_caps(bitmap_argb32 &dest, int miny, int maxy, int midx, int width, int caps, rgb_t color); + static void draw_segment_vertical(bitmap_argb32 &dest, int miny, int maxy, int midx, int width, rgb_t color); + static void draw_segment_diagonal_1(bitmap_argb32 &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color); + static void draw_segment_diagonal_2(bitmap_argb32 &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color); + static void draw_segment_decimal(bitmap_argb32 &dest, int midx, int midy, int width, rgb_t color); + static void draw_segment_comma(bitmap_argb32 &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color); + static void apply_skew(bitmap_argb32 &dest, int skewwidth); private: using bounds_vector = emu::render::detail::bounds_vector; @@ -141,7 +151,6 @@ private: class disk_component; class text_component; class led7seg_component; - class led8seg_gts1_component; class led14seg_component; class led16seg_component; class led14segsc_component; @@ -173,7 +182,6 @@ private: // internal helpers static void element_scale(bitmap_argb32 &dest, bitmap_argb32 &source, const rectangle &sbounds, void *param); template <typename T> static component::ptr make_component(environment &env, util::xml::data_node const &compnode); - template <int D> static component::ptr make_dotmatrix_component(environment &env, util::xml::data_node const &compnode); static make_component_map const s_make_component; // maps component XML names to creator functions @@ -281,7 +289,7 @@ public: // interactivity bool has_input() const { return bool(m_input_port); } - std::pair<ioport_port *, ioport_value> input_tag_and_mask() const { return std::make_pair(m_input_port, m_input_mask); }; + std::pair<ioport_port *, ioport_value> input_tag_and_mask() const { return std::make_pair(m_input_port, m_input_mask); } bool clickthrough() const { return m_clickthrough; } // fetch state based on configured source diff --git a/src/emu/rendutil.cpp b/src/emu/rendutil.cpp index 2d0a823db28..cffef8263d7 100644 --- a/src/emu/rendutil.cpp +++ b/src/emu/rendutil.cpp @@ -19,6 +19,7 @@ #include <csetjmp> #include <cstdlib> +#include <tuple> namespace { @@ -375,118 +376,118 @@ static void resample_argb_bitmap_bilinear(u32 *dest, u32 drowpixels, u32 dwidth, } -/*------------------------------------------------- - render_clip_line - clip a line to a rectangle --------------------------------------------------*/ +//------------------------------------------------- +// render_clip_line - clip a line to a rectangle +//------------------------------------------------- -bool render_clip_line(render_bounds *bounds, const render_bounds *clip) +bool render_clip_line(render_bounds &bounds, const render_bounds &clip) { - /* loop until we get a final result */ - while (1) + // loop until we get a final result + while (true) { u8 code0 = 0, code1 = 0; u8 thiscode; float x, y; - /* compute Cohen Sutherland bits for first coordinate */ - if (bounds->y0 > clip->y1) + // compute Cohen Sutherland bits for first coordinate + if (bounds.y0 > clip.y1) code0 |= 1; - if (bounds->y0 < clip->y0) + if (bounds.y0 < clip.y0) code0 |= 2; - if (bounds->x0 > clip->x1) + if (bounds.x0 > clip.x1) code0 |= 4; - if (bounds->x0 < clip->x0) + if (bounds.x0 < clip.x0) code0 |= 8; - /* compute Cohen Sutherland bits for second coordinate */ - if (bounds->y1 > clip->y1) + // compute Cohen Sutherland bits for second coordinate + if (bounds.y1 > clip.y1) code1 |= 1; - if (bounds->y1 < clip->y0) + if (bounds.y1 < clip.y0) code1 |= 2; - if (bounds->x1 > clip->x1) + if (bounds.x1 > clip.x1) code1 |= 4; - if (bounds->x1 < clip->x0) + if (bounds.x1 < clip.x0) code1 |= 8; - /* trivial accept: just return false */ + // trivial accept: just return false if ((code0 | code1) == 0) return false; - /* trivial reject: just return true */ + // trivial reject: just return true if ((code0 & code1) != 0) return true; - /* fix one of the OOB cases */ + // fix one of the OOB cases thiscode = code0 ? code0 : code1; - /* off the bottom */ + // off the bottom if (thiscode & 1) { - x = bounds->x0 + (bounds->x1 - bounds->x0) * (clip->y1 - bounds->y0) / (bounds->y1 - bounds->y0); - y = clip->y1; + x = bounds.x0 + (bounds.x1 - bounds.x0) * (clip.y1 - bounds.y0) / (bounds.y1 - bounds.y0); + y = clip.y1; } - /* off the top */ + // off the top else if (thiscode & 2) { - x = bounds->x0 + (bounds->x1 - bounds->x0) * (clip->y0 - bounds->y0) / (bounds->y1 - bounds->y0); - y = clip->y0; + x = bounds.x0 + (bounds.x1 - bounds.x0) * (clip.y0 - bounds.y0) / (bounds.y1 - bounds.y0); + y = clip.y0; } - /* off the right */ + // off the right else if (thiscode & 4) { - y = bounds->y0 + (bounds->y1 - bounds->y0) * (clip->x1 - bounds->x0) / (bounds->x1 - bounds->x0); - x = clip->x1; + y = bounds.y0 + (bounds.y1 - bounds.y0) * (clip.x1 - bounds.x0) / (bounds.x1 - bounds.x0); + x = clip.x1; } - /* off the left */ + // off the left else { - y = bounds->y0 + (bounds->y1 - bounds->y0) * (clip->x0 - bounds->x0) / (bounds->x1 - bounds->x0); - x = clip->x0; + y = bounds.y0 + (bounds.y1 - bounds.y0) * (clip.x0 - bounds.x0) / (bounds.x1 - bounds.x0); + x = clip.x0; } - /* fix the appropriate coordinate */ + // fix the appropriate coordinate if (thiscode == code0) { - bounds->x0 = x; - bounds->y0 = y; + bounds.x0 = x; + bounds.y0 = y; } else { - bounds->x1 = x; - bounds->y1 = y; + bounds.x1 = x; + bounds.y1 = y; } } } -/*------------------------------------------------- - render_clip_quad - clip a quad to a rectangle --------------------------------------------------*/ +//------------------------------------------------- +// render_clip_quad - clip a quad to a rectangle +//------------------------------------------------- -bool render_clip_quad(render_bounds *bounds, const render_bounds *clip, render_quad_texuv *texcoords) +bool render_clip_quad(render_bounds &bounds, const render_bounds &clip, render_quad_texuv *texcoords) { - /* ensure our assumptions about the bounds are correct */ - assert(bounds->x0 <= bounds->x1); - assert(bounds->y0 <= bounds->y1); + // ensure our assumptions about the bounds are correct + assert(bounds.x0 <= bounds.x1); + assert(bounds.y0 <= bounds.y1); - /* trivial reject */ - if (bounds->y1 < clip->y0) + // trivial reject + if (bounds.y1 < clip.y0) return true; - if (bounds->y0 > clip->y1) + if (bounds.y0 > clip.y1) return true; - if (bounds->x1 < clip->x0) + if (bounds.x1 < clip.x0) return true; - if (bounds->x0 > clip->x1) + if (bounds.x0 > clip.x1) return true; - /* clip top (x0,y0)-(x1,y1) */ - if (bounds->y0 < clip->y0) + // clip top (x0,y0)-(x1,y1) + if (bounds.y0 < clip.y0) { - float frac = (clip->y0 - bounds->y0) / (bounds->y1 - bounds->y0); - bounds->y0 = clip->y0; + float frac = (clip.y0 - bounds.y0) / (bounds.y1 - bounds.y0); + bounds.y0 = clip.y0; if (texcoords != nullptr) { texcoords->tl.u += (texcoords->bl.u - texcoords->tl.u) * frac; @@ -496,11 +497,11 @@ bool render_clip_quad(render_bounds *bounds, const render_bounds *clip, render_q } } - /* clip bottom (x3,y3)-(x2,y2) */ - if (bounds->y1 > clip->y1) + // clip bottom (x3,y3)-(x2,y2) + if (bounds.y1 > clip.y1) { - float frac = (bounds->y1 - clip->y1) / (bounds->y1 - bounds->y0); - bounds->y1 = clip->y1; + float frac = (bounds.y1 - clip.y1) / (bounds.y1 - bounds.y0); + bounds.y1 = clip.y1; if (texcoords != nullptr) { texcoords->bl.u -= (texcoords->bl.u - texcoords->tl.u) * frac; @@ -510,11 +511,11 @@ bool render_clip_quad(render_bounds *bounds, const render_bounds *clip, render_q } } - /* clip left (x0,y0)-(x3,y3) */ - if (bounds->x0 < clip->x0) + // clip left (x0,y0)-(x3,y3) + if (bounds.x0 < clip.x0) { - float frac = (clip->x0 - bounds->x0) / (bounds->x1 - bounds->x0); - bounds->x0 = clip->x0; + float frac = (clip.x0 - bounds.x0) / (bounds.x1 - bounds.x0); + bounds.x0 = clip.x0; if (texcoords != nullptr) { texcoords->tl.u += (texcoords->tr.u - texcoords->tl.u) * frac; @@ -524,11 +525,11 @@ bool render_clip_quad(render_bounds *bounds, const render_bounds *clip, render_q } } - /* clip right (x1,y1)-(x2,y2) */ - if (bounds->x1 > clip->x1) + // clip right (x1,y1)-(x2,y2) + if (bounds.x1 > clip.x1) { - float frac = (bounds->x1 - clip->x1) / (bounds->x1 - bounds->x0); - bounds->x1 = clip->x1; + float frac = (bounds.x1 - clip.x1) / (bounds.x1 - bounds.x0); + bounds.x1 = clip.x1; if (texcoords != nullptr) { texcoords->tr.u -= (texcoords->tr.u - texcoords->tl.u) * frac; @@ -541,14 +542,14 @@ bool render_clip_quad(render_bounds *bounds, const render_bounds *clip, render_q } -/*------------------------------------------------- - render_line_to_quad - convert a line and a - width to four points --------------------------------------------------*/ +//------------------------------------------------- +// render_line_to_quad - convert a line and a +// width to four points +//----------------------------------------------- -void render_line_to_quad(const render_bounds *bounds, float width, float length_extension, render_bounds *bounds0, render_bounds *bounds1) +std::pair<render_bounds, render_bounds> render_line_to_quad(const render_bounds &bounds, float width, float length_extension) { - render_bounds modbounds = *bounds; + render_bounds modbounds = bounds; /* High-level logic -- due to math optimizations, this info is lost below. @@ -595,18 +596,18 @@ void render_line_to_quad(const render_bounds *bounds, float width, float length_ D.y = p1.y - 0.5 * w * u.x */ - /* we only care about the half-width */ + // we only care about the half-width float half_width = width * 0.5f; - /* compute a vector from point 0 to point 1 */ + // compute a vector from point 0 to point 1 float unitx = modbounds.x1 - modbounds.x0; float unity = modbounds.y1 - modbounds.y0; - /* points just use a +1/+1 unit vector; this gives a nice diamond pattern */ + // points just use a +1/+1 unit vector; this gives a nice diamond pattern if (unitx == 0 && unity == 0) { - /* length of a unit vector (1,1) */ - float unit_length = 0.70710678f; + // length of a unit vector (1,1) + constexpr float unit_length = 0.70710678f; unitx = unity = unit_length * half_width; modbounds.x0 -= unitx; @@ -615,12 +616,12 @@ void render_line_to_quad(const render_bounds *bounds, float width, float length_ modbounds.y1 += unity; } - /* lines need to be divided by their length */ + // lines need to be divided by their length else { float length = sqrtf(unitx * unitx + unity * unity); - /* extend line length */ + // extend line length if (length_extension > 0.0f) { float half_length_extension = length_extension *0.5f; @@ -634,27 +635,16 @@ void render_line_to_quad(const render_bounds *bounds, float width, float length_ modbounds.y1 += directiony * half_length_extension; } - /* prescale unitx and unity by the half-width */ + // prescale unitx and unity by the half-width float invlength = half_width / length; unitx *= invlength; unity *= invlength; } - /* rotate the unit vector by 90 degrees and add to point 0 */ - bounds0->x0 = modbounds.x0 - unity; - bounds0->y0 = modbounds.y0 + unitx; - - /* rotate the unit vector by -90 degrees and add to point 0 */ - bounds0->x1 = modbounds.x0 + unity; - bounds0->y1 = modbounds.y0 - unitx; - - /* rotate the unit vector by 90 degrees and add to point 1 */ - bounds1->x0 = modbounds.x1 - unity; - bounds1->y0 = modbounds.y1 + unitx; - - /* rotate the unit vector by -90 degrees and add to point 1 */ - bounds1->x1 = modbounds.x1 + unity; - bounds1->y1 = modbounds.y1 - unitx; + // rotate the unit vector by 90 and -90 degrees and add to points 0 and 1 + return std::make_pair( + render_bounds{ modbounds.x0 - unity, modbounds.y0 + unitx, modbounds.x0 + unity, modbounds.y0 - unitx }, + render_bounds{ modbounds.x1 - unity, modbounds.y1 + unitx, modbounds.x1 + unity, modbounds.y1 - unitx }); } diff --git a/src/emu/rendutil.h b/src/emu/rendutil.h index 4d2b89567e3..1ffcdf41263 100644 --- a/src/emu/rendutil.h +++ b/src/emu/rendutil.h @@ -17,6 +17,7 @@ #include <algorithm> #include <cmath> +#include <utility> /* ----- image formats ----- */ @@ -40,9 +41,9 @@ enum ru_imgformat /* ----- render utilities ----- */ void render_resample_argb_bitmap_hq(bitmap_argb32 &dest, bitmap_argb32 &source, const render_color &color, bool force = false); -bool render_clip_line(render_bounds *bounds, const render_bounds *clip); -bool render_clip_quad(render_bounds *bounds, const render_bounds *clip, render_quad_texuv *texcoords); -void render_line_to_quad(const render_bounds *bounds, float width, float length_extension, render_bounds *bounds0, render_bounds *bounds1); +bool render_clip_line(render_bounds &bounds, const render_bounds &clip); +bool render_clip_quad(render_bounds &bounds, const render_bounds &clip, render_quad_texuv *texcoords); +std::pair<render_bounds, render_bounds> render_line_to_quad(const render_bounds &bounds, float width, float length_extension); void render_load_msdib(bitmap_argb32 &bitmap, util::random_read &file); void render_load_jpeg(bitmap_argb32 &bitmap, util::random_read &file); bool render_load_png(bitmap_argb32 &bitmap, util::random_read &file, bool load_as_alpha_to_existing = false); diff --git a/src/emu/romload.cpp b/src/emu/romload.cpp index c4c3101bc89..4ce34832c78 100644 --- a/src/emu/romload.cpp +++ b/src/emu/romload.cpp @@ -11,12 +11,14 @@ #include "emu.h" #include "romload.h" -#include "corestr.h" -#include "emuopts.h" #include "drivenum.h" +#include "emuopts.h" +#include "fileio.h" #include "softlist_dev.h" #include "ui/uimain.h" +#include "corestr.h" + #include <algorithm> #include <set> @@ -1070,7 +1072,13 @@ void rom_load_manager::process_disk_entries(std::initializer_list<std::reference err = do_open_disk(machine().options(), searchpath, romp, chd->orig_chd(), next_parent); if (err) { - handle_missing_file(romp, std::vector<std::string>(), err); + std::vector<std::string> tried; + for (auto const &paths : searchpath) + { + for (std::string const &path : paths.get()) + tried.emplace_back(path); + } + handle_missing_file(romp, tried, err); chd = nullptr; continue; } @@ -1200,7 +1208,7 @@ void rom_load_manager::normalize_flags_for_device(std::string_view rgntag, u8 &w /*------------------------------------------------- load_software_part_region - load a software part - This is used by MESS when loading a piece of + This is used by MAME when loading a piece of software. The code should be merged with process_region_list or updated to use a slight more general process_region_list. @@ -1220,7 +1228,7 @@ void rom_load_manager::load_software_part_region(device_t &device, software_list const software_info *const swinfo = swlist.find(std::string(swname)); if (swinfo) { - // dispay a warning for unsupported software + // display a warning for unsupported software // TODO: list supported clones like we do for machines? if (swinfo->supported() == software_support::PARTIALLY_SUPPORTED) { diff --git a/src/emu/save.cpp b/src/emu/save.cpp index a27a98ee23c..b8acfa24b0a 100644 --- a/src/emu/save.cpp +++ b/src/emu/save.cpp @@ -208,7 +208,7 @@ void save_manager::save_memory(device_t *device, const char *module, const char // state //------------------------------------------------- -save_error save_manager::check_file(running_machine &machine, emu_file &file, const char *gamename, void (CLIB_DECL *errormsg)(const char *fmt, ...)) +save_error save_manager::check_file(running_machine &machine, util::core_file &file, const char *gamename, void (CLIB_DECL *errormsg)(const char *fmt, ...)) { // if we want to validate the signature, compute it u32 sig; @@ -217,7 +217,8 @@ save_error save_manager::check_file(running_machine &machine, emu_file &file, co // seek to the beginning and read the header file.seek(0, SEEK_SET); u8 header[HEADER_SIZE]; - if (file.read(header, sizeof(header)) != sizeof(header)) + size_t actual(0); + if (file.read(header, sizeof(header), actual) || actual != sizeof(header)) { if (errormsg != nullptr) (*errormsg)("Could not read %s save file header",emulator_info::get_appname()); @@ -257,7 +258,7 @@ void save_manager::dispatch_presave() // write_file - writes the data to a file //------------------------------------------------- -save_error save_manager::write_file(emu_file &file) +save_error save_manager::write_file(util::core_file &file) { util::write_stream::ptr writer; save_error err = do_write( @@ -290,7 +291,7 @@ save_error save_manager::write_file(emu_file &file) // read_file - read the data from a file //------------------------------------------------- -save_error save_manager::read_file(emu_file &file) +save_error save_manager::read_file(util::core_file &file) { util::read_stream::ptr reader; return do_read( diff --git a/src/emu/save.h b/src/emu/save.h index 2ea17ab9921..677f127853a 100644 --- a/src/emu/save.h +++ b/src/emu/save.h @@ -300,9 +300,9 @@ public: { save_pointer(nullptr, "global", nullptr, index, std::forward<ItemType>(value), element, valname, count); } // file processing - static save_error check_file(running_machine &machine, emu_file &file, const char *gamename, void (CLIB_DECL *errormsg)(const char *fmt, ...)); - save_error write_file(emu_file &file); - save_error read_file(emu_file &file); + static save_error check_file(running_machine &machine, util::core_file &file, const char *gamename, void (CLIB_DECL *errormsg)(const char *fmt, ...)); + save_error write_file(util::core_file &file); + save_error read_file(util::core_file &file); save_error write_stream(std::ostream &str); save_error read_stream(std::istream &str); diff --git a/src/emu/schedule.cpp b/src/emu/schedule.cpp index e32afb68f00..dd72dfa13b0 100644 --- a/src/emu/schedule.cpp +++ b/src/emu/schedule.cpp @@ -49,7 +49,6 @@ emu_timer::emu_timer() : m_next(nullptr), m_prev(nullptr), m_param(0), - m_ptr(nullptr), m_enabled(false), m_temporary(false), m_period(attotime::zero), @@ -75,7 +74,7 @@ emu_timer::~emu_timer() // re-allocated as a non-device timer //------------------------------------------------- -inline emu_timer &emu_timer::init(running_machine &machine, timer_expired_delegate callback, void *ptr, bool temporary) +inline emu_timer &emu_timer::init(running_machine &machine, timer_expired_delegate callback, bool temporary) { // ensure the entire timer state is clean m_machine = &machine; @@ -83,7 +82,6 @@ inline emu_timer &emu_timer::init(running_machine &machine, timer_expired_delega m_prev = nullptr; m_callback = callback; m_param = 0; - m_ptr = ptr; m_enabled = false; m_temporary = temporary; m_period = attotime::never; @@ -107,7 +105,7 @@ inline emu_timer &emu_timer::init(running_machine &machine, timer_expired_delega // re-allocated as a device timer //------------------------------------------------- -inline emu_timer &emu_timer::init(device_t &device, device_timer_id id, void *ptr, bool temporary) +inline emu_timer &emu_timer::init(device_t &device, device_timer_id id, bool temporary) { // ensure the entire timer state is clean m_machine = &device.machine(); @@ -115,7 +113,6 @@ inline emu_timer &emu_timer::init(device_t &device, device_timer_id id, void *pt m_prev = nullptr; m_callback = timer_expired_delegate(FUNC(emu_timer::device_timer_expired), this); m_param = 0; - m_ptr = ptr; m_enabled = false; m_temporary = temporary; m_period = attotime::never; @@ -296,7 +293,7 @@ inline void emu_timer::schedule_next_period() void emu_timer::dump() const { - machine().logerror("%p: en=%d temp=%d exp=%15s start=%15s per=%15s param=%d ptr=%p", this, m_enabled, m_temporary, m_expire.as_string(PRECISION), m_start.as_string(PRECISION), m_period.as_string(PRECISION), m_param, m_ptr); + machine().logerror("%p: en=%d temp=%d exp=%15s start=%15s per=%15s param=%d", this, m_enabled, m_temporary, m_expire.as_string(PRECISION), m_start.as_string(PRECISION), m_period.as_string(PRECISION), m_param); if (m_device == nullptr) if (m_callback.name() == nullptr) machine().logerror(" cb=NULL\n"); @@ -312,9 +309,9 @@ void emu_timer::dump() const // conditional jump on the hot path //------------------------------------------------- -void emu_timer::device_timer_expired(emu_timer &timer, void *ptr, s32 param) +void emu_timer::device_timer_expired(emu_timer &timer, s32 param) { - timer.m_device->timer_expired(timer, timer.m_id, param, ptr); + timer.m_device->timer_expired(timer, timer.m_id, param); } @@ -340,7 +337,7 @@ device_scheduler::device_scheduler(running_machine &machine) : m_quantum_minimum(ATTOSECONDS_IN_NSEC(1) / 1000) { // append a single never-expiring timer so there is always one in the list - m_timer_list = &m_timer_allocator.alloc()->init(machine, timer_expired_delegate(), nullptr, true); + m_timer_list = &m_timer_allocator.alloc()->init(machine, timer_expired_delegate(), true); m_timer_list->adjust(attotime::never); // register global states @@ -597,9 +594,9 @@ void device_scheduler::boost_interleave(const attotime ×lice_time, const at // timer and return a pointer //------------------------------------------------- -emu_timer *device_scheduler::timer_alloc(timer_expired_delegate callback, void *ptr) +emu_timer *device_scheduler::timer_alloc(timer_expired_delegate callback) { - return &m_timer_allocator.alloc()->init(machine(), callback, ptr, false); + return &m_timer_allocator.alloc()->init(machine(), callback, false); } @@ -609,9 +606,9 @@ emu_timer *device_scheduler::timer_alloc(timer_expired_delegate callback, void * // amount of time //------------------------------------------------- -void device_scheduler::timer_set(const attotime &duration, timer_expired_delegate callback, int param, void *ptr) +void device_scheduler::timer_set(const attotime &duration, timer_expired_delegate callback, int param) { - m_timer_allocator.alloc()->init(machine(), callback, ptr, true).adjust(duration, param); + m_timer_allocator.alloc()->init(machine(), callback, true).adjust(duration, param); } @@ -620,9 +617,9 @@ void device_scheduler::timer_set(const attotime &duration, timer_expired_delegat // and return a pointer //------------------------------------------------- -emu_timer *device_scheduler::timer_alloc(device_t &device, device_timer_id id, void *ptr) +emu_timer *device_scheduler::timer_alloc(device_t &device, device_timer_id id) { - return &m_timer_allocator.alloc()->init(device, id, ptr, false); + return &m_timer_allocator.alloc()->init(device, id, false); } @@ -632,9 +629,9 @@ emu_timer *device_scheduler::timer_alloc(device_t &device, device_timer_id id, v // time //------------------------------------------------- -void device_scheduler::timer_set(const attotime &duration, device_t &device, device_timer_id id, int param, void *ptr) +void device_scheduler::timer_set(const attotime &duration, device_t &device, device_timer_id id, int param) { - m_timer_allocator.alloc()->init(device, id, ptr, true).adjust(duration, param); + m_timer_allocator.alloc()->init(device, id, true).adjust(duration, param); } @@ -655,7 +652,7 @@ void device_scheduler::eat_all_cycles() // given amount of time //------------------------------------------------- -void device_scheduler::timed_trigger(void *ptr, s32 param) +void device_scheduler::timed_trigger(s32 param) { trigger(param); } @@ -904,7 +901,7 @@ inline void device_scheduler::execute_timers() LOG("execute_timers: timer device %s timer %d\n", timer.m_device->tag(), timer.m_id); else LOG("execute_timers: timer callback %s\n", timer.m_callback.name()); - timer.m_callback(timer.m_ptr, timer.m_param); + timer.m_callback(timer.m_param); } g_profiler.stop(); diff --git a/src/emu/schedule.h b/src/emu/schedule.h index 9e90ed68ed5..b194c8b2d1c 100644 --- a/src/emu/schedule.h +++ b/src/emu/schedule.h @@ -22,7 +22,7 @@ // MACROS //************************************************************************** -#define TIMER_CALLBACK_MEMBER(name) void name(void *ptr, s32 param) +#define TIMER_CALLBACK_MEMBER(name) void name(s32 param) //************************************************************************** @@ -30,7 +30,7 @@ //************************************************************************** // timer callbacks look like this -typedef named_delegate<void (void *, s32)> timer_expired_delegate; +typedef named_delegate<void (s32)> timer_expired_delegate; // ======================> emu_timer @@ -45,8 +45,8 @@ class emu_timer ~emu_timer(); // allocation and re-use - emu_timer &init(running_machine &machine, timer_expired_delegate callback, void *ptr, bool temporary); - emu_timer &init(device_t &device, device_timer_id id, void *ptr, bool temporary); + emu_timer &init(running_machine &machine, timer_expired_delegate callback, bool temporary); + emu_timer &init(device_t &device, device_timer_id id, bool temporary); emu_timer &release(); public: @@ -55,12 +55,10 @@ public: running_machine &machine() const noexcept { assert(m_machine != nullptr); return *m_machine; } bool enabled() const { return m_enabled; } int param() const { return m_param; } - void *ptr() const { return m_ptr; } // setters bool enable(bool enable = true); void set_param(int param) { m_param = param; } - void set_ptr(void *ptr) { m_ptr = ptr; } // control void reset(const attotime &duration = attotime::never) { adjust(duration, m_param, m_period); } @@ -78,7 +76,7 @@ private: void register_save(); void schedule_next_period(); void dump() const; - static void device_timer_expired(emu_timer &timer, void *ptr, s32 param); + static void device_timer_expired(emu_timer &timer, s32 param); // internal state running_machine * m_machine; // reference to the owning machine @@ -86,7 +84,6 @@ private: emu_timer * m_prev; // previous timer in order in the list timer_expired_delegate m_callback; // callback function s32 m_param; // integer parameter - void * m_ptr; // pointer parameter bool m_enabled; // is the timer enabled? bool m_temporary; // is the timer temporary? attotime m_period; // the repeat frequency of the timer @@ -124,13 +121,13 @@ public: void suspend_resume_changed() { m_suspend_changes_pending = true; } // timers, specified by callback/name - emu_timer *timer_alloc(timer_expired_delegate callback, void *ptr = nullptr); - void timer_set(const attotime &duration, timer_expired_delegate callback, int param = 0, void *ptr = nullptr); - void synchronize(timer_expired_delegate callback = timer_expired_delegate(), int param = 0, void *ptr = nullptr) { timer_set(attotime::zero, callback, param, ptr); } + emu_timer *timer_alloc(timer_expired_delegate callback); + void timer_set(const attotime &duration, timer_expired_delegate callback, int param = 0); + void synchronize(timer_expired_delegate callback = timer_expired_delegate(), int param = 0) { timer_set(attotime::zero, callback, param); } // timers, specified by device/id; generally devices should use the device_t methods instead - emu_timer *timer_alloc(device_t &device, device_timer_id id = 0, void *ptr = nullptr); - void timer_set(const attotime &duration, device_t &device, device_timer_id id = 0, int param = 0, void *ptr = nullptr); + emu_timer *timer_alloc(device_t &device, device_timer_id id = 0); + void timer_set(const attotime &duration, device_t &device, device_timer_id id = 0, int param = 0); // debugging void dump_timers() const; @@ -140,7 +137,7 @@ public: private: // callbacks - void timed_trigger(void *ptr, s32 param); + void timed_trigger(s32 param); void presave(); void postload(); diff --git a/src/emu/screen.cpp b/src/emu/screen.cpp index 5a9c055bbbb..77ae6fbea02 100644 --- a/src/emu/screen.cpp +++ b/src/emu/screen.cpp @@ -12,6 +12,7 @@ #include "screen.h" #include "emuopts.h" +#include "fileio.h" #include "render.h" #include "rendutil.h" @@ -554,7 +555,7 @@ screen_device::screen_device(const machine_config &mconfig, const char *tag, dev , m_curtexture(0) , m_changed(true) , m_last_partial_scan(0) - , m_partial_scan_hpos(-1) + , m_partial_scan_hpos(0) , m_color(rgb_t(0xff, 0xff, 0xff, 0xff)) , m_brightness(0xff) , m_frame_period(DEFAULT_FRAME_PERIOD.as_attoseconds()) @@ -683,9 +684,9 @@ void screen_device::device_validity_check(validity_checker &valid) const osd_printf_error("Non-raster display cannot have a variable width\n"); } - // check for zero frame rate - if (m_refresh == 0) - osd_printf_error("Invalid (zero) refresh rate\n"); + // check for invalid frame rate + if (m_refresh == 0 || m_refresh > ATTOSECONDS_PER_SECOND) + osd_printf_error("Invalid (under 1Hz) refresh rate\n"); texture_format texformat = !m_screen_update_ind16.isnull() ? TEXFORMAT_PALETTE16 : TEXFORMAT_RGB32; if (m_palette.finder_tag() != finder_base::DUMMY_TAG) @@ -934,7 +935,7 @@ void screen_device::device_post_load() // fires //------------------------------------------------- -void screen_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +void screen_device::device_timer(emu_timer &timer, device_timer_id id, int param) { switch (id) { @@ -1244,7 +1245,7 @@ bool screen_device::update_partial(int scanline) // remember where we left off m_last_partial_scan = scanline + 1; - m_partial_scan_hpos = -1; + m_partial_scan_hpos = 0; return true; } @@ -1298,10 +1299,10 @@ void screen_device::update_now() if (current_vpos > m_last_partial_scan) { // if the line before us was incomplete, we must do it in two pieces - if (m_partial_scan_hpos >= 0) + if (m_partial_scan_hpos > 0) { // now finish the previous partial scanline - clip.set((std::max)(clip.left(), m_partial_scan_hpos + 1), + clip.set((std::max)(clip.left(), m_partial_scan_hpos), clip.right(), (std::max)(clip.top(), m_last_partial_scan), (std::min)(clip.bottom(), m_last_partial_scan)); @@ -1340,7 +1341,7 @@ void screen_device::update_now() m_changed |= ~flags & UPDATE_HAS_NOT_CHANGED; } - m_partial_scan_hpos = -1; + m_partial_scan_hpos = 0; m_last_partial_scan++; } if (current_vpos > m_last_partial_scan) @@ -1350,47 +1351,50 @@ void screen_device::update_now() } // now draw this partial scanline - clip = m_visarea; - - clip.set((std::max)(clip.left(), m_partial_scan_hpos + 1), - (std::min)(clip.right(), current_hpos), - (std::max)(clip.top(), current_vpos), - (std::min)(clip.bottom(), current_vpos)); - - // and if there's something to draw, do it - if (!clip.empty()) + if (current_hpos > 0) { - g_profiler.start(PROFILER_VIDEO); + clip = m_visarea; - LOG_PARTIAL_UPDATES(("doing scanline partial draw: Y %d X %d-%d\n", clip.bottom(), clip.left(), clip.right())); + clip.set((std::max)(clip.left(), m_partial_scan_hpos), + (std::min)(clip.right(), current_hpos - 1), + (std::max)(clip.top(), current_vpos), + (std::min)(clip.bottom(), current_vpos)); - u32 flags = 0; - screen_bitmap &curbitmap = m_bitmap[m_curbitmap]; - if (m_video_attributes & VIDEO_VARIABLE_WIDTH) + // and if there's something to draw, do it + if (!clip.empty()) { - pre_update_scanline(current_vpos); - switch (curbitmap.format()) + g_profiler.start(PROFILER_VIDEO); + + LOG_PARTIAL_UPDATES(("doing scanline partial draw: Y %d X %d-%d\n", clip.bottom(), clip.left(), clip.right())); + + u32 flags = 0; + screen_bitmap &curbitmap = m_bitmap[m_curbitmap]; + if (m_video_attributes & VIDEO_VARIABLE_WIDTH) { - default: - case BITMAP_FORMAT_IND16: flags = m_screen_update_ind16(*this, *(bitmap_ind16 *)m_scan_bitmaps[m_curbitmap][current_vpos], clip); break; - case BITMAP_FORMAT_RGB32: flags = m_screen_update_rgb32(*this, *(bitmap_rgb32 *)m_scan_bitmaps[m_curbitmap][current_vpos], clip); break; + pre_update_scanline(current_vpos); + switch (curbitmap.format()) + { + default: + case BITMAP_FORMAT_IND16: flags = m_screen_update_ind16(*this, *(bitmap_ind16 *)m_scan_bitmaps[m_curbitmap][current_vpos], clip); break; + case BITMAP_FORMAT_RGB32: flags = m_screen_update_rgb32(*this, *(bitmap_rgb32 *)m_scan_bitmaps[m_curbitmap][current_vpos], clip); break; + } } - } - else - { - switch (curbitmap.format()) + else { - default: - case BITMAP_FORMAT_IND16: flags = m_screen_update_ind16(*this, curbitmap.as_ind16(), clip); break; - case BITMAP_FORMAT_RGB32: flags = m_screen_update_rgb32(*this, curbitmap.as_rgb32(), clip); break; + switch (curbitmap.format()) + { + default: + case BITMAP_FORMAT_IND16: flags = m_screen_update_ind16(*this, curbitmap.as_ind16(), clip); break; + case BITMAP_FORMAT_RGB32: flags = m_screen_update_rgb32(*this, curbitmap.as_rgb32(), clip); break; + } } - } - m_partial_updates_this_frame++; - g_profiler.stop(); + m_partial_updates_this_frame++; + g_profiler.stop(); - // if we modified the bitmap, we have to commit - m_changed |= ~flags & UPDATE_HAS_NOT_CHANGED; + // if we modified the bitmap, we have to commit + m_changed |= ~flags & UPDATE_HAS_NOT_CHANGED; + } } // remember where we left off @@ -1407,7 +1411,7 @@ void screen_device::update_now() void screen_device::reset_partial_updates() { m_last_partial_scan = 0; - m_partial_scan_hpos = -1; + m_partial_scan_hpos = 0; m_partial_updates_this_frame = 0; m_scanline0_timer->adjust(time_until_pos(0)); } diff --git a/src/emu/screen.h b/src/emu/screen.h index b909c25cecc..f5fa859a8c2 100644 --- a/src/emu/screen.h +++ b/src/emu/screen.h @@ -13,6 +13,8 @@ #pragma once +#include "rendertypes.h" + #include <type_traits> #include <utility> @@ -31,16 +33,6 @@ enum screen_type_enum SCREEN_TYPE_SVG }; -// texture formats -enum texture_format -{ - TEXFORMAT_UNDEFINED = 0, // require a format to be specified - TEXFORMAT_PALETTE16, // 16bpp palettized, no alpha - TEXFORMAT_RGB32, // 32bpp 8-8-8 RGB - TEXFORMAT_ARGB32, // 32bpp 8-8-8-8 ARGB - TEXFORMAT_YUY16 // 16bpp 8-8 Y/Cb, Y/Cr in sequence -}; - // screen_update callback flags constexpr u32 UPDATE_HAS_NOT_CHANGED = 0x0001; // the video has not changed @@ -233,7 +225,7 @@ public: screen_device &set_raw(u32 pixclock, u16 htotal, u16 hbend, u16 hbstart, u16 vtotal, u16 vbend, u16 vbstart) { assert(pixclock != 0); - m_clock = pixclock; + set_clock(pixclock); m_refresh = HZ_TO_ATTOSECONDS(pixclock) * htotal * vtotal; m_vblank = m_refresh / vtotal * (vtotal - (vbstart - vbend)); m_width = htotal; @@ -246,6 +238,10 @@ public: xtal.validate(std::string("Configuring screen ") + tag()); return set_raw(xtal.value(), htotal, hbend, hbstart, vtotal, vbend, vbstart); } + screen_device &set_raw(const XTAL &xtal, u16 htotal, u16 vtotal, rectangle visarea) + { + return set_raw(xtal, htotal, visarea.left(), visarea.right() + 1, vtotal, visarea.top(), visarea.bottom() + 1); + } void set_refresh(attoseconds_t rate) { m_refresh = rate; } /// \brief Set refresh rate in Hertz @@ -445,7 +441,7 @@ private: virtual void device_reset() override; virtual void device_stop() override; virtual void device_post_load() override; - virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param) override; // internal helpers void set_container(render_container &container) { m_container = &container; } diff --git a/src/emu/softlist_dev.cpp b/src/emu/softlist_dev.cpp index 7d25dd17013..c6a32f0b30f 100644 --- a/src/emu/softlist_dev.cpp +++ b/src/emu/softlist_dev.cpp @@ -13,6 +13,7 @@ #include "diimage.h" #include "emuopts.h" +#include "fileio.h" #include "romload.h" #include "validity.h" diff --git a/src/emu/sound.cpp b/src/emu/sound.cpp index 56b7d7ef071..a4cb5041d8f 100644 --- a/src/emu/sound.cpp +++ b/src/emu/sound.cpp @@ -885,7 +885,7 @@ void sound_stream::reprime_sync_timer() // synchronous stream //------------------------------------------------- -void sound_stream::sync_update(void *, s32) +void sound_stream::sync_update(s32) { update(); reprime_sync_timer(); @@ -1457,7 +1457,7 @@ stream_buffer::sample_t sound_manager::adjust_toward_compressor_scale(stream_buf // and send it to the OSD layer //------------------------------------------------- -void sound_manager::update(void *ptr, int param) +void sound_manager::update(int param) { VPRINTF(("sound_update\n")); diff --git a/src/emu/sound.h b/src/emu/sound.h index c1e66808ae6..658c956e5d4 100644 --- a/src/emu/sound.h +++ b/src/emu/sound.h @@ -373,6 +373,7 @@ public: // safely write a sample to the buffer void put(s32 start, sample_t sample) { + sound_assert(u32(start) < samples()); m_buffer->put(index_to_buffer_index(start), sample); } @@ -399,6 +400,7 @@ public: // safely add a sample to the buffer void add(s32 start, sample_t sample) { + sound_assert(u32(start) < samples()); u32 index = index_to_buffer_index(start); m_buffer->put(index, m_buffer->get(index) + sample); } @@ -458,7 +460,6 @@ private: // given a stream starting offset, return the buffer index u32 index_to_buffer_index(s32 start) const { - sound_assert(u32(start) < samples()); u32 index = start + m_start; if (index >= m_buffer->size()) index -= m_buffer->size(); @@ -673,7 +674,7 @@ private: void reprime_sync_timer(); // timer callback for synchronous streams - void sync_update(void *, s32); + void sync_update(s32); // return a view of 0 data covering the given time period read_stream_view empty_view(attotime start, attotime end); @@ -816,7 +817,7 @@ private: stream_buffer::sample_t adjust_toward_compressor_scale(stream_buffer::sample_t curscale, stream_buffer::sample_t prevsample, stream_buffer::sample_t rawsample); // periodic sound update, called STREAMS_UPDATE_FREQUENCY per second - void update(void *ptr = nullptr, s32 param = 0); + void update(s32 param = 0); // internal state running_machine &m_machine; // reference to the running machine diff --git a/src/emu/validity.cpp b/src/emu/validity.cpp index 18ba2c6fc6b..e4cf0860064 100644 --- a/src/emu/validity.cpp +++ b/src/emu/validity.cpp @@ -2292,8 +2292,9 @@ void validity_checker::validate_analog_input_field(const ioport_field &field) void validity_checker::validate_dip_settings(const ioport_field &field) { - const char *demo_sounds = ioport_string_from_index(INPUT_STRING_Demo_Sounds); - const char *flipscreen = ioport_string_from_index(INPUT_STRING_Flip_Screen); + char const *const demo_sounds = ioport_string_from_index(INPUT_STRING_Demo_Sounds); + char const *const flipscreen = ioport_string_from_index(INPUT_STRING_Flip_Screen); + char const *const name = field.specific_name(); u8 coin_list[__input_string_coinage_end + 1 - __input_string_coinage_start] = { 0 }; bool coin_error = false; @@ -2306,15 +2307,15 @@ void validity_checker::validate_dip_settings(const ioport_field &field) coin_list[strindex - __input_string_coinage_start] = 1; // make sure demo sounds default to on - if (field.name() == demo_sounds && strindex == INPUT_STRING_On && field.defvalue() != setting->value()) + if (name == demo_sounds && strindex == INPUT_STRING_On && field.defvalue() != setting->value()) osd_printf_error("Demo Sounds must default to On\n"); // check for bad demo sounds options - if (field.name() == demo_sounds && (strindex == INPUT_STRING_Yes || strindex == INPUT_STRING_No)) + if (name == demo_sounds && (strindex == INPUT_STRING_Yes || strindex == INPUT_STRING_No)) osd_printf_error("Demo Sounds option must be Off/On, not %s\n", setting->name()); // check for bad flip screen options - if (field.name() == flipscreen && (strindex == INPUT_STRING_Yes || strindex == INPUT_STRING_No)) + if (name == flipscreen && (strindex == INPUT_STRING_Yes || strindex == INPUT_STRING_No)) osd_printf_error("Flip Screen option must be Off/On, not %s\n", setting->name()); // if we have a neighbor, compare ourselves to him @@ -2324,21 +2325,21 @@ void validity_checker::validate_dip_settings(const ioport_field &field) // check for inverted off/on DIP switch order int next_strindex = get_defstr_index(nextsetting->name(), true); if (strindex == INPUT_STRING_On && next_strindex == INPUT_STRING_Off) - osd_printf_error("%s option must have Off/On options in the order: Off, On\n", field.name()); + osd_printf_error("%s option must have Off/On options in the order: Off, On\n", name); // check for inverted yes/no DIP switch order else if (strindex == INPUT_STRING_Yes && next_strindex == INPUT_STRING_No) - osd_printf_error("%s option must have Yes/No options in the order: No, Yes\n", field.name()); + osd_printf_error("%s option must have Yes/No options in the order: No, Yes\n", name); // check for inverted upright/cocktail DIP switch order else if (strindex == INPUT_STRING_Cocktail && next_strindex == INPUT_STRING_Upright) - osd_printf_error("%s option must have Upright/Cocktail options in the order: Upright, Cocktail\n", field.name()); + osd_printf_error("%s option must have Upright/Cocktail options in the order: Upright, Cocktail\n", name); // check for proper coin ordering else if (strindex >= __input_string_coinage_start && strindex <= __input_string_coinage_end && next_strindex >= __input_string_coinage_start && next_strindex <= __input_string_coinage_end && strindex >= next_strindex && setting->condition() == nextsetting->condition()) { - osd_printf_error("%s option has unsorted coinage %s > %s\n", field.name(), setting->name(), nextsetting->name()); + osd_printf_error("%s option has unsorted coinage %s > %s\n", name, setting->name(), nextsetting->name()); coin_error = true; } } @@ -2467,9 +2468,6 @@ void validity_checker::validate_inputs(device_t &root) // check for invalid UTF-8 if (!utf8_is_valid_string(name)) osd_printf_error("Field '%s' has invalid characters\n", name); - - // look up the string and print an error if default strings are not used - /*strindex =get_defstr_index(defstr_map, name, driver, &error);*/ } // verify conditions on the field diff --git a/src/emu/video.cpp b/src/emu/video.cpp index 652272f680b..f50d33d224a 100644 --- a/src/emu/video.cpp +++ b/src/emu/video.cpp @@ -11,10 +11,12 @@ #include "emu.h" #include "emuopts.h" #include "debugger.h" +#include "fileio.h" #include "ui/uimain.h" #include "crsshair.h" #include "rendersw.hxx" #include "output.h" +#include "screen.h" #include "corestr.h" #include "png.h" @@ -317,7 +319,7 @@ std::string video_manager::speed_text() // file handle //------------------------------------------------- -void video_manager::save_snapshot(screen_device *screen, emu_file &file) +void video_manager::save_snapshot(screen_device *screen, util::core_file &file) { // validate assert(!m_snap_native || screen != nullptr); @@ -492,7 +494,7 @@ void video_manager::exit() // when there are no screens to drive it //------------------------------------------------- -void video_manager::screenless_update_callback(void *ptr, int param) +void video_manager::screenless_update_callback(int param) { // force an update frame_update(false); @@ -506,8 +508,13 @@ void video_manager::screenless_update_callback(void *ptr, int param) void video_manager::postload() { + attotime const emutime = machine().time(); for (const auto &x : m_movie_recordings) - x->set_next_frame_time(machine().time()); + x->set_next_frame_time(emutime); + + // reset speed measurements + m_speed_last_realtime = osd_ticks(); + m_speed_last_emutime = emutime; } @@ -590,7 +597,7 @@ bool video_manager::finish_screen_updates() bool has_live_screen = false; for (screen_device &screen : iter) { - if (screen.partial_scan_hpos() >= 0) // previous update ended mid-scanline + if (screen.partial_scan_hpos() > 0) // previous update ended mid-scanline screen.update_now(); screen.update_partial(screen.visible_area().max_y); @@ -1129,7 +1136,7 @@ std::error_condition video_manager::open_next(emu_file &file, const char *extens if (pos_time != -1) { - char t_str[15]; + char t_str[16]; const std::time_t cur_time = std::time(nullptr); strftime(t_str, sizeof(t_str), "%Y%m%d_%H%M%S", std::localtime(&cur_time)); strreplace(snapstr, "%t", t_str); diff --git a/src/emu/video.h b/src/emu/video.h index c6d69194ba1..da57d6b8a98 100644 --- a/src/emu/video.h +++ b/src/emu/video.h @@ -78,7 +78,7 @@ public: // snapshots bool snap_native() const { return m_snap_native; } render_target &snapshot_target() { return *m_snap_target; } - void save_snapshot(screen_device *screen, emu_file &file); + void save_snapshot(screen_device *screen, util::core_file &file); void save_active_screen_snapshots(); // movies @@ -90,7 +90,7 @@ public: private: // internal helpers void exit(); - void screenless_update_callback(void *ptr, int param); + void screenless_update_callback(int param); void postload(); // effective value helpers diff --git a/src/emu/xtal.cpp b/src/emu/xtal.cpp index 16178a2bfc7..403993ab2d7 100644 --- a/src/emu/xtal.cpp +++ b/src/emu/xtal.cpp @@ -80,10 +80,12 @@ const double XTAL::known_xtals[] = { 2'000'000, /* 2_MHz_XTAL - */ 2'012'160, /* 2.01216_MHz_XTAL Cidelsa Draco sound board */ 2'097'152, /* 2.097152_MHz_XTAL Icatel 1995 - Brazilian public payphone */ + 2'250'000, /* 2.25_MHz_XTAL Resonator - YM2154 on Yamaha PSR-60 & PSR-70 */ 2'376'000, /* 2.376_MHz_XTAL CIT-101 keyboard */ 2'457'600, /* 2.4576_MHz_XTAL Atari ST MFP */ 2'500'000, /* 2.5_MHz_XTAL Janken Man units */ 2'600'000, /* 2.6_MHz_XTAL Sharp PC-1500 */ + 2'700'000, /* 2.7_MHz_XTAL Resonator - YM2154 on Yamaha RX15 */ 2'950'000, /* 2.95_MHz_XTAL Playmatic MPU-C, MPU-III & Sound-3 */ 3'000'000, /* 3_MHz_XTAL Probably only used to drive 68705 or similar MCUs on 80's Taito PCBs */ 3'072'000, /* 3.072_MHz_XTAL INS 8520 input clock rate */ @@ -122,6 +124,7 @@ const double XTAL::known_xtals[] = { 5'460'000, /* 5.46_MHz_XTAL ec1840 and ec1841 keyboard */ 5'529'600, /* 5.5296_MHz_XTAL Kontron PSI98 keyboard */ 5'626'000, /* 5.626_MHz_XTAL RCA CDP1869 PAL dot clock */ + 5'659'200, /* 5.6592_MHz_XTAL Digilog 320 dot clock */ 5'670'000, /* 5.67_MHz_XTAL RCA CDP1869 NTSC dot clock */ 5'714'300, /* 5.7143_MHz_XTAL Cidelsa Destroyer, TeleVideo serial keyboards */ 5'856'000, /* 5.856_MHz_XTAL HP 3478A Multimeter */ @@ -261,6 +264,7 @@ const double XTAL::known_xtals[] = { 16'364'000, /* 16.364_MHz_XTAL Corvus Concept */ 16'384'000, /* 16.384_MHz_XTAL - */ 16'400'000, /* 16.4_MHz_XTAL MS 6102 */ + 16'537'000, /* 16.537_MHz_XTAL Falco terminals 80-column clock */ 16'572'000, /* 16.572_MHz_XTAL Micro-Term ACT-5A */ 16'588'800, /* 16.5888_MHz_XTAL SM 7238 */ 16'666'600, /* 16.6666_MHz_XTAL Firebeat GCU */ @@ -327,6 +331,7 @@ const double XTAL::known_xtals[] = { 22'464'000, /* 22.464_MHz_XTAL CIT-101 132-column display clock */ 22'579'000, /* 22.579_MHz_XTAL Sega System H1 SCSP clock */ 22'656'000, /* 22.656_MHz_XTAL Super Pinball Action (~1440x NTSC line rate) */ + 22'680'000, /* 22.680_MHz_XTAL HDS200 80-columns display clock */ 22'896'000, /* 22.896_MHz_XTAL DEC VT220 132-column display clock */ 23'200'000, /* 23.2_MHz_XTAL Roland JV-80 & JV-880 PCM clock */ 23'814'000, /* 23.814_MHz_XTAL TeleVideo TVI-912, 920 & 950 */ @@ -371,7 +376,7 @@ const double XTAL::known_xtals[] = { 28'475'000, /* 28.475_MHz_XTAL CoCo 3 PAL */ 28'480'000, /* 28.48_MHz_XTAL Chromatics CGC-7900 */ 28'636'000, /* 28.636_MHz_XTAL Super Kaneko Nova System */ - 28'636'363, /* 28.636363_MHz_XTAL Later Leland games and Atari GT, Amiga NTSC, Raiden2 h/w (8x NTSC subcarrier)*/ + 28'636'363, /* 28.636363_MHz_XTAL Later Leland games and Atari GT, Amiga NTSC, Raiden2 h/w (8x NTSC subcarrier), NEC PC-88xx */ 28'640'000, /* 28.64_MHz_XTAL Fuuki FG-1c AI AM-2 PCB */ 28'700'000, /* 28.7_MHz_XTAL - */ 29'376'000, /* 29.376_MHz_XTAL Qume QVT-103 */ @@ -402,6 +407,8 @@ const double XTAL::known_xtals[] = { 34'000'000, /* 34_MHz_XTAL Gaelco PCBs */ 34'291'712, /* 34.291712_MHz_XTAL Fairlight CMI master card */ 34'846'000, /* 34.846_MHz_XTAL Visual 550 */ + 35'469'000, /* 35.469_MHz_XTAL ZX Spectrum +2/+3 (~8x PAL subcarrier) */ + 35'640'000, /* 35.640_MHz_XTAL HDS200 132-column display clock */ 35'834'400, /* 35.8344_MHz_XTAL Tab Products E-22 132-column display clock */ 35'840'000, /* 35.84_MHz_XTAL Akai MPC 60 voice PCB */ 35'904'000, /* 35.904_MHz_XTAL Used on HP98543 graphics board */ @@ -450,6 +457,7 @@ const double XTAL::known_xtals[] = { 57'272'727, /* 57.272727_MHz_XTAL Psikyo SH2 with /2 divider (16x NTSC subcarrier)*/ 57'283'200, /* 57.2832_MHz_XTAL Macintosh IIci RBV, 15-inch portrait display */ 58'000'000, /* 58_MHz_XTAL Magic Reel (Play System) */ + 58'982'400, /* 58.9824_MHz_XTAL Wyse WY-65 */ 59'292'000, /* 59.292_MHz_XTAL Data General D461 */ 60'000'000, /* 60_MHz_XTAL ARM610 */ 61'440'000, /* 61.44_MHz_XTAL Donkey Kong */ |