Class: Badline::Computer

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
IntegerHelper, KeyboardBuffer
Defined in:
lib/badline/computer.rb

Constant Summary collapse

INIT_THRESHOLD =
2_500_000

Constants included from KeyboardBuffer

KeyboardBuffer::ADDRESS, KeyboardBuffer::CAPACITY, KeyboardBuffer::COUNT

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from KeyboardBuffer

#type_text

Methods included from IntegerHelper

#bcd, #bcd_to_i, #format16, #format8, #high_byte, #low_byte, #signed_int8, #uint16

Constructor Details

#initialize(debug: false) ⇒ Computer

Returns a new instance of Computer.



15
16
17
18
19
20
21
22
23
24
25
# File 'lib/badline/computer.rb', line 15

def initialize(debug: false)
  @address_bus = AddressBus.new
  @cpu = CPU.new(@address_bus, debug:)
  @vic = @address_bus.vic
  @cia1 = @address_bus.cia1
  @cia2 = @address_bus.cia2
  @cycles = 0
  @nmi_asserted = false
  @init_handlers = []
  @pending_keys = nil
end

Instance Attribute Details

#address_busObject (readonly)

Returns the value of attribute address_bus.



11
12
13
# File 'lib/badline/computer.rb', line 11

def address_bus
  @address_bus
end

#cpuObject (readonly)

Returns the value of attribute cpu.



11
12
13
# File 'lib/badline/computer.rb', line 11

def cpu
  @cpu
end

#cyclesObject (readonly)

Returns the value of attribute cycles.



11
12
13
# File 'lib/badline/computer.rb', line 11

def cycles
  @cycles
end

Instance Method Details

#attach_cartridge(cartridge) ⇒ Object



54
55
56
57
# File 'lib/badline/computer.rb', line 54

def attach_cartridge(cartridge)
  address_bus.attach_cartridge(cartridge)
  cpu.reset!
end

#capture_outputObject



68
69
70
71
72
# File 'lib/badline/computer.rb', line 68

def capture_output
  @capture_output ||= ChroutTrap.new(cpu:, bus: address_bus).tap do |trap|
    cpu.install_trap(ChroutTrap::ADDRESS) { trap.call }
  end
end

#cycle!Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/badline/computer.rb', line 29

def cycle!
  handle_init if @cycles == INIT_THRESHOLD
  feed_keyboard if @pending_keys

  @vic.cycle!
  @cia1.cycle!
  @cia2.cycle!

  @cpu.irq = @cia1.interrupted? || @vic.interrupted?

  nmi = @cia2.interrupted?
  @cpu.nmi = true if nmi && !@nmi_asserted
  @nmi_asserted = nmi

  @cpu.cycle! if @cpu.pending_write? || !@vic.ba_low?

  @cycles += 1
end

#inspectObject



74
75
76
# File 'lib/badline/computer.rb', line 74

def inspect
  "#<#{self.class.name} cycles=#{@cycles} cpu=(#{@cpu.inspect})>"
end

#load_prg(data) ⇒ Object



48
49
50
51
52
# File 'lib/badline/computer.rb', line 48

def load_prg(data)
  uint16(data[0], data[1]).tap do |load_addr|
    ram.write(load_addr, data[2..])
  end
end

#mount(storage) ⇒ Object



59
60
61
62
63
64
65
66
# File 'lib/badline/computer.rb', line 59

def mount(storage)
  load_trap = KernalTrap::Load.new(cpu:, bus: address_bus, storage:)
  cpu.install_trap(KernalTrap::Load::ADDRESS) { load_trap.call }
  return unless storage.respond_to?(:write_file)

  save_trap = KernalTrap::Save.new(cpu:, bus: address_bus, storage:)
  cpu.install_trap(KernalTrap::Save::ADDRESS) { save_trap.call }
end

#on_init(&block) ⇒ Object



78
79
80
81
82
83
84
# File 'lib/badline/computer.rb', line 78

def on_init(&block)
  if booting?
    @init_handlers << block
  else
    block.call
  end
end