rubyboy 0.1.0 → 0.2.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,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Rubyboy
6
+ class Interrupt
7
+ attr_accessor :ie, :if
8
+
9
+ def initialize
10
+ @ie = 0
11
+ @if = 0
12
+ end
13
+
14
+ def interrupts
15
+ @if & @ie & 0x1f
16
+ end
17
+
18
+ def request(interrupt)
19
+ @if |= interrupt
20
+ end
21
+ end
22
+ end
data/lib/rubyboy/ppu.rb CHANGED
@@ -17,15 +17,15 @@ module Rubyboy
17
17
 
18
18
  def step(cycles)
19
19
  @cycles += cycles
20
- if @cycles >= 456
21
- @cycles -= 456
22
- @ly = (@ly + 1) % 154
23
- end
20
+ return if @cycles < 456
21
+
22
+ @cycles -= 456
23
+ @ly = (@ly + 1) % 154
24
24
  end
25
25
 
26
26
  def draw_bg
27
- tile_map_addr = @lcdc[3] == 0 ? 0x9800 : 0x9c00
28
- tile_data_addr = @lcdc[4] == 0 ? 0x9000 : 0x8000
27
+ tile_map_addr = @lcdc[3].zero? ? 0x9800 : 0x9c00
28
+ tile_data_addr = @lcdc[4].zero? ? 0x9000 : 0x8000
29
29
 
30
30
  bg = Array.new(256) { Array.new(256, 0x00) }
31
31
 
@@ -38,12 +38,12 @@ module Rubyboy
38
38
  tile = @vram[tile_data_addr - 0x8000 + tile_index * 16, 16]
39
39
 
40
40
  8.times do |i|
41
- pixelsa = tile[i*2]
42
- pixelsb = tile[i*2+1]
41
+ pixelsa = tile[i * 2]
42
+ pixelsb = tile[i * 2 + 1]
43
43
 
44
44
  8.times do |j|
45
- c = (pixelsb[7-j] << 1) + pixelsa[7-j]
46
- bg[y*8+i][x*8+j] = get_color(c)
45
+ c = (pixelsb[7 - j] << 1) + pixelsa[7 - j]
46
+ bg[y * 8 + i][x * 8 + j] = get_color(c)
47
47
  end
48
48
  end
49
49
  end
@@ -52,7 +52,7 @@ module Rubyboy
52
52
 
53
53
  144.times do |y|
54
54
  160.times do |x|
55
- view_port[y][x] = bg[(y+@scy) % 144][(x+@scx) % 160]
55
+ view_port[y][x] = bg[(y + @scy) % 144][(x + @scx) % 160]
56
56
  end
57
57
  end
58
58
  view_port
@@ -63,13 +63,13 @@ module Rubyboy
63
63
  def get_color(color_num)
64
64
  case color_num
65
65
  when 0
66
- [0xff, 0xff, 0xff]
66
+ [0xff, 0xff, 0xff, 0xff]
67
67
  when 1
68
- [0xcc, 0xcc, 0xcc]
68
+ [0xcc, 0xcc, 0xcc, 0xff]
69
69
  when 2
70
- [0x77, 0x77, 0x77]
70
+ [0x77, 0x77, 0x77, 0xff]
71
71
  when 3
72
- [0x00, 0x00, 0x00]
72
+ [0x00, 0x00, 0x00, 0xff]
73
73
  end
74
74
  end
75
75
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rubyboy
4
+ class Ram
5
+ attr_accessor :eram, :wram1, :wram2, :hram
6
+
7
+ def initialize
8
+ @eram = Array.new(0x2000, 0)
9
+ @wram1 = Array.new(0x1000, 0)
10
+ @wram2 = Array.new(0x1000, 0)
11
+ @hram = Array.new(0x80, 0)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Rubyboy
6
+ class Register
7
+ attr_reader :value
8
+
9
+ def initialize(name:, value:)
10
+ @name = name
11
+ @value = value
12
+ end
13
+
14
+ def value=(v)
15
+ @value = v & 0xff
16
+ end
17
+
18
+ def increment
19
+ @value = (@value + 1) & 0xff
20
+ end
21
+
22
+ def decrement
23
+ @value = (@value - 1) & 0xff
24
+ end
25
+ end
26
+ end
data/lib/rubyboy/rom.rb CHANGED
@@ -27,7 +27,7 @@ module Rubyboy
27
27
 
