summaryrefslogtreecommitdiff
path: root/qpsxserial.cpp
diff options
context:
space:
mode:
authorXaviDCR92 <xavi.dcr@gmail.com>2017-08-05 17:26:40 +0200
committerXaviDCR92 <xavi.dcr@gmail.com>2017-08-05 17:26:40 +0200
commit1c3712dfa33757b11ff9b3082903e92f038e7b3d (patch)
tree57d703f8962bce0ac7184bc0941ea73d0fd0b33d /qpsxserial.cpp
parent51119d11fe6e9096861e1aeb7c3a03835710058b (diff)
* Added CLI support for QPSXSerial. Use "--help" information when executing QPSXSerial for further reference.
Diffstat (limited to 'qpsxserial.cpp')
-rw-r--r--qpsxserial.cpp532
1 files changed, 423 insertions, 109 deletions
diff --git a/qpsxserial.cpp b/qpsxserial.cpp
index 5775d00..0da333c 100644
--- a/qpsxserial.cpp
+++ b/qpsxserial.cpp
@@ -4,34 +4,49 @@
#include "qpsxserial.h"
#include "ui_qpsxserial.h"
-QPSXSerial::QPSXSerial(QWidget *parent) :
+#define LOST_PACKET_TIMEOUT 3000
+#define CONNECT_TO_PSX_TIMEOUT 500
+
+QPSXSerial::QPSXSerial(QWidget *parent, APP_INTERFACE interface) :
QMainWindow(parent),
ui(new Ui::QPSXSerial),
- stdout_ui(new Ui::Stdout_Console)
+ stdout_ui(new Ui::Stdout_Console),
+ stdout_dialog(new QDialog)
{
- ui->setupUi(this);
+ app_interface = interface;
+
lost_packet_timer = new QTimer();
+
connect(lost_packet_timer, SIGNAL(timeout()), this, SLOT(onPacketLost()));
- connect(ui->stdout_Button, SIGNAL(released()), this, SLOT(onStdOutButtonReleased()));
- connect(ui->loadFile_Btn, SIGNAL(released()), this, SLOT(onLoadFileBtnReleased()));
- connect(ui->updatePorts_Btn, SIGNAL(released()), this, SLOT(onUpdatePortsBtnReleased()));
- connect(ui->send_Btn, SIGNAL(released()), this, SLOT(onSendBtnReleased()));
- connect(ui->ports_ComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(onPortSelectedComboBox(QString)));
connect(&serial, SIGNAL(bytesWritten(qint64)), this, SLOT(onBytesWritten(qint64)));
connect(&serial, SIGNAL(readyRead()), this, SLOT(onReadyRead(void)));
- ack = false;
- init_timer = NULL;
+ if(app_interface == GUI_APP)
+ {
+ ui->setupUi(this);
- ui->exeProgressBar->setVisible(false);
+ connect(ui->stdout_Button, SIGNAL(released()), this, SLOT(onStdOutButtonReleased()));
+ connect(ui->loadFile_Btn, SIGNAL(released()), this, SLOT(onLoadFileBtnReleased()));
+ connect(ui->updatePorts_Btn, SIGNAL(released()), this, SLOT(onUpdatePortsBtnReleased()));
+ connect(ui->send_Btn, SIGNAL(released()), this, SLOT(onSendBtnReleased()));
+ connect(ui->ports_ComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(onPortSelectedComboBox(QString)));
- ui->send_Btn->setEnabled(false);
+ ui->exeProgressBar->setVisible(false);
+ ui->send_Btn->setEnabled(false);
+ ui->inFileName->setVisible(false);
- ui->inFileName->setVisible(false);
+ stdout_ui->setupUi(stdout_dialog);
+ connect(stdout_ui->close_Btn, SIGNAL(released()), stdout_dialog, SLOT(close()));
+ connect(this, SIGNAL(debug_frame_received(QString)), stdout_ui->stdout_Log, SLOT(append(QString)));
+ }
+
+ ack = false;
+ init_timer = NULL;
write_ready = false;
exe_sent = false;
+ first_entered = false;
}
QPSXSerial::~QPSXSerial()
@@ -46,21 +61,14 @@ QPSXSerial::~QPSXSerial()
void QPSXSerial::onStdOutButtonReleased(void)
{
- QDialog* dialog_ui = new QDialog();
-
- qDebug() << "1";
-
- stdout_ui->setupUi(dialog_ui);
-
- qDebug() << "2";
+ stdout_dialog->show();
+}
- connect(stdout_ui->close_Btn, SIGNAL(released()), dialog_ui, SLOT(close()));
- qDebug() << "3";
- connect(this, SIGNAL(debug_frame_received(QString)), stdout_ui->stdout_Log, SLOT(append(QString)));
- qDebug() << "4";
+void QPSXSerial::showError(QString error)
+{
+ QMessageBox box(QMessageBox::Critical, "QPSXSerial serror", error);
- dialog_ui->show();
- qDebug() << "5";
+ box.show();
}
void QPSXSerial::onLoadFileBtnReleased(void)
@@ -75,53 +83,14 @@ void QPSXSerial::onLoadFileBtnReleased(void)
return;
}
- selectedFolder.append("/");
-
ui->loadedFile_LineEdit->setText(selectedFolder);
- QFile system_f(selectedFolder + "\\SYSTEM.CNF");
+ inputExe = getInputExeFromFolder(&selectedFolder);
- if(system_f.open(QFile::ReadOnly) == false)
+ if(selectedPort.isEmpty() == false)
{
- qDebug() << "Could not open " + selectedFolder + "\\SYSTEM.CNF";
- return;
+ ui->send_Btn->setEnabled(true);
}
-
- QTextStream system_txt(&system_f);
-
- QString fileSelected;
-
- do
- {
- if(system_txt.atEnd() == true)
- {
- return;
- }
-
- QString line = system_txt.readLine();
-
- QStringList tokens = line.split("=");
-
- if(tokens.isEmpty() == true)
- {
- continue;
- }
-
- if(tokens.at(0).contains("BOOT") == false)
- {
- continue;
- }
-
- fileSelected = tokens.at(1).split("\\").at(1);
-
- fileSelected.chop(2); // Remove ";1" suffix.
- break;
-
- }while(1);
-
-
- inputExe = selectedFolder + fileSelected;
- qDebug() << "inputExe = " + inputExe;
}
void QPSXSerial::onUpdatePortsBtnReleased(void)
@@ -140,7 +109,7 @@ void QPSXSerial::onSendBtnReleased(void)
{
if(selectedPort.isEmpty() == true)
{
- qDebug() << "No selected port!";
+ showGUICLIerror("No selected port!");
return;
}
@@ -152,41 +121,49 @@ void QPSXSerial::onSendBtnReleased(void)
if(serial.open(QIODevice::ReadWrite) == false)
{
- qDebug() << "Could not open port " + selectedPort;
+ showGUICLIerror("Could not open port " + selectedPort);
return;
}
- qDebug() << "Connected succesfully to " + selectedPort;
-
if(init_timer == NULL)
{
init_timer = new QTimer();
init_timer->setSingleShot(true);
- init_timer->setInterval(3000);
+ init_timer->setInterval(CONNECT_TO_PSX_TIMEOUT);
connect(init_timer, SIGNAL(timeout(void)), this, SLOT(connectToPSXTimeout(void)));
}
- ui->exeProgressBar->setVisible(true);
-
- ui->exeProgressBar->setMinimum(0);
- ui->exeProgressBar->setMaximum(0);
-
- ui->inFileName->setText("Waiting for PSX response...");
+ init_timer->start(CONNECT_TO_PSX_TIMEOUT);
- ui->inFileName->setVisible(true);
-
- init_timer->start(3000);
-
- ui->send_Btn->setText("Disconnect from PSX");
+ if(app_interface == GUI_APP)
+ {
+ ui->exeProgressBar->setVisible(true);
+ ui->exeProgressBar->setMinimum(0);
+ ui->exeProgressBar->setMaximum(0);
+ ui->inFileName->setText("Waiting for PSX response...");
+ ui->inFileName->setVisible(true);
+ ui->send_Btn->setText("Disconnect from PSX");
+ }
+ else
+ {
+ printf("Connected to port successfully.\n");
+ printf("Waiting for PSX response...\n");
+ }
}
else
{
+ if(app_interface == GUI_APP)
+ {
+ ui->send_Btn->setText("Send to PSX!");
+ ui->exeProgressBar->setVisible(false);
+ ui->inFileName->clear();
+ }
+
serial.close();
- ui->send_Btn->setText("Send to PSX!");
- qDebug() << "Disconnected";
- ui->exeProgressBar->setVisible(false);
+ //qDebug() << "Disconnected";
+ first_entered = false;
exe_sent = false;
lost_packet_timer->stop();
init_timer->stop();
@@ -205,14 +182,19 @@ void QPSXSerial::connectToPSXTimeout(void)
//qDebug() << "Retry...";
- init_timer->start(1000);
+ init_timer->start(CONNECT_TO_PSX_TIMEOUT);
}
}
void QPSXSerial::onPortSelectedComboBox(QString port)
{
selectedPort = port;
- ui->send_Btn->setEnabled(true);
+
+ if(inputExe.isEmpty() == false)
+ {
+ ui->send_Btn->setEnabled(true);
+ }
+
qDebug() << "Selected port: " + selectedPort;
}
@@ -232,7 +214,6 @@ void QPSXSerial::onBytesWritten(qint64)
void QPSXSerial::onReadyRead(void)
{
- static bool first_entered = false;
QByteArray data = serial.readAll();
static QTime time = QTime::currentTime();
static bool cdrom_petition;
@@ -244,7 +225,7 @@ void QPSXSerial::onReadyRead(void)
{
static QByteArray fileName;
- if(data.startsWith("#") == true)
+ if(data.contains("#") == true)
{
cdrom_petition = true;
fileName.clear();
@@ -261,10 +242,28 @@ void QPSXSerial::onReadyRead(void)
if(cdrom_petition == true)
{
- fileName.append(data);
+ if(data.contains("#") == true)
+ {
+ int initial_i = data.indexOf("#");
+
+ qDebug() << initial_i;
+
+ fileName.append(data.mid(initial_i, data.count() - initial_i));
+ }
+ else
+ {
+ fileName.append(data);
+ }
- if(fileName.endsWith("@") == true)
+ if(fileName.contains("@") == true)
{
+ int terminator_i = fileName.indexOf("@");
+
+ if(terminator_i >= fileName.count())
+ {
+ fileName.chop(terminator_i - fileName.count() - 1);
+ }
+
cdrom_petition = false;
qDebug() << "INPUT FRAME: " + fileName;
@@ -312,8 +311,19 @@ void QPSXSerial::onReadyRead(void)
}
else
{
- qDebug() << data;
- emit debug_frame_received(QString(data));
+ if(app_interface == GUI_APP)
+ {
+ emit debug_frame_received(QString(data));
+ }
+ else if(app_interface == CLI_APP)
+ {
+ if(disable_psx_stdout == false)
+ {
+ const char* string_received = data.toStdString().c_str();
+
+ printf("%s\n", string_received);
+ }
+ }
}
}
@@ -362,8 +372,18 @@ bool QPSXSerial::sendExe(void)
ack = false;
QByteArray data = f.read(2048 /* PSX-EXE header */);
- qDebug () << "Sending PSX-EXE header...";
+ if(app_interface == GUI_APP)
+ {
+ ui->inFileName->setText("Sending PSX-EXE size...");
+ }
+ else if(app_interface == CLI_APP)
+ {
+ printf("Sending PSX-EXE header data...\n");
+ }
+
+ // PSX-EXE header is actually 2048 bytes long, but initial 32 bytes
+ // contain all the information we need for this.
for(int i = 0; i < 32; i+=8)
{
QByteArray send;
@@ -381,6 +401,15 @@ bool QPSXSerial::sendExe(void)
}
}
+ if(app_interface == GUI_APP)
+ {
+ ui->inFileName->setText("Sending PSX-EXE size...");
+ }
+ else if(app_interface == CLI_APP)
+ {
+ printf("Sending PSX-EXE size...\n");
+ }
+
while(ack == false)
{
QApplication::processEvents();
@@ -438,10 +467,10 @@ void QPSXSerial::sendDataSize(quint32 size)
}
}
- for(unsigned int i = 0; i < sizeof(quint32); i++)
+ /*for(unsigned int i = 0; i < sizeof(quint32); i++)
{
qDebug() << "0x" + QString::number(ar.at(i), 16);
- }
+ }*/
ack = false;
}
@@ -452,20 +481,26 @@ void QPSXSerial::onPacketLost(void)
if(ack == false)
{
-
serial.write(last_packet_sent);
- lost_packet_timer->start(100);
+ lost_packet_timer->start(LOST_PACKET_TIMEOUT);
}
}
void QPSXSerial::sendData(QByteArray data, QString fileName)
{
- ui->exeProgressBar->setVisible(true);
- ui->exeProgressBar->setRange(0, data.count());
- ui->inFileName->setText(fileName);
- ui->inFileName->setVisible(true);
+ static int last_i;
+
+ last_i = 0;
+
+ if(app_interface == GUI_APP)
+ {
+ ui->exeProgressBar->setVisible(true);
+ ui->exeProgressBar->setRange(0, data.count());
+ ui->inFileName->setText(fileName);
+ ui->inFileName->setVisible(true);
+ }
- lost_packet_timer->setInterval(100);
+ lost_packet_timer->setInterval(LOST_PACKET_TIMEOUT);
lost_packet_timer->setSingleShot(true);
for(int i = 0; i < data.count(); i+= 8)
@@ -481,20 +516,299 @@ void QPSXSerial::sendData(QByteArray data, QString fileName)
last_packet_sent = send;
- lost_packet_timer->start(100);
+ lost_packet_timer->start(LOST_PACKET_TIMEOUT);
while(ack == false)
{
QApplication::processEvents();
}
- ui->exeProgressBar->setValue(i);
+ if(app_interface == GUI_APP)
+ {
+ ui->exeProgressBar->setValue(i);
+ }
+ else if(app_interface == CLI_APP)
+ {
+ if( (i - last_i) > data.count() >> 7)
+ {
+ int j;
+ bool draw_arrow = true;
+
+ // Fancy, CLI progress bar
+
+ printf("\r");
+
+ printf("|");
+
+ for(j = 0; j < data.count(); j += data.count() >> 5)
+ {
+ if(i > j)
+ {
+ printf("=");
+ }
+ else if(i < j)
+ {
+ if(draw_arrow == true)
+ {
+ draw_arrow = false;
+ printf(">");
+ }
+ printf(" ");
+ }
+ else
+ {
+ printf(">");
+ }
+ }
+
+ printf("|");
+
+ printf("\t%d/%d bytes sent...", i, data.count());
+
+ last_i = i;
+ }
+ }
}
+ printf("\n");
+
lost_packet_timer->stop();
- ui->exeProgressBar->setValue(data.count());
- ui->inFileName->setText("Transfer complete!");
+ if(app_interface == GUI_APP)
+ {
+ ui->exeProgressBar->setValue(data.count());
+ ui->inFileName->setText("Transfer complete!");
+ }
+ else if(app_interface == CLI_APP)
+ {
+ printf("Transfer complete!\n");
+ }
ack = false;
}
+
+void QPSXSerial::cli_run(void)
+{
+ QStringList allowed_flags;
+ bool correct_flag_used = false;
+
+ allowed_flags.append("--help");
+ allowed_flags.append("--port");
+ allowed_flags.append("--inpath");
+
+ foreach(QString flag, allowed_flags)
+ {
+ if(_paramlist.contains(flag) == true)
+ {
+ correct_flag_used = true;
+ break;
+ }
+ }
+
+ if( (_paramlist.count() < 2) ||
+ (_paramlist.contains("--help") == true) ||
+ (correct_flag_used == false) )
+ {
+ showHelp();
+
+ emit finished();
+
+ return;
+ }
+
+ // Check specified port
+
+ int port_i = _paramlist.indexOf("--port");
+
+ if(port_i == -1)
+ {
+ printf("No port specified! Please include \"--port\" flag and port name e.g.: \"--port COM7\"\n");
+
+ emit finished();
+ return;
+ }
+
+ if(_paramlist.count() > (++port_i ) )
+ {
+ selectedPort = _paramlist.at(port_i);
+ }
+ else
+ {
+ printf("No port name specified! Please write port name e.g.: \"--port COM7\"\n");
+ emit finished();
+ return;
+ }
+
+ // Check specified folder
+
+ int folder_i = _paramlist.indexOf("--input_folder");
+
+ if(folder_i == -1)
+ {
+ printf("No input folder has been specified. Please include \"--help\" for further reference"
+ " about QPSXSerial usage.\n");
+ emit finished();
+ return;
+ }
+
+ if(_paramlist.count() > (++folder_i ) )
+ {
+ selectedFolder = _paramlist.at(folder_i);
+ }
+ else
+ {
+ printf( "No input folder path! Please write valid folder path e.g.: "
+ "--input-folder ~/MyGame/cdimg\n");
+ emit finished();
+ return;
+ }
+
+ inputExe = getInputExeFromFolder(&selectedFolder);
+
+ if(inputExe.isEmpty() == true)
+ {
+ printf("Could not find PSX-EXE from specified input folder.\n");
+ emit finished();
+ return;
+ }
+
+ // Check optional flags
+
+ int psx_sdtout_flag = _paramlist.indexOf("--disable_psx_stdout");
+
+ if(psx_sdtout_flag != -1)
+ {
+ disable_psx_stdout = true;
+ }
+ else
+ {
+ disable_psx_stdout = false;
+ }
+
+ onSendBtnReleased();
+}
+
+void QPSXSerial::showHelp(void)
+{
+ printf("##########################\n");
+ printf("QPSXSerial version %s\n", QPSXSERIAL_VERSION_STR);
+ printf("##########################\n");
+ printf("This application allows uploading PSX-EXE files to a PlayStation 1\n");
+ printf("console (also known as PSX) using serial port interface.\n");
+ printf("To be used together with OpenSend, available on the link below:\n");
+
+ printf("\n%s\n\n", OPENSEND_URL);
+ printf("Report any bugs, issues or suggestions on the official Github repository for QPSXSerial:\n");
+ printf("\n%s\n\n", QPSXSERIAL_URL);
+
+ printf("Usage:\n\n");
+
+ printf("QPSXSerial --input_folder inpath --port PORTNAME [options]\n\n");
+
+ printf("The following options are available:\n");
+ printf("--disable_psx_stdout\t\tDisables stdout messages from console to PC\n\n");
+
+ printf("Additionally to PSX-EXEs, QPSXSerial can also send external files e.g.:\n"
+ "*.TIM or *.VAG files whenever the game requests such data.\n");
+ printf("A working example of this bidirectional communication can be found on my open-source\n");
+ printf("video game \"Airport\", available on the following Github repository:\n");
+ printf("\nhttps://github.com/XaviDCR92/Airport/\n\n");
+ printf("QPSXSerial, OpenSend and Airport written by Xavier Del Campo (aka Xavi92).\n");
+ printf("All software released under the General Public License (GPL-3.0).\n");
+ printf("This application has been created using Qt toolkit %s\n", QT_VERSION_STR);
+ printf("\nINFO: In case you do not set any parameters, GUI is enabled by default.\n");
+}
+
+QString QPSXSerial::getInputExeFromFolder(QString* folder)
+{
+ QFile system_f(*folder + "\\SYSTEM.CNF");
+
+ QString fileSelected;
+ QString retExe;
+
+ if( (folder->endsWith("/") == false) && (folder->endsWith("\\") == false) )
+ {
+ folder->append("/");
+ }
+
+ if(system_f.exists() == false)
+ {
+ QDir d(*folder);
+ QStringList filters;
+
+ filters.append("*.EXE");
+ filters.append("*.exe");
+
+ QStringList exe_list = d.entryList(filters);
+
+ if(exe_list.isEmpty() == true)
+ {
+ retExe.clear();
+ return retExe;
+ }
+
+ if(exe_list.contains("PSX.EXE") == true)
+ {
+ fileSelected = "PSX.EXE";
+ }
+ else
+ {
+ fileSelected = exe_list.first();
+ }
+ }
+ else
+ {
+ if(system_f.open(QFile::ReadOnly) == false)
+ {
+ QString error = "Could not open " + *folder + "\\SYSTEM.CNF";
+ showGUICLIerror(error);
+
+ retExe.clear();
+ return retExe;
+ }
+
+ QTextStream system_txt(&system_f);
+
+ do
+ {
+ QString line = system_txt.readLine();
+
+ QStringList tokens = line.split("=");
+
+ if(tokens.isEmpty() == true)
+ {
+ continue;
+ }
+
+ if(tokens.at(0).contains("BOOT") == false)
+ {
+ continue;
+ }
+
+ fileSelected = tokens.at(1).split("\\").at(1);
+
+ fileSelected.chop(2); // Remove ";1" suffix.
+ break;
+
+ }while(system_txt.atEnd() == false);
+ }
+
+
+ retExe = *folder + fileSelected;
+
+ return retExe;
+}
+
+void QPSXSerial::showGUICLIerror(QString error)
+{
+ if(app_interface == GUI_APP)
+ {
+ showError(error);
+ }
+ else if(app_interface == CLI_APP)
+ {
+ const char* c_str_error = error.toStdString().c_str();
+
+ printf("%s\n", c_str_error);
+ }
+}