gamerom 0.5.0 → 0.6.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/.github/workflows/main.yml +5 -7
- data/.rubocop.yml +5 -0
- data/.ruby-version +1 -1
- data/.tool-versions +1 -1
- data/CHANGELOG.md +9 -1
- data/Dockerfile +1 -1
- data/Gemfile +4 -4
- data/Gemfile.lock +60 -54
- data/README.md +75 -7
- data/gamerom.gemspec +3 -3
- data/lib/gamerom/cli.rb +121 -21
- data/lib/gamerom/errors.rb +9 -0
- data/lib/gamerom/game.rb +4 -2
- data/lib/gamerom/repo_adapter.rb +5 -1
- data/lib/gamerom/repo_adapters/coolrom.rb +1 -0
- data/lib/gamerom/repo_adapters/edgeemu.rb +136 -0
- data/lib/gamerom/repo_adapters/vimm.rb +12 -36
- data/lib/gamerom/version.rb +1 -1
- data/lib/gamerom.rb +1 -4
- data/lib/mechanizeprogress.rb +5 -1
- metadata +11 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 33c71545b14feb811985d98d9e1e4677b7101f7e86676865c50770eb53b99169
|
|
4
|
+
data.tar.gz: 3388785345996bdb7711c90150ad03cc8bc3cf08afaad281144690ce8da85144
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '0694ea12b96bac2fb769f0176ca0b459804eb1b955c51c44fb57dc60046d63136836a0b206c696fb6cbee9096c211d475cf038a9dc14c4a2ff43b232af3cd87d'
|
|
7
|
+
data.tar.gz: ff44e316119690d3732f629ff162af18feef6ccb512881063625b899782adf4d95100c9a49829e619f09c82ce4fb944bd793490d0358c0cc3bbbb36158d06603
|
data/.github/workflows/main.yml
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
name: Ruby
|
|
2
2
|
|
|
3
|
-
on: [push,pull_request]
|
|
3
|
+
on: [push, pull_request]
|
|
4
4
|
|
|
5
5
|
jobs:
|
|
6
6
|
build:
|
|
7
7
|
runs-on: ubuntu-latest
|
|
8
8
|
steps:
|
|
9
|
-
- uses: actions/checkout@
|
|
9
|
+
- uses: actions/checkout@v7
|
|
10
10
|
- name: Set up Ruby
|
|
11
11
|
uses: ruby/setup-ruby@v1
|
|
12
12
|
with:
|
|
13
|
-
ruby-version:
|
|
13
|
+
ruby-version: .ruby-version
|
|
14
|
+
bundler-cache: true
|
|
14
15
|
- name: Run the default task
|
|
15
|
-
run:
|
|
16
|
-
gem install bundler -v 2.6.2
|
|
17
|
-
bundle install
|
|
18
|
-
bundle exec rake
|
|
16
|
+
run: bundle exec rake
|
data/.rubocop.yml
CHANGED
|
@@ -42,6 +42,11 @@ Style/SoleNestedConditional:
|
|
|
42
42
|
Exclude:
|
|
43
43
|
- 'lib/mechanizeprogress.rb'
|
|
44
44
|
|
|
45
|
+
# mechanizeprogress.rb monkeypatches two existing classes on purpose
|
|
46
|
+
Style/OneClassPerFile:
|
|
47
|
+
Exclude:
|
|
48
|
+
- 'lib/mechanizeprogress.rb'
|
|
49
|
+
|
|
45
50
|
plugins:
|
|
46
51
|
- rubocop-rake
|
|
47
52
|
- rubocop-rspec
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
ruby-3.4.
|
|
1
|
+
ruby-3.4.12
|
data/.tool-versions
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
ruby 3.4.
|
|
1
|
+
ruby 3.4.12
|
data/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.6.0] - 2026-11-01
|
|
10
|
+
- feat: add edgeemu repo (https://edgeemu.net), 48 platforms
|
|
11
|
+
- feat: recover - do not claim files that belong to a game with a longer name (e.g. "Kung-Fu" vs "Kung-Fu Master")
|
|
12
|
+
- feat: use ruby 3.4.12 and update all dependencies
|
|
13
|
+
- fix: install_all - Ctrl-C stops the loop again
|
|
14
|
+
- feat: vimm repo - the site now blocks automated downloads, so install shows the game page URL and the target directory for a manual download; database, search and recover keep working
|
|
15
|
+
|
|
9
16
|
## [0.5.0] - 2025-03-25
|
|
10
17
|
- feat: add ps3 platform for coolrom repo
|
|
11
18
|
- feat: add new platforms for vimm repo (Sega 32X, Atari 2600, Atari 5200, Atari 7800, Game Gear, Lynx, Sega CD, Master System, TurboGrafx-16, TurboGrafx-CD, Virtual Boy, XBox, XBox 360)
|
|
@@ -46,7 +53,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
46
53
|
## [0.1.0] - 2021-05-07
|
|
47
54
|
- Initial release
|
|
48
55
|
|
|
49
|
-
[Unreleased]: https://github.com/lucasmundim/gamerom/compare/v0.
|
|
56
|
+
[Unreleased]: https://github.com/lucasmundim/gamerom/compare/v0.6.0...HEAD
|
|
57
|
+
[0.6.0]: https://github.com/lucasmundim/gamerom/compare/v0.5.0...v0.6.0
|
|
50
58
|
[0.5.0]: https://github.com/lucasmundim/gamerom/compare/v0.4.1...v0.5.0
|
|
51
59
|
[0.4.1]: https://github.com/lucasmundim/gamerom/compare/v0.4.0...v0.4.1
|
|
52
60
|
[0.4.0]: https://github.com/lucasmundim/gamerom/compare/v0.3.0...v0.4.0
|
data/Dockerfile
CHANGED
data/Gemfile
CHANGED
|
@@ -5,10 +5,10 @@ source 'https://rubygems.org'
|
|
|
5
5
|
# Specify your gem's dependencies in gamerom.gemspec
|
|
6
6
|
gemspec
|
|
7
7
|
|
|
8
|
-
gem 'rake', '~> 13.2
|
|
8
|
+
gem 'rake', '~> 13.4.2'
|
|
9
9
|
|
|
10
|
-
gem 'rspec', '~> 3.13.
|
|
10
|
+
gem 'rspec', '~> 3.13.2'
|
|
11
11
|
|
|
12
|
-
gem 'rubocop', '~> 1.
|
|
12
|
+
gem 'rubocop', '~> 1.92.2'
|
|
13
13
|
gem 'rubocop-rake', '~> 0.7.1'
|
|
14
|
-
gem 'rubocop-rspec', '~> 3.
|
|
14
|
+
gem 'rubocop-rspec', '~> 3.10.2'
|
data/Gemfile.lock
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
gamerom (0.
|
|
5
|
-
mechanize (~> 2.14.
|
|
4
|
+
gamerom (0.6.0)
|
|
5
|
+
mechanize (~> 2.14.2)
|
|
6
6
|
mechanize-progressbar (~> 0.2.0)
|
|
7
|
-
nokogiri (~> 1.
|
|
7
|
+
nokogiri (~> 1.19.4)
|
|
8
8
|
progressbar (~> 1.13.0)
|
|
9
9
|
rest-client (~> 2.1.0)
|
|
10
|
-
thor (~> 1.
|
|
10
|
+
thor (~> 1.5.0)
|
|
11
11
|
|
|
12
12
|
GEM
|
|
13
13
|
remote: https://rubygems.org/
|
|
14
14
|
specs:
|
|
15
|
-
addressable (2.
|
|
16
|
-
public_suffix (>= 2.0.2, <
|
|
15
|
+
addressable (2.9.2)
|
|
16
|
+
public_suffix (>= 2.0.2, < 8.0)
|
|
17
17
|
ast (2.4.3)
|
|
18
|
-
base64 (0.
|
|
19
|
-
connection_pool (
|
|
20
|
-
diff-lcs (1.6.
|
|
21
|
-
domain_name (0.
|
|
18
|
+
base64 (0.3.0)
|
|
19
|
+
connection_pool (3.0.2)
|
|
20
|
+
diff-lcs (1.6.2)
|
|
21
|
+
domain_name (0.7.20261007)
|
|
22
22
|
http-accept (1.7.0)
|
|
23
|
-
http-cookie (1.
|
|
23
|
+
http-cookie (1.1.6)
|
|
24
24
|
domain_name (~> 0.5)
|
|
25
|
-
json (
|
|
26
|
-
language_server-protocol (3.17.0.
|
|
25
|
+
json (3.1.0)
|
|
26
|
+
language_server-protocol (3.17.0.6)
|
|
27
27
|
lint_roller (1.1.0)
|
|
28
|
-
logger (1.
|
|
29
|
-
mechanize (2.14.
|
|
28
|
+
logger (1.7.0)
|
|
29
|
+
mechanize (2.14.2)
|
|
30
30
|
addressable (~> 2.8)
|
|
31
31
|
base64
|
|
32
32
|
domain_name (~> 0.5, >= 0.5.20190701)
|
|
@@ -42,93 +42,99 @@ GEM
|
|
|
42
42
|
mechanize-progressbar (0.2.0)
|
|
43
43
|
mechanize (>= 1.0.0)
|
|
44
44
|
progressbar (>= 0.9.0)
|
|
45
|
-
mime-types (3.
|
|
45
|
+
mime-types (3.7.0)
|
|
46
46
|
logger
|
|
47
|
-
mime-types-data (~> 3.
|
|
48
|
-
mime-types-data (3.
|
|
47
|
+
mime-types-data (~> 3.2025, >= 3.2025.0507)
|
|
48
|
+
mime-types-data (3.2026.1027)
|
|
49
49
|
net-http-digest_auth (1.4.1)
|
|
50
|
-
net-http-persistent (4.0.
|
|
51
|
-
connection_pool (
|
|
50
|
+
net-http-persistent (4.0.8)
|
|
51
|
+
connection_pool (>= 2.2.4, < 4)
|
|
52
52
|
netrc (0.11.0)
|
|
53
|
-
nkf (0.
|
|
54
|
-
nokogiri (1.
|
|
53
|
+
nkf (0.3.0)
|
|
54
|
+
nokogiri (1.19.4-aarch64-linux-musl)
|
|
55
55
|
racc (~> 1.4)
|
|
56
|
-
nokogiri (1.
|
|
56
|
+
nokogiri (1.19.4-arm64-darwin)
|
|
57
57
|
racc (~> 1.4)
|
|
58
|
-
nokogiri (1.
|
|
58
|
+
nokogiri (1.19.4-x86_64-darwin)
|
|
59
59
|
racc (~> 1.4)
|
|
60
|
-
nokogiri (1.
|
|
60
|
+
nokogiri (1.19.4-x86_64-linux-gnu)
|
|
61
61
|
racc (~> 1.4)
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
nokogiri (1.19.4-x86_64-linux-musl)
|
|
63
|
+
racc (~> 1.4)
|
|
64
|
+
parallel (2.3.0)
|
|
65
|
+
parser (3.3.13.0)
|
|
64
66
|
ast (~> 2.4.1)
|
|
65
67
|
racc
|
|
68
|
+
prism (1.9.0)
|
|
66
69
|
progressbar (1.13.0)
|
|
67
|
-
public_suffix (
|
|
70
|
+
public_suffix (7.0.5)
|
|
68
71
|
racc (1.8.1)
|
|
69
72
|
rainbow (3.1.1)
|
|
70
|
-
rake (13.2
|
|
71
|
-
regexp_parser (2.
|
|
73
|
+
rake (13.4.2)
|
|
74
|
+
regexp_parser (2.13.1)
|
|
72
75
|
rest-client (2.1.0)
|
|
73
76
|
http-accept (>= 1.7.0, < 2.0)
|
|
74
77
|
http-cookie (>= 1.0.2, < 2.0)
|
|
75
78
|
mime-types (>= 1.16, < 4.0)
|
|
76
79
|
netrc (~> 0.8)
|
|
77
|
-
rspec (3.13.
|
|
80
|
+
rspec (3.13.2)
|
|
78
81
|
rspec-core (~> 3.13.0)
|
|
79
82
|
rspec-expectations (~> 3.13.0)
|
|
80
83
|
rspec-mocks (~> 3.13.0)
|
|
81
|
-
rspec-core (3.13.
|
|
84
|
+
rspec-core (3.13.6)
|
|
82
85
|
rspec-support (~> 3.13.0)
|
|
83
|
-
rspec-expectations (3.13.
|
|
86
|
+
rspec-expectations (3.13.5)
|
|
84
87
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
85
88
|
rspec-support (~> 3.13.0)
|
|
86
|
-
rspec-mocks (3.13.
|
|
89
|
+
rspec-mocks (3.13.8)
|
|
87
90
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
88
91
|
rspec-support (~> 3.13.0)
|
|
89
|
-
rspec-support (3.13.
|
|
90
|
-
rubocop (1.
|
|
91
|
-
json (
|
|
92
|
+
rspec-support (3.13.7)
|
|
93
|
+
rubocop (1.92.2)
|
|
94
|
+
json (>= 2.3)
|
|
92
95
|
language_server-protocol (~> 3.17.0.2)
|
|
93
96
|
lint_roller (~> 1.1.0)
|
|
94
|
-
parallel (
|
|
97
|
+
parallel (>= 1.10)
|
|
95
98
|
parser (>= 3.3.0.2)
|
|
96
99
|
rainbow (>= 2.2.2, < 4.0)
|
|
97
|
-
regexp_parser (>= 2.
|
|
98
|
-
rubocop-ast (>= 1.
|
|
100
|
+
regexp_parser (>= 2.11.3, < 3.0)
|
|
101
|
+
rubocop-ast (>= 1.49.0, < 2.0)
|
|
99
102
|
ruby-progressbar (~> 1.7)
|
|
100
103
|
unicode-display_width (>= 2.4.0, < 4.0)
|
|
101
|
-
rubocop-ast (1.
|
|
104
|
+
rubocop-ast (1.50.0)
|
|
102
105
|
parser (>= 3.3.7.2)
|
|
106
|
+
prism (~> 1.7)
|
|
103
107
|
rubocop-rake (0.7.1)
|
|
104
108
|
lint_roller (~> 1.1)
|
|
105
109
|
rubocop (>= 1.72.1)
|
|
106
|
-
rubocop-rspec (3.
|
|
110
|
+
rubocop-rspec (3.10.2)
|
|
107
111
|
lint_roller (~> 1.1)
|
|
108
|
-
|
|
112
|
+
regexp_parser (>= 2.0)
|
|
113
|
+
rubocop (~> 1.86, >= 1.86.2)
|
|
109
114
|
ruby-progressbar (1.13.0)
|
|
110
|
-
rubyntlm (0.6.
|
|
115
|
+
rubyntlm (0.6.8)
|
|
111
116
|
base64
|
|
112
|
-
thor (1.
|
|
113
|
-
unicode-display_width (3.
|
|
114
|
-
unicode-emoji (~> 4.
|
|
115
|
-
unicode-emoji (4.0
|
|
116
|
-
webrick (1.9.
|
|
117
|
+
thor (1.5.0)
|
|
118
|
+
unicode-display_width (3.3.0)
|
|
119
|
+
unicode-emoji (~> 4.3)
|
|
120
|
+
unicode-emoji (4.3.0)
|
|
121
|
+
webrick (1.9.2)
|
|
117
122
|
webrobots (0.1.2)
|
|
118
123
|
|
|
119
124
|
PLATFORMS
|
|
120
125
|
aarch64-linux-musl
|
|
121
126
|
arm64-darwin-24
|
|
122
127
|
x86_64-darwin-20
|
|
128
|
+
x86_64-linux
|
|
123
129
|
x86_64-linux-musl
|
|
124
130
|
|
|
125
131
|
DEPENDENCIES
|
|
126
132
|
gamerom!
|
|
127
|
-
rake (~> 13.2
|
|
128
|
-
rspec (~> 3.13.
|
|
129
|
-
rubocop (~> 1.
|
|
133
|
+
rake (~> 13.4.2)
|
|
134
|
+
rspec (~> 3.13.2)
|
|
135
|
+
rubocop (~> 1.92.2)
|
|
130
136
|
rubocop-rake (~> 0.7.1)
|
|
131
|
-
rubocop-rspec (~> 3.
|
|
137
|
+
rubocop-rspec (~> 3.10.2)
|
|
132
138
|
|
|
133
139
|
BUNDLED WITH
|
|
134
|
-
2.6.
|
|
140
|
+
2.6.9
|
data/README.md
CHANGED
|
@@ -4,8 +4,9 @@ A command-line installer for game ROMs from many repositories.
|
|
|
4
4
|
|
|
5
5
|
It currently supports the following repositories:
|
|
6
6
|
|
|
7
|
-
- https://vimm.net
|
|
8
7
|
- https://coolrom.com.au
|
|
8
|
+
- https://edgeemu.net
|
|
9
|
+
- https://vimm.net (search and database only: downloads must be done manually, see `install` below)
|
|
9
10
|
|
|
10
11
|
## Installation
|
|
11
12
|
|
|
@@ -14,7 +15,7 @@ It currently supports the following repositories:
|
|
|
14
15
|
Add this to your .bashrc, .bash_aliases, etc:
|
|
15
16
|
|
|
16
17
|
```
|
|
17
|
-
alias gamerom="docker run -e UID=$(id -u) -e GROUP_ID=$(id -g) --rm -it -v ~/.gamerom:/home/runuser/.gamerom --platform=linux/amd64 docker.io/lucasmundim/gamerom:0.
|
|
18
|
+
alias gamerom="docker run -e UID=$(id -u) -e GROUP_ID=$(id -g) --rm -it -v ~/.gamerom:/home/runuser/.gamerom --platform=linux/amd64 docker.io/lucasmundim/gamerom:0.6.0"
|
|
18
19
|
```
|
|
19
20
|
|
|
20
21
|
Use it as:
|
|
@@ -85,6 +86,7 @@ List available repo
|
|
|
85
86
|
$ gamerom repo
|
|
86
87
|
listing available repo...
|
|
87
88
|
coolrom
|
|
89
|
+
edgeemu
|
|
88
90
|
vimm
|
|
89
91
|
```
|
|
90
92
|
|
|
@@ -122,6 +124,61 @@ listing available platforms for coolrom repo...
|
|
|
122
124
|
psp: Sony Playstation Portable
|
|
123
125
|
```
|
|
124
126
|
|
|
127
|
+
```
|
|
128
|
+
$ gamerom platform -r edgeemu
|
|
129
|
+
listing available platforms for edgeemu repo...
|
|
130
|
+
---
|
|
131
|
+
:platforms:
|
|
132
|
+
atari-2600: Atari 2600
|
|
133
|
+
atari-5200: Atari 5200
|
|
134
|
+
atari-7800: Atari 7800
|
|
135
|
+
atari-jaguar: Atari Jaguar
|
|
136
|
+
atari-jaguar-cd: Atari Jaguar CD
|
|
137
|
+
atari-lynx: Atari Lynx
|
|
138
|
+
atari-st: Atari ST
|
|
139
|
+
bandai-wonderswan: Bandai WonderSwan
|
|
140
|
+
colecovision: Coleco ColecoVision
|
|
141
|
+
commodore-64: Commodore 64
|
|
142
|
+
commodore-amiga: Commodore Amiga
|
|
143
|
+
commodore-amiga-cd: Commodore Amiga CD
|
|
144
|
+
commodore-amiga-cd32: Commodore Amiga CD32
|
|
145
|
+
commodore-plus-4: Commodore Plus-4
|
|
146
|
+
commodore-vic-20: Commodore VIC-20
|
|
147
|
+
fairchild-channel-f: Fairchild Channel F
|
|
148
|
+
gce-vectrex: GCE Vectrex
|
|
149
|
+
microsoft-msx: Microsoft MSX / MSX2
|
|
150
|
+
nec-pc-engine-cd-turbografx-cd: NEC PC Engine CD / TurboGrafx CD
|
|
151
|
+
nec-pc-engine-supergrafx: NEC PC Engine SuperGrafx
|
|
152
|
+
nec-pc-engine-turbografx-16: NEC PC Engine / TurboGrafx 16
|
|
153
|
+
nintendo-64: Nintendo 64
|
|
154
|
+
nintendo-ds: Nintendo DS
|
|
155
|
+
nintendo-fds: Nintendo Famicom Disk System (FDS)
|
|
156
|
+
nintendo-gameboy: Nintendo Game Boy
|
|
157
|
+
nintendo-gameboy-advance: Nintendo Game Boy Advance
|
|
158
|
+
nintendo-gameboy-color: Nintendo Game Boy Color
|
|
159
|
+
nintendo-gamecube: Nintendo Gamecube
|
|
160
|
+
nintendo-nes: Nintendo Entertainment System (NES)
|
|
161
|
+
nintendo-satellaview: Nintendo Satellaview
|
|
162
|
+
nintendo-snes: Super NES (SNES)
|
|
163
|
+
nintendo-virtualboy: Nintendo Virtual Boy
|
|
164
|
+
panasonic-3do: Panasonic 3DO
|
|
165
|
+
philips-cdi: Philips CDi
|
|
166
|
+
rca-studioii: RCA Studio II
|
|
167
|
+
sega-32x: Sega 32X
|
|
168
|
+
sega-cd: Sega Mega-CD / Sega CD
|
|
169
|
+
sega-dreamcast: Sega Dreamcast
|
|
170
|
+
sega-gamegear: Sega Game Gear
|
|
171
|
+
sega-genesis: Sega Mega Drive / Genesis
|
|
172
|
+
sega-pico: Sega PICO
|
|
173
|
+
sega-saturn: Sega Saturn
|
|
174
|
+
sega-sg1000: Sega SG-1000
|
|
175
|
+
sega-sms: Sega Master System / Mark III
|
|
176
|
+
sinclair-zx-spectrum-3: Sinclair ZX Spectrum +3
|
|
177
|
+
snk-neo-geo-cd: SNK Neo Geo CD
|
|
178
|
+
snk-ngpc: SNK Neo Geo Pocket Color
|
|
179
|
+
watara-supervision: Watara Supervision
|
|
180
|
+
```
|
|
181
|
+
|
|
125
182
|
```
|
|
126
183
|
$ gamerom platform -r vimm
|
|
127
184
|
listing available platforms for vimm repo...
|
|
@@ -211,13 +268,24 @@ USA
|
|
|
211
268
|
|
|
212
269
|
Install game GAME_IDENTIFIER (id/name)
|
|
213
270
|
|
|
271
|
+
```
|
|
272
|
+
$ gamerom install -r edgeemu -p rca-studioii 'Pinball (Europe)'
|
|
273
|
+
installing game 2675927342 - Pinball (Europe) - Europe on rca-studioii platform on edgeemu repo...
|
|
274
|
+
100% |ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo| 1.1KB 12.3KB/s Time: 00:00:00
|
|
275
|
+
Downloaded: Pinball (Europe).zip
|
|
276
|
+
Game installed
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
The vimm repo does not allow automated downloads, so `install` tells you where to
|
|
280
|
+
download the game and where to save it. Run `recover` afterwards to register it:
|
|
281
|
+
|
|
214
282
|
```
|
|
215
283
|
$ gamerom install -r vimm -p NES 'Mega Man'
|
|
216
284
|
installing game 545 - Mega Man - USA on NES platform on vimm repo...
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
285
|
+
vimm.net does not allow automated downloads.
|
|
286
|
+
Download the game from https://vimm.net/vault/545 in your browser and save it to:
|
|
287
|
+
/home/user/.gamerom/games/vimm/NES/USA/
|
|
288
|
+
Then run `gamerom recover -r vimm -p NES` to register it.
|
|
221
289
|
```
|
|
222
290
|
|
|
223
291
|
### install_all
|
|
@@ -550,7 +618,7 @@ Print program version
|
|
|
550
618
|
|
|
551
619
|
```
|
|
552
620
|
$ gamerom version
|
|
553
|
-
0.
|
|
621
|
+
0.6.0
|
|
554
622
|
```
|
|
555
623
|
|
|
556
624
|
## Development
|
data/gamerom.gemspec
CHANGED
|
@@ -30,12 +30,12 @@ Gem::Specification.new do |spec|
|
|
|
30
30
|
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
31
31
|
spec.require_paths = ['lib']
|
|
32
32
|
|
|
33
|
-
spec.add_dependency 'mechanize', '~> 2.14.
|
|
33
|
+
spec.add_dependency 'mechanize', '~> 2.14.2'
|
|
34
34
|
spec.add_dependency 'mechanize-progressbar', '~> 0.2.0'
|
|
35
|
-
spec.add_dependency 'nokogiri', '~> 1.
|
|
35
|
+
spec.add_dependency 'nokogiri', '~> 1.19.4'
|
|
36
36
|
spec.add_dependency 'progressbar', '~> 1.13.0'
|
|
37
37
|
spec.add_dependency 'rest-client', '~> 2.1.0'
|
|
38
|
-
spec.add_dependency 'thor', '~> 1.
|
|
38
|
+
spec.add_dependency 'thor', '~> 1.5.0'
|
|
39
39
|
|
|
40
40
|
# For more information and examples about making a new gem, checkout our
|
|
41
41
|
# guide at: https://bundler.io/guides/creating_gem.html
|
data/lib/gamerom/cli.rb
CHANGED
|
@@ -61,6 +61,8 @@ module Gamerom
|
|
|
61
61
|
end
|
|
62
62
|
game.install
|
|
63
63
|
shell.say 'Game installed', :green
|
|
64
|
+
rescue Gamerom::ManualDownloadRequired => e
|
|
65
|
+
shell.say e.message, :yellow
|
|
64
66
|
rescue StandardError => e
|
|
65
67
|
render_error e, options
|
|
66
68
|
exit 1
|
|
@@ -75,7 +77,13 @@ module Gamerom
|
|
|
75
77
|
validate_platform repo, options[:platform]
|
|
76
78
|
games = repo.games options[:platform], region: options[:region]
|
|
77
79
|
games.each do |game|
|
|
78
|
-
|
|
80
|
+
if game.installed?
|
|
81
|
+
shell.say "Game #{game.name} already installed", :yellow
|
|
82
|
+
next
|
|
83
|
+
end
|
|
84
|
+
install(game.id)
|
|
85
|
+
rescue StandardError, SystemExit => e
|
|
86
|
+
shell.say "Error installing game #{game.name}: #{e.message}", :red
|
|
79
87
|
end
|
|
80
88
|
rescue StandardError => e
|
|
81
89
|
render_error e, options
|
|
@@ -116,28 +124,12 @@ module Gamerom
|
|
|
116
124
|
validate_platform repo, options[:platform]
|
|
117
125
|
puts "recovering state of roms for #{options[:platform]} platform on #{options[:repo]} repo..."
|
|
118
126
|
games = repo.games options[:platform]
|
|
119
|
-
|
|
120
|
-
games.
|
|
121
|
-
filename = nil
|
|
122
|
-
basename = "#{Gamerom::GAME_DIR}/#{repo.name}/#{options[:platform]}/#{game[:region]}/#{game[:name]}"
|
|
123
|
-
%w[zip 7z rar].each do |ext|
|
|
124
|
-
fullname = "#{basename}.#{ext}"
|
|
125
|
-
filename = fullname if File.exist? fullname
|
|
126
|
-
end
|
|
127
|
+
game_names = games.to_h { |game| [game.id, game.name] }
|
|
128
|
+
results = games.group_by { |game| recover_game(game, game_names) }
|
|
127
129
|
|
|
128
|
-
|
|
129
|
-
game.update_state File.basename(filename)
|
|
130
|
-
puts "Found game #{game[:name]}"
|
|
131
|
-
else
|
|
132
|
-
games_not_found << game[:name]
|
|
133
|
-
end
|
|
134
|
-
end
|
|
135
|
-
if games_not_found.count.positive?
|
|
136
|
-
puts 'Games not found:'
|
|
137
|
-
puts games_not_found
|
|
138
|
-
end
|
|
130
|
+
print_recover_summary(results.fetch(:found, []), results.fetch(:already_installed, []), results.fetch(:not_found, []))
|
|
139
131
|
rescue StandardError => e
|
|
140
|
-
|
|
132
|
+
render_error e, options
|
|
141
133
|
exit 1
|
|
142
134
|
end
|
|
143
135
|
|
|
@@ -332,5 +324,113 @@ module Gamerom
|
|
|
332
324
|
|
|
333
325
|
raise "Expected '--platform' to be one of #{repo.platforms.keys.join(", ")}; got #{platform}"
|
|
334
326
|
end
|
|
327
|
+
|
|
328
|
+
# Recover helpers
|
|
329
|
+
|
|
330
|
+
def recover_game(game, game_names)
|
|
331
|
+
puts
|
|
332
|
+
puts "Checking game #{game}"
|
|
333
|
+
if game.filenames.any?
|
|
334
|
+
puts "#{shell.set_color("*", :green)} Found game at: #{game.filenames.first}"
|
|
335
|
+
return :already_installed
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
game_files = glob_game_files(game).select { |file| file_belongs_to_game?(file, game, game_names) }.sort
|
|
339
|
+
if game_files.empty?
|
|
340
|
+
puts "#{shell.set_color("*", :red)} not found"
|
|
341
|
+
return :not_found
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
game.update_state(game_files.map { |file| File.basename(file) })
|
|
345
|
+
print_recovered_files(game_files)
|
|
346
|
+
:found
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
def glob_game_files(game)
|
|
350
|
+
patterns = [
|
|
351
|
+
glob_escape(game.name.tr(' ', '_'), '_'),
|
|
352
|
+
glob_escape(game.name, ' ')
|
|
353
|
+
]
|
|
354
|
+
patterns.flat_map { |pattern| Dir.glob("#{game.filepath}/#{pattern}*") }.uniq
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
def glob_escape(str, spacer)
|
|
358
|
+
str
|
|
359
|
+
.gsub(/([\\\[\]*?{}) ,])/, '\\\\\1')
|
|
360
|
+
.gsub(':', "#{spacer}-")
|
|
361
|
+
.gsub('!', '\!*')
|
|
362
|
+
.gsub('(', '*\(')
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
# A globbed file is kept for a game unless it is a better match for another
|
|
366
|
+
# game whose name starts with this game's name (e.g. "Kung-Fu" vs "Kung-Fu Master").
|
|
367
|
+
def file_belongs_to_game?(file, game, game_names)
|
|
368
|
+
filename = File.basename(file).downcase
|
|
369
|
+
return true if exact_filename_match?(filename, game.name.downcase)
|
|
370
|
+
|
|
371
|
+
number = sequel_number(game.name)
|
|
372
|
+
return true if number && filename.include?(number)
|
|
373
|
+
return true if game.name.include?('Limited Run Games') && filename.include?('limited_run')
|
|
374
|
+
|
|
375
|
+
!claimed_by_other_game?(filename, game, game_names)
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
# "Game.zip", "Game_Name.zip" or "Game (USA).zip"
|
|
379
|
+
def exact_filename_match?(filename, name)
|
|
380
|
+
[name, name.tr(' ', '_')].any? do |variant|
|
|
381
|
+
filename.match?(/\A#{Regexp.escape(variant)}(\s*\(\w+\))?\.\w+\z/i)
|
|
382
|
+
end
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
# The number that identifies a sequel, e.g. "2" in "Tony Hawk's Pro Skater 2"
|
|
386
|
+
def sequel_number(name)
|
|
387
|
+
match = name.match(/(\d+|\s+\d+)[\s':]/) || name.match(/\s(\d+)$/)
|
|
388
|
+
match && match[1].strip
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
def claimed_by_other_game?(filename, game, game_names)
|
|
392
|
+
name = game.name.downcase
|
|
393
|
+
game_names.any? do |other_id, other_name|
|
|
394
|
+
next false if other_id == game.id
|
|
395
|
+
|
|
396
|
+
other = other_name.downcase
|
|
397
|
+
next false unless other.length > name.length && other.start_with?(name)
|
|
398
|
+
|
|
399
|
+
filename_matches_other_game?(filename, other_name)
|
|
400
|
+
end
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
def filename_matches_other_game?(filename, other_name)
|
|
404
|
+
other = other_name.downcase
|
|
405
|
+
other_underscored = other.tr(' ', '_')
|
|
406
|
+
return false unless filename.include?(other_underscored) || filename.include?(other)
|
|
407
|
+
|
|
408
|
+
number = sequel_number(other_name)
|
|
409
|
+
return filename.include?(number) if number
|
|
410
|
+
|
|
411
|
+
filename.start_with?(other_underscored) ||
|
|
412
|
+
filename.start_with?(other) ||
|
|
413
|
+
filename.include?(other_underscored.tr(':', '_')) ||
|
|
414
|
+
filename.include?(other.tr(':', '-'))
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
def print_recovered_files(game_files)
|
|
418
|
+
if game_files.size > 1
|
|
419
|
+
puts "#{shell.set_color("*", :green)} Found #{game_files.size} disks for game:"
|
|
420
|
+
game_files.each { |file| puts " - #{file}" }
|
|
421
|
+
else
|
|
422
|
+
puts "#{shell.set_color("*", :green)} Found game at: #{game_files.first}"
|
|
423
|
+
end
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
def print_recover_summary(games_found, games_already_installed, games_not_found)
|
|
427
|
+
if games_not_found.empty?
|
|
428
|
+
puts "All #{games_found.count + games_already_installed.count} games found"
|
|
429
|
+
else
|
|
430
|
+
puts "#{shell.set_color(games_found.count, :green)} games found"
|
|
431
|
+
puts "#{shell.set_color(games_already_installed.count, :yellow)} games already installed"
|
|
432
|
+
puts "#{shell.set_color(games_not_found.count, :red)} games not found"
|
|
433
|
+
end
|
|
434
|
+
end
|
|
335
435
|
end
|
|
336
436
|
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Gamerom
|
|
4
|
+
class Error < StandardError; end
|
|
5
|
+
|
|
6
|
+
# Raised by repo adapters whose site does not allow automated downloads.
|
|
7
|
+
# The message tells the user where to download the game and where to save it.
|
|
8
|
+
class ManualDownloadRequired < Error; end
|
|
9
|
+
end
|
data/lib/gamerom/game.rb
CHANGED
|
@@ -6,7 +6,7 @@ require 'yaml'
|
|
|
6
6
|
module Gamerom
|
|
7
7
|
# Game - Represents a game ROM
|
|
8
8
|
class Game
|
|
9
|
-
attr_accessor :id, :name, :platform, :region, :repo, :tags
|
|
9
|
+
attr_accessor :id, :name, :platform, :region, :repo, :tags, :url
|
|
10
10
|
|
|
11
11
|
def initialize(attributes = {})
|
|
12
12
|
@tags = []
|
|
@@ -16,7 +16,9 @@ module Gamerom
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def filenames
|
|
19
|
-
|
|
19
|
+
return [] unless File.exist? state_filename
|
|
20
|
+
|
|
21
|
+
Array(YAML.load_file(state_filename)).map do |filename|
|
|
20
22
|
"#{filepath}/#{filename}"
|
|
21
23
|
end
|
|
22
24
|
end
|
data/lib/gamerom/repo_adapter.rb
CHANGED
|
@@ -12,11 +12,15 @@ module Gamerom
|
|
|
12
12
|
|
|
13
13
|
def games(platform)
|
|
14
14
|
games = []
|
|
15
|
+
|
|
16
|
+
columns = `tput cols`.to_i
|
|
17
|
+
length = [120, columns].min
|
|
18
|
+
|
|
15
19
|
progress_bar = ProgressBar.create(
|
|
16
20
|
title: platform,
|
|
17
21
|
total: sections.count,
|
|
18
22
|
autofinish: true,
|
|
19
|
-
length:
|
|
23
|
+
length: length,
|
|
20
24
|
format: "%t: %b\e[0;93m\u{15E7}\e[0m%i %j%% %e",
|
|
21
25
|
progress_mark: ' ',
|
|
22
26
|
remainder_mark: "\e[0;34m\u{FF65}\e[0m"
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'mechanize'
|
|
4
|
+
require 'uri'
|
|
5
|
+
require 'mechanize/progressbar'
|
|
6
|
+
require 'mechanizeprogress'
|
|
7
|
+
|
|
8
|
+
module Gamerom
|
|
9
|
+
module RepoAdapters
|
|
10
|
+
# Edgeemu - An adapter for the Edge Emulation repository website
|
|
11
|
+
class Edgeemu
|
|
12
|
+
extend Gamerom::RepoAdapter
|
|
13
|
+
|
|
14
|
+
BASE_URL = 'https://edgeemu.net'
|
|
15
|
+
|
|
16
|
+
PLATFORM = {
|
|
17
|
+
'atari-2600' => 'Atari 2600',
|
|
18
|
+
'atari-5200' => 'Atari 5200',
|
|
19
|
+
'atari-7800' => 'Atari 7800',
|
|
20
|
+
'atari-jaguar' => 'Atari Jaguar',
|
|
21
|
+
'atari-jaguar-cd' => 'Atari Jaguar CD',
|
|
22
|
+
'atari-lynx' => 'Atari Lynx',
|
|
23
|
+
'atari-st' => 'Atari ST',
|
|
24
|
+
'bandai-wonderswan' => 'Bandai WonderSwan',
|
|
25
|
+
'colecovision' => 'Coleco ColecoVision',
|
|
26
|
+
'commodore-64' => 'Commodore 64',
|
|
27
|
+
'commodore-amiga' => 'Commodore Amiga',
|
|
28
|
+
'commodore-amiga-cd' => 'Commodore Amiga CD',
|
|
29
|
+
'commodore-amiga-cd32' => 'Commodore Amiga CD32',
|
|
30
|
+
'commodore-plus-4' => 'Commodore Plus-4',
|
|
31
|
+
'commodore-vic-20' => 'Commodore VIC-20',
|
|
32
|
+
'fairchild-channel-f' => 'Fairchild Channel F',
|
|
33
|
+
'gce-vectrex' => 'GCE Vectrex',
|
|
34
|
+
'microsoft-msx' => 'Microsoft MSX / MSX2',
|
|
35
|
+
'nec-pc-engine-cd-turbografx-cd' => 'NEC PC Engine CD / TurboGrafx CD',
|
|
36
|
+
'nec-pc-engine-supergrafx' => 'NEC PC Engine SuperGrafx',
|
|
37
|
+
'nec-pc-engine-turbografx-16' => 'NEC PC Engine / TurboGrafx 16',
|
|
38
|
+
'nintendo-64' => 'Nintendo 64',
|
|
39
|
+
'nintendo-ds' => 'Nintendo DS',
|
|
40
|
+
'nintendo-fds' => 'Nintendo Famicom Disk System (FDS)',
|
|
41
|
+
'nintendo-gameboy' => 'Nintendo Game Boy',
|
|
42
|
+
'nintendo-gameboy-advance' => 'Nintendo Game Boy Advance',
|
|
43
|
+
'nintendo-gameboy-color' => 'Nintendo Game Boy Color',
|
|
44
|
+
'nintendo-gamecube' => 'Nintendo Gamecube',
|
|
45
|
+
'nintendo-nes' => 'Nintendo Entertainment System (NES)',
|
|
46
|
+
'nintendo-satellaview' => 'Nintendo Satellaview',
|
|
47
|
+
'nintendo-snes' => 'Super NES (SNES)',
|
|
48
|
+
'nintendo-virtualboy' => 'Nintendo Virtual Boy',
|
|
49
|
+
'panasonic-3do' => 'Panasonic 3DO',
|
|
50
|
+
'philips-cdi' => 'Philips CDi',
|
|
51
|
+
'rca-studioii' => 'RCA Studio II',
|
|
52
|
+
'sega-32x' => 'Sega 32X',
|
|
53
|
+
'sega-cd' => 'Sega Mega-CD / Sega CD',
|
|
54
|
+
'sega-dreamcast' => 'Sega Dreamcast',
|
|
55
|
+
'sega-gamegear' => 'Sega Game Gear',
|
|
56
|
+
'sega-genesis' => 'Sega Mega Drive / Genesis',
|
|
57
|
+
'sega-pico' => 'Sega PICO',
|
|
58
|
+
'sega-saturn' => 'Sega Saturn',
|
|
59
|
+
'sega-sg1000' => 'Sega SG-1000',
|
|
60
|
+
'sega-sms' => 'Sega Master System / Mark III',
|
|
61
|
+
'sinclair-zx-spectrum-3' => 'Sinclair ZX Spectrum +3',
|
|
62
|
+
'snk-neo-geo-cd' => 'SNK Neo Geo CD',
|
|
63
|
+
'snk-ngpc' => 'SNK Neo Geo Pocket Color',
|
|
64
|
+
'watara-supervision' => 'Watara Supervision',
|
|
65
|
+
}.freeze
|
|
66
|
+
|
|
67
|
+
# No-Intro region tags, as they appear in parentheses in the file names
|
|
68
|
+
REGIONS = [
|
|
69
|
+
'World', 'USA', 'Europe', 'Japan', 'Asia', 'Australia', 'Brazil', 'Canada', 'China', 'France',
|
|
70
|
+
'Germany', 'Greece', 'Hong Kong', 'Italy', 'Korea', 'Netherlands', 'Norway', 'Poland', 'Portugal',
|
|
71
|
+
'Russia', 'Scandinavia', 'Spain', 'Sweden', 'Taiwan', 'UK', 'Unknown', 'Latin America'
|
|
72
|
+
].freeze
|
|
73
|
+
|
|
74
|
+
def self.platforms
|
|
75
|
+
PLATFORM
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def self.sections
|
|
79
|
+
('a'..'z').to_a.unshift('1')
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def self.extract_games(platform)
|
|
83
|
+
sections.each_with_index do |section, index|
|
|
84
|
+
page = nokogiri_get("#{BASE_URL}/browse/#{platform}/#{section}")
|
|
85
|
+
yield page.css('div.item details').map { |item| game(item) }, index
|
|
86
|
+
rescue RestClient::NotFound
|
|
87
|
+
yield [], index
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Each item looks like:
|
|
92
|
+
# <details data-name="Espial (USA).zip">
|
|
93
|
+
# <summary>Espial (USA)</summary>
|
|
94
|
+
# <p><a href="/download/atari-2600/Espial%20%28USA%29.zip">download</a> ...</p>
|
|
95
|
+
# <p>hash: <span>931A0BDC</span></p>
|
|
96
|
+
# </details>
|
|
97
|
+
# The hash is the CRC32 of the ROM, which is used as the game id.
|
|
98
|
+
def self.game(item)
|
|
99
|
+
name = item.at_css('summary').text.strip
|
|
100
|
+
{
|
|
101
|
+
id: item.css('p').find { |p| p.text.start_with?('hash') }.at_css('span').text.strip.to_i(16),
|
|
102
|
+
name: name,
|
|
103
|
+
region: region(name),
|
|
104
|
+
url: "#{BASE_URL}#{item.at_css('a[href^="/download/"]')["href"]}",
|
|
105
|
+
}
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# "Espial (USA)" => "USA", "Game (USA, Europe) (Proto)" => "USA, Europe"
|
|
109
|
+
def self.region(name)
|
|
110
|
+
groups = name.scan(/\(([^)]+)\)/).flatten
|
|
111
|
+
groups.find { |group| REGIONS.include?(group.split(',').first.strip) } || 'Unknown'
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def self.install(game)
|
|
115
|
+
agent = Mechanize.new
|
|
116
|
+
agent.pluggable_parser.default = Mechanize::Download
|
|
117
|
+
agent.user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36'
|
|
118
|
+
|
|
119
|
+
response = nil
|
|
120
|
+
agent.progressbar do
|
|
121
|
+
response = agent.get(game.url)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
return unless response.code.to_i == 200
|
|
125
|
+
|
|
126
|
+
# The Content-Disposition header ends with a stray ";" that Mechanize cannot parse,
|
|
127
|
+
# so it falls back to the percent-encoded URL basename. Decode it instead.
|
|
128
|
+
filename = URI.decode_uri_component(File.basename(URI.parse(game.url).path))
|
|
129
|
+
FileUtils.mkdir_p(game.filepath)
|
|
130
|
+
response.save!("#{game.filepath}/#{filename}")
|
|
131
|
+
puts "Downloaded: #{filename}"
|
|
132
|
+
yield [filename]
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require '
|
|
4
|
-
require 'mechanize/progressbar'
|
|
5
|
-
require 'mechanizeprogress'
|
|
3
|
+
require 'fileutils'
|
|
6
4
|
|
|
7
5
|
module Gamerom
|
|
8
6
|
module RepoAdapters
|
|
@@ -69,42 +67,20 @@ module Gamerom
|
|
|
69
67
|
}
|
|
70
68
|
end
|
|
71
69
|
|
|
70
|
+
# Vimm's Lair protects game pages with a browser challenge, so games have to be
|
|
71
|
+
# downloaded by hand. Prepare the target directory and tell the user what to do.
|
|
72
72
|
def self.install(game)
|
|
73
73
|
FileUtils.mkdir_p(game.filepath)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
game_files = []
|
|
82
|
-
multiple_disks = page.css('#download_disc_number')
|
|
83
|
-
|
|
84
|
-
if multiple_disks.empty?
|
|
85
|
-
game_files << { id: form['mediaId'], name: 'single file rom' }
|
|
86
|
-
else
|
|
87
|
-
puts 'multiple discs detected'
|
|
88
|
-
game_files.concat(multiple_disks.children[1..-2].map { |disk| { name: disk.text, id: disk['value'] } })
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
game_files.each do |game_file|
|
|
92
|
-
puts "downloading #{game_file[:name]}"
|
|
93
|
-
form.method = 'GET'
|
|
94
|
-
button = form.button_with(type: 'submit')
|
|
95
|
-
response = nil
|
|
96
|
-
form['mediaId'] = game_file[:id]
|
|
97
|
-
agent.progressbar do
|
|
98
|
-
response = form.click_button(button)
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
break unless response.code.to_i == 200
|
|
74
|
+
raise Gamerom::ManualDownloadRequired, <<~MSG
|
|
75
|
+
vimm.net does not allow automated downloads.
|
|
76
|
+
Download the game from #{game_url(game)} in your browser and save it to:
|
|
77
|
+
#{game.filepath}/
|
|
78
|
+
Then run `gamerom recover -r vimm -p #{game.platform}` to register it.
|
|
79
|
+
MSG
|
|
80
|
+
end
|
|
102
81
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
filenames << filename
|
|
106
|
-
end
|
|
107
|
-
yield filenames
|
|
82
|
+
def self.game_url(game)
|
|
83
|
+
"https://vimm.net/vault/#{game.id}"
|
|
108
84
|
end
|
|
109
85
|
end
|
|
110
86
|
end
|
data/lib/gamerom/version.rb
CHANGED
data/lib/gamerom.rb
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative 'gamerom/errors'
|
|
3
4
|
require_relative 'gamerom/config'
|
|
4
5
|
require_relative 'gamerom/game'
|
|
5
6
|
require_relative 'gamerom/game_info'
|
|
6
7
|
require_relative 'gamerom/repo'
|
|
7
8
|
require_relative 'gamerom/cli'
|
|
8
9
|
require_relative 'gamerom/version'
|
|
9
|
-
|
|
10
|
-
module Gamerom
|
|
11
|
-
class Error < StandardError; end
|
|
12
|
-
end
|
data/lib/mechanizeprogress.rb
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
# Mechanize - A Monkeypatch for the mechanize progressbar
|
|
4
4
|
class Mechanize
|
|
5
5
|
include MechanizeProgressBarAPI # (1of7)a
|
|
6
|
+
|
|
6
7
|
class HTTP
|
|
7
8
|
# Agent - A Monkeypatch for the mechanize progressbar
|
|
8
9
|
class Agent
|
|
@@ -65,11 +66,14 @@ class MechanizeProgressBar
|
|
|
65
66
|
total = pbar_opts[:total] || filesize(response)
|
|
66
67
|
pbar_class = pbar_opts[:reversed] ? ReversedProgressBar : ProgressBar
|
|
67
68
|
|
|
69
|
+
columns = `tput cols`.to_i
|
|
70
|
+
length = [120, columns].min
|
|
71
|
+
|
|
68
72
|
pbar_class.create(
|
|
69
73
|
title: title,
|
|
70
74
|
total: total,
|
|
71
75
|
output: out,
|
|
72
|
-
length:
|
|
76
|
+
length: length,
|
|
73
77
|
format: format,
|
|
74
78
|
rate_scale: ->(rate) { rate / 1024 },
|
|
75
79
|
progress_mark: ' ',
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: gamerom
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Lucas Mundim
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: mechanize
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - "~>"
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 2.14.
|
|
18
|
+
version: 2.14.2
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - "~>"
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 2.14.
|
|
25
|
+
version: 2.14.2
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: mechanize-progressbar
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -43,14 +43,14 @@ dependencies:
|
|
|
43
43
|
requirements:
|
|
44
44
|
- - "~>"
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: 1.
|
|
46
|
+
version: 1.19.4
|
|
47
47
|
type: :runtime
|
|
48
48
|
prerelease: false
|
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
50
|
requirements:
|
|
51
51
|
- - "~>"
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: 1.
|
|
53
|
+
version: 1.19.4
|
|
54
54
|
- !ruby/object:Gem::Dependency
|
|
55
55
|
name: progressbar
|
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -85,14 +85,14 @@ dependencies:
|
|
|
85
85
|
requirements:
|
|
86
86
|
- - "~>"
|
|
87
87
|
- !ruby/object:Gem::Version
|
|
88
|
-
version: 1.
|
|
88
|
+
version: 1.5.0
|
|
89
89
|
type: :runtime
|
|
90
90
|
prerelease: false
|
|
91
91
|
version_requirements: !ruby/object:Gem::Requirement
|
|
92
92
|
requirements:
|
|
93
93
|
- - "~>"
|
|
94
94
|
- !ruby/object:Gem::Version
|
|
95
|
-
version: 1.
|
|
95
|
+
version: 1.5.0
|
|
96
96
|
description: A command-line installer for game ROMs from many repositories.
|
|
97
97
|
email:
|
|
98
98
|
- lucas.mundim@gmail.com
|
|
@@ -124,11 +124,13 @@ files:
|
|
|
124
124
|
- lib/gamerom.rb
|
|
125
125
|
- lib/gamerom/cli.rb
|
|
126
126
|
- lib/gamerom/config.rb
|
|
127
|
+
- lib/gamerom/errors.rb
|
|
127
128
|
- lib/gamerom/game.rb
|
|
128
129
|
- lib/gamerom/game_info.rb
|
|
129
130
|
- lib/gamerom/repo.rb
|
|
130
131
|
- lib/gamerom/repo_adapter.rb
|
|
131
132
|
- lib/gamerom/repo_adapters/coolrom.rb
|
|
133
|
+
- lib/gamerom/repo_adapters/edgeemu.rb
|
|
132
134
|
- lib/gamerom/repo_adapters/vimm.rb
|
|
133
135
|
- lib/gamerom/version.rb
|
|
134
136
|
- lib/mechanizeprogress.rb
|
|
@@ -155,7 +157,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
155
157
|
- !ruby/object:Gem::Version
|
|
156
158
|
version: '0'
|
|
157
159
|
requirements: []
|
|
158
|
-
rubygems_version: 3.6.
|
|
160
|
+
rubygems_version: 3.6.9
|
|
159
161
|
specification_version: 4
|
|
160
162
|
summary: The Video Game ROM downloader
|
|
161
163
|
test_files: []
|