format codes

This commit is contained in:
Ishotihadus
2019-11-21 22:20:36 +09:00
parent 5c32fc9b8c
commit 9d189b2550
12 changed files with 1648 additions and 1626 deletions
+7 -5
View File
@@ -1,14 +1,16 @@
require "bundler/gem_tasks" # frozen_string_literal: true
require "rake/extensiontask"
require 'bundler/gem_tasks'
require 'rake/extensiontask'
task :scream do task :scream do
puts "みくは自分を曲げないよ!" puts 'みくは自分を曲げないよ!'
end end
task :build => :compile task build: :compile
Rake::ExtensionTask.new('decoders/native') do |ext| Rake::ExtensionTask.new('decoders/native') do |ext|
ext.lib_dir = 'lib/mikunyan' ext.lib_dir = 'lib/mikunyan'
end end
task :default => [:clobber, :compile, :spec] task default: %i[clobber compile spec]
+9 -7
View File
@@ -1,11 +1,13 @@
require "mikunyan/version" # frozen_string_literal: true
require "mikunyan/asset_bundle" require 'mikunyan/version'
require "mikunyan/asset"
require "mikunyan/binary_reader" require 'mikunyan/asset_bundle'
require "mikunyan/object_value" require 'mikunyan/asset'
require "mikunyan/type_tree" require 'mikunyan/binary_reader'
require "mikunyan/constants" require 'mikunyan/object_value'
require 'mikunyan/type_tree'
require 'mikunyan/constants'
# Module for deserializing Unity Assets and AssetBundles # Module for deserializing Unity Assets and AssetBundles
module Mikunyan module Mikunyan
+22 -22
View File
@@ -1,3 +1,5 @@
# frozen_string_literal: true
module Mikunyan module Mikunyan
# Class for representing Unity Asset # Class for representing Unity Asset
# @attr_reader [String] name Asset name # @attr_reader [String] name Asset name
@@ -53,23 +55,23 @@ module Mikunyan
# @param [String] name Asset name (automatically generated if not specified) # @param [String] name Asset name (automatically generated if not specified)
# @return [Mikunyan::Asset] deserialized Asset object # @return [Mikunyan::Asset] deserialized Asset object
def self.file(file, name = nil) def self.file(file, name = nil)
name = File.basename(name, '.*') unless name name ||= File.basename(name, '.*')
Asset.load(File.binread(file), name) Asset.load(File.binread(file), name)
end end
# Returns list of all path IDs # Returns list of all path IDs
# @return [Array<Integer>] list of all path IDs # @return [Array<Integer>] list of all path IDs
def path_ids def path_ids
@objects.map{|e| e.path_id} @objects.map(&:path_id)
end end
# Returns list of containers # Returns list of containers
# @return [Array<Hash>,nil] list of all containers # @return [Array<Hash>,nil] list of all containers
def containers def containers
obj = parse_object(1) obj = parse_object(1)
return nil unless obj && obj.m_Container && obj.m_Container.array? return nil unless obj&.m_Container && obj.m_Container.array?
obj.m_Container.value.map do |e| obj.m_Container.value.map do |e|
{:name => e.first.value, :preload_index => e.second.preloadIndex.value, :path_id => e.second.asset.m_PathID.value} { name: e.first.value, preload_index: e.second.preloadIndex.value, path_id: e.second.asset.m_PathID.value }
end end
end end
@@ -113,12 +115,10 @@ module Mikunyan
return nil return nil
end end
klass = (obj.class_idx ? @klasses[obj.class_idx] : @klasses.find{|e| e.class_id == obj.class_id} || @klasses.find{|e| e.class_id == obj.type_id}) klass = (obj.class_idx ? @klasses[obj.class_idx] : @klasses.find{|e| e.class_id == obj.class_id} || @klasses.find{|e| e.class_id == obj.type_id})
if klass && klass.type_tree && klass.type_tree.nodes[0] if klass&.type_tree && klass.type_tree.nodes[0]
klass.type_tree.nodes[0].type klass.type_tree.nodes[0].type
elsif klass elsif klass
Mikunyan::CLASS_ID[klass.class_id] Mikunyan::CLASS_ID[klass.class_id]
else
nil
end end
end end
@@ -153,10 +153,10 @@ module Mikunyan
class_id = br.i32 class_id = br.i32
br.adv(1) br.adv(1)
script_id = br.i16 script_id = br.i16
if class_id < 0 || class_id == 114 hash = if class_id < 0 || class_id == 114
hash = br.read(32) br.read(32)
else else
hash = br.read(16) br.read(16)
end end
@klasses << Klass.new(class_id, script_id, hash, has_type_trees ? TypeTree.load(br) : TypeTree.load_default(hash)) @klasses << Klass.new(class_id, script_id, hash, has_type_trees ? TypeTree.load(br) : TypeTree.load_default(hash))
end end
@@ -165,10 +165,10 @@ module Mikunyan
type_tree_count = br.i32u type_tree_count = br.i32u
type_tree_count.times do type_tree_count.times do
class_id = br.i32 class_id = br.i32
if class_id < 0 hash = if class_id < 0
hash = br.read(32) br.read(32)
else else
hash = br.read(16) br.read(16)
end end
@klasses << Klass.new(class_id, nil, hash, has_type_trees ? TypeTree.load(br) : TypeTree.load_default(hash)) @klasses << Klass.new(class_id, nil, hash, has_type_trees ? TypeTree.load(br) : TypeTree.load_default(hash))
end end
@@ -190,10 +190,10 @@ module Mikunyan
path_id = long_object_ids ? br.i64 : br.i32 path_id = long_object_ids ? br.i64 : br.i32
offset = br.i32u offset = br.i32u
size = br.i32u size = br.i32u
if @format >= 17 @objects << if @format >= 17
@objects << ObjectData.new(path_id, offset, size, nil, nil, br.i32u, @format <= 10 && br.i16 != 0) ObjectData.new(path_id, offset, size, nil, nil, br.i32u, @format <= 10 && br.i16 != 0)
else else
@objects << ObjectData.new(path_id, offset, size, br.i32, br.i16, nil, @format <= 10 && br.i16 != 0) ObjectData.new(path_id, offset, size, br.i32, br.i16, nil, @format <= 10 && br.i16 != 0)
end end
br.adv(2) if 11 <= @format && @format <= 16 br.adv(2) if 11 <= @format && @format <= 16
br.adv(1) if 15 <= @format && @format <= 16 br.adv(1) if 15 <= @format && @format <= 16
@@ -231,10 +231,10 @@ module Mikunyan
data = nil data = nil
size = parse_object_private(br, children.find{|e| e[:name] == 'size'}).value size = parse_object_private(br, children.find{|e| e[:name] == 'size'}).value
data_type_tree = children.find{|e| e[:name] == 'data'} data_type_tree = children.find{|e| e[:name] == 'data'}
if node.type == 'TypelessData' data = if node.type == 'TypelessData'
data = br.read(size * data_type_tree[:node].size) br.read(size * data_type_tree[:node].size)
else else
data = size.times.map{ parse_object_private(br, data_type_tree) } size.times.map{parse_object_private(br, data_type_tree)}
end end
r = ObjectValue.new(node.name, node.type, br.endian, data) r = ObjectValue.new(node.name, node.type, br.endian, data)
elsif node.size == -1 elsif node.size == -1
@@ -242,7 +242,7 @@ module Mikunyan
if children.size == 1 && children[0][:name] == 'Array' && children[0][:node].type == 'Array' && children[0][:node].array? if children.size == 1 && children[0][:name] == 'Array' && children[0][:node].type == 'Array' && children[0][:node].array?
if node.type == 'string' if node.type == 'string'
size = parse_object_private(br, children[0][:children].find{|e| e[:name] == 'size'}).value size = parse_object_private(br, children[0][:children].find{|e| e[:name] == 'size'}).value
r.value = br.read(size * children[0][:children].find{|e| e[:name] == 'data'}[:node].size).force_encoding("utf-8") r.value = br.read(size * children[0][:children].find{|e| e[:name] == 'data'}[:node].size).force_encoding('utf-8')
br.align(4) if children[0][:node].flags & 0x4000 != 0 br.align(4) if children[0][:node].flags & 0x4000 != 0
else else
r.value = parse_object_private(br, children[0]).value r.value = parse_object_private(br, children[0]).value
@@ -255,7 +255,7 @@ module Mikunyan
r[child[:name]] = parse_object_private(br, child) r[child[:name]] = parse_object_private(br, child)
end end
end end
elsif children.size > 0 elsif !children.empty?
pos = br.pos pos = br.pos
r = ObjectValue.new(node.name, node.type, br.endian) r = ObjectValue.new(node.name, node.type, br.endian)
r.is_struct = true r.is_struct = true
@@ -326,7 +326,7 @@ module Mikunyan
tree = {} tree = {}
stack = [] stack = []
nodes.each do |node| nodes.each do |node|
this = {:name => node.name, :node => node, :children => []} this = { name: node.name, node: node, children: [] }
if node.depth == 0 if node.depth == 0
tree = this tree = this
else else
+7 -5
View File
@@ -1,3 +1,5 @@
# frozen_string_literal: true
require 'extlz4' require 'extlz4'
require 'extlzma' require 'extlzma'
@@ -61,9 +63,9 @@ module Mikunyan
if compressed if compressed
br.adv(4) br.adv(4)
block_count = br.i32u block_count = br.i32u
blocks = block_count.times.map{{ :c => br.i32u, :u => br.i32u }} blocks = block_count.times.map{{ c: br.i32u, u: br.i32u }}
br.jmp(header_size) br.jmp(header_size)
data = String.new data = ''
blocks.each{|b| data << LZMA.decode(br.read(b[:c]))} blocks.each{|b| data << LZMA.decode(br.read(b[:c]))}
br = BinaryReader.new(data) br = BinaryReader.new(data)
else else
@@ -96,13 +98,13 @@ module Mikunyan
blocks = [] blocks = []
block_count = head.i32u block_count = head.i32u
block_count.times{ blocks << {:u => head.i32u, :c => head.i32u, :f => head.i16u} } block_count.times{blocks << { u: head.i32u, c: head.i32u, f: head.i16u }}
asset_blocks = [] asset_blocks = []
asset_count = head.i32u asset_count = head.i32u
asset_count.times{ asset_blocks << {:offset => head.i64u, :size => head.i64u, :status => head.i32, :name => head.cstr} } asset_count.times{asset_blocks << { offset: head.i64u, size: head.i64u, status: head.i32, name: head.cstr }}
raw_data = String.new raw_data = ''
blocks.each{|b| raw_data << uncompress(br.read(b[:c]), b[:u], b[:f])} blocks.each{|b| raw_data << uncompress(br.read(b[:c]), b[:u], b[:f])}
asset_blocks.each do |b| asset_blocks.each do |b|
+5 -3
View File
@@ -1,3 +1,5 @@
# frozen_string_literal: true
require 'bin_utils' require 'bin_utils'
module Mikunyan module Mikunyan
@@ -62,7 +64,7 @@ module Mikunyan
# Read string until null character # Read string until null character
# @return [String] string # @return [String] string
def cstr def cstr
r = @data.unpack("@#{pos}Z*")[0] r = @data.unpack1("@#{pos}Z*")
@pos += r.bytesize + 1 @pos += r.bytesize + 1
r r
end end
@@ -145,14 +147,14 @@ module Mikunyan
# Read 32bit floating point value # Read 32bit floating point value
def float def float
r = little? ? @data.byteslice(@pos, 4).unpack('e')[0] : @data.byteslice(@pos, 4).unpack('g')[0] r = little? ? @data.byteslice(@pos, 4).unpack1('e') : @data.byteslice(@pos, 4).unpack1('g')
@pos += 4 @pos += 4
r r
end end
# Read 64bit floating point value # Read 64bit floating point value
def double def double
r = little? ? @data.byteslice(@pos, 8).unpack('E')[0] : @data.byteslice(@pos, 8).unpack('G')[0] r = little? ? @data.byteslice(@pos, 8).unpack1('E') : @data.byteslice(@pos, 8).unpack1('G')
@pos += 8 @pos += 8
r r
end end
+5 -2
View File
@@ -1,5 +1,8 @@
# frozen_string_literal: true
module Mikunyan module Mikunyan
private private
STRING_TABLE = { STRING_TABLE = {
0 => 'AABB', 0 => 'AABB',
5 => 'AnimationClip', 5 => 'AnimationClip',
@@ -101,7 +104,7 @@ module Mikunyan
1006 => 'Vector4f', 1006 => 'Vector4f',
1015 => 'm_ScriptingClassIdentifier', 1015 => 'm_ScriptingClassIdentifier',
1042 => 'Gradient' 1042 => 'Gradient'
} }.freeze
CLASS_ID = { CLASS_ID = {
1 => 'GameObject', 1 => 'GameObject',
@@ -340,5 +343,5 @@ module Mikunyan
1112 => 'SubstanceImporter', 1112 => 'SubstanceImporter',
1113 => 'LightmapParameters', 1113 => 'LightmapParameters',
1120 => 'LightmapSnapshot' 1120 => 'LightmapSnapshot'
} }.freeze
end end
+2
View File
@@ -1,3 +1,5 @@
# frozen_string_literal: true
require 'mikunyan/decoders/image_decoder' require 'mikunyan/decoders/image_decoder'
module Mikunyan module Mikunyan
+12 -10
View File
@@ -1,4 +1,10 @@
begin; require 'oily_png'; rescue LoadError; require 'chunky_png'; end # frozen_string_literal: true
begin
require 'oily_png'
rescue LoadError
require 'chunky_png'
end
require 'bin_utils' require 'bin_utils'
require 'mikunyan/decoders/native' require 'mikunyan/decoders/native'
@@ -23,7 +29,7 @@ module Mikunyan
bin = bin.value bin = bin.value
fmt = fmt.value fmt = fmt.value
if bin.size == 0 && object['m_StreamData'] if bin.empty? && object['m_StreamData']
bin = object['m_StreamData'].value bin = object['m_StreamData'].value
return nil unless bin return nil unless bin
end end
@@ -89,8 +95,6 @@ module Mikunyan
decode_rg16(width, height, bin) decode_rg16(width, height, bin)
when 63 when 63
decode_r8(width, height, bin) decode_r8(width, height, bin)
else
nil
end end
end end
@@ -315,7 +319,7 @@ module Mikunyan
mem = String.new(capacity: width * height * 3) mem = String.new(capacity: width * height * 3)
unpackstr = endian == :little ? 'e' : 'g' unpackstr = endian == :little ? 'e' : 'g'
(width * height).times do |i| (width * height).times do |i|
c = f2i(bin.byteslice(i*4, 4).unpack(unpackstr)[0]) c = f2i(bin.byteslice(i * 4, 4).unpack1(unpackstr))
BinUtils.append_int8!(mem, c, c, c) BinUtils.append_int8!(mem, c, c, c)
end end
ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
@@ -435,13 +439,11 @@ module Mikunyan
bin = bin.value if bin.class == ObjectValue bin = bin.value if bin.class == ObjectValue
if width && height && fmt && astc_list[fmt] if width && height && fmt && astc_list[fmt]
header = "\x13\xAB\xA1\x5C".force_encoding('ascii-8bit') header = "\x13\xAB\xA1\x5C".force_encoding('ascii-8bit')
header << [astc_list[fmt], astc_list[fmt], 1].pack("C*") header << [astc_list[fmt], astc_list[fmt], 1].pack('C*')
header << [width].pack("V").byteslice(0, 3) header << [width].pack('V').byteslice(0, 3)
header << [height].pack("V").byteslice(0, 3) header << [height].pack('V').byteslice(0, 3)
header << "\x01\x00\x00" header << "\x01\x00\x00"
header + bin header + bin
else
nil
end end
end end
+4 -2
View File
@@ -1,3 +1,5 @@
# frozen_string_literal: true
module Mikunyan module Mikunyan
# Class for representing decoded object # Class for representing decoded object
# @attr [String] name object name # @attr [String] name object name
@@ -81,12 +83,12 @@ module Mikunyan
# Return value of called key # Return value of called key
# @param [String] name key # @param [String] name key
# @return [Object] value # @return [Object] value
def method_missing(name, *args) def method_missing(name, *_args)
@attr[name.to_s] @attr[name.to_s]
end end
# Implementation of respond_to_missing? # Implementation of respond_to_missing?
def respond_to_missing?(symbol, include_private) def respond_to_missing?(symbol, _include_private)
@attr.key?(symbol.to_s) @attr.key?(symbol.to_s)
end end
end end
+10 -8
View File
@@ -1,3 +1,5 @@
# frozen_string_literal: true
module Mikunyan module Mikunyan
# Class for representing TypeTree # Class for representing TypeTree
# @attr [Array<Mikunyan::TypeTree::Node>] nodes list of all nodes # @attr [Array<Mikunyan::TypeTree::Node>] nodes list of all nodes
@@ -27,15 +29,15 @@ module Mikunyan
end end
buffer = br.read(buffer_size) buffer = br.read(buffer_size)
nodes.each do |n| nodes.each do |n|
if n.type >= 0 n.type = if n.type >= 0
n.type = buffer.unpack("@#{n.type}Z*")[0] buffer.unpack1("@#{n.type}Z*")
else else
n.type = Mikunyan::STRING_TABLE[n.type + 2**31] Mikunyan::STRING_TABLE[n.type + 2**31]
end end
if n.name >= 0 n.name = if n.name >= 0
n.name = buffer.unpack("@#{n.name}Z*")[0] buffer.unpack1("@#{n.name}Z*")
else else
n.name = Mikunyan::STRING_TABLE[n.name + 2**31] Mikunyan::STRING_TABLE[n.name + 2**31]
end end
end end
r = TypeTree.new r = TypeTree.new
@@ -49,7 +51,7 @@ module Mikunyan
def self.load_legacy(br) def self.load_legacy(br)
nodes = [] nodes = []
stack = [0] stack = [0]
while stack.size > 0 until stack.empty?
depth = stack.pop depth = stack.pop
type = br.cstr type = br.cstr
name = br.cstr name = br.cstr
@@ -71,7 +73,7 @@ module Mikunyan
# @param [String] hash # @param [String] hash
# @return [Mikunyan::TypeTree,nil] created TypeTree # @return [Mikunyan::TypeTree,nil] created TypeTree
def self.load_default(hash) def self.load_default(hash)
hash_str = hash.unpack('H*')[0] hash_str = hash.unpack1('H*')
file = File.expand_path("../typetrees/#{hash_str}.dat", __FILE__) file = File.expand_path("../typetrees/#{hash_str}.dat", __FILE__)
return nil unless File.file?(file) return nil unless File.file?(file)
r = TypeTree.new r = TypeTree.new
+3 -1
View File
@@ -1,4 +1,6 @@
# frozen_string_literal: true
module Mikunyan module Mikunyan
# version string # version string
VERSION = "3.9.6" VERSION = '3.9.6'
end end
+17 -16
View File
@@ -1,31 +1,32 @@
# coding: utf-8 # frozen_string_literal: true
lib = File.expand_path("../lib", __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) lib = File.expand_path('lib', __dir__)
require "mikunyan/version" $:.unshift(lib) unless $:.include?(lib)
require 'mikunyan/version'
Gem::Specification.new do |spec| Gem::Specification.new do |spec|
spec.name = "mikunyan" spec.name = 'mikunyan'
spec.version = Mikunyan::VERSION spec.version = Mikunyan::VERSION
spec.authors = ["Ishotihadus"] spec.authors = ['Ishotihadus']
spec.email = ["hanachan.pao@gmail.com"] spec.email = ['hanachan.pao@gmail.com']
spec.summary = "Unity asset deserializer for Ruby" spec.summary = 'Unity asset deserializer for Ruby'
spec.description = "Library to deserialize Unity assetbundles and assets." spec.description = 'Library to deserialize Unity assetbundles and assets.'
spec.homepage = "https://github.com/Ishotihadus/mikunyan" spec.homepage = 'https://github.com/Ishotihadus/mikunyan'
spec.license = "MIT" spec.license = 'MIT'
spec.files = `git ls-files -z`.split("\x0").reject do |f| spec.files = `git ls-files -z`.split("\x0").reject do |f|
f.match(%r{^(test|spec|features)/}) f.match(%r{^(test|spec|features)/})
end end
spec.bindir = "exe" spec.bindir = 'exe'
spec.executables = spec.files.grep(%r{^exe/}){|f| File.basename(f)} spec.executables = spec.files.grep(%r{^exe/}){|f| File.basename(f)}
spec.require_paths = ["lib"] spec.require_paths = ['lib']
spec.extensions = ["ext/decoders/native/extconf.rb"] spec.extensions = ['ext/decoders/native/extconf.rb']
spec.add_dependency 'extlz4', '~> 0'
spec.add_dependency 'extlzma', '~> 0'
spec.add_dependency 'bin_utils', '~> 0' spec.add_dependency 'bin_utils', '~> 0'
spec.add_dependency 'chunky_png', '~> 1' spec.add_dependency 'chunky_png', '~> 1'
spec.add_dependency 'extlz4', '~> 0'
spec.add_dependency 'extlzma', '~> 0'
spec.add_dependency 'json', '~> 2' spec.add_dependency 'json', '~> 2'
spec.add_development_dependency 'bundler', '~> 1' spec.add_development_dependency 'bundler', '~> 1'