PageRenderTime 51ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/misc/win32/hitfilemaker/q3data.c

http://sgfork.googlecode.com/
C | 793 lines | 543 code | 108 blank | 142 comment | 164 complexity | a9a0fdb31ceeb85a2b74aec132efbeff MD5 | raw file
Possible License(s): AGPL-1.0, Unlicense
  1. #include <io.h>
  2. #include <sys/stat.h>
  3. #include "q3data.h"
  4. #include "md3lib.h"
  5. #ifdef _WIN32
  6. #include <windows.h>
  7. #endif
  8. qbool g_verbose;
  9. qbool g_stripify = qtrue;
  10. qbool g_release; // don't grab, copy output data to new tree
  11. char g_releasedir[1024]; // c:\quake2\baseq2, etc
  12. qbool g_archive; // don't grab, copy source data to new tree
  13. char g_only[256]; // if set, only grab this cd
  14. qbool g_skipmodel; // set true when a cd is not g_only
  15. /*
  16. =======================================================
  17. PAK FILES
  18. =======================================================
  19. */
  20. unsigned Com_BlockChecksum (void *buffer, int length);
  21. typedef struct
  22. {
  23. char name[56];
  24. int filepos, filelen;
  25. } packfile_t;
  26. typedef struct
  27. {
  28. char id[4];
  29. int dirofs;
  30. int dirlen;
  31. } packheader_t;
  32. packfile_t pfiles[16384];
  33. FILE *pakfile;
  34. packfile_t *pf;
  35. packheader_t pakheader;
  36. /*
  37. ==============
  38. BeginPak
  39. ==============
  40. */
  41. #if 0
  42. void BeginPak (char *outname)
  43. {
  44. if (!g_pak)
  45. return;
  46. pakfile = SafeOpenWrite (outname);
  47. // leave space for header
  48. SafeWrite (pakfile, &pakheader, sizeof(pakheader));
  49. pf = pfiles;
  50. }
  51. #endif
  52. /*
  53. ==============
  54. ReleaseFile
  55. Filename should be gamedir reletive.
  56. Either copies the file to the release dir, or adds it to
  57. the pak file.
  58. ==============
  59. */
  60. void ReleaseFile (char *filename)
  61. {
  62. char source[1024];
  63. char dest[1024];
  64. if (!g_release)
  65. return;
  66. sprintf (source, "%s%s", gamedir, filename);
  67. // if (!g_pak)
  68. { // copy it
  69. sprintf (dest, "%s/%s", g_releasedir, filename);
  70. printf ("copying to %s\n", dest);
  71. QCopyFile (source, dest);
  72. return;
  73. }
  74. #if 0
  75. else
  76. {
  77. int len;
  78. byte *buf;
  79. // pak it
  80. printf ("paking %s\n", filename);
  81. if (strlen(filename) >= sizeof(pf->name))
  82. Error ("Filename too long for pak: %s", filename);
  83. len = LoadFile (source, (void **)&buf);
  84. /*
  85. if (g_compress_pak && len < 4096*1024 )
  86. {
  87. cblock_t in, out;
  88. cblock_t Huffman (cblock_t in);
  89. in.count = len;
  90. in.data = buf;
  91. out = Huffman (in);
  92. if (out.count < in.count)
  93. {
  94. printf (" compressed from %i to %i\n", in.count, out.count);
  95. free (in.data);
  96. buf = out.data;
  97. len = out.count;
  98. }
  99. else
  100. free (out.data);
  101. }
  102. */
  103. strcpy (pf->name, filename);
  104. pf->filepos = LittleLong(ftell(pakfile));
  105. pf->filelen = LittleLong(len);
  106. pf++;
  107. SafeWrite (pakfile, buf, len);
  108. free (buf);
  109. }
  110. #endif
  111. }
  112. typedef struct
  113. {
  114. // shader
  115. // opaque
  116. // opaque 2
  117. // blend
  118. // blend 2
  119. char names[5][1024];
  120. int num;
  121. } ShaderFiles_t;
  122. ShaderFiles_t s_shaderFiles;
  123. void FindShaderFiles( char *filename )
  124. {
  125. char buffer[1024];
  126. char stripped[1024];
  127. char linebuffer[1024];
  128. int len, i;
  129. char *buf;
  130. char *diffuseExtensions[] =
  131. {
  132. ".TGA",
  133. ".WAL",
  134. ".PCX",
  135. 0
  136. };
  137. char *otherExtensions[] =
  138. {
  139. ".specular.TGA",
  140. ".blend.TGA",
  141. ".alpha.TGA",
  142. 0
  143. };
  144. s_shaderFiles.num = 0;
  145. strcpy( stripped, filename );
  146. if ( strrchr( stripped, '.' ) )
  147. *strrchr( stripped, '.' ) = 0;
  148. strcat( stripped, ".shader" );
  149. if ( FileExists( stripped ) )
  150. {
  151. char *p;
  152. char mapa[512], mapb[512];
  153. strcpy( s_shaderFiles.names[s_shaderFiles.num], stripped );
  154. s_shaderFiles.num++;
  155. // load and parse
  156. len = LoadFile( stripped, (void **)&buf);
  157. p = buf;
  158. while ( p - buf < len )
  159. {
  160. i = 0;
  161. // skip spaces
  162. while ( *p == ' ' || *p == '\n' || *p == '\t' )
  163. p++;
  164. // grab rest of the line
  165. while ( *p != 0 && *p != '\n' )
  166. {
  167. linebuffer[i] = *p;
  168. i++;
  169. p++;
  170. }
  171. if ( *p == '\n' )
  172. p++;
  173. linebuffer[i] = 0;
  174. strlwr( linebuffer );
  175. // see if the line specifies an opaque map or blendmap
  176. if ( strstr( linebuffer, "opaquemap" ) == linebuffer ||
  177. strstr( linebuffer, "blendmap" ) == linebuffer )
  178. {
  179. int j;
  180. i = 0;
  181. mapa[0] = mapb[0] = 0;
  182. // skip past the keyword
  183. while ( linebuffer[i] != ' ' && linebuffer[i] != '\t' && linebuffer[i] )
  184. i++;
  185. // skip past spaces
  186. while ( ( linebuffer[i] == ' ' || linebuffer[i] == '\t' ) && linebuffer[i] )
  187. i++;
  188. // grab first map name
  189. j = 0;
  190. while ( linebuffer[i] != ' ' && linebuffer[i] != '\t' && linebuffer[i] )
  191. {
  192. mapa[j] = linebuffer[i];
  193. j++;
  194. i++;
  195. }
  196. mapa[j] = 0;
  197. // skip past spaces
  198. while ( ( linebuffer[i] == ' ' || linebuffer[i] == '\t' ) && linebuffer[i] )
  199. i++;
  200. // grab second map name
  201. j = 0;
  202. while ( linebuffer[i] != ' ' && linebuffer[i] != '\t' && linebuffer[i] )
  203. {
  204. mapb[j] = linebuffer[i];
  205. j++;
  206. i++;
  207. }
  208. mapb[j] = 0;
  209. // store map names
  210. if ( mapa[0] != 0 && mapa[0] != '-' )
  211. {
  212. sprintf( s_shaderFiles.names[s_shaderFiles.num], "%s%s", gamedir, mapa );
  213. s_shaderFiles.num++;
  214. }
  215. if ( mapb[0] != 0 && mapb[0] != '-' && mapb[0] != '^' && mapb[0] != '*' )
  216. {
  217. sprintf( s_shaderFiles.names[s_shaderFiles.num], "%s%s", gamedir, mapb );
  218. s_shaderFiles.num++;
  219. }
  220. }
  221. }
  222. }
  223. else
  224. {
  225. if ( strrchr( stripped, '.' ) )
  226. *strrchr( stripped, '.' ) = 0;
  227. // look for diffuse maps
  228. for ( i = 0; i < 3; i++ )
  229. {
  230. strcpy( buffer, stripped );
  231. strcat( buffer, diffuseExtensions[i] );
  232. if ( FileExists( buffer ) )
  233. {
  234. strcpy( s_shaderFiles.names[s_shaderFiles.num], buffer );
  235. s_shaderFiles.num++;
  236. break;
  237. }
  238. }
  239. for ( i = 0; i < 3; i++ )
  240. {
  241. strcpy( buffer, stripped );
  242. strcat( buffer, otherExtensions[i] );
  243. if ( FileExists( buffer ) )
  244. {
  245. strcpy( s_shaderFiles.names[s_shaderFiles.num], buffer );
  246. s_shaderFiles.num++;
  247. }
  248. }
  249. }
  250. }
  251. /*
  252. ==============
  253. ReleaseShader
  254. Copies all needed files for a shader to the release directory
  255. ==============
  256. */
  257. void ReleaseShader( char *filename )
  258. {
  259. char fullpath[1024];
  260. char dest[1024];
  261. char stripped[1024];
  262. int i;
  263. sprintf( fullpath, "%s%s", gamedir, filename );
  264. FindShaderFiles( fullpath );
  265. // if ( !g_pak )
  266. {
  267. for ( i = 0; i < s_shaderFiles.num; i++ )
  268. {
  269. strcpy( stripped, s_shaderFiles.names[i] );
  270. if ( strstr( stripped, gamedir ) )
  271. {
  272. memmove( stripped, stripped+ strlen( gamedir ), strlen( stripped ) );
  273. }
  274. sprintf( dest, "%s/%s", g_releasedir, stripped );
  275. printf ("copying to %s\n", dest );
  276. QCopyFile( s_shaderFiles.names[i], dest );
  277. }
  278. }
  279. }
  280. /*
  281. ==============
  282. FinishPak
  283. ==============
  284. */
  285. #if 0
  286. void FinishPak (void)
  287. {
  288. int dirlen;
  289. int d;
  290. int i;
  291. unsigned checksum;
  292. if (!g_pak)
  293. return;
  294. pakheader.id[0] = 'P';
  295. pakheader.id[1] = 'A';
  296. pakheader.id[2] = 'C';
  297. pakheader.id[3] = 'K';
  298. dirlen = (byte *)pf - (byte *)pfiles;
  299. pakheader.dirofs = LittleLong(ftell(pakfile));
  300. pakheader.dirlen = LittleLong(dirlen);
  301. checksum = Com_BlockChecksum ( (void *)pfiles, dirlen );
  302. SafeWrite (pakfile, pfiles, dirlen);
  303. i = ftell (pakfile);
  304. fseek (pakfile, 0, SEEK_SET);
  305. SafeWrite (pakfile, &pakheader, sizeof(pakheader));
  306. fclose (pakfile);
  307. d = pf - pfiles;
  308. printf ("%i files packed in %i bytes\n",d, i);
  309. printf ("checksum: 0x%x\n", checksum);
  310. }
  311. #endif
  312. /*
  313. ===============
  314. Cmd_File
  315. This is only used to cause a file to be copied during a release
  316. build (default.cfg, maps, etc)
  317. ===============
  318. */
  319. void Cmd_File (void)
  320. {
  321. GetToken (qfalse);
  322. ReleaseFile (token);
  323. }
  324. /*
  325. ===============
  326. PackDirectory_r
  327. ===============
  328. */
  329. #ifdef _WIN32
  330. #include "io.h"
  331. void PackDirectory_r (char *dir)
  332. {
  333. struct _finddata_t fileinfo;
  334. int handle;
  335. char dirstring[1024];
  336. char filename[1024];
  337. sprintf (dirstring, "%s%s/*.*", gamedir, dir);
  338. handle = _findfirst (dirstring, &fileinfo);
  339. if (handle == -1)
  340. return;
  341. do
  342. {
  343. sprintf (filename, "%s/%s", dir, fileinfo.name);
  344. if (fileinfo.attrib & _A_SUBDIR)
  345. { // directory
  346. if (fileinfo.name[0] != '.') // don't pak . and ..
  347. PackDirectory_r (filename);
  348. continue;
  349. }
  350. // copy or pack the file
  351. ReleaseFile (filename);
  352. } while (_findnext( handle, &fileinfo ) != -1);
  353. _findclose (handle);
  354. }
  355. #else
  356. #include <sys/types.h>
  357. #ifdef NeXT
  358. #include <sys/dir.h>
  359. #else
  360. #include <sys/dirent.h>
  361. #endif
  362. void PackDirectory_r (char *dir)
  363. {
  364. #ifdef NeXT
  365. struct direct **namelist, *ent;
  366. #else
  367. struct dirent **namelist, *ent;
  368. #endif
  369. int count;
  370. struct stat st;
  371. int i;
  372. int len;
  373. char fullname[1024];
  374. char dirstring[1024];
  375. char *name;
  376. sprintf (dirstring, "%s%s", gamedir, dir);
  377. count = scandir(dirstring, &namelist, NULL, NULL);
  378. for (i=0 ; i<count ; i++)
  379. {
  380. ent = namelist[i];
  381. name = ent->d_name;
  382. if (name[0] == '.')
  383. continue;
  384. sprintf (fullname, "%s/%s", dir, name);
  385. sprintf (dirstring, "%s%s/%s", gamedir, dir, name);
  386. if (stat (dirstring, &st) == -1)
  387. Error ("fstating %s", pf->name);
  388. if (st.st_mode & S_IFDIR)
  389. { // directory
  390. PackDirectory_r (fullname);
  391. continue;
  392. }
  393. // copy or pack the file
  394. ReleaseFile (fullname);
  395. }
  396. }
  397. #endif
  398. /*
  399. ===============
  400. Cmd_Dir
  401. This is only used to cause a directory to be copied during a
  402. release build (sounds, etc)
  403. ===============
  404. */
  405. void Cmd_Dir (void)
  406. {
  407. GetToken (qfalse);
  408. PackDirectory_r (token);
  409. }
  410. //========================================================================
  411. #define MAX_RTEX 16384
  412. int numrtex;
  413. char rtex[MAX_RTEX][64];
  414. void ReleaseTexture (char *name)
  415. {
  416. int i;
  417. char path[1024];
  418. for (i=0 ; i<numrtex ; i++)
  419. if (!Q_stricmp(name, rtex[i]))
  420. return;
  421. if (numrtex == MAX_RTEX)
  422. Error ("numrtex == MAX_RTEX");
  423. strcpy (rtex[i], name);
  424. numrtex++;
  425. sprintf (path, "textures/%s.wal", name);
  426. ReleaseFile (path);
  427. }
  428. /*
  429. ===============
  430. Cmd_Maps
  431. Only relevent for release and pak files.
  432. Releases the .bsp files for the maps, and scans all of the files to
  433. build a list of all textures used, which are then released.
  434. ===============
  435. */
  436. void Cmd_Maps (void)
  437. {
  438. char map[1024];
  439. // int i;
  440. while (TokenAvailable ())
  441. {
  442. GetToken (qfalse);
  443. sprintf (map, "maps/%s.bsp", token);
  444. ReleaseFile (map);
  445. if (!g_release)
  446. continue;
  447. // get all the texture references
  448. sprintf (map, "%smaps/%s.bsp", gamedir, token);
  449. LoadBSPFile( map );
  450. #if 0 // FIXME: Q3 surface parsing
  451. for (i=0 ; i<numtexinfo ; i++)
  452. ReleaseTexture (texinfo[i].texture);
  453. #endif
  454. }
  455. }
  456. //==============================================================
  457. /*
  458. ===============
  459. ParseScript
  460. ===============
  461. */
  462. void ParseScript (void)
  463. {
  464. while (1)
  465. {
  466. do
  467. { // look for a line starting with a $ command
  468. GetToken (qtrue);
  469. if (endofscript)
  470. return;
  471. if (token[0] == '$')
  472. break;
  473. while (TokenAvailable())
  474. GetToken (qfalse);
  475. } while (1);
  476. //
  477. // model commands
  478. //
  479. if (!strcmp (token, "$modelname"))
  480. Cmd_Modelname ();
  481. else if (!strcmp (token, "$base"))
  482. Cmd_Base ();
  483. else if ( !strcmp( token, "$exit" ) )
  484. break;
  485. else if ( !strcmp( token, "$3dsconvert" ) )
  486. Cmd_3DSConvert();
  487. else if (!strcmp (token, "$spritebase"))
  488. Cmd_SpriteBase ();
  489. else if (!strcmp (token, "$cd"))
  490. Cmd_Cd ();
  491. else if (!strcmp (token, "$origin"))
  492. Cmd_Origin ();
  493. else if (!strcmp (token, "$scale"))
  494. Cmd_ScaleUp ();
  495. else if (!strcmp (token, "$frame"))
  496. Cmd_Frame ();
  497. else if (!strcmp (token, "$skin" ))
  498. Cmd_Skin();
  499. else if (!strcmp (token, "$spriteshader"))
  500. Cmd_SpriteShader();
  501. else if (!strcmp( token, "$aseconvert" ))
  502. Cmd_ASEConvert( qfalse );
  503. else if (!strcmp( token, "$aseanimconvert" ) )
  504. Cmd_ASEConvert( qtrue );
  505. //
  506. // image commands
  507. //
  508. else if (!strcmp (token, "$grab"))
  509. Cmd_Grab ();
  510. else if (!strcmp (token, "$raw"))
  511. Cmd_Raw ();
  512. else if (!strcmp (token, "$colormap"))
  513. Cmd_Colormap ();
  514. else if (!strcmp (token, "$environment"))
  515. Cmd_Environment ();
  516. //
  517. // video
  518. //
  519. else if (!strcmp (token, "$video"))
  520. Cmd_Video ();
  521. //
  522. // misc
  523. //
  524. else if (!strcmp (token, "$file"))
  525. Cmd_File ();
  526. else if (!strcmp (token, "$dir"))
  527. Cmd_Dir ();
  528. else if (!strcmp (token, "$maps"))
  529. Cmd_Maps ();
  530. else
  531. Error ("bad command %s\n", token);
  532. }
  533. }
  534. //=======================================================
  535. void ConvertMD3ToHit(char *filename, char * tagname, qbool tag_exists);
  536. void ConvertMD3ToMD(char *filename);
  537. void OpenHitFile( char *filename);
  538. /*
  539. ==============
  540. main
  541. ==============
  542. */
  543. int main (int argc, char **argv)
  544. {
  545. static int i; // VC4.2 compiler bug if auto...
  546. char path[1024];
  547. char tag[64];
  548. printf ("\nModel-To-Hitfile-Converter v.2.0, (c) 2002 by Spoon\n");
  549. ExpandWildcards (&argc, &argv);
  550. // build a md own engine ;)
  551. if(!strcmp(argv[1], "-mdbuild")){
  552. strcpy(path, argv[2]);
  553. ConvertMD3ToMD(path);
  554. return 0;
  555. }
  556. if(argc < 2){
  557. Error ("usage: md2hit [modelpath] [tag]");
  558. }
  559. if(argc >= 3){
  560. if(!stricmp(argv[2], "read") ){
  561. strcpy(path, argv[1]);
  562. DefaultExtension (path, ".hit");
  563. OpenHitFile(path);
  564. return 0;
  565. }
  566. strcpy(tag, argv[2]);
  567. tag[4] = '\0';
  568. if(!stricmp(tag, "tag_")){
  569. strcpy(tag, argv[2]);
  570. printf("\nIncluding %s\n", tag);
  571. strcpy(path, argv[1]);
  572. ConvertMD3ToHit(path, tag, qtrue);
  573. return 0;
  574. }
  575. }
  576. strcpy(path, argv[1]);
  577. ConvertMD3ToHit(path, tag, qfalse);
  578. return 0;
  579. for (i=1 ; i<argc ; i++)
  580. {
  581. if (!strcmp(argv[i], "-archive"))
  582. {
  583. // -archive f:/quake2/release/dump_11_30
  584. archive = qtrue;
  585. strcpy (archivedir, argv[i+1]);
  586. printf ("Archiving source to: %s\n", archivedir);
  587. i++;
  588. }
  589. else if (!strcmp(argv[i], "-release"))
  590. {
  591. g_release = qtrue;
  592. strcpy (g_releasedir, argv[i+1]);
  593. printf ("Copy output to: %s\n", g_releasedir);
  594. i++;
  595. }
  596. else if ( !strcmp( argv[i], "-nostrips" ) )
  597. {
  598. g_stripify = qfalse;
  599. printf( "Not optimizing for strips\n" );
  600. }
  601. else if ( !strcmp( argv[i], "-writedir" ) )
  602. {
  603. strcpy( writedir, argv[i+1] );
  604. printf( "Write output to: %s\n", writedir );
  605. i++;
  606. }
  607. else if ( !strcmp( argv[i], "-verbose" ) )
  608. {
  609. g_verbose = qtrue;
  610. }
  611. else if ( !strcmp( argv[i], "-dump" ) )
  612. {
  613. printf( "Dumping contents of: '%s'\n", argv[i+1] );
  614. if ( strstr( argv[i+1], ".md3" ) )
  615. {
  616. MD3_Dump( argv[i+1] );
  617. }
  618. else
  619. {
  620. Error( "Do not know how to dump the contents of '%s'\n", argv[i+1] );
  621. }
  622. i++;
  623. }
  624. else if ( !strcmp( argv[i], "-3dsconvert" ) )
  625. {
  626. printf( "Converting %s.3DS to %s.MD3\n", argv[i+1], argv[i+1] );
  627. SetQdirFromPath( argv[i+1] );
  628. Convert3DStoMD3( argv[i+1] );
  629. i++;
  630. }
  631. #if 0
  632. else if (!strcmp(argv[i], "-pak"))
  633. {
  634. g_release = qtrue;
  635. g_pak = qtrue;
  636. printf ("Building pakfile: %s\n", argv[i+1]);
  637. BeginPak (argv[i+1]);
  638. i++;
  639. }
  640. #endif
  641. else if (!strcmp(argv[i], "-only"))
  642. {
  643. strcpy (g_only, argv[i+1]);
  644. printf ("Only grabbing %s\n", g_only);
  645. i++;
  646. }
  647. else if (argv[i][0] == '-')
  648. Error ("Unknown option \"%s\"", argv[i]);
  649. else
  650. break;
  651. }
  652. if (i == argc)
  653. Error ("usage: qgrab [-archive <directory>] [-dump <file>] [-release <directory>] [-only <model>] [-3ds] [-verbose] [file.qdt]");
  654. for ( ; i<argc ; i++)
  655. {
  656. printf ("--------------- %s ---------------\n", argv[i]);
  657. // load the script
  658. strcpy (path, argv[i]);
  659. DefaultExtension (path, ".qdt");
  660. SetQdirFromPath (path);
  661. LoadScriptFile (ExpandArg(path));
  662. //
  663. // parse it
  664. //
  665. ParseScript ();
  666. // write out the last model
  667. FinishModel ( TYPE_UNKNOWN );
  668. }
  669. #if 0
  670. if (g_pak)
  671. FinishPak ();
  672. #endif
  673. return 0;
  674. }