# File lib/file_systems/AppleDos.rb, line 173
def self.add_file(file_system_image,native_filetype_class,filename,file_contents,file_type=nil,aux_code=nil)
  #make sure the file type is supported on DOS 3.3!

  raise "#{native_filetype_class} not supported on Apple DOS 3.3 file system" if  native_filetype_class.file_system_file_types[self].nil?
  expected_file_type=native_filetype_class.file_system_file_types[self] 
  file_type=expected_file_type if file_type.nil?
  raise "inconsistent file_type (should be #{expected_file_type} but was #{file_type})" unless expected_file_type==file_type
  native_file=native_filetype_class.new(file_system_image,filename,file_contents,file_type,aux_code)
  raise "couldn't make #{native_filetype_class}" if native_file.nil?
  #if this file exists, delete it first

  file_system_image.delete_file(filename) unless file_system_image.files[filename].nil?
  catalog_slot=find_catalog_slot(file_system_image,nil)
  raise "CATALOG IS FULL!" if catalog_slot.nil?
  raise "invalid catalog slot " if catalog_slot[2].nil?
  free_sectors=free_sector_list(file_system_image)
  sectors_needed=1+(255+file_contents.length)/256
  raise "not enough free space - #{sectors_needed} sectors needed, #{free_sectors.length} available " unless sectors_needed<=free_sectors.length
  #TODO - allow files of more than 122 sectors

  raise "only files up to 122 sectors currently supported " if sectors_needed>122
  #TRACK/SECTOR LIST FORMAT (from Beneath Apple DOS p 4-6)

  # 00  Not used

  # 01  Track number of next T/S list of one is needed or zero if no more t/s list

  # 02  Sector number of next T/S list (if one is present)

  # 03-04       Not used

  # 05-06       Sector offset in file of the first sector described by this list

  # 07-oB       Not used

  # 0C-0D       Track and sector of first data sector or zeros

  # 0E-0F       Track and sector of second data sector or zeros

  # 10-FF       Up to 120 more track and sector pairs

  track_sector_list="\0"*256
  track_sector_list_sector=free_sectors[0]
    (0..sectors_needed-2).each do |sector_in_file|
    sector_to_use=free_sectors[sector_in_file+1]
    track_sector_list[(sector_in_file*2)+0x0C]=sector_to_use[0]
    track_sector_list[(sector_in_file*2)+0X0D]=sector_to_use[1]
    sector_contents=file_contents[(sector_in_file*256),256] || ""
    self.set_sector(file_system_image,sector_to_use[0],sector_to_use[1],sector_contents)
  end
  #write the track/sector list

  self.set_sector(file_system_image,track_sector_list_sector[0],track_sector_list_sector[1],track_sector_list)

  #update the catalog file descriptive entry

  #FILE DESCRIPTIVE ENTRY (from Beneath Apple DOS p 4-6)

  # 00    Track of first track/sector list sector, if this is a deleted file this contains FF

  #     and the original track number is copied to the last byte of the file name (BYTE 20)

  #     If this byte contains a 00, the entry is assumed to never have been used and is

  #     available for use. (This means track 0 can never be used for data even if the DOS image

  #     is 'wiped' from the disk)

  #

  # 01    Sector of first track/sector list sector

  # 02    File type and flags:

  #     80+file type - file is locked

  #     00+file type - file is not locked

  #

  #     00 - TEXT file

  #     01 - INTEGER BASIC file

  #     02 - APPLESOFT BASIC file

  #     04 - BINARY file

  #     08 - S type file

  #     10 - RELOCATABLE object module file

  #     20 - a type file

  #     40 - b type file

  #

  # 03-20 File Name (30 characters)

  # 21-22 Length of file in sectors (LO/HI format)


  catalog_sector=file_system_image.get_sector(catalog_slot[0],catalog_slot[1])
  raise "invalid catalog track #{catalog_slot[0]},sector #{catalog_slot[1]}" if catalog_sector.nil?
  file_descriptive_entry="\0"*0x23
  file_descriptive_entry[0]=track_sector_list_sector[0]
  file_descriptive_entry[1]=track_sector_list_sector[1]
  file_descriptive_entry[2]=file_type
  file_descriptive_entry[3..0x20]=catalog_filename(filename)
  file_descriptive_entry[0x21]=(sectors_needed-1)%256
  file_descriptive_entry[0x22]=(sectors_needed-1)/256

  catalog_sector[catalog_slot[2],0x23]=file_descriptive_entry
  
  self.set_sector(file_system_image,catalog_slot[0],catalog_slot[1],catalog_sector)
  
  raise "catalog not updated correctly!" if find_catalog_slot(file_system_image,filename).nil?
  raise "error: file should now be in catalog" if files(file_system_image)[filename].nil?
  return native_file
end