home *** CD-ROM | disk | FTP | other *** search
/ Superpower (Alt) / SUPERPOWER.iso / q / util / mbq319 / sprgen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-01  |  10.2 KB  |  544 lines

  1. //
  2. // spritegen.c: generates a .spr file from a series of .lbm frame files.
  3. // Result is stored in /raid/quake/id1/sprites/<scriptname>.spr.
  4. //
  5.  
  6. #define INCLUDELIBS
  7.  
  8. #include <sys/file.h>
  9.  
  10. #include "spritegn.h"
  11.  
  12. #define MAX_BUFFER_SIZE        0x100000
  13. #define MAX_FRAMES            1000
  14.  
  15. dsprite_t        sprite;
  16. byte            *byteimage, *lbmpalette;
  17. int                byteimagewidth, byteimageheight;
  18. byte            *lumpbuffer, *plump;
  19. char            spritedir[1024];
  20. char            spriteoutname[1024];
  21. int                framesmaxs[2];
  22. int                framecount;
  23.  
  24. typedef struct {
  25.     spriteframetype_t    type;        // single frame or group of frames
  26.     void                *pdata;        // either a dspriteframe_t or group info
  27.     float                interval;    // only used for frames in groups
  28.     int                    numgroupframes;    // only used by group headers
  29. } spritepackage_t;
  30.  
  31. spritepackage_t    frames[MAX_FRAMES];
  32.  
  33. void WriteSprite (int spriteouthandle);
  34. void FinishSprite (void);
  35. void Cmd_Spritename (void);
  36.  
  37.  
  38. /*
  39. ============
  40. WriteFrame
  41. ============
  42. */
  43. void WriteFrame (int spriteouthandle, int framenum)
  44. {
  45.     dspriteframe_t    *pframe;
  46.     dspriteframe_t    frametemp;
  47.  
  48.     pframe = (dspriteframe_t *)frames[framenum].pdata;
  49.     frametemp.origin[0] = LittleLong (pframe->origin[0]);
  50.     frametemp.origin[1] = LittleLong (pframe->origin[1]);
  51.     frametemp.width = LittleLong (pframe->width);
  52.     frametemp.height = LittleLong (pframe->height);
  53.  
  54.     SafeWrite (spriteouthandle, &frametemp, sizeof (frametemp));
  55.     SafeWrite (spriteouthandle,
  56.                (byte *)(pframe + 1),
  57.                pframe->height * pframe->width);
  58. }
  59.  
  60.  
  61. /*
  62. ============
  63. WriteSprite
  64. ============
  65. */
  66. void WriteSprite (int spriteouthandle)
  67. {
  68.     int            i, groupframe, curframe;
  69.     dsprite_t    spritetemp;
  70.  
  71.     sprite.boundingradius = sqrt (((framesmaxs[0] >> 1) *
  72.                                    (framesmaxs[0] >> 1)) +
  73.                                   ((framesmaxs[1] >> 1) *
  74.                                    (framesmaxs[1] >> 1)));
  75.  
  76. //
  77. // write out the sprite header
  78. //
  79.     spritetemp.type = LittleLong (sprite.type);
  80.     spritetemp.boundingradius = LittleFloat (sprite.boundingradius);
  81.     spritetemp.width = LittleLong (framesmaxs[0]);
  82.     spritetemp.height = LittleLong (framesmaxs[1]);
  83.     spritetemp.numframes = LittleLong (sprite.numframes);
  84.     spritetemp.beamlength = LittleFloat (sprite.beamlength);
  85.     spritetemp.synctype = LittleFloat (sprite.synctype);
  86.     spritetemp.version = LittleLong (SPRITE_VERSION);
  87.     spritetemp.ident = LittleLong (IDSPRITEHEADER);
  88.  
  89.     SafeWrite (spriteouthandle, &spritetemp, sizeof(spritetemp));
  90.  
  91. //
  92. // write out the frames
  93. //
  94.     curframe = 0;
  95.  
  96.     for (i=0 ; i<sprite.numframes ; i++)
  97.     {
  98.         SafeWrite (spriteouthandle, &frames[curframe].type,
  99.                    sizeof(frames[curframe].type));
  100.  
  101.         if (frames[curframe].type == SPR_SINGLE)
  102.         {
  103.         //
  104.         // single (non-grouped) frame
  105.         //
  106.             WriteFrame (spriteouthandle, curframe);
  107.             curframe++;
  108.         }
  109.         else
  110.         {
  111.             int                    j, numframes;
  112.             dspritegroup_t        dsgroup;
  113.             float                totinterval;
  114.  
  115.             groupframe = curframe;
  116.             curframe++;
  117.             numframes = frames[groupframe].numgroupframes;
  118.  
  119.         //
  120.         // set and write the group header
  121.         //
  122.             dsgroup.numframes = LittleLong (numframes);
  123.  
  124.             SafeWrite (spriteouthandle, &dsgroup, sizeof(dsgroup));
  125.  
  126.         //
  127.         // write the interval array
  128.         //
  129.             totinterval = 0.0;
  130.  
  131.             for (j=0 ; j<numframes ; j++)
  132.             {
  133.                 dspriteinterval_t    temp;
  134.  
  135.                 totinterval += frames[groupframe+1+j].interval;
  136.                 temp.interval = LittleFloat (totinterval);
  137.  
  138.                 SafeWrite (spriteouthandle, &temp, sizeof(temp));
  139.             }
  140.  
  141.             for (j=0 ; j<numframes ; j++)
  142.             {
  143.                 WriteFrame (spriteouthandle, curframe);
  144.                 curframe++;
  145.             }
  146.         }
  147.     }
  148. }
  149.  
  150.  
  151. /*
  152. ============
  153. ExecCommand
  154. ============
  155. */
  156. int    cmdsrun;
  157.  
  158. void ExecCommand (char *cmd, ...)
  159. {
  160.     int        ret;
  161.     char    cmdline[1024];
  162.     va_list    argptr;
  163.     
  164.     cmdsrun++;
  165.     
  166.     va_start (argptr, cmd);
  167.     vsprintf (cmdline,cmd,argptr);
  168.     va_end (argptr);
  169.     
  170. //    printf ("=============================================================\n");
  171. //    printf ("spritegen: %s\n",cmdline);
  172.     fflush (stdout);
  173.     ret = system (cmdline);
  174. //    printf ("=============================================================\n");
  175.     
  176.     if (ret)
  177.         Error ("spritegen: exiting due to error");
  178. }
  179.  
  180. /*
  181. ============
  182. FileTime
  183.  
  184. returns -1 if not present
  185. ============
  186. */
  187. int    FileTime (char *path)
  188. {
  189.     struct    stat    buf;
  190.     
  191.     if (stat (path,&buf) == -1)
  192.         return -1;
  193.     
  194.     return buf.st_mtime;
  195. }
  196.  
  197.  
  198. /*
  199. ==============
  200. LoadScreen
  201. ==============
  202. */
  203. void LoadScreen (char *name)
  204. {
  205.     printf ("grabbing from %s...\n",name);
  206.     LoadLBM (name, &byteimage, &lbmpalette);
  207.  
  208.     byteimagewidth = bmhd.w;
  209.     byteimageheight = bmhd.h;
  210. }
  211.  
  212.  
  213. /*
  214. ===============
  215. Cmd_Type
  216. ===============
  217. */
  218. void Cmd_Type (void)
  219. {
  220.     GetToken (false);
  221.     if (!strcmp (token, "vp_parallel_upright"))
  222.         sprite.type = SPR_VP_PARALLEL_UPRIGHT;
  223.     else if (!strcmp (token, "facing_upright"))
  224.         sprite.type = SPR_FACING_UPRIGHT;
  225.     else if (!strcmp (token, "vp_parallel"))
  226.         sprite.type = SPR_VP_PARALLEL;
  227.     else if (!strcmp (token, "oriented"))
  228.         sprite.type = SPR_ORIENTED;
  229.     else if (!strcmp (token, "vp_parallel_oriented"))
  230.         sprite.type = SPR_VP_PARALLEL_ORIENTED;
  231.     else
  232.         Error ("Bad sprite type\n");
  233. }
  234.  
  235.  
  236. /*
  237. ===============
  238. Cmd_Beamlength
  239. ===============
  240. */
  241. void Cmd_Beamlength ()
  242. {
  243.     GetToken (false);
  244.     sprite.beamlength = atof (token);
  245. }
  246.  
  247.  
  248. /*
  249. ===============
  250. Cmd_Load
  251. ===============
  252. */
  253. void Cmd_Load (void)
  254. {
  255.     GetToken (false);
  256.     LoadScreen (token);
  257. }
  258.  
  259.  
  260. /*
  261. ===============
  262. Cmd_Frame
  263. ===============
  264. */
  265. void Cmd_Frame ()
  266. {
  267.     int             x,y,xl,yl,xh,yh,w,h;
  268.     byte            *screen_p, *source;
  269.     int             linedelta;
  270.     dspriteframe_t    *pframe;
  271.     int                pix;
  272.     
  273.     GetToken (false);
  274.     xl = atoi (token);
  275.     GetToken (false);
  276.     yl = atoi (token);
  277.     GetToken (false);
  278.     w = atoi (token);
  279.     GetToken (false);
  280.     h = atoi (token);
  281.  
  282.     if ((xl & 0x07) || (yl & 0x07) || (w & 0x07) || (h & 0x07))
  283.         Error ("Sprite dimensions not multiples of 8\n");
  284.  
  285.     if ((w > 255) || (h > 255))
  286.         Error ("Sprite has a dimension longer than 255");
  287.  
  288.     xh = xl+w;
  289.     yh = yl+h;
  290.  
  291.     pframe = (dspriteframe_t *)plump;
  292.     frames[framecount].pdata = pframe;
  293.     frames[framecount].type = SPR_SINGLE;
  294.  
  295.     if (TokenAvailable ())
  296.     {
  297.         GetToken (false);
  298.         frames[framecount].interval = atof (token);
  299.         if (frames[framecount].interval <= 0.0)
  300.             Error ("Non-positive interval");
  301.     }
  302.     else
  303.     {
  304.         frames[framecount].interval = 0.1;
  305.     }
  306.     
  307.     if (TokenAvailable ())
  308.     {
  309.         GetToken (false);
  310.         pframe->origin[0] = -atoi (token);
  311.         GetToken (false);
  312.         pframe->origin[1] = atoi (token);
  313.     }
  314.     else
  315.     {
  316.         pframe->origin[0] = -(w >> 1);
  317.         pframe->origin[1] = h >> 1;
  318.     }
  319.  
  320.     pframe->width = w;
  321.     pframe->height = h;
  322.  
  323.     if (w > framesmaxs[0])
  324.         framesmaxs[0] = w;
  325.     
  326.     if (h > framesmaxs[1])
  327.         framesmaxs[1] = h;
  328.     
  329.     plump = (byte *)(pframe + 1);
  330.  
  331.     screen_p = byteimage + yl*byteimagewidth + xl;
  332.     linedelta = byteimagewidth - w;
  333.  
  334.     source = plump;
  335.  
  336.     for (y=yl ; y<yh ; y++)
  337.     {
  338.         for (x=xl ; x<xh ; x++)
  339.         {
  340.             pix = *screen_p;
  341.             *screen_p++ = 0;
  342. //            if (pix == 255)
  343. //                pix = 0;
  344.             *plump++ = pix;
  345.         }
  346.         screen_p += linedelta;
  347.     }
  348.  
  349.     framecount++;
  350.     if (framecount >= MAX_FRAMES)
  351.         Error ("Too many frames; increase MAX_FRAMES\n");
  352. }
  353.  
  354.  
  355. /*
  356. ===============
  357. Cmd_GroupStart    
  358. ===============
  359. */
  360. void Cmd_GroupStart (void)
  361. {
  362.     int            groupframe;
  363.  
  364.     groupframe = framecount++;
  365.  
  366.     frames[groupframe].type = SPR_GROUP;
  367.     frames[groupframe].numgroupframes = 0;
  368.  
  369.     while (1)
  370.     {
  371.         GetToken (true);
  372.         if (endofscript)
  373.             Error ("End of file during group");
  374.  
  375.         if (!strcmp (token, "$frame"))
  376.         {
  377.             Cmd_Frame ();
  378.             frames[groupframe].numgroupframes++;
  379.         }
  380.         else if (!strcmp (token, "$load"))
  381.         {
  382.             Cmd_Load ();
  383.         }
  384.         else if (!strcmp (token, "$groupend"))
  385.         {
  386.             break;
  387.         }
  388.         else
  389.         {
  390.             Error ("$frame, $load, or $groupend expected\n");
  391.         }
  392.  
  393.     }
  394.  
  395.     if (frames[groupframe].numgroupframes == 0)
  396.         Error ("Empty group\n");
  397. }
  398.  
  399.  
  400. /*
  401. ===============
  402. ParseScript    
  403. ===============
  404. */
  405. void ParseScript (void)
  406. {
  407.     while (1)
  408.     {
  409.         GetToken (true);
  410.         if (endofscript)
  411.             break;
  412.     
  413.         if (!strcmp (token, "$load"))
  414.         {
  415.             Cmd_Load ();
  416.         }
  417.         if (!strcmp (token, "$spritename"))
  418.         {
  419.             Cmd_Spritename ();
  420.         }
  421.         else if (!strcmp (token, "$type"))
  422.         {
  423.             Cmd_Type ();
  424.         }
  425.         else if (!strcmp (token, "$beamlength"))
  426.         {
  427.             Cmd_Beamlength ();
  428.         }
  429.         else if (!strcmp (token, "$sync"))
  430.         {
  431.             sprite.synctype = ST_SYNC;
  432.         }
  433.         else if (!strcmp (token, "$frame"))
  434.         {
  435.             Cmd_Frame ();
  436.             sprite.numframes++;
  437.         }        
  438.         else if (!strcmp (token, "$load"))
  439.         {
  440.             Cmd_Load ();
  441.         }
  442.         else if (!strcmp (token, "$groupstart"))
  443.         {
  444.             Cmd_GroupStart ();
  445.             sprite.numframes++;
  446.         }
  447.     }
  448. }
  449.  
  450. /*
  451. ==============
  452. Cmd_Spritename
  453. ==============
  454. */
  455. void Cmd_Spritename (void)
  456. {
  457.     if (sprite.numframes)
  458.         FinishSprite ();
  459.  
  460.     GetToken (false);
  461.     sprintf (spriteoutname, "%s/%s.spr", spritedir, token);
  462.     memset (&sprite, 0, sizeof(sprite));
  463.     framecount = 0;
  464.  
  465.     framesmaxs[0] = -9999999;
  466.     framesmaxs[1] = -9999999;
  467.  
  468.     lumpbuffer = malloc (MAX_BUFFER_SIZE * 2);    // *2 for padding
  469.     if (!lumpbuffer)
  470.         Error ("Couldn't get buffer memory");
  471.  
  472.     plump = lumpbuffer;
  473.     sprite.synctype = ST_RAND;    // default
  474. }
  475.  
  476. /*
  477. ==============
  478. FinishSprite    
  479. ==============
  480. */
  481. void FinishSprite (void)
  482. {
  483.     int        spriteouthandle;
  484.  
  485.     if (sprite.numframes == 0)
  486.         Error ("no frames\n");
  487.  
  488.     if (!strlen(spriteoutname))
  489.         Error ("Didn't name sprite file");
  490.         
  491.     if ((plump - lumpbuffer) > MAX_BUFFER_SIZE)
  492.         Error ("Sprite package too big; increase MAX_BUFFER_SIZE");
  493.  
  494.     spriteouthandle = SafeOpenWrite (spriteoutname);
  495.     printf ("saving in %s\n", spriteoutname);
  496.     WriteSprite (spriteouthandle);
  497.     close (spriteouthandle);
  498.     
  499.     printf ("spritegen: successful\n");
  500.     printf ("%d frame(s)\n", sprite.numframes);
  501.     printf ("%d ungrouped frame(s), including group headers\n", framecount);
  502.     
  503.     spriteoutname[0] = 0;        // clear for a new sprite
  504. }
  505.  
  506. /*
  507. ==============
  508. main
  509.     
  510. ==============
  511. */
  512. int main (int argc, char **argv)
  513. {
  514.     char    *script;
  515.  
  516.     if (argc != 2)
  517.     {
  518.         printf ("usage: spritegen scriptfile\n");
  519.         exit (1);
  520.     }
  521.  
  522.     script = argv[1];
  523.     if ((script[0] == '/') || (script[0] == '.'))
  524.     {
  525.         ExtractFilePath (script, spritedir);
  526.         spritedir[strlen(spritedir)-1] = 0;    // strip off the last slash
  527.     }
  528.     else
  529.     {
  530.         getwd (spritedir);
  531.     }
  532.  
  533. //
  534. // load the script
  535. //
  536.     LoadScriptFile (script);
  537.     
  538.     ParseScript ();
  539.     FinishSprite ();
  540.  
  541.     return 0;
  542. }
  543.  
  544.