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 /qpsxserial.cpp | |
| parent | 51119d11fe6e9096861e1aeb7c3a03835710058b (diff) | |
* Added CLI support for QPSXSerial. Use "--help" information when executing QPSXSerial for further reference.
Diffstat (limited to 'qpsxserial.cpp')
| -rw-r--r-- | qpsxserial.cpp | 532 |
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); + } +} |
