Class: Distillery::DatFile

Inherits:
Object
  • Object
show all
Defined in:
lib/distillery/datfile.rb

Overview

Handle information from DAT file

Defined Under Namespace

Classes: ContentError

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(datfile) ⇒ DatFile

Create DatFile representation from file.

Parameters:

  • datfile (String)


43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/distillery/datfile.rb', line 43

def initialize(datfile)
    @games     = Set.new
    @roms      = Vault::new
    @roms_game = {}

    if !FileTest.file?(datfile)
        raise ArgumentError, "DAT file is missing or not a regular file"
    end
    
    # Get datafile as XML document
    dat = Nokogiri::XML(File.read(datfile))

    dat.xpath('//header').each {|hdr|
        @name        = hdr.xpath('name'       )&.first&.content
        @description = hdr.xpath('description')&.first&.content
        @url         = hdr.xpath('url'        )&.first&.content
        @date        = hdr.xpath('date'       )&.first&.content
        @version     = hdr.xpath('version'    )&.first&.content
    }
    
    # Process each game elements
    dat.xpath('//game').each {|g|
        releases = g.xpath('release').map {|r|
            Release::new(r[:name], region: r[:region].upcase)
        }
        roms     = g.xpath('rom').map {|r|
            path = File.join(r[:name].split('\\'))
            ROM::new(ROM::Path::Virtual.new(path),
                     :size  => Integer(r[:size]),
                     :crc32 => r[:crc ],
                     :md5   => r[:md5 ],
                     :sha1  => r[:sha1])
        }
        game     = Game::new(g['name'], *roms, releases: releases,
                                                cloneof: g['cloneof'])

        roms.each {|rom|
            (@roms_game[rom.object_id] ||= []) << game
            @roms << rom
        }

        if @games.add?(game).nil?
            raise ContentError,
                  "Game '#{game}' defined multiple times in DAT file"
        end
    }
end

Instance Attribute Details

#dateString? (readonly)

Datfile date

Returns:

  • (String, nil)


170
171
172
# File 'lib/distillery/datfile.rb', line 170

def date
  @date
end

#descriptionString? (readonly)

Datfile description

Returns:

  • (String, nil)


158
159
160
# File 'lib/distillery/datfile.rb', line 158

def description
  @description
end

#gamesSet<Games> (readonly)

Returns:

  • (Set<Games>)


134
135
136
# File 'lib/distillery/datfile.rb', line 134

def games
  @games
end

#nameString? (readonly)

Datfile name

Returns:

  • (String, nil)


152
153
154
# File 'lib/distillery/datfile.rb', line 152

def name
  @name
end

#romsVault (readonly)

Returns:



118
119
120
# File 'lib/distillery/datfile.rb', line 118

def roms
  @roms
end

#urlString? (readonly)

Datfile url

Returns:

  • (String, nil)


164
165
166
# File 'lib/distillery/datfile.rb', line 164

def url
  @url
end

#versionString? (readonly)

Datfile version

Returns:

  • (String, nil)


176
177
178
# File 'lib/distillery/datfile.rb', line 176

def version
  @version
end

Instance Method Details

#clash(type = :fullname) ⇒ Hash{String => Array<ROM>}

Identify ROM which have the same fullname/name but are different

Parameters:

  • type (:fullname, :name) (defaults to: :fullname)

    Check by fullname or name

Returns:

  • (Hash{String => Array<ROM>})


97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/distillery/datfile.rb', line 97

def clash(type = :fullname)
    grp = case type
          when :fullname then @roms.each.group_by {|rom| rom.fullname      }
          when :name     then @roms.each.group_by {|rom| rom.name          }
          else raise ArgumentError
          end

    grp.select           {|_, roms| roms.size > 1 }
       .transform_values {|roms|
        lst = []
        while rom = roms.first do
            t, f = roms.partition {|r| r.same?(rom) }
            lst << t.first
            roms = f
        end
        lst
    }
end

#each_game {|game| ... } ⇒ self, Enumerator

Iterate over each game

Yield Parameters:

Returns:

  • (self, Enumerator)


143
144
145
146
# File 'lib/distillery/datfile.rb', line 143

def each_game
    block_given? ? @games.each {|g| yield(g) }
                 : @games.each
end

#each_rom {|rom| ... } ⇒ self, Enumerator

Iterate over each ROM

Yield Parameters:

Returns:

  • (self, Enumerator)


127
128
129
130
# File 'lib/distillery/datfile.rb', line 127

def each_rom
    block_given? ? @roms.each {|r| yield(r) }
                 : @roms.each
end

#getGames(rom) ⇒ Array<Game>

Note:

This only works for ROMs created by the DatFile

Get Games to which this ROM belongs.

Parameters:

  • rom (Rom)

Returns:



34
35
36
# File 'lib/distillery/datfile.rb', line 34

def getGames(rom)
    @roms_game[rom.object_id]
end

#with_partial_checksumArray<ROM>?

List of ROM with loosely defined (ie: with some missing checksum)

Returns:

  • (Array<ROM>, nil)


22
23
24
# File 'lib/distillery/datfile.rb', line 22

def with_partial_checksum
    @roms.with_partial_checksum
end