$:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__))) require 'D65' require 'DSKFile' require 'HGR' #Apple DOS 3.3 file class DOSFile < DSKFile attr_accessor(:filename,:contents,:locked,:file_type_byte) def initialize(filename,contents,locked=false,file_type_byte=nil) @filename=filename @locked=locked @contents=contents @file_type_byte=file_type_byte @file_type=sprintf("$%02X",file_type_byte) end #File type as displayed in Apple DOS 3.3 Catalog def file_type @file_type end def file_type_byte @file_type_byte end #render a filename in form suitable for inclusion in a DOS catalog def DOSFile.catalog_filename(filename) s="" for i in 0..29 c=(filename[i]) if c.nil? then c=0xA0 else c=(c|0x80) end s+=c.chr end s end def catalog_filename DOSFile.catalog_filename(filename) end end class TextFile < DOSFile def file_type "T" end def file_type_byte 0x00 end def file_extension ".txt" end def to_s s="" @contents.each_byte{|b| s+=(b%0x80).chr.tr(0x0D.chr,"\n")} return s.sub(/\0*$/,"") end end class BinaryFile < DOSFile def file_type "B" end def file_type_byte 0x04 end def file_extension ".bin" end def contents_without_header file_length=contents[2]+contents[3]*256 @contents[4..file_length+3] end def disassembly start_address=(@contents[0]+@contents[1]*256) D65.disassemble(contents_without_header,start_address) end def can_be_picture? start_address=(@contents[0]+@contents[1]*256) HGR.can_be_hgr_screen?(contents_without_header,start_address) end def to_png(pallete_mode=:amber) HGR.buffer_to_png(contents_without_header,pallete_mode) end end # Adapted from FID.C -- a utility to browse Apple II .DSK image files by Paul Schlyter (pausch@saaf.se) #Integer Basic file format: # (16-bit little endian) # # ...... # # # where is: # 1 byte: Line length # 2 bytes: Line number, binary little endian # # # # ...... # # # is one of: # $12 - $7F: Tokens as listed below: 1 byte/token # $80 - $FF: ASCII characters with high bit set # $B0 - $B9: Integer constant, 3 bytes: $B0-$B9, # followed by the integer value in # 2-byte binary little-endian format # (Note: a $B0-$B9 byte preceded by an # alphanumeric ASCII(hi_bit_set) byte # is not the start of an integer # constant, but instead part of a # variable name) # # is: # $01: One byte having the value $01 # (Note: a $01 byte may also appear # inside an integer constant) # # Note that the tokens $02 to $11 represent commands which # can be executed as direct commands only -- any attempt to # enter then into an Integer Basic program will be rejected # as a syntax error. Therefore, no Integer Basic program # which was entered through the Integer Basic interpreter # will contain any of the tokens $02 to $11. The token $00 # appears to be unused and won't appear in Integer Basic # programs either. However, $00 is used as an end-of-line # marker in S-C Assembler source files, which also are of # DOS file type "I". # # (note here a difference from Applesoft Basic, where there # are no "direct mode only" commands - any Applesoft commands # can be entered into an Applesoft program as well). class IntegerBasicFile < DOSFile def file_type "I" end def file_extension ".bas" end def file_type_byte 0x01 end #display file with all INTEGER BASIC tokens expanded to ASCII def to_s buffer_as_integer_basic_file(@contents) end private IB_REM_TOKEN =0x5D IB_UNARY_PLUS = 0x35 IB_UNARY_MINUS = 0x36 IB_QUOTE_START = 0x28 IB_QUOTE_END = 0x29 INTEGER_BASIC_TOKENS= [ # $00-$0F "HIMEM:","<$01>", "_", " : ", "LOAD", "SAVE", "CON", "RUN", # Direct commands "RUN", "DEL", ",", "NEW", "CLR", "AUTO", ",", "MAN", # $10-$1F "HIMEM:","LOMEM:","+", "-", # Binary ops "*", "/", "=", "#", ">=", ">", "<=", "<>", "<", "AND", "OR", "MOD", # $20-$2F "^", "+", "(", ",", "THEN", "THEN", ",", ",", "\"", "\"", "(", "!", "!", "(", "PEEK", "RND", # $30-$3F "SGN", "ABS", "PDL", "RNDX", "(", "+", "-", "NOT", # Unary ops "(", "=", "#", "LEN(", "ASC(", "SCRN(", ",", "(", # $40-$4F "$", "$", "(", ",", ",", ";", ";", ";", ",", ",", ",", "TEXT", # Statements "GR", "CALL", "DIM", "DIM", # $50-$5F "TAB", "END", "INPUT", "INPUT", "INPUT", "FOR", "=", "TO", "STEP", "NEXT", ",", "RETURN", "GOSUB", "REM", "LET", "GOTO", # $60-$6F "IF", "PRINT", "PRINT", "PRINT", "POKE", ",", "COLOR=","PLOT", ",", "HLIN", ",", "AT", "VLIN", ",", "AT", "VTAB", # $70-$7F "=", "=", ")", ")", "LIST", ",", "LIST", "POP", "NODSP", "DSP", "NOTRACE","DSP", "DSP", "TRACE", "PR#", "IN#", ] def is_alnum(c) !((c.chr=~/[A-Za-z0-9]/).nil?) end def buffer_as_integer_basic_file(buffer) length=buffer[0]+buffer[1]*256 index=2 s="" while (index= 0x80 ) then if ( !in_REM && !in_QUOTE && !last_AN && (b>= 0xB0 && b <= 0xB9) ) then integer = buffer[index+1]+buffer[index+2]*256 index+=2 s+=sprintf( (last_TOK && lead_SP ) ? " %d" : "%d", integer ) lead_SP = true else c = b & 0x7F if (!in_REM && !in_QUOTE && last_TOK && lead_SP && is_alnum(c)) then s+=" " end if ( c >= 0x20 ) then s+=c.chr else s+="^"+(c+0x40).chr end last_AN = is_alnum(c) end last_TOK =false else token = INTEGER_BASIC_TOKENS[b] lastchar = token[token.length-1] case b when IB_REM_TOKEN then in_REM = true when IB_QUOTE_START then in_QUOTE = true when IB_QUOTE_END then in_QUOTE = false end if lead_SP && ( is_alnum(token[0]) || b == IB_UNARY_PLUS || b == IB_UNARY_MINUS || b == IB_QUOTE_START ) then s+=" " end s+=token last_AN = false lead_SP = is_alnum(lastchar) || lastchar == ')' || lastchar == '\"' last_TOK = true end index+=1 done_line=(index>length)||(buffer[index]==0x01) end s+="\n" index+=1 # skip over "end of line" marker end s end end class AppleSoftFile < DOSFile def file_type "A" end def file_type_byte 0x02 end #display file with all AppleSoft BASIC tokens expanded to ASCII def to_s buffer_as_applesoft_file(@contents) end def file_extension ".bas" end end # Adapted from FID.C -- a utility to browse Apple II .DSK image files by Paul Schlyter (pausch@saaf.se) # # S-C Assembler file format: # # (16-bit little endian) # # ...... # # # where is: # (8-bit: including length byte, line no, contents, zero> # (16-bit little endian: 0-65535) # # ($00, to mark the end of the S-C Asm source line) # # where are an arbitrary sequence of: # : $20 to $7E - literal characters # : $80 to $BF - represents 1 to 63 spaces # : $C0 - represents n times # class SCAsmFile < DOSFile def file_type "I" end def file_type_byte 0x01 end #display file with all tokens expanded def to_s SCAsmFile.buffer_as_scasm_file(@contents) end def file_extension ".asm" end def SCAsmFile.can_be_scasm_file?(buffer) if buffer.length<2 then return false end length=buffer[0]+buffer[1]*256 index=2 s="" while (index0xc0 then return false end end index+= (line_length-3).abs end return true end private def SCAsmFile.buffer_as_scasm_file(buffer) length=buffer[0]+buffer[1]*256 index=2 s="" while (index=0x80) then s+=" "*(b-0x80) index+=1 else s+=b.chr index+=1 end end index+=1 #skip over end-of-line marker s+="\n" end s end end # == Author # Jonno Downes (jonno@jamtronix.com) # # == Copyright # Copyright (c) 2007 Jonno Downes (jonno@jamtronix.com) # #Permission is hereby granted, free of charge, to any person obtaining #a copy of this software and associated documentation files (the #"Software"), to deal in the Software without restriction, including #without limitation the rights to use, copy, modify, merge, publish, #distribute, sublicense, and/or sell copies of the Software, and to #permit persons to whom the Software is furnished to do so, subject to #the following conditions: # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.