home *** CD-ROM | disk | FTP | other *** search
/ PC PowerPlay 58 / pcpp58a.iso / extras / quake 3 source / Q3A_ToolSource.exe / Main / q3data.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-02  |  14.6 KB  |  754 lines

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