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
#!/bin/env tclsh
set file [dict get [info frame 0] file]
source [file dirname $file]/pvrt.tcl
proc fatal {num reason} {
global argv0
puts stderr "fatal: $argv0: $reason"
exit $num
}
if {[llength $argv] != 2} {
puts stderr "usage: $argv0 FILE.PAC OUTDIR/"
exit 1
}
lassign $argv file dir
set fp [open $file rb]
binary scan [read $fp 0xc] {iii} magic numents startpos
if {$magic != 0x00434150} {
die 2 "${file}: unknown magic: [format %08x $magic]"
}
set hdrlen [expr {0xc + ($numents * 4)}]
puts "${file}: header length: $hdrlen ($numents entries)"
puts "${file}: record start: $startpos"
set endhdr [read $fp [expr {$numents * 4}]]
binary scan $endhdr "i$numents" endtab
puts "${file}: record end table: $endtab"
seek $fp $startpos
file mkdir $dir
set pos $startpos
set i 0
foreach endpt $endtab {
set id [format %04d $i]
set filebase $dir/$id
set length [expr {$endpt - $pos}]
set data [read $fp $length]
set type [string range $data 0 3]
switch -- $type {
NZIP {
puts "${file}: record $id: Deflate Compressed"
set data [string range $data 8 end]
set decom [zlib inflate $data]
set magic [string range $decom 0 3]
if {$magic in {GBIX PVRT}} {
set ext pvr
puts "${file}: record $id (decompressed): Sega PowerVR Texture"
} else {
set ext bin
binary scan $type i tynum
puts "${file}: record $id (decompressed): Unknown (magic 0x[format %08x $tynum])"
}
set fp2 [open ${filebase}.${ext} wb]
puts $fp2 $decom
close $fp2
if {$ext == "pvr"} {
if {[catch {
pvrt2tga::convert ${filebase}.${ext} ${filebase}.tga
exec -- convert ${filebase}.tga ${filebase}.png
file delete ${filebase}.tga
puts "${file}: record $id (decompressed): Converted to PNG"
} why]} {
puts "${file}: record $id (decompressed): PNG Conversion Failed: $why"
}
}
}
NJCM {
puts "${file}: record $id: Ninja Chunk Model"
set fp2 [open ${filebase}.njcm wb]
puts $fp2 $data
close $fp2
}
NJTL {
puts "${file}: record $id: Ninja Texture List"
set fp2 [open ${filebase}.njtl wb]
puts $fp2 $data
close $fp2
}
NMDM {
puts "${file}: record $id: Ninja Motion"
set fp2 [open ${filebase}.nmdm wb]
puts $fp2 $data
close $fp2
}
default {
binary scan $type i tynum
puts "${file}: record $id: Unknown (magic 0x[format %08x $tynum])"
set fp2 [open ${filebase}.rec wb]
puts $fp2 $data
close $fp2
}
}
set pos $endpt
incr i
}