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.

obj2kh2v.cpp 11KB

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