Sun, 11 Aug 2013 02:58:55 +0300
Overhauled the way versions are handled, it's all kept dynamically now.
src/bytestream.cpp | file | annotate | diff | comparison | revisions | |
src/config.cpp | file | annotate | diff | comparison | revisions | |
src/config.h | file | annotate | diff | comparison | revisions | |
src/demo.cpp | file | annotate | diff | comparison | revisions | |
src/demo.h | file | annotate | diff | comparison | revisions | |
src/main.cpp | file | annotate | diff | comparison | revisions | |
src/main.h | file | annotate | diff | comparison | revisions | |
src/misc.cpp | file | annotate | diff | comparison | revisions | |
src/misc.h | file | annotate | diff | comparison | revisions | |
src/src.pro | file | annotate | diff | comparison | revisions | |
src/ui/configbox.ui | file | annotate | diff | comparison | revisions |
--- a/src/bytestream.cpp Wed Jul 17 19:45:19 2013 +0300 +++ b/src/bytestream.cpp Sun Aug 11 02:58:55 2013 +0300 @@ -7,38 +7,38 @@ float f; } g_floatunion; -Bytestream::Bytestream( ulong len ) { +Bytestream::Bytestream (ulong len) { m_data = null; - resize( len ); + resize (len); clear(); } -Bytestream::Bytestream( const char* data, ulong len ) { +Bytestream::Bytestream (const char* data, ulong len) { m_data = null; - init( data, len ); + init (data, len); } -void Bytestream::resize( ulong newsize ) { +void Bytestream::resize (ulong newsize) { char* olddata = null; ulong oldsize; - - if( m_data ) { + + if (m_data) { oldsize = m_size; olddata = new char[oldsize]; - memcpy( olddata, m_data, oldsize ); + memcpy (olddata, m_data, oldsize); } - + delete[] m_data; m_data = new uint8[newsize]; m_size = newsize; - - if( olddata ) - memcpy( m_data, olddata, min<ulong> ( oldsize, newsize )); + + if (olddata) + memcpy (m_data, olddata, min<ulong> (oldsize, newsize)); } -void Bytestream::init( const char* data, ulong len ) { - resize( len ); - memcpy( m_data, data, len ); +void Bytestream::init (const char* data, ulong len) { + resize (len); + memcpy (m_data, data, len); m_ptr = &m_data[0]; m_len = len; } @@ -52,15 +52,15 @@ m_len = 0; } -uint8& Bytestream::subscript( ulong idx ) { +uint8& Bytestream::subscript (ulong idx) { return m_data[idx]; } -const uint8& Bytestream::const_subscript( ulong idx ) const { +const uint8& Bytestream::const_subscript (ulong idx) const { return m_data[idx]; } -void Bytestream::seek( ulong pos ) { +void Bytestream::seek (ulong pos) { m_ptr = m_data + pos; } @@ -70,51 +70,51 @@ } ulong Bytestream::bytesLeft() const { - return ( m_len - ( m_ptr - &m_data[0] )); + return (m_len - (m_ptr - &m_data[0])); } ulong Bytestream::spaceLeft() const { - return ( m_size - m_len ); + return (m_size - m_len); } // ============================================================================= -bool Bytestream::readByte( uint8& val ) { - if( bytesLeft() < 1 ) +bool Bytestream::readByte (uint8& val) { + if (bytesLeft() < 1) return false; - + val = *m_ptr++; return true; } // ============================================================================= -bool Bytestream::readShort( uint16& val ) { - if( bytesLeft() < 2 ) +bool Bytestream::readShort (uint16& val) { + if (bytesLeft() < 2) return false; - + val = 0; - - for( int i = 0; i < 2; ++i ) - val |= *m_ptr++ << ( i * 8 ); + + for (int i = 0; i < 2; ++i) + val |= *m_ptr++ << (i * 8); return true; } // ============================================================================= -bool Bytestream::readLong( uint32& val ) { - if( bytesLeft() < 4 ) +bool Bytestream::readLong (uint32& val) { + if (bytesLeft() < 4) return false; - + val = 0; - - for( int i = 0; i < 4; ++i ) - val |= *m_ptr++ << ( i * 8 ); - + + for (int i = 0; i < 4; ++i) + val |= *m_ptr++ << (i * 8); + return true; } // ============================================================================= -bool Bytestream::readFloat( float& val ) { - if( !readLong( g_floatunion.i )) +bool Bytestream::readFloat (float& val) { + if (!readLong (g_floatunion.i)) return false; val = g_floatunion.f; @@ -122,104 +122,104 @@ } // ============================================================================= -bool Bytestream::readString( str& val ) { - if( bytesLeft() < 1 ) // need at least the null terminator +bool Bytestream::readString (str& val) { + if (bytesLeft() < 1) // need at least the null terminator return false; - + uint8_t c; - - while( readByte( c ) && c != '\0' ) - val += ( char ) c; - + + while (readByte (c) && c != '\0') + val += (char) c; + return true; } // ============================================================================= -void Bytestream::doWrite( uint8_t val ) { +void Bytestream::doWrite (uint8_t val) { *m_ptr++ = val; m_len++; } -void Bytestream::growToFit( ulong bytes ) { - if( spaceLeft() < bytes ) - resize( m_size + bytes + 128 ); +void Bytestream::growToFit (ulong bytes) { + if (spaceLeft() < bytes) + resize (m_size + bytes + 128); } -bool Bytestream::readBytes( uint8 numbytes, uint8* val ) { - while( numbytes-- ) - if( !readByte( *val++ )) +bool Bytestream::readBytes (uint8 numbytes, uint8* val) { + while (numbytes--) + if (!readByte (*val++)) return false; - + return true; } -void Bytestream::writeBytes( uint8 numbytes, const uint8* val ) { - growToFit( numbytes ); - - while( numbytes-- ) - writeByte( *val++ ); +void Bytestream::writeBytes (uint8 numbytes, const uint8* val) { + growToFit (numbytes); + + while (numbytes--) + writeByte (*val++); } // ============================================================================= -void Bytestream::writeByte( uint8 val ) { - growToFit( 1 ); - doWrite( val ); +void Bytestream::writeByte (uint8 val) { + growToFit (1); + doWrite (val); } // ============================================================================= -void Bytestream::writeShort( uint16 val ) { - growToFit( 2 ); - - for( int i = 0; i < 2; ++i ) - doWrite(( val >> ( i * 8 )) & 0xFF ); +void Bytestream::writeShort (uint16 val) { + growToFit (2); + + for (int i = 0; i < 2; ++i) + doWrite ( (val >> (i * 8)) & 0xFF); } // ============================================================================= -void Bytestream::writeLong( uint32 val ) { - growToFit( 4 ); - - for( int i = 0; i < 4; ++i ) - doWrite(( val >> ( i * 8 )) & 0xFF ); +void Bytestream::writeLong (uint32 val) { + growToFit (4); + + for (int i = 0; i < 4; ++i) + doWrite ( (val >> (i * 8)) & 0xFF); } // ============================================================================= -void Bytestream::writeFloat( float val ) { +void Bytestream::writeFloat (float val) { g_floatunion.f = val; - writeLong( g_floatunion.i ); + writeLong (g_floatunion.i); } // ============================================================================= -void Bytestream::writeString( str val ) { - growToFit( val.length() + 1 ); - - for( qchar c : val ) - doWrite( c.toAscii() ); - - doWrite( '\0' ); +void Bytestream::writeString (str val) { + growToFit (val.length() + 1); + +for (qchar c : val) + doWrite (c.toAscii()); + + doWrite ('\0'); } // ============================================================================= -bool Bytestream::tryMerge( const Bytestream& other ) { - if( spaceLeft() < other.len() ) +bool Bytestream::tryMerge (const Bytestream& other) { + if (spaceLeft() < other.len()) return false; - - for( ulong i = 0; i < other.len(); ++i ) - writeByte( other[i] ); - + + for (ulong i = 0; i < other.len(); ++i) + writeByte (other[i]); + return true; } -void Bytestream::merge( const Bytestream& other ) { - growToFit( other.len() ); - - if( !tryMerge( other )) { +void Bytestream::merge (const Bytestream& other) { + growToFit (other.len()); + + if (!tryMerge (other)) { // Shouldn't happen - fprint( stderr, "ByteStream: Not enough space for merge (%1 bytes left, need %2)", - spaceLeft(), other.len() ); + fprint (stderr, "ByteStream: Not enough space for merge (%1 bytes left, need %2)", + spaceLeft(), other.len()); abort(); } } const uint8* Bytestream::data() const { return m_data; -} \ No newline at end of file +}
--- a/src/config.cpp Wed Jul 17 19:45:19 2013 +0300 +++ b/src/config.cpp Sun Aug 11 02:58:55 2013 +0300 @@ -1,57 +1,56 @@ #include <QLabel> #include <QFileDialog> #include <QFormLayout> +#include <QProgressBar> +#include <QMessageBox> +#include <QUrl> +#include <QNetworkAccessManager> +#include <QNetworkRequest> +#include <QNetworkReply> #include "config.h" #include "ui_configbox.h" #include "misc.h" +#include "demo.h" +#include "build/moc_config.cpp" // ============================================================================= // ----------------------------------------------------------------------------- class FindPathButton : public QPushButton { public: - explicit FindPathButton( QWidget* parent = null ) : QPushButton( parent ) { - setText( "..." ); + explicit FindPathButton (QWidget* parent = null) : QPushButton (parent) { + setText ("..."); } - - QLineEdit* editWidget() const { return m_editWidget; } - void setEditWidget( QLineEdit* edit ) { m_editWidget = edit; } - + + QLineEdit* editWidget() const { + return m_editWidget; + } + void setEditWidget (QLineEdit* edit) { + m_editWidget = edit; + } + private: QLineEdit* m_editWidget; }; // ============================================================================= // ----------------------------------------------------------------------------- -ConfigBox::ConfigBox( QWidget* parent, Qt::WindowFlags f ) : QDialog( parent, f ) { +ConfigBox::ConfigBox (QWidget* parent, Qt::WindowFlags f) : QDialog (parent, f), + m_nam (new QNetworkAccessManager (this)) { ui = new Ui_ConfigBox; - ui->setupUi( this ); - QFormLayout* layout = new QFormLayout( ui->zandronumVersions ); - - for( str ver : g_zanVersions ) { - QLabel* lb = new QLabel( ver + ":" ); - QLineEdit* ledit = new QLineEdit; - FindPathButton* btn = new FindPathButton; - btn->setEditWidget( ledit ); - - QWidget* wdg = new QWidget; - QHBoxLayout* leditLayout = new QHBoxLayout( wdg ); - leditLayout->addWidget( ledit ); - leditLayout->addWidget( btn ); - - m_zanBinaries << ledit; - layout->addRow( lb, wdg ); - connect( btn, SIGNAL( clicked() ), this, SLOT( findZanBinary() )); - } - + ui->setupUi (this); + ui->updateProgress->hide(); + ui->updateLabel->hide(); + + initVersions(); initFromSettings(); - - connect( ui->wad_add, SIGNAL( clicked() ), this, SLOT( addPath() )); - connect( ui->wad_pathEntry, SIGNAL( returnPressed() ), this, SLOT( addPath() )); - connect( ui->wad_findPath, SIGNAL( clicked() ), this, SLOT( findPath() )); - connect( ui->wad_del, SIGNAL( clicked() ), this, SLOT( delPath() )); - connect( ui->buttonBox, SIGNAL( accepted() ), this, SLOT( okPressed() )); - connect( ui->buttonBox, SIGNAL( rejected() ), this, SLOT( cancelPressed() )); - setWindowTitle( fmt( APPNAME " %1", versionString())); + + connect (ui->wad_add, SIGNAL (clicked()), this, SLOT (addPath())); + connect (ui->wad_pathEntry, SIGNAL (returnPressed()), this, SLOT (addPath())); + connect (ui->wad_findPath, SIGNAL (clicked()), this, SLOT (findPath())); + connect (ui->wad_del, SIGNAL (clicked()), this, SLOT (delPath())); + connect (ui->buttonBox, SIGNAL (clicked (QAbstractButton*)), this, + SLOT (buttonPressed (QAbstractButton*))); + setWindowTitle (fmt (APPNAME " %1", versionString())); } // ============================================================================= @@ -62,45 +61,104 @@ // ============================================================================= // ----------------------------------------------------------------------------- +void ConfigBox::initVersions() { + QFormLayout* releaseLayout = new QFormLayout (ui->zandronumVersions), + *testLayout = new QFormLayout (ui->betaVersions); + list<var> versions = getVersionsList(), + releases = getReleasesList(); + + for (const var& ver : versions) { + str verstring = ver.toString(); + + bool isRelease = false; + for (const var& rel : releases) { + if (rel.toString() == verstring) { + isRelease = true; + break; + } + } + + QLabel* lb = new QLabel (verstring + ":"); + QLineEdit* ledit = new QLineEdit; + FindPathButton* btn = new FindPathButton; + btn->setEditWidget (ledit); + + QWidget* wdg = new QWidget; + QHBoxLayout* leditLayout = new QHBoxLayout (wdg); + leditLayout->addWidget (ledit); + leditLayout->addWidget (btn); + + m_zanBinaries << ledit; + connect (btn, SIGNAL (clicked()), this, SLOT (findZanBinary())); + + if (isRelease) + releaseLayout->addRow (lb, wdg); + else + testLayout->addRow (lb, wdg); + } +} + +// ============================================================================= +// ----------------------------------------------------------------------------- void ConfigBox::initFromSettings() { QSettings cfg; - ui->wad_pathsList->clear(); + list<var> paths = cfg.value ("wads/paths", list<var>()).toList(); - list<var> paths = cfg.value( "wads/paths", list<var>() ).toList(); - for( const var& it : paths ) - addPath( it.toString() ); + for (const var & it : paths) + addPath (it.toString()); int i = 0; - for( str ver : g_zanVersions ) - m_zanBinaries[i++]->setText( cfg.value( binaryConfigName( ver ), "" ).toString() ); + + list<var> versions = getVersionsList(); + for (const var& ver : versions) + m_zanBinaries[i++]->setText (cfg.value (binaryConfigName (ver.toString()), "").toString()); - ui->noDemoPrompt->setChecked( cfg.value( "nodemoprompt", false ).toBool() ); + ui->noDemoPrompt->setChecked (cfg.value ("nodemoprompt", false).toBool()); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +void ConfigBox::saveSettings() { + QSettings cfg; + list<var> wadPathList; + + for (int i = 0; i < ui->wad_pathsList->count(); ++i) + wadPathList << ui->wad_pathsList->item (i)->text(); + + cfg.setValue ("wads/paths", wadPathList); + cfg.setValue ("nodemoprompt", ui->noDemoPrompt->isChecked()); + + int i = 0; + list<var> versions = getVersionsList(); + for (const var& ver : versions) + cfg.setValue (binaryConfigName (ver.toString()), m_zanBinaries[i++]->text()); } // ============================================================================= // ----------------------------------------------------------------------------- void ConfigBox::addPath() { - addPath( ui->wad_pathEntry->text() ); + addPath (ui->wad_pathEntry->text()); ui->wad_pathEntry->clear(); } // ============================================================================= // ----------------------------------------------------------------------------- -void ConfigBox::addPath( str path ) { - ui->wad_pathsList->addItem( path ); - QListWidgetItem* item = ui->wad_pathsList->item( ui->wad_pathsList->count() - 1 ); - item->setFlags( item->flags() | Qt::ItemIsEditable ); +void ConfigBox::addPath (str path) { + ui->wad_pathsList->addItem (path); + QListWidgetItem* item = ui->wad_pathsList->item (ui->wad_pathsList->count() - 1); + item->setFlags (item->flags() | Qt::ItemIsEditable); } // ============================================================================= // ----------------------------------------------------------------------------- void ConfigBox::findPath() { - str path = QFileDialog::getExistingDirectory( this ); - if( path.isEmpty() ) + str path = QFileDialog::getExistingDirectory (this); + + if (path.isEmpty()) return; - - ui->wad_pathEntry->setText( path ); + + ui->wad_pathEntry->setText (path); } // ============================================================================= @@ -112,46 +170,40 @@ // ============================================================================= // ----------------------------------------------------------------------------- void ConfigBox::findZanBinary() { - FindPathButton* btn = dynamic_cast<FindPathButton*>( sender() ); - str path; + FindPathButton* btn = dynamic_cast<FindPathButton*> (sender()); - if( !btn ) + if (!btn) return; - str filter; -#ifdef _WIN32 - filter = "Zandronum Binaries (zandronum.exe)(zandronum.exe);;All files (*.*)(*.*)"; -#else - filter = "Zandronum Binaries (zandronum)(zandronum);;All files (*.*)(*.*)"; -#endif - - if(( path = QFileDialog::getOpenFileName( this, QString(), QString(), filter )).isEmpty() ) + str path = getBinaryPath (this); + if (path.isEmpty()) return; - btn->editWidget()->setText( path ); + btn->editWidget()->setText (path); } // ============================================================================= // ----------------------------------------------------------------------------- -void ConfigBox::okPressed() { - QSettings cfg; - list<var> wadPathList; - - for( int i = 0; i < ui->wad_pathsList->count(); ++i ) - wadPathList << ui->wad_pathsList->item( i )->text(); +str ConfigBox::getBinaryPath (QWidget* parent) { + str path; + const str filter = +#ifdef _WIN32 + "Zandronum Binaries (zandronum.exe)(zandronum.exe);;All files (*.*)(*.*)"; +#else + "Zandronum Binaries (zandronum)(zandronum);;All files (*.*)(*.*)"; +#endif - cfg.setValue( "wads/paths", wadPathList ); - cfg.setValue( "nodemoprompt", ui->noDemoPrompt->isChecked() ); - - int i = 0; - for( str ver : g_zanVersions ) - cfg.setValue( binaryConfigName( ver ), m_zanBinaries[i++]->text() ); - - accept(); + return QFileDialog::getOpenFileName (parent, QString(), QString(), filter); } // ============================================================================= // ----------------------------------------------------------------------------- -void ConfigBox::cancelPressed() { - reject(); +void ConfigBox::buttonPressed (QAbstractButton* btn) { + if (btn == ui->buttonBox->button (QDialogButtonBox::Ok)) { + saveSettings(); + accept(); + } elif (btn == ui->buttonBox->button (QDialogButtonBox::Cancel)) + reject(); + elif (btn == ui->buttonBox->button (QDialogButtonBox::Apply)) + saveSettings(); } \ No newline at end of file
--- a/src/config.h Wed Jul 17 19:45:19 2013 +0300 +++ b/src/config.h Sun Aug 11 02:58:55 2013 +0300 @@ -5,8 +5,13 @@ #include "main.h" #include "types.h" +class QNetworkReply; +class QHBoxLayout; +class QLabel; +class QAbstractButton; class QLineEdit; class Ui_ConfigBox; +class QNetworkAccessManager; class ConfigBox : public QDialog { Q_OBJECT @@ -16,18 +21,23 @@ virtual ~ConfigBox(); void addPath( str path ); void initFromSettings(); + void saveSettings(); + void initVersions(); + + static str getBinaryPath (QWidget* parent); public slots: void addPath(); void findPath(); void delPath(); void findZanBinary(); - void okPressed(); - void cancelPressed(); + void buttonPressed( QAbstractButton* btn ); private: Ui_ConfigBox* ui; list<QLineEdit*> m_zanBinaries; + QNetworkAccessManager* m_nam; + QNetworkReply* m_reply; }; #endif // CONFIG_H \ No newline at end of file
--- a/src/demo.cpp Wed Jul 17 19:45:19 2013 +0300 +++ b/src/demo.cpp Sun Aug 11 02:58:55 2013 +0300 @@ -6,49 +6,75 @@ #include "bytestream.h" #include "misc.h" #include "ui_demoprompt.h" +#include "prompts.h" -static const uint32 g_demoSignature = makeByteID( 'Z', 'C', 'L', 'D' ); +static const uint32 g_demoSignature = makeByteID ('Z', 'C', 'L', 'D'); // ============================================================================= // ----------------------------------------------------------------------------- -static str tr( const char* msg ) { - return QObject::tr( msg ); +str uncolorize (const str& in) { + str out; + int skip = 0; + + for (const qchar& c : in) { + if (skip-- > 0) + continue; + + if (c.toAscii() == '\034') { + skip = 1; + continue; + } + + out += c; + } + + return out; } // ============================================================================= // ----------------------------------------------------------------------------- -static void error( str msg ) { - QMessageBox::critical( null, "Error", msg ); +static str tr (const char* msg) { + return QObject::tr (msg); } // ============================================================================= // ----------------------------------------------------------------------------- -static int getVersionIndex( str ver ) { - int i; - - for( i = 0; i < g_zanVersions.size(); ++i ) - if( g_zanVersions[i] == ver ) - return i; - - return -1; +static void error (str msg) { + QMessageBox::critical (null, "Error", msg); } // ============================================================================= // ----------------------------------------------------------------------------- -static str findWAD( str name ) { +static bool isKnownVersion (str ver) { QSettings cfg; - list<var> paths = cfg.value( "wads/paths", list<var>() ).toList(); + list<var> versions = getVersionsList(); + + for (const var& it : versions) + if (it.toString() == ver || it.toString() + 'M' == ver) + return true; - if( paths.size() == 0 ) { - error( tr( "No WAD paths configured!" )); - exit( 9 ); + return false; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +static str findWAD (str name) { + QSettings cfg; + list<var> paths = cfg.value ("wads/paths", list<var>()).toList(); + + if (paths.size() == 0) { + error (tr ("No WAD paths configured!")); + + // Cannot just return an empty string here since that'd trigger + // another error prompt - skip ahead and exit. + exit (9); } - for( var it : paths ) { - str fullpath = fmt( "%1/%2", it.toString(), name ); - QFile f( fullpath ); + for (const var& it : paths) { + str fullpath = fmt ("%1/%2", it.toString(), name); + QFile f (fullpath); - if( f.exists() ) + if (f.exists()) return fullpath; } @@ -57,27 +83,27 @@ // ============================================================================= // ----------------------------------------------------------------------------- -int launchDemo( str path ) { - FILE* fp = fopen( path.toStdString().c_str(), "r" ); +int launchDemo (str path) { + FILE* fp = fopen (path.toStdString().c_str(), "r"); - if( !fp ) { - error( fmt( tr( "Couldn't open '%1' for reading: %2" ), path, strerror( errno ))); + if (!fp) { + error (fmt (tr ("Couldn't open '%1' for reading: %2"), path, strerror (errno))); return 1; } - fseek( fp, 0, SEEK_END ); - const size_t fsize = ftell( fp ); - rewind( fp ); + fseek (fp, 0, SEEK_END); + const size_t fsize = ftell (fp); + rewind (fp); char* buf = new char[fsize]; - if( fread( buf, 1, fsize, fp ) != fsize ) { - error( tr( "I/O error" )); + if (fread (buf, 1, fsize, fp) != fsize) { + error (tr ("I/O error")); delete[] buf; return 2; } - - Bytestream s( buf, fsize ); + + Bytestream s (buf, fsize); delete[] buf; uint8 offset; @@ -93,8 +119,8 @@ { uint32 sig; - if( !s.readLong( sig ) || sig != g_demoSignature ) { - error( fmt( tr( "'%1' is not a Zandronum demo file!" ), path )); + if (!s.readLong (sig) || sig != g_demoSignature) { + error (fmt (tr ("'%1' is not a Zandronum demo file!"), path)); return 3; } } @@ -102,108 +128,123 @@ // Zandronum stores CLD_DEMOLENGTH after the signature. This is also the // first demo enumerator, so we can determine the offset (which is variable!) // from this byte - s.readByte( offset ); - s.readLong( length ); - + s.readByte (offset); + s.readLong (length); + uint16 zanversionID, numWads; uint32 longSink; str zanversion; list<str> wads; bool ready = false; + uint8 buildID; - for( ;; ) { + // Read the demo header and get data + for (;;) { uint8 header; - if( !s.readByte( header )) + + if (!s.readByte (header)) break; - if( header == DemoBodyStart + offset ) { + if (header == DemoBodyStart + offset) { ready = true; break; - } elif( header == DemoVersion + offset ) { - s.readShort( zanversionID ); - s.readString( zanversion ); - s.readLong( longSink ); // rng seed - we don't need it - } elif( header == DemoUserInfo + offset ) { - s.readString( userinfo.netname ); - s.readByte( userinfo.gender ); - s.readLong( userinfo.color ); - s.readLong( userinfo.aimdist ); - s.readString( userinfo.skin ); - s.readLong( userinfo.railcolor ); - s.readByte( userinfo.handicap ); - s.readByte( userinfo.unlagged ); - s.readByte( userinfo.respawnOnFire ); - s.readByte( userinfo.ticsPerUpdate ); - s.readByte( userinfo.connectionType ); - s.readString( userinfo.className ); - } elif( header == DemoWads + offset ) { - s.readShort( numWads ); + } elif (header == DemoVersion + offset) { + s.readShort (zanversionID); + s.readString (zanversion); + + if (zanversion.left (4) != "1.1-" && zanversion.left (6) != "1.1.1-") + s.readByte (buildID); + else + buildID = 1; - for( uint8 i = 0; i < numWads; ++i ) { + s.readLong (longSink); // rng seed - we don't need it + } elif (header == DemoUserInfo + offset) { + s.readString (userinfo.netname); + s.readByte (userinfo.gender); + s.readLong (userinfo.color); + s.readLong (userinfo.aimdist); + s.readString (userinfo.skin); + s.readLong (userinfo.railcolor); + s.readByte (userinfo.handicap); + s.readByte (userinfo.unlagged); + s.readByte (userinfo.respawnOnFire); + s.readByte (userinfo.ticsPerUpdate); + s.readByte (userinfo.connectionType); + s.readString (userinfo.className); + } elif (header == DemoWads + offset) { + str sink; + s.readShort (numWads); + + for (uint8 i = 0; i < numWads; ++i) { str wad; - s.readString( wad ); + s.readString (wad); wads << wad; } // The demo has two checksum strings. We're not interested // in them though. - str sink; - for( int i = 0; i < 2; ++i ) - s.readString( sink ); + for (int i = 0; i < 2; ++i) + s.readString (sink); } else { - error( fmt( tr( "Unknown header %1!\n" ), (int) header )); - return 4; + error (fmt (tr ("Unknown header %1!\n"), (int) header)); + return 3; } } - - if( !ready ) { - error( fmt( tr( "Incomplete demo header in '%s'!" ), path )); - return 5; - } - - int i = getVersionIndex( zanversion ); - if( i == -1 ) { - error( fmt( tr( "Unknown Zandronum version %1!\n" ), zanversion )); - return 6; + + if (!ready) { + error (fmt (tr ("Incomplete demo header in '%s'!"), path)); + return 3; } + if (!isKnownVersion (zanversion)) { + UnknownVersionPrompt* prompt = new UnknownVersionPrompt (path, zanversion, (buildID == 1)); + if (!prompt->exec()) + return 6; + + if (!isKnownVersion (zanversion)) { + error (tr ("Failure in configuration! This shouldn't happen.")); + return 6; + } + } + QSettings cfg; - str binarypath = cfg.value( binaryConfigName( zanversion )).toString(); - - if( binarypath.isEmpty() ) { - error( fmt( tr( "No binary path specified for Zandronum version %1!\n" ), zanversion )); + str binarypath = cfg.value (binaryConfigName (zanversion)).toString(); + + if (binarypath.isEmpty()) { + error (fmt (tr ("No binary path specified for Zandronum version %1!"), zanversion)); return 7; } - - str iwad, iwadpath; - list<str> pwads, pwadpaths; + + str iwadpath; + list<str> pwadpaths; // Find the WADs - for( const str& wad : wads ) { - str path = findWAD( wad ); + for (const str& wad : wads) { + str path = findWAD (wad); // IWAD names can appear in uppercase too. Linux is case-sensitive, so.. - if( &wad == &wads[0] && path.isEmpty() ) - path = findWAD( wad.toUpper() ); + if (&wad == &wads[0] && path.isEmpty()) + path = findWAD (wad.toUpper()); - if( path.isEmpty() ) { - error( fmt( tr( "Couldn't find %1!\n" ), wad )); + if (path.isEmpty()) { + error (fmt (tr ("Couldn't find %1!"), wad)); return 8; } - if( &wad == &wads[0] ) { + if (&wad == &wads[0]) iwadpath = path; - iwad = wad; - } else { + else pwadpaths << path; - pwads << wad; - } } - if( !cfg.value( "nodemoprompt", false ).toBool() ) { + if (!cfg.value ("nodemoprompt", false).toBool()) { str pwadtext; - for( const str& pwad : pwads ) { - if( !pwadtext.isEmpty() ) + + for (const str& pwad : wads) { + if (&pwad == &wads[0]) + continue; // skip the IWAD + + if (!pwadtext.isEmpty()) pwadtext += "<br />"; pwadtext += pwad; @@ -211,33 +252,31 @@ QDialog* dlg = new QDialog; Ui_DemoPrompt ui; - ui.setupUi( dlg ); - ui.demoNameLabel->setText( basename( path )); - ui.demoRecorder->setText( userinfo.netname ); - ui.versionLabel->setText( zanversion ); - ui.iwadLabel->setText( wads[0] ); - ui.pwadsLabel->setText( pwadtext ); + ui.setupUi (dlg); + ui.demoNameLabel->setText (basename (path)); + ui.demoRecorder->setText (uncolorize (userinfo.netname)); + ui.versionLabel->setText (zanversion); + ui.iwadLabel->setText (wads[0]); + ui.pwadsLabel->setText (pwadtext); + dlg->setWindowTitle (fmt (APPNAME " %1", versionString())); - if( !dlg->exec() ) + if (!dlg->exec()) return 1; } - - print( "binary: %1\n", binarypath ); - print( "iwad: %1\npwads: %2\n", iwadpath, pwadpaths ); - - QStringList cmdlineList ({ + + QStringList cmdlineList ( { "-playdemo", path, "-iwad", iwadpath, }); - if( pwadpaths.size() > 0 ) { + if (pwadpaths.size() > 0) { cmdlineList << "-file"; cmdlineList << pwadpaths; } - print( "commandline: %1 %2\n", binarypath, cmdlineList.join( " " )); + print ("Executing: %1 %2\n", binarypath, cmdlineList.join (" ")); QProcess* proc = new QProcess; - proc->start( binarypath, cmdlineList ); - proc->waitForFinished( -1 ); + proc->start (binarypath, cmdlineList); + proc->waitForFinished (-1); return 0; } \ No newline at end of file
--- a/src/demo.h Wed Jul 17 19:45:19 2013 +0300 +++ b/src/demo.h Sun Aug 11 02:58:55 2013 +0300 @@ -1,5 +1,6 @@ #ifndef DEMO_H #define DEMO_H + #include "types.h" enum { @@ -16,6 +17,12 @@ DemoWads }; -int launchDemo( str path ); +struct VersionInfo { + str shortVersion; + str versionString; + bool release; +}; + +int launchDemo (str path); #endif // DEMO_H \ No newline at end of file
--- a/src/main.cpp Wed Jul 17 19:45:19 2013 +0300 +++ b/src/main.cpp Sun Aug 11 02:58:55 2013 +0300 @@ -4,10 +4,6 @@ #include "config.h" #include "demo.h" -const list<str> g_zanVersions ({ - "1.1-r130716-1906M", -}); - // ============================================================================= // ----------------------------------------------------------------------------- int main( int argc, char* argv[] ) {
--- a/src/main.h Wed Jul 17 19:45:19 2013 +0300 +++ b/src/main.h Sun Aug 11 02:58:55 2013 +0300 @@ -19,9 +19,9 @@ #include <QSettings> +struct VersionInfo; static const std::nullptr_t null = nullptr; -extern const QList<QString> g_zanVersions; QString versionString(); #endif // MAIN_H \ No newline at end of file
--- a/src/misc.cpp Wed Jul 17 19:45:19 2013 +0300 +++ b/src/misc.cpp Sun Aug 11 02:58:55 2013 +0300 @@ -1,22 +1,54 @@ #include "misc.h" -uint32 makeByteID( uint8 a, uint8 b, uint8 c, uint8 d ) { - return a | ( b << 8 ) | ( c << 16 ) | ( d << 24 ); +uint32 makeByteID (uint8 a, uint8 b, uint8 c, uint8 d) { + return a | (b << 8) | (c << 16) | (d << 24); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +str binaryConfigName (str ver) { + return fmt ("binaries/%1", ver); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +list<var> getVersionsList() { + QSettings cfg; + return cfg.value ("binarynames", list<var>()).toList(); } // ============================================================================= // ----------------------------------------------------------------------------- -str binaryConfigName( str ver ) { - return fmt( "binaries/%1", ver ); +list<var> getReleasesList() { + QSettings cfg; + return cfg.value ("releasenames", list<var>()).toList(); } // ============================================================================= // ----------------------------------------------------------------------------- -str basename( str path ) { - long lastpos = path.lastIndexOf( "/" ); +void addVersion (str name, bool isRelease, str binaryPath) { + QSettings cfg; + list<var> versions = getVersionsList(); + versions << var (name); + cfg.setValue ("binarynames", versions); + cfg.setValue (binaryConfigName (name), binaryPath); - if( lastpos != -1 ) - return path.mid( lastpos + 1 ); + if (isRelease) { + versions = getReleasesList(); + versions << var (name); + cfg.setValue ("releasenames", versions); + } + + cfg.sync(); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +str basename (str path) { + long lastpos = path.lastIndexOf ("/"); + + if (lastpos != -1) + return path.mid (lastpos + 1); return path; -} \ No newline at end of file +}
--- a/src/misc.h Wed Jul 17 19:45:19 2013 +0300 +++ b/src/misc.h Sun Aug 11 02:58:55 2013 +0300 @@ -3,9 +3,12 @@ #include "types.h" -uint32 makeByteID( uint8 a, uint8 b, uint8 c, uint8 d ); -str binaryConfigName( str ver ); -str basename( str path ); +uint32 makeByteID (uint8 a, uint8 b, uint8 c, uint8 d); +str binaryConfigName (str ver); +str basename (str path); +list<var> getVersionsList(); +list<var> getReleasesList(); +void addVersion (str name, bool isRelease, str binaryPath); // ----------------------------------------------------------------------------- // Templated clamp
--- a/src/src.pro Wed Jul 17 19:45:19 2013 +0300 +++ b/src/src.pro Sun Aug 11 02:58:55 2013 +0300 @@ -9,5 +9,6 @@ RCC_DIR = ./build/ SOURCES = *.cpp HEADERS = *.h +QT += network FORMS = ui/*.ui QMAKE_CXXFLAGS += -std=c++0x \ No newline at end of file
--- a/src/ui/configbox.ui Wed Jul 17 19:45:19 2013 +0300 +++ b/src/ui/configbox.ui Sun Aug 11 02:58:55 2013 +0300 @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>480</width> - <height>320</height> + <width>544</width> + <height>308</height> </rect> </property> <property name="minimumSize"> @@ -115,11 +115,14 @@ </widget> <widget class="QWidget" name="tab_2"> <attribute name="title"> - <string>Zandronum Binaries</string> + <string>Release Binaries</string> </attribute> <layout class="QVBoxLayout" name="verticalLayout_4"> <item> <widget class="QScrollArea" name="scrollArea"> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> <property name="widgetResizable"> <bool>true</bool> </property> @@ -128,8 +131,8 @@ <rect> <x>0</x> <y>0</y> - <width>96</width> - <height>26</height> + <width>516</width> + <height>213</height> </rect> </property> <layout class="QVBoxLayout" name="verticalLayout_5"> @@ -142,6 +145,38 @@ </item> </layout> </widget> + <widget class="QWidget" name="tab_4"> + <attribute name="title"> + <string>Testing Binaries</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_7"> + <item> + <widget class="QScrollArea" name="scrollArea_2"> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="widgetResizable"> + <bool>true</bool> + </property> + <widget class="QWidget" name="scrollAreaWidgetContents_2"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>516</width> + <height>213</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout_8"> + <item> + <widget class="QWidget" name="betaVersions" native="true"/> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> <widget class="QWidget" name="tab_3"> <attribute name="title"> <string>Misc</string> @@ -153,7 +188,7 @@ <string>If this is not set, a prompt showing demo info is displayed first.</string> </property> <property name="text"> - <string>Launch immediately</string> + <string>Launch without prompt</string> </property> </widget> </item> @@ -175,14 +210,66 @@ </widget> </item> <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QWidget" name="widget" native="true"> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QLabel" name="updateLabel"> + <property name="text"> + <string>Checking for updates... </string> + </property> + </widget> + </item> + <item> + <widget class="QProgressBar" name="updateProgress"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16</height> + </size> + </property> + <property name="maximum"> + <number>0</number> + </property> + <property name="value"> + <number>-1</number> + </property> + <property name="textVisible"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> </item> </layout> </widget>