mos6502-workbench 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +189 -0
- data/bin/assemble +122 -0
- data/bin/disassemble +58 -0
- data/bin/run_assembled_program +80 -0
- data/bin/run_klaus_functional_test +19 -0
- data/examples/README.md +147 -0
- data/examples/branching.asm +16 -0
- data/examples/countdown.asm +17 -0
- data/examples/labels_and_data.asm +28 -0
- data/examples/primes.asm +61 -0
- data/examples/simple_machine.rb +25 -0
- data/examples/traced_machine.rb +55 -0
- data/lib/mos6502/workbench/assembler.rb +725 -0
- data/lib/mos6502/workbench/bus.rb +264 -0
- data/lib/mos6502/workbench/cpu.rb +1292 -0
- data/lib/mos6502/workbench/device.rb +64 -0
- data/lib/mos6502/workbench/disassembler.rb +234 -0
- data/lib/mos6502/workbench/flags.rb +74 -0
- data/lib/mos6502/workbench/intel_hex.rb +116 -0
- data/lib/mos6502/workbench/machine.rb +140 -0
- data/lib/mos6502/workbench/memory.rb +159 -0
- data/lib/mos6502/workbench/registers.rb +19 -0
- data/lib/mos6502/workbench/tui.rb +537 -0
- data/lib/mos6502/workbench/version.rb +9 -0
- data/lib/mos6502/workbench.rb +12 -0
- metadata +126 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
; Demonstrates labels, .byte/.word data, low-byte and high-byte extraction,
|
|
2
|
+
; and cross-segment absolute addressing.
|
|
3
|
+
|
|
4
|
+
.org $9000
|
|
5
|
+
|
|
6
|
+
message:
|
|
7
|
+
.byte 'O', 'K', 0
|
|
8
|
+
|
|
9
|
+
message_ptr:
|
|
10
|
+
.word message
|
|
11
|
+
|
|
12
|
+
.org $8000
|
|
13
|
+
|
|
14
|
+
start:
|
|
15
|
+
lda #<message
|
|
16
|
+
sta $0200
|
|
17
|
+
|
|
18
|
+
lda #>message
|
|
19
|
+
sta $0201
|
|
20
|
+
|
|
21
|
+
lda message
|
|
22
|
+
sta $0202
|
|
23
|
+
|
|
24
|
+
lda message + 1
|
|
25
|
+
sta $0203
|
|
26
|
+
|
|
27
|
+
done:
|
|
28
|
+
jmp done
|
data/examples/primes.asm
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
.org $0000
|
|
2
|
+
current:
|
|
3
|
+
.byte 0
|
|
4
|
+
divisor:
|
|
5
|
+
.byte 0
|
|
6
|
+
prime_count:
|
|
7
|
+
.byte 0
|
|
8
|
+
prime_ptr:
|
|
9
|
+
.word 0
|
|
10
|
+
|
|
11
|
+
.org $8000
|
|
12
|
+
start:
|
|
13
|
+
lda #$00
|
|
14
|
+
sta prime_count
|
|
15
|
+
lda #<$0300
|
|
16
|
+
sta prime_ptr
|
|
17
|
+
lda #>$0300
|
|
18
|
+
sta prime_ptr + 1
|
|
19
|
+
lda #$02
|
|
20
|
+
sta current
|
|
21
|
+
|
|
22
|
+
candidate_loop:
|
|
23
|
+
lda #$02
|
|
24
|
+
sta divisor
|
|
25
|
+
|
|
26
|
+
divisor_loop:
|
|
27
|
+
lda divisor
|
|
28
|
+
cmp current
|
|
29
|
+
beq store_prime
|
|
30
|
+
|
|
31
|
+
lda current
|
|
32
|
+
remainder_loop:
|
|
33
|
+
sec
|
|
34
|
+
sbc divisor
|
|
35
|
+
beq next_candidate
|
|
36
|
+
bcc try_next_divisor
|
|
37
|
+
jmp remainder_loop
|
|
38
|
+
|
|
39
|
+
try_next_divisor:
|
|
40
|
+
inc divisor
|
|
41
|
+
jmp divisor_loop
|
|
42
|
+
|
|
43
|
+
store_prime:
|
|
44
|
+
ldy #$00
|
|
45
|
+
lda current
|
|
46
|
+
sta (prime_ptr), y
|
|
47
|
+
inc prime_ptr
|
|
48
|
+
bne pointer_ready
|
|
49
|
+
inc prime_ptr + 1
|
|
50
|
+
pointer_ready:
|
|
51
|
+
inc prime_count
|
|
52
|
+
|
|
53
|
+
next_candidate:
|
|
54
|
+
inc current
|
|
55
|
+
lda current
|
|
56
|
+
bne candidate_loop
|
|
57
|
+
|
|
58
|
+
done:
|
|
59
|
+
lda prime_count
|
|
60
|
+
sta $02ff
|
|
61
|
+
jmp done
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
$LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
|
|
4
|
+
require 'mos6502/workbench'
|
|
5
|
+
|
|
6
|
+
machine = MOS6502::Machine.new
|
|
7
|
+
machine.map_ram(start_address: 0x0000, end_address: 0x7fff)
|
|
8
|
+
|
|
9
|
+
rom = Array.new(0x8000, 0xea)
|
|
10
|
+
rom[0x0000] = 0xa9
|
|
11
|
+
rom[0x0001] = 0x42
|
|
12
|
+
rom[0x0002] = 0x8d
|
|
13
|
+
rom[0x0003] = 0x00
|
|
14
|
+
rom[0x0004] = 0x20
|
|
15
|
+
rom[0x0005] = 0x4c
|
|
16
|
+
rom[0x0006] = 0x05
|
|
17
|
+
rom[0x0007] = 0x80
|
|
18
|
+
rom[0x7ffc] = 0x00
|
|
19
|
+
rom[0x7ffd] = 0x80
|
|
20
|
+
|
|
21
|
+
machine.map_rom(rom, start_address: 0x8000)
|
|
22
|
+
machine.power_on
|
|
23
|
+
machine.run(max_instructions: 3)
|
|
24
|
+
|
|
25
|
+
puts format('PC=%04X cycles=%d mem[2000]=%02X', machine.cpu.program_counter, machine.cpu.cycle_count, machine.cpu.read_byte(0x2000))
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
$LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
|
|
4
|
+
require 'mos6502/workbench'
|
|
5
|
+
|
|
6
|
+
#
|
|
7
|
+
# A tiny memory-mapped register used to demonstrate custom devices.
|
|
8
|
+
class ConsoleRegister < MOS6502::Device
|
|
9
|
+
attr_reader :value
|
|
10
|
+
|
|
11
|
+
def initialize
|
|
12
|
+
super
|
|
13
|
+
@value = 0
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def read_byte(_address)
|
|
17
|
+
value
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def write_byte(_address, byte)
|
|
21
|
+
@value = byte & 0xff
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
machine = MOS6502::Machine.new(bus: MOS6502::Bus.new)
|
|
26
|
+
machine.map_ram(start_address: 0x0000, end_address: 0x7eff)
|
|
27
|
+
machine.map_device(ConsoleRegister.new, start_address: 0x7f00, end_address: 0x7f00)
|
|
28
|
+
|
|
29
|
+
rom = Array.new(0x8100, 0xea)
|
|
30
|
+
program = [
|
|
31
|
+
0xa9, 'H'.ord,
|
|
32
|
+
0x8d, 0x00, 0x7f,
|
|
33
|
+
0xa9, 'I'.ord,
|
|
34
|
+
0x8d, 0x00, 0x7f,
|
|
35
|
+
0x4c, 0x0a, 0x80
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
program.each_with_index { |byte, offset| rom[offset] = byte }
|
|
39
|
+
rom[0x7ffc] = 0x00
|
|
40
|
+
rom[0x7ffd] = 0x80
|
|
41
|
+
|
|
42
|
+
machine.map_rom(rom, start_address: 0x8000)
|
|
43
|
+
|
|
44
|
+
machine.cpu.subscribe_steps do |event|
|
|
45
|
+
puts format('STEP %04X %-3s %-10s cycles=%d A=%02X', event[:address], event[:mnemonic].to_s.upcase, event[:mode], event[:cycles], event[:snapshot][:accumulator])
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
machine.bus.subscribe_accesses do |event|
|
|
49
|
+
next unless event[:address] == 0x7f00 && event[:operation] == :write
|
|
50
|
+
|
|
51
|
+
puts format("IO write -> '%s'", event[:value].chr)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
machine.power_on
|
|
55
|
+
machine.run(max_instructions: 5)
|