rsgt 0.0.1
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 +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
|