diff options
| author | XaviDCR92 <xavi.dcr@gmail.com> | 2017-08-05 17:26:40 +0200 |
|---|---|---|
| committer | XaviDCR92 <xavi.dcr@gmail.com> | 2017-08-05 17:26:40 +0200 |
| commit | 1c3712dfa33757b11ff9b3082903e92f038e7b3d (patch) | |
| tree | 57d703f8962bce0ac7184bc0941ea73d0fd0b33d | |
| parent | 51119d11fe6e9096861e1aeb7c3a03835710058b (diff) | |
| download | qpsxserial-1c3712dfa33757b11ff9b3082903e92f038e7b3d.tar.gz | |
* Added CLI support for QPSXSerial. Use "--help" information when executing QPSXSerial for further reference.
| -rw-r--r-- | main.cpp | 36 | ||||
| -rw-r--r-- | qpsxserial.cpp | 532 | ||||
| -rw-r--r-- | qpsxserial.h | 29 | ||||
| -rw-r--r-- | release/QPSXSerial.exe | bin | 53760 -> 87552 bytes | |||
| -rw-r--r-- | release/QPSXSerial_Win32.zip | bin | 17146764 -> 17164093 bytes | |||
| -rw-r--r-- | stdout.ui | 2 |
6 files changed, 486 insertions, 113 deletions
@@ -4,8 +4,40 @@ int main(int argc, char *argv[]) { QApplication a(argc, argv); - QPSXSerial w; - w.show(); + + QStringList param_list; + + for(int i = 1; i < argc; i++) + { + param_list.append(argv[i]); + } + + QPSXSerial* w; + + if(param_list.isEmpty() == true) + { + w = new QPSXSerial(0, GUI_APP); + } + else + { + w = new QPSXSerial(0, CLI_APP); + } + + w->setParamList(param_list); + + if(param_list.isEmpty() == true) + { + w->show(); + } + else + { + // This will cause the application to exit when + // the task signals finished. + QObject::connect(w, SIGNAL(finished(void)), &a, SLOT(quit(void))); + + // This will run the task from the application event loop. + QTimer::singleShot(0, w, SLOT(cli_run())); + } return a.exec(); } 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); + } +} diff --git a/qpsxserial.h b/qpsxserial.h index 13d098e..10b7faa 100644 --- a/qpsxserial.h +++ b/qpsxserial.h @@ -9,8 +9,21 @@ #include <QThread> #include <QTime> #include <QWinTaskbarButton> +#include <QMessageBox> +#include <iostream> #include "ui_stdout.h" +#define QPSXSERIAL_VERSION_NUMBER 0.3 +#define QPSXSERIAL_VERSION_STR "0.3" +#define QPSXSERIAL_URL "https://github.com/XaviDCR92/OpenSend" +#define OPENSEND_URL "https://github.com/XaviDCR92/QPSXSerial/" + +typedef enum t_AppInterface +{ + CLI_APP = 0, + GUI_APP +}APP_INTERFACE; + namespace Ui { class QPSXSerial; } @@ -20,16 +33,23 @@ class QPSXSerial : public QMainWindow Q_OBJECT public: - explicit QPSXSerial(QWidget *parent = 0); + explicit QPSXSerial(QWidget *parent = 0, APP_INTERFACE interface = GUI_APP); ~QPSXSerial(); + void setParamList(QStringList param){_paramlist = param;} private: bool sendExe(void); void sendData(QByteArray data, QString fileName); void sendDataSize(quint32 size); + void showError(QString error); + void showHelp(void); + QString getInputExeFromFolder(QString *folder); + void showGUICLIerror(QString error); Ui::QPSXSerial *ui; Ui::Stdout_Console *stdout_ui; + QDialog *stdout_dialog; + APP_INTERFACE app_interface; QString inputExe; QString selectedPort; QString selectedFolder; @@ -40,7 +60,13 @@ private: bool write_ready; bool byte_sent_received; QByteArray last_packet_sent; + bool first_entered; QTimer* lost_packet_timer; + QStringList _paramlist; + bool disable_psx_stdout; + +public slots: + void cli_run(void); private slots: void onLoadFileBtnReleased(void); @@ -55,6 +81,7 @@ private slots: signals: void debug_frame_received(QString); + void finished(void); }; #endif // QPSXSERIAL_H diff --git a/release/QPSXSerial.exe b/release/QPSXSerial.exe Binary files differindex 1c67436..d60c080 100644 --- a/release/QPSXSerial.exe +++ b/release/QPSXSerial.exe diff --git a/release/QPSXSerial_Win32.zip b/release/QPSXSerial_Win32.zip Binary files differindex 4232770..becdccd 100644 --- a/release/QPSXSerial_Win32.zip +++ b/release/QPSXSerial_Win32.zip @@ -11,7 +11,7 @@ </rect> </property> <property name="windowTitle"> - <string>Dialog</string> + <string>Stdout Console</string> </property> <widget class="QPushButton" name="close_Btn"> <property name="geometry"> |
