Hello there! i try search models from this game in unpacked data with idtool, what i found in Model Researcher:
I newbie on hex founding meshes and etc, but have some success but i don't understand where and how to find UV, if someone have a time help me out please, sample files will be below.
P.S. i think skeletal data in same file as mesh (i've research 00d.dat), i don't know now what file is .dbr maybe texture.
UPDATE: I don't understand how to find UV in hex table, right, or where i can start, i know for UV need use UV tab, if you possible found UV let me know how and where it start in hex or just do a sample screen from model researcher.
https://dropmefiles.com/1oa1x
Important information: this site is currently scheduled to go offline indefinitely by end of the year.
Fahrenheit (Indigo Prophecy) 2005 EU PC - Research
-
- veteran
- Posts: 84
- Joined: Sat Oct 08, 2016 11:56 am
- Has thanked: 17 times
- Been thanked: 55 times
Re: Fahrenheit (Indigo Prophecy) 2005 EU PC - Help find UV
After finding the vertices, you can start looking for the normals, because they can be visualized. Texture coordinates can also be rendered in the Texture tab.
You do not have the required permissions to view the files attached to this post.
-
- advanced
- Posts: 53
- Joined: Wed Aug 12, 2015 11:59 pm
- Has thanked: 27 times
- Been thanked: 5 times
Re: Fahrenheit (Indigo Prophecy) 2005 EU PC - Research
I'll remane topic for better name becouse it is not about UV only now.
And with new question, for who made exporters models, How i can better know when model info start?
I want do export script for noesis or console app (c#) for find mesh (vertex\normal\UV) then export it by OBJ or SMD, becouse look game files one by one is hard and kill lots of time.
And what ive try search match by hex like
and next bytes are verteces but not all it is 2D 2D 2D 2D 2D 2D 2D 2D sometime its just start, and i want to know where i need start to know where vertex a begun, or get position of start or count of vertex\normal\UV and etc. or maybe have tools who hust find vertex of file and try to generate model or some code, becouse if i can't know start of model i think i've can't do batch export of model.
I've appreciate help with c# code, noesis or blender scripts, or just tip how to parse model then next or check by nothing meshes found.
Here a bunch of samples https://dropmefiles.com/soqWc
P.S. If some have tutorial for that link me, please maybe it help me.
And with new question, for who made exporters models, How i can better know when model info start?
I want do export script for noesis or console app (c#) for find mesh (vertex\normal\UV) then export it by OBJ or SMD, becouse look game files one by one is hard and kill lots of time.
And what ive try search match by hex like
Code: Select all
08 00 00 00 08 00 00 00 2D 2D 2D 2D 2D 2D 2D 2D
I've appreciate help with c# code, noesis or blender scripts, or just tip how to parse model then next or check by nothing meshes found.
Here a bunch of samples https://dropmefiles.com/soqWc
P.S. If some have tutorial for that link me, please maybe it help me.
- shakotay2
- MEGAVETERAN
- Posts: 4286
- Joined: Fri Apr 20, 2012 9:24 am
- Location: Nexus, searching for Jim Kirk
- Has thanked: 1147 times
- Been thanked: 2242 times
Re: Fahrenheit (Indigo Prophecy) 2005 EU PC - Research
Counts should not be a big deal if you're a coder:
. Search for 000001000200 to find start of face indices block(s).
End of block 2D2D [2D...?]
Counts to follow, see picture.
To get start of vertices (0x6f80 for "hand" here) do a backward search for 080000002D2D2D2D2D2D2D2D
(so backwards 2D2D2D2D2D2D2D2D00000008) starting from FI's start address (0x8f10 for "hand" in this sample).
That's how I'd do it.
Don't know whether this applies for all sub meshes/all samples - just found this on a quick glance!
And please: it spells "because", not "becouse".
. Search for 000001000200 to find start of face indices block(s).
End of block 2D2D [2D...?]
Counts to follow, see picture.
To get start of vertices (0x6f80 for "hand" here) do a backward search for 080000002D2D2D2D2D2D2D2D
(so backwards 2D2D2D2D2D2D2D2D00000008) starting from FI's start address (0x8f10 for "hand" in this sample).
That's how I'd do it.
Don't know whether this applies for all sub meshes/all samples - just found this on a quick glance!
And please: it spells "because", not "becouse".
You do not have the required permissions to view the files attached to this post.
Tuts: a) Bigchillghost, viewtopic.php?f=29&t=17889
b) Extracting simple models: http://forum.xentax.com/viewtopic.php?f=29&t=10894
"Quoting the whole thing. Would u ever stop this nonsense?"
b) Extracting simple models: http://forum.xentax.com/viewtopic.php?f=29&t=10894
"Quoting the whole thing. Would u ever stop this nonsense?"
-
- advanced
- Posts: 53
- Joined: Wed Aug 12, 2015 11:59 pm
- Has thanked: 27 times
- Been thanked: 5 times
Re: Fahrenheit (Indigo Prophecy) 2005 EU PC - Research
Very thanks shakotay2, excuse me for mistake in english, i try search how to convert hex faces into tri-stripes, when i read just short (2 byte int16) it looks like quads:
but i need tri strips like that, how it looks in model researcher:
for example, this is may noob question but i didn't understand and can't see simple tutorial how to convert quad to tri-stripts, but i see many peoples do that in exporters, if some one can teach me with sample or code i will be appreciate it.
P.S. This is what i want in the end:
Code: Select all
f 0 1 2 2
f 3 3 3 4
f 5 6 7 8
f 9 10 11 12
f 13 14 15 16
f 16 10 10 8
f 17 17 18 18
Code: Select all
f 0 1 2
f 3 4 5
f 6 5 4
f 5 6 7
f 8 7 6
f 7 8 9
f 10 9 8
f 9 10 11
f 12 11 10
f 11 12 13
f 14 13 12
f 13 14 15
f 16 15 14
f 10 8 17
f 20 19 18
P.S. This is what i want in the end:
Code: Select all
f 1/1/1 2/2/2 3/3/3
f 4/4/4 5/5/5 6/6/6
f 7/7/7 6/6/6 5/5/5
f 6/6/6 7/7/7 8/8/8
f 9/9/9 8/8/8 7/7/7
f 8/8/8 9/9/9 10/10/10
f 11/11/11 10/10/10 9/9/9
f 10/10/10 11/11/11 12/12/12
f 13/13/13 12/12/12 11/11/11
f 12/12/12 13/13/13 14/14/14
f 15/15/15 14/14/14 13/13/13
f 14/14/14 15/15/15 16/16/16
f 17/17/17 16/16/16 15/15/15
f 11/11/11 9/9/9 18/18/18
- shakotay2
- MEGAVETERAN
- Posts: 4286
- Joined: Fri Apr 20, 2012 9:24 am
- Location: Nexus, searching for Jim Kirk
- Has thanked: 1147 times
- Been thanked: 2242 times
Re: Fahrenheit (Indigo Prophecy) 2005 EU PC - Research
For the hand (no quads afaics) the tri strips look like so (using hex2obj):
f 1 2 3
f 4 6 5
f 5 6 7
f 6 8 7
f 7 8 2
f 8 9 2
f 2 9 3
f 9 10 3
...
and the algo used (usually?) is to be found here:
edit: the link I gave above was for auto creating triangle strips, so not correct here!
see remark here:
f 1 2 3
f 4 6 5
f 5 6 7
f 6 8 7
f 7 8 2
f 8 9 2
f 2 9 3
f 9 10 3
...
and the algo used (usually?) is to be found here:
But there's different ways/algos so may not apply to every mesh.
edit: the link I gave above was for auto creating triangle strips, so not correct here!
see remark here:
Last edited by shakotay2 on Fri Feb 19, 2021 2:15 pm, edited 1 time in total.
Tuts: a) Bigchillghost, viewtopic.php?f=29&t=17889
b) Extracting simple models: http://forum.xentax.com/viewtopic.php?f=29&t=10894
"Quoting the whole thing. Would u ever stop this nonsense?"
b) Extracting simple models: http://forum.xentax.com/viewtopic.php?f=29&t=10894
"Quoting the whole thing. Would u ever stop this nonsense?"
-
- advanced
- Posts: 53
- Joined: Wed Aug 12, 2015 11:59 pm
- Has thanked: 27 times
- Been thanked: 5 times
Re: Fahrenheit (Indigo Prophecy) 2005 EU PC - Research
@shakotay2 i try find vertex and faces count by 2D 2D 2D 2D pattern and 6 of 8 will be successful, but sometime it without 2D 2D 2D 2D at the end, just store after faces end like on image, this is eyeball, one of it, second, first eye ball will have 2D 2D 2D 2D at the end.
You do not have the required permissions to view the files attached to this post.
-
- advanced
- Posts: 53
- Joined: Wed Aug 12, 2015 11:59 pm
- Has thanked: 27 times
- Been thanked: 5 times
Re: Fahrenheit (Indigo Prophecy) 2005 EU PC - Research
I've try search pair (vert. face count) and found only two possitions, after face ind. and before vertex data of model i think.
try to search more maybe i found postions or better pattern to stop using 2D 2D 2D 2D.
Code: Select all
part ofs. vcount fcount
1 6300 CA 00 00 00 55 02 00 00
2 8EA0 CA 00 00 00 62 02 00 00
3 BA60 21 00 00 00 6E 00 00 00
4 C7D0 21 00 00 00 68 00 00 00
5 D530 46 03 00 00 F9 08 00 00
6 17190 23 02 00 00 A3 06 00 00
7 1D5D0 65 01 00 00 EB 02 00 00
8 214F0 28 00 00 00 40 00 00 00
-
- advanced
- Posts: 53
- Joined: Wed Aug 12, 2015 11:59 pm
- Has thanked: 27 times
- Been thanked: 5 times
Re: Fahrenheit (Indigo Prophecy) 2005 EU PC - Research
@shakotay2 I've looking at your code and test it on c#, i im right it generate faces from vertex count?
Ive get this from build_tristrips:
It looks like okay firts time, but in model research faces tab sometime faces looks like that:
And i don't see simiral from my output, its gonna be like:
and etc.
Picture below how it look in blender.
Ive get this from build_tristrips:
Code: Select all
f 1 2 3
f 2 4 3
f 3 4 5
f 4 6 5
f 5 6 7
f 6 8 7
f 7 8 9
f 8 10 9
f 9 10 11
Code: Select all
f 204 191 208
f 191 204 192
f 199 192 204
f 192 199 193
f 15 16 26
f 250 26 16
f 26 250 32
f 105 32 250
f 32 105 41
f 95 41 105
Code: Select all
f 248 250 249
f 249 250 251
f 250 252 251
f 251 252 253
f 252 254 253
f 253 254 255
f 254 256 255
f 255 256 257
f 256 258 257
...
f 475 476 477
f 476 478 477
f 477 478 479
f 478 480 479
...
Picture below how it look in blender.
You do not have the required permissions to view the files attached to this post.
-
- advanced
- Posts: 53
- Joined: Wed Aug 12, 2015 11:59 pm
- Has thanked: 27 times
- Been thanked: 5 times
Re: Fahrenheit (Indigo Prophecy) 2005 EU PC - Research
@shakotay2 Ive made it work! A big thanks for the code!
Ive just give f1 f2 f3 my faces and input facecount from faces list and hooray miracle it look fine!
P.S. i may post c# code if you want a look a it, i just little edit your C code sample.
Ive just give f1 f2 f3 my faces and input facecount from faces list and hooray miracle it look fine!
P.S. i may post c# code if you want a look a it, i just little edit your C code sample.
You do not have the required permissions to view the files attached to this post.
- shakotay2
- MEGAVETERAN
- Posts: 4286
- Joined: Fri Apr 20, 2012 9:24 am
- Location: Nexus, searching for Jim Kirk
- Has thanked: 1147 times
- Been thanked: 2242 times
Re: Fahrenheit (Indigo Prophecy) 2005 EU PC - Research
Upps, well, sorry! My fault, what I linked was the code for auto generated triangle strips. But f1, f2 should not be preset for existing face indices. So f1= GetFaceIndex(...); f2= GetFaceIndex(...); (That's what you've changed probably.)
Feel free to post it here - might help others, too.P.S. i may post c# code if you want a look a it, i just little edit your C code sample.
Tuts: a) Bigchillghost, viewtopic.php?f=29&t=17889
b) Extracting simple models: http://forum.xentax.com/viewtopic.php?f=29&t=10894
"Quoting the whole thing. Would u ever stop this nonsense?"
b) Extracting simple models: http://forum.xentax.com/viewtopic.php?f=29&t=10894
"Quoting the whole thing. Would u ever stop this nonsense?"
- Bigchillghost
- double-veteran
- Posts: 1026
- Joined: Tue Jul 05, 2016 9:37 am
- Has thanked: 31 times
- Been thanked: 1211 times
Re: Fahrenheit (Indigo Prophecy) 2005 EU PC - Research
The byte 0x2D (the char '-') is merely a character for padding when the data block is not aligned to 0x10 bytes. The count fields of the vertices/indices are usually stored before corresponding data blocks, if there's no further info (size fields, offsets etc.) stored ahead that can help determining how to read the data correctly. There seems to always be a 0x130-byte header before the vertices block, with the fixed signature 70 01 95 00. So if you must do it by searching for a signature, this should be a good choice.
You do not have the required permissions to view the files attached to this post.
May you find peace in this puzzle-solving game.
- An Imitable Workflow for Reverse Engineering a Game Model
- Advanced Mesh Reaper
- Reverse Model Wireframe
-
- ultra-veteran
- Posts: 586
- Joined: Sun Jun 05, 2005 12:00 pm
- Location: Ontario, Canada
- Has thanked: 36 times
- Been thanked: 243 times
Re: Fahrenheit (Indigo Prophecy) 2005 EU PC - Research
Only thing i've been able to find are heads, I'm guessing there is a different block type that holds weighted geometry...
I usually would write a program to import directly into blender or 3dsmax, but I gave C# a go and wrote this exporter.
Code: Select all
/*
C# Programs, dumps geometry from data file to obj from Fahrenheit (Indigo Prophecy) 2005
Author: mariokart64n
Date: February 19, 2021
more info:
https://forum.xentax.com/viewtopic.php?f=16&t=23441
*/
using System;
using System.IO;
using System.Text;
namespace PackExtract {
class Program {
static Encoding enc8 = Encoding.UTF8; // Required for ReadString Function
static int readShort(ref Byte[] buffer, ref int ptr) {
// Converts Unsigned 16bit Integer from the buffer
int word = 0;
word += buffer[ptr + 1] * 0x00000100;
word += buffer[ptr + 0] * 0x00000001;
ptr += 2;
return word;
}
static int readLong(ref Byte[] buffer, ref int ptr) {
// Converts Unsigned 32bit Integer from the buffer
int dword = 0;
dword += buffer[ptr + 3] * 0x01000000;
dword += buffer[ptr + 2] * 0x00010000;
dword += buffer[ptr + 1] * 0x00000100;
dword += buffer[ptr + 0] * 0x00000001;
ptr += 4;
return dword;
}
static double readFloat(ref Byte[] buffer, ref int ptr) {
int inputAsInt = readLong(ref buffer, ref ptr);
double fraction = 0.0F;
for (int i = 0; i < 23; i++) {
fraction += (1 & (inputAsInt >> ((23 - i) - 1))) * (Math.Pow(2, -(i + 1)));
}
int sign = -1;
if (((inputAsInt >> 31) & 0x00000001) == 0) {
sign = 1;
}
return (sign * (1 + fraction) * (Math.Pow(2, (((inputAsInt & 0x7F800000) >> 23) - 127))));
}
static string ReadString(ref Byte[] buffer, ref int pos, int length) {
// Reads a string from the buffer
string output = String.Empty;
Decoder decoder8 = enc8.GetDecoder();
int nChars = decoder8.GetCharCount(buffer, pos, length);
char[] chars = new char[nChars];
nChars = decoder8.GetChars(buffer, pos, length, chars, 0);
output += new String(chars, 0, nChars);
pos += length;
return output.Replace("\0", string.Empty);
}
static void Main(string[] args) {
Console.WriteLine("===========================================================\n");
Console.WriteLine("OBJ Dumper for Fahrenheit (Indigo Prophecy) 2005\n");
Console.WriteLine("Written By:\tmariokart64n");
Console.WriteLine("Released:\tFebruary 19, 2021\n");
Console.WriteLine(" https://forum.xentax.com/viewtopic.php?f=16&t=23441\n");
Console.WriteLine("===========================================================\n\n");
// Check that an argument was supplied
if (args.Length > 0) {
// Set Filepath
string file = args[0];
Console.WriteLine("File:\t{0}\n", file);
// Open File into a FileStream
var fs = new FileStream(file, FileMode.Open);
// Read File into byte[] Array
var fsize = (int)fs.Length;
var buffer = new byte[fsize];
fs.Read(buffer, 0, fsize);
fs.Close();
// Read file id
int ptr = 0;
int i = 0;
int fileID1 = 0;
int fileID2 = 0;
if (fsize > 8) {
fileID1 = readLong(ref buffer, ref ptr);
fileID2 = readLong(ref buffer, ref ptr);
}
if (fileID1 == 0x41544144 && fileID2 == 0x4B4E4142) {
int unk01 = readLong(ref buffer, ref ptr); // always 1?
int filesize = readLong(ref buffer, ref ptr);
int count = readShort(ref buffer, ref ptr);
int unk03 = readLong(ref buffer, ref ptr); // count?
int unk04 = readLong(ref buffer, ref ptr); // 0
int unk05 = readLong(ref buffer, ref ptr); // addr?
int unk06 = readLong(ref buffer, ref ptr); // count?
int unk10 = 0;
int unk11 = 0;
int unk12 = 0;
int addr = 0;
int hash1 = 0;
int hash2 = 0;
int meshCount = 0;
int vertCount = 0;
int faceCount = 0;
string objfile = "";
bool faceCW = true;
int f1 = 0;
int f2 = 0;
int f3 = 0;
int faceOffset = 0;
double x = 0.0F;
double y = 0.0F;
double z = 0.0F;
double w = 0.0F;
if (count > 0) {
for (int b = 0; b < count; b++) {
ptr = 0x20 + (b * 0x10);
unk10 = readLong(ref buffer, ref ptr); // ?
unk11 = readLong(ref buffer, ref ptr); // ?
unk12 = readLong(ref buffer, ref ptr); // always 0
addr = readLong(ref buffer, ref ptr);
ptr = addr;
hash1 = readLong(ref buffer, ref ptr);
hash2 = readLong(ref buffer, ref ptr);
if (hash1 == 0x00931B68 && hash2 == 0x00ADA1F8) {
Console.WriteLine("MESHDATA{0}: [{1}{2}]\t@ {3}\n", b, hash1, hash2, addr);
ptr += 0x14;
meshCount = readLong(ref buffer, ref ptr);
Console.WriteLine("MESHCOUNT\t{0}\n-------------------------------------\n", meshCount);
ptr += 0x03E0;
faceOffset = 1;
for (int m = 0; m < meshCount; m++) {
Console.WriteLine(" SUBMESH\t{0}\n", m);
ptr += 0x60;
vertCount = readLong(ref buffer, ref ptr);
faceCount = readLong(ref buffer, ref ptr);
Console.WriteLine(" VERTCOUNT\t{0}\n", vertCount);
Console.WriteLine(" FACECOUNT\t{0}\n", faceCount);
ptr += 0x0108;
Console.WriteLine(" POSITIONS\t@ {0}\n", ptr);
for (i = 0; i < vertCount; i++) {
objfile += "v " + (readFloat(ref buffer, ref ptr)).ToString("0.000000");
objfile += " " + (readFloat(ref buffer, ref ptr)).ToString("0.000000");
objfile += " " + (readFloat(ref buffer, ref ptr)).ToString("0.000000") + "\n";
ptr += 4;
}
objfile += "\n";
Console.WriteLine(" NORMALS\t@ {0}\n", ptr);
for (i = 0; i < vertCount; i++) {
x = readFloat(ref buffer, ref ptr);
y = readFloat(ref buffer, ref ptr);
z = readFloat(ref buffer, ref ptr);
w = readFloat(ref buffer, ref ptr);
//x *= w; y *= w; z *= w;
w = Math.Sqrt(Math.Pow(x, 2) + Math.Pow(y, 2) + Math.Pow(z, 2));
x /= w; y /= w; z /= w;
objfile += "vn " + (x).ToString("0.000000");
objfile += " " + (y).ToString("0.000000");
objfile += " " + (z).ToString("0.000000") + "\n";
}
objfile += "\n";
Console.WriteLine(" TEXCOORD\t@ {0}\n", ptr);
for (i = 0; i < vertCount; i++) {
objfile += "vt " + (readFloat(ref buffer, ref ptr)).ToString("0.000000");
objfile += " " + (-readFloat(ref buffer, ref ptr)).ToString("0.000000") + " 0.000000\n";
}
ptr += (16-(ptr % 16)) % 16;
objfile += "\n";
Console.WriteLine(" PRIMITIVES\t@ {0}\n", ptr);
objfile += "o mesh_" + m.ToString("0") + "\n";
objfile += "g mesh_" + m.ToString("0") + "\n";
i = 0;
while (i < faceCount) {
faceCW = true;
f1 = readShort(ref buffer, ref ptr);
f2 = readShort(ref buffer, ref ptr);
i+=2;
while (i < faceCount) {
f3 = readShort(ref buffer, ref ptr);
if (f3 == 0xFFFF || f3 == -1) {break;}
if (f1 != f2 && f2 != f3 && f3 != f1) {
if (faceCW) {
objfile += "f " + (f1 + faceOffset).ToString("0");
objfile += "/" + (f1 + faceOffset).ToString("0");
objfile += "/" + (f1 + faceOffset).ToString("0");
objfile += " " + (f2 + faceOffset).ToString("0");
objfile += "/" + (f2 + faceOffset).ToString("0");
objfile += "/" + (f2 + faceOffset).ToString("0");
objfile += " " + (f3 + faceOffset).ToString("0");
objfile += "/" + (f3 + faceOffset).ToString("0");
objfile += "/" + (f3 + faceOffset).ToString("0") + "\n";
}
else {
objfile += "f " + (f1 + faceOffset).ToString("0");
objfile += "/" + (f1 + faceOffset).ToString("0");
objfile += "/" + (f1 + faceOffset).ToString("0");
objfile += " " + (f3 + faceOffset).ToString("0");
objfile += "/" + (f3 + faceOffset).ToString("0");
objfile += "/" + (f3 + faceOffset).ToString("0");
objfile += " " + (f2 + faceOffset).ToString("0");
objfile += "/" + (f2 + faceOffset).ToString("0");
objfile += "/" + (f2 + faceOffset).ToString("0") + "\n";
}
}
faceCW = !faceCW;
f1 = f2; f2 = f3;
i += 1;
}
}
ptr += (16-(ptr % 16)) % 16;
objfile += "\n";
faceOffset += vertCount;
Console.WriteLine(" END BLOCK\t@ {0}\n-------------------------------------\n", ptr);
}
}
else {
//Console.WriteLine("Unknown Block [{0}{1}]\t@ {2}\n", hash1, hash2, addr);
}
}
}
if (objfile != "") {
using (StreamWriter outputFile = new StreamWriter(Path.Combine(Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(file) + ".obj"), false)) {
outputFile.WriteLine(objfile);
}
}
}
else {
// Warning User that File Is Invalid
Console.WriteLine("Invalid File");
}
}
else {Console.WriteLine("Usage:\n\tdat_obj_dumper.exe <dat_file>");}
Console.WriteLine("\n\n\tPress Any Key to Continue....");
Console.WriteLine("===========================================================");
Console.Read();
}
}
}
Maxscript and other finished work I've done can be found on my DeviantArt account