diff options
| author | XaviDCR92 <xavi.dcr@gmail.com> | 2017-07-20 23:54:08 +0200 |
|---|---|---|
| committer | XaviDCR92 <xavi.dcr@gmail.com> | 2017-07-20 23:54:08 +0200 |
| commit | f4b10b24bcf178e1d9072fb494922c875c0ecb0a (patch) | |
| tree | d392dc48f77546abeb56d2e209845bc50a47c07e | |
+ Added first version of QPSXSerial. Still lot of job to do and room for improvement.
| -rw-r--r-- | main.cpp | 11 | ||||
| -rw-r--r-- | qpsxserial.cpp | 458 | ||||
| -rw-r--r-- | qpsxserial.h | 54 | ||||
| -rw-r--r-- | release/QPSXSerial.exe | bin | 0 -> 49152 bytes | |||
| -rw-r--r-- | release/QPSXSerial_20072017_Win32.zip | bin | 0 -> 17145085 bytes |
5 files changed, 523 insertions, 0 deletions
diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..748160a --- /dev/null +++ b/main.cpp @@ -0,0 +1,11 @@ +#include "qpsxserial.h" +#include <QApplication> + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + QPSXSerial w; + w.show(); + + return a.exec(); +} diff --git a/qpsxserial.cpp b/qpsxserial.cpp new file mode 100644 index 0000000..6bc0a5a --- /dev/null +++ b/qpsxserial.cpp @@ -0,0 +1,458 @@ +#include <QFileDialog> +#include <QFile> +#include <QSerialPortInfo> +#include "qpsxserial.h" +#include "ui_qpsxserial.h" + +QPSXSerial::QPSXSerial(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::QPSXSerial) +{ + ui->setupUi(this); + lost_packet_timer = new QTimer(); + + connect(lost_packet_timer, SIGNAL(timeout()), this, SLOT(onPacketLost())); + + 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; + + ui->exeProgressBar->setVisible(false); + + ui->send_Btn->setEnabled(false); + + ui->inFileName->setVisible(false); + + write_ready = false; + exe_sent = false; +} + +QPSXSerial::~QPSXSerial() +{ + if(serial.isOpen() == true) + { + serial.close(); + } + + delete ui; +} + +void QPSXSerial::onLoadFileBtnReleased(void) +{ + selectedFolder = QFileDialog::getExistingDirectory( this, + "Load folder with PSX data", + "C:/", + QFileDialog::ShowDirsOnly ); + + if(selectedFolder.isEmpty() == true) + { + return; + } + + selectedFolder.append("/"); + + ui->loadedFile_LineEdit->setText(selectedFolder); + + QFile system_f(selectedFolder + "\\SYSTEM.CNF"); + + if(system_f.open(QFile::ReadOnly) == false) + { + qDebug() << "Could not open " + selectedFolder + "\\SYSTEM.CNF"; + return; + } + + 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) +{ + ui->ports_ComboBox->clear(); + + foreach(QSerialPortInfo port, QSerialPortInfo::availablePorts()) + { + ui->ports_ComboBox->addItem(port.portName()); + } +} + +void QPSXSerial::onSendBtnReleased(void) +{ + qDebug() << serial.isOpen(); + + if(serial.isOpen() == false) + { + if(selectedPort.isEmpty() == true) + { + qDebug() << "No selected port!"; + return; + } + + serial.setPortName(selectedPort); + serial.setBaudRate(QSerialPort::Baud115200); + serial.setParity(QSerialPort::NoParity); + serial.setDataBits(QSerialPort::Data8); + serial.setStopBits(QSerialPort::OneStop); + + if(serial.open(QIODevice::ReadWrite) == false) + { + qDebug() << "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(1000); + + 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..."); + + ui->inFileName->setVisible(true); + + init_timer->start(1000); + + ui->send_Btn->setText("Disconnect from PSX"); + } + else + { + serial.close(); + ui->send_Btn->setText("Send to PSX!"); + qDebug() << "Disconnected"; + init_timer->stop(); + } +} + +void QPSXSerial::connectToPSXTimeout(void) +{ + QByteArray ba; + + if(ack == false) + { + ba.append(99); + + serial.write(ba); + + //qDebug() << "Retry..."; + + init_timer->start(1000); + } +} + +void QPSXSerial::onPortSelectedComboBox(QString port) +{ + selectedPort = port; + ui->send_Btn->setEnabled(true); + qDebug() << "Selected port: " + selectedPort; +} + +void QPSXSerial::onBytesWritten(qint64) +{ + //qDebug() << "Bytes written: " + QString::number(bytes_written); + + /*byte_sent_received = false; + + while(byte_sent_received == false) + { + QApplication::processEvents(); + }*/ + + write_ready = true; +} + +void QPSXSerial::onReadyRead(void) +{ + static bool first_entered = false; + QByteArray data = serial.readAll(); + static QTime time = QTime::currentTime(); + + //qDebug() << QString("Received ") + QString::number(data.count()) + QString(" bytes."); + //qDebug() << QString("Took ") + QString::number(time.msecsTo(QTime::currentTime())); + + if(exe_sent == true) + { + //qDebug() << data; + + QByteArray header = data.left(5); + + if(header == "cdrom") + { + qDebug() << "INPUT FRAME: " + data; + QString filePath = QString(data); + + filePath.remove("cdrom:\\"); + + qDebug() << "selectedFolder = " + selectedFolder; + + filePath.prepend(selectedFolder); + + filePath.replace("\\", "/"); + + filePath.chop(2); // Remove ending ";1" + + qDebug() << "filePath = " + filePath; + + QFile f(filePath); + + if(f.open(QFile::ReadOnly) == false) + { + qDebug() << "Error while reading input file!"; + return; + } + + QByteArray file_data = f.readAll(); + quint32 sz = file_data.count(); + + sendDataSize(sz); + + while(ack == false) + { + QApplication::processEvents(); + } + + qDebug() << "sendData for file..."; + + sendData(file_data, filePath); + } + else + { + if(data.count() == 1) + { + if(data.at(0) == 'b') + { + ack = true; + } + } + else + { + qDebug() << data; + } + } + } + + if(data.isEmpty() == false) + { + quint8 data_byte = (quint8)data.at(0); + + if(data_byte == 'b') + { + //qDebug() << "Received ACK"; + // Received handshaking byte. Start transmission! + + ack = true; + + init_timer->stop(); + + if(first_entered == false) + { + first_entered = true; + + if(sendExe() == false) + { + qDebug() << "An error happened when sending EXE file!"; + } + + exe_sent = true; + } + } + } + + time = QTime::currentTime(); +} + +bool QPSXSerial::sendExe(void) +{ + QFile f(inputExe); + + if(f.open(QFile::ReadOnly) == false) + { + qDebug() << "Could not open input EXE file!"; + return false; + } + + f.seek(0); + + ack = false; + + QByteArray data = f.read(2048 /* PSX-EXE header */); + qDebug () << "Sending PSX-EXE header..."; + + for(int i = 0; i < 32; i++) + { + QByteArray send; + write_ready = false; + + send.append(data[i]); + + serial.write(send); + + while(write_ready == false) + { + QApplication::processEvents(); + } + } + + while(ack == false) + { + QApplication::processEvents(); + } + + qDebug () << "Sending EXE size..."; + + qint64 sz = f.size() - 2048; + + sendDataSize((quint32)sz); + + while(ack == false) + { + QApplication::processEvents(); + } + + // Send file size without header + + qDebug() << "Dump EXE data..."; + + f.seek(2048); + + data = f.readAll(); + + qDebug() << data.count(); + + sendData(data, inputExe); + + f.close(); + + return true; +} + +void QPSXSerial::sendDataSize(quint32 size) +{ + QByteArray ar; + + for(unsigned int i = 0; i < sizeof(quint32); i++) + { + char send = (char)( size >> (i << 3) ); + + QByteArray send_arr; + + send_arr.append(send); + + ar.append(send); + + serial.write(send_arr); + + while(write_ready == false) + { + QApplication::processEvents(); + } + } + + for(unsigned int i = 0; i < sizeof(quint32); i++) + { + qDebug() << "0x" + QString::number(ar.at(i), 16); + } + + ack = false; +} + +void QPSXSerial::onPacketLost(void) +{ + qDebug() << "Entering onPacketLost..."; + + if(ack == false) + { + + serial.write(last_packet_sent); + lost_packet_timer->start(100); + } +} + +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); + + lost_packet_timer->setInterval(100); + lost_packet_timer->setSingleShot(true); + + for(int i = 0; i < data.count(); i+= 8) + { + QByteArray send; + ack = false; + + send.append(data.mid(i, 8)); + + //qDebug() << "Sent packet"; + + serial.write(send); + + last_packet_sent = send; + + lost_packet_timer->start(100); + + while(ack == false) + { + QApplication::processEvents(); + } + + ui->exeProgressBar->setValue(i); + } + + lost_packet_timer->stop(); + + ui->exeProgressBar->setValue(data.count()); + ui->inFileName->setText("Transfer complete!"); + + ack = false; +} diff --git a/qpsxserial.h b/qpsxserial.h new file mode 100644 index 0000000..2728ce3 --- /dev/null +++ b/qpsxserial.h @@ -0,0 +1,54 @@ +#ifndef QPSXSERIAL_H +#define QPSXSERIAL_H + +#include <QMainWindow> +#include <QtSerialPort/QSerialPort> +#include <QString> +#include <QDebug> +#include <QTimer> +#include <QThread> +#include <QTime> +#include <QWinTaskbarButton> + +namespace Ui { +class QPSXSerial; +} + +class QPSXSerial : public QMainWindow +{ + Q_OBJECT + +public: + explicit QPSXSerial(QWidget *parent = 0); + ~QPSXSerial(); + +private: + bool sendExe(void); + void sendData(QByteArray data, QString fileName); + void sendDataSize(quint32 size); + + Ui::QPSXSerial *ui; + QString inputExe; + QString selectedPort; + QString selectedFolder; + QSerialPort serial; + bool ack; + bool exe_sent; + QTimer* init_timer; + bool write_ready; + bool byte_sent_received; + QByteArray last_packet_sent; + QTimer* lost_packet_timer; + +private slots: + void onLoadFileBtnReleased(void); + void onUpdatePortsBtnReleased(void); + void onSendBtnReleased(void); + void onPortSelectedComboBox(QString); + void onBytesWritten(qint64); + void onReadyRead(void); + void connectToPSXTimeout(void); + void onPacketLost(void); +}; + +#endif // QPSXSERIAL_H diff --git a/release/QPSXSerial.exe b/release/QPSXSerial.exe Binary files differnew file mode 100644 index 0000000..bc8b44e --- /dev/null +++ b/release/QPSXSerial.exe diff --git a/release/QPSXSerial_20072017_Win32.zip b/release/QPSXSerial_20072017_Win32.zip Binary files differnew file mode 100644 index 0000000..4af6eb5 --- /dev/null +++ b/release/QPSXSerial_20072017_Win32.zip |
