VIF packet creator for Kingdom Hearts II models
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.

kh2vif.cpp 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. #include <fstream>
  2. #include <iostream>
  3. #include <limits>
  4. #include <math.h>
  5. #include <sstream>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <string>
  9. #include <unistd.h>
  10. #include <vector>
  11. int max(int x, int y, int z) {
  12. int flagx = x;
  13. if (y > flagx) {
  14. flagx = y;
  15. }
  16. if (z > flagx) {
  17. flagx = z;
  18. }
  19. return flagx;
  20. }
  21. void help() { printf("Usage: kh2vif model.obj\n"); }
  22. int main(int argc, char *argv[]) {
  23. // max uv buffer, should be enough for an entire set of obj vertices
  24. int uvs[8192];
  25. int uv_count = 0;
  26. int vertex_count = 0;
  27. int face_count = 0;
  28. int vertices_arg = 0;
  29. int vertex_affiliation = 0;
  30. int junk = 0;
  31. int map = 0;
  32. char *objname = argv[1];
  33. printf("kh2vif\n-- If you don't know what a VIF packet be prepared to be "
  34. "driven to insanity\n\n");
  35. if (argc < 2) {
  36. help();
  37. return -1;
  38. }
  39. if ((strcmp(objname, "-m") == 0) || (strcmp(objname, "--map") == 0)) {
  40. printf("\nSwitching to map mode\n");
  41. map = 1;
  42. objname = argv[2];
  43. }
  44. if (access(objname, F_OK) == -1) {
  45. help();
  46. return -1;
  47. }
  48. std::ifstream input(objname, std::ios::in);
  49. std::string dsmname =
  50. std::string(objname).substr(0, std::string(objname).find_last_of('.')) +
  51. ".dsm";
  52. std::string kh2vname =
  53. std::string(objname).substr(0, std::string(objname).find_last_of('.')) +
  54. ".kh2v";
  55. std::ofstream dsm(dsmname);
  56. std::string line;
  57. std::vector<std::string> dsm_mem;
  58. std::vector<int> bones;
  59. dsm_mem.push_back(".align 0");
  60. line = ";";
  61. line += objname;
  62. dsm_mem.push_back(line);
  63. dsm_mem.push_back(";Automatically generated by kh2vif");
  64. dsm_mem.push_back(";DO NOT EDIT IF YOU DON'T KNOW WHAT YOU ARE DOING");
  65. dsm_mem.push_back("");
  66. dsm_mem.push_back(
  67. "stcycl 01, 01; We write code to memory without skips/overwrite");
  68. dsm_mem.push_back("");
  69. dsm_mem.push_back("unpack[r] V4_32, 0, * ;Model Part Header");
  70. if (map) {
  71. dsm_mem.push_back(".int 0, 0, 0, 0 ;type 0 Model");
  72. } else {
  73. dsm_mem.push_back(".int 1, 0, 0, 0 ;type 1 Model");
  74. }
  75. // 3 MPHeader lines we will fix at the end, Vector is 11 here
  76. int tmpheader = dsm_mem.size();
  77. dsm_mem.push_back("");
  78. dsm_mem.push_back("");
  79. dsm_mem.push_back("");
  80. dsm_mem.push_back(".EndUnpack");
  81. dsm_mem.push_back("");
  82. dsm_mem.push_back(
  83. "stcycl 01, 01; We write code to memory without skips/overwrite");
  84. dsm_mem.push_back("");
  85. dsm_mem.push_back("unpack[r] V2_16, 4, *; UV definition");
  86. if (dsm.is_open()) {
  87. while (getline(input, line)) {
  88. if (line.substr(0, 2) == "v ") {
  89. vertex_count++;
  90. }
  91. }
  92. input.clear();
  93. input.seekg(0, std::ios::beg);
  94. while (getline(input, line)) {
  95. if (line.substr(0, 2) == "f ") {
  96. face_count++;
  97. }
  98. }
  99. input.clear();
  100. input.seekg(0, std::ios::beg);
  101. while (getline(input, line)) {
  102. if (line.substr(0, 3) == "vt ") {
  103. std::istringstream s(line.substr(3));
  104. float u, v;
  105. s >> u;
  106. s >> v;
  107. printf("tx= %f, ty= %f, txr= %d, tyr=%d\n", u, v,
  108. int(round(u * 4095)), int(round(v * 4095)));
  109. uvs[uv_count] = int(round(u * 4095));
  110. uvs[uv_count + 1] = int(round(v * 4095));
  111. uv_count += 2;
  112. }
  113. }
  114. input.clear();
  115. input.seekg(0, std::ios::beg);
  116. while (getline(input, line)) {
  117. if (line.substr(0, 3) == "vb ") {
  118. std::istringstream s(line.substr(2));
  119. int v;
  120. s >> v;
  121. bones.push_back(v);
  122. printf("bone= %d\n", v);
  123. }
  124. }
  125. if (bones.size() == 0) {
  126. bones.push_back(vertex_count);
  127. }
  128. input.clear();
  129. input.seekg(0, std::ios::beg);
  130. // making temporary entries for uvs to insert later on
  131. int uv_pos = dsm_mem.size();
  132. for (int i = 0; i < face_count; i++) {
  133. dsm_mem.push_back("");
  134. dsm_mem.push_back("");
  135. dsm_mem.push_back("");
  136. }
  137. dsm_mem.push_back(".EndUnpack");
  138. dsm_mem.push_back("");
  139. dsm_mem.push_back(
  140. "stmask 0xcfcfcfcf; Sets mask register(3303, check EEUSER_E)");
  141. dsm_mem.push_back(
  142. "stcycl 01, 01; We write code to memory without skips/overwrite");
  143. dsm_mem.push_back("");
  144. dsm_mem.push_back("unpack[mru] S_8, 4, *; Vertex indices");
  145. while (getline(input, line)) {
  146. if (line.substr(0, 2) == "f ") {
  147. std::istringstream s(line.substr(2));
  148. std::string i, n, u;
  149. int ii, inn, iu;
  150. s >> i;
  151. s >> n;
  152. s >> u;
  153. ii = std::stoi(i.substr(0, i.find("/")));
  154. inn = std::stoi(n.substr(0, n.find("/")));
  155. iu = std::stoi(u.substr(0, u.find("/")));
  156. // printf("i1: %d i2: %d i3: %d\n", ii, inn, iu);
  157. line = ".byte " + std::to_string(ii - 1);
  158. dsm_mem.push_back(line);
  159. line = ".short " + std::to_string(uvs[(ii - 1) * 2]) + ", " +
  160. std::to_string(uvs[((ii - 1) * 2) + 1]);
  161. dsm_mem[uv_pos] = line;
  162. uv_pos++;
  163. line = ".byte " + std::to_string(inn - 1);
  164. dsm_mem.push_back(line);
  165. line = ".short " + std::to_string(uvs[(inn - 1) * 2]) + ", " +
  166. std::to_string(uvs[((inn - 1) * 2) + 1]);
  167. dsm_mem[uv_pos] = line;
  168. uv_pos++;
  169. line = ".byte " + std::to_string(iu - 1);
  170. dsm_mem.push_back(line);
  171. line = ".short " + std::to_string(uvs[(iu - 1) * 2]) + ", " +
  172. std::to_string(uvs[((iu - 1) * 2) + 1]);
  173. dsm_mem[uv_pos] = line;
  174. uv_pos++;
  175. // printf("bis i1: %d i2: %d i3: %d\n", (ii-1)*2, (inn-1)*2,
  176. // (iu-1)*2);
  177. }
  178. }
  179. input.clear();
  180. input.seekg(0, std::ios::beg);
  181. dsm_mem.push_back(".EndUnpack");
  182. dsm_mem.push_back("");
  183. dsm_mem.push_back(
  184. "stmask 0x3f3f3f3f; Sets mask register(3330, check EEUSER_E)");
  185. dsm_mem.push_back(
  186. "stcycl 01, 01; We write code to memory without skips/overwrite");
  187. dsm_mem.push_back("");
  188. dsm_mem.push_back("unpack[mru] S_8, 4, *; Flags");
  189. for (int i = 0; i < face_count; i++) {
  190. dsm_mem.push_back(".byte 0x10; stock");
  191. dsm_mem.push_back(".byte 0x10; stock");
  192. dsm_mem.push_back(".byte 0x20; draw triangle");
  193. }
  194. dsm_mem.push_back(".EndUnpack");
  195. dsm_mem.push_back("");
  196. dsm_mem.push_back("stcol 0x3f800000, 0x3f800000, 0x3f800000, "
  197. "0x3f800000; We set garbage data to 1(float) so even "
  198. "if nothing is referenced game doesn't go crazy");
  199. dsm_mem.push_back(
  200. "stmask 0x80808080; Sets mask register(0002, check EEUSER_E)");
  201. dsm_mem.push_back(
  202. "stcycl 01, 01; We write code to memory without skips/overwrite");
  203. dsm_mem.push_back("");
  204. dsm_mem.push_back("unpack[mr] V3_32, , *; Vertex definition");
  205. vertices_arg = dsm_mem.size() - 1;
  206. while (getline(input, line)) {
  207. if (line.substr(0, 2) == "v ") {
  208. std::istringstream s(line.substr(2));
  209. float x, y, z;
  210. s >> x;
  211. s >> y;
  212. s >> z;
  213. line = ".float " + std::to_string(x) + ", " +
  214. std::to_string(y) + ", " + std::to_string(z);
  215. dsm_mem.push_back(line);
  216. }
  217. }
  218. dsm_mem.push_back(".EndUnpack");
  219. dsm_mem.push_back("");
  220. if (!map) {
  221. dsm_mem.push_back("stcycl 01, 01; We write code to memory without "
  222. "skips/overwrite");
  223. dsm_mem.push_back("");
  224. dsm_mem.push_back("unpack[r] V4_32, ,*; Vertex affiliation header");
  225. // printf("%lu", bones.size());
  226. vertex_affiliation = dsm_mem.size() - 1;
  227. for (unsigned int i = 0; i < ceil(float(bones.size()) / 4); i++) {
  228. line = ".int " + std::to_string(bones[(i * 4)]);
  229. unsigned int z = 1;
  230. while ((i * 4) + z < bones.size() && z < 4) {
  231. line += ", " + std::to_string(bones[(i * 4) + z]);
  232. z++;
  233. }
  234. for (; z < 4; z++) {
  235. line += ", 0";
  236. }
  237. dsm_mem.push_back(line);
  238. }
  239. dsm_mem.push_back(".EndUnpack");
  240. } else {
  241. // For some reason this is only specified in maps, should look at
  242. // how necessary this truly is later
  243. dsm_mem.push_back(
  244. "mscnt; We tell the game the microcode continues");
  245. }
  246. dsm_mem.push_back("vifnop");
  247. dsm_mem.push_back("vifnop; We wait for data to be kicked in");
  248. }
  249. printf("h1: %i, h2: 4, h3: %i, h4: %i\nj1: %i, j2: %i, j3: 0, j4: 1\n", 0,
  250. 4 + (face_count * 3) + vertex_count,
  251. int(4 + (face_count * 3) + vertex_count +
  252. ceil(float(bones.size()) / 4)),
  253. 4 + (face_count * 3), int(bones.size()));
  254. // TODO: Stop hardcode Header size(5type-line exist) and Vert/Array
  255. // h3: 1 not because 1 value but 1 array of 4, padding needs to be
  256. // checked!
  257. if (!map) {
  258. line = ".int " + std::to_string(face_count * 3) + ", 4, " +
  259. std::to_string(4 + (face_count * 3) + vertex_count) + ", " +
  260. std::to_string(int(4 + (face_count * 3) + vertex_count +
  261. ceil(float(bones.size()) / 4))) +
  262. "; Number of u+v+flag+index, their offset, offset of vertex "
  263. "affiliation header, offset of mat definition(end)";
  264. } else {
  265. line = ".int " + std::to_string(face_count * 3) +
  266. ", 4, 0, 0; Number of u+v+flag+index, their offset, offset of "
  267. "vertex "
  268. "affiliation header, offset of mat definition(end)";
  269. }
  270. dsm_mem[tmpheader] = line;
  271. dsm_mem[tmpheader + 1] =
  272. ".int 0, 0, 0, 0; Nobody care about vertices merging and colors";
  273. if (!map) {
  274. line =
  275. ".int " + std::to_string(vertex_count) + ", " +
  276. std::to_string(4 + (face_count * 3)) + ", 0, " +
  277. std::to_string(bones.size()) +
  278. "; Number of vertices, their offset, reserved and number of array "
  279. "attribution";
  280. } else {
  281. line = ".int " + std::to_string(vertex_count) + ", " +
  282. std::to_string(4 + (face_count * 3)) +
  283. ", 0, 0; Number of vertices, their offset, reserved and number "
  284. "of array "
  285. "attribution";
  286. }
  287. dsm_mem[tmpheader + 2] = line;
  288. line = "unpack[mr] V3_32, " + std::to_string(4 + (face_count * 3)) +
  289. ", *; Vertex definition";
  290. dsm_mem[vertices_arg] = line;
  291. if (!map) {
  292. line = "unpack[r] V4_32, " +
  293. std::to_string(4 + (face_count * 3) + vertex_count) +
  294. " ,*; Vertex affiliation header";
  295. dsm_mem[vertex_affiliation] = line;
  296. }
  297. for (unsigned int i = 0; i < dsm_mem.size(); i++) {
  298. dsm << dsm_mem[i] << std::endl;
  299. }
  300. dsm.close();
  301. if (system(("dvp-as \"" + dsmname + "\" -o junk.o").c_str()) != 0) {
  302. printf("Could not proceed, please install the homebrew ps2 sdk!\n");
  303. return -1;
  304. }
  305. if (system(("dvp-objcopy -O binary junk.o \"" + kh2vname + "\"").c_str()) !=
  306. 0) {
  307. printf("Your homebrew ps2 sdk installation seems to be broken, please "
  308. "reinstall\n");
  309. return -1;
  310. }
  311. remove("junk.o");
  312. if (!junk) {
  313. remove(dsmname.c_str());
  314. }
  315. FILE *vifpkt = fopen(kh2vname.c_str(), "a");
  316. char empty[] = { 0x00 };
  317. while (ftell(vifpkt) % 16 != 0) {
  318. fwrite(empty, 1, sizeof(empty), vifpkt);
  319. }
  320. fclose(vifpkt);
  321. return 1;
  322. }