def to_listing
s=""
variable_name_table_displacement=(contents[2]+(contents[3]<<8))-0x100
variable_value_table_displacement=(contents[6]+(contents[7]<<8))-0x100
statement_table_displacement=(contents[8]+(contents[9]<<8))-0x100
file_end_displacement=(contents[12]+(contents[13]<<8))-0x100
variable_name_table=contents[variable_name_table_displacement+START_OF_FILE_PART_TWO,(variable_value_table_displacement-variable_name_table_displacement)]
variable_names={}
variable_token=0x80
current_variable_name=""
variable_name_table.each_byte do |byte|
if byte>=0x80 then
current_variable_name+=(byte-0x80).chr
variable_names[variable_token]=current_variable_name
variable_token+=1
current_variable_name=""
else
current_variable_name+=byte.chr
end
end
statement_table=contents[statement_table_displacement+START_OF_FILE_PART_TWO,(file_end_displacement-statement_table_displacement)]
p=0
s=""
while p<statement_table.length
line_number=statement_table[p,2].unpack("v")[0]
break if line_number==0x8000
line_length=statement_table[p+2]
line=statement_table[p+3,line_length-2]
s<<"#{line_number} "
break if line_length==0
t=0
start_of_statement=true
while (!line.nil?) && t<line.length && line[t]!=0x16
actual_file_offset=statement_table_displacement+START_OF_FILE_PART_TWO+p+t
token=line[t]
if start_of_statement then
t+=1
token=line[t]
command=ATARI_BASIC_COMMAND_TOKENS[token]
command="[UNK CMD %02X]" % token if command.nil?
s<<"#{command} " unless token==0x36
start_of_statement=false
if token==0x00 then
s<<line[t+1,line.length-(t+3)]
t=line.length
end
elsif token>=0x80 then
variable=variable_names[token]
variable="[UNK VAR %02X]" % token if variable.nil?
s<<variable
elsif token==0x14 then
s<<":"
start_of_statement=true
elsif token==0x0D then
const=line[t+1]+(line[t+2]<<8)
s<<"&%x"%const
t+=2
elsif token==0x0E then
buffer=line[t+1,6]
s<<parse_bytes_as_float(buffer).to_s.sub(/\.0$/,'')
t+=6
elsif token==0x0F then
length=line[t+1]
s<<"\"#{line[t+2,length]}\""
t+=length+1
elsif token==0x1B then
s<<"THEN "
start_of_statement=true
else
op_func=ATARI_BASIC_OPERATORS_AND_FUNCTIONS[token]
op_func="[UNK OP/FUNC %02X]" % token if op_func.nil?
s<<"#{op_func}"
end
t+=1
end
s<<"\n"
p+=line_length
end
s
end