Code updated 12/26/12: Recursive file searching, loads shaders information, lots of cleaning up
Code: Select all
fPKG = getOpenFileName caption:"Choose Geometry File:" \
types:"Midtown Madness 2 (*.pkg)|*.pkg|"
if fPKG != undefined then (
f = fopen fPKG "rb"
clearlistener()
fn readFixedStr bstream fixedLen =
(
local str = ""
for i = 1 to fixedLen do
(
str+= bit.intAsChar (ReadByte bstream #unsigned)
)
str
)
fn getPos name: =
(
if name != unsupplied then (
Print ((name)+": 0x"+((bit.intAsHex(ftell f))as string))
) else (
Print ("Current position: 0x"+((bit.intAsHex(ftell f))as string))
)
)
pkgTyp=readFixedStr f 4
-- Must be PKG3 file, otherwise terminate
if ((pkgTyp.count != 0) and (pkgTyp == "PKG3")) then (
struct pkgDat (nSections, nVerticesTot, nIndiciesTot, nSections2, fFVF)
struct pkgSec (nStrips, nFlags, shaderOffset)
struct pVertex (x, y, z, nx, ny, nz, u, v)
print "Angel Studios PacKaGe File Format V3"
messageBox ("PKG3 file ("+(fPKG)+") loaded") title:"File type"
-- PKG files begin at offset 4
fseek f 4 #seek_set
-- We need to determine how many occurances of FILE there are
-- So recursively read each FILE (this method will not work for PKG2)
-- Ignore shaders and offset!
DAVE0=true
hitOffset=false
parse=true
numFiles = 0
filePosition=0
do (
getPos name:"FILE"
idf=readFixedStr f 4
fln=ReadByte f
fls=readFixedStr f fln
print fls
if fls == "shaders" then (
print ((numFiles as string)+" Geometry files found!")
print "End of geometry."
print "-------------------------"
shadersLength=ReadLong f
shadersPosition=ftell f
shadersOffset=shadersLength+shadersPosition
shadersType=ReadLong f
shadersPerPaintjob=ReadLong f
DAVE0=false
fseek f 0 #seek_set
print ("Shaders type: "+(shadersType as string))
print ("Shaders per paintjob: "+(shadersPerPaintjob as string))
print "End of shaders."
print "-------------------------"
) else (
numFiles += 1
fileLength=ReadLong f
filePosition=ftell f
fileOffset=fileLength+filePosition
fseek f 0 #seek_set
fseek f fileOffset #seek_cur
getPos name:"OFFSET"
)
) while DAVE0 == true
if parse == true do (
fseek f 4 #seek_set
for q = 1 to numFiles do (
idFILE=readFixedStr f 4 -- "FILE"
fLenName=ReadByte f #unsigned
fStrName=readFixedStr f fLenName
fFileLen=ReadLong f
-- PKG File Data
dataOffset = ftell f
Print ("pkgDAT: "+fStrName+" @ 0x"+((bit.intAsHex(dataOffset))as string))
fData = pkgDat nSections: (ReadLong f) nVerticesTot: (ReadLong f) nIndiciesTot: (ReadLong f) nSections2: (ReadLong f) fFVF: (ReadLong f)
for pd = 1 to fData.nSections do (
sectionOffset = ftell f
fSection = pkgSec nStrips: (ReadShort f #unsigned) nFlags: (ReadShort f #unsigned) shaderOffset: (ReadLong f)
fseek f sectionOffset #seek_set
Print ("pkgSEC: "+fStrName+" @ 0x"+((bit.intAsHex(sectionOffset))as string))
curVerts=#()
curFaces=#()
curUVs=#()
for s = 1 to fSection.nStrips do (
fNStrips=ReadShort f #unsigned -- Number of strips in this section
fUnkFlags=ReadShort f #unsigned -- Flags (unused in MM2)
fToShaders=ReadLong f -- Offset to assigned shader in list
-- PKG Strip
fPrimType=ReadLong f -- Primitive type for this strip (triangle)
fNVertices=ReadLong f
-- PKG Vertex
for v = 1 to fNVertices do (
vert = pVertex x: (ReadFloat f) y: (ReadFloat f) z: (ReadFloat f) nx: (ReadFloat f) ny: (ReadFloat f) nz: (ReadFloat f) u: (ReadFloat f) v: (ReadFloat f)
append curVerts[-vert.x,vert.z,vert.y]
append curUVs[vert.u,-vert.v,0]
)
fNIndicies=ReadLong f
for x = 1 to fNIndicies/3 do (
fa=ReadShort f #unsigned+1
fb=ReadShort f #unsigned+1
fc=ReadShort f #unsigned+1
append curFaces[fa,fb,fc]
)
)
pkg = mesh vertices:curVerts faces:curFaces
pkg.numTVerts = curUVs.count
buildTVFaces pkg
pkg.name=fStrName
for j = 1 to curUVs.count do setTVert pkg j curUVs[j]
for j = 1 to curFaces.count do setTVFace pkg j curFaces[j]
convertTo pkg PolyMeshObject
)
)
Print ("Last Read @ 0x"+((bit.intAsHex(ftell f))as string))
)
) else (
clearlistener()
messageBox "Unsupported file type, terminating!" title:"PKG Tool"
)
gc()
fclose f
) else (
clearlistener()
messageBox "No file was selected." title:"PKG Tool"
)
UVs are loaded perfectly as well:

My only problem is that each time it recursively searches each "Strip" from a section, it builds an entirely separate mesh based off of the information it was given. The reason the meshes get split is because the PKG file format has to offset to an entry in a shaders list, so it splits each "strip" into a separate object based on what material is assigned to it and how it corresponds to a shader entry.
I have tried EVERYTHING to solve this problem, but it just completely screws up the face order. Vertices are loaded, but faces are in the wrong order. If I could have it build a separate mesh each time then just attach them into one object, would the export process get screwed up? Or would I still be able to write in a [Vertex, Faces..Vertex, Faces...Vertex, Faces..] order? If that's all I have to do, great, someone please tell me!
All help is appreciated! Happy holidays and Merry christmas!


