Model importer for Kingdom Hearts II
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

818 lines
29 KiB

  1. #include <assimp/Exporter.hpp>
  2. #include <assimp/Importer.hpp>
  3. #include <assimp/postprocess.h>
  4. #include <assimp/scene.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. /*
  8. * Here is an high-level overview of the MDLX file format
  9. *
  10. * BAR
  11. * |-------------------|
  12. * | 0x04 |
  13. * | |---------------| |
  14. * | | | |
  15. * | | MDL_H | |
  16. * | | |-------| | |
  17. * | | |MDL_P_H| | |
  18. * | | |MDL_P_H| | |
  19. * | | | ... | | |
  20. * | | |-------| | |
  21. * | | ????? | | <- unused in KH2, used in KH1
  22. * | | MDL_P | |
  23. * | | |-----------| | |
  24. * | | | BONES | | |
  25. * | | | |-------| | | |
  26. * | | | | BONE | | | |
  27. * | | | | BONE | | | |
  28. * | | | | ... | | | |
  29. * | | | |-------| | | |
  30. * | | | SUBP | | |
  31. * | | | |-------| | | |
  32. * | | | | VIFPKT| | | |
  33. * | | | | VIFPKT| | | |
  34. * | | | | ... | | | |
  35. * | | | |-------| | | |
  36. * | | | DMA | | |
  37. * | | | |-------| | | |
  38. * | | | |DMA_VIF| | | |
  39. * | | | | MAT_I | | | |
  40. * | | | | MAT_I | | | |
  41. * | | | | ... | | | |
  42. * | | | |DMA_VIF| | | |
  43. * | | | | ... | | | |
  44. * | | | --------- | | |
  45. * | | | MAT | | |
  46. * | | | |-------| | | |
  47. * | | | | MAT_I | | | |
  48. * | | | | MAT_I | | | |
  49. * | | | | ... | | | |
  50. * | | | |-------| | | |
  51. * | | |-----------| | |
  52. * | | MDL_P | |
  53. * | | |-----------| | |
  54. * | | | BONES | | |
  55. * | | | |-------| | | |
  56. * | | | | BONE | | | |
  57. * | | | | BONE | | | |
  58. * | | | | ... | | | |
  59. * | | | |-------| | | |
  60. * | | | SUBP | | |
  61. * | | | |-------| | | |
  62. * | | | | VIFPKT| | | |
  63. * | | | | VIFPKT| | | |
  64. * | | | | ... | | | |
  65. * | | | |-------| | | |
  66. * | | | DMA | | |
  67. * | | | |-------| | | |
  68. * | | | |DMA_VIF| | | |
  69. * | | | | MAT_I | | | |
  70. * | | | | MAT_I | | | |
  71. * | | | | ... | | | |
  72. * | | | |DMA_VIF| | | |
  73. * | | | | ... | | | |
  74. * | | | --------- | | |
  75. * | | | MAT | | |
  76. * | | | |-------| | | |
  77. * | | | | MAT_I | | | |
  78. * | | | | MAT_I | | | |
  79. * | | | | ... | | | |
  80. * | | | |-------| | | |
  81. * | | |-----------| | |
  82. | | ... | |
  83. * | |---------------| |
  84. * | |
  85. * |-------------------|
  86. * | 0x07 |
  87. * | |---------| |
  88. * | | TIM_0 | |
  89. * | | TIM_1 | |
  90. * | | ..... | |
  91. * | |---------| |
  92. * | |
  93. * |-------------------|
  94. * | 0x17 |
  95. * |-------------------|
  96. *
  97. *
  98. * 0x04 is the model. It contains a model header, followed by a model part per
  99. * texture, each including their list of bones, subpart to render by the VU1,
  100. * DMA tags to refer to the subparts and matrices. For more informations refer
  101. * to kh2vif.
  102. *
  103. * 0x07 is the texture container: it contains several textures under the TIM2
  104. * format. For more information refer to the tool building it.
  105. *
  106. * 0x17 is the object definition: contains collision, which bone lock-on target
  107. * is on, etc */
  108. struct mdl_header {
  109. unsigned int nmb;
  110. unsigned int res1;
  111. unsigned int res2;
  112. unsigned int next_mdl_header;
  113. unsigned short bone_cnt;
  114. unsigned short unk1;
  115. unsigned int bone_off;
  116. unsigned int unk_off;
  117. unsigned short mdl_subpart_cnt;
  118. unsigned short unk2;
  119. };
  120. struct mdl_subpart_header {
  121. unsigned int unk1;
  122. unsigned int texture_idx;
  123. unsigned int unk2;
  124. unsigned int unk3;
  125. unsigned int DMA_off;
  126. unsigned int mat_off;
  127. unsigned int DMA_size;
  128. unsigned int unk5;
  129. };
  130. struct bone_entry {
  131. unsigned short idx;
  132. unsigned short res1;
  133. int parent;
  134. unsigned int unk1;
  135. unsigned int unk2;
  136. float sca_x;
  137. float sca_y;
  138. float sca_z;
  139. float sca_w;
  140. float rot_x;
  141. float rot_y;
  142. float rot_z;
  143. float rot_w;
  144. float trans_x;
  145. float trans_y;
  146. float trans_z;
  147. float trans_w;
  148. };
  149. struct DMA {
  150. unsigned short vif_len;
  151. unsigned short res1;
  152. unsigned int vif_off;
  153. };
  154. void write_packet(int vert_count, int bone_count, int face_count,
  155. unsigned int bones_drawn[], int faces_drawn[],
  156. unsigned int vertices_drawn[], int mp, int vifpkt,
  157. const aiMesh &mesh, char *name, int last, int bones_prec[],
  158. int mat_entries[], int dma_entries[]) {
  159. // should be enough chars for a lifetime
  160. char *filename = (char *)malloc(PATH_MAX * sizeof(char));
  161. sprintf(filename, "%s_mp%d_pkt%d.obj", name, mp, vifpkt);
  162. FILE *pkt = fopen(filename, "w");
  163. /*
  164. printf("%d, %d, %d\n", bone_count, vert_count, face_count);
  165. for(int i=0; i<bone_count; i++){printf("%d, ", bones_drawn[i]);}
  166. printf("\n");
  167. for(int i=0; i<vert_count; i++){printf("%d, ", vertices_drawn[i]);}
  168. printf("\n");
  169. for(int i=0; i<face_count; i++){printf("%d, ", faces_drawn[i]);}
  170. printf("\n");*/
  171. // if we are over the maximum size allowed for a packet we
  172. // sort vertices per bones, rearrange the model to draw
  173. // to file
  174. // we do not sort bones as we sort vertices based on bone
  175. // order
  176. int bone_to_vertex[bone_count];
  177. for (int i = 0; i < bone_count; i++) {
  178. bone_to_vertex[i] = 0;
  179. }
  180. unsigned int vert_new_order[vert_count];
  181. for (int i = 0; i < vert_count; i++) {
  182. vert_new_order[i] = 0;
  183. }
  184. int new_order_count = 0;
  185. // we check the number of vertices assigned to each bone
  186. // in this packet, and reorganize them per bone
  187. for (int d = 0; d < bone_count; d++) {
  188. for (unsigned int e = 0; e < mesh.mBones[bones_drawn[d]]->mNumWeights;
  189. e++) {
  190. for (int f = 0; f < vert_count; f++) {
  191. if (mesh.mBones[bones_drawn[d]]->mWeights[e].mVertexId ==
  192. vertices_drawn[f]) {
  193. bone_to_vertex[d]++;
  194. }
  195. }
  196. }
  197. }
  198. // we now sort vertices per bone order
  199. for (int d = 0; d < bone_count; d++) {
  200. for (unsigned int e = 0; e < mesh.mBones[bones_drawn[d]]->mNumWeights;
  201. e++) {
  202. for (int f = 0; f < vert_count; f++) {
  203. int tmp_check = 0;
  204. if (mesh.mBones[bones_drawn[d]]->mWeights[e].mVertexId ==
  205. vertices_drawn[f]) {
  206. for (int g = 0; g < new_order_count; g++) {
  207. if (vert_new_order[g] == vertices_drawn[f]) {
  208. tmp_check = 1;
  209. }
  210. }
  211. if (tmp_check == 0) {
  212. vert_new_order[new_order_count] = vertices_drawn[f];
  213. new_order_count++;
  214. }
  215. }
  216. }
  217. }
  218. }
  219. /*
  220. printf("Sorted vertices: \n");
  221. for(int i=0; i<vert_count; i++){printf("%d, ", vert_new_order[i]);}
  222. printf("\n");*/
  223. // we write the sorted model packet
  224. for (int i = 0; i < vert_count; i++) {
  225. fprintf(pkt, "v %f %f %f\n", mesh.mVertices[vert_new_order[i]].x,
  226. mesh.mVertices[vert_new_order[i]].y,
  227. mesh.mVertices[vert_new_order[i]].z);
  228. // TODO: maybe check according to assimp doc min and
  229. // max values for UV? Should be between 0 and 1
  230. fprintf(pkt, "vt %f %f\n", mesh.mTextureCoords[0][vert_new_order[i]].x,
  231. mesh.mTextureCoords[0][vert_new_order[i]].y);
  232. }
  233. for (int i = 0; i < bone_count; i++) {
  234. fprintf(pkt, "vb %d\n", bone_to_vertex[i]);
  235. }
  236. for (int i = 0; i < face_count; i++) {
  237. int f1 = -1;
  238. int f2 = -1;
  239. int f3 = -1;
  240. int y = 0;
  241. while (f1 == -1) {
  242. if (mesh.mFaces[faces_drawn[i]].mIndices[0] == vert_new_order[y]) {
  243. f1 = y;
  244. }
  245. y++;
  246. }
  247. y = 0;
  248. while (f2 == -1) {
  249. if (mesh.mFaces[faces_drawn[i]].mIndices[1] == vert_new_order[y]) {
  250. f2 = y;
  251. }
  252. y++;
  253. }
  254. y = 0;
  255. while (f3 == -1) {
  256. if (mesh.mFaces[faces_drawn[i]].mIndices[2] == vert_new_order[y]) {
  257. f3 = y;
  258. }
  259. y++;
  260. }
  261. fprintf(pkt, "f %d %d %d\n", f1 + 1, f2 + 1, f3 + 1);
  262. }
  263. char *kh2vname = (char *)malloc(PATH_MAX * sizeof(char));
  264. char *dmaname = (char *)malloc(PATH_MAX * sizeof(char));
  265. char *matname = (char *)malloc(PATH_MAX * sizeof(char));
  266. char *makepkt = (char *)malloc((PATH_MAX + 10) * sizeof(char));
  267. sprintf(kh2vname, "%s_mp%d_pkt%d.kh2v", name, mp, vifpkt);
  268. sprintf(dmaname, "%s_mp%d_pkt%d.dma", name, mp, vifpkt);
  269. sprintf(matname, "%s_mp%d_pkt%d.mat", name, mp, vifpkt);
  270. fclose(pkt);
  271. sprintf(makepkt, "kh2vif \"%s\"", filename);
  272. system(makepkt);
  273. // scanf("%d\n");
  274. FILE *kh2v = fopen(kh2vname, "rb");
  275. fseek(kh2v, 0x24, SEEK_SET);
  276. char mat_vif_off;
  277. fread(&mat_vif_off, 4, 1, kh2v);
  278. fseek(kh2v, 0x44, SEEK_SET);
  279. int mat_cnt = 0;
  280. // fread(&mat_cnt, sizeof(int), 1, kh2v);
  281. remove(filename);
  282. FILE *dma_file = fopen(dmaname, "wb");
  283. struct DMA *dma_entry = (DMA *)malloc(sizeof(struct DMA));
  284. fseek(kh2v, 0x0, SEEK_END);
  285. dma_entry->vif_len = ftell(kh2v) / 16;
  286. dma_entry->res1 = 0x3000;
  287. fclose(kh2v);
  288. // TOFIX: we don't know yet where in the final file our packet will
  289. // end up so we blank it out for now.
  290. dma_entry->vif_off = 0;
  291. char vif_empty[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  292. fwrite(dma_entry, 1, sizeof(struct DMA), dma_file);
  293. fwrite(vif_empty, 1, sizeof(vif_empty), dma_file);
  294. dma_entries[mp - 1]++;
  295. for (int i = 0; i < bone_count; i++) {
  296. dma_entry->vif_len = 4;
  297. dma_entry->res1 = 0x3000;
  298. dma_entry->vif_off = bones_drawn[i] + bones_prec[mp - 1];
  299. unsigned char vif_inst[] = { 0x01, 0x01, 0x00, 0x01,
  300. 0x00, 0x80, 0x04, 0x6C };
  301. vif_inst[4] = mat_vif_off + (i * 4);
  302. fwrite(dma_entry, 1, sizeof(struct DMA), dma_file);
  303. fwrite(vif_inst, 1, sizeof(vif_inst), dma_file);
  304. dma_entries[mp - 1]++;
  305. }
  306. char end_dma[] = { 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
  307. 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00 };
  308. fwrite(end_dma, 1, sizeof(end_dma), dma_file);
  309. dma_entries[mp - 1]++;
  310. FILE *mat_file = fopen(matname, "wb");
  311. // the count of mat entries, we need to modify that!
  312. if (vifpkt == 1) {
  313. fwrite(&mat_cnt, 1, sizeof(mat_cnt), mat_file);
  314. }
  315. for (int i = 0; i < bone_count; i++) {
  316. int bones_new = bones_drawn[i] + bones_prec[mp - 1];
  317. printf("original bone: %d, new: %d\n", bones_drawn[i], bones_new);
  318. fwrite(&bones_new, 1, sizeof(bones_new), mat_file);
  319. printf("MP %d, incremeting number of mat entries\n", mp);
  320. mat_entries[mp - 1]++;
  321. }
  322. int end_mat = -1;
  323. if (last) {
  324. end_mat = 0;
  325. }
  326. fwrite(&end_mat, 1, sizeof(end_mat), mat_file);
  327. if (!last) {
  328. printf("MP %d, incremeting number of mat entries\n", mp);
  329. mat_entries[mp - 1]++;
  330. }
  331. fclose(dma_file);
  332. fclose(mat_file);
  333. // TODO: write Mati here
  334. // remove(kh2vname);
  335. }
  336. int main(int argc, char *argv[]) {
  337. printf("kh2mdlx\n--- Early rev, don't blame me if it eats your cat\n\n");
  338. if (argc < 2) {
  339. printf("usage: kh2mdlx model.dae\n");
  340. return -1;
  341. }
  342. FILE *mdl;
  343. char empty[] = { 0x00 };
  344. std::string kh2mname =
  345. std::string(argv[1]).substr(0, std::string(argv[1]).find_last_of('.')) +
  346. ".kh2m";
  347. mdl = fopen(kh2mname.c_str(), "wb");
  348. Assimp::Importer importer;
  349. importer.SetPropertyInteger(
  350. AI_CONFIG_PP_RVC_FLAGS,
  351. aiComponent_NORMALS | aiComponent_TANGENTS_AND_BITANGENTS |
  352. aiComponent_COLORS | aiComponent_LIGHTS | aiComponent_CAMERAS);
  353. const aiScene *scene = importer.ReadFile(
  354. argv[1], aiProcess_Triangulate | aiProcess_RemoveComponent |
  355. aiProcess_JoinIdenticalVertices | aiProcess_SortByPType);
  356. if (!scene) {
  357. printf("error loading model!: %s", importer.GetErrorString());
  358. return -1;
  359. }
  360. // we are listing node hierarchy per bone here, hoping i can get some sort
  361. // of parser in place
  362. for (unsigned int i = 0; i < scene->mNumMeshes; i++) {
  363. aiMesh *mesh = scene->mMeshes[i];
  364. const char *bone_hierarchy[mesh->mNumBones];
  365. int bone_parent[mesh->mNumBones];
  366. for (unsigned int z = 0; z < mesh->mNumBones; z++) {
  367. bone_hierarchy[z] = "";
  368. }
  369. for (unsigned int z = 0; z < mesh->mNumBones; z++) {
  370. bone_parent[z] = -1;
  371. }
  372. for (unsigned int j = 0; j < mesh->mNumBones; j++) {
  373. aiBone *bone = mesh->mBones[j];
  374. bone_hierarchy[j] = bone->mName.C_Str();
  375. }
  376. for (unsigned int j = 0; j < mesh->mNumBones; j++) {
  377. aiBone *bone = mesh->mBones[j];
  378. aiNode *currentNode = scene->mRootNode->FindNode(bone->mName);
  379. while (currentNode != scene->mRootNode) {
  380. for (unsigned int z = 0; z < mesh->mNumBones; z++) {
  381. if (z == j) {
  382. break;
  383. }
  384. if (strcmp(bone_hierarchy[z], currentNode->mName.C_Str()) ==
  385. 0) {
  386. printf("PARENT FOUND: %d\n", z);
  387. bone_parent[j] = z;
  388. z = mesh->mNumBones;
  389. break;
  390. }
  391. }
  392. currentNode = currentNode->mParent;
  393. }
  394. printf("Bone id: %d name: %s, parent: %d\n", j, bone_hierarchy[j],
  395. bone_parent[j]);
  396. }
  397. }
  398. /*Assimp::Exporter exporter;
  399. const aiExportFormatDesc *format = exporter.GetExportFormatDescription(0);
  400. exporter.Export(scene, "fbx", "test.fbx", scene->mFlags);*/
  401. unsigned int mesh_nmb = scene->mNumMeshes;
  402. int vifpkt[mesh_nmb];
  403. printf("Number of meshes: %d\n", mesh_nmb);
  404. int bones_prec[mesh_nmb];
  405. int mat_entries[mesh_nmb];
  406. int dma_entries[mesh_nmb];
  407. for (unsigned int z = 0; z < mesh_nmb; z++) {
  408. mat_entries[z] = 0;
  409. }
  410. for (unsigned int z = 0; z < mesh_nmb; z++) {
  411. dma_entries[z] = 0;
  412. }
  413. for (unsigned int z = 0; z < mesh_nmb; z++) {
  414. if (z == 0) {
  415. bones_prec[z] = 0;
  416. } else {
  417. const aiMesh &mesh = *scene->mMeshes[z - 1];
  418. bones_prec[z] = (mesh.mNumBones) + bones_prec[z - 1];
  419. }
  420. }
  421. for (unsigned int i = 0; i < mesh_nmb; i++) {
  422. vifpkt[i] = 1;
  423. int vert_count = 0;
  424. int face_count = 0;
  425. int bone_count = 0;
  426. const aiMesh &mesh = *scene->mMeshes[i];
  427. // for some reason those arrays aren't initialized as 0...?
  428. unsigned int vertices_drawn[mesh.mNumVertices];
  429. for (unsigned int z = 0; z < mesh.mNumVertices; z++) {
  430. vertices_drawn[z] = 0;
  431. }
  432. unsigned int bones_drawn[mesh.mNumBones];
  433. for (unsigned int z = 0; z < mesh.mNumBones; z++) {
  434. bones_drawn[z] = 0;
  435. }
  436. int faces_drawn[mesh.mNumFaces];
  437. for (unsigned int z = 0; z < mesh.mNumFaces; z++) {
  438. faces_drawn[z] = 0;
  439. }
  440. printf("Bone for MP %d : %d\n", i + 1, mesh.mNumBones);
  441. // we are writing a custom interlaced, bone-supporting obj here,
  442. // don't assume everything is following the obj standard!
  443. // printf("Generating Model Part %d, packet %d\n", i+1, vifpkt);
  444. for (unsigned int y = 0; y < mesh.mNumFaces; y++) {
  445. // we make the biggest vif packet, possible, for this, here
  446. // is the size that each type of entry takes:
  447. //
  448. // header - 4 qwc
  449. // bones - 1/4 of a qwc + 4 qwc(DMA tags)
  450. // vertices - 1 qwc
  451. // Face drawing - 3 qwc, UV and flags are bundled with it
  452. // we here take the worst case scenario to ensure the vif
  453. // packet < the maximum size
  454. if (((((ceil((bone_count + 3) / 4) + (4 * (bone_count + 3))) +
  455. (vert_count + 3) + ((face_count + 1) * 3)) +
  456. 4) < 100)) {
  457. // we update faces
  458. faces_drawn[face_count] = y;
  459. face_count++;
  460. // we update bones
  461. // printf("This face has the vertices %d %d
  462. // %d\n",mesh.mFaces[y].mIndices[0],mesh.mFaces[y].mIndices[1],
  463. // mesh.mFaces[y].mIndices[2]);
  464. int tmp_check = 0;
  465. for (unsigned int d = 0; d < mesh.mNumBones; d++) {
  466. for (unsigned int e = 0; e < mesh.mBones[d]->mNumWeights;
  467. e++) {
  468. tmp_check = 0;
  469. if (mesh.mBones[d]->mWeights[e].mVertexId ==
  470. mesh.mFaces[y].mIndices[0] ||
  471. mesh.mBones[d]->mWeights[e].mVertexId ==
  472. mesh.mFaces[y].mIndices[1] ||
  473. mesh.mBones[d]->mWeights[e].mVertexId ==
  474. mesh.mFaces[y].mIndices[2]) {
  475. for (int f = 0; f < bone_count; f++) {
  476. if (bones_drawn[f] == d) {
  477. tmp_check = 1;
  478. }
  479. }
  480. // if we find a vertex of this face
  481. // associated to any bone and it is not a
  482. // duplicate we add it
  483. if (tmp_check == 0) {
  484. bones_drawn[bone_count] = d;
  485. bone_count++;
  486. }
  487. }
  488. }
  489. }
  490. tmp_check = 0;
  491. // we update vertices
  492. for (int d = 0; d < vert_count; d++) {
  493. if (vertices_drawn[d] == mesh.mFaces[y].mIndices[0]) {
  494. tmp_check = 1;
  495. }
  496. }
  497. if (tmp_check == 0) {
  498. vertices_drawn[vert_count] = mesh.mFaces[y].mIndices[0];
  499. vert_count++;
  500. }
  501. tmp_check = 0;
  502. for (int d = 0; d < vert_count; d++) {
  503. if (vertices_drawn[d] == mesh.mFaces[y].mIndices[1]) {
  504. tmp_check = 1;
  505. }
  506. }
  507. if (tmp_check == 0) {
  508. vertices_drawn[vert_count] = mesh.mFaces[y].mIndices[1];
  509. vert_count++;
  510. }
  511. tmp_check = 0;
  512. for (int d = 0; d < vert_count; d++) {
  513. if (vertices_drawn[d] == mesh.mFaces[y].mIndices[2]) {
  514. tmp_check = 1;
  515. }
  516. }
  517. if (tmp_check == 0) {
  518. vertices_drawn[vert_count] = mesh.mFaces[y].mIndices[2];
  519. vert_count++;
  520. }
  521. if (y == mesh.mNumFaces - 1) {
  522. write_packet(vert_count, bone_count, face_count,
  523. bones_drawn, faces_drawn, vertices_drawn,
  524. i + 1, vifpkt[i], mesh, argv[1], 1, bones_prec,
  525. mat_entries, dma_entries);
  526. }
  527. } else {
  528. write_packet(vert_count, bone_count, face_count, bones_drawn,
  529. faces_drawn, vertices_drawn, i + 1, vifpkt[i],
  530. mesh, argv[1], 0, bones_prec, mat_entries,
  531. dma_entries);
  532. y--;
  533. vifpkt[i]++;
  534. face_count = 0;
  535. bone_count = 0;
  536. vert_count = 0;
  537. for (unsigned int z = 0; z < mesh.mNumVertices; z++) {
  538. vertices_drawn[z] = 0;
  539. }
  540. for (unsigned int z = 0; z < mesh.mNumBones; z++) {
  541. bones_drawn[z] = 0;
  542. }
  543. for (unsigned int z = 0; z < mesh.mNumFaces; z++) {
  544. faces_drawn[z] = 0;
  545. }
  546. // printf("Generating Model Part %d, packet %d\n", i+1, vifpkt);
  547. }
  548. // fclose(pkt);
  549. }
  550. printf("Generated Model Part %d, splitted in %d packets\n", i + 1,
  551. vifpkt[i]);
  552. }
  553. // now that we have all intermediate files we can finally begin creating
  554. // the actual model by assembling all of them together
  555. // write kh2 dma in-game header
  556. for (int i = 0; i < 0x90; i++) {
  557. fwrite(empty, 1, sizeof(empty), mdl);
  558. }
  559. int bones_nmb = 0;
  560. for (unsigned int i = 0; i < mesh_nmb; i++) {
  561. const aiMesh &mesh = *scene->mMeshes[i];
  562. bones_nmb += mesh.mNumBones;
  563. }
  564. unsigned int subp_off[mesh_nmb];
  565. unsigned int mph = ftell(mdl);
  566. struct mdl_header *head = (mdl_header *)malloc(sizeof(struct mdl_header));
  567. head->nmb = 3;
  568. head->res1 = 0;
  569. head->res2 = 0;
  570. // this is where the shadow model will get written
  571. head->next_mdl_header = 0;
  572. head->bone_cnt = bones_nmb;
  573. head->unk1 = 0;
  574. // we need to write this once we generated the bone tables
  575. head->bone_off = 0;
  576. // as this table is unused nobody cares and we blank it out, saves
  577. // space
  578. head->unk_off = 0;
  579. head->mdl_subpart_cnt = mesh_nmb;
  580. head->unk2 = 0;
  581. fwrite(head, 1, sizeof(struct mdl_header), mdl);
  582. for (unsigned int y = 0; y < mesh_nmb; y++) {
  583. // write subheader here!
  584. subp_off[y] = ftell(mdl);
  585. struct mdl_subpart_header *subhead =
  586. (mdl_subpart_header *)malloc(sizeof(struct mdl_subpart_header));
  587. // TODO: verify what those unknowns are!
  588. // we do not have any offset yet so we just blank out everything
  589. subhead->unk1 = 0;
  590. // subhead->texture_idx = y;
  591. subhead->texture_idx = 0;
  592. subhead->unk2 = 0;
  593. subhead->unk3 = 0;
  594. subhead->DMA_off = 0;
  595. subhead->mat_off = 0;
  596. subhead->DMA_size = 0;
  597. subhead->unk5 = 0;
  598. fwrite(subhead, 1, sizeof(struct mdl_subpart_header), mdl);
  599. }
  600. // we are writing the bone table offset in the model header
  601. unsigned int cur_pos = ftell(mdl);
  602. fseek(mdl, mph, SEEK_SET);
  603. head->unk_off = cur_pos - 0x90;
  604. fwrite(head, 1, sizeof(struct mdl_header), mdl);
  605. fseek(mdl, cur_pos, SEEK_SET);
  606. unsigned char stupid_table[] __attribute__((aligned(16))) = {
  607. 0x3c, 0xa6, 0x95, 0xc2, 0xdd, 0x6e, 0xcf, 0x42, 0xa7, 0x94, 0x6b, 0xc2,
  608. 0x00, 0x00, 0x80, 0x3f, 0x9a, 0x98, 0x32, 0xc2, 0x18, 0x90, 0xe0, 0x42,
  609. 0x68, 0xc1, 0x96, 0x42, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
  610. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  611. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  612. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  613. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  614. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  615. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  616. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  617. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  618. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  619. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  620. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  621. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  622. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  623. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  624. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  625. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  626. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  627. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  628. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  629. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa3, 0xec, 0x9b, 0x42,
  630. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  631. };
  632. fwrite(stupid_table, 1, sizeof(stupid_table), mdl);
  633. // we are writing the bone table offset in the model header
  634. cur_pos = ftell(mdl);
  635. fseek(mdl, mph, SEEK_SET);
  636. head->bone_off = cur_pos - 0x90;
  637. fwrite(head, 1, sizeof(struct mdl_header), mdl);
  638. fseek(mdl, cur_pos, SEEK_SET);
  639. for (unsigned int i = 0; i < mesh_nmb; i++) {
  640. const aiMesh &mesh = *scene->mMeshes[i];
  641. for (unsigned int y = 0; y < mesh.mNumBones; y++) {
  642. struct bone_entry *bone =
  643. (bone_entry *)malloc(sizeof(struct bone_entry));
  644. bone->idx = y + bones_prec[i];
  645. bone->res1 = 0;
  646. // FIXME: write correctly parent and coordinates absolutely!!!
  647. bone->parent = -1;
  648. bone->unk1 = 0;
  649. bone->unk2 = 0;
  650. bone->sca_x = 1;
  651. bone->sca_y = 1;
  652. bone->sca_z = 1;
  653. bone->sca_w = 0;
  654. bone->rot_x = 0;
  655. bone->rot_y = 0;
  656. bone->rot_z = 0;
  657. bone->rot_w = 0;
  658. bone->trans_x = 0;
  659. bone->trans_y = 0;
  660. bone->trans_z = 0;
  661. bone->trans_w = 0;
  662. fwrite(bone, 1, sizeof(struct bone_entry), mdl);
  663. }
  664. }
  665. for (unsigned int i = 0; i < mesh_nmb; i++) {
  666. unsigned int vifp_off[mesh_nmb * vifpkt[i]];
  667. int dma_check = 1;
  668. int mat_check = 1;
  669. for (int y = 0; y < vifpkt[i]; y++) {
  670. vifp_off[y] = ftell(mdl) - 0x90;
  671. char *kh2vname = (char *)malloc(PATH_MAX * sizeof(char));
  672. sprintf(kh2vname, "%s_mp%d_pkt%d.kh2v", argv[1], i + 1, y + 1);
  673. FILE *vif_final = fopen(kh2vname, "rb");
  674. size_t n, m;
  675. unsigned char buff[8192];
  676. do {
  677. n = fread(buff, 1, sizeof buff, vif_final);
  678. if (n)
  679. m = fwrite(buff, 1, n, mdl);
  680. else
  681. m = 0;
  682. } while ((n > 0) && (n == m));
  683. fclose(vif_final);
  684. remove(kh2vname);
  685. }
  686. for (int y = 0; y < vifpkt[i]; y++) {
  687. char *dmaname = (char *)malloc(PATH_MAX * sizeof(char));
  688. sprintf(dmaname, "%s_mp%d_pkt%d.dma", argv[1], i + 1, y + 1);
  689. FILE *dma_final;
  690. if (dma_check) {
  691. unsigned int cur_pos = ftell(mdl);
  692. fseek(mdl, subp_off[i] + 0x10, SEEK_SET);
  693. int dmahdr = cur_pos - 0x90;
  694. fwrite(&dmahdr, 1, sizeof(dmahdr), mdl);
  695. printf("Dma entries: %d\n", dma_entries[i]);
  696. fseek(mdl, subp_off[i] + 0x18, SEEK_SET);
  697. fwrite(&dma_entries[i], 1, sizeof(dma_entries[i]), mdl);
  698. fseek(mdl, cur_pos, SEEK_SET);
  699. dma_check = 0;
  700. }
  701. dma_final = fopen(dmaname, "rb+");
  702. fseek(dma_final, 0x4, SEEK_SET);
  703. fwrite(&vifp_off[y], 1, sizeof(vifp_off[y]), dma_final);
  704. fclose(dma_final);
  705. dma_final = fopen(dmaname, "rb");
  706. size_t n, m;
  707. unsigned char buff[8192];
  708. do {
  709. n = fread(buff, 1, sizeof buff, dma_final);
  710. if (n)
  711. m = fwrite(buff, 1, n, mdl);
  712. else
  713. m = 0;
  714. } while ((n > 0) && (n == m));
  715. fclose(dma_final);
  716. remove(dmaname);
  717. }
  718. for (int y = 0; y < vifpkt[i]; y++) {
  719. char *matname = (char *)malloc(PATH_MAX * sizeof(char));
  720. sprintf(matname, "%s_mp%d_pkt%d.mat", argv[1], i + 1, y + 1);
  721. FILE *mat_final;
  722. if (mat_check) {
  723. unsigned int cur_pos = ftell(mdl);
  724. fseek(mdl, subp_off[i] + 0x14, SEEK_SET);
  725. unsigned int mathdr = cur_pos - 0x90;
  726. fwrite(&mathdr, 1, sizeof(mathdr), mdl);
  727. fseek(mdl, cur_pos, SEEK_SET);
  728. printf("Mat entries: %d\n", mat_entries[i]);
  729. mat_final = fopen(matname, "rb+");
  730. fwrite(&mat_entries[i], 1, sizeof(mat_entries[i]), mat_final);
  731. fclose(mat_final);
  732. mat_check = 0;
  733. }
  734. mat_final = fopen(matname, "rb");
  735. size_t n, m;
  736. unsigned char buff[8192];
  737. do {
  738. n = fread(buff, 1, sizeof buff, mat_final);
  739. if (n)
  740. m = fwrite(buff, 1, n, mdl);
  741. else
  742. m = 0;
  743. } while ((n > 0) && (n == m));
  744. fclose(mat_final);
  745. remove(matname);
  746. }
  747. while (ftell(mdl) % 16 != 0) {
  748. fwrite(empty, 1, sizeof(empty), mdl);
  749. }
  750. }
  751. fclose(mdl);
  752. }