summaryrefslogtreecommitdiff
path: root/VP-miscwork.lua
blob: 1a5bc14f23234fb9761bf026fe38b82c99146419 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
function process_arcgfx(fname, h, size, ext)
    log("Processing " .. fname .. "." .. ext)
    if dump_mode then
        o = Output(fname .. "." .. ext)
        o:copyfrom(h, size)
        o:destroy()
        h:seek(-size, SEEK_CUR)
    end
    log("Extracting " .. fname .. " - format 'arcgfx'")
    dump_mkdir(fname)
    local nfiles = h:readU32()
    local extra = h:readU32()
    local ret
    if dump_mode then
        o = Output(fname .. "/--extra.bin")
        o:writeU32(extra)
        o:destroy()
        o = Output(fname .. string.format("/0000-%08X", extra))
        o:writeU32(extra)
        o:destroy()
    else
        ret = Buffer(true)
        ret:writeU32(nfiles)
        ret:writeU32(extra)
    end
    
    index = {}
    for i = 1, nfiles do
        index[i] = {}
        index[i].extra = h:readU32()
        index[i].size = h:readU32()
    end
    
    local outfile = {}
    local script = nil
    local font = nil
    for i = 1, nfiles do
        local tell = h:tell()
        local handler = nil
        local counter = 1
        local f1 = andB(index[i].extra, 0xffffff00)
        if dump_mode and f1 == 0x00300900 then
            if script then error "Can't have two scripts" end
            handler = function(fname, h, size, ext)
                if counter == 1 then
                    log "taking script"
                    script = Buffer(true)
                    script:copyfrom(h)
                else
                    error "Too many files"
                end
                counter = counter + 1
            end
        elseif dump_mode and f1 == 0x00300800 then
            if font then error "Can't have two fonts" end
            handler = function(fname, h, size, ext)
                if counter == 1 then
                    log "taking font"
                    font = Buffer(true)
                    font:copyfrom(h)
                else
                    error "Too many files"
                end
                counter = counter + 1
            end
        elseif not dump_mode and f1 == 0x00300900 then
            error "Not written yet"
        elseif not dump_mode and f1 == 0x00300800 then
            error "Not written yet"
        end
        outfile[i] = process_single_file(fname .. string.format("/%04i-%08X", i, index[i].extra), h, index[i].size, ext, handler)
        
        if handler and script and font then
            if dump_mode then
                extract_simple_script(fname .. string.format("/%04i", i), script, font)
            end
            script:destroy()
            font:destroy()
            script = nil
            font = nil
        end
        h:seek(tell + index[i].size)
    end
    
    if not dump_mode then
        for i = 1, nfiles do
            local alignment_bytes = alignment(outfile[i]:getsize(), 4)
            for j = 1, alignment_bytes do
                outfile[i]:writeU8(0)
            end
            ret:writeU32(index[i].extra)
            ret:writeU32(outfile[i]:getsize())
        end
        for i = 1, nfiles do
            ret:copyfrom(outfile[i])
            outfile[i]:destroy()
        end
    end
    
--    return ret
end

function process_cscript(fname, h, size, ext)
    log("Processing " .. fname .. ".slz")
    log("Extracting " .. fname .. " - format 'cscript'")
    local counter = 1
    local script
    local font
    local handler = function(fname, h, size, ext)
        if counter == 1 then
            log "taking script"
            script = Buffer(true)
            script:copyfrom(h)
        elseif counter == 2 then
            log "taking font"
            font = Buffer(true)
            font:copyfrom(h)
        else
            error "Too many files"
        end
        counter = counter + 1
    end

    process_single_file(fname, h, h:getsize(), ext, handler)

    if not script or not font then error "Not enough files" end
    if dump_mode then
        extract_simple_script(fname, script, font)
    end
    script:destroy()
    font:destroy()
end

function process_carc(fname, h, size, ext)
    log("Processing " .. fname .. "." .. ext)
    if dump_mode then
        o = Output(fname .. "." .. ext)
        o:copyfrom(h, size)
        o:destroy()
        h:seek(-size, SEEK_CUR)
    end
    log("Extracting " .. fname .. " - format 'carc'")
    dump_mkdir(fname)
    local nfiles = h:readU32()
    local ret
    if not dump_mode then
        ret = Buffer(true)
        ret:writeU32(nfiles)
    end
    
    local index = {}
    for i = 1, nfiles do
        index[i] = {}
        local offset = h:readU32()
        index[i].extra = shr(offset, 24)
        index[i].offset = andB(offset, 0xffffff)
    end

    index[nfiles + 1] = {}
    index[nfiles + 1].extra = 0
    index[nfiles + 1].offset = size

    local outfile = {}
    local script = nil
    local font = nil
    for i = 1, nfiles do
        local tell = h:tell()
        local handler = nil
        local counter = 1
        if index[i].extra == 3 then
            handler = function(fname, h, size, ext)
                if counter ~= 1 then error "Too many files" end
                counter = counter + 1
                return process_carc(fname, h, size, ext)
            end
        elseif dump_mode and index[i].extra == 2 then
            if script then error "Can't have two scripts" end
            handler = function(fname, h, size, ext)
                if counter == 1 then
                    log "taking script"
                    script = Buffer(true)
                    script:copyfrom(h)
                else
                    error "Too many files"
                end
                counter = counter + 1
            end
        elseif dump_mode and index[i].extra == 1 then
            if font then error "Can't have two fonts" end
            handler = function(fname, h, size, ext)
                if counter == 1 then
                    log "taking font"
                    font = Buffer(true)
                    font:copyfrom(h)
                else
                    error "Too many files"
                end
                counter = counter + 1
            end
        elseif not dump_mode and index[i].extra == 2 then
            error "Not written yet"
        elseif not dump_mode and index[i].extra == 1 then
            error "Not written yet"
        end
        local fsize = index[i + 1].offset - index[i].offset
        outfile[i] = process_single_file(fname .. string.format("/%04i-%08X", i, index[i].extra), h, fsize, ext, handler)
        
        if handler and script and font then
            if dump_mode then
                second_style_script = true
                extract_simple_script(fname .. string.format("/%04i", i), script, font)
                second_style_script = false
            end
            script:destroy()
            font:destroy()
            script = nil
            font = nil
        end
        h:seek(tell + fsize)
    end
    
    if not dump_mode then
        for i = 1, nfiles do
            local alignment_bytes = alignment(outfile[i]:getsize(), 4)
            for j = 1, alignment_bytes do
                outfile[i]:writeU8(0)
            end
            ret:writeU32(index[i].extra)
            ret:writeU32(outfile[i]:getsize())
        end
        for i = 1, nfiles do
            ret:copyfrom(outfile[i])
            outfile[i]:destroy()
        end
    end
    
--    return ret
end