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 a new bank
# File lib/n65/memory_space.rb, line 41 def self.create_bank(type) self.new(BankSizes[type], type) end
Create a new CHAR ROM
# File lib/n65/memory_space.rb, line 34 def self.create_char_rom self.create_bank(:char) end
Create a new PROG ROM
# File lib/n65/memory_space.rb, line 27 def self.create_prog_rom self.create_bank(:prog) end
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
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
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
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
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
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
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
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
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