class N65::MemorySpace

Let’s use this to simulate a virtual address space Either a 16kb prog rom or 8kb char rom space. It can also be used to create arbitrary sized spaces for example to build the final binary ROM in.

Constants

BankSizes

Some constants, the size of PROG and CHAR ROM

Public Class Methods

create_bank(type) click to toggle source

Create a new bank

# File lib/n65/memory_space.rb, line 41
def self.create_bank(type)
  self.new(BankSizes[type], type)
end
create_char_rom() click to toggle source

Create a new CHAR ROM

# File lib/n65/memory_space.rb, line 34
def self.create_char_rom
  self.create_bank(:char)
end
create_prog_rom() click to toggle source

Create a new PROG ROM

# File lib/n65/memory_space.rb, line 27
def self.create_prog_rom
  self.create_bank(:prog)
end
new(size, type) click to toggle source

Create a completely zeroed memory space

# File lib/n65/memory_space.rb, line 48
def initialize(size, type)
  @type = type
  @memory = Array.new(size, 0x0)
end

Public Instance Methods

emit_bytes() click to toggle source

Return the memory as an array of bytes to write to disk

# File lib/n65/memory_space.rb, line 81
def emit_bytes
  @memory
end
read(address, count) click to toggle source

Normalized read from memory

# File lib/n65/memory_space.rb, line 56
def read(address, count)
  from_normalized = normalize_address(address)
  to_normalized = normalize_address(address + (count - 1))
  ensure_addresses_in_bounds!([from_normalized, to_normalized])

  @memory[from_normalized..to_normalized]
end
write(address, bytes) click to toggle source

Normalized write to memory

# File lib/n65/memory_space.rb, line 67
def write(address, bytes)
  from_normalized = normalize_address(address)
  to_normalized = normalize_address(address + bytes.size - 1)
  ensure_addresses_in_bounds!([from_normalized, to_normalized])

  bytes.each_with_index do |byte, index|
    @memory[from_normalized + index] = byte
  end
  bytes.size
end

Private Instance Methods

address_inside_char_rom?(address) click to toggle source

Is this address inside the char rom area?

# File lib/n65/memory_space.rb, line 143
def address_inside_char_rom?(address)
  address >= 0x0000 && address <= 0x1fff
end
address_inside_prog_rom1?(address) click to toggle source

Is this address inside the prog rom 1 area?

# File lib/n65/memory_space.rb, line 129
def address_inside_prog_rom1?(address)
  address >= 0x8000 && address < 0xC000
end
address_inside_prog_rom2?(address) click to toggle source

Is this address inside the prog rom 2 area?

# File lib/n65/memory_space.rb, line 136
def address_inside_prog_rom2?(address)
  address >= 0xC000 && address <= 0xffff
end
ensure_addresses_in_bounds!(addresses) click to toggle source

Are the given addresses in bounds? If not blow up.

# File lib/n65/memory_space.rb, line 90
def ensure_addresses_in_bounds!(addresses)
  addresses.each do |address|
    unless address >= 0 && address < @memory.size
      fail(AccessOutOfBounds, sprintf("Address $%.4X is out of bounds in this #{@type} bank"))
    end
  end
  true
end
normalize_address(address) click to toggle source

Since prog rom can be loaded at either 0x8000 or 0xC000 We should normalize the addresses to fit properly into these banks, basically it acts like it is mirroring addresses in those segments. Char rom doesn’t need this. This will also fail if you are accessing outside of the address space.

# File lib/n65/memory_space.rb, line 106
def normalize_address(address)
  case @type
  when :prog
    if address_inside_prog_rom1?(address)
      return address - 0x8000
    end
    if address_inside_prog_rom2?(address)
      return address - 0xC000
    end
    fail(AccessOutsideProgRom, sprintf("Address $%.4X is outside PROG ROM", address))
  when :char
    unless address_inside_char_rom?(address)
      fail(AccessOutsideCharRom, sprintf("Address $%.4X is outside CHAR ROM", address))
    end
    address
  else
    address
  end
end