rrb-common 0.1.6 → 0.1.7
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/lib/rune/cache/archive.rb +63 -0
- data/lib/rune/cache/constants.rb +21 -0
- data/lib/rune/cache/file_system.rb +182 -0
- data/lib/rune/cache/index.rb +37 -0
- data/lib/rune/common.rb +9 -0
- data/lib/rune/core/buffer.rb +5 -0
- data/lib/rune/core/constants.rb +5 -1
- data/lib/rune/core/ruby_isaac.rb +1 -5
- data/lib/rune/core/writeable_buffer.rb +3 -7
- metadata +21 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0ce1791f92b3956911a84c638f8c6b55b1dc41b250321f0ee14a3aa2e70771d0
|
4
|
+
data.tar.gz: 1d80809c5a7633e2f379a3c6df03ad0cd278d127775a2ad76fae52c31f4ae534
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 59abbc5acfb4daad674f5555d23adf9714987a448fbc6c051aee422977672206550973039df89f85dd27adc31b872763b3c700983022bf91333fe46232d7af0b
|
7
|
+
data.tar.gz: af50e56189702d9c4820ec9a78e04ec0a4dc042a825ff7015d736938dd6119610d75df3e16792d7329eb2c7cc46f3dc8359fcdc8e2179ff96ec6cc7ceca94819
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module RuneRb::Cache
|
2
|
+
# An archive of data in the Cache.
|
3
|
+
class Archive
|
4
|
+
include RuneRb::Core::Logging
|
5
|
+
|
6
|
+
# @!attribute [r] entries
|
7
|
+
# @return [Array<Hash>] the entries in the archive
|
8
|
+
attr_reader :entries
|
9
|
+
|
10
|
+
# Constructs a new CacheArchive
|
11
|
+
# @param entries [Array<Hash>] the entries in the archive
|
12
|
+
def initialize(entries)
|
13
|
+
@entries = entries
|
14
|
+
end
|
15
|
+
|
16
|
+
# Decodes an archive from the specified buffer.
|
17
|
+
# @param buffer [RuneRb::Core::Buffer] the buffer to decode
|
18
|
+
def self.decode(buffer)
|
19
|
+
extracted_size = buffer.read(type: :int24)
|
20
|
+
size = buffer.read(type: :int24)
|
21
|
+
extracted = false
|
22
|
+
|
23
|
+
if size != extracted_size
|
24
|
+
data = buffer.data.slice!(0..size)
|
25
|
+
data = StringIO.new(data)
|
26
|
+
decompressor = RBzip2.default_adapter::Decompressor.new(data)
|
27
|
+
buffer = RuneRb::Core::Buffer.new(mode: 'r')
|
28
|
+
buffer << decompressor.read
|
29
|
+
extracted = true
|
30
|
+
end
|
31
|
+
|
32
|
+
entry_count = buffer.read(type: :short)
|
33
|
+
identifiers = Array.new(entry_count)
|
34
|
+
extracted_sizes = Array.new(entry_count)
|
35
|
+
sizes = Array.new(entry_count)
|
36
|
+
|
37
|
+
entry_count.times do |i|
|
38
|
+
identifiers[i] = buffer.read(type: :int)
|
39
|
+
extracted_sizes[i] = buffer.read(type: :int24)
|
40
|
+
sizes[i] = buffer.read(type: :int24)
|
41
|
+
end
|
42
|
+
|
43
|
+
entries = Array.new(entry_count)
|
44
|
+
entry_count.times do |entry|
|
45
|
+
entry_buffer = RuneRb::Core::Buffer.new(mode: 'r')
|
46
|
+
|
47
|
+
if extracted == false
|
48
|
+
data = buffer.data.slice!(0..sizes[entry])
|
49
|
+
data = StringIO.new(data)
|
50
|
+
decompressor = RBzip2.default_adapter::Decompressor.new(data)
|
51
|
+
entry_buffer << decompressor.read
|
52
|
+
else
|
53
|
+
data = buffer.data.slice!(0..extracted_sizes[entry])
|
54
|
+
entry_buffer << data
|
55
|
+
end
|
56
|
+
|
57
|
+
entries[entry] = { id: identifiers[entry], buffer: entry_buffer }
|
58
|
+
end
|
59
|
+
|
60
|
+
RuneRb::Cache::Archive.new(entries)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module RuneRb::Cache::Constants
|
2
|
+
# The number of archives in the cache.
|
3
|
+
# @return [Integer]
|
4
|
+
ARCHIVE_COUNT = 0x9
|
5
|
+
|
6
|
+
# The size of a single index
|
7
|
+
# @return [Integer]
|
8
|
+
INDEX_SIZE = 0x6
|
9
|
+
|
10
|
+
# The size of a single data header
|
11
|
+
# @return [Integer]
|
12
|
+
HEADER_SIZE = 0x8
|
13
|
+
|
14
|
+
# The size of a chunk of data
|
15
|
+
# @return [Integer]
|
16
|
+
CHUNK_SIZE = 512
|
17
|
+
|
18
|
+
# The size of a single data block
|
19
|
+
# @return [Integer]
|
20
|
+
BLOCK_SIZE = HEADER_SIZE + CHUNK_SIZE;
|
21
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
module RuneRb::Cache
|
2
|
+
class FileSystem
|
3
|
+
include RuneRb::Core::Logging
|
4
|
+
|
5
|
+
# @attribute [r] cache
|
6
|
+
# @return [Hash<FileDescriptor, RuneRb::Cache::Archive>] a map of decoded archives.
|
7
|
+
attr_reader :cache
|
8
|
+
|
9
|
+
# @attribute [r] crc_table
|
10
|
+
# @return [RuneRb::Core::Buffer] the CRC table for the cache.
|
11
|
+
attr_reader :crc_table
|
12
|
+
|
13
|
+
# @attribute [r] crc
|
14
|
+
# @return [Array<Integer>] the CRC values for the cache.
|
15
|
+
attr_reader :crc
|
16
|
+
|
17
|
+
# @attribute [r] indicies
|
18
|
+
# @return [Array<StringIO>] the indicies for the cache.
|
19
|
+
attr_reader :indicies
|
20
|
+
|
21
|
+
# @attribute [r] data_file
|
22
|
+
# @return [StringIO] the data file for the cache.
|
23
|
+
attr_reader :data_file
|
24
|
+
|
25
|
+
# Constructs a new FileSystem instance.
|
26
|
+
# @param path [String] the path to the cache.
|
27
|
+
def initialize(path)
|
28
|
+
@indicies = Array.new
|
29
|
+
@crc_table = RuneRb::Core::Buffer.new(mode: 'r')
|
30
|
+
@crc = Array.new
|
31
|
+
@cache = Hash.new
|
32
|
+
@data_file = StringIO.new
|
33
|
+
read_layout(path)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Retrieves an {RuneRb::Cache::Archive} by the specified {FileDescriptor}.
|
37
|
+
# @param type [Integer] the file type.
|
38
|
+
# @param file [Integer] the file identifier.
|
39
|
+
def archive(type, file)
|
40
|
+
descriptor = FileDescriptor.new(type, file)
|
41
|
+
cached = @cache[descriptor]
|
42
|
+
|
43
|
+
if cached == nil
|
44
|
+
file = cache_file(descriptor)
|
45
|
+
cached = RuneRb::Cache::Archive.decode(file)
|
46
|
+
@cache[descriptor] = cached
|
47
|
+
end
|
48
|
+
|
49
|
+
cached
|
50
|
+
end
|
51
|
+
|
52
|
+
# Retrieves a {RuneRb::Core::Buffer} that corresponds to the specified {FileDescriptor} in the cache.
|
53
|
+
# @param descriptor [FileDescriptor] the descriptor to retrieve.
|
54
|
+
# @raise [RuntimeError] if a Chunk id does not match what is expected during cache file read.
|
55
|
+
# @raise [RuntimeError] if a type does not match descriptor type during cache file read.
|
56
|
+
# @raise [RuntimeError] if a file identifier does not match descriptor file identifier during cache file read.
|
57
|
+
# @return [RuneRb::Core::Buffer] the buffer containing data that corresponds to the specified descriptor.
|
58
|
+
def cache_file(descriptor)
|
59
|
+
index = index_for(descriptor)
|
60
|
+
buffer = RuneRb::Core::Buffer.new(mode: 'r')
|
61
|
+
|
62
|
+
position = index.block * RuneRb::Cache::BLOCK_SIZE
|
63
|
+
read = 0
|
64
|
+
size = index.size
|
65
|
+
blocks = size / RuneRb::Cache::CHUNK_SIZE
|
66
|
+
|
67
|
+
if size % RuneRb::Cache::CHUNK_SIZE != 0
|
68
|
+
blocks += 1
|
69
|
+
end
|
70
|
+
|
71
|
+
info "Reading #{blocks} blocks from position #{position}."
|
72
|
+
|
73
|
+
blocks.times do |i|
|
74
|
+
@data_file.seek(position)
|
75
|
+
header = @data_file.read
|
76
|
+
header_data = header.unpack('C*')
|
77
|
+
|
78
|
+
position += RuneRb::Cache::HEADER_SIZE
|
79
|
+
|
80
|
+
next_file = header_data[0] << 8 | header_data[1]
|
81
|
+
current_chunk = header_data[2] << 8 | header_data[3]
|
82
|
+
next_block = header_data[4] << 16 | header_data[5] << 8 | header_data[6]
|
83
|
+
next_type = header_data[7]
|
84
|
+
|
85
|
+
raise "Chunk id mismatch! (Current #{current_chunk}, Expected #{i})" if current_chunk != i
|
86
|
+
|
87
|
+
chunk_size = size - read
|
88
|
+
chunk_size = RuneRb::Cache::CHUNK_SIZE if chunk_size > RuneRb::Cache::CHUNK_SIZE
|
89
|
+
|
90
|
+
@data_file.seek(position)
|
91
|
+
buffer << @data_file.read
|
92
|
+
|
93
|
+
read += chunk_size
|
94
|
+
position = next_block * RuneRb::Cache::BLOCK_SIZE
|
95
|
+
|
96
|
+
if size > read
|
97
|
+
raise "Next type (#{next_type}) does not match descriptor type (#{descriptor.type + 1})." if next_type != descriptor.type + 1
|
98
|
+
raise "Next file (#{next_file}) does not match descriptor file (#{descriptor.file})." if next_file != descriptor.file
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
info "Read #{buffer.length} from cache."
|
103
|
+
|
104
|
+
buffer
|
105
|
+
end
|
106
|
+
|
107
|
+
def index_for(descriptor)
|
108
|
+
idx = descriptor.type
|
109
|
+
raise "Index out of bounds. (#{idx})" if idx < 0 || idx >= @indicies.length
|
110
|
+
|
111
|
+
buffer = String.new
|
112
|
+
idx_file = @indicies[idx]
|
113
|
+
position = descriptor.file * RuneRb::Cache::INDEX_SIZE
|
114
|
+
info "Reading index from position #{position}"
|
115
|
+
|
116
|
+
if position >= 0 && (idx_file.length >= (position + RuneRb::Cache::INDEX_SIZE))
|
117
|
+
idx_file.seek(position, IO::SEEK_CUR)
|
118
|
+
buffer << idx_file.read
|
119
|
+
else
|
120
|
+
raise "Could not find index file at position #{position}."
|
121
|
+
end
|
122
|
+
|
123
|
+
info " Length: #{buffer.length}, Index data: #{buffer.bytes}"
|
124
|
+
|
125
|
+
RuneRb::Cache::Index.decode(buffer)
|
126
|
+
end
|
127
|
+
|
128
|
+
def close
|
129
|
+
@indicies.each(&:close)
|
130
|
+
@data_file.close
|
131
|
+
end
|
132
|
+
|
133
|
+
# The number of index files in the cache.
|
134
|
+
# @return [Integer] the number of index files in the cache.
|
135
|
+
def cache_count
|
136
|
+
@indicies.length
|
137
|
+
end
|
138
|
+
|
139
|
+
# The number of files in a cache.
|
140
|
+
# @param cache [Integer] the cache to check.
|
141
|
+
def file_count(cache)
|
142
|
+
(@indicies[cache].size / RuneRb::Core::INDEX_SIZE) - 1
|
143
|
+
end
|
144
|
+
|
145
|
+
# Reads the layout of the cache from the specified path.
|
146
|
+
# @param path [String] the path to the cache directory.
|
147
|
+
# @raise [RuntimeError] if the cache archive is not found.
|
148
|
+
def read_layout(path)
|
149
|
+
raise "Cache archive not found. Please install them into the #{path} directory." unless check_for_archives(path)
|
150
|
+
|
151
|
+
# Find how many index files exist
|
152
|
+
count = 0.upto(255).each do |i|
|
153
|
+
break i unless File.exist?(File.join(path, "main_file_cache.idx#{i}"))
|
154
|
+
end
|
155
|
+
|
156
|
+
# Gather file objects
|
157
|
+
@data_file = File.open(File.join(path, "main_file_cache.dat"), "r")
|
158
|
+
|
159
|
+
count.times do |i|
|
160
|
+
data = File.read("#{path}/main_file_cache.idx#{i}")
|
161
|
+
@indicies[i] = StringIO.new(data)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# Checks for the existence of cache archives in a path.
|
166
|
+
# @param path [String] the path to the cache directory.
|
167
|
+
def check_for_archives(path)
|
168
|
+
return false if path.nil?
|
169
|
+
return false unless File.directory?(path)
|
170
|
+
return false unless File.exist?(path)
|
171
|
+
return false unless File.readable?(path)
|
172
|
+
return false if Dir.empty?(path)
|
173
|
+
true
|
174
|
+
end
|
175
|
+
|
176
|
+
FileDescriptor = Struct.new(:type, :file) do
|
177
|
+
def equals(other)
|
178
|
+
other.file == file && other.type == type
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module RuneRb::Cache
|
2
|
+
# An instance of a {CacheIndex} points to a file in the `main_file_cache.dat` file.
|
3
|
+
class Index
|
4
|
+
include RuneRb::Core::Logging
|
5
|
+
|
6
|
+
# @!attribute [r] size
|
7
|
+
# @return [Integer] the size of the file.
|
8
|
+
# @note This attribute is read-only.
|
9
|
+
attr_reader :size
|
10
|
+
|
11
|
+
# @!attribute [r] block
|
12
|
+
# @return [Integer] the block of the file.
|
13
|
+
# @note This attribute is read-only.
|
14
|
+
attr_reader :block
|
15
|
+
|
16
|
+
# Constructs a new Cache Index given the block size and identifier.
|
17
|
+
# @param size [Integer] the size of the block file
|
18
|
+
# @param block [Integer] the first block of the file
|
19
|
+
def initialize(size, block)
|
20
|
+
@size = size
|
21
|
+
@block = block
|
22
|
+
end
|
23
|
+
|
24
|
+
# Decodes a buffer into an index.
|
25
|
+
# @param buffer [String] the buffer to decode.
|
26
|
+
def self.decode(buffer)
|
27
|
+
#raise "Unexpected buffer length. Buffer #{buffer.bytesize}, Expected: #{RuneRb::Core::INDEX_SIZE}" unless buffer.bytesize == RuneRb::Core::INDEX_SIZE
|
28
|
+
|
29
|
+
bytes = buffer.unpack('C*')
|
30
|
+
size = bytes[0] << 16 | bytes[1] << 8 | bytes[2]
|
31
|
+
block = bytes[3] << 16 | bytes[4] << 8 | bytes[5]
|
32
|
+
info "Decoded index: size: #{size}, block: #{block}"
|
33
|
+
|
34
|
+
RuneRb::Cache::Index.new(size, block)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/rune/common.rb
CHANGED
@@ -35,6 +35,15 @@ module RuneRb
|
|
35
35
|
autoload :SetRefinements, 'rune/patches/set_refinements'
|
36
36
|
end
|
37
37
|
|
38
|
+
module Cache
|
39
|
+
autoload :Archive, 'rune/cache/archive'
|
40
|
+
autoload :Constants, 'rune/cache/constants'
|
41
|
+
autoload :FileSystem, 'rune/cache/file_system'
|
42
|
+
autoload :Index, 'rune/cache/index'
|
43
|
+
|
44
|
+
include RuneRb::Cache::Constants
|
45
|
+
end
|
46
|
+
|
38
47
|
# The Logger utility for the RuneRb framework.
|
39
48
|
# @return [Console::Logger] the logger instance.
|
40
49
|
def self.logger
|
data/lib/rune/core/buffer.rb
CHANGED
@@ -3,6 +3,11 @@ module RuneRb::Core
|
|
3
3
|
# A Buffer encapsulates raw data in a String instance. Depending on the mode, the buffer can be read from or written to.
|
4
4
|
class Buffer
|
5
5
|
|
6
|
+
# @!attribute [r] data
|
7
|
+
# @return [String] the data contained in the buffer.
|
8
|
+
# @note This attribute is read-only.
|
9
|
+
attr_reader :data
|
10
|
+
|
6
11
|
# Constructs a new Buffer instance.
|
7
12
|
# @param mode [String] the mode of the buffer.
|
8
13
|
def initialize(mode: 'rw')
|
data/lib/rune/core/constants.rb
CHANGED
@@ -19,6 +19,10 @@ module RuneRb::Core::Constants
|
|
19
19
|
# @return [Array<Integer>]
|
20
20
|
BIT_MASK_OUT = (0...32).collect { (1 << _1) - 1 }.freeze
|
21
21
|
|
22
|
+
# The number of archives in the cache.
|
23
|
+
# @return [Integer]
|
24
|
+
ARCHIVE_COUNT = 0x9
|
25
|
+
|
22
26
|
# The size of a single index
|
23
27
|
# @return [Integer]
|
24
28
|
INDEX_SIZE = 0x6
|
@@ -41,4 +45,4 @@ module RuneRb::Core::Constants
|
|
41
45
|
BIG: [0, 1, 2].freeze,
|
42
46
|
LITTLE: [2, 1, 0].freeze
|
43
47
|
}.freeze
|
44
|
-
end
|
48
|
+
end
|
data/lib/rune/core/ruby_isaac.rb
CHANGED
@@ -52,18 +52,14 @@ module RuneRb::Core::WriteableBuffer
|
|
52
52
|
# @param value [Integer] the medium value to write.
|
53
53
|
# @param mutation [String] the mutation made to the byte.
|
54
54
|
# @param order [String] the order in which bytes will be written.
|
55
|
-
def write_int24(value, mutation: :STD,
|
55
|
+
def write_int24(value, mutation: :STD, order: :BIG)
|
56
56
|
case order
|
57
57
|
when :BIG
|
58
58
|
write_byte(value >> 16)
|
59
59
|
write_byte(value >> 8)
|
60
|
-
write_byte(value, mutation: mutation
|
61
|
-
when :MIDDLE
|
62
|
-
write_byte(value >> 8)
|
63
|
-
write_byte(value, mutation: mutation, signed: signed)
|
64
|
-
write_byte(value >> 16)
|
60
|
+
write_byte(value, mutation: mutation)
|
65
61
|
when :LITTLE
|
66
|
-
write_byte(value, mutation: mutation
|
62
|
+
write_byte(value, mutation: mutation)
|
67
63
|
write_byte(value >> 8)
|
68
64
|
write_byte(value >> 16)
|
69
65
|
else raise "Unrecognized byte order: #{order}"
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rrb-common
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Patrick W.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-04-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rbzip2
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.3'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.3'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: dotenv
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -156,6 +170,10 @@ executables: []
|
|
156
170
|
extensions: []
|
157
171
|
extra_rdoc_files: []
|
158
172
|
files:
|
173
|
+
- lib/rune/cache/archive.rb
|
174
|
+
- lib/rune/cache/constants.rb
|
175
|
+
- lib/rune/cache/file_system.rb
|
176
|
+
- lib/rune/cache/index.rb
|
159
177
|
- lib/rune/common.rb
|
160
178
|
- lib/rune/core/archive.rb
|
161
179
|
- lib/rune/core/buffer.rb
|
@@ -187,7 +205,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
187
205
|
- !ruby/object:Gem::Version
|
188
206
|
version: '0'
|
189
207
|
requirements: []
|
190
|
-
rubygems_version: 3.
|
208
|
+
rubygems_version: 3.5.3
|
191
209
|
signing_key:
|
192
210
|
specification_version: 4
|
193
211
|
summary: Common utilities for RuneRb.
|