romloader 1.0.0 → 1.1.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.
- checksums.yaml +4 -4
- data/README.md +2 -0
- data/lib/romloader.rb +4 -2
- data/lib/romloader/archive_extractor.rb +30 -26
- data/lib/romloader/freeroms_scraper.rb +10 -7
- data/lib/romloader/game_rom.rb +4 -2
- data/lib/romloader/game_system.rb +9 -5
- data/lib/romloader/romloader_cli.rb +33 -18
- metadata +2 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 87a10ca23bd4fc1e499ef4240027008cc2a4d911
|
4
|
+
data.tar.gz: 953fe06a0b401c28467d65a00acbb7818f84c6ae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0c3b71b8b3319c7d2f5a8ec434b87981d7307a36c4e968188f373b66ca1543b1b8fcb47012a13cb4ed38f3f5ffdfd48d159aab3800ea524490d4ff8b47571c1d
|
7
|
+
data.tar.gz: ac72b823b59ca07ac9677116f02264ce8343dc03cefc2aa11765be4e936f73bd2900459d4bf21d27eac81fd97344ce4c2a7a228d5fdc4a87ca758a67dc92da22
|
data/README.md
CHANGED
@@ -27,6 +27,8 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/jinstr
|
|
27
27
|
|
28
28
|
## Version Changes
|
29
29
|
|
30
|
+
v. 1.1: Added basic rom download capability for Windows (requires Powershell v 3.0 or higher)
|
31
|
+
|
30
32
|
v. 1.0: Changed the namespacing of classes, added zip/7-zip extraction and rom download directory management. Also, added the ability to open the newly downloaded game from the command line (requires a emulator)
|
31
33
|
|
32
34
|
v. 0.0: Basic rom listing from Freeroms.com, and rom download feature
|
data/lib/romloader.rb
CHANGED
@@ -5,8 +5,10 @@ end
|
|
5
5
|
require 'open-uri'
|
6
6
|
require 'nokogiri'
|
7
7
|
require 'cgi'
|
8
|
-
|
9
|
-
require '
|
8
|
+
unless /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
|
9
|
+
require 'zip'
|
10
|
+
require 'seven_zip_ruby'
|
11
|
+
end
|
10
12
|
require 'fileutils'
|
11
13
|
require_relative 'romloader/game_rom.rb'
|
12
14
|
require_relative 'romloader/game_system.rb'
|
@@ -3,53 +3,57 @@ class RomLoader::ArchiveExtractor
|
|
3
3
|
|
4
4
|
#Extracts zip or 7-zip rom files, manages the extracted dirs, then deletes archive files
|
5
5
|
def self.extract(dir,game_obj)
|
6
|
-
file_or_dir_to_open =
|
7
|
-
/(?<=\().+(?=\))/.match(game_obj.system.name) ?
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
file_or_dir_to_open = nil
|
7
|
+
/(?<=\().+(?=\))/.match(game_obj.system.name) ? system_name = /(?<=\().+(?=\))/.match(game_obj.system.name)[0] : system_name = nil
|
8
|
+
system_name ||= game_obj.system.name
|
9
|
+
system_name = system_name.rstrip.gsub(/[[[:space:]]\/]/, "_").downcase
|
10
|
+
dir_w_system = File.join(Dir.home,"videogame_roms",system_name)
|
11
|
+
dir_game_name = game_obj.filename.split(game_obj.file_ext)[0]
|
12
|
+
|
13
|
+
Dir.mkdir(dir_w_system) unless Dir.exist?(dir_w_system)
|
11
14
|
|
12
15
|
if game_obj.system.name != "MAME"
|
13
16
|
puts "Extracting #{game_obj.filename}"
|
14
17
|
if game_obj.file_ext == ".zip"
|
15
18
|
Zip::File.open(dir) do |zip_archive|
|
16
19
|
zip_archive.glob("*htm").each { |entry| zip_archive.remove(entry) }
|
17
|
-
Dir.mkdir(File.join(
|
20
|
+
Dir.mkdir(File.join(dir_w_system,dir_game_name)) if zip_archive.size > 1 && !Dir.exist?(File.join(dir_w_system,dir_game_name))
|
18
21
|
zip_archive.each_entry do |rom|
|
19
|
-
if Dir.exist?(File.join(
|
20
|
-
rom.extract(File.join(
|
22
|
+
if Dir.exist?(File.join(dir_w_system,dir_game_name))
|
23
|
+
rom.extract(File.join(dir_w_system,dir_game_name,rom.name)) unless File.exist?(File.join(dir_w_system,dir_game_name,rom.name))
|
21
24
|
else
|
22
|
-
rom.extract(File.join(
|
25
|
+
rom.extract(File.join(dir_w_system,rom.name)) unless File.exist?(File.join(dir_w_system,rom.name))
|
23
26
|
end
|
24
|
-
zip_archive.size == 1 ? file_or_dir_to_open = File.join(
|
27
|
+
zip_archive.size == 1 ? file_or_dir_to_open = File.join(dir_w_system,"\"#{rom.name}\"") : file_or_dir_to_open = File.join(dir_w_system,dir_game_name)
|
25
28
|
end
|
26
29
|
end
|
27
|
-
|
30
|
+
elsif game_obj.file_ext == ".7z"
|
28
31
|
File.open(dir, "rb") do |seven_zip_archive|
|
29
|
-
Dir.mkdir(File.join(Dir.home,"videogame_roms",system_dir,game_obj.filename.split(game_obj.file_ext)[0])) unless Dir.exist?(File.join(Dir.home,"videogame_roms",system_dir,game_obj.filename.split(game_obj.file_ext)[0]))
|
30
32
|
SevenZipRuby::Reader.open(seven_zip_archive) do |szr|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
file_match ? file_name = file_match[0].split(file_match[1])[1] : file_name = nil
|
36
|
-
!files_already_in_dir.any? { |file| file == file_name || file_name =~ /\.htm/}
|
37
|
-
end
|
38
|
-
szr.extract(files_to_be_extracted, File.join(Dir.home,"videogame_roms",system_dir,game_obj.filename.split(game_obj.file_ext)[0]))
|
33
|
+
if szr.entries.size > 2
|
34
|
+
Dir.mkdir(File.join(dir_w_system,dir_game_name)) unless Dir.exist?(File.join(dir_w_system,dir_game_name))
|
35
|
+
szr.extract_if(File.join(dir_w_system,dir_game_name)) { |entry| !/\.htm/.match(entry.inspect) }
|
36
|
+
file_or_dir_to_open = File.join(dir_w_system,dir_game_name)
|
39
37
|
else
|
40
|
-
szr.
|
38
|
+
szr.extract_if(dir_w_system) do |entry|
|
39
|
+
game_name = /(?<=file, |dir, |anti, )[.[^\.]]+\..+(?=>)/.match(entry.inspect)[0] unless /\.htm/.match(entry.inspect)
|
40
|
+
!/\.htm/.match(entry.inspect)
|
41
|
+
end
|
42
|
+
file_or_dir_to_open = File.join(dir_w_system,"\"#{game_name}\"")
|
41
43
|
end
|
42
44
|
end
|
43
|
-
Dir.chdir(File.join(Dir.home,"videogame_roms",system_dir,game_obj.filename.split(game_obj.file_ext)[0])) do
|
44
|
-
Dir.entries(".").size == 1 ? file_or_dir_to_open = File.join(Dir.pwd,"\"#{Dir.entries(".").first}\"") : file_or_dir_to_open = Dir.pwd
|
45
|
-
end
|
46
45
|
end
|
47
46
|
end
|
48
47
|
File.delete(dir)
|
49
48
|
file_or_dir_to_open
|
50
49
|
else
|
51
|
-
|
52
|
-
|
50
|
+
if game_obj.system.name == "MAME"
|
51
|
+
puts "NOTE: No archive extraction. MAME roms must remain zipped to play."
|
52
|
+
else
|
53
|
+
puts "NOTE: No archive extraction. Only Zip and 7-Zip extraction is supported."
|
54
|
+
end
|
55
|
+
FileUtils.move dir, dir_w_system
|
56
|
+
file_or_dir_to_open = dir_w_system
|
53
57
|
end
|
54
58
|
end
|
55
59
|
|
@@ -12,7 +12,7 @@ class RomLoader::FreeromsScraper
|
|
12
12
|
begin
|
13
13
|
system_rom_url = system_info.attribute("href").value
|
14
14
|
rescue NoMethodError
|
15
|
-
|
15
|
+
|
16
16
|
else
|
17
17
|
game_system << {name: system_name, rom_index_url: system_rom_url}
|
18
18
|
end
|
@@ -21,7 +21,8 @@ class RomLoader::FreeromsScraper
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
# To retrieve the names and main rom urls of the individual games currently begin served by freeroms.com.
|
24
|
+
# To retrieve the names and main rom urls of the individual games currently begin served by freeroms.com.
|
25
|
+
# Returns this information in the form of an array of hashes
|
25
26
|
def self.rom_scrape(url)
|
26
27
|
|
27
28
|
game_list = Nokogiri::HTML(open(url)).css("tr[class^=\"game\"] > td[align=\"left\"]")
|
@@ -30,7 +31,7 @@ class RomLoader::FreeromsScraper
|
|
30
31
|
begin
|
31
32
|
download_link = game_info.css("a").attribute("href").value
|
32
33
|
rescue NoMethodError
|
33
|
-
|
34
|
+
|
34
35
|
else
|
35
36
|
game_name = game_info.css("span").text
|
36
37
|
unless game_name == ""
|
@@ -43,7 +44,8 @@ class RomLoader::FreeromsScraper
|
|
43
44
|
end
|
44
45
|
end
|
45
46
|
|
46
|
-
# To retrieve the detailed information of individual games currently begin served by freeroms.com.
|
47
|
+
# To retrieve the detailed information of individual games currently begin served by freeroms.com.
|
48
|
+
# Returns this information in the form of a hash
|
47
49
|
def self.rom_details(url)
|
48
50
|
|
49
51
|
direct_download = Nokogiri::HTML(open(url))
|
@@ -53,7 +55,7 @@ class RomLoader::FreeromsScraper
|
|
53
55
|
begin
|
54
56
|
game_url = /http:\/\/.+(\.zip|\.7z)/.match(direct_download.css("td#romss > script").first.children.first.text)
|
55
57
|
rescue NoMethodError
|
56
|
-
|
58
|
+
|
57
59
|
else
|
58
60
|
if game_url
|
59
61
|
game[:download_url] = game_url[0]
|
@@ -70,7 +72,8 @@ class RomLoader::FreeromsScraper
|
|
70
72
|
end
|
71
73
|
end
|
72
74
|
|
73
|
-
#
|
75
|
+
# To retrieve the letter indices for the roms of the game systems currently begin served by freeroms.com.
|
76
|
+
# Returns this information in the form of a hash
|
74
77
|
def self.rom_index_scrape(url)
|
75
78
|
|
76
79
|
rom_letter_list = Nokogiri::HTML(open(url)).css("tr.letters > td[align=\"center\"] > font > a")
|
@@ -80,7 +83,7 @@ class RomLoader::FreeromsScraper
|
|
80
83
|
begin
|
81
84
|
letter_hash[letter] = letter_list.attribute("href").value if letter =~ /\A[A-Z#]\Z/
|
82
85
|
rescue NoMethodError
|
83
|
-
|
86
|
+
|
84
87
|
end
|
85
88
|
end
|
86
89
|
end
|
data/lib/romloader/game_rom.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
|
2
|
-
# The class whose instances represent an individual game rom
|
2
|
+
# The class whose instances represent an individual game rom
|
3
|
+
# (e.g. Chrono Trigger object)
|
3
4
|
class RomLoader::GameRom
|
4
5
|
|
5
6
|
attr_accessor :name, :system
|
6
7
|
attr_reader :rom_detail_url ,:download_url, :size, :file_ext, :filename
|
7
8
|
|
8
|
-
# Create individual game rom objects from information scraped from freeroms.com,
|
9
|
+
# Create individual game rom objects from information scraped from freeroms.com,
|
10
|
+
# then sets the required name and rom_detail_url instance variables
|
9
11
|
def initialize(name:, rom_detail_url:)
|
10
12
|
@name = name
|
11
13
|
@rom_detail_url = rom_detail_url
|
@@ -1,5 +1,6 @@
|
|
1
1
|
|
2
|
-
# The class whose instances represent an individual game system
|
2
|
+
# The class whose instances represent an individual game system
|
3
|
+
# (e.g. Sega Genesis object)
|
3
4
|
class RomLoader::GameSystem
|
4
5
|
|
5
6
|
attr_accessor :name, :rom_index_url
|
@@ -27,22 +28,25 @@ class RomLoader::GameSystem
|
|
27
28
|
@@all
|
28
29
|
end
|
29
30
|
|
30
|
-
# Retrieves an array of all GameRom objects starting which the provided letter index
|
31
|
+
# Retrieves an array of all GameRom objects starting which the provided letter index
|
32
|
+
# (e.g. [Sonic the Hedgehog, Streets of Rage,...])
|
31
33
|
def get_roms_by_letter(letter_index)
|
32
34
|
@roms[letter_index]
|
33
35
|
end
|
34
36
|
|
35
|
-
# Retrieves an array of the indicies for the roms
|
37
|
+
# Retrieves an array of the indicies for the roms
|
38
|
+
# (i.e. ["A","B","C"...])
|
36
39
|
def get_rom_indices
|
37
40
|
@rom_indices.keys
|
38
41
|
end
|
39
42
|
|
40
|
-
# Retrieves the url for roms of a particular letter index
|
43
|
+
# Retrieves the url for roms of a particular letter index
|
44
|
+
# (e.g. "A" => "http://freeroms.com/genesis_games_that_start_with_a.html")
|
41
45
|
def get_rom_collection_url(letter_index)
|
42
46
|
@rom_indices[letter_index]
|
43
47
|
end
|
44
48
|
|
45
|
-
# Add the game collection scraped from http://freeroms.com to the GameSystem object to the roms
|
49
|
+
# Add the game collection scraped from http://freeroms.com to the GameSystem object to the roms Hash
|
46
50
|
def add_roms_to_collection_by_letter(letter_index, game_obj_array)
|
47
51
|
|
48
52
|
game_obj_array.each { |game| game.system = self }
|
@@ -12,7 +12,7 @@ class RomLoader::RomLoaderCli
|
|
12
12
|
input_stack = []
|
13
13
|
control_flow_level = 1
|
14
14
|
|
15
|
-
puts "Thanks for using RomLoader, powered by freeroms.com!\nNOTE: To play
|
15
|
+
puts "Thanks for using RomLoader, powered by freeroms.com!\nNOTE: To play the games, please download an emulator for the desired system.\nConnecting to freeroms.com and retrieving the systems index...\n\n"
|
16
16
|
sleep 3
|
17
17
|
while control_flow_level > 0
|
18
18
|
case control_flow_level
|
@@ -67,13 +67,15 @@ class RomLoader::RomLoaderCli
|
|
67
67
|
input = input_prompt("Download? (Y/n) [exit]:", /[yn]/, control_flow_level)
|
68
68
|
if input == 'y' || input == ""
|
69
69
|
file_or_dir_to_open = download_rom(game)
|
70
|
-
if
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
70
|
+
if file_or_dir_to_open
|
71
|
+
if /\".+\"/.match(file_or_dir_to_open)
|
72
|
+
game_file = /\".+\"/.match(file_or_dir_to_open)[0]
|
73
|
+
input = input_prompt("Play #{game_file}? (Y/n) [exit]:", /[yn]/,control_flow_level)
|
74
|
+
else
|
75
|
+
input = input_prompt("Open #{file_or_dir_to_open}? (Y/n) [exit]:", /[yn]/,control_flow_level)
|
76
|
+
end
|
77
|
+
system("open #{file_or_dir_to_open}") if input == 'y' || input == ""
|
78
|
+
end
|
77
79
|
end
|
78
80
|
input_stack.shift
|
79
81
|
input == "exit" ? control_flow_level = 0 : control_flow_level -= 1
|
@@ -97,7 +99,8 @@ class RomLoader::RomLoaderCli
|
|
97
99
|
end
|
98
100
|
end
|
99
101
|
|
100
|
-
# Lists the game systems scraped from http://freeroms.com and saved in Romloader::GameSystem.all
|
102
|
+
# Lists the game systems scraped from http://freeroms.com and saved in Romloader::GameSystem.all
|
103
|
+
# (e.g. 1. Amiga, 2. Atari, etc...)
|
101
104
|
def list_systems
|
102
105
|
RomLoader::GameSystem.all.each_with_index { |game_system, index| puts "#{index+1}. #{game_system.name}"}
|
103
106
|
print "\n"
|
@@ -108,7 +111,8 @@ class RomLoader::RomLoaderCli
|
|
108
111
|
RomLoader::GameSystem.all[index-1]
|
109
112
|
end
|
110
113
|
|
111
|
-
# List game index for the selected system by letter
|
114
|
+
# List game index for the selected system by letter
|
115
|
+
# (e.g. A B C D...)
|
112
116
|
def list_system_index(selected_system)
|
113
117
|
if selected_system.get_rom_indices.empty?
|
114
118
|
selected_system.rom_indices = RomLoader::FreeromsScraper.rom_index_scrape(selected_system.rom_index_url)
|
@@ -119,14 +123,16 @@ class RomLoader::RomLoaderCli
|
|
119
123
|
puts "\n\n"
|
120
124
|
end
|
121
125
|
|
122
|
-
# Retrieves all the games available for the selected system under the selected index
|
126
|
+
# Retrieves all the games available for the selected system under the selected index
|
127
|
+
# (e.g. NES,"G")
|
123
128
|
def select_game_collection_by_index(system, letter)
|
124
129
|
puts "Loading roms...\n"
|
125
130
|
games_list = system.get_roms_by_letter(letter)
|
126
131
|
games_list ||= system.add_roms_to_collection_by_letter(letter,RomLoader::GameRom.create_collection(RomLoader::FreeromsScraper.rom_scrape(system.get_rom_collection_url(letter))))
|
127
132
|
end
|
128
133
|
|
129
|
-
# List all the games available for the selected index
|
134
|
+
# List all the games available for the selected index
|
135
|
+
# (e.g. "S": 1. Super Castlevania, 2. Super Mario World, etc...)
|
130
136
|
def list_games(games)
|
131
137
|
games.each_with_index {|game,index| puts "#{index+1}. #{game.name}"}
|
132
138
|
print "\n"
|
@@ -138,7 +144,8 @@ class RomLoader::RomLoaderCli
|
|
138
144
|
game_collection[index-1]
|
139
145
|
end
|
140
146
|
|
141
|
-
# List the details of the selected game
|
147
|
+
# List the details of the selected game
|
148
|
+
# (e.g. Chrono Trigger | SNES | 5.38 MB | .zip)
|
142
149
|
def display_rom_details(game)
|
143
150
|
puts "Rom details:"
|
144
151
|
puts "#{game.name} | System: #{game.system.name} | File size: #{game.size} | File type: #{game.file_ext}"
|
@@ -167,19 +174,27 @@ class RomLoader::RomLoaderCli
|
|
167
174
|
input
|
168
175
|
end
|
169
176
|
|
177
|
+
def isWindows?
|
178
|
+
/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
|
179
|
+
end
|
180
|
+
|
170
181
|
# Downloads the selected game to the local directory (~/videogame_roms)
|
171
182
|
def download_rom(game)
|
172
|
-
file_or_dir_to_open =
|
183
|
+
file_or_dir_to_open = nil
|
173
184
|
puts "Downloading #{game.name} (#{game.size})..."
|
174
|
-
|
185
|
+
if isWindows?
|
186
|
+
result = Dir.chdir(File.join(Dir.home,"videogame_roms")) { system("powershell -command \"& { Invoke-WebRequest '#{game.download_url}' -OutFile '#{game.filename}' }\"") }
|
187
|
+
else
|
188
|
+
result = Dir.chdir(File.join(Dir.home,"videogame_roms")) { system("curl -Og# \"#{game.download_url}\"") }
|
189
|
+
end
|
190
|
+
|
175
191
|
if result == true
|
176
192
|
puts "Finished downloading #{game.filename} to #{File.join(Dir.home,"videogame_roms")}.\n"
|
177
|
-
file_or_dir_to_open = RomLoader::ArchiveExtractor.extract(File.join(Dir.home,"videogame_roms",game.filename),game)
|
193
|
+
file_or_dir_to_open = RomLoader::ArchiveExtractor.extract(File.join(Dir.home,"videogame_roms",game.filename),game) unless isWindows?
|
178
194
|
else
|
179
195
|
puts "An error occured, the rom couldn't be downloaded.\n"
|
180
196
|
end
|
181
|
-
sleep
|
182
|
-
puts "\n"
|
197
|
+
sleep 2
|
183
198
|
file_or_dir_to_open
|
184
199
|
end
|
185
200
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: romloader
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Efrain Perez Jr
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-10-
|
11
|
+
date: 2016-10-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -52,20 +52,6 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '1.2'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: fileutils
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0.7'
|
62
|
-
type: :runtime
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '0.7'
|
69
55
|
- !ruby/object:Gem::Dependency
|
70
56
|
name: bundler
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|