home *** CD-ROM | disk | FTP | other *** search
- #include "xentax.h"
- #include "stdres.h"
- #include "ps3_gundam_crossfire.h"
- #include "xb360_onechanbara2.h"
-
- INT_PTR CALLBACK RipperProc(HWND dialog, UINT message, WPARAM wparam, LPARAM lparam);
- bool is_face_flipped(const float* v1, const float* v2, const float* v3, const float* n1, const float* n2, const float* n3);
-
- bool Test(void)
- {
- ifstream ifile("anna1u.chr", ios::binary);
- if(!ifile) return false;
-
- ifile.seekg(0x14);
- uint32 vbuffer_offset = LE_read_uint32(ifile);
- uint32 ibuffer_offset = LE_read_uint32(ifile);
- uint32 tbuffer_offset = LE_read_uint32(ifile);
-
- // calculate vertex buffer properties
- uint32 vbuffer_size = ibuffer_offset - vbuffer_offset;
- uint32 vertices = vbuffer_size/32;
- cout << "size of vertex buffer in bytes = " << vbuffer_size << endl;
- cout << "number of vertices = " << vertices << endl;
- cout << endl;
-
- // calculate index buffer properties
- uint32 ibuffer_size = tbuffer_offset - ibuffer_offset;
- uint32 indices = ibuffer_size/2;
- cout << "size of index buffer in bytes = " << ibuffer_size << endl;
- cout << "number of indices = " << indices << endl;
- cout << endl;
-
- // read number of textures
- ifile.seekg(0x2C);
- uint32 n_textures = LE_read_uint32(ifile);
- cout << "number of textures = " << n_textures << endl;
-
- // surface data
- deque<size_t> stripsizes;
- deque<size_t> stripimage;
- deque<bool> stripeffect;
-
- // read surfaces
- uint32 curr_surface = 0;
- ifile.seekg(0x40);
- for(;;)
- {
- uint32 temp1 = LE_read_uint32(ifile);
- if(temp1 == 0)
- {
- uint32 h01 = temp1;
- uint32 h02 = LE_read_uint32(ifile);
- uint32 h03 = LE_read_uint16(ifile);
- uint32 h04 = LE_read_uint16(ifile);
- cout << "h01 = " << h01 << endl;
- cout << "h02 = " << h02 << endl;
- cout << "h03 = " << h03 << endl;
- cout << "h04 = " << h04 << endl;
-
- // read a bunch of half-floats
- LE_read_float16(ifile);
- LE_read_float16(ifile);
- LE_read_float16(ifile);
- LE_read_float16(ifile);
- LE_read_float16(ifile);
- LE_read_float16(ifile);
- LE_read_float16(ifile);
- LE_read_float16(ifile);
- }
- else if(temp1 == 1)
- {
- cout << "surface " << curr_surface++ << endl;
- uint32 param01 = LE_read_uint32(ifile);
- uint32 param02 = LE_read_uint32(ifile);
- uint16 param03 = LE_read_uint16(ifile); // usually 68
- uint16 param04 = LE_read_uint16(ifile);
- uint32 param05 = LE_read_uint32(ifile);
- uint32 param06 = LE_read_uint32(ifile);
- uint32 param07 = LE_read_uint32(ifile);
- uint32 param08 = LE_read_uint32(ifile);
- uint32 param09 = LE_read_uint32(ifile);
- uint32 param10 = LE_read_uint32(ifile);
- uint32 param11 = LE_read_uint32(ifile); // texture
- uint32 param12 = LE_read_uint32(ifile);
- uint32 param13 = LE_read_uint32(ifile);
- uint32 param14 = LE_read_uint32(ifile); // number of indices to use
- stripeffect.push_back((param05 == 3));
- stripimage.push_back(param11);
- stripsizes.push_back(param14);
-
- cout << param01 << endl;
- cout << param02 << endl;
- cout << param03 << endl; // usually 68
- cout << param04 << endl;
- cout << param05 << endl;
- cout << param06 << endl;
- cout << param07 << endl;
- cout << param08 << endl;
- cout << param09 << endl;
- cout << param10 << endl;
- cout << param11 << endl;
- cout << param12 << endl;
- cout << param13 << endl;
- cout << param14 << endl;
- cout << endl;
- }
- else if(temp1 == 2)
- {
- cout << "surface " << curr_surface++ << endl;
- uint32 param01 = LE_read_uint32(ifile); // texture
- uint32 param02 = LE_read_uint32(ifile);
- uint32 param03 = LE_read_uint32(ifile);
- uint32 param04 = LE_read_uint32(ifile);
- stripeffect.push_back(false);
- stripimage.push_back(param01);
- stripsizes.push_back(param04);
-
- cout << param01 << endl;
- cout << param02 << endl;
- cout << param03 << endl; // usually 68
- cout << param04 << endl;
- cout << endl;
- }
- else if(temp1 == 0xFFFFFFFF)
- {
- // marks last surface?
- }
- else
- break;
- }
-
- // create OBJ file
- ofstream ofile("output.obj");
- ofile << "o output.obj" << endl;
- ofile << "mtllib " << "output" << ".mtl" << endl;
-
- // move file pointer to vertex buffer
- ifile.seekg(vbuffer_offset);
-
- // create vertex buffer
- VERTEX_BUFFER vbuffer;
- vbuffer.flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_UV;
- vbuffer.elem = vertices;
- vbuffer.data.reset(new VERTEX[vbuffer.elem]);
-
- // read vertex data
- for(uint32 i = 0; i < vertices; i++)
- {
- // read vertex data
- VERTEX v;
- v.vx = LE_read_float16(ifile);
- v.vy = LE_read_float16(ifile);
- v.vz = LE_read_float16(ifile);
- LE_read_float16(ifile);
- v.nx = LE_read_float16(ifile);
- v.ny = LE_read_float16(ifile);
- v.nz = LE_read_float16(ifile);
- LE_read_float16(ifile);
- v.tu = LE_read_float16(ifile);
- v.tv = 1.0f - LE_read_float16(ifile);
- LE_read_float16(ifile);
- LE_read_float16(ifile);
- LE_read_float16(ifile);
- LE_read_float16(ifile);
- LE_read_float16(ifile);
- LE_read_float16(ifile);
-
- // save vertex data
- vbuffer.data[i] = v;
-
- // save vertex data
- ofile << "v " << v.vx << " " << v.vy << " " << v.vz << endl;
- ofile << "vn " << v.nx << " " << v.ny << " " << v.nz << endl;
- ofile << "vt " << v.tu << " " << v.tv << endl;
- }
-
- // move to index data
- ifile.seekg(ibuffer_offset);
-
- // read index data
- boost::shared_array<uint16> ibuffer(new uint16[indices]);
- LE_read_array(ifile, ibuffer.get(), indices);
-
- //
- uint32 sum = 0;
- for(size_t i = 0; i < stripsizes.size(); i++) sum += stripsizes[i];
- cout << "sum = " << sum << endl;
- cout << "indices = " << indices << endl;
- uint32 leftover = indices - sum;
- cout << "leftover = " << leftover << endl;
- cout << endl;
-
- // process surfaces
- uint32 offset = 0;
- for(size_t i = 0; i < stripsizes.size(); i++)
- {
- uint32 indices = stripsizes[i];
- cout << "surface indices = " << indices << endl;
-
- if(!stripeffect[i]) // TEST
- {
-
- // save group
- ofile << "g " << "surface_" << setfill('0') << setw(3) << i << endl;
- ofile << "usemtl " << "surface_" << setfill('0') << setw(3) << i << endl;
-
- // save first triangle
- uint32 a = ibuffer[offset + 0] + 1;
- uint32 b = ibuffer[offset + 1] + 1;
- uint32 c = ibuffer[offset + 2] + 1;
-
- float v1[3] = { vbuffer.data[a - 1].vx, vbuffer.data[a - 1].vy, vbuffer.data[a - 1].vz };
- float v2[3] = { vbuffer.data[b - 1].vx, vbuffer.data[b - 1].vy, vbuffer.data[b - 1].vz };
- float v3[3] = { vbuffer.data[c - 1].vx, vbuffer.data[c - 1].vy, vbuffer.data[c - 1].vz };
- float n1[3] = { vbuffer.data[a - 1].nx, vbuffer.data[a - 1].ny, vbuffer.data[a - 1].nz };
- float n2[3] = { vbuffer.data[b - 1].nx, vbuffer.data[b - 1].ny, vbuffer.data[b - 1].nz };
- float n3[3] = { vbuffer.data[c - 1].nx, vbuffer.data[c - 1].ny, vbuffer.data[c - 1].nz };
-
- if(is_face_flipped(v1, v2, v3, n1, n2, n3)) {
- ofile << "f " << a << "/" << a << "/" << a << " " <<
- c << "/" << c << "/" << c << " " <<
- b << "/" << b << "/" << b << endl;
- }
- else {
- ofile << "f " << a << "/" << a << "/" << a << " " <<
- b << "/" << b << "/" << b << " " <<
- c << "/" << c << "/" << c << endl;
- }
-
- // save other triangles
- for(size_t j = 3; j < stripsizes[i]; j++)
- {
- a = b;
- b = c;
- c = ibuffer[offset + j] + 1;
-
- // skip degenerate triangles
- if(a == b || a == c || b == c)
- continue;
-
- if(j % 2)
- {
- float v1[3] = { vbuffer.data[a - 1].vx, vbuffer.data[a - 1].vy, vbuffer.data[a - 1].vz };
- float v2[3] = { vbuffer.data[c - 1].vx, vbuffer.data[c - 1].vy, vbuffer.data[c - 1].vz };
- float v3[3] = { vbuffer.data[b - 1].vx, vbuffer.data[b - 1].vy, vbuffer.data[b - 1].vz };
- float n1[3] = { vbuffer.data[a - 1].nx, vbuffer.data[a - 1].ny, vbuffer.data[a - 1].nz };
- float n2[3] = { vbuffer.data[c - 1].nx, vbuffer.data[c - 1].ny, vbuffer.data[c - 1].nz };
- float n3[3] = { vbuffer.data[b - 1].nx, vbuffer.data[b - 1].ny, vbuffer.data[b - 1].nz };
-
- if(is_face_flipped(v1, v2, v3, n1, n2, n3)) {
- ofile << "f " << a << "/" << a << "/" << a << " " <<
- b << "/" << b << "/" << b << " " <<
- c << "/" << c << "/" << c << endl;
- }
- else {
- ofile << "f " << a << "/" << a << "/" << a << " " <<
- c << "/" << c << "/" << c << " " <<
- b << "/" << b << "/" << b << endl;
- }
- }
- else
- {
- float v1[3] = { vbuffer.data[a - 1].vx, vbuffer.data[a - 1].vy, vbuffer.data[a - 1].vz };
- float v2[3] = { vbuffer.data[b - 1].vx, vbuffer.data[b - 1].vy, vbuffer.data[b - 1].vz };
- float v3[3] = { vbuffer.data[c - 1].vx, vbuffer.data[c - 1].vy, vbuffer.data[c - 1].vz };
- float n1[3] = { vbuffer.data[a - 1].nx, vbuffer.data[a - 1].ny, vbuffer.data[a - 1].nz };
- float n2[3] = { vbuffer.data[b - 1].nx, vbuffer.data[b - 1].ny, vbuffer.data[b - 1].nz };
- float n3[3] = { vbuffer.data[c - 1].nx, vbuffer.data[c - 1].ny, vbuffer.data[c - 1].nz };
-
- if(is_face_flipped(v1, v2, v3, n1, n2, n3)) {
- ofile << "f " << a << "/" << a << "/" << a << " " <<
- c << "/" << c << "/" << c << " " <<
- b << "/" << b << "/" << b << endl;
- }
- else {
- ofile << "f " << a << "/" << a << "/" << a << " " <<
- b << "/" << b << "/" << b << " " <<
- c << "/" << c << "/" << c << endl;
- }
- }
- }
-
- } // TEST
-
- // move offset
- offset += stripsizes[i];
- }
-
- // save materials
- ofstream mtlfile("output.mtl");
- if(!mtlfile) return error("OBJ EXPORT: Error creating material file.");
- for(size_t i = 0; i < stripsizes.size(); i++) {
- mtlfile << "newmtl " << "surface_" << setfill('0') << setw(3) << i << endl;
- mtlfile << "Ka 0 0 0" << endl;
- mtlfile << "Kd 0.784314 0.784314 0.784314" << endl;
- mtlfile << "Ks 0 0 0" << endl;
- mtlfile << "Ni 1" << endl;
- mtlfile << "Ns 400" << endl;
- mtlfile << "Tf 1 1 1" << endl;
- mtlfile << "d 1" << endl;
- mtlfile << "map_Kd texture_" << setfill('0') << setw(3) << stripimage[i] << ".png" << endl;
- mtlfile << endl;
- }
-
- // move to texture data
- ifile.seekg(tbuffer_offset);
-
- struct TEXTUREINFO { uint32 p1, p2, p3, p4; };
- deque<TEXTUREINFO> tinfo;
-
- // read texture info
- for(size_t i = 0; i < n_textures; i++)
- {
- TEXTUREINFO item;
- item.p1 = LE_read_uint32(ifile);
- item.p2 = LE_read_uint32(ifile);
- item.p3 = LE_read_uint32(ifile);
- item.p4 = LE_read_uint32(ifile);
- tinfo.push_back(item);
- }
-
- // read texture data
- for(size_t i = 0; i < n_textures; i++)
- {
- TEXTUREINFO item = tinfo[i];
-
- //
- stringstream ss;
- ss << "texture_" << setfill('0') << setw(3) << i << ".dds";
- ofstream ddsfile(ss.str().c_str(), ios::binary);
- ddsfile.write("DDS ", 4);
-
- // save DDS header
- DDS_HEADER header;
- CreateUncompressedDDSHeader(item.p1, item.p2, 0, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000, FALSE, &header);
- ddsfile.write((char*)&header, sizeof(header));
-
- // save DDS data
- boost::shared_array<char> data(new char[item.p3]);
- ifile.read(data.get(), item.p3);
- ddsfile.write(data.get(), item.p3);
- }
-
- return true;
- }
-
- void Test2(void)
- {
- // negate z to convert to right-hand space
- double points[7][3] = {
- { -3.38441, 147.212, 2.82783 }, // 0
- { -4.17231, 147.948, 2.17650 }, // 1
- { -3.65146, 147.122, 2.01224 }, // 2
- { -3.98159, 147.350, 1.01742 }, // 50
- { -4.53017, 148.112, 1.25919 }, // 62
- { -3.84511, 148.011, 2.93451 }, // 63
- { -4.57004, 148.829, 2.43792 }, // 64
- };
-
- // triangle
- double v1[3] = { 26.3867, 136.591, -1.16695 };
- double v2[3] = { 26.304, 138.489, -1.08023 };
- double v3[3] = { 23.769, 136.48, -1.12714 };
-
- // compute a
- double a[3] = {
- v2[0] - v1[0],
- v2[1] - v1[1],
- v2[2] - v1[2],
- };
- double da = std::sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
- a[0] /= da;
- a[1] /= da;
- a[2] /= da;
-
- // compute b
- double b[3] = {
- v3[0] - v1[0],
- v3[1] - v1[1],
- v3[2] - v1[2],
- };
- double db = std::sqrt(b[0]*b[0] + b[1]*b[1] + b[2]*b[2]);
- b[0] /= db;
- b[1] /= db;
- b[2] /= db;
-
- // compute c
- double c[3] = {
- a[1]*b[2] - a[2]*b[1],
- a[2]*b[0] - a[0]*b[2],
- a[0]*b[1] - a[1]*b[0],
- };
- double dc = std::sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2]);
- c[0] /= dc;
- c[1] /= dc;
- c[2] /= dc;
-
- cout << "normal = " << c[0] << "," << c[1] << "," << c[2] << endl;
-
- // compute d
- double d[3] = {
- -6,
- 94,
- -123,
- };
- double dd = std::sqrt(d[0]*d[0] + d[1]*d[1] + d[2]*d[2]);
- d[0] /= dd;
- d[1] /= dd;
- d[2] /= dd;
- cout << "normal = " << d[0] << "," << d[1] << "," << d[2] << endl;
- }
-
- int main()
- {
- //PS3::GundamCrossfire::extract();
- XB360::Onechanbara2::extract();
-
- /*
- ifstream ifile("nina1u.kmd", ios::binary);
-
- LE_read_uint32(ifile);
- LE_read_uint32(ifile);
- LE_read_uint32(ifile); // 98
- LE_read_uint32(ifile); // ??
- LE_read_uint32(ifile); // 8
- LE_read_uint32(ifile); // 0xDC0 + 0x10 = offset to data
- LE_read_uint32(ifile); // 0xC9F
- LE_read_uint32(ifile); // 0x1FBC
- LE_read_uint32(ifile); // 0x5F34
- LE_read_uint32(ifile); // 0x581
- LE_read_uint32(ifile); // 0x2ABE
- LE_read_uint32(ifile); // 0
- LE_read_uint32(ifile); // 0
- LE_read_uint32(ifile); // 0xD0D
- LE_read_uint32(ifile); // 0
- LE_read_uint32(ifile); // 0
- LE_read_uint32(ifile); // 0
- LE_read_uint32(ifile); // 0
- LE_read_uint32(ifile); // 0xB9D60 = offset
- LE_read_uint32(ifile); // 0
- LE_read_uint32(ifile); // 0
- LE_read_uint32(ifile); // 0
- LE_read_uint32(ifile); // 0
- LE_read_uint32(ifile); // 0xFC160
- LE_read_uint32(ifile); // 0x1070A0
- LE_read_uint32(ifile); // 0x1077A0
- LE_read_uint32(ifile); // 0
- LE_read_uint32(ifile); // 0
- LE_read_uint32(ifile); // 0
- LE_read_uint32(ifile); // 0
- LE_read_uint32(ifile); // 0
- LE_read_uint32(ifile); // 0xFFFFFFFF
-
- ofstream ofile("test.obj");
- ofile << "o test.obj" << endl;
-
- struct bone {
- uint32 parent;
- float x;
- float y;
- float z;
- float x_abs;
- float y_abs;
- float z_abs;
- };
- map<uint32, bone> bonemap;
- typedef map<uint32, bone>::value_type boneitem;
- typedef map<uint32, bone>::iterator bone_iterator;
-
- ifile.seekg(0x7C);
- size_t max_parent = 0;
- for(size_t i = 0; i < 98; i++)
- {
- uint32 parent = LE_read_uint32(ifile);
- float x = LE_read_float32(ifile);
- float y = LE_read_float32(ifile);
- float z = LE_read_float32(ifile);
- float sx = LE_read_float32(ifile);
- float sy = LE_read_float32(ifile);
- float sz = LE_read_float32(ifile);
- LE_read_uint32(ifile);
- cout << endl;
-
- bone b;
- b.parent = parent;
- b.x = x*sx;
- b.y = y*sy;
- b.z = z*sz;
- b.x_abs = b.x;
- b.y_abs = b.y;
- b.z_abs = b.z;
-
- // add bone
- bonemap.insert(boneitem(i, b));
- }
-
- for(bone_iterator i = bonemap.begin(); i != bonemap.end(); i++)
- {
- bone_iterator iter = bonemap.find(i->second.parent);
- if(iter != bonemap.end()) {
- i->second.x_abs += iter->second.x_abs;
- i->second.y_abs += iter->second.y_abs;
- i->second.z_abs += iter->second.z_abs;
- }
- ofile << "v " << i->second.x_abs << " " << i->second.y_abs << " " << i->second.z_abs << endl;
- }
-
- ifstream chrfile("nina1u.chr", ios::binary);
- chrfile.seekg(0x14BC);
- size_t n_bones = 106;
- float x = 0;
- float y = 0;
- float z = 0;
- for(size_t i = 0; i < n_bones; i++) {
- float m[16];
- m[ 0] = LE_read_float32(chrfile);
- m[ 1] = LE_read_float32(chrfile);
- m[ 2] = LE_read_float32(chrfile);
- m[ 3] = LE_read_float32(chrfile);
- m[ 4] = LE_read_float32(chrfile);
- m[ 5] = LE_read_float32(chrfile);
- m[ 6] = LE_read_float32(chrfile);
- m[ 7] = LE_read_float32(chrfile);
- m[ 8] = LE_read_float32(chrfile);
- m[ 9] = LE_read_float32(chrfile);
- m[10] = LE_read_float32(chrfile);
- m[11] = LE_read_float32(chrfile);
- m[12] = LE_read_float32(chrfile);
- m[13] = LE_read_float32(chrfile);
- m[14] = LE_read_float32(chrfile);
- m[15] = LE_read_float32(chrfile);
- x = m[12];
- y = m[13];
- z = m[14];
-
- // cout << m[ 0] << " " << m[ 1] << " " << m[ 2] << " " << m[ 3] << endl;
- // cout << m[ 4] << " " << m[ 5] << " " << m[ 6] << " " << m[ 7] << endl;
- // cout << m[ 8] << " " << m[ 9] << " " << m[10] << " " << m[11] << endl;
- // cout << m[12] << " " << m[13] << " " << m[14] << " " << m[15] << endl;
- // cout << endl;
-
- //ofile << "v " << x << " " << y << " " << z << endl;
- }
- */
-
- return 0;
- }
-
- INT_PTR CALLBACK RipperProc(HWND dialog, UINT message, WPARAM wparam, LPARAM lparam)
- {
- switch(message) {
- case(WM_INITDIALOG) :
- {
- HWND system = GetDlgItem(dialog, IDC_SYSTEM);
- if(!system) {
- MessageBox(dialog, TEXT("Dialog control missing."), TEXT("Error"), MB_ICONSTOP);
- EndDialog(dialog, IDCANCEL);
- }
- SendMessage(system, CB_ADDSTRING, 0, (LPARAM)TEXT("Playstation 3"));
- SendMessage(system, CB_ADDSTRING, 0, (LPARAM)TEXT("PC"));
- SendMessage(system, CB_ADDSTRING, 0, (LPARAM)TEXT("XBox 360"));
- SendMessage(system, CB_SETCURSEL, (WPARAM)0, (LPARAM)0);
- return TRUE;
- }
- case(WM_COMMAND) : {
- int cmd = LOWORD(wparam);
- if(cmd == IDOK) {
- EndDialog(dialog, IDOK);
- return TRUE;
- }
- if(cmd == IDCANCEL) {
- EndDialog(dialog, IDCANCEL);
- return TRUE;
- }
- return FALSE;
- }
- }
- return FALSE;
- }
-
- bool is_face_flipped(const float* v1, const float* v2, const float* v3, const float* n1, const float* n2, const float* n3)
- {
- // compute a
- float a[3] = {
- v2[0] - v1[0],
- v2[1] - v1[1],
- v2[2] - v1[2],
- };
- float da = std::sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
- a[0] /= da;
- a[1] /= da;
- a[2] /= da;
-
- // compute b
- float b[3] = {
- v3[0] - v1[0],
- v3[1] - v1[1],
- v3[2] - v1[2],
- };
- float db = std::sqrt(b[0]*b[0] + b[1]*b[1] + b[2]*b[2]);
- b[0] /= db;
- b[1] /= db;
- b[2] /= db;
-
- // compute c
- float c[3] = {
- a[1]*b[2] - a[2]*b[1],
- a[2]*b[0] - a[0]*b[2],
- a[0]*b[1] - a[1]*b[0],
- };
- float dc = std::sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2]);
- c[0] /= dc;
- c[1] /= dc;
- c[2] /= dc;
-
- // compute average of vertex normals
- float q[3] = {
- (n1[0] + n2[0] + n3[0])/3.0f,
- (n1[1] + n2[1] + n3[1])/3.0f,
- (n1[2] + n2[2] + n3[2])/3.0f,
- };
- float dq = std::sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2]);
- q[0] /= dq;
- q[1] /= dq;
- q[2] /= dq;
-
- // now compute angle between two normals
- float angle = std::acos((c[0]*q[0] + c[1]*q[1] + c[2]*q[2]));
- angle = angle*(180.0f/3.1415f);
- return (angle > 90.0f);
- }