mos6502 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []