size_t SarReader::getFileLength( const char *file_name )
{
    size_t ret;
    if ( ( ret = DirectReader::getFileLength( file_name ) ) ) return ret;

    ArchiveInfo *info = archive_info.next;
    unsigned int j = 0;
    for ( int i=0 ; i<num_of_sar_archives ; i++ ){
        j = getIndexFromFile( info, file_name );
        if ( j != info->num_of_files ) break;
        info = info->next;
    }
    if ( !info ) return 0;
    
    if ( info->fi_list[j].original_length != 0 )
        return info->fi_list[j].original_length;

    int type = info->fi_list[j].compression_type;
    if ( type == NO_COMPRESSION )
        type = getRegisteredCompressionType( file_name );
    if ( type == NBZ_COMPRESSION || type == SPB_COMPRESSION ) {
        info->fi_list[j].original_length = getDecompressedFileLength( type, info->file_handle, info->fi_list[j].offset );
    }
    
    return info->fi_list[j].original_length;
}
size_t SarReader::getFileSub( ArchiveInfo *ai, const char *file_name, unsigned char *buf )
{
    unsigned int i = getIndexFromFile( ai, file_name );
    if ( i == ai->num_of_files ) return 0;

#if defined(PSP)
    if (ai->power_resume_number != psp_power_resume_number){
        FILE *fp = fopen(ai->file_name, "rb");
        ai->file_handle = fp;
        ai->power_resume_number = psp_power_resume_number;
    }
#endif

    int type = ai->fi_list[i].compression_type;
    if ( type == NO_COMPRESSION ) type = getRegisteredCompressionType( file_name );

    if      ( type == NBZ_COMPRESSION ){
        return decodeNBZ( ai->file_handle, ai->fi_list[i].offset, buf );
    }
    else if ( type == LZSS_COMPRESSION ){
        return decodeLZSS( ai, i, buf );
    }
    else if ( type == SPB_COMPRESSION ){
        return decodeSPB( ai->file_handle, ai->fi_list[i].offset, buf );
    }

    fseek( ai->file_handle, ai->fi_list[i].offset, SEEK_SET );
    size_t ret = fread( buf, 1, ai->fi_list[i].length, ai->file_handle );
    if (key_table_flag)
        for (size_t j=0 ; j<ret ; j++) buf[j] = key_table[buf[j]];
    return ret;
}
Example #3
0
size_t NsaReader::getFileLengthSub( ArchiveInfo *ai, const char *file_name )
{
    unsigned int i = getIndexFromFile( ai, file_name );

    if ( i == ai->num_of_files ) return 0;

    if ( ai->fi_list[i].compression_type == NO_COMPRESSION ){
        int type = getRegisteredCompressionType( file_name );
        if ( type == NBZ_COMPRESSION || type == SPB_COMPRESSION )
            return getDecompressedFileLength( type, ai->file_handle, ai->fi_list[i].offset );
    }
    
    return ai->fi_list[i].original_length;
}
void SarReader::readArchive( ArchiveInfo *ai, int archive_type, unsigned int offset )
{
    unsigned int i;
    
    /* Read header */
    for (i=0; i<offset; i++)
        readChar( ai->file_handle ); // for commands "ns2" and "ns3"

    if ( archive_type == ARCHIVE_TYPE_NS2 ) {
        // new archive type since NScr2.91
        // - header starts with base_offset (byte-swapped), followed by
        //   filename data - doesn't tell how many files!
        // - filenames are surrounded by ""s
        // - new NS2 filename def: "filename", length (4bytes, swapped)
        // - no compression type? really, no compression.
        // - not sure if NS2 uses key_table or not, using default funcs for now
        ai->base_offset = swapLong( readLong( ai->file_handle ) );
        ai->base_offset += offset;

        // need to parse the whole header to see how many files there are
        ai->num_of_files = 0;
        long unsigned int cur_offset = offset + 4;
        // there's an extra byte at the end of the header, not sure what for
        while(1){
            unsigned char ch = key_table[fgetc( ai->file_handle )];
            if (ch != '"') break;
            cur_offset++;
            do cur_offset++;
            while( (ch = key_table[fgetc( ai->file_handle )] ) != '"' );
            cur_offset += 4;
            readLong( ai->file_handle );
            ai->num_of_files++;
        }
        ai->fi_list = new FileInfo[ ai->num_of_files ];

        // now go back to the beginning and read the file info
        cur_offset = ai->base_offset;
        fseek( ai->file_handle, 4 + offset, SEEK_SET );
        for ( i=0 ; i<ai->num_of_files ; i++ ){
            unsigned int count = 0;
            //skip the beginning double-quote
            unsigned char ch = key_table[fgetc( ai->file_handle )];
            while( (ch = key_table[fgetc( ai->file_handle )] ) != '"' ){
                if ( 'a' <= ch && ch <= 'z' ) ch += 'A' - 'a';
                ai->fi_list[i].name[count++] = ch;
            }
            ai->fi_list[i].name[count] = '\0';
            ai->fi_list[i].compression_type = getRegisteredCompressionType( ai->fi_list[i].name );
            ai->fi_list[i].offset = cur_offset;
            ai->fi_list[i].length = swapLong( readLong( ai->file_handle ) );
            ai->fi_list[i].original_length = ai->fi_list[i].length;
            cur_offset += ai->fi_list[i].length;
        }
    } else {
        // old NSA filename def: filename, ending '\0' byte , compr-type byte,
        // start (4byte), length (4byte))
        ai->num_of_files = readShort( ai->file_handle );
        ai->fi_list = new FileInfo[ ai->num_of_files ];
    
        ai->base_offset = readLong( ai->file_handle );
        ai->base_offset += offset;
    
        for ( i=0 ; i<ai->num_of_files ; i++ ){
            unsigned char ch;
            int count = 0;

            while( (ch = key_table[fgetc( ai->file_handle )] ) ){
                if ( 'a' <= ch && ch <= 'z' ) ch += 'A' - 'a';
                ai->fi_list[i].name[count++] = ch;
            }
            ai->fi_list[i].name[count] = ch;

            if ( archive_type == ARCHIVE_TYPE_NSA )
                ai->fi_list[i].compression_type = readChar( ai->file_handle );
            else
                ai->fi_list[i].compression_type = NO_COMPRESSION;
            ai->fi_list[i].offset = readLong( ai->file_handle ) + ai->base_offset;
            ai->fi_list[i].length = readLong( ai->file_handle );

            if ( archive_type == ARCHIVE_TYPE_NSA ){
                ai->fi_list[i].original_length = readLong( ai->file_handle );
            }
            else{
                ai->fi_list[i].original_length = ai->fi_list[i].length;
            }

            /* Registered Plugin check */
            if ( ai->fi_list[i].compression_type == NO_COMPRESSION )
                ai->fi_list[i].compression_type = getRegisteredCompressionType( ai->fi_list[i].name );

            if ( ai->fi_list[i].compression_type == NBZ_COMPRESSION ||
                 ai->fi_list[i].compression_type == SPB_COMPRESSION ){
                // Delaying checking decompressed file length to prevent
                // massive random access in the archives at the start-up.
                ai->fi_list[i].original_length = 0;
            }
        }
    }
}