amaterasu 0.6.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.
Files changed (158) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +1 -0
  4. data/.rubocop.yml +54 -0
  5. data/Gemfile +32 -0
  6. data/Gemfile.lock +267 -0
  7. data/LICENSE +21 -0
  8. data/README.md +115 -0
  9. data/Steepfile +7 -0
  10. data/exe/amaterasu +23 -0
  11. data/lib/amaterasu/cartridge/mbc1.rb +56 -0
  12. data/lib/amaterasu/cartridge/rom.rb +118 -0
  13. data/lib/amaterasu/cartridge.rb +68 -0
  14. data/lib/amaterasu/cli.rb +60 -0
  15. data/lib/amaterasu/emulator.rb +121 -0
  16. data/lib/amaterasu/game_boy/apu.rb +12 -0
  17. data/lib/amaterasu/game_boy/bus.rb +161 -0
  18. data/lib/amaterasu/game_boy/cpu/instructions/adc.rb +64 -0
  19. data/lib/amaterasu/game_boy/cpu/instructions/add16.rb +73 -0
  20. data/lib/amaterasu/game_boy/cpu/instructions/add8.rb +63 -0
  21. data/lib/amaterasu/game_boy/cpu/instructions/and.rb +62 -0
  22. data/lib/amaterasu/game_boy/cpu/instructions/base.rb +38 -0
  23. data/lib/amaterasu/game_boy/cpu/instructions/call.rb +48 -0
  24. data/lib/amaterasu/game_boy/cpu/instructions/cb_bit.rb +52 -0
  25. data/lib/amaterasu/game_boy/cpu/instructions/cb_res.rb +49 -0
  26. data/lib/amaterasu/game_boy/cpu/instructions/cb_rl.rb +70 -0
  27. data/lib/amaterasu/game_boy/cpu/instructions/cb_rlc.rb +68 -0
  28. data/lib/amaterasu/game_boy/cpu/instructions/cb_rr.rb +70 -0
  29. data/lib/amaterasu/game_boy/cpu/instructions/cb_rrc.rb +68 -0
  30. data/lib/amaterasu/game_boy/cpu/instructions/cb_set.rb +51 -0
  31. data/lib/amaterasu/game_boy/cpu/instructions/cb_sla.rb +69 -0
  32. data/lib/amaterasu/game_boy/cpu/instructions/cb_sra.rb +71 -0
  33. data/lib/amaterasu/game_boy/cpu/instructions/cb_srl.rb +69 -0
  34. data/lib/amaterasu/game_boy/cpu/instructions/cb_swap.rb +67 -0
  35. data/lib/amaterasu/game_boy/cpu/instructions/cp.rb +61 -0
  36. data/lib/amaterasu/game_boy/cpu/instructions/daa.rb +59 -0
  37. data/lib/amaterasu/game_boy/cpu/instructions/dec.rb +64 -0
  38. data/lib/amaterasu/game_boy/cpu/instructions/di.rb +21 -0
  39. data/lib/amaterasu/game_boy/cpu/instructions/ei.rb +19 -0
  40. data/lib/amaterasu/game_boy/cpu/instructions/halt.rb +19 -0
  41. data/lib/amaterasu/game_boy/cpu/instructions/inc.rb +64 -0
  42. data/lib/amaterasu/game_boy/cpu/instructions/jp.rb +54 -0
  43. data/lib/amaterasu/game_boy/cpu/instructions/jr.rb +45 -0
  44. data/lib/amaterasu/game_boy/cpu/instructions/ld16.rb +79 -0
  45. data/lib/amaterasu/game_boy/cpu/instructions/ld8.rb +210 -0
  46. data/lib/amaterasu/game_boy/cpu/instructions/ldh.rb +61 -0
  47. data/lib/amaterasu/game_boy/cpu/instructions/misc.rb +53 -0
  48. data/lib/amaterasu/game_boy/cpu/instructions/nop.rb +19 -0
  49. data/lib/amaterasu/game_boy/cpu/instructions/or.rb +56 -0
  50. data/lib/amaterasu/game_boy/cpu/instructions/pop.rb +39 -0
  51. data/lib/amaterasu/game_boy/cpu/instructions/push.rb +43 -0
  52. data/lib/amaterasu/game_boy/cpu/instructions/ret.rb +70 -0
  53. data/lib/amaterasu/game_boy/cpu/instructions/rotate.rb +120 -0
  54. data/lib/amaterasu/game_boy/cpu/instructions/rst.rb +33 -0
  55. data/lib/amaterasu/game_boy/cpu/instructions/sbc.rb +64 -0
  56. data/lib/amaterasu/game_boy/cpu/instructions/stop.rb +19 -0
  57. data/lib/amaterasu/game_boy/cpu/instructions/sub.rb +63 -0
  58. data/lib/amaterasu/game_boy/cpu/instructions/xor.rb +60 -0
  59. data/lib/amaterasu/game_boy/cpu/instructions.rb +600 -0
  60. data/lib/amaterasu/game_boy/cpu/registers.rb +264 -0
  61. data/lib/amaterasu/game_boy/cpu.rb +232 -0
  62. data/lib/amaterasu/game_boy/dma.rb +114 -0
  63. data/lib/amaterasu/game_boy/interrupts.rb +108 -0
  64. data/lib/amaterasu/game_boy/joypad.rb +127 -0
  65. data/lib/amaterasu/game_boy/oam/sprite.rb +106 -0
  66. data/lib/amaterasu/game_boy/oam.rb +29 -0
  67. data/lib/amaterasu/game_boy/ppu/modes/disabled.rb +29 -0
  68. data/lib/amaterasu/game_boy/ppu/modes/h_blank.rb +45 -0
  69. data/lib/amaterasu/game_boy/ppu/modes/oam_scan.rb +93 -0
  70. data/lib/amaterasu/game_boy/ppu/modes/rendering/bg_win_fetcher.rb +204 -0
  71. data/lib/amaterasu/game_boy/ppu/modes/rendering/pixel_emitter.rb +83 -0
  72. data/lib/amaterasu/game_boy/ppu/modes/rendering/pixel_fifo.rb +70 -0
  73. data/lib/amaterasu/game_boy/ppu/modes/rendering/sprite_fetcher.rb +140 -0
  74. data/lib/amaterasu/game_boy/ppu/modes/rendering.rb +108 -0
  75. data/lib/amaterasu/game_boy/ppu/modes/v_blank.rb +43 -0
  76. data/lib/amaterasu/game_boy/ppu/modes.rb +22 -0
  77. data/lib/amaterasu/game_boy/ppu/registers/lcd_control.rb +57 -0
  78. data/lib/amaterasu/game_boy/ppu/registers/lcd_status.rb +88 -0
  79. data/lib/amaterasu/game_boy/ppu/registers.rb +131 -0
  80. data/lib/amaterasu/game_boy/ppu.rb +207 -0
  81. data/lib/amaterasu/game_boy/ram.rb +70 -0
  82. data/lib/amaterasu/game_boy/serial.rb +91 -0
  83. data/lib/amaterasu/game_boy/timer.rb +230 -0
  84. data/lib/amaterasu/game_boy/vram/tile.rb +68 -0
  85. data/lib/amaterasu/game_boy/vram/tile_data.rb +52 -0
  86. data/lib/amaterasu/game_boy/vram/tile_map.rb +71 -0
  87. data/lib/amaterasu/game_boy/vram.rb +51 -0
  88. data/lib/amaterasu/hal/console.rb +23 -0
  89. data/lib/amaterasu/hal/sdl2/bindings.rb +59 -0
  90. data/lib/amaterasu/hal/sdl2.rb +127 -0
  91. data/lib/amaterasu/utils/bit_ops.rb +22 -0
  92. data/lib/amaterasu.rb +13 -0
  93. data/sig/akane/cartridge/rom.rbs +29 -0
  94. data/sig/akane/cartridge.rbs +12 -0
  95. data/sig/akane/cli.rbs +16 -0
  96. data/sig/akane/emulator.rbs +19 -0
  97. data/sig/akane/game_boy/apu.rbs +7 -0
  98. data/sig/akane/game_boy/bus.rbs +25 -0
  99. data/sig/akane/game_boy/cpu/instructions/adc.rbs +18 -0
  100. data/sig/akane/game_boy/cpu/instructions/add16.rbs +19 -0
  101. data/sig/akane/game_boy/cpu/instructions/add8.rbs +18 -0
  102. data/sig/akane/game_boy/cpu/instructions/and.rbs +18 -0
  103. data/sig/akane/game_boy/cpu/instructions/base.rbs +20 -0
  104. data/sig/akane/game_boy/cpu/instructions/call.rbs +18 -0
  105. data/sig/akane/game_boy/cpu/instructions/cb_bit.rbs +20 -0
  106. data/sig/akane/game_boy/cpu/instructions/cb_res.rbs +19 -0
  107. data/sig/akane/game_boy/cpu/instructions/cb_rl.rbs +21 -0
  108. data/sig/akane/game_boy/cpu/instructions/cb_rlc.rbs +21 -0
  109. data/sig/akane/game_boy/cpu/instructions/cb_rr.rbs +21 -0
  110. data/sig/akane/game_boy/cpu/instructions/cb_rrc.rbs +21 -0
  111. data/sig/akane/game_boy/cpu/instructions/cb_set.rbs +20 -0
  112. data/sig/akane/game_boy/cpu/instructions/cb_sla.rbs +21 -0
  113. data/sig/akane/game_boy/cpu/instructions/cb_sra.rbs +21 -0
  114. data/sig/akane/game_boy/cpu/instructions/cb_srl.rbs +21 -0
  115. data/sig/akane/game_boy/cpu/instructions/cb_swap.rbs +21 -0
  116. data/sig/akane/game_boy/cpu/instructions/cp.rbs +18 -0
  117. data/sig/akane/game_boy/cpu/instructions/daa.rbs +17 -0
  118. data/sig/akane/game_boy/cpu/instructions/dec.rbs +19 -0
  119. data/sig/akane/game_boy/cpu/instructions/di.rbs +13 -0
  120. data/sig/akane/game_boy/cpu/instructions/ei.rbs +13 -0
  121. data/sig/akane/game_boy/cpu/instructions/halt.rbs +13 -0
  122. data/sig/akane/game_boy/cpu/instructions/inc.rbs +19 -0
  123. data/sig/akane/game_boy/cpu/instructions/jp.rbs +18 -0
  124. data/sig/akane/game_boy/cpu/instructions/jr.rbs +18 -0
  125. data/sig/akane/game_boy/cpu/instructions/ld16.rbs +18 -0
  126. data/sig/akane/game_boy/cpu/instructions/ld8.rbs +31 -0
  127. data/sig/akane/game_boy/cpu/instructions/ldh.rbs +23 -0
  128. data/sig/akane/game_boy/cpu/instructions/misc.rbs +20 -0
  129. data/sig/akane/game_boy/cpu/instructions/nop.rbs +13 -0
  130. data/sig/akane/game_boy/cpu/instructions/or.rbs +18 -0
  131. data/sig/akane/game_boy/cpu/instructions/pop.rbs +17 -0
  132. data/sig/akane/game_boy/cpu/instructions/push.rbs +18 -0
  133. data/sig/akane/game_boy/cpu/instructions/ret.rbs +20 -0
  134. data/sig/akane/game_boy/cpu/instructions/rotate.rbs +23 -0
  135. data/sig/akane/game_boy/cpu/instructions/rst.rbs +17 -0
  136. data/sig/akane/game_boy/cpu/instructions/sbc.rbs +19 -0
  137. data/sig/akane/game_boy/cpu/instructions/stop.rbs +13 -0
  138. data/sig/akane/game_boy/cpu/instructions/sub.rbs +18 -0
  139. data/sig/akane/game_boy/cpu/instructions/xor.rbs +19 -0
  140. data/sig/akane/game_boy/cpu/instructions.rbs +12 -0
  141. data/sig/akane/game_boy/cpu/registers.rbs +56 -0
  142. data/sig/akane/game_boy/cpu.rbs +39 -0
  143. data/sig/akane/game_boy/interrupts.rbs +28 -0
  144. data/sig/akane/game_boy/joypad.rbs +25 -0
  145. data/sig/akane/game_boy/oam/sprite.rbs +30 -0
  146. data/sig/akane/game_boy/ppu/modes/disabled.rbs +17 -0
  147. data/sig/akane/game_boy/ppu/modes/h_blank.rbs +20 -0
  148. data/sig/akane/game_boy/ppu/modes/oam_scan.rbs +28 -0
  149. data/sig/akane/game_boy/ppu/modes/rendering.rbs +26 -0
  150. data/sig/akane/game_boy/ppu/modes/v_blank.rbs +20 -0
  151. data/sig/akane/game_boy/ppu/modes.rbs +13 -0
  152. data/sig/akane/game_boy/ppu.rbs +59 -0
  153. data/sig/akane/game_boy/ram.rbs +16 -0
  154. data/sig/akane/game_boy/serial.rbs +21 -0
  155. data/sig/akane/game_boy/timer.rbs +30 -0
  156. data/sig/akane/utils/bit_ops.rbs +11 -0
  157. data/sig/akane.rbs +3 -0
  158. metadata +226 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d8be27ada9ca577ac19fee656335c0666f26de70e8cd46aa330485ef818bf74b
