Class: Amaterasu::GameBoy::Ppu::Modes::OamScan

Inherits:
Object
  • Object
show all
Defined in:
lib/amaterasu/game_boy/ppu/modes/oam_scan.rb,
sig/akane/game_boy/ppu/modes/oam_scan.rbs

Overview

Defines the behavior of the PPU during OAM Scan mode.

Constant Summary collapse

SCAN_DURATION_IN_DOTS =

Each Sprite takes 2 dots to scan.

Returns:

  • (Integer)
80

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(ppu) ⇒ OamScan

Returns a new instance of OamScan.

Parameters:



15
16
17
18
19
20
21
22
23
24
# File 'lib/amaterasu/game_boy/ppu/modes/oam_scan.rb', line 15

def initialize(ppu)
  @ppu = ppu

  @name = 'OAM SCAN'
  @number = 2

  @sprite_count = 0
  @sprite_index = 0
  @current_sprite = nil
end

Instance Attribute Details

#nameString (readonly)

Returns the value of attribute name.

Returns:

  • (String)


12
13
14
# File 'lib/amaterasu/game_boy/ppu/modes/oam_scan.rb', line 12

def name
  @name
end

#numberInteger (readonly)

Returns the value of attribute number.

Returns:

  • (Integer)


12
13
14
# File 'lib/amaterasu/game_boy/ppu/modes/oam_scan.rb', line 12

def number
  @number
end

Instance Method Details

#inspectString

Custom inspect to prevent circular dependencies.

Returns:

  • (String)


53
54
55
56
57
58
# File 'lib/amaterasu/game_boy/ppu/modes/oam_scan.rb', line 53

def inspect
  '#<Amaterasu::GameBoy::Ppu::Modes::OamScan ' \
    "@name='#{@name}' " \
    "@number=#{@number} " \
    "@sprite_buffer=#{@sprite_buffer}"
end

#sort_sprites_by_x_positionsvoid

This method returns an undefined value.

TODO: benchmark the performance of both



85
86
87
88
# File 'lib/amaterasu/game_boy/ppu/modes/oam_scan.rb', line 85

def sort_sprites_by_x_positions
  @ppu.sprite_buffer.sort_by!(&:x)
  # @ppu.sprite_buffer.sort! { |a, b| a.x <=> b.x }
end

#sprite_within_current_scanline?Boolean

Returns:

  • (Boolean)


77
78
79
80
81
82
# File 'lib/amaterasu/game_boy/ppu/modes/oam_scan.rb', line 77

def sprite_within_current_scanline?
  sprite_height = @ppu.registers.lcdc.obj_size_8x16? ? 16 : 8

  @ppu.registers.ly >= @current_sprite.y_screen_pos
    && @ppu.registers.ly < @current_sprite.y_screen_pos + sprite_height
end

#tickvoid

This method returns an undefined value.

This method is called by the PPU each T-cycle for all visible scanlines (0 - 143) and when dots are between 0 and 79.

Takes exactly 2 dots to fetch a sprite so every even dot (0, 2, 4, ..., 78) is a NO-OP.



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/amaterasu/game_boy/ppu/modes/oam_scan.rb', line 32

def tick
  if @ppu.dots.odd?
    @current_sprite = @ppu.fetch_sprite_at(@sprite_index) #=> 0 - 39
    @sprite_index += 1

    if sprite_within_current_scanline? && @sprite_count < Ppu::MAX_SPRITES_PER_SCANLINE
      @ppu.sprite_buffer << @current_sprite
      @sprite_count += 1
    end
  end

  return unless @ppu.dots == SCAN_DURATION_IN_DOTS

  sort_sprites_by_x_positions unless @ppu.sprite_buffer.empty?
  @sprite_count = 0
  @sprite_index = 0
  @ppu.wy_eq_ly = true if window_triggered?
  @ppu.set_mode(:rendering)
end

#to_sString

Custom to_s method to use in the Ppu#log_state method.

Returns:

  • (String)


61
62
63
64
65
# File 'lib/amaterasu/game_boy/ppu/modes/oam_scan.rb', line 61

def to_s
  "#{@name} (##{@number}) | " \
    "SCANNED: Sprite ##{format('%02d', @sprite_index)} | " \
    "BUFFER: #{@ppu.sprite_buffer} (#{@ppu.sprite_buffer.size})"
end

#window_triggered?Boolean

Returns:

  • (Boolean)


69
70
71
72
73
74
75
# File 'lib/amaterasu/game_boy/ppu/modes/oam_scan.rb', line 69

def window_triggered?
  return false unless @ppu.registers.lcdc.window_enabled?
  return false unless @ppu.registers.ly == @ppu.registers.wy
  return false if @ppu.wy_eq_ly

  true
end