Class: NEXXT::Parser::Session

Inherits:
Object
  • Object
show all
Defined in:
lib/nexxt/parser/session.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(text) ⇒ Session

Returns a new instance of Session.



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/nexxt/parser/session.rb', line 11

def initialize(text)
  @text = text
  lines = text.lines(chomp: true).compact
  @flat_table = lines.grep(/=/).to_h { |line| line.split('=', 2) }
  @table = Session.parse_table(@flat_table)
  @chr_main = Session.decode_hex(@table.dig('CHR', 'Main'))
  @chr_copy = Session.decode_hex(@table.dig('CHR', 'Copy'))
  @chr_undo = Session.decode_hex(@table.dig('CHR', 'Undo'))
  @metasprites_offset = @table.dig('Var', 'Sprite', 'Grid').then do |grid|
    {
      x: grid['X'].to_i,
      y: grid['Y'].to_i
    }
  end
  @metasprites = Session.make_metasprites(
    names: Session.metasprite_names(@table.dig('Meta', 'Sprite')),
    bytes: Session.decode_hex(@table.dig('Meta', 'Sprites')),
    offset: @metasprites_offset
  )
end

Instance Attribute Details

#chr_copyObject (readonly)

Returns the value of attribute chr_copy.



8
9
10
# File 'lib/nexxt/parser/session.rb', line 8

def chr_copy
  @chr_copy
end

#chr_mainObject (readonly)

Returns the value of attribute chr_main.



8
9
10
# File 'lib/nexxt/parser/session.rb', line 8

def chr_main
  @chr_main
end

#flat_tableObject (readonly)

Returns the value of attribute flat_table.



8
9
10
# File 'lib/nexxt/parser/session.rb', line 8

def flat_table
  @flat_table
end

#metaspritesObject (readonly)

Returns the value of attribute metasprites.



8
9
10
# File 'lib/nexxt/parser/session.rb', line 8

def metasprites
  @metasprites
end

#metasprites_offsetObject (readonly)

Returns the value of attribute metasprites_offset.



8
9
10
# File 'lib/nexxt/parser/session.rb', line 8

def metasprites_offset
  @metasprites_offset
end

#tableObject (readonly)

Returns the value of attribute table.



8
9
10
# File 'lib/nexxt/parser/session.rb', line 8

def table
  @table
end

#textObject (readonly)

Returns the value of attribute text.



8
9
10
# File 'lib/nexxt/parser/session.rb', line 8

def text
  @text
end

Class Method Details

.decode_hex(string) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/nexxt/parser/session.rb', line 57

def self.decode_hex(string)
  return if string.nil? || string.empty?

  string = string['_root'] if string.is_a?(Hash)
  values = []
  until string.empty?
    match = string.match(/\A(?:\[(?<rle>[0-9a-f]+)\]|(?<literal>[0-9a-f]{2}))(?<rest>.*)/)
    raise "Invalid string #{string}" unless match

    if (rle = match['rle'])
      values += [values[-1] || 0] * (rle.to_i(16) - 1)
    elsif (literal = match['literal'])
      values << literal.to_i(16)
    end
    string = match['rest']
  end
  values
end

.decompose_key(key) ⇒ Object



53
54
55
# File 'lib/nexxt/parser/session.rb', line 53

def self.decompose_key(key)
  key.split(/(?<=[^A-Z0-9])(?=[A-Z0-9])|(?<=CHR)/).map { |part| part.delete('_') }
end

.make_metasprites(names:, bytes:, offset:) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/nexxt/parser/session.rb', line 83

def self.make_metasprites(names:, bytes:, offset:)
  return [] if bytes.nil? || bytes.empty?

  sprites = bytes.each_slice(256)
                 .to_a
                 .map do |meta_bytes|
    meta_bytes.each_slice(4)
              .reject { |row| row[0] == 255 && row[2] == 255 && row[3] == 255 }
              .map do |y, tile, attribute, x|
      raise "Invalid bytes #{bytes}" if y.nil? || tile.nil? || attribute.nil? || x.nil?

      Sprite.new(y: y - offset[:y], tile: tile, attribute: attribute, x: x - offset[:x])
    end
  end
  names.map do |name, index|
    Metasprite.new(name: name, sprites: sprites[index])
  end
end

.metasprite_names(table) ⇒ Object



76
77
78
79
80
81
# File 'lib/nexxt/parser/session.rb', line 76

def self.metasprite_names(table)
  return {} if table.nil?

  table.select { |key, value| value.is_a?(String) && key =~ /\d/ }
       .to_h { |key, value| [value, key.to_i] }
end

.parse_table(flat_table) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/nexxt/parser/session.rb', line 36

def self.parse_table(flat_table)
  table = {}
  flat_table.each do |key, value|
    path = decompose_key(key)
    path.reduce(table) do |a, e|
      a[e] = { '_root' => a[e] } unless a[e].nil? || a[e].is_a?(Hash)
      a[e] ||= {}
    end
    if path.size > 1
      table.dig(*path[..-2])[path[-1]] = value
    else
      table[path.first] = value
    end
  end
  table
end

.read(file) ⇒ Object



32
33
34
# File 'lib/nexxt/parser/session.rb', line 32

def self.read(file)
  new(File.read(file))
end