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; }
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; } } } }