mirror of
https://github.com/safiire/n65.git
synced 2025-01-19 00:29:59 +00:00
103 lines
2.4 KiB
Ruby
103 lines
2.4 KiB
Ruby
require_relative '../instruction_base'
|
|
require_relative '../regexes.rb'
|
|
|
|
module N65
|
|
|
|
|
|
####
|
|
## This directive to include bytes
|
|
class Bytes < InstructionBase
|
|
|
|
#### Custom Exceptions
|
|
class InvalidByteValue < StandardError; end
|
|
|
|
|
|
####
|
|
## Try to parse an incbin directive
|
|
def self.parse(line)
|
|
match_data = line.match(/^\.bytes\s+(.+)$/)
|
|
return nil if match_data.nil?
|
|
|
|
bytes_array = match_data[1].split(',').map do |byte_string|
|
|
|
|
## Does byte_string represent a numeric literal, or is it a symbol?
|
|
## In numeric captures $2 is always binary, $1 is always hex
|
|
|
|
case byte_string.strip
|
|
when Regexp.new("^#{Regexes::Num8}$")
|
|
$2.nil? ? $1.to_i(16) : $2.to_i(2)
|
|
|
|
when Regexp.new("^#{Regexes::Num16}$")
|
|
value = $2.nil? ? $1.to_i(16) : $2.to_i(2)
|
|
|
|
## Break value up into two bytes
|
|
high = (0xff00 & value) >> 8
|
|
low = (0x00ff & value)
|
|
[low, high]
|
|
when Regexp.new("^#{Regexes::Sym}$")
|
|
$1
|
|
else
|
|
fail(InvalidByteValue, byte_string)
|
|
end
|
|
end.flatten
|
|
|
|
Bytes.new(bytes_array)
|
|
end
|
|
|
|
|
|
####
|
|
## Initialize with filename
|
|
def initialize(bytes_array)
|
|
@bytes_array = bytes_array
|
|
end
|
|
|
|
|
|
####
|
|
## Execute on the assembler
|
|
def exec(assembler)
|
|
|
|
promise = assembler.with_saved_state do |saved_assembler|
|
|
@bytes_array.map! do |byte|
|
|
case byte
|
|
when Fixnum
|
|
byte
|
|
when String
|
|
value = saved_assembler.symbol_table.resolve_symbol(byte)
|
|
else
|
|
fail(InvalidByteValue, byte)
|
|
end
|
|
end
|
|
saved_assembler.write_memory(@bytes_array)
|
|
end
|
|
|
|
begin
|
|
promise.call
|
|
rescue SymbolTable::UndefinedSymbol
|
|
## Write the bytes but assume a zero page address for all symbols
|
|
## And just write 0xDE for a placeholder
|
|
placeholder_bytes = @bytes_array.map do |byte|
|
|
case bytes
|
|
when Fixnum
|
|
byte
|
|
when String
|
|
0xDE
|
|
else
|
|
fail(InvalidByteValue, byte)
|
|
end
|
|
end
|
|
assembler.write_memory(placeholder_bytes)
|
|
return promise
|
|
end
|
|
end
|
|
|
|
|
|
####
|
|
## Display, I don't want to write all these out
|
|
def to_s
|
|
".bytes (#{@bytes_array.length})"
|
|
end
|
|
|
|
end
|
|
|
|
end
|