Skip to content

Commit

Permalink
nif versions below 4
Browse files Browse the repository at this point in the history
  • Loading branch information
m4444x committed Sep 27, 2006
1 parent fa2411c commit f626a1d
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 76 deletions.
1 change: 0 additions & 1 deletion basemodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,6 @@ Q_OBJECT
virtual quint32 str2ver( QString ) const = 0;

virtual bool setHeaderString( const QString & ) = 0;
virtual bool setVersion( quint32 ) = 0;

// root item
NifItem * root;
Expand Down
5 changes: 0 additions & 5 deletions kfmmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,11 +233,6 @@ bool KfmModel::setHeaderString( const QString & s )
}
}

bool KfmModel::setVersion( quint32 v )
{
return false;
}

bool KfmModel::load( QIODevice & device )
{
clear();
Expand Down
1 change: 0 additions & 1 deletion kfmmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ Q_OBJECT
bool setItemValue( NifItem * item, const NifValue & v );

bool setHeaderString( const QString & );
bool setVersion( quint32 );

bool evalVersion( NifItem * item, bool chkParents = false ) const;

Expand Down
186 changes: 139 additions & 47 deletions nifmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,21 @@ QString NifModel::version2string( quint32 v )
quint32 NifModel::version2number( const QString & s )
{
if ( s.isEmpty() ) return 0;
QStringList l = s.split( "." );
if ( l.count() != 4 )

if ( s.contains( "." ) )
{
QStringList l = s.split( "." );
quint32 v = 0;
for ( int i = 0; i < 4 && i < l.count(); i++ )
v += l[i].toInt( 0, 10 ) << ( (3-i) * 8 );
return v;
}
else
{
bool ok;
quint32 i = s.toUInt( &ok );
return ( i == 0xffffffff ? 0 : i );
}
quint32 v = 0;
for ( int i = 0; i < 4; i++ )
v += l[i].toInt( 0, 10 ) << ( (3-i) * 8 );
return v;
}

bool NifModel::evalVersion( NifItem * item, bool chkParents ) const
Expand Down Expand Up @@ -1048,19 +1052,39 @@ bool NifModel::setHeaderString( const QString & s )
msg( Message() << "this is not a NIF" );
return false;
}
return true;
}

bool NifModel::setVersion( quint32 v )
{
// verify version number
if ( ! isVersionSupported( v ) )

int p = s.indexOf( "Version", 0, Qt::CaseInsensitive );
if ( p >= 0 )
{
QString v = s;

v.remove( 0, p + 8 );

for ( int i = 0; i < v.length(); i++ )
{
if ( v[i].isDigit() || v[i] == QChar( '.' ) )
continue;
else
{
v = v.left( i );
}
}

version = version2number( v );

if ( ! isVersionSupported( version ) )
{
msg( Message() << "version" << version2string( version ) << "(" << v << ")" << "is not supported yet" );
return false;
}

return true;
}
else
{
msg( Message() << "version" << version2string( v ) << "is not supported yet" );
msg( Message() << "invalid header string" );
return false;
}
version = v;
return true;
}

bool NifModel::load( QIODevice & device )
Expand All @@ -1082,47 +1106,101 @@ bool NifModel::load( QIODevice & device )

emit sigProgress( 0, numblocks );
QTime t = QTime::currentTime();

// read in the NiBlocks

