# File lib/file_systems/AppleCPM.rb, line 129
  def self.add_file(file_system_image,native_filetype_class,full_filename,file_contents,file_type=nil,aux_code=nil)
    raise "#{native_filetype_class} not supported on Apple CPM file system" if  native_filetype_class.file_system_file_types[self].nil?
    partial_filename,file_type=CPMFile.split_filename(full_filename)
    full_filename ="#{partial_filename}.#{file_type}"
#    puts "#{full_filename},#{partial_filename},#{file_type}"

    delete_file(file_system_image,full_filename) unless file_system_image.files[full_filename].nil? #so we can overwrite the file if it already exists  

    free_blocks,free_directory_entries=find_free_space(file_system_image)
    total_record_count=(file_contents.length/RECORD_SIZE.to_f).ceil
    total_blocks_needed=(total_record_count/RECORDS_PER_BLOCK.to_f).ceil    
    total_extents_needed=(total_blocks_needed/BLOCKS_PER_EXTENT.to_f).ceil
#    puts "#{total_extents_needed} extents needed"

    raise "#{total_blocks_needed} free blocks required, only #{free_blocks.length} available" unless total_blocks_needed<=free_blocks.length
    raise "#{total_extents_needed} free directory entries required, only #{free_directory_entries.length} available" unless total_extents_needed<=free_directory_entries.length
    catalog=get_block(file_system_image,0)+get_block(file_system_image,1)
    padded_file_contents=file_contents+(0x1A.chr*BLOCK_SIZE)
    
    total_extents_needed.times do |extent_no|
      records_this_extent=(extent_no==(total_extents_needed-1) ? (total_record_count % RECORDS_PER_EXTENT):RECORDS_PER_EXTENT)
      blocks_this_extent=(records_this_extent/RECORDS_PER_BLOCK.to_f).ceil
      blocks_used=[0]*BLOCKS_PER_EXTENT
      first_record_this_extent=extent_no*RECORDS_PER_EXTENT
      contents_this_extent=padded_file_contents[(first_record_this_extent*RECORD_SIZE),blocks_this_extent*BLOCK_SIZE]
      
      blocks_this_extent.times do |block_no|
          this_block=free_blocks[block_no+(extent_no*BLOCKS_PER_EXTENT)]
          set_block(file_system_image,this_block,contents_this_extent[block_no*BLOCK_SIZE,BLOCK_SIZE])
          blocks_used[block_no]=this_block
      end
      dir_entry_no=free_directory_entries[extent_no]
      dir_entry_start=dir_entry_no*0x20
      dir_entry=[0,partial_filename,file_type,extent_no,0,0,records_this_extent,blocks_used].flatten.pack("CA8A3C4C16")
      catalog[dir_entry_start,0x20]=dir_entry
#      puts "dir entry # #{dir_entry_no}"

    end
    
    set_block(file_system_image,0,catalog[0,BLOCK_SIZE])
    set_block(file_system_image,1,catalog[BLOCK_SIZE,BLOCK_SIZE])
    
    native_file=files(file_system_image)[full_filename]
    raise "error: file should now be in catalog\n #{file_system_image.catalog}" if native_file.nil?
    return native_file
  end