feh-hsdarcwriter 0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: fc8fea65e2141fa49e6fb251787bdce08cb795d6bcb13bf93323bf568e67fc69
4
+ data.tar.gz: 0c9c2a9746096edab92918dabbcec0f716426718d4a9eca3291670e01beb5871
5
+ SHA512:
6
+ metadata.gz: d1f2cbf197939691480a4172a1220431b39151d437d89dd9fd4884cd3016baa51aea056dc79770bf994e506e1801f2c63fb2835585c2b7754bb8e11130046eb6
7
+ data.tar.gz: b8b7dc36a11fd1863b084ed83708dc809f9051103d6e5aa228d81714c22720439afec3713f603d31fbbbec5b66a00589fd91bd6c7cf4dced6b75715fa7f7f80d
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ Gemfile.lock
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --markup markdown
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in feh-hsdarcwriter.gemspec
6
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Quinton Miller
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # feh-hsdarcwriter
2
+
3
+ `Feh::HSDArcWriter` is an interface for generating files in the HSDArc file
4
+ format used by Fire Emblem Heroes.
5
+
6
+ ## Installation
7
+
8
+ ```ruby
9
+ $ gem install feh-hsdarcwriter
10
+ ```
11
+
12
+ ## Example
13
+
14
+ The following script generates an HSDArc file _equivalent_ to
15
+ `assets/Common/SRPG/Move.bin` as of FEH version 2.9.1:
16
+
17
+ ```ruby
18
+ #!/usr/bin/env ruby
19
+
20
+ require 'feh/hsdarc_writer'
21
+
22
+ MVMTS = [
23
+ {id_tag: 'MVID_歩行', range: 2, costs: [
24
+ 1, 1, 1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1,
25
+ 1, 2, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1,
26
+ 1, -1, -1]},
27
+ {id_tag: 'MVID_重装', range: 1, costs: [
28
+ 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1,
29
+ 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1,
30
+ 1, -1, -1]},
31
+ {id_tag: 'MVID_騎馬', range: 3, costs: [
32
+ 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1,
33
+ 1, -1, 1, -1, -1, -1, 3, 3, 3, 3, -1, 1, 1, 1, 1, 1,
34
+ 1, -1, -1]},
35
+ {id_tag: 'MVID_飛行', range: 2, costs: [
36
+ 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1,
37
+ 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
38
+ 1, -1, -1]},
39
+ ]
40
+
41
+ writer = Feh::HSDArcWriter.new
42
+ writer.ptr do |blk|
43
+ MVMTS.each_with_index do |mvmt, index|
44
+ blk.string(mvmt[:id_tag], Feh::HSDArcWriter::XORKeys::ID_XORKEY)
45
+ blk.ptr {|costs| costs.i8(mvmt[:costs], 0xB8)}
46
+ blk.i32(index, 0xD5025852)
47
+ blk.i8(mvmt[:range], 0x80)
48
+ end
49
+ end
50
+ writer.i64(MVMTS.size, 0x20A10C408924170E)
51
+
52
+ IO.binwrite('Move.bin', writer.hsdarc.pack('c*'))
53
+
54
+ # if Feh::Bin is available:
55
+ # require 'feh/bin'
56
+ # IO.binwrite('Move.bin.lz', Feh::Bin.compress(writer.hsdarc).pack('c*'))
57
+ ```
58
+
59
+ ## Changelog
60
+
61
+ ### V0.1.0
62
+
63
+ - Initial release
64
+
65
+ ## License
66
+
67
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ task :default => :test
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.description = 'Run unit tests'
8
+ t.libs << 'lib'
9
+ t.test_files = FileList['spec/**/*_spec.rb']
10
+ end
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "feh/hsdarcwriter"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,25 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "feh/hsdarc_writer/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "feh-hsdarcwriter"
8
+ spec.version = Feh::HSDArcWriter::VERSION
9
+ spec.authors = ["Quinton Miller"]
10
+ spec.email = ["nicetas.c@gmail.com"]
11
+
12
+ spec.summary = "HSDArc file builder for Fire Emblem Heroes"
13
+ spec.description = "Builder interface for the HSDArc file format used in Fire Emblem Heroes."
14
+ spec.homepage = "https://github.com/HertzDevil/feh-hsdarcwriter"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
18
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ end
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.16"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "minitest", "~> 5.0"
25
+ end
@@ -0,0 +1,167 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'feh/hsdarc_writer/version'
4
+ require 'feh/hsdarc_writer/xor_keys'
5
+
6
+ module Feh
7
+ # A class that builds well-formed HSDArc files used in Fire Emblem Heroes.
8
+ #
9
+ # Duplicate strings are currently stored like any other sub-block and not
10
+ # optimized; the compiled HSDArc data might not be byte-for-byte identical to
11
+ # the original asset files.
12
+ class HSDArcWriter
13
+ def initialize
14
+ @buf = []
15
+ @subblocks = []
16
+ end
17
+
18
+ # @return [Array<Integer>] the relocatable pointer list
19
+ def reloc_ptrs
20
+ @subblocks.map(&:first)
21
+ end
22
+
23
+ # Writes 8-bit integers.
24
+ # @param x [Integer, Array<Integer>] the integer value(s)
25
+ # @param xor [Integer] XOR value
26
+ # @return [HSDArcWriter] self
27
+ def i8(x, xor = 0)
28
+ int(x, 1, xor)
29
+ end
30
+
31
+ # Writes 16-bit integers.
32
+ # @param x [Integer, Array<Integer>] the integer value(s)
33
+ # @param xor [Integer] XOR value
34
+ # @return [HSDArcWriter] self
35
+ def i16(x, xor = 0)
36
+ int(x, 2, xor)
37
+ end
38
+
39
+ # Writes 32-bit integers.
40
+ # @param x [Integer, Array<Integer>] the integer value(s)
41
+ # @param xor [Integer] XOR value
42
+ # @return [HSDArcWriter] self
43
+ def i32(x, xor = 0)
44
+ int(x, 4, xor)
45
+ end
46
+
47
+ # Writes 64-bit integers.
48
+ # @param x [Integer, Array<Integer>] the integer value(s)
49
+ # @param xor [Integer] XOR value
50
+ # @return [HSDArcWriter] self
51
+ def i64(x, xor = 0)
52
+ int(x, 8, xor)
53
+ end
54
+
55
+ # Writes boolean values.
56
+ # @param b [Object, Array<Object>] the boolean value(s), only truthiness is
57
+ # considered
58
+ # @param xor [Integer] XOR value
59
+ # @return [HSDArcWriter] self
60
+ def bool(b, xor = 0)
61
+ i8(b ? 1 : 0, xor)
62
+ end
63
+
64
+ # Writes an XOR-encrypted string. The resulting string is always zero-padded
65
+ # to align on 64-bit boundaries.
66
+ # @param str [String] UTF-8 string
67
+ # @param xor [Array<Integer>] optional XOR cipher to use, writes unencrypted
68
+ # strings by default
69
+ # @return [HSDArcWriter] self
70
+ def xor_str(str, xor = [0])
71
+ align(8)
72
+ bytes = str.bytes.zip(xor.cycle).map {|x, y| x != y ? x ^ y : x}
73
+ bytes += [0] * (8 - bytes.size % 8)
74
+ @buf += bytes
75
+ self
76
+ end
77
+
78
+ # Creates a pointer to an XOR-encrypted string.
79
+ # @param str [String] UTF-8 string
80
+ # @param xor [Array<Integer>] optional XOR cipher to use, writes unencrypted
81
+ # strings by default
82
+ # @return [HSDArcWriter] self
83
+ def string(str, xor = [0])
84
+ ptr {|blk| blk.xor_str(str, xor)}
85
+ end
86
+
87
+ # Writes a null pointer.
88
+ # @return [HSDArcWriter] self
89
+ def nullptr
90
+ i64(0)
91
+ end
92
+
93
+ # Writes a pointer that points to a new block.
94
+ # @yieldparam blk [HSDArcWriter] the sub-block object
95
+ # @return [HSDArcWriter] self
96
+ def ptr(&block)
97
+ blk = self.class.new
98
+ block.(blk)
99
+ align(8)
100
+ @subblocks << [@buf.size, blk]
101
+ nullptr
102
+ end
103
+
104
+ # Compiles the data section of the HSDArc file.
105
+ # @return [Array<Integer>] Content of the data section
106
+ def compile
107
+ hsdarc_impl.first
108
+ end
109
+
110
+ # Compiles the whole HSDArc file.
111
+ # @return [Array<Integer>] Content of the HSDArc file
112
+ def hsdarc
113
+ bin, reloc = hsdarc_impl
114
+ total_size = 0x20 + bin.size + reloc.size * 8
115
+ header = [total_size, reloc.empty? ? 0 : bin.size, reloc.size, 0, 0, 1, 0, 0]
116
+ .pack('i*').bytes
117
+ header + bin + reloc.pack('j*').bytes
118
+ end
119
+
120
+ # Aligns the data pointer.
121
+ # @param x [Integer] alignment byte count
122
+ # @return [HSDArcWriter] self
123
+ def align(x)
124
+ @buf += [0] * ((-@buf.size) % x)
125
+ self
126
+ end
127
+
128
+ private
129
+ def int(x, len, xor = 0)
130
+ align(len)
131
+ if x.is_a?(Array)
132
+ x.map! {|y| y ^ xor}
133
+ x.each {|y| @buf += Array.new(len) {|i| (y >> (i * 8)) & 0xFF}}
134
+ else
135
+ x ^= xor
136
+ @buf += Array.new(len) {|i| (x >> (i * 8)) & 0xFF}
137
+ end
138
+ self
139
+ end
140
+
141
+ def self.replace_ptr(arr, pos, x)
142
+ x += arr[pos, 8].pack('c*').unpack('j').first
143
+ arr[pos, 8] = Array.new(8) {|i| (x >> (i * 8)) & 0xFF}
144
+ nil
145
+ end
146
+
147
+ def hsdarc_impl
148
+ bin = @buf.dup
149
+ bin += [0] * ((-bin.size) % 8)
150
+ reloc = reloc_ptrs
151
+
152
+ @subblocks.each do |pos, blk|
153
+ s = bin.size
154
+ bin2 = blk.compile
155
+ reloc2 = blk.reloc_ptrs
156
+ reloc2.map! {|x| x + s}
157
+ bin += bin2
158
+ reloc2.each {|x| self.class.replace_ptr(bin, x, s)}
159
+ reloc += reloc2
160
+ self.class.replace_ptr(bin, pos, s)
161
+ end
162
+
163
+ bin += [0] * ((-bin.size) % 8)
164
+ [bin, reloc]
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module Feh
4
+ class HSDArcWriter
5
+ # Version number.
6
+ VERSION = "0.1.0"
7
+ end
8
+ end
@@ -0,0 +1,113 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module Feh
4
+ class HSDArcWriter
5
+ module XORKeys
6
+ # Produces a XOR cipher from an internal key.
7
+ # @param key [Array<Integer>] byte values of the internal key
8
+ # @return [Array<Integer>] content of the XOR cipher
9
+ def self.make_cipher(key)
10
+ k = (key[0] + key[1]) & 0xFF
11
+ cipher = []
12
+ key.each do |x|
13
+ k ^= x
14
+ cipher << k
15
+ end
16
+ key.each do |x|
17
+ k ^= x
18
+ cipher << k
19
+ end
20
+ cipher
21
+ end
22
+
23
+ # XOR cipher used for almost all asset files.
24
+ ID_XORKEY = make_cipher([
25
+ 0x40, 0x81, 0x80, 0x24, 0xFE, 0x4C, 0x79, 0x17, 0x2F,
26
+ 0xD6, 0xAC, 0xDA, 0x0B, 0x9A, 0x69, 0x28, 0x52,
27
+ ]).freeze
28
+
29
+ # XOR cipher used for message files.
30
+ MSG_XORKEY = make_cipher([
31
+ 0x58, 0xDF, 0x3F, 0x59, 0x39, 0x85, 0x30, 0xB1, 0x2D,
32
+ 0xB0, 0x80, 0x13, 0xB3, 0xCB, 0x25, 0xB0, 0xE8, 0x5D,
33
+ 0x2E, 0x29, 0xBF, 0xC9, 0xEA, 0x70, 0x33, 0x7B, 0xE6,
34
+ 0xD3, 0xD2,
35
+ ]).freeze
36
+
37
+ # XOR cipher used for files under `assets/Common/Tutorial/`.
38
+ TUT_XORKEY = make_cipher([
39
+ 0x0B, 0x76, 0x02, 0xC7, 0x63, 0x1F, 0xDD, 0x15, 0xE3,
40
+ 0x90, 0x7E, 0x4E, 0xC6, 0x7C, 0x60, 0x81, 0x7A, 0x94,
41
+ ]).freeze
42
+
43
+ # XOR cipher used for files under `assets/Common/SRPG/StageBgm/`.
44
+ BGM_XORKEY = make_cipher([
45
+ 0xE0, 0xAF, 0xF7, 0x8B, 0x7B, 0xA8, 0x6B, 0x3F, 0x55,
46
+ 0x15, 0x0D, 0xCE, 0x7F, 0xE9, 0x20, 0x0F, 0xE7, 0x82,
47
+ ]).freeze
48
+
49
+ # XOR cipher used for files under `assets/Common/Occupation/World/`.
50
+ GC_XORKEY = make_cipher([
51
+ 0x56, 0xEB, 0x35, 0x23, 0x93, 0x10, 0x4D, 0x99, 0x19,
52
+ 0xF0, 0x5A, 0x56, 0xE5, 0x36, 0xBD, 0xFB, 0x62, 0x1B,
53
+ ]).freeze
54
+
55
+ # XOR cipher used for files under `assets/Common/Tournament/`.
56
+ VG_XORKEY = make_cipher([
57
+ 0xD7, 0x76, 0x02, 0xC7, 0xA8, 0x1F, 0x5C, 0x80, 0xE3,
58
+ 0x2C, 0x7E, 0x4E, 0xC6, 0x0C, 0x94, 0x15, 0x7A, 0x60,
59
+ ]).freeze
60
+
61
+ # XOR cipher used for files under `assets/Common/Portrait/`.
62
+ FB_XORKEY = make_cipher([
63
+ 0x04, 0x27, 0x6E, 0x8B, 0x91, 0xE4, 0xAC, 0x1E, 0xCE,
64
+ 0x48, 0xED, 0x90, 0x34, 0xFA, 0xCD, 0x8C, 0x76, 0x1A,
65
+ 0x44, 0xA8, 0x59, 0x8D, 0xAD, 0x5E, 0xBD, 0x6C, 0x0E,
66
+ 0xE1, 0xE2,
67
+ ]).freeze
68
+
69
+ # XOR cipher used for files under `assets/Common/LoginBonus/`.
70
+ LOGIN_XORKEY = make_cipher([
71
+ 0xA9, 0xBB, 0xE3, 0xE8, 0x07, 0x8F, 0x46, 0xB8, 0xED,
72
+ 0x2F, 0xF0, 0x4B, 0x8E, 0x62, 0x7C, 0x91, 0x4E, 0x0C,
73
+ ]).freeze
74
+
75
+ # XOR cipher used for files under `assets/Common/Summon/`.
76
+ SUMMON_XORKEY = make_cipher([
77
+ 0x87, 0x1C, 0xC0, 0xF8, 0x4C, 0xAC, 0xCE, 0x0D, 0x50,
78
+ 0xF0, 0x6C, 0x2B, 0x40, 0x0B, 0x7B, 0x1D, 0x3B, 0x77,
79
+ ]).freeze
80
+
81
+ # XOR cipher used for files under `assets/Common/Home/`.
82
+ HOME_XORKEY = make_cipher([
83
+ 0xE3, 0x17, 0xC8, 0xEF, 0x87, 0x81, 0x71, 0x52, 0xBC,
84
+ 0x66, 0x38, 0xBD, 0xFB, 0x5B, 0x79, 0xF1, 0xE3, 0xE1,
85
+ ]).freeze
86
+
87
+ # XOR cipher used for `assets/Common/Loading/Data.bin`.
88
+ LOADING_XORKEY = make_cipher([
89
+ 0x73, 0x76, 0xEF, 0xC7, 0xC5, 0x1F, 0x5C, 0x80, 0xE3,
90
+ 0x70, 0x7E, 0x53, 0xC6, 0xD7, 0x94, 0x15, 0x7A, 0x60,
91
+ ]).freeze
92
+
93
+ # XOR cipher used for files under `assets/Common/Battle/Asset/`.
94
+ BATTLE_XORKEY = make_cipher([
95
+ 0x01, 0x6F, 0x1A, 0xF1, 0xB2, 0x3D, 0x66, 0xBE, 0x9C,
96
+ 0x76, 0x73, 0xE3, 0x4D, 0x1C, 0xA1, 0x7A, 0x1D, 0x41,
97
+ 0x19, 0x20, 0x33, 0xC6, 0x85, 0xA6,
98
+ ]).freeze
99
+
100
+ # XOR cipher used for files under `assets/Common/Effect/arc/`.
101
+ EFFECT_ARC_XORKEY = make_cipher([
102
+ 0x0B, 0x44, 0x35, 0xF4, 0x3E, 0xEB, 0xDC, 0x59, 0x62,
103
+ 0xED, 0x01, 0x74, 0xA7, 0xA8, 0x3D, 0x81, 0x64, 0x7C,
104
+ ]).freeze
105
+
106
+ # XOR cipher used for files under `assets/Common/Sound/arc/`.
107
+ SOUND_ARC_XORKEY = make_cipher([
108
+ 0x30, 0x3A, 0x10, 0xF0, 0x21, 0x33, 0x9E, 0xF9, 0xD2,
109
+ 0xA5, 0x10, 0xCA, 0x42, 0x90, 0xDC, 0x2C, 0x3C, 0x81,
110
+ ]).freeze
111
+ end
112
+ end
113
+ end
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: feh-hsdarcwriter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Quinton Miller
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-09-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ description: Builder interface for the HSDArc file format used in Fire Emblem Heroes.
56
+ email:
57
+ - nicetas.c@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".yardopts"
64
+ - Gemfile
65
+ - LICENSE.txt
66
+ - README.md
67
+ - Rakefile
68
+ - bin/console
69
+ - bin/setup
70
+ - feh-hsdarcwriter.gemspec
71
+ - lib/feh/hsdarc_writer.rb
72
+ - lib/feh/hsdarc_writer/version.rb
73
+ - lib/feh/hsdarc_writer/xor_keys.rb
74
+ homepage: https://github.com/HertzDevil/feh-hsdarcwriter
75
+ licenses:
76
+ - MIT
77
+ metadata: {}
78
+ post_install_message:
79
+ rdoc_options: []
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ requirements: []
93
+ rubyforge_project:
94
+ rubygems_version: 2.7.6
95
+ signing_key:
96
+ specification_version: 4
97
+ summary: HSDArc file builder for Fire Emblem Heroes
98
+ test_files: []