A README.md => README.md +83 -0
@@ 0,0 1,83 @@
+script to extract the .PAC asset bundle format, present in (at least)
+magic the gathering for dreamcast. it also converts the PVRT textures
+to PNGs
+
+# usage:
+
+install tcl and imagemagick. in particular, make sure `convert` is
+present in $PATH. if you're on a unix, installing tcl should be
+trivial. on windows, it is available in a package called "magicsplat".
+YMMV.
+
+to run it, open a terminal and enter
+
+```
+$ ./unpac.tcl ./path/to/bundle.pac ./path/to/output/
+```
+
+this may take a while for a PAC with large images, as the PVRT->PNG
+decoder is largely implemented in tcl. optimization patches welcome.
+
+this will output a directory structure like:
+
+```
+./path/to/output/
+ xxxx.pvr - decompressed powervr texture image
+ xxxx.png - for each .pvr, a matching .png is created.
+
+ xxxx.njcm - ninja chunk model, raw 3d model data
+
+ xxxx.njtl - ninja texlist, texture mapping info for a model
+
+ xxxx.nmdm - ninja motion, animation
+
+ xxxx.bin - unknown decompressed record type
+ xxxx.rec - unknown record type
+```
+
+the PVRT converter is incomplete, and only supports the pixel/data
+modes present in magic the gathering. an unsupported PVRT will not be
+converted, but you can apply an external tool to it if need be.
+
+# details:
+
+.PAC is a pretty simple bundle format. it consists of a header, and a
+set of concatenated records, where each record begins with a 4-byte
+prefix specifying its type. it is a little-endian format.
+
+```
+Header Format (all values are 4 bytes):
+
+ +----------------+
+ 0x00 | "PAC\0" magic |
+ +----------------+
+ 0x04 | # of records |
+ +----------------+
+ 0x08 | data start pos |
+ +----------------+
+ 0x0c | record 1 end |
+ 0x10 | record 2 end |
+ | ... |
+ 0x?? | record # end |
+ +----------------+
+```
+
+the first record is data start bytes into the file, from the absolute
+beginning. it ends at record 1 end, and record 2 starts immediately
+after. the last entry in the record end table is the length of the
+file.
+
+4 record types are known:
+
+- `NZIP`, rest of record is deflate compressed data
+- `NJCM`, ninja chunk model
+- `NJTL`, ninja texlist
+- `NMDM`, ninja motion
+
+NZIP appears to be for storing PVRT images. the other types are
+well-known dreamcast sdk formats
+
+# license:
+
+if you pinky swear not to sue me for anything I pinky swear not to sue
+you for anything. not like I have lawyer money, anyway
M pvrt.tcl => pvrt.tcl +6 -3
@@ 204,9 204,8 @@ proc ::pvrt2tga::convert {src dst} {
seek $sfp 16
}
if {[read $sfp 4] != "PVRT"} {
- puts "$src not PVRT"
close $sfp
- return
+ return -code error "missing PVRT magic"
}
binary scan [read $sfp 12] iccsss len pfmt dfmt _ w h
@@ 216,7 215,11 @@ proc ::pvrt2tga::convert {src dst} {
set pdec [pfmt::lookup $pfmt]
set ddec [dfmt::lookup $dfmt]
-# puts "$src $dst $pdec $ddec $w $h"
+ if {$pdec == ""} {
+ return -code error "unsupported pixel format: $pfmt"
+ } elseif {$ddec == ""} {
+ return -code error "unsupported data format: $dfmt"
+ }
$ddec $pdec srcbuf dstbuf $w $h
R => unpac.tcl +8 -4
@@ 67,10 67,14 @@ foreach endpt $endtab {
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"
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 {