~aleteoryx/mtg-pac

ref: 0fd560cb0fcf9d7f69b026999cb22a17b683afd0 mtg-pac/extract.tcl -rwxr-xr-x 2.2 KiB
0fd560cb — Aleteoryx damn thing works 3 months ago
                                                                                
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
#!/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"} {
			pvrt2tga::convert ${filebase}.${ext} ${filebase}.tga
			exec -- convert ${filebase}.tga ${filebase}.png
			file delete ${filebase}.tga
			puts "${file}: record $id (decompressed): Converted to PNG"
		}
	}
	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
}