mos6502 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.
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2020, Robert Haines.
4
+ #
5
+ # Licensed under the BSD License. See LICENCE for details.
6
+
7
+ module Mos6502
8
+ class Cpu
9
+ private
10
+
11
+ def adc(value)
12
+ carry = @status.carry? ? 1 : 0
13
+
14
+ if @status.decimal_mode?
15
+ result = (@a & 0x0f) + (value & 0x0f) + carry
16
+ result = 0x10 | ((result + 0x06) & 0x0f) if result >= 0x0a
17
+ result += (@a & 0xf0) + (value & 0xf0)
18
+
19
+ if result >= 0xa0
20
+ result += 0x60
21
+ @status.carry = true
22
+ @status.overflow = ((@a ^ value) & 0x80).zero? && (result >= 0x0180)
23
+ else
24
+ @status.carry = false
25
+ @status.overflow = !((@a ^ value) & 0x80).zero? && (result < 0x80)
26
+ end
27
+ else
28
+ result = @a + value + carry
29
+ @status.overflow =
30
+ (((@a & 0x7f) + (value & 0x7f) + carry) >> 7) ^ (result >> 8)
31
+ @status.carry = result > 0xff
32
+ end
33
+
34
+ @a = result & 0xff
35
+ set_nz_flags(@a)
36
+ end
37
+
38
+ def asl(value)
39
+ set_carry(value, 7)
40
+ value = value << 1
41
+ set_nz_flags(value)
42
+ value
43
+ end
44
+
45
+ def bit(value)
46
+ @status.zero = (@a & value).zero?
47
+ @status.overflow = value & 0x40
48
+ @status.negative = value & 0x80
49
+ end
50
+
51
+ def branch(offset)
52
+ if offset > 0x7f
53
+ @pc - (0x100 - offset)
54
+ else
55
+ @pc + offset
56
+ end
57
+ end
58
+
59
+ def compare(register, value)
60
+ @status.carry = register >= value
61
+ set_nz_flags(register - value)
62
+ end
63
+
64
+ def dec(value)
65
+ value = (value - 1) & 0xff
66
+ set_nz_flags(value)
67
+ value
68
+ end
69
+
70
+ def inc(value)
71
+ value = (value + 1) & 0xff
72
+ set_nz_flags(value)
73
+ value
74
+ end
75
+
76
+ def lsr(value)
77
+ set_carry(value, 0)
78
+ value = value >> 1
79
+ set_nz_flags(value)
80
+ value
81
+ end
82
+
83
+ def rol(value)
84
+ carry = @status.carry? ? 1 : 0
85
+ set_carry(value, 7)
86
+ value = value << 1
87
+ value |= carry
88
+ set_nz_flags(value)
89
+ value
90
+ end
91
+
92
+ def ror(value)
93
+ carry = @status.carry?
94
+ set_carry(value, 0)
95
+ value = value >> 1
96
+ value |= 0x80 if carry
97
+ set_nz_flags(value)
98
+ value
99
+ end
100
+
101
+ def sbc(value)
102
+ if @status.decimal_mode?
103
+ carry = @status.carry? ? 1 : 0
104
+ ones = 0x0f + (@a & 0x0f) - (value & 0x0f) + carry
105
+ tens = 0xf0 + (@a & 0xf0) - (value & 0xf0)
106
+
107
+ if ones < 0x10
108
+ ones -= 6
109
+ else
110
+ tens += 0x10
111
+ ones -= 0x10
112
+ end
113
+
114
+ if tens < 0x100
115
+ tens -= 0x60
116
+ @status.carry = false
117
+ @status.overflow = !((@a ^ value) & 0x80).zero? && (tens < 0x80)
118
+ else
119
+ @status.carry = true
120
+ @status.overflow = !((@a ^ value) & 0x80).zero? && (tens < 0x0180)
121
+ end
122
+
123
+ @a = (ones + tens) & 0xff
124
+ set_nz_flags(@a)
125
+ else
126
+ adc(value ^ 0xff)
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2020, Robert Haines.
4
+ #
5
+ # Licensed under the BSD License. See LICENCE for details.
6
+
7
+ module Mos6502
8
+ class Memory
9
+ def initialize(image = nil)
10
+ load!(image)
11
+ end
12
+
13
+ def set(address, value)
14
+ @memory[address] = (value & 0xff)
15
+ end
16
+
17
+ def get(address)
18
+ @memory[address] || 0x00
19
+ end
20
+
21
+ def get_word(address)
22
+ get(address) + (get(address + 1) << 8)
23
+ end
24
+
25
+ def load(image, start = 0)
26
+ return if image.nil?
27
+
28
+ image = image.bytes if image.respond_to?(:bytes)
29
+ @memory[start, image.length] = image
30
+ end
31
+
32
+ def load!(image, start = 0)
33
+ @memory = []
34
+ load(image, start)
35
+ end
36
+
37
+ def dump(start, length)
38
+ (start...(start + length)).reduce([]) { |acc, i| acc << get(i) }
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2020, Robert Haines.
4
+ #
5
+ # Licensed under the BSD License. See LICENCE for details.
6
+
7
+ module Mos6502
8
+ VERSION = '1.0.0'
9
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2020 Robert Haines.
4
+ #
5
+ # Licensed under the BSD License. See LICENCE for details.
6
+
7
+ require_relative 'lib/mos6502/version'
8
+
9
+ Gem::Specification.new do |s|
10
+ s.name = 'mos6502'
11
+ s.version = Mos6502::VERSION
12
+ s.authors = ['Robert Haines']
13
+ s.email = ['robert.haines@manchester.ac.uk']
14
+
15
+ s.summary = 'A 6502 microprocessor in ruby.'
16
+ s.homepage = 'https://github.com/hainesr/mos6502'
17
+
18
+ s.required_ruby_version = Gem::Requirement.new('>= 2.4.0')
19
+
20
+ s.files = Dir.chdir(File.expand_path(__dir__)) do
21
+ `git ls-files -z`.split("\x0").reject do |f|
22
+ f.match(%r{^(test|spec|features)/})
23
+ end
24
+ end
25
+ s.bindir = 'exe'
26
+ s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ s.require_paths = ['lib']
28
+
29
+ s.add_development_dependency 'coveralls', '~> 0.8'
30
+ s.add_development_dependency 'minitest', '~> 5.0'
31
+ s.add_development_dependency 'rake', '~> 12.0'
32
+ s.add_development_dependency 'rubocop', '0.93.0'
33
+ s.add_development_dependency 'rubocop-performance', '1.8.1'
34
+ end
metadata ADDED
@@ -0,0 +1,132 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mos6502
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Robert Haines
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-10-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: coveralls
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.8'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.8'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '12.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '12.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.93.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '='
67
+ - !ruby/object:Gem::Version
68
+ version: 0.93.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop-performance
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '='
74
+ - !ruby/object:Gem::Version
75
+ version: 1.8.1
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '='
81
+ - !ruby/object:Gem::Version
82
+ version: 1.8.1
83
+ description:
84
+ email:
85
+ - robert.haines@manchester.ac.uk
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".gitmodules"
92
+ - ".rubocop.yml"
93
+ - ".rubocop_todo.yml"
94
+ - ".travis.yml"
95
+ - CODE_OF_CONDUCT.md
96
+ - Gemfile
97
+ - LICENCE
98
+ - README.md
99
+ - Rakefile
100
+ - bin/console
101
+ - bin/setup
102
+ - lib/mos6502.rb
103
+ - lib/mos6502/cpu.rb
104
+ - lib/mos6502/cpu_flags.rb
105
+ - lib/mos6502/cpu_instructions.rb
106
+ - lib/mos6502/cpu_ops.rb
107
+ - lib/mos6502/memory.rb
108
+ - lib/mos6502/version.rb
109
+ - mos6502.gemspec
110
+ homepage: https://github.com/hainesr/mos6502
111
+ licenses: []
112
+ metadata: {}
113
+ post_install_message:
114
+ rdoc_options: []
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: 2.4.0
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ requirements: []
128
+ rubygems_version: 3.1.2
129
+ signing_key:
130
+ specification_version: 4
131
+ summary: A 6502 microprocessor in ruby.
132
+ test_files: []