SPRGEN.C 9.5 KB

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