Page 1 of 2
EA Tiger Woods 2012
Posted: Thu Apr 14, 2011 6:45 pm
by Mogulbasher
I am trying to extract some data from this game. Progress so far. I have extracted a series of XEN and TOC files from the ISO. Reading through the XEN files they had a number of references to 78 DA indicating a zlib compression routine using max compression. Using a zlib extractor I extracted a number of files some of which appear to be RSF files. These appear to contain the model data I am after. I am not sure whether anyone has done any work on RSF files in the past or whether they are a standard or proprietary format to EA.
Here is the top of the file...
Looking at this information it appears that the header section contains the following
RSF HEader
No Data
INFO header
Long 0
Long 80 (Appears to be overall length of INFO section)
Long 16 (Length of header data?)
Long 58 (Length of following filename)
Data Filename
BILD
Long 80 (Appears to be overall length of BILD section)
Long 16 (Length of header data?)
Long 7 (Length of Author)
Data Name
Long 25 (Length of time stamp)
Data Time Stamp
Long 11 (Length of date stamp)
Data Date Stamp
Padding
GEOM ( At this point I am a little lost as to what the following data is.
VFMT
VFMT
VFMT
This is followed by what appears to be three large sections of data
STRM
STRM
STRM
Finally towards the bottom of the file is some sort of index perhaps...
Firstly of mesh and texture lists
and finally of boundings
I have uploaded the whole file here is someone can help.
Download Here
Any advice or pointers greatly appreciated.
Re: EA Tiger Woods 2012
Posted: Sat Apr 16, 2011 9:06 pm
by Mogulbasher
Well I successfully wrote a c# application to extract all the textures but am still a little lost on the 3D model stuff. Anyone have any idea?
Re: EA Tiger Woods 2012
Posted: Sun Apr 17, 2011 9:05 pm
by Mogulbasher
Ok Brief Update. I have figured out the structure of the RSF file.
Basically it consists of a bunch of files as follows.
Magic
Unknown
Long Length of section
Long Length of Header
Long Length of Data
Long Number of Elements
Parsing this yields the following files
OFNI (Info)
DLIB
MOEG (Geometry)
TEXT (Textures)
RDHS (Shader)
LTAM (Materials)
SGRF (Some sort of Node based bounding)
Now that I have extracted all this stuff does anyone know what I do with them. Again any advice guidance or pointers will be appreciated.
Andrew
Re: EA Tiger Woods 2012
Posted: Sun Apr 17, 2011 9:10 pm
by chrrox
look at the code for Granado Espada or Valkyria Chronicles they are very close to your format and should give you some ideas on what to do.
Re: EA Tiger Woods 2012
Posted: Thu Apr 21, 2011 2:49 am
by Mogulbasher
Thanks for this. I have written a max script using yours as a base. Using the debugger I have validated that the data appears to be loading correctly.
The script runs without error and then ends. Am I missing something or should a model load in the screen.
The file I am running this on is located here
http://www.apcd2003.com/img/file4.zip
Again additional pointers greatly appreciated...Cant thank you enough for the progress to date...
Here is my messy script
Code: Select all
if (heapSize < 20000000) then
heapSize = 200000000 -- allow ~ 40 MB instead of just 7.5 MB. Prevents "Runtime Error: Out of scripter memory"
fname = getOpenFileName \
caption:"Open Tiger Woods Model File" \
types:"Tiger Woods Model File(*.rsf)|*.rsf" \
historyCategory:"Tiger Woods Object Presets"
f = fopen fname "rb"
fn floatSwap2 f =
(
i = bit.floatAsInt f
h = bit.intashex i
while h.count < 8 do h = "0" + h
s = (substring h 7 2) + (substring h 5 2) + (substring h 3 2) + (substring h 1 2)
bit.intAsFloat (bit.hexasint s)
)
fn ReadBEfloat fstream = (
return floatSwap2(readfloat fstream)
)
fn PrintOffset Var =
(
local Var = Var
print ("This is the offset 0x" + (bit.intAsHex Var) as string)
Var
)
fn PrintCount Var =
(
local Var = Var
print ("This is the Count 0x" + (bit.intAsHex Var) as string)
Var
)
fn ReadBEword fstream = (
return (bit.swapBytes (readshort fstream #unsigned) 1 2)
)
fn convertTo32 input16 = (
inputAsInt = input16
sign = bit.get inputAsInt 16
exponent = (bit.shift (bit.and inputAsInt (bit.hexasint "7C00")) -10) as integer - 16
fraction = bit.and inputAsInt (bit.hexasint "03FF")
if sign==true then sign = 1 else sign = 0
exponentF = exponent + 127
--Ouput 32 bit integer representing a 32 bit float
outputAsFloat = bit.or (bit.or (bit.shift fraction 13) (bit.shift exponentF 23)) (bit.shift sign 31)
--Output Check
return bit.intasfloat outputasfloat
)
fn ReadBEHalfFloat fstream = (
return convertTo32(ReadBEword fstream)
)
fn ReadBElong fstream = (
long = readlong fstream
long = bit.swapBytes long 1 4
long = bit.swapBytes long 2 3
return long
)
fn ReadFixedString bstream fixedLen =
(
local str = ""
for i = 1 to fixedLen do
(
str += bit.intAsChar (ReadByte bstream #unsigned)
)
str
)
struct Face_Offset_Struct
(
ID,Face_Offset
)
struct Vert_Info_Struct
(
u01,u02,u03,VCount,FCount,n01,u04,VPos,FPos,n02,n03
)
magicsize = 16
moegsize = 20
MRTS_Array = #()
XDNI_Array = #()
fseek f 0x18#seek_set
infosize = ReadLong f
fseek f 0x20#seek_set
modelnamesize = Readlong f
modelname = ReadFixedString f modelnamesize
--break()
fseek f (infosize + magicsize + 8)#seek_set
dlibsize = Readlong f
--break()
fseek f (infosize+magicsize+dlibsize+16)#seek_set
nbrTFMV = Readlong f
regionsize=0
--break()
for t = 1 to nbrTFMV do (
idstring = ReadFixedString f 4
secsize = Readlong f
regionsize = secsize+regionsize +8
fseek f (infosize+magicsize+dlibsize+moegsize+regionsize)#seek_set
idstring = ReadFixedString f 4
if idstring !="TMFV" do(
regionsize = regionsize+1
)
fseek f (infosize+magicsize+dlibsize+moegsize+regionsize)#seek_set
--break()
)
numobjects = Readlong f
Vert_array = #()
Normal_array = #()
UV_array = #()
Face_array = #()
--break()
for i=1 to numobjects do(
SecStart = (ftell f)
idstring = ReadFixedString f 4
print idstring
SecHeader = 17
fseek f 0x05#seek_cur
--break()
NumVerts = Readlong f
VertLength = Readlong f
VertType = Readlong f
SecSize = VertLength * NumVerts
--break()
for k=1 to NumVerts do (
if VertLength == 44 Do (
vx = Readfloat f
vy = Readfloat f
vz = Readfloat f
tu = Readfloat f
tv = Readfloat f
uk = Readfloat f
uk = Readfloat f
uk = Readfloat f
uk = Readfloat f
uk = Readfloat f
uk = Readfloat f
)
if VertLength == 32 Do (
vx = ReadBEfloat f
vy = ReadBEfloat f
vz = ReadBEfloat f
tu = Readfloat f
tv = Readfloat f
uk = Readfloat f
uk = Readfloat f
uk = Readfloat f
)
if VertLength == 52 Do (
vx = ReadBEfloat f
vy = ReadBEfloat f
vz = ReadBEfloat f
tu = Readfloat f
tv = Readfloat f
uk = Readfloat f
uk = Readfloat f
uk = Readfloat f
uk = Readfloat f
uk = Readfloat f
uk = Readfloat f
uk = Readfloat f
uk = Readfloat f
)
--break()
append Vert_array [vx,vy,vz]
--append Normal_array [nx,ny,nz]
append UV_array [tu,tv,0]
)
--break()
)
--break()
numobjects = Readlong f
print numobjects
--break()
for i=1 to numobjects do(
SecStart = (ftell f)
idstring = ReadFixedString f 4
print idstring
SecHeader = 17
fseek f 0x05#seek_cur
NumFace = Readlong f
NumFace = NumFace / 3
SecSize = (NumFace*2)
--break()
append XDNI_Array SecStart
for k = 1 to NumFace do (
f1= Readshort f +1
f2 = Readshort f +1
f3 = Readshort f +1
append Face_array [(f1),(f3),(f2)]
--break()
)
fseek f 0x04#seek_cur
SecEnd= (ftell f)
--break()
)
break()
msh = mesh vertices:Vert_array faces:Face_array
break()
msh.numTVerts = UV_array.count
break()
buildTVFaces msh
for j = 1 to UV_array.count do setTVert msh j UV_array[j]
for j = 1 to Face_array.count do setTVFace msh j Face_array[j]
for j = 1 to Normal_array.count do setNormal msh j Normal_array[j]
fclose f
Re: EA Tiger Woods 2012
Posted: Thu Apr 21, 2011 3:06 am
by chrrox
what you want to do is store all the offsets of the mesh and index locations then after you parse the file create a loop that loops to the first part of each section
fseek vert1 start #seek_set
read first verts
fseek f face1 start#seek_set
read first faces
build mesh here
next loop
if you notice all the indecies are based on the vert sections so the id's do not constantly increase into one big array like you have them.
At-least if i am reading your script correctly.
Re: EA Tiger Woods 2012
Posted: Thu Apr 21, 2011 11:37 pm
by Mogulbasher
Great.... That got it sort of working. At least I see something inside MAX now. I am just looking at the first model in the file of 83 models. However, clearly I have not got the right pieces in the right places. What is the best way to figure that out. I have vert sections that range from 28 byte to 52 byte depending on the model. They dont appear to all be the same so for example while the 44 byte one clearly starts with x,y,z the 28 one does not have verts at the beginning. I cant figure out how to tell a normal from a texture coord and when I should look for half floats full floats or shorts even.
Any more advice... I am getting there albeit slowly, but as I said this is the first time I tried to do anything like this.
Ta...Andrew
Re: EA Tiger Woods 2012
Posted: Fri Apr 22, 2011 1:35 am
by chrrox
make sure you reset your array after creating each section
so put the
vert_array = #()
ext
inside your mesh import loop
Re: EA Tiger Woods 2012
Posted: Fri Apr 22, 2011 1:53 am
by Mogulbasher
Yup understood. I had not done that.. But how do you normally go about figuring out which of the floats are normals and which are UVs Is it just a case of trial and error? OR is there some sort of rule of thumb? Tomorrow I will post a couple of pieces to explain.
Re: EA Tiger Woods 2012
Posted: Fri Apr 22, 2011 2:12 am
by chrrox
you can look at the data values that will tell you what type of data it is. but if you import different parts as verts in max normals will look like a sphere and uv's will look like the uv map if you set the z to 0.
Re: EA Tiger Woods 2012
Posted: Fri Apr 22, 2011 8:46 pm
by Mogulbasher
Quick Follow Up. The meshes are importing but it seems as if the faces are out. In other words it is connecting the faces incorrectly. Is there a method to find out in what order the faces should be

Re: EA Tiger Woods 2012
Posted: Fri Apr 22, 2011 9:01 pm
by chrrox
you are importing them as tri list they are most likely tri strip.
Re: EA Tiger Woods 2012
Posted: Fri Apr 22, 2011 9:27 pm
by Mogulbasher
ok it looks like the model verts and model faces are not stored in order so I guess somewhere is a listing of the model and where the verts are and where the faces are. Guess I will have to hunt it down
On your post unfortunately I have no idea what that means

Re: EA Tiger Woods 2012
Posted: Sat Apr 23, 2011 1:11 am
by chrrox
tri list means the triangles are stored like this
123
234
345
456
ext
in tri strip they give you
123
then they just give you
4
5
6
and what you assume is the last 2 faces you read are the first 2 of the next triangle
so 123 then i read 4 becomes
234
think of a square made of 2 triangles
you draw the first triangle which is 3 points 1 2 3
now you only need 1 more dot to make the other triangle
4 then you reuse the edge of the triangle they would share.
Re: EA Tiger Woods 2012
Posted: Sat Apr 23, 2011 12:55 pm
by Mogulbasher
Thanks for that I understand it now. I think I had it right it is just that unfortunately mesh order stored in file is not same as face order... Go figure.. So I went through each face section identified the highest face value and then searched for a mesh with that number of verts and here is what I got
So my next question is how do I go about bringing in the mappings so when I apply a texture to it it works. Thanks again for all your help, you have no idea the amount of time you have saved me yet allowing me to somewhat figure it out.
A