#include "config.h"
#include "Headless.h"
#include "IOUtils.h"
#include <chrono>
#include <filesystem>
#include <iostream>
#ifndef _WIN32
#include <getopt.h>
#endif
int main(int argc, char *argv[])
{
try {
return vc64::Headless().main(argc, argv);
} catch (vc64::SyntaxError &e) {
std::cout << "Usage: VirtualC64Core [-svm] | { [-vm] <script> } " << std::endl;
std::cout << std::endl;
std::cout << " -s or --selftest Checks the integrity of the build" << std::endl;
std::cout << " -v or --verbose Print executed script lines" << std::endl;
std::cout << " -m or --messages Observe the message queue" << std::endl;
std::cout << std::endl;
if (auto what = string(e.what()); !what.empty()) {
std::cout << what << std::endl;
}
return 1;
std::cout << "VC64Error: " << std::endl;
std::cout << e.
what() << std::endl;
return 1;
} catch (std::exception &e) {
std::cout << "Error: " << std::endl;
std::cout << e.what() << std::endl;
return 1;
} catch (...) {
std::cout << "Error" << std::endl;
}
return 0;
}
int
Headless::main(int argc, char *argv[])
{
std::cout <<
"VirtualC64 Headless v" << c64.
version();
std::cout << " - (C)opyright Dirk W. Hoffmann" << std::endl << std::endl;
parseArguments(argc, argv);
if (keys.find(
"verbose") != keys.end()) c64.retroShell.
setStream(std::cout);
auto script = MediaFile::make(keys["arg1"], FILETYPE_SCRIPT);
c64.
launch(
this, vc64::process);
barrier.lock();
return returnCode;
}
#ifdef _WIN32
void
Headless::parseArguments(int argc, char *argv[])
{
keys["selftest"] = "1";
keys["verbose"] = "1";
keys["arg1"] = selfTestScript();
}
#else
void
Headless::parseArguments(int argc, char *argv[])
{
static struct option long_options[] = {
{ "selftest", no_argument, NULL, 's' },
{ "verbose", no_argument, NULL, 'v' },
{ "messages", no_argument, NULL, 'm' },
{ NULL, 0, NULL, 0 }
};
opterr = 0;
keys["exec"] = fs::absolute(argv[0]);
while (1) {
int arg = getopt_long(argc, argv, ":svm", long_options, NULL);
if (arg == -1) break;
switch (arg) {
case 's':
keys["selftest"] = "1";
break;
case 'v':
keys["verbose"] = "1";
break;
case 'm':
keys["messages"] = "1";
break;
case ':':
throw SyntaxError("Missing argument for option '" +
string(argv[optind - 1]) + "'");
default:
throw SyntaxError("Invalid option '" +
string(argv[optind - 1]) + "'");
}
}
auto nr = 1;
while (optind < argc) {
keys["arg" + std::to_string(nr++)] = fs::absolute(fs::path(argv[optind++])).string();
}
checkArguments();
if (keys.find("selftest") != keys.end()) keys["arg1"] = selfTestScript();
}
#endif
void
Headless::checkArguments()
{
if (keys.find("selftest") != keys.end()) {
if (keys.find("arg1") != keys.end()) {
throw SyntaxError("No script file must be given in selftest mode");
}
} else {
if (keys.find("arg1") == keys.end()) {
throw SyntaxError("No script file is given");
}
if (keys.find("arg2") != keys.end()) {
throw SyntaxError("More than one script file is given");
}
if (!util::fileExists(keys["arg1"])) {
throw SyntaxError("File " + keys["arg1"] + " does not exist");
}
}
}
string
Headless::selfTestScript()
{
auto path = std::filesystem::temp_directory_path() / "selftest.ini";
auto file = std::ofstream(path);
for (isize i = 0; i < isizeof(testScript) / isizeof(const char *); i++) {
file << testScript[i] << std::endl;
}
return path.string();
}
void
process(const void *listener, Message msg)
{
((Headless *)listener)->process(msg);
}
void
Headless::process(Message msg)
{
static bool messages = keys.find("messages") != keys.end();
if (messages) {
std::cout << MsgTypeEnum::key(msg.type);
std::cout << "(" << msg.value << ")";
std::cout << std::endl;
}
switch (msg.type) {
returnCode = 0;
barrier.unlock();
break;
returnCode = 1;
barrier.unlock();
break;
default:
break;
}
}
}
void launch(const void *listener, Callback *func)
Launches the emulator thread.
Definition VirtualC64.cpp:298
static string version()
Returns a version string for this release.
Definition VirtualC64.cpp:40
VirtualC64 project namespace.
Definition CmdQueue.cpp:16
@ MSG_SCRIPT_DONE
A RetroShell script has been successfully executed.
Definition MsgQueueTypes.h:46
@ MSG_ABORT
The emulator requests the GUI to quit the app.
Definition MsgQueueTypes.h:37
@ MSG_SCRIPT_ABORT
The execution of a RetroShell ccript has been aborted.
Definition MsgQueueTypes.h:47
Emulator exception.
Definition Error.h:24
const char * what() const override
Returns a textual description of this error.
Definition Error.cpp:259
void setStream(std::ostream &os)
Assign an additional output stream.
Definition VirtualC64.cpp:1018
void execScript(std::stringstream &ss)
Executes a script.
Definition VirtualC64.cpp:994