28
28
  # 0x104 - 0x133: Nintendo Logo
29
29
  @logo = @data[0x104..0x133]
30
- raise 'logo is not match' unless LOGO_DUMP == @logo
30
+ raise 'logo is not match' unless @logo == LOGO_DUMP
31
31
 
32
32
  # 0x134 - 0x143: Title
33
33
  @title = @data[0x134..0x143]
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Rubyboy
6
+ class Timer
7
+ def initialize(interrupt)
8
+ @div = 0
9
+ @tima = 0
10
+ @tma = 0
11
+ @tac = 0
12
+ @cycles = 0
13
+ @interrupt = interrupt
14
+ end
15
+
16
+ def step(cycles)
17
+ before_cycles = @cycles
18
+ after_cycles = @cycles + cycles
19
+ @cycles = after_cycles & 0xffff
20
+
21
+ @div += after_cycles / 256 - before_cycles / 256
22
+ @div &= 0xffff
23
+
24
+ return if @tac[2].zero?
25
+
26
+ divider = case @tac & 0b11
27
+ when 0b00 then 1024
28
+ when 0b01 then 16
29
+ when 0b10 then 64
30
+ when 0b11 then 256
31
+ end
32
+
33
+ tima_diff = (after_cycles / divider - before_cycles / divider)
34
+ @tima += tima_diff
35
+
36
+ return if @tima < 256
37
+
38
+ @tima &= 0xff
39
+ @interrupt.request(0b0000_0100)
40
+ end
41
+
42
+ def read_byte(byte)
43
+ case byte
44
+ when 0xff04
45
+ @div >> 8
46
+ when 0xff05
47
+ @tima
48
+ when 0xff06
49
+ @tma
50
+ when 0xff07
51
+ @tac | 0b1111_1000
52
+ end
53
+ end
54
+
55
+ def write_byte(byte, value)
56
+ case byte
57
+ when 0xff04
58
+ @div = 0
59
+ when 0xff05
60
+ @tima = value
61
+ when 0xff06
62
+ @tma = value
63
+ when 0xff07
64
+ @tac = value & 0b111
65
+ end
66
+ end
67
+ end
68
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rubyboy
4
- VERSION = "0.1.0"
4
+ VERSION = '0.2.0'
5
5
  end
data/lib/rubyboy.rb CHANGED
@@ -1,11 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'gosu'
4
- require_relative "rubyboy/version"
4
+ require 'benchmark'
5
+ require_relative 'rubyboy/version'
5
6
  require_relative 'rubyboy/bus'
6
7
  require_relative 'rubyboy/cpu'
7
8
  require_relative 'rubyboy/ppu'
8
9
  require_relative 'rubyboy/rom'
10
+ require_relative 'rubyboy/timer'
9
11
 
10
12
  module Rubyboy
11
13
  class Console < Gosu::Window
@@ -18,8 +20,10 @@ module Rubyboy
18
20
  @total_cycles = 0
19
21
 
20
22
  rom = Rom.new(rom_data)
23
+ interrupt = Interrupt.new
21
24
  @ppu = Ppu.new
22
- @bus = Bus.new(@ppu, rom)
25
+ @timer = Timer.new(interrupt)
26
+ @bus = Bus.new(@ppu, rom, @timer, interrupt)
23
27
  @cpu = Cpu.new(@bus)
24
28
  end
25
29
 
@@ -27,21 +31,19 @@ module Rubyboy
27
31
  while @total_cycles < 70224
28
32
  cycles = @cpu.exec
29
33
  @total_cycles += cycles
34
+ @timer.step(cycles)
30
35
  @ppu.step(cycles)
31
36
  end
32
37
  @total_cycles -= 70224
33
-
34
- rescue => e
35
- p e
38
+ rescue StandardError => e
39
+ p e.to_s[0, 100]
40
+ raise e
36
41
  end
37
42
 
38
43
  def draw
