$:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__))) # Disk image in NADOL format # #CATALOG will be at track $00, sector $03 to track $00, sector $09 #each entry consists of $10 bytes, which are: # 00-0B - filename - if file is deleted, first byte will be FF # 0C-0D - filesize (low byte first) # 0E - track of track sector list sector # 0F - sector of track sector list sector # #TRACK/SECTOR LIST FORMAT # pairs of track/sectors in order. up to 128 entries [assumes that no file can be > 128 sectors] # #SECTOR USAGE BITMAP #is at Track $00, Sector $2, from bytes $20 .. $65 #bitmap is of form: # # ----hi bit-- # | | # 01234567 89ABCDEF # ^^^^^^ ^^^^^^^ # low byte hi byte require 'NADOLFile' class NADOLDisk < DSK def dump_catalog s="" files.keys.sort.each { |file_name| file=files[file_name] s<< "#{sprintf('% 6d',file.contents.length)} #{file.filename}\n" } s end def initialize(file_bytes,sector_order) super(file_bytes,sector_order) self.read_catalog end def file_system :nadol end def set_sector(track,sector,contents) super(track,sector,contents) #now mark sector as used in sector usage list #don't bother marking the 'system' sectors used if ((track>0) || (sector>9)) then sector_usage_bitmap_sector=get_sector(0,2) offset_of_byte_containing_this_sector=0x20+(track*2)+(sector/8) byte_containing_this_sector=sector_usage_bitmap_sector[offset_of_byte_containing_this_sector] byte_containing_this_sector=byte_containing_this_sector|(2**(7-(sector%8))) sector_usage_bitmap_sector[offset_of_byte_containing_this_sector]=byte_containing_this_sector set_sector(0,2,sector_usage_bitmap_sector) end end #iterate through the CATALOG to find either the named file or (if nil is passed in) an empty slot def find_catalog_slot(filename) track=0 sector=3 catalog_filename=NADOLFile.catalog_filename(filename.upcase) unless filename.nil? while (sector<=9) do sector_data=get_sector(track,sector) (0..15).each do |slot_no| slot_start=slot_no*0x10 if (filename.nil? && (sector_data[slot_start]==0x00)|| (sector_data[slot_start]==0xFF)) then return DSKTrackSector.new(track,sector,slot_start) end if (!filename.nil?) && (sector_data[slot_start..slot_start+0x0B]==catalog_filename) then return DSKTrackSector.new(track,sector,slot_start) end end sector+=1 end nil end #iterate through the sector usage bitmap, return a list of [track,sector] for sectors marked available def free_sector_list sector_usage_bitmap=get_sector(0,2)[0x20..0x65] free_sectors=[] (0..(sector_usage_bitmap.length/2)-1).each do |track| track_bitmap_lo=sector_usage_bitmap[track*2] track_bitmap_hi=sector_usage_bitmap[1+track*2] (0..7).each do |sector| if ((track_bitmap_lo & (2**(7-sector)))==0) then free_sectors<0) then contents="" get_track_sector_list(file_descriptive_entry[0x0E],file_descriptive_entry[0x0F]).each do |ts| contents<