4
+ data.tar.gz: af21c688666e9b186498502adbd02c95dc72182be970e15f4044becb5cbf42bf
5
+ SHA512:
6
+ metadata.gz: e783cb26b1a517ab3d3a96562606d9d2d50f36fb561c132b952f0240984e43c6e2bdb3778ffa570b444c9d2ef2b870c44865683aa00165d908858eb251ac79d9
7
+ data.tar.gz: 472bbd93c146ea25b94006e8259c5c8ffa7507c1312ef6d2d57079eaca892bbb7ccd33c7d1f9be76d9ddc736e5b8ed5debf33ae8a8ebfff121f0a0b1b06e576f
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ .idea
2
+ .tool-versions
3
+ .vscode/
4
+ .ruby-lsp/
5
+ .yardoc/
6
+ coverage/
7
+ doc/
8
+ docs/
9
+ notes/
10
+ rdoc/
11
+ roms/
12
+ tmp/
13
+ *.json
14
+ *.dump
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,54 @@
1
+ plugins:
2
+ - rubocop-performance
3
+ - rubocop-rspec
4
+
5
+ AllCops:
6
+ NewCops: enable
7
+
8
+ Metrics/AbcSize:
9
+ Enabled: false
10
+
11
+ Metrics/ClassLength:
12
+ Max: 120
13
+
14
+ Metrics/CyclomaticComplexity:
15
+ Max: 20
16
+
17
+ Metrics/MethodLength:
18
+ Max: 20
19
+ Exclude:
20
+ - 'lib/amaterasu/gameboy/bus.rb'
21
+
22
+ Metrics/ParameterLists:
23
+ Enabled: false
24
+
25
+ Metrics/PerceivedComplexity:
26
+ Max: 20
27
+
28
+ Naming/AccessorMethodName:
29
+ Enabled: false
30
+
31
+ RSpec/ExampleLength:
32
+ Max: 15
33
+
34
+ RSpec/NestedGroups:
35
+ Max: 4
36
+
37
+ RSpec/MultipleMemoizedHelpers:
38
+ Max: 10
39
+
40
+ Style/FrozenStringLiteralComment:
41
+ Enabled: true
42
+ EnforcedStyle: always
43
+
44
+ Style/ComparableBetween:
45
+ Enabled: false
46
+
47
+ Style/EmptyLiteral:
48
+ Enabled: false
49
+
50
+ Style/NumericPredicate:
51
+ Enabled: false
52
+
53
+ Style/BitwisePredicate:
54
+ Enabled: false
data/Gemfile ADDED
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ ruby '4.0.3'
6
+
7
+ # gem 'curses'
8
+ # gem 'gosu'
9
+ # gem 'raylib-bindings'
10
+
11
+ gemspec
12
+
13
+ group :development do
14
+ gem 'benchmark-ips'
15
+ gem 'debug'
16
+ gem 'memory_profiler'
17
+ gem 'pastel'
18
+ gem 'rake'
19
+ gem 'rubocop'
20
+ gem 'rubocop-performance'
21
+ gem 'rubocop-rspec'
22
+ gem 'stackprof'
23
+ gem 'steep', require: false
24
+ gem 'vernier', require: false
25
+ gem 'yard', require: false
26
+ end
27
+
28
+ group :test do
29
+ gem 'rspec'
30
+ gem 'rspec-benchmark'
31
+ gem 'simplecov'
32
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,267 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ ast (2.4.3)
5
+ benchmark-ips (2.14.0)
6
+ benchmark-malloc (0.2.0)
7
+ benchmark-perf (0.6.0)
8
+ benchmark-trend (0.4.0)
9
+ concurrent-ruby (1.3.6)
10
+ csv (3.3.5)
11
+ date (3.5.1)
12
+ debug (1.11.1)
13
+ irb (~> 1.10)
14
+ reline (>= 0.3.8)
15
+ diff-lcs (1.6.2)
16
+ docile (1.4.1)
17
+ erb (6.0.4)
18
+ ffi (1.17.4)
19
+ ffi (1.17.4-aarch64-linux-gnu)
20
+ ffi (1.17.4-aarch64-linux-musl)
21
+ ffi (1.17.4-arm-linux-gnu)
22
+ ffi (1.17.4-arm-linux-musl)
23
+ ffi (1.17.4-arm64-darwin)
24
+ ffi (1.17.4-x86-linux-gnu)
25
+ ffi (1.17.4-x86-linux-musl)
26
+ ffi (1.17.4-x86_64-darwin)
27
+ ffi (1.17.4-x86_64-linux-gnu)
28
+ ffi (1.17.4-x86_64-linux-musl)
29
+ fileutils (1.8.0)
30
+ io-console (0.8.2)
31
+ irb (1.18.0)
32
+ pp (>= 0.6.0)
33
+ prism (>= 1.3.0)
34
+ rdoc (>= 4.0.0)
35
+ reline (>= 0.4.2)
36
+ json (2.19.4)
37
+ language_server-protocol (3.17.0.5)
38
+ lint_roller (1.1.0)
39
+ listen (3.10.0)
40
+ logger
41
+ rb-fsevent (~> 0.10, >= 0.10.3)
42
+ rb-inotify (~> 0.9, >= 0.9.10)
43
+ logger (1.7.0)
44
+ memory_profiler (1.1.0)
45
+ parallel (2.1.0)
46
+ parser (3.3.11.1)
47
+ ast (~> 2.4.1)
48
+ racc
49
+ pastel (0.8.0)
50
+ tty-color (~> 0.5)
51
+ pp (0.6.3)
52
+ prettyprint
53
+ prettyprint (0.2.0)
54
+ prism (1.9.0)
55
+ psych (5.3.1)
56
+ date
57
+ stringio
58
+ racc (1.8.1)
59
+ rainbow (3.1.1)
60
+ rake (13.4.2)
61
+ rb-fsevent (0.11.2)
62
+ rb-inotify (0.11.1)
63
+ ffi (~> 1.0)
64
+ rbs (4.0.2)
65
+ logger
66
+ prism (>= 1.6.0)
67
+ tsort
68
+ rdoc (7.2.0)
69
+ erb
70
+ psych (>= 4.0.0)
71
+ tsort
72
+ regexp_parser (2.12.0)
73
+ reline (0.6.3)
74
+ io-console (~> 0.5)
75
+ rspec (3.13.2)
76
+ rspec-core (~> 3.13.0)
77
+ rspec-expectations (~> 3.13.0)
78
+ rspec-mocks (~> 3.13.0)
79
+ rspec-benchmark (0.6.0)
80
+ benchmark-malloc (~> 0.2)
81
+ benchmark-perf (~> 0.6)
82
+ benchmark-trend (~> 0.4)
83
+ rspec (>= 3.0)
84
+ rspec-core (3.13.6)
85
+ rspec-support (~> 3.13.0)
86
+ rspec-expectations (3.13.5)
87
+ diff-lcs (>= 1.2.0, < 2.0)
88
+ rspec-support (~> 3.13.0)
89
+ rspec-mocks (3.13.8)
90
+ diff-lcs (>= 1.2.0, < 2.0)
91
+ rspec-support (~> 3.13.0)
92
+ rspec-support (3.13.7)
93
+ rubocop (1.86.1)
94
+ json (~> 2.3)
95
+ language_server-protocol (~> 3.17.0.2)
96
+ lint_roller (~> 1.1.0)
97
+ parallel (>= 1.10)
98
+ parser (>= 3.3.0.2)
99
+ rainbow (>= 2.2.2, < 4.0)
100
+ regexp_parser (>= 2.9.3, < 3.0)
101
+ rubocop-ast (>= 1.49.0, < 2.0)
102
+ ruby-progressbar (~> 1.7)
103
+ unicode-display_width (>= 2.4.0, < 4.0)
104
+ rubocop-ast (1.49.1)
105
+ parser (>= 3.3.7.2)
106
+ prism (~> 1.7)
107
+ rubocop-performance (1.26.1)
108
+ lint_roller (~> 1.1)
109
+ rubocop (>= 1.75.0, < 2.0)
110
+ rubocop-ast (>= 1.47.1, < 2.0)
111
+ rubocop-rspec (3.9.0)
112
+ lint_roller (~> 1.1)
113
+ rubocop (~> 1.81)
114
+ ruby-progressbar (1.13.0)
115
+ securerandom (0.4.1)
116
+ simplecov (0.22.0)
117
+ docile (~> 1.1)
118
+ simplecov-html (~> 0.11)
119
+ simplecov_json_formatter (~> 0.1)
120
+ simplecov-html (0.13.2)
121
+ simplecov_json_formatter (0.1.4)
122
+ stackprof (0.2.28)
123
+ steep (2.0.0)
124
+ concurrent-ruby (>= 1.1.10)
125
+ csv (>= 3.0.9)
126
+ fileutils (>= 1.1.0)
127
+ json (>= 2.1.0)
128
+ language_server-protocol (>= 3.17.0.4, < 4.0)
129
+ listen (~> 3.0)
130
+ logger (>= 1.3.0)
131
+ parser (>= 3.2)
132
+ prism (>= 0.25.0)
133
+ rainbow (>= 2.2.2, < 4.0)
134
+ rbs (~> 4.0)
135
+ securerandom (>= 0.1)
136
+ strscan (>= 1.0.0)
137
+ terminal-table (>= 2, < 5)
138
+ uri (>= 0.12.0)
139
+ stringio (3.2.0)
140
+ strscan (3.1.8)
141
+ terminal-table (4.0.0)
142
+ unicode-display_width (>= 1.1.1, < 4)
143
+ tsort (0.2.0)
144
+ tty-color (0.6.0)
145
+ unicode-display_width (3.2.0)
146
+ unicode-emoji (~> 4.1)
147
+ unicode-emoji (4.2.0)
148
+ uri (1.1.1)
149
+ vernier (1.10.0)
150
+ yard (0.9.43)
151
+ zeitwerk (2.8.2)
152
+
153
+ PLATFORMS
154
+ aarch64-linux-gnu
155
+ aarch64-linux-musl
156
+ arm-linux-gnu
157
+ arm-linux-musl
158
+ arm64-darwin
159
+ ruby
160
+ x86-linux-gnu
161
+ x86-linux-musl
162
+ x86_64-darwin
163
+ x86_64-linux-gnu
164
+ x86_64-linux-musl
165
+
166
+ DEPENDENCIES
167
+ benchmark-ips
168
+ debug
169
+ ffi
170
+ memory_profiler
171
+ pastel
172
+ rake
173
+ rspec
174
+ rspec-benchmark
175
+ rubocop
176
+ rubocop-performance
177
+ rubocop-rspec
178
+ simplecov
179
+ stackprof
180
+ steep
181
+ vernier
182
+ yard
183
+ zeitwerk
184
+
185
+ CHECKSUMS
186
+ ast (2.4.3) sha256=954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383
187
+ benchmark-ips (2.14.0) sha256=b72bc8a65d525d5906f8cd94270dccf73452ee3257a32b89fbd6684d3e8a9b1d
188
+ benchmark-malloc (0.2.0) sha256=37c68f0435261634026f584d79956a35325a3027e3e6b4cc8d7575aa10537e6b
189
+ benchmark-perf (0.6.0) sha256=fe2b01959f3de0f9dd34820d54ef881eb4f3589fccb7d17b63068ac92d7f9621
190
+ benchmark-trend (0.4.0) sha256=de5a02a9f443babefbbd97784759820decee8554a0c273d859c02a0990845d81
191
+ concurrent-ruby (1.3.6) sha256=6b56837e1e7e5292f9864f34b69c5a2cbc75c0cf5338f1ce9903d10fa762d5ab
192
+ csv (3.3.5) sha256=6e5134ac3383ef728b7f02725d9872934f523cb40b961479f69cf3afa6c8e73f
193
+ date (3.5.1) sha256=750d06384d7b9c15d562c76291407d89e368dda4d4fff957eb94962d325a0dc0
194
+ debug (1.11.1) sha256=2e0b0ac6119f2207a6f8ac7d4a73ca8eb4e440f64da0a3136c30343146e952b6
195
+ diff-lcs (1.6.2) sha256=9ae0d2cba7d4df3075fe8cd8602a8604993efc0dfa934cff568969efb1909962
196
+ docile (1.4.1) sha256=96159be799bfa73cdb721b840e9802126e4e03dfc26863db73647204c727f21e
197
+ erb (6.0.4) sha256=38e3803694be357fe2bfe312487c74beaf9fb4e5beb3e22498952fe1645b95d9
198
+ ffi (1.17.4) sha256=bcd1642e06f0d16fc9e09ac6d49c3a7298b9789bcb58127302f934e437d60acf
199
+ ffi (1.17.4-aarch64-linux-gnu) sha256=b208f06f91ffd8f5e1193da3cae3d2ccfc27fc36fba577baf698d26d91c080df
200
+ ffi (1.17.4-aarch64-linux-musl) sha256=9286b7a615f2676245283aef0a0a3b475ae3aae2bb5448baace630bb77b91f39
201
+ ffi (1.17.4-arm-linux-gnu) sha256=d6dbddf7cb77bf955411af5f187a65b8cd378cb003c15c05697f5feee1cb1564
202
+ ffi (1.17.4-arm-linux-musl) sha256=9d4838ded0465bef6e2426935f6bcc93134b6616785a84ffd2a3d82bc3cf6f95
203
+ ffi (1.17.4-arm64-darwin) sha256=19071aaf1419251b0a46852abf960e77330a3b334d13a4ab51d58b31a937001b
204
+ ffi (1.17.4-x86-linux-gnu) sha256=38e150df5f4ca555e25beca4090823ae09657bceded154e3c52f8631c1ed72cf
205
+ ffi (1.17.4-x86-linux-musl) sha256=fbeec0fc7c795bcf86f623bb18d31ea1820f7bd580e1703a3d3740d527437809
206
+ ffi (1.17.4-x86_64-darwin) sha256=aa70390523cf3235096cf64962b709b4cfbd5c082a2cb2ae714eb0fe2ccda496
207
+ ffi (1.17.4-x86_64-linux-gnu) sha256=9d3db14c2eae074b382fa9c083fe95aec6e0a1451da249eab096c34002bc752d
208
+ ffi (1.17.4-x86_64-linux-musl) sha256=3fdf9888483de005f8ef8d1cf2d3b20d86626af206cbf780f6a6a12439a9c49e
209
+ fileutils (1.8.0) sha256=8c6b1df54e2540bdb2f39258f08af78853aa70bad52b4d394bbc6424593c6e02
210
+ io-console (0.8.2) sha256=d6e3ae7a7cc7574f4b8893b4fca2162e57a825b223a177b7afa236c5ef9814cc
211
+ irb (1.18.0) sha256=de9454a0703a54704b9811a5ef31a60c86949fbf4013fcf244fabc7c775248e3
212
+ json (2.19.4) sha256=670a7d333fb3b18ca5b29cb255eb7bef099e40d88c02c80bd42a3f30fe5239ac
213
+ language_server-protocol (3.17.0.5) sha256=fd1e39a51a28bf3eec959379985a72e296e9f9acfce46f6a79d31ca8760803cc
214
+ lint_roller (1.1.0) sha256=2c0c845b632a7d172cb849cc90c1bce937a28c5c8ccccb50dfd46a485003cc87
215
+ listen (3.10.0) sha256=c6e182db62143aeccc2e1960033bebe7445309c7272061979bb098d03760c9d2
216
+ logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
217
+ memory_profiler (1.1.0) sha256=79a17df7980a140c83c469785905409d3027ca614c42c086089d128b805aa8f8
218
+ parallel (2.1.0) sha256=b35258865c2e31134c5ecb708beaaf6772adf9d5efae28e93e99260877b09356
219
+ parser (3.3.11.1) sha256=d17ace7aabe3e72c3cc94043714be27cc6f852f104d81aa284c2281aecc65d54
220
+ pastel (0.8.0) sha256=481da9fb7d2f6e6b1a08faf11fa10363172dc40fd47848f096ae21209f805a75
221
+ pp (0.6.3) sha256=2951d514450b93ccfeb1df7d021cae0da16e0a7f95ee1e2273719669d0ab9df6
222
+ prettyprint (0.2.0) sha256=2bc9e15581a94742064a3cc8b0fb9d45aae3d03a1baa6ef80922627a0766f193
223
+ prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85
224
+ psych (5.3.1) sha256=eb7a57cef10c9d70173ff74e739d843ac3b2c019a003de48447b2963d81b1974
225
+ racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f
226
+ rainbow (3.1.1) sha256=039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a
227
+ rake (13.4.2) sha256=cb825b2bd5f1f8e91ca37bddb4b9aaf345551b4731da62949be002fa89283701
228
+ rb-fsevent (0.11.2) sha256=43900b972e7301d6570f64b850a5aa67833ee7d87b458ee92805d56b7318aefe
229
+ rb-inotify (0.11.1) sha256=a0a700441239b0ff18eb65e3866236cd78613d6b9f78fea1f9ac47a85e47be6e
230
+ rbs (4.0.2) sha256=af75671e66cd03434cc546622741ebf83f6197ec4328375805306330bf78ef25
231
+ rdoc (7.2.0) sha256=8650f76cd4009c3b54955eb5d7e3a075c60a57276766ebf36f9085e8c9f23192
232
+ regexp_parser (2.12.0) sha256=35a916a1d63190ab5c9009457136ae5f3c0c7512d60291d0d1378ba18ce08ebb
233
+ reline (0.6.3) sha256=1198b04973565b36ec0f11542ab3f5cfeeec34823f4e54cebde90968092b1835
234
+ rspec (3.13.2) sha256=206284a08ad798e61f86d7ca3e376718d52c0bc944626b2349266f239f820587
235
+ rspec-benchmark (0.6.0) sha256=1014adb57ec2599a2455c63884229f367a2fff6a63a77fd68ce5d804c83dd6cf
236
+ rspec-core (3.13.6) sha256=a8823c6411667b60a8bca135364351dda34cd55e44ff94c4be4633b37d828b2d
237
+ rspec-expectations (3.13.5) sha256=33a4d3a1d95060aea4c94e9f237030a8f9eae5615e9bd85718fe3a09e4b58836
238
+ rspec-mocks (3.13.8) sha256=086ad3d3d17533f4237643de0b5c42f04b66348c28bf6b9c2d3f4a3b01af1d47
239
+ rspec-support (3.13.7) sha256=0640e5570872aafefd79867901deeeeb40b0c9875a36b983d85f54fb7381c47c
240
+ rubocop (1.86.1) sha256=44415f3f01d01a21e01132248d2fd0867572475b566ca188a0a42133a08d4531
241
+ rubocop-ast (1.49.1) sha256=4412f3ee70f6fe4546cc489548e0f6fcf76cafcfa80fa03af67098ffed755035
242
+ rubocop-performance (1.26.1) sha256=cd19b936ff196df85829d264b522fd4f98b6c89ad271fa52744a8c11b8f71834
243
+ rubocop-rspec (3.9.0) sha256=8fa70a3619408237d789aeecfb9beef40576acc855173e60939d63332fdb55e2
244
+ ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33
245
+ securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1
246
+ simplecov (0.22.0) sha256=fe2622c7834ff23b98066bb0a854284b2729a569ac659f82621fc22ef36213a5
247
+ simplecov-html (0.13.2) sha256=bd0b8e54e7c2d7685927e8d6286466359b6f16b18cb0df47b508e8d73c777246
248
+ simplecov_json_formatter (0.1.4) sha256=529418fbe8de1713ac2b2d612aa3daa56d316975d307244399fa4838c601b428
249
+ stackprof (0.2.28) sha256=4ec2ace02f386012b40ca20ef80c030ad711831f59511da12e83b34efb0f9a04
250
+ steep (2.0.0) sha256=6eb0ecc09637bbb54f0a5f2cf63daea6d3208ccace64b4f1107d976333605c30
251
+ stringio (3.2.0) sha256=c37cb2e58b4ffbd33fe5cd948c05934af997b36e0b6ca6fdf43afa234cf222e1
252
+ strscan (3.1.8) sha256=aae2db611a225559f21ffbb71765c9a4e60fd262534a9ea84f4f11c7f32f679e
253
+ terminal-table (4.0.0) sha256=f504793203f8251b2ea7c7068333053f0beeea26093ec9962e62ea79f94301d2
254
+ tsort (0.2.0) sha256=9650a793f6859a43b6641671278f79cfead60ac714148aabe4e3f0060480089f
255
+ tty-color (0.6.0) sha256=6f9c37ca3a4e2367fb2e6d09722762647d6f455c111f05b59f35730eeb24332a
256
+ unicode-display_width (3.2.0) sha256=0cdd96b5681a5949cdbc2c55e7b420facae74c4aaf9a9815eee1087cb1853c42
257
+ unicode-emoji (4.2.0) sha256=519e69150f75652e40bf736106cfbc8f0f73aa3fb6a65afe62fefa7f80b0f80f
258
+ uri (1.1.1) sha256=379fa58d27ffb1387eaada68c749d1426738bd0f654d812fcc07e7568f5c57c6
259
+ vernier (1.10.0) sha256=5b1dc57012e08ed23e14f4d2943540140d454aa8434c7c35e7eb97befd4969bf
260
+ yard (0.9.43) sha256=cf8733a8f0485df2a162927e9b5f182215a61f6d22de096b8f402c726a1c5821
261
+ zeitwerk (2.8.2) sha256=7212a61311083c604184b1ea2574b9aa05cd14f855a0841c06985cabe9181d12
262
+
263
+ RUBY VERSION
264
+ ruby 4.0.3
265
+
266
+ BUNDLED WITH
267
+ 4.0.6
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Fernando Eufrásio
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,115 @@
1
+ <div align="center">
2
+ <h1 style="font-size: 3em; font-weight: bold;">Amaterasu</h1>
3
+ <p>A <s>cycle-accurate?</s> Game Boy emulator written in Ruby.</p>
4
+ </div>
5
+
6
+ ---
7
+
8
+ ## About
9
+
10
+ This is, at its core, a research project. I always loved the concept of emulation and retro gaming, but as a web developer, low level development was never my strong suit. This is my first deep dive into the subject and it has been a great experience so far.
11
+
12
+ I will try to document my progress as I try to create the emulator from the ground up (as cycle accurate as I can make it), this also helps me internalize some of the concepts about hardware emulation. I am finding it extremely challenging, but also very rewarding when your code actually behaves as the hardware would. I highly recommend for whoever is interested in learning those subjects.
13
+
14
+ ### Goals
15
+
16
+ - Build a fully cycle-accurate emulator and try to replicate all the hardware quirks
17
+ - Pass all the accuracy tests I can find and also document the progress of Passed/Failed tests
18
+ - Try to reduce optimize code performance and memory usage as much as possible without losing code readability
19
+ - Use a clean and idiomatic OOP approach for writing the code, extracting every self containing logic to a Class
20
+
21
+ ## Resources
22
+
23
+ I'm heavily relying on the great work done by the community to document every possible (and obscure) behaviors that can be found in the Game Boy. I'll place here all the resources I'm using and some other relevant ones I find.
24
+
25
+ ### Docs
26
+
27
+ - **[Pan Docs](https://gbdev.io/pandocs/)**: The single most comprehensive technical reference for the Game Boy. An absolute must-read.
28
+ - **[Opcode Table](https://gbdev.io/gb-opcodes/optables/)**: Complete Opcode table for the Game Boy CPU instruction set.
29
+ - **[RGBDS Docs](https://rgbds.gbdev.io/docs/v1.0.1/gbz80.7)**: Game Boy CPU instruction reference.
30
+ - **[GB: Complete Technical Reference](https://gekkio.fi/files/gb-docs/gbctr.pdf)**: Great documentation about how the Game Boy hardware behaves, including some of the most obscure behaviors.
31
+ - **[The Ultimate Game Boy Talk](https://www.youtube.com/watch?v=HyzD8pNlpwI)**: An amazing talk that provides a high-level overview of the hardware architecture.
32
+ - **[GBDev Community](https://gbdev.io/)**: A fantastic hub for documentation, forums, and tools related to Game Boy development.
33
+
34
+ ### Tests
35
+
36
+ - **[Mooneye Test Suite](https://github.com/Gekkio/mooneye-test-suite)**: Very complete suite of ROMs to test pretty much all aspects of the Game Boy.
37
+ - **[Blargg's Test ROMs](https://gbdev.gg8.se/files/roms/blargg-gb-tests/)**: A suite of essential test ROMs for verifying the accuracy of CPU instructions, timing, and memory access.
38
+ - **[Game Boy Test Roms](https://github.com/c-sp/game-boy-test-roms)**: A collection of different test suites for your Game Boy emulator, also has a [Wiki](https://deepwiki.com/c-sp/game-boy-test-roms/1-overview).
39
+
40
+ ### Other Emulators
41
+
42
+ - **[SameBoy](https://github.com/LIJI32/SameBoy)**: Open source Game Boy (DMG) and Game Boy Color (CGB) emulator, written in portable C.
43
+ - **[Mooneye GB](https://github.com/Gekkio/mooneye-gb)**: A Game Boy research project and emulator written in Rust.
44
+ - **[LLD_gbemu](https://github.com/rockytriton/LLD_gbemu)**: A Game Boy emulator written in C as part of the Low Level Dev tutorial.
45
+ - **[Rubyboy](https://github.com/sacckey/rubyboy)**: A Game Boy emulator written in Ruby.
46
+
47
+ ## Current Progress
48
+
49
+ Here is a snapshot of the current implementation status of the Game Boy's hardware components.
50
+
51
+ ### Address Bus
52
+
53
+ - [x] Receives all components by dependency injection.
54
+ - [x] Creates a public API with read_byte and write_byte methods.
55
+ - [x] Delegates the memory read and write to the correct components.
56
+ - [x] Correctly mapped the address range for the Cartridge, External RAM, VRAM, Echo RAM, OAM, HRAM and most of the IO registers.
57
+ - [ ] Still pending to wire and implement all the APU registers.
58
+
59
+ ### CPU
60
+
61
+ - [x] All base opcodes implemented with the correct timing.
62
+ - [x] All CB prefixed opcodes implemented with the correct timing.
63
+ - [x] Interrupts handling (IME, IE, IF registers and service routines).
64
+
65
+ ### Timer
66
+
67
+ - [x] Resets the value of the internal counter on any write to DIV.
68
+
69
+ ### DMA Controller
70
+
71
+ - [x] Correctly latches the value used to start the transfer, if $FF46 is read return this value.
72
+ - [x] Correctly implemented the 1 cycle delay before starting the actual transfer.
73
+ - [x] Correctly implemented the 160 cycles (1 byte per cycle) transfer.
74
+ - [x] Correctly implemented the Bus locking mechanism, whila DMA is active, the CPU should only be able to read/write in the IO + HRAM address range (0xFF00 - 0xFFFF).
75
+ - [x] Correctly implemented the DMA restart logic, should reset the cycles to 0, source address to the new source * $100 and target address to 0xFE00.
76
+
77
+ ### Serial Port
78
+
79
+ - [x] Correctly implemented the behavior for registers SC and SB.
80
+ - [x] Captures the message received to a message buffer to allow printing.
81
+ - [x] Requests serial interrupt when transfer is completed.
82
+
83
+ ## Accuracy Checks
84
+
85
+ | Suite | Passed | Failed | Total |
86
+ |:---------|-------:|---------:|-------:|
87
+ | Blargg | 18 | 3 | 21 |
88
+ | Mooneye | - | - | - |
89
+
90
+
91
+ ### Blargg Tests
92
+
93
+ | Test | Status |
94
+ |---------------------------------------|:--------:|
95
+ | `cpu_instrs/01-special.gb` | ✅ |
96
+ | `cpu_instrs/02-interrupts.gb` | ✅ |
97
+ | `cpu_instrs/03-op sp,hl.gb` | ✅ |
98
+ | `cpu_instrs/04-op r,imm.gb` | ✅ |
99
+ | `cpu_instrs/05-op rp.gb` | ✅ |
100
+ | `cpu_instrs/06-ld r,r.gb` | ✅ |
101
+ | `cpu_instrs/07-jr,jp,call,ret,rst.gb` | ✅ |
102
+ | `cpu_instrs/08-misc instrs.gb` | ✅ |
103
+ | `cpu_instrs/09-op r,r.gb` | ✅ |
104
+ | `cpu_instrs/10-bit ops.gb` | ✅ |
105
+ | `cpu_instrs/11-op a,(hl).gb` | ✅ |
106
+ | `instr_timing.gb` | ✅ |
107
+ | `mem_timing/01-read_timing.gb` | ✅ |
108
+ | `mem_timing/02-write_timing.gb` | ✅ |
109
+ | `mem_timing/03-modify_timing.gb` | ✅ |
110
+ | `mem_timing_2/01-read_timing.gb` | ✅ |
111
+ | `mem_timing_2/02-write_timing.gb` | ✅ |
112
+ | `mem_timing_2/03-modify_timing.gb` | ✅ |
113
+ | `interrupt_time.gb` | ❌ |
114
+ | `halt_bug.gb` | ❌ |
115
+ | `dmg_sound.gb` | ❌ |
data/Steepfile ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ target :lib do
4
+ signature 'sig'
5
+ check 'lib'
6
+ library 'optparse'
7
+ end
data/exe/amaterasu ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # RubyVM::YJIT.enable if defined?(RubyVM::YJIT)
5
+
6
+ require_relative '../lib/amaterasu'
7
+
8
+ options = Amaterasu::CLI.parse(ARGV)
9
+
10
+ if options[:profiling]
11
+ require 'stackprof'
12
+
13
+ StackProf.start(mode: options[:profiling].to_sym)
14
+
15
+ at_exit do
16
+ StackProf.stop
17
+ StackProf.results(
18
+ "tmp/#{Time.now.to_i}-#{options[:profiling]}-emulator-results.dump"
19
+ )
20
+ end
21
+ end
22
+
23
+ Amaterasu::Emulator.new(**options).start
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Amaterasu
4
+ class Cartridge
5
+ # Models the MBC1 chip inside the Game Boy cartridge.
6
+ #
7
+ # 0x0000 - 0x3FFF => ROM Bank X0
8
+ # 0x4000 - 0x7FFF => ROM Bank 01-7F (1 - 127)
9
+ #
10
+ # Can switch between Modes 0 and 1.
11
+ class Mbc1
12
+ def initialize(rom, ram)
13
+ @rom = rom
14
+ @ram = ram
15
+
16
+ @rom_banks = rom.rom_size / ROM_BANK_SIZE
17
+ @ram_enabled = false
18
+ @banking_mode = 0
19
+ @rom_banking_reg1 = 0b00001
20
+ @rom_banking_reg2 = 0b00
21
+ end
22
+
23
+ def write_byte(address, value)
24
+ if address <= 0x1FFF
25
+ @ram_enabled = true if (value & 0xF) == 0xA
26
+ elsif address <= 0x3FFF
27
+ value &= 0b11111
28
+ @rom_banking_reg1 = value.zero? ? 1 : value
29
+ elsif address <= 0x5FFF
30
+ @rom_banking_reg2 = value & 0b11
31
+ elsif address <= 0x7FFF
32
+ @banking_mode = value & 1
33
+ else
34
+ return 0xFF if @ram.nil? || !@ram_enabled
35
+
36
+ @ram.write_byte(address:, value:)
37
+ end
38
+ end
39
+
40
+ # TODO: Implement banking mode logic for reads
41
+ def read_byte(address)
42
+ if address <= 0x3FFF
43
+ @rom.read_byte(address)
44
+ elsif address <= 0x7FFF
45
+ selected_bank = (@rom_banking_reg2 << 5) | @rom_banking_reg1
46
+ bank_offset = selected_bank * ROM_BANK_SIZE
47
+ @rom.read_byte(address - 0x4000 + bank_offset)
48
+ else
49
+ return 0xFF if @ram.nil? || !@ram_enabled
50
+
51
+ @ram.read_byte(address:)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end