rsgt 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +6 -0
- data/.rspec +2 -0
- data/Gemfile +6 -0
- data/README.markdown +139 -0
- data/Rakefile +10 -0
- data/bin/rsgt +5 -0
- data/lib/rsgt.rb +42 -0
- data/lib/rsgt/audio_extractor.rb +25 -0
- data/lib/rsgt/cli.rb +89 -0
- data/lib/rsgt/command_runner.rb +41 -0
- data/lib/rsgt/encrypted_steam_file.rb +44 -0
- data/lib/rsgt/multipacker.rb +114 -0
- data/lib/rsgt/multipacker/config_processor.rb +44 -0
- data/lib/rsgt/repacker.rb +37 -0
- data/lib/rsgt/rs_custom_song_toolkit.rb +41 -0
- data/lib/rsgt/saved_game.rb +37 -0
- data/lib/rsgt/saved_game/learn_a_song/song.rb +46 -0
- data/lib/rsgt/saved_game/score_attack/song.rb +38 -0
- data/lib/rsgt/saved_game/song_collection.rb +16 -0
- data/lib/rsgt/saved_game/statistics.rb +91 -0
- data/lib/rsgt/saved_game/statistics/song.rb +58 -0
- data/lib/rsgt/steam.rb +45 -0
- data/lib/rsgt/unpacked_psarc.rb +72 -0
- data/lib/rsgt/version.rb +3 -0
- data/lib/rsgt/vocals_extractor.rb +24 -0
- data/lib/rsgt/wav_shifter.rb +54 -0
- data/lib/rsgt/wwise_converter.rb +99 -0
- data/rsgt.gemspec +31 -0
- data/spec/lib/rsgt/audio_extractor_spec.rb +14 -0
- data/spec/lib/rsgt/command_runner_spec.rb +37 -0
- data/spec/lib/rsgt/repacker_spec.rb +24 -0
- data/spec/lib/rsgt/rs_custom_song_toolkit_spec.rb +47 -0
- data/spec/lib/rsgt/saved_game/learn_a_song/song_spec.rb +15 -0
- data/spec/lib/rsgt/saved_game_spec.rb +49 -0
- data/spec/lib/rsgt/unpacked_psarc_spec.rb +35 -0
- data/spec/lib/rsgt/vocals_extractor_spec.rb +14 -0
- data/spec/lib/rsgt/wav_shifter_spec.rb +30 -0
- data/spec/lib/rsgt/wwise_converter_spec.rb +22 -0
- data/spec/spec_helper.rb +11 -0
- metadata +168 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4cfc5355379a4cbe1f82dbc8e1804e17d39cd59c
|
4
|
+
data.tar.gz: b4d7dfd5381f73ab1afb6777db0915e3cb2ca474
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 61f701a60a21e1cc8baf7c2fda41b0c7e86d100ea7c6f05072b4d25450afa067e294548e54ece30574d03cf861490247828e501cf75c9ac563fd0c9b85ca5d9f
|
7
|
+
data.tar.gz: 4c6bfe25aa2a2d62ca7e62de312fac64744e861db37ff697d6696ad6083fe6e17a3b83f8044b005303b6b0f5f0e58ec8e826be4092d998c34893b7fc810166da
|
data/.rspec
ADDED
data/Gemfile
ADDED
data/README.markdown
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
# Rocksmith Guitar Tech
|
2
|
+
|
3
|
+
Ruby 💎 tool for working with rocksmith songs, DLC, and profile data.
|
4
|
+
Almost certainly only useful for Mac.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
`gem install rsgt`
|
9
|
+
|
10
|
+
### Dependencies
|
11
|
+
|
12
|
+
This tool relies on various bits of software to do the various bits of things it does...
|
13
|
+
|
14
|
+
- `pyrocksmith` (https://github.com/0x0L/rocksmith)
|
15
|
+
- Needed for anything involving unpacking/repacking
|
16
|
+
- Install by doing:
|
17
|
+
- `brew install pip`
|
18
|
+
- `pip3 install git+https://github.com/0x0L/rocksmith.git`
|
19
|
+
- WWise (https://www.audiokinetic.com/download/#macosx)
|
20
|
+
- Needed if you're going to repack audio
|
21
|
+
- [Rocksmith Custom Song Toolkit](https://www.rscustom.net/)
|
22
|
+
- Used for extracting audio out to ogg files
|
23
|
+
- Used for sng <-> xml conversion (like changing vocals)
|
24
|
+
- Installation:
|
25
|
+
- Move to `/Applications`
|
26
|
+
- `brew cask install mono-mdk`
|
27
|
+
- `brew install wine winetricks`
|
28
|
+
- `ffmpeg`
|
29
|
+
- `brew install ffmpeg`
|
30
|
+
|
31
|
+
## Usage: Uncensoring
|
32
|
+
|
33
|
+
For example...
|
34
|
+
|
35
|
+
```bash
|
36
|
+
# Extracts ragebomb_vocals.xml:
|
37
|
+
rsgt extract-vocals --psarc=ragekilling_m.psarc
|
38
|
+
|
39
|
+
# Edit the vocals file, putting back in missing words:
|
40
|
+
vim ragebomb_vocals.xml
|
41
|
+
|
42
|
+
# Extract the audio track to use as a guide track
|
43
|
+
# This creates output.ogg
|
44
|
+
rsgt extract-audio --psarc=ragekilling_m.psarc
|
45
|
+
|
46
|
+
# Using output.ogg as a guide track, take the real CD wav, line it up, save as fixed.wav
|
47
|
+
<AUDIO EDITING>
|
48
|
+
|
49
|
+
# Repack the fixed vocals and audio track back in:
|
50
|
+
rsgt \
|
51
|
+
repack \
|
52
|
+
--psarc=ragekilling_m.psarc \
|
53
|
+
--xml=ragebomb_vocals.xml \
|
54
|
+
--audio=fixed.wav
|
55
|
+
```
|
56
|
+
|
57
|
+
#### Repacking Options
|
58
|
+
|
59
|
+
You can also repack the preview if you want:
|
60
|
+
|
61
|
+
```bash
|
62
|
+
rsgt \
|
63
|
+
repack \
|
64
|
+
--psarc=ragekilling_m.psarc \
|
65
|
+
--xml=ragebomb_vocals.xml \
|
66
|
+
--audio=fixed.wav \
|
67
|
+
--preview \
|
68
|
+
--chorus=45
|
69
|
+
```
|
70
|
+
|
71
|
+
## Usage: Multipacker
|
72
|
+
|
73
|
+
The Multipacker can pack a bunch of psarcs into a single multipack.
|
74
|
+
|
75
|
+
For example, say you have this kind of folder structure:
|
76
|
+
|
77
|
+
```
|
78
|
+
~/rocksmith/songs
|
79
|
+
/uncensored
|
80
|
+
- Green Day - American Idiot_m.psarc
|
81
|
+
... some other songs
|
82
|
+
/Official
|
83
|
+
- Green Day - American Idiot_m.psarc
|
84
|
+
... hundreds of other songs
|
85
|
+
/CDLC
|
86
|
+
... hundreds of custom songs
|
87
|
+
```
|
88
|
+
|
89
|
+
Then you'd create a config file such as:
|
90
|
+
|
91
|
+
```yaml
|
92
|
+
destination: ~/Library/Application\ Support/Steam/SteamApps/common/Rocksmith2014/dlc
|
93
|
+
|
94
|
+
repacks:
|
95
|
+
- title: Uncensored
|
96
|
+
directory: ~/rocksmith/songs/Uncensored
|
97
|
+
unpack_dir: ~/rocksmith/unpacks/uncensored
|
98
|
+
repack_dir: ~/rocksmith/repacks/uncensored
|
99
|
+
options:
|
100
|
+
reset_unpack: false
|
101
|
+
reset_repack: false
|
102
|
+
|
103
|
+
- title: Official
|
104
|
+
directory: ~/rocksmith/songs/Official
|
105
|
+
unpack_dir: ~/rocksmith/unpacks/official
|
106
|
+
repack_dir: ~/rocksmith/repacks/official
|
107
|
+
options:
|
108
|
+
reset_unpack: false
|
109
|
+
reset_repack: false
|
110
|
+
|
111
|
+
- title: Custom
|
112
|
+
directory: ~/rocksmith/songs/CDLC
|
113
|
+
unpack_dir: ~/rocksmith/unpacks/cdlc
|
114
|
+
repack_dir: ~/rocksmith/repacks/cdlc
|
115
|
+
options:
|
116
|
+
reset_unpack: false
|
117
|
+
reset_repack: false
|
118
|
+
```
|
119
|
+
|
120
|
+
And running `rsgt multipack --config=thatfile.yml` would:
|
121
|
+
- Repack all of your uncensored songs into a single "Uncensored - n songs _m.psarc" file, and move it to your DLC folder.
|
122
|
+
- Repack all of your official songs into a single "Official - n songs _m.psarc" file, and move it to your DLC folder.
|
123
|
+
- Leaving out songs that it already got from uncensored
|
124
|
+
- Repack all of your custom songs into a single "Custom - n songs _m.psarc" file, and move it to your DLC folder.
|
125
|
+
|
126
|
+
##### Notes:
|
127
|
+
- Make sure to check the RS DLC folder, and remove any duplicates - just leave the lastest of each multipack
|
128
|
+
- You can keep your `unpack`/`repack` directories around as a cache
|
129
|
+
- The "reset" options will nuke that folder:
|
130
|
+
- If you're just adding songs, keep it as false, and it'll be zippy
|
131
|
+
- If you're deleting/changing songs, change it to true, so stale copies don't get packed in
|
132
|
+
|
133
|
+
## Usage: Saved Game exploration
|
134
|
+
|
135
|
+
... this area is WIP, you probably don't want to mess with `RSGuitarTech::SavedGame` at all right now.
|
136
|
+
|
137
|
+
## License
|
138
|
+
|
139
|
+
MIT
|
data/Rakefile
ADDED
data/bin/rsgt
ADDED
data/lib/rsgt.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require "tmpdir"
|
2
|
+
require "fileutils"
|
3
|
+
require "shellwords"
|
4
|
+
require "bindata"
|
5
|
+
require "zlib"
|
6
|
+
require "json"
|
7
|
+
require "openssl"
|
8
|
+
require "active_support"
|
9
|
+
require "active_support/core_ext"
|
10
|
+
|
11
|
+
begin
|
12
|
+
require "pry"
|
13
|
+
rescue LoadError
|
14
|
+
end
|
15
|
+
|
16
|
+
require "rsgt/version"
|
17
|
+
require "rsgt/command_runner"
|
18
|
+
require "rsgt/rs_custom_song_toolkit"
|
19
|
+
require "rsgt/unpacked_psarc"
|
20
|
+
require "rsgt/vocals_extractor"
|
21
|
+
require "rsgt/audio_extractor"
|
22
|
+
require "rsgt/wwise_converter"
|
23
|
+
require "rsgt/repacker"
|
24
|
+
require "rsgt/wav_shifter"
|
25
|
+
require "rsgt/multipacker/config_processor"
|
26
|
+
require "rsgt/steam"
|
27
|
+
require "rsgt/encrypted_steam_file"
|
28
|
+
require "rsgt/saved_game/song_collection"
|
29
|
+
require "rsgt/saved_game/score_attack/song"
|
30
|
+
require "rsgt/saved_game/statistics/song"
|
31
|
+
require "rsgt/saved_game/learn_a_song/song"
|
32
|
+
require "rsgt/saved_game/statistics"
|
33
|
+
require "rsgt/saved_game"
|
34
|
+
require "rsgt/multipacker"
|
35
|
+
require "rsgt/cli"
|
36
|
+
|
37
|
+
module RSGuitarTech
|
38
|
+
class << self
|
39
|
+
attr_accessor :verbose
|
40
|
+
@verbose = false
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module RSGuitarTech
|
2
|
+
class AudioExtractor
|
3
|
+
|
4
|
+
attr_accessor :psarc, :opts, :unpacked
|
5
|
+
|
6
|
+
def initialize(opts)
|
7
|
+
@psarc = File.expand_path(opts.delete :psarc)
|
8
|
+
@opts = opts
|
9
|
+
end
|
10
|
+
|
11
|
+
def extract!
|
12
|
+
UnpackedPSARC.from_psarc(psarc, opts) do |unpacked|
|
13
|
+
|
14
|
+
# Convert main track from wem to ogg:
|
15
|
+
CommandRunner.run! RSCustomSongToolkit.ww2ogg(unpacked.audio_track)
|
16
|
+
raise StandardError unless File.exist?(unpacked.ogg_track)
|
17
|
+
|
18
|
+
# Revorb it so it doesn't sound bad...
|
19
|
+
CommandRunner.run! RSCustomSongToolkit.revorb(unpacked.ogg_track)
|
20
|
+
|
21
|
+
FileUtils.cp unpacked.ogg_track, "output.ogg"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/rsgt/cli.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
require "trollop"
|
2
|
+
|
3
|
+
module RSGuitarTech
|
4
|
+
class CLI
|
5
|
+
|
6
|
+
SUB_COMMANDS = %w(extract-vocals extract-audio repack shift multipack)
|
7
|
+
|
8
|
+
TOP_BANNER = <<~STRING
|
9
|
+
Tool to work with RS DLC and saves
|
10
|
+
USAGE: rsgt [options] command [command_options]
|
11
|
+
|
12
|
+
Options for all commands:
|
13
|
+
|
14
|
+
STRING
|
15
|
+
|
16
|
+
USAGE = <<~STRING
|
17
|
+
|
18
|
+
Available command are:
|
19
|
+
extract-vocals: Extract a .xml of the vocals for editing
|
20
|
+
extract-audio: Extract the audio track as an .ogg (ie, to use as guide track)
|
21
|
+
repack: Repack altered lyrics/audio into a psarc
|
22
|
+
shift: Shift a .wav by ms
|
23
|
+
multipack: Repack multiple PSARCs into a single PSARC
|
24
|
+
STRING
|
25
|
+
|
26
|
+
def self.parse(args)
|
27
|
+
global_opts = Trollop::options do
|
28
|
+
banner TOP_BANNER
|
29
|
+
opt :verbose, "More output", short: "-v"
|
30
|
+
banner USAGE
|
31
|
+
|
32
|
+
stop_on SUB_COMMANDS
|
33
|
+
end
|
34
|
+
|
35
|
+
cmd = args.shift # get the subcommand
|
36
|
+
cmd_opts = case cmd
|
37
|
+
when "extract-vocals"
|
38
|
+
Trollop::options do
|
39
|
+
banner "Extracts and converts vocals into an XML"
|
40
|
+
opt :psarc, "PSARC to extract", type: :string, required: true
|
41
|
+
opt :output, "Optional path to output the XML", type: :string
|
42
|
+
end
|
43
|
+
when "extract-audio"
|
44
|
+
Trollop::options do
|
45
|
+
banner "Extracts and converts the audio track into an .ogg"
|
46
|
+
opt :psarc, "PSARC to extract", type: :string, required: true
|
47
|
+
opt :output, "Optional path to output the .ogg", type: :string
|
48
|
+
end
|
49
|
+
when "repack"
|
50
|
+
Trollop::options do
|
51
|
+
banner "Repack a psarc with new vocals XML and/or audio tracks"
|
52
|
+
opt :psarc, "PSARC to repack files into", type: :string, required: true
|
53
|
+
opt :vocals_xml, "Vocals XML file to repack", type: :string
|
54
|
+
opt :audio, "Audio file to repack", type: :string
|
55
|
+
opt :wwise_ver, "WWise version to use", type: :string, default: "2016.2.4.6098"
|
56
|
+
opt :quality, "Quality of OGG encoding", type: :string, default: "6"
|
57
|
+
opt :preview, "Flag to regenerate the preview", type: :boolean, default: false
|
58
|
+
opt :chorus, "Seconds in to start the preview", type: :string, default: "30"
|
59
|
+
opt :output, "Optional place to output the repacked psarc", type: :string
|
60
|
+
end
|
61
|
+
when "shift"
|
62
|
+
Trollop::options do
|
63
|
+
banner "Shift a .WAV file by given MS"
|
64
|
+
opt :wav, "WAV file to shift", type: :string, required: true
|
65
|
+
opt :dir, "Direction to shift (forward or backward)", type: :string, required: true
|
66
|
+
opt :amount, "Amount in MS", type: :string, required: true
|
67
|
+
end
|
68
|
+
when "multipack"
|
69
|
+
Trollop::options do
|
70
|
+
banner "Repack multiple PSARCs into a single PSARC"
|
71
|
+
opt :config, "Config File", type: :string, required: true
|
72
|
+
end
|
73
|
+
else
|
74
|
+
Trollop::educate
|
75
|
+
end
|
76
|
+
|
77
|
+
RSGuitarTech.verbose = true if global_opts[:verbose]
|
78
|
+
RSGuitarTech.verbose = true if cmd_opts[:verbose]
|
79
|
+
|
80
|
+
case cmd
|
81
|
+
when "extract-vocals" then VocalsExtractor.new(cmd_opts).extract!
|
82
|
+
when "extract-audio" then AudioExtractor.new(cmd_opts).extract!
|
83
|
+
when "repack" then Repacker.new(cmd_opts).repack!
|
84
|
+
when "shift" then WavShifter.new(cmd_opts).shift!
|
85
|
+
when "multipack" then Multipacker::ConfigProcessor.new(cmd_opts).process!
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "shellwords"
|
2
|
+
require "open3"
|
3
|
+
|
4
|
+
module RSGuitarTech
|
5
|
+
class CommandRunner
|
6
|
+
|
7
|
+
def self.run!(args, skip_escaping: false)
|
8
|
+
self.new(args, skip_escaping: skip_escaping).run!
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_accessor :cmd
|
12
|
+
|
13
|
+
def initialize(args, skip_escaping: false)
|
14
|
+
if skip_escaping
|
15
|
+
@cmd = Array(args).join " "
|
16
|
+
else
|
17
|
+
@cmd = Shellwords.join Array(args)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def run!
|
22
|
+
if RSGuitarTech.verbose
|
23
|
+
puts "*" * 40
|
24
|
+
puts ""
|
25
|
+
puts cmd
|
26
|
+
puts ""
|
27
|
+
end
|
28
|
+
|
29
|
+
stdout, stderr, status = Open3.capture3(cmd)
|
30
|
+
if RSGuitarTech.verbose
|
31
|
+
stdout.split("\n").each do |line|
|
32
|
+
puts "--- #{line}"
|
33
|
+
end
|
34
|
+
stderr.split("\n").each do |line|
|
35
|
+
puts "!!! #{line}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
status
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module RSGuitarTech
|
2
|
+
class EncryptedSteamFile < BinData::Record
|
3
|
+
endian :little
|
4
|
+
|
5
|
+
string :evas, read_length: 4 # Is always 'EVAS'
|
6
|
+
uint32 :version # Is always 1
|
7
|
+
uint64 :profile # Steam profile
|
8
|
+
uint32 :len
|
9
|
+
rest :payload
|
10
|
+
|
11
|
+
KEY = [
|
12
|
+
0x72, 0x8B, 0x36, 0x9E, 0x24, 0xED, 0x01, 0x34,
|
13
|
+
0x76, 0x85, 0x11, 0x02, 0x18, 0x12, 0xAF, 0xC0,
|
14
|
+
0xA3, 0xC2, 0x5D, 0x02, 0x06, 0x5F, 0x16, 0x6B,
|
15
|
+
0x4B, 0xCC, 0x58, 0xCD, 0x26, 0x44, 0xF2, 0x9E
|
16
|
+
].pack('C*')
|
17
|
+
|
18
|
+
def decrypted
|
19
|
+
aes = OpenSSL::Cipher::Cipher.new 'AES-256-ECB'
|
20
|
+
aes.decrypt
|
21
|
+
aes.key = KEY
|
22
|
+
aes.padding = 0
|
23
|
+
|
24
|
+
aes.update(payload) + aes.final
|
25
|
+
end
|
26
|
+
|
27
|
+
def encrypted
|
28
|
+
aes = OpenSSL::Cipher::Cipher.new 'AES-256-ECB'
|
29
|
+
aes.encrypt
|
30
|
+
aes.key = KEY
|
31
|
+
aes.padding = 0
|
32
|
+
|
33
|
+
aes.update(payload) + aes.final
|
34
|
+
end
|
35
|
+
|
36
|
+
def uncompressed
|
37
|
+
Zlib::Inflate.inflate decrypted
|
38
|
+
end
|
39
|
+
|
40
|
+
def uncompressed_json
|
41
|
+
JSON.parse uncompressed.strip
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module RSGuitarTech
|
2
|
+
class Multipacker
|
3
|
+
|
4
|
+
def self.process!(*args)
|
5
|
+
self.new(*args).process!
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_accessor *%i{title directory unpack_dir repack_dir dest_dir filters options count}
|
9
|
+
|
10
|
+
def initialize(title:, directory:, unpack_dir:, repack_dir:, dest_dir:, filters: {}, options: {})
|
11
|
+
@title = title
|
12
|
+
@directory = directory
|
13
|
+
@unpack_dir = unpack_dir
|
14
|
+
@repack_dir = repack_dir
|
15
|
+
@dest_dir = dest_dir
|
16
|
+
@filters = filters
|
17
|
+
@options = options
|
18
|
+
@count = {psarcs: 0, skipped: 0, failed: 0, total: 0}
|
19
|
+
end
|
20
|
+
|
21
|
+
def process!
|
22
|
+
reset! unpack_dir if options[:reset_unpack]
|
23
|
+
reset! repack_dir if options[:reset_repack]
|
24
|
+
ensure_dir! unpack_dir
|
25
|
+
ensure_dir! repack_dir
|
26
|
+
unpack!
|
27
|
+
if count[:skipped] >= count[:total]
|
28
|
+
puts "All done! No new files found to repack"
|
29
|
+
return
|
30
|
+
end
|
31
|
+
repack!
|
32
|
+
move!
|
33
|
+
end
|
34
|
+
|
35
|
+
def reset!(dir)
|
36
|
+
shell_out "rm -rf #{dir}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def ensure_dir!(dir)
|
40
|
+
shell_out "mkdir -p #{dir}/"
|
41
|
+
end
|
42
|
+
|
43
|
+
def unpack!
|
44
|
+
filtered_psarscs.each do |dlc|
|
45
|
+
if unpack dlc
|
46
|
+
count[:total] = count[:total] + 1
|
47
|
+
else
|
48
|
+
count[:failed] = count[:failed] + 1
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def repack!
|
54
|
+
puts "Packing #{count[:total]} songs into #{repack_dir}.psarc"
|
55
|
+
shell_out %Q{pyrocksmith --no-crypto --pack "#{repack_dir}"}
|
56
|
+
end
|
57
|
+
|
58
|
+
def move!
|
59
|
+
packed_psarc = repack_dir.split("/").last + ".psarc"
|
60
|
+
puts "Moving packed psarc (#{packed_psarc}) to: #{title} - #{count[:total]} songs _m.psarc"
|
61
|
+
shell_out "mv #{packed_psarc} #{dest_dir}/#{title}\\ \\-\\ #{count[:total]}\\ songs\\ \\_m.psarc"
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def unpack(dlc)
|
67
|
+
count[:psarcs] = count[:psarcs] + 1
|
68
|
+
base_name = File.basename dlc, '.*'
|
69
|
+
|
70
|
+
if Dir.exists? "#{unpack_dir}/#{base_name}"
|
71
|
+
puts "Skipping #{dlc} (#{base_name})"
|
72
|
+
count[:skipped] = count[:skipped] + 1
|
73
|
+
return true
|
74
|
+
end
|
75
|
+
|
76
|
+
puts "Unpacking #{dlc} (#{base_name})"
|
77
|
+
|
78
|
+
return false unless shell_out %Q{pyrocksmith --no-crypto --unpack "#{dlc}"}
|
79
|
+
return false unless shell_out %Q{mv "#{base_name}/" #{unpack_dir}/}
|
80
|
+
return false unless shell_out %Q{ditto "#{unpack_dir}/#{base_name}/" "#{repack_dir}"}
|
81
|
+
|
82
|
+
true
|
83
|
+
end
|
84
|
+
|
85
|
+
def filtered_psarscs
|
86
|
+
@filtered_psarscs ||= begin
|
87
|
+
reject_filters = Array(filters[:reject]).flatten
|
88
|
+
select_filters = Array(filters[:select]).flatten
|
89
|
+
limit = options[:limit]
|
90
|
+
|
91
|
+
_fp = psarcs
|
92
|
+
_fp = _fp.take(limit) if limit
|
93
|
+
_fp = _fp.reject { |filename| reject_filters.include? simplfied(filename) } if reject_filters.any?
|
94
|
+
_fp = _fp.select { |filename| select_filters.include? simplfied(filename) } if select_filters.any?
|
95
|
+
_fp
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def psarcs
|
100
|
+
@psarcs ||= Dir.glob("#{directory}/*.psarc")
|
101
|
+
end
|
102
|
+
|
103
|
+
def simplfied(filename)
|
104
|
+
filename.split("/").last.split(" _m").first
|
105
|
+
end
|
106
|
+
|
107
|
+
def shell_out(cmd)
|
108
|
+
puts cmd if options[:verbose]
|
109
|
+
return true if system(cmd)
|
110
|
+
puts "FAILED: #{cmd}"
|
111
|
+
false
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|