39
- bg = @ppu.draw_bg
40
- bg.each_with_index do |xarray, i|
41
- xarray.each_with_index do |c, j|
42
- draw_pixel(j, i, c)
43
- end
44
- end
44
+ pixel_data = @ppu.draw_bg.flatten.pack('C*')
45
+ @image = Gosu::Image.from_blob(160, 144, pixel_data)
46
+ @image.draw(0, 0, 0, SCALE, SCALE)
45
47
  end
46
48
 
47
49
  def draw_pixel(x, y, color)
@@ -53,5 +55,5 @@ module Rubyboy
53
55
  end
54
56
  end
55
57
 
56
- rom_data = File.open(File.expand_path('roms/hello-world.gb', __dir__), 'r') { _1.read.bytes }
58
+ rom_data = File.open(File.expand_path('roms/cpu_instrs/cpu_instrs.gb', __dir__), 'r') { _1.read.bytes }
57
59
  Rubyboy::Console.new(rom_data).show
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubyboy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - sacckey
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-10-13 00:00:00.000000000 Z
11
+ date: 2023-11-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gosu
@@ -37,14 +37,36 @@ files:
37
37
  - LICENSE.txt
38
38
  - README.md
39
39
  - Rakefile
40
+ - lib/opcodes.json
41
+ - lib/roms/cpu_instrs/cpu_instrs.gb
42
+ - lib/roms/cpu_instrs/individual/01-special.gb
43
+ - lib/roms/cpu_instrs/individual/02-interrupts.gb
44
+ - lib/roms/cpu_instrs/individual/03-op sp,hl.gb
45
+ - lib/roms/cpu_instrs/individual/04-op r,imm.gb
46
+ - lib/roms/cpu_instrs/individual/05-op rp.gb
47
+ - lib/roms/cpu_instrs/individual/06-ld r,r.gb
48
+ - lib/roms/cpu_instrs/individual/07-jr,jp,call,ret,rst.gb
49
+ - lib/roms/cpu_instrs/individual/08-misc instrs.gb
50
+ - lib/roms/cpu_instrs/individual/09-op r,r.gb
51
+ - lib/roms/cpu_instrs/individual/10-bit ops.gb
52
+ - lib/roms/cpu_instrs/individual/11-op a,(hl).gb
53
+ - lib/roms/cpu_instrs/readme.txt
40
54
  - lib/roms/hello-world.gb
41
- - lib/roms/hello.gb
55
+ - lib/roms/instr_timing/instr_timing.gb
56
+ - lib/roms/instr_timing/readme.txt
42
57
  - lib/roms/tobu.gb
43
58
  - lib/rubyboy.rb
44
59
  - lib/rubyboy/bus.rb
60
+ - lib/rubyboy/cartridge/factory.rb
61
+ - lib/rubyboy/cartridge/mbc1.rb
62
+ - lib/rubyboy/cartridge/nombc.rb
45
63
  - lib/rubyboy/cpu.rb
64
+ - lib/rubyboy/interrupt.rb
46
65
  - lib/rubyboy/ppu.rb
66
+ - lib/rubyboy/ram.rb
67
+ - lib/rubyboy/register.rb
47
68
  - lib/rubyboy/rom.rb
69
+ - lib/rubyboy/timer.rb
48
70
  - lib/rubyboy/version.rb
49
71
  - sig/rubyboy.rbs
50
72
  homepage: https://github.com/sacckey/rubyboy
@@ -55,6 +77,7 @@ metadata:
55
77
  homepage_uri: https://github.com/sacckey/rubyboy
56
78
  source_code_uri: https://github.com/sacckey/rubyboy
57
79
  changelog_uri: https://github.com/sacckey/rubyboy/blob/main/CHANGELOG.md
80
+ rubygems_mfa_required: 'true'
58
81
  post_install_message:
59
82
  rdoc_options: []
60
83
  require_paths:
@@ -63,7 +86,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
63
86
  requirements:
64
87
  - - ">="
65
88
  - !ruby/object:Gem::Version
66
- version: 2.6.0
89
+ version: 3.2.0
67
90
  required_rubygems_version: !ruby/object:Gem::Requirement
68
91
  requirements:
69
92
  - - ">="