module Z80

Include this module in your program class to turn it to a powerfull Z80 macro assembler.


To fully benefit from z80rb powers:


Constants

DebugInfo
Relocation

Attributes

alias_info[R]

A map of alias labels and their evaluated values.

code[R]

A compiled code for the Z80 CPU as a binary string.

debug_info[R]

A raw, debug information with all selections applied.

imports[R]

A hash containing all instanced of imported programs.

labels[R]

A hash containing all evaluated label values of the compiled program.

org[R]

The starting address of the compiled code.

reloc_info[R]

A relocation table with all selections applied.

Public Class Methods

add_code(prg, data, type = 1, mnemo = nil, *mpar) click to toggle source

Method used by Program instructions was placed here to not pollute program namespace anymore.

# File lib/z80.rb, line 139
def add_code(prg, data, type = 1, mnemo = nil, *mpar)
        raise TypeError unless data.is_a? String
        l = Label.new(pc = prg.pc, type, :code)
        prg.debug << DebugInfo.new(pc, data.bytesize, mnemo, mpar, prg.instance_variable_get('@context_labels').dup << l)
        prg.code << data
        l
end
add_reloc(prg, label, size, offset = 0, from = nil) click to toggle source

Method used by Program instructions was placed here to not pollute program namespace anymore.

# File lib/z80.rb, line 147
def add_reloc(prg, label, size, offset = 0, from = nil)
        raise Syntax, "from argument accepted only for reloc size == 1" unless from.nil? or size == 1
        alloc = label.to_label(prg).to_alloc
        if alloc.immediate? and (size == 2 or from==:self)
                prg.reloc << Relocation.new(prg.pc + offset, alloc, size, from)
                [alloc.to_i(0, from)].pack(size == 1 ? 'c' : 's<')
        else
                prg.reloc << Relocation.new(prg.pc + offset, alloc, size, from)
                "\x0"*size
        end
end

Public Instance Methods

[](name) click to toggle source

Returns an evaluated label's value by its name.

# File lib/z80.rb, line 40
def [](name)
        @labels[name.to_s]
end
debug() click to toggle source

Creates a debugger view from an instance of a Z80::Program. Returns an array of strings.

Example debugger output:

=============== ZXMath ===============
8023:                                  :mul
8023: 5D          ld   e, l
8024: 54          ld   d, h
8025: 218080      ld   hl, 0000H
8028: CB3F        srl  a               :mul.loop1
802A: 3803        jr   NC, 802fH       -> noadd
802C: 19          add  hl, de
802D: 380B        jr   C, 803aH
802F: 2807        jr   Z, 8038H        :mul.noadd -> ok
8031: CB23        sla  e
8033: CB12        rl   d
8035: D22880      jp   NC, 8028H       -> loop1
8038: 4D          ld   c, l            :mul.ok
8039: 44          ld   b, h
803A: D0          ret  NC
803B: CF          rst  08H
803C: 0A                      .
^^^^^^^^^^^^^^^ ZXMath ^^^^^^^^^^^^^^^
# File lib/z80.rb, line 67
def debug
        return @debug if @debug
        reloc = @reloc_info
        imports = @imports.values
        aliases = @alias_info
        @debug = @debug_info.map do |d|
                case d
                when DebugInfo
                        data = code[d.addr, d.size]

                        hxd = proc {|as, g| as.map {|c| '%02X'%c.ord}.join g}

                        label = if d.labels.last.to_name
                                " :" + d.labels.map {|n| n.to_name || n.to_i(org).to_s(16) }.join('.')
                        end

                        unless d.size.zero?
                                relocs = reloc.select {|r| Integer === r.size and (d.addr...d.addr+d.size).member? r.addr }
                                                                                        .map {|r| r.alloc.to_s}
                                                                                        .join(', ')
                                unless relocs.empty?
                                        label = label.to_s + " -> #{relocs}"
                                end
                        end

                        if (mnemo = d.text)
                                if (prm = d.args)
                                        mnemo = mnemo % prm.each_slice(2).map { |o, t|
                                                case t
                                                when :word
                                                        data[o, 2].unpack('S<')[0]
                                                when :index
                                                        if (v = data[o, 1].unpack('c')[0]) < 0
                                                                [?-, -v]
                                                        else
                                                                [?+, v]
                                                        end
                                                when :byte
                                                        data[o, 1].unpack('C')[0]
                                                when :pcrel
                                                        data[o, 1].unpack('c')[0] + d.addr + d.size + org
                                                when :alias
                                                        label = label.to_s + " -> #{d.labels.last.to_aliased_name(org)}"
                                                        aliases[d.labels.last]
                                                end
                                        }.flatten
                                end
                                "#{'%04X'%(d.addr+org)}: #{hxd[data.split(''),''].ljust 12}#{mnemo.ljust 20}#{label}"
                        elsif data.empty? and label
                                "#{'%04X'%(d.addr+org)}: #{' '*32}#{label}"
                        else
                                a = d.addr - 8 + org
                                data.split('').each_slice(8).map do |ds|
                                        a+= 8
                                        "#{'%04X'%a}: #{hxd[ds, ' '].ljust 24}#{ds.join.gsub(/[\x0-\x1f]/, '.').ljust 8}#{label}"
                                end
                        end
                when Integer
                        [" #{imports[d].class} ".center(38, ?=)] + imports[d].debug + [" #{imports[d].class} ".center(38, ?^)]
                else
                        raise "Invalid debug element: #{d.inspect}"
                end
        end.flatten
end