root/lang/ruby/asc3to2/swf.rb @ 7736

Revision 7736, 3.2 kB (checked in by gyuque, 5 years ago)

3to2: updated utils

Line 
1# swf.rb
2#  based on AsConverter.rb by KLab, Inc.
3
4require 'zlib'
5module SWF
6
7SWFTAG = {
8        9  => "SETBACKGROUNDCOLOR",
9        1  => "SHOWFRAME",
10        12 => "DOACTION",
11        39 => "DEFINESPRITE",
12        56 => "EXPORTASSETS",
13        59 => "INITACTION",
14        82 => "DOABC",
15        -1 => "unknown"
16}
17
18ACTIONS = {
19
20        0x0b => "SUBTRACT"    ,
21        0x0c => "MULTIPLY"    ,
22        0x0d => "DIVIDE"      ,
23        0x17 => "POP"         ,
24        0x12 => "LOGICALNOT"  ,
25#       0x18 => "INT"         ,
26        0x1c => "GETVARIABLE" ,
27        0x3d => "CALLFUNCTION",
28        0x3e => "RETURN"      ,
29        0x3f => "MODULO"      ,
30        0x40 => "NEW"         ,
31        0x41 => "VAR"         ,
32        0x42 => "INITARRAY"   ,
33        0x47 => "NEWADD"      ,
34        0x48 => "NEWLESSTHAN" ,
35        0x49 => "NEWEQUALS"   ,
36        0x4e => "GETMEMBER"   ,
37        0x4f => "SETMEMBER"   ,
38        0x50 => "INCREMENT"   ,
39        0x52 => "CALLMETHOD"  ,
40
41        0x87 => "SETREGISTER" ,
42        0x88 => "CONSTANTPOOL",
43        0x8e => "DEFINEFUNCTION2",
44        0x96 => "PUSHDATA"    ,
45        0x99 => "BRANCHALWAYS",
46        0x9d => "BRANCHIFTRUE"
47}
48
49class SWF
50        def load(filename)
51                bs  = nil
52
53                File.open(filename) {|infile|
54                        infile.binmode
55                        src = infile.read
56                        bs = make_bits(src)
57                }
58
59                # 最初の64ビットを無視
60                bs.read(64)
61
62                # RECT構造体
63                rl = bs.read_as_int(5) # 構造体各要素長さ
64                bs.read(5 + (4*rl))    # RECT構造体を無視
65
66                bs.align_byte
67
68                # ヘッダの残り32ビットを無視
69                bs.read(32)
70               
71                read_tags(bs)
72        end
73
74        def read_tags(bs)
75                begin
76                        tag_and_length = bs.read_short
77                        tag_id  = tag_and_length >> 6
78                        tag_len = tag_and_length & 0x3f
79
80                        break if tag_id == 0 # END tag
81
82                        # longタグ
83                        if (0x3f == tag_len)
84                                tag_len =       bs.read_as_int(8)         |
85                                                        (bs.read_as_int(8) << 8 ) |
86                                                        (bs.read_as_int(8) << 16) |
87                                                        (bs.read_as_int(8) << 24)
88                        end
89
90                        handle_tag(bs, tag_id, tag_len)
91                end while bs.empty?
92        end
93
94        def make_bits(src)
95                # ヘッダ部
96                ## CWS形式だったらswfを読み込み直す
97                if src[0] == 67 # 'C'
98                        bits = src[0,8].unpack("B*").to_s
99                        bits << Zlib::Inflate.inflate(src[8, src.length-8]).unpack("B*").to_s
100
101                        return BitStream.new(bits)
102                else
103                        return BitStream.new(src.unpack("B*").to_s)
104                end
105
106                raise "must not be reached"
107        end
108
109        def handle_tag(bs, tag_id, tag_len)
110                tagname = "unknown"
111                tagname = SWFTAG[tag_id] if SWFTAG.has_key?(tag_id)
112
113                handler_name = "tag#{tagname}"
114
115                # puts "tag=#{tagname} len=#{tag_len}"
116
117                # タグに対応するメソッドを探す
118                if respond_to?(handler_name)
119                        __send__(handler_name, bs, tag_len)
120                else
121                        # 未知のタグを読み飛ばす
122                        bs.read(8*tag_len)
123                end
124        end
125end
126
127class BitStream
128        def initialize(bits)
129                @bits = bits
130                @pos = 0
131                @length = bits.length
132        end
133
134        def empty?
135                return @pos < @length
136        end
137       
138        attr_reader :length
139
140        def read(count)
141                ret = @bits[@pos, count]
142                @pos += count
143
144                return ret
145        end
146
147        def read_byte(count = 1)
148                read(count*8)
149        end
150       
151        def read_as_stream(count)
152                BitStream.new(read(count))
153        end
154
155        def read_as_int(count)
156                ret = @bits[@pos, count]
157                @pos += count
158
159                return ret.to_i(2)
160        end
161
162        def read_short
163                read_as_int(8) | (read_as_int(8) << 8)
164        end
165
166        def align_byte
167                @pos += 8 - (@pos%8)
168        end
169end
170
171
172end # of module SWF
Note: See TracBrowser for help on using the browser.