summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--3rdparty/linenoise-ng/src/linenoise.cpp24
-rw-r--r--scripts/src/main.lua1
-rw-r--r--src/frontend/mame/clifront.cpp275
-rw-r--r--src/frontend/mame/clifront.h2
-rw-r--r--src/frontend/mame/mame.cpp5
5 files changed, 205 insertions, 102 deletions
diff --git a/3rdparty/linenoise-ng/src/linenoise.cpp b/3rdparty/linenoise-ng/src/linenoise.cpp
index 10ab72790bd..751c535d084 100644
--- a/3rdparty/linenoise-ng/src/linenoise.cpp
+++ b/3rdparty/linenoise-ng/src/linenoise.cpp
@@ -2281,11 +2281,11 @@ int InputBuffer::incrementalHistorySearch(PromptBase& pi, int startChar) {
break;
// job control is its own thing
-#ifndef _WIN32
+//#ifndef _WIN32
case ctrlChar('Z'): // ctrl-Z, job control
disableRawMode(); // Returning to Linux (whatever) shell, leave raw
// mode
- raise(SIGSTOP); // Break out in mid-line
+ // raise(SIGSTOP); // Break out in mid-line
enableRawMode(); // Back from Linux shell, re-enter raw mode
{
bufferSize = historyLineLength + 1;
@@ -2295,9 +2295,9 @@ int InputBuffer::incrementalHistorySearch(PromptBase& pi, int startChar) {
dynamicRefresh(dp, tempUnicode.get(), historyLineLength,
historyLinePosition);
}
- continue;
- break;
-#endif
+ fprintf(stdout, "\n");
+ std::exit(0);
+//#endif
// these characters update the search string, and hence the selected input
// line
@@ -2929,16 +2929,18 @@ int InputBuffer::getInputLine(PromptBase& pi) {
beep();
break;
-#ifndef _WIN32
+//#ifndef _WIN32
case ctrlChar('Z'): // ctrl-Z, job control
disableRawMode(); // Returning to Linux (whatever) shell, leave raw
// mode
- raise(SIGSTOP); // Break out in mid-line
+ //raise(SIGSTOP); // Break out in mid-line
enableRawMode(); // Back from Linux shell, re-enter raw mode
- if (!pi.write()) break; // Redraw prompt
- refreshLine(pi); // Refresh the line
- break;
-#endif
+ //if (!pi.write()) break; // Redraw prompt
+ //refreshLine(pi); // Refresh the line
+ fprintf(stdout,"\n");
+ std::exit(0);
+ //break;
+//#endif
// DEL, delete the character under the cursor
case 127:
diff --git a/scripts/src/main.lua b/scripts/src/main.lua
index 08f047d99db..eb7cac4c8d5 100644
--- a/scripts/src/main.lua
+++ b/scripts/src/main.lua
@@ -195,6 +195,7 @@ end
if (STANDALONE~=true) then
links {
"frontend",
+ "linenoise-ng",
}
end
if (MACHINES["NETLIST"]~=null) then
diff --git a/src/frontend/mame/clifront.cpp b/src/frontend/mame/clifront.cpp
index a274326fac2..c3fbb049ffa 100644
--- a/src/frontend/mame/clifront.cpp
+++ b/src/frontend/mame/clifront.cpp
@@ -9,6 +9,7 @@
***************************************************************************/
#include "emu.h"
+#include "luaengine.h"
#include "mame.h"
#include "chd.h"
#include "emuopts.h"
@@ -31,6 +32,10 @@
#include "language.h"
#include "pluginopts.h"
+#include "linenoise-ng/include/linenoise.h"
+#include <atomic>
+#include <thread>
+
#include <new>
#include <ctype.h>
@@ -482,123 +487,219 @@ cli_frontend::~cli_frontend()
mame_options::remove_device_options(m_options);
}
-//-------------------------------------------------
-// execute - execute a game via the standard
-// command line interface
-//-------------------------------------------------
-
-int cli_frontend::execute(int argc, char **argv)
+void cli_frontend::start_execution(mame_machine_manager *manager,int argc, char **argv,std::string &option_errors)
{
- // wrap the core execution in a try/catch to field all fatal errors
- m_result = EMU_ERR_NONE;
- mame_machine_manager *manager = mame_machine_manager::instance(m_options, m_osd);
-
- try
+ if (*(m_options.software_name()) != 0)
{
- // first parse options to be able to get software from it
- std::string option_errors;
- mame_options::parse_command_line(m_options,argc, argv, option_errors);
-
- mame_options::parse_standard_inis(m_options,option_errors);
-
- load_translation(m_options);
+ const game_driver *system = mame_options::system(m_options);
+ if (system == nullptr && *(m_options.system_name()) != 0)
+ throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "Unknown system '%s'", m_options.system_name());
- manager->start_luaengine();
+ machine_config config(*system, m_options);
+ software_list_device_iterator iter(config.root_device());
+ if (iter.count() == 0)
+ throw emu_fatalerror(EMU_ERR_FATALERROR, "Error: unknown option: %s\n", m_options.software_name());
- if (*(m_options.software_name()) != 0)
+ bool found = false;
+ bool compatible = false;
+ for (software_list_device &swlistdev : iter)
{
- const game_driver *system = mame_options::system(m_options);
- if (system == nullptr && *(m_options.system_name()) != 0)
- throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "Unknown system '%s'", m_options.system_name());
-
- machine_config config(*system, m_options);
- software_list_device_iterator iter(config.root_device());
- if (iter.count() == 0)
- throw emu_fatalerror(EMU_ERR_FATALERROR, "Error: unknown option: %s\n", m_options.software_name());
-
- bool found = false;
- bool compatible = false;
- for (software_list_device &swlistdev : iter)
+ const software_info *swinfo = swlistdev.find(m_options.software_name());
+ if (swinfo != nullptr)
{
- const software_info *swinfo = swlistdev.find(m_options.software_name());
- if (swinfo != nullptr)
+ // loop through all parts
+ for (const software_part &swpart : swinfo->parts())
{
- // loop through all parts
- for (const software_part &swpart : swinfo->parts())
+ // only load compatible software this way
+ if (swlistdev.is_compatible(swpart) == SOFTWARE_IS_COMPATIBLE)
{
- // only load compatible software this way
- if (swlistdev.is_compatible(swpart) == SOFTWARE_IS_COMPATIBLE)
+ device_image_interface *image = software_list_device::find_mountable_image(config, swpart);
+ if (image != nullptr)
{
- device_image_interface *image = software_list_device::find_mountable_image(config, swpart);
- if (image != nullptr)
- {
- std::string val = string_format("%s:%s:%s", swlistdev.list_name(), m_options.software_name(), swpart.name());
+ std::string val = string_format("%s:%s:%s", swlistdev.list_name(), m_options.software_name(), swpart.name());
- // call this in order to set slot devices according to mounting
- mame_options::parse_slot_devices(m_options, argc, argv, option_errors, image->instance_name(), val.c_str(), &swpart);
- }
- compatible = true;
+ // call this in order to set slot devices according to mounting
+ mame_options::parse_slot_devices(m_options, argc, argv, option_errors, image->instance_name(), val.c_str(), &swpart);
}
+ compatible = true;
}
- found = true;
}
-
- if (compatible)
- break;
- }
- if (!compatible)
- {
- software_list_device::display_matches(config, nullptr, m_options.software_name());
- if (!found)
- throw emu_fatalerror(EMU_ERR_FATALERROR, nullptr);
- else
- throw emu_fatalerror(EMU_ERR_FATALERROR, "Software '%s' is incompatible with system '%s'\n", m_options.software_name(), m_options.system_name());
+ found = true;
}
- }
- // parse the command line, adding any system-specific options
- if (!mame_options::parse_command_line(m_options,argc, argv, option_errors))
+ if (compatible)
+ break;
+ }
+ if (!compatible)
{
- // if we failed, check for no command and a system name first; in that case error on the name
- if (*(m_options.command()) == 0 && mame_options::system(m_options) == nullptr && *(m_options.system_name()) != 0)
- throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "Unknown system '%s'", m_options.system_name());
+ software_list_device::display_matches(config, nullptr, m_options.software_name());
+ if (!found)
+ throw emu_fatalerror(EMU_ERR_FATALERROR, nullptr);
+ else
+ throw emu_fatalerror(EMU_ERR_FATALERROR, "Software '%s' is incompatible with system '%s'\n", m_options.software_name(), m_options.system_name());
+ }
+ }
+ // parse the command line, adding any system-specific options
+ if (!mame_options::parse_command_line(m_options, argc, argv, option_errors))
+ {
+ // if we failed, check for no command and a system name first; in that case error on the name
+ if (*(m_options.command()) == 0 && mame_options::system(m_options) == nullptr && *(m_options.system_name()) != 0)
+ throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "Unknown system '%s'", m_options.system_name());
- // otherwise, error on the options
- throw emu_fatalerror(EMU_ERR_INVALID_CONFIG, "%s", strtrimspace(option_errors).c_str());
+ // otherwise, error on the options
+ throw emu_fatalerror(EMU_ERR_INVALID_CONFIG, "%s", strtrimspace(option_errors).c_str());
+ }
+ if (!option_errors.empty())
+ osd_printf_error("Error in command line:\n%s\n", strtrimspace(option_errors).c_str());
+
+ // determine the base name of the EXE
+ std::string exename = core_filename_extract_base(argv[0], true);
+
+ // if we have a command, execute that
+ if (*(m_options.command()) != 0)
+ execute_commands(exename.c_str());
+
+ // otherwise, check for a valid system
+ else
+ {
+ // We need to preprocess the config files once to determine the web server's configuration
+ // and file locations
+ if (m_options.read_config())
+ {
+ m_options.revert(OPTION_PRIORITY_INI);
+ mame_options::parse_standard_inis(m_options, option_errors);
}
if (!option_errors.empty())
osd_printf_error("Error in command line:\n%s\n", strtrimspace(option_errors).c_str());
- // determine the base name of the EXE
- std::string exename = core_filename_extract_base(argv[0], true);
+ // if we can't find it, give an appropriate error
+ const game_driver *system = mame_options::system(m_options);
+ if (system == nullptr && *(m_options.system_name()) != 0)
+ throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "Unknown system '%s'", m_options.system_name());
- // if we have a command, execute that
- if (*(m_options.command()) != 0)
- execute_commands(exename.c_str());
+ // otherwise just run the game
+ m_result = manager->execute();
+ }
+}
+/*
+static const char* examples[] = {
+ "db", "hello", "hallo", "hans", "hansekogge", "seamann", "quetzalcoatl", "quit", "power", NULL
+};
- // otherwise, check for a valid system
- else
+void completionHook(char const* prefix, linenoiseCompletions* lc) {
+ size_t i;
+
+ for (i = 0; examples[i] != NULL; ++i) {
+ if (strncmp(prefix, examples[i], strlen(prefix)) == 0) {
+ linenoiseAddCompletion(lc, examples[i]);
+ }
+ }
+}
+*/
+
+void read_console(std::atomic<bool>& run, std::atomic<bool>& wait, std::string &cmdLine)
+{
+ char const* prompt = "\x1b[1;36m[MAME]\x1b[0m> ";
+
+ while (run.load())
+ {
+ while (wait.load())
{
- // We need to preprocess the config files once to determine the web server's configuration
- // and file locations
- if (m_options.read_config())
- {
- m_options.revert(OPTION_PRIORITY_INI);
- mame_options::parse_standard_inis(m_options,option_errors);
+ using namespace std::chrono_literals;
+ std::this_thread::sleep_for(100ms);
+ }
+ char* result = linenoise(prompt);
+ if (result == NULL)
+ {
+ continue;
+ }
+/* else if (!strncmp(result, "/history", 8)) {
+ // Display the current history.
+ for (int index = 0; ; ++index) {
+ char* hist = linenoiseHistoryLine(index);
+ if (hist == NULL) break;
+ printf("%4d: %s\n", index, hist);
+ free(hist);
}
- if (!option_errors.empty())
- osd_printf_error("Error in command line:\n%s\n", strtrimspace(option_errors).c_str());
+ }*/
+ else if (*result == '\0') {
+ free(result);
+ continue;
+ }
+ cmdLine = std::string(result);
+ linenoiseHistoryAdd(result);
+ //prompt = "\x1b[1;36m[MAME]\x1b[0m \x1b[1;32m[test]\x1b[0m> ";
- // if we can't find it, give an appropriate error
- const game_driver *system = mame_options::system(m_options);
- if (system == nullptr && *(m_options.system_name()) != 0)
- throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "Unknown system '%s'", m_options.system_name());
+ free(result);
+ wait.store(true);
+ }
+}
- // otherwise just run the game
- m_result = manager->execute();
+void cli_frontend::start_console()
+{
+ linenoiseInstallWindowChangeHandler();
+ std::string cmdLine = "";
+ const char* file = "./history";
+
+ linenoiseHistoryLoad(file);
+ //linenoiseSetCompletionCallback(completionHook);
+ printf(" _/ _/ _/_/ _/ _/ _/_/_/_/\n");
+ printf(" _/_/ _/_/ _/ _/ _/_/ _/_/ _/ \n");
+ printf(" _/ _/ _/ _/_/_/_/ _/ _/ _/ _/_/_/ \n");
+ printf(" _/ _/ _/ _/ _/ _/ _/ \n");
+ printf("_/ _/ _/ _/ _/ _/ _/_/_/_/ \n");
+ printf("\n");
+ printf("%s v%s\n%s\n\n", emulator_info::get_appname(), build_version, emulator_info::get_copyright_info());
+
+ std::atomic<bool> run(true), wait(false);
+ std::thread cinThread(read_console, std::ref(run), std::ref(wait), std::ref(cmdLine));
+
+ while (run.load())
+ {
+ if (wait.load())
+ {
+ //printf("command %s\n", cmdLine.c_str());
+ cmdLine.clear();
+ wait.store(false);
}
}
+ run.store(false);
+ cinThread.join();
+
+ linenoiseHistorySave(file);
+ linenoiseHistoryFree();
+}
+//-------------------------------------------------
+// execute - execute a game via the standard
+// command line interface
+//-------------------------------------------------
+
+int cli_frontend::execute(int argc, char **argv)
+{
+ // wrap the core execution in a try/catch to field all fatal errors
+ m_result = EMU_ERR_NONE;
+ mame_machine_manager *manager = mame_machine_manager::instance(m_options, m_osd);
+
+ try
+ {
+ // first parse options to be able to get software from it
+ std::string option_errors;
+ mame_options::parse_command_line(m_options,argc, argv, option_errors);
+
+ mame_options::parse_standard_inis(m_options,option_errors);
+
+ load_translation(m_options);
+
+ manager->start_luaengine();
+
+ if (m_options.console()) {
+ //manager->lua()->start_console();
+ start_console();
+ } else {
+ start_execution(manager, argc, argv, option_errors);
+ }
+ }
// handle exceptions of various types
catch (emu_fatalerror &fatal)
{
diff --git a/src/frontend/mame/clifront.h b/src/frontend/mame/clifront.h
index 4c4641ff72e..aeceeace397 100644
--- a/src/frontend/mame/clifront.h
+++ b/src/frontend/mame/clifront.h
@@ -61,6 +61,8 @@ private:
void display_help(const char *exename);
void display_suggestions(const char *gamename);
void output_single_softlist(FILE *out, software_list_device &swlist);
+ void start_execution(mame_machine_manager *manager, int argc, char **argv, std::string &option_errors);
+ void start_console();
// internal state
emu_options & m_options;
diff --git a/src/frontend/mame/mame.cpp b/src/frontend/mame/mame.cpp
index 0a4fc03b3bd..55c8219a425 100644
--- a/src/frontend/mame/mame.cpp
+++ b/src/frontend/mame/mame.cpp
@@ -178,10 +178,7 @@ int mame_machine_manager::execute()
// loop across multiple hard resets
bool exit_pending = false;
int error = EMU_ERR_NONE;
-
- if (m_options.console()) {
- m_lua->start_console();
- }
+
while (error == EMU_ERR_NONE && !exit_pending)
{
m_new_driver_pending = nullptr;