/*** * * Copyright (c) 1996-2001, Valve LLC. All rights reserved. * * This product contains software technology licensed from Id * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * All Rights Reserved. * ****/ // // spritegen.c: generates a .spr file from a series of .lbm frame files. // Result is stored in /raid/quake/id1/sprites/.spr. // #pragma warning(disable : 4244) // type conversion warning. #define INCLUDELIBS #ifdef NeXT #include #endif #include "spritegn.h" #define MAX_BUFFER_SIZE 0x100000 #define MAX_FRAMES 1000 dsprite_t sprite; byte *byteimage, *lbmpalette; int byteimagewidth, byteimageheight; byte *lumpbuffer = NULL, *plump; char spritedir[1024]; char spriteoutname[1024]; int framesmaxs[2]; int framecount; qboolean do16bit = true; typedef struct { spriteframetype_t type; // single frame or group of frames void *pdata; // either a dspriteframe_t or group info float interval; // only used for frames in groups int numgroupframes; // only used by group headers } spritepackage_t; spritepackage_t frames[MAX_FRAMES]; void FinishSprite (void); void Cmd_Spritename (void); /* ============ WriteFrame ============ */ void WriteFrame (FILE *spriteouthandle, int framenum) { dspriteframe_t *pframe; dspriteframe_t frametemp; pframe = (dspriteframe_t *)frames[framenum].pdata; frametemp.origin[0] = LittleLong (pframe->origin[0]); frametemp.origin[1] = LittleLong (pframe->origin[1]); frametemp.width = LittleLong (pframe->width); frametemp.height = LittleLong (pframe->height); SafeWrite (spriteouthandle, &frametemp, sizeof (frametemp)); SafeWrite (spriteouthandle, (byte *)(pframe + 1), pframe->height * pframe->width); } /* ============ WriteSprite ============ */ void WriteSprite (FILE *spriteouthandle) { int i, groupframe, curframe; dsprite_t spritetemp; sprite.boundingradius = sqrt (((framesmaxs[0] >> 1) * (framesmaxs[0] >> 1)) + ((framesmaxs[1] >> 1) * (framesmaxs[1] >> 1))); // // write out the sprite header // spritetemp.type = LittleLong (sprite.type); spritetemp.texFormat = LittleLong (sprite.texFormat); spritetemp.boundingradius = LittleFloat (sprite.boundingradius); spritetemp.width = LittleLong (framesmaxs[0]); spritetemp.height = LittleLong (framesmaxs[1]); spritetemp.numframes = LittleLong (sprite.numframes); spritetemp.beamlength = LittleFloat (sprite.beamlength); spritetemp.synctype = LittleFloat (sprite.synctype); spritetemp.version = LittleLong (SPRITE_VERSION); spritetemp.ident = LittleLong (IDSPRITEHEADER); SafeWrite (spriteouthandle, &spritetemp, sizeof(spritetemp)); if( do16bit ) { // Write out palette in 16bit mode short cnt = 256; SafeWrite( spriteouthandle, (void *) &cnt, sizeof(cnt) ); SafeWrite( spriteouthandle, lbmpalette, cnt * 3 ); } // // write out the frames // curframe = 0; for (i=0 ; i 256) || (h > 256)) Error ("Sprite has a dimension longer than 256"); xh = xl+w; yh = yl+h; pframe = (dspriteframe_t *)plump; frames[framecount].pdata = pframe; frames[framecount].type = SPR_SINGLE; if (TokenAvailable ()) { GetToken (false); frames[framecount].interval = atof (token); if (frames[framecount].interval <= 0.0) Error ("Non-positive interval"); } else { frames[framecount].interval = (float)0.1; } if (TokenAvailable ()) { GetToken (false); pframe->origin[0] = -atoi (token); GetToken (false); pframe->origin[1] = atoi (token); } else { pframe->origin[0] = -(w >> 1); pframe->origin[1] = h >> 1; } pframe->width = w; pframe->height = h; if (w > framesmaxs[0]) framesmaxs[0] = w; if (h > framesmaxs[1]) framesmaxs[1] = h; plump = (byte *)(pframe + 1); screen_p = byteimage + yl*byteimagewidth + xl; linedelta = byteimagewidth - w; source = plump; for (y=yl ; y= MAX_FRAMES) Error ("Too many frames; increase MAX_FRAMES\n"); } /* =============== Cmd_GroupStart =============== */ void Cmd_GroupStart (void) { int groupframe; groupframe = framecount++; frames[groupframe].type = SPR_GROUP; frames[groupframe].numgroupframes = 0; while (1) { GetToken (true); if (endofscript) Error ("End of file during group"); if (!strcmp (token, "$frame")) { Cmd_Frame (); frames[groupframe].numgroupframes++; } else if (!strcmp (token, "$load")) { Cmd_Load (); } else if (!strcmp (token, "$groupend")) { break; } else { Error ("$frame, $load, or $groupend expected\n"); } } if (frames[groupframe].numgroupframes == 0) Error ("Empty group\n"); } /* =============== ParseScript =============== */ void ParseScript (void) { while (1) { GetToken (true); if (endofscript) break; if (!strcmp (token, "$load")) { Cmd_Load (); } if (!strcmp (token, "$spritename")) { Cmd_Spritename (); } else if (!strcmp (token, "$type")) { Cmd_Type (); } else if (!strcmp (token, "$texture")) { Cmd_Texture (); } else if (!strcmp (token, "$beamlength")) { Cmd_Beamlength (); } else if (!strcmp (token, "$sync")) { sprite.synctype = ST_SYNC; } else if (!strcmp (token, "$frame")) { Cmd_Frame (); sprite.numframes++; } else if (!strcmp (token, "$load")) { Cmd_Load (); } else if (!strcmp (token, "$groupstart")) { Cmd_GroupStart (); sprite.numframes++; } } } /* ============== Cmd_Spritename ============== */ void Cmd_Spritename (void) { if (sprite.numframes) FinishSprite (); GetToken (false); sprintf (spriteoutname, "%s%s.spr", spritedir, token); memset (&sprite, 0, sizeof(sprite)); framecount = 0; framesmaxs[0] = -9999999; framesmaxs[1] = -9999999; if ( !lumpbuffer ) lumpbuffer = malloc (MAX_BUFFER_SIZE * 2); // *2 for padding if (!lumpbuffer) Error ("Couldn't get buffer memory"); plump = lumpbuffer; sprite.synctype = ST_RAND; // default } /* ============== FinishSprite ============== */ void FinishSprite (void) { FILE *spriteouthandle; if (sprite.numframes == 0) Error ("no frames\n"); if (!strlen(spriteoutname)) Error ("Didn't name sprite file"); if ((plump - lumpbuffer) > MAX_BUFFER_SIZE) Error ("Sprite package too big; increase MAX_BUFFER_SIZE"); spriteouthandle = SafeOpenWrite (spriteoutname); printf ("saving in %s\n", spriteoutname); WriteSprite (spriteouthandle); fclose (spriteouthandle); printf ("spritegen: successful\n"); printf ("%d frame(s)\n", sprite.numframes); printf ("%d ungrouped frame(s), including group headers\n", framecount); spriteoutname[0] = 0; // clear for a new sprite } /* ============== main ============== */ extern char qproject[]; int main (int argc, char **argv) { int i; printf( "sprgen.exe v 1.1 (%s)\n", __DATE__ ); printf ("----- Sprite Gen ----\n"); if (argc < 2 || argc > 7 ) Error ("usage: sprgen [-archive directory] [-no16bit] [-proj ] file.qc"); for( i=1; i