try
{
for ( int c = 0; c < numblocks; c++ )
if ( version >= 0x0303000d )
{
emit sigProgress( c + 1, numblocks );

if ( device.atEnd() )
throw QString( "unexpected EOF during load" );

QString blktyp;

if ( version > 0x0a000000 )
// read in the NiBlocks
for ( int c = 0; c < numblocks; c++ )
{
if ( version < 0x0a020000 ) device.read( 4 );
emit sigProgress( c + 1, numblocks );

if ( device.atEnd() )
throw QString( "unexpected EOF during load" );

QString blktyp;

if ( version >= 0x0a000000 )
{
if ( version < 0x0a020000 ) device.read( 4 );

// block types are stored in the header for versions above 10.x.x.x
int blktypidx = get<int>( index( c, 0, getIndex( createIndex( header->row(), 0, header ), "Block Type Index" ) ) );
blktyp = get<QString>( index( blktypidx, 0, getIndex( createIndex( header->row(), 0, header ), "Block Types" ) ) );
}
else
{
int len;
device.read( (char *) &len, 4 );
if ( len < 2 || len > 80 )
throw QString( "next block does not start with a NiString" );
blktyp = device.read( len );
}

int blktypidx = get<int>( index( c, 0, getIndex( createIndex( header->row(), 0, header ), "Block Type Index" ) ) );
blktyp = get<QString>( index( blktypidx, 0, getIndex( createIndex( header->row(), 0, header ), "Block Types" ) ) );
if ( isNiBlock( blktyp ) )
{
msg( DbgMsg() << "loading block" << c << ":" << blktyp );
insertNiBlock( blktyp, -1, true );
if ( ! load( root->child( c+1 ), stream, true ) )
throw QString( "failed to load block number %1 (%2) previous block was %3" ).arg( c ).arg( blktyp ).arg( root->child( c )->name() );
}
else
throw QString( "encountered unknown block (%1)" ).arg( blktyp );
}
else

// read in the footer
if ( !load( getFooterItem(), stream, true ) )
throw QString( "failed to load file footer" );
}
else
{ // versions below 3.3.0.13
QMap<qint32,qint32> linkMap;

for ( qint32 c = 0; true; c++ )
{
emit sigProgress( c + 1, 0 );

if ( device.atEnd() )
throw QString( "unexpected EOF during load" );

int len;
device.read( (char *) &len, 4 );
if ( len < 2 || len > 80 )
throw QString( "next block starts not with a NiString" );
blktyp = device.read( len );
}

if ( isNiBlock( blktyp ) )
{
msg( DbgMsg() << "loading block" << c << ":" << blktyp );
insertNiBlock( blktyp, -1, true );
if ( ! load( root->child( c+1 ), stream, true ) )
throw QString( "failed to load block number %1 (%2) previous block was %3" ).arg( c ).arg( blktyp ).arg( root->child( c )->name() );
if ( len < 0 || len > 80 )
throw QString( "next block does not start with a NiString" );

QString blktyp = device.read( len );

if ( blktyp == "End Of File" )
{
break;
}
else if ( blktyp == "Top Level Object" )
{
device.read( (char *) &len, 4 );
if ( len < 0 || len > 80 )
throw QString( "next block does not start with a NiString" );
blktyp = device.read( len );
}

qint32 p;
device.read( (char *) &p, 4 );
p -= 1;
if ( p != c )
linkMap.insert( p, c );

if ( isNiBlock( blktyp ) )
{
msg( Message() << "loading block" << c << ":" << blktyp );
insertNiBlock( blktyp, -1, true );
if ( ! load( root->child( c+1 ), stream, true ) )
throw QString( "failed to load block number %1 (%2) previous block was %3" ).arg( c ).arg( blktyp ).arg( root->child( c )->name() );
}
else
throw QString( "encountered unknown block (%1)" ).arg( blktyp );
}
else
throw QString( "encountered unknown block (%1)" ).arg( blktyp );
mapLinks( linkMap );
}
if ( !load( getFooterItem(), stream, true ) )
throw QString( "failed to load file footer" );
}
catch ( QString err )
{
Expand All @@ -1137,6 +1215,12 @@ bool NifModel::load( QIODevice & device )

bool NifModel::save( QIODevice & device ) const
{
if ( ! checkVersion( 0x04000000, 0 ) )
{
msg( Message() << "saving not supported yet for nif versions below 4.0" );
return false;
}

NifOStream stream( this, &device );

emit sigProgress( 0, rowCount( QModelIndex() ) );
Expand Down Expand Up @@ -1233,7 +1317,15 @@ bool NifModel::loadHeaderOnly( const QString & fname )
bool NifModel::checkForBlock( const QString & filepath, const QString & blockId )
{
NifModel nif;
return nif.loadHeaderOnly( filepath ) && nif.getArray<QString>( nif.getHeader(), "Block Types" ).contains( blockId );
if ( nif.loadHeaderOnly( filepath ) )
{
foreach ( QString s, nif.getArray<QString>( nif.getHeader(), "Block Types" ) )
{
if ( inherits( s, blockId ) )
return true;
}
}
return false;
}

bool NifModel::save( QIODevice & device, const QModelIndex & index ) const
Expand Down
1 change: 0 additions & 1 deletion nifmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ Q_OBJECT
int getBlockNumber( NifItem * item ) const;

bool setHeaderString( const QString & );
bool setVersion( quint32 );

QString ver2str( quint32 v ) const { return version2string( v ); }
quint32 str2ver( QString s ) const { return version2number( s ); }
Expand Down
Loading

0 comments on commit f626a1d

Please sign in to comment.