PageRenderTime 48ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/tools/quake2/extra/qdata/qdata.c

https://gitlab.com/illwieckz/netradiant
C | 551 lines | 353 code | 81 blank | 117 comment | 100 complexity | ffcdbf9ecaa91d1a8075460f66df914b MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-2.0
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1997-2006 Id Software, Inc.
  4. This file is part of Quake 2 Tools source code.
  5. Quake 2 Tools source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake 2 Tools source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Quake 2 Tools source code; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. #include "qdata.h"
  19. qboolean g_compress_pak;
  20. qboolean g_release; // don't grab, copy output data to new tree
  21. qboolean g_pak; // if true, copy to pak instead of release
  22. char g_releasedir[1024]; // c:\quake2\baseq2, etc
  23. qboolean g_archive; // don't grab, copy source data to new tree
  24. qboolean do3ds;
  25. char g_only[256]; // if set, only grab this cd
  26. qboolean g_skipmodel; // set true when a cd is not g_only
  27. char *ext_3ds = "3ds";
  28. char *ext_tri= "tri";
  29. char *trifileext;
  30. /*
  31. =======================================================
  32. PAK FILES
  33. =======================================================
  34. */
  35. unsigned Com_BlockChecksum (void *buffer, int length);
  36. typedef struct
  37. {
  38. char name[56];
  39. int filepos, filelen;
  40. } packfile_t;
  41. typedef struct
  42. {
  43. char id[4];
  44. int dirofs;
  45. int dirlen;
  46. } packheader_t;
  47. packfile_t pfiles[16384];
  48. FILE *pakfile;
  49. packfile_t *pf;
  50. packheader_t pakheader;
  51. /*
  52. ==============
  53. BeginPak
  54. ==============
  55. */
  56. void BeginPak (char *outname)
  57. {
  58. if (!g_pak)
  59. return;
  60. pakfile = SafeOpenWrite (outname);
  61. // leave space for header
  62. SafeWrite (pakfile, &pakheader, sizeof(pakheader));
  63. pf = pfiles;
  64. }
  65. /*
  66. ==============
  67. ReleaseFile
  68. Filename should be gamedir reletive.
  69. Either copies the file to the release dir, or adds it to
  70. the pak file.
  71. ==============
  72. */
  73. void ReleaseFile (char *filename)
  74. {
  75. int len;
  76. byte *buf;
  77. char source[1024];
  78. char dest[1024];
  79. if (!g_release)
  80. return;
  81. sprintf (source, "%s%s", gamedir, filename);
  82. if (!g_pak)
  83. { // copy it
  84. sprintf (dest, "%s/%s", g_releasedir, filename);
  85. printf ("copying to %s\n", dest);
  86. QCopyFile (source, dest);
  87. return;
  88. }
  89. // pak it
  90. printf ("paking %s\n", filename);
  91. if (strlen(filename) >= sizeof(pf->name))
  92. Error ("Filename too long for pak: %s", filename);
  93. len = LoadFile (source, (void **)&buf);
  94. if (g_compress_pak && len < 4096*1024 )
  95. {
  96. cblock_t in, out;
  97. cblock_t Huffman (cblock_t in);
  98. in.count = len;
  99. in.data = buf;
  100. out = Huffman (in);
  101. if (out.count < in.count)
  102. {
  103. printf (" compressed from %i to %i\n", in.count, out.count);
  104. free (in.data);
  105. buf = out.data;
  106. len = out.count;
  107. }
  108. else
  109. free (out.data);
  110. }
  111. strcpy (pf->name, filename);
  112. pf->filepos = LittleLong(ftell(pakfile));
  113. pf->filelen = LittleLong(len);
  114. pf++;
  115. SafeWrite (pakfile, buf, len);
  116. free (buf);
  117. }
  118. /*
  119. ==============
  120. FinishPak
  121. ==============
  122. */
  123. void FinishPak (void)
  124. {
  125. int dirlen;
  126. int d;
  127. int i;
  128. unsigned checksum;
  129. if (!g_pak)
  130. return;
  131. pakheader.id[0] = 'P';
  132. pakheader.id[1] = 'A';
  133. pakheader.id[2] = 'C';
  134. pakheader.id[3] = 'K';
  135. dirlen = (byte *)pf - (byte *)pfiles;
  136. pakheader.dirofs = LittleLong(ftell(pakfile));
  137. pakheader.dirlen = LittleLong(dirlen);
  138. checksum = Com_BlockChecksum ( (void *)pfiles, dirlen );
  139. SafeWrite (pakfile, pfiles, dirlen);
  140. i = ftell (pakfile);
  141. fseek (pakfile, 0, SEEK_SET);
  142. SafeWrite (pakfile, &pakheader, sizeof(pakheader));
  143. fclose (pakfile);
  144. d = pf - pfiles;
  145. printf ("%i files packed in %i bytes\n",d, i);
  146. printf ("checksum: 0x%x\n", checksum);
  147. }
  148. /*
  149. ===============
  150. Cmd_File
  151. This is only used to cause a file to be copied during a release
  152. build (default.cfg, maps, etc)
  153. ===============
  154. */
  155. void Cmd_File (void)
  156. {
  157. GetToken (false);
  158. ReleaseFile (token);
  159. }
  160. /*
  161. ===============
  162. PackDirectory_r
  163. ===============
  164. */
  165. #if GDEF_OS_WINDOWS
  166. #include "io.h"
  167. void PackDirectory_r (char *dir)
  168. {
  169. struct _finddata_t fileinfo;
  170. int handle;
  171. char dirstring[1024];
  172. char filename[1024];
  173. sprintf (dirstring, "%s%s/*.*", gamedir, dir);
  174. handle = _findfirst (dirstring, &fileinfo);
  175. if (handle == -1)
  176. return;
  177. do
  178. {
  179. sprintf (filename, "%s/%s", dir, fileinfo.name);
  180. if (fileinfo.attrib & _A_SUBDIR)
  181. { // directory
  182. if (fileinfo.name[0] != '.') // don't pak . and ..
  183. PackDirectory_r (filename);
  184. continue;
  185. }
  186. // copy or pack the file
  187. ReleaseFile (filename);
  188. } while (_findnext( handle, &fileinfo ) != -1);
  189. _findclose (handle);
  190. }
  191. #else
  192. #include <sys/types.h>
  193. #ifdef NeXT
  194. #include <sys/dir.h>
  195. #else
  196. #include <sys/dirent.h>
  197. #endif
  198. void PackDirectory_r (char *dir)
  199. {
  200. #ifdef NeXT
  201. struct direct **namelist, *ent;
  202. #else
  203. struct dirent **namelist, *ent;
  204. #endif
  205. int count;
  206. struct stat st;
  207. int i;
  208. int len;
  209. char fullname[1024];
  210. char dirstring[1024];
  211. char *name;
  212. sprintf (dirstring, "%s%s", gamedir, dir);
  213. count = scandir(dirstring, &namelist, NULL, NULL);
  214. for (i=0 ; i<count ; i++)
  215. {
  216. ent = namelist[i];
  217. name = ent->d_name;
  218. if (name[0] == '.')
  219. continue;
  220. sprintf (fullname, "%s/%s", dir, name);
  221. sprintf (dirstring, "%s%s/%s", gamedir, dir, name);
  222. if (stat (dirstring, &st) == -1)
  223. Error ("fstating %s", pf->name);
  224. if (st.st_mode & S_IFDIR)
  225. { // directory
  226. PackDirectory_r (fullname);
  227. continue;
  228. }
  229. // copy or pack the file
  230. ReleaseFile (fullname);
  231. }
  232. }
  233. #endif
  234. /*
  235. ===============
  236. Cmd_Dir
  237. This is only used to cause a directory to be copied during a
  238. release build (sounds, etc)
  239. ===============
  240. */
  241. void Cmd_Dir (void)
  242. {
  243. GetToken (false);
  244. PackDirectory_r (token);
  245. }
  246. //========================================================================
  247. #define MAX_RTEX 16384
  248. int numrtex;
  249. char rtex[MAX_RTEX][64];
  250. void ReleaseTexture (char *name)
  251. {
  252. int i;
  253. char path[1024];
  254. for (i=0 ; i<numrtex ; i++)
  255. if (!Q_strcasecmp(name, rtex[i]))
  256. return;
  257. if (numrtex == MAX_RTEX)
  258. Error ("numrtex == MAX_RTEX");
  259. strcpy (rtex[i], name);
  260. numrtex++;
  261. sprintf (path, "textures/%s.wal", name);
  262. ReleaseFile (path);
  263. }
  264. /*
  265. ===============
  266. Cmd_Maps
  267. Only relevent for release and pak files.
  268. Releases the .bsp files for the maps, and scans all of the files to
  269. build a list of all textures used, which are then released.
  270. ===============
  271. */
  272. void Cmd_Maps (void)
  273. {
  274. char map[1024];
  275. int i;
  276. while (TokenAvailable ())
  277. {
  278. GetToken (false);
  279. sprintf (map, "maps/%s.bsp", token);
  280. ReleaseFile (map);
  281. if (!g_release)
  282. continue;
  283. // get all the texture references
  284. sprintf (map, "%smaps/%s.bsp", gamedir, token);
  285. LoadBSPFileTexinfo (map);
  286. for (i=0 ; i<numtexinfo ; i++)
  287. ReleaseTexture (texinfo[i].texture);
  288. }
  289. }
  290. //==============================================================
  291. /*
  292. ===============
  293. ParseScript
  294. ===============
  295. */
  296. void ParseScript (void)
  297. {
  298. while (1)
  299. {
  300. do
  301. { // look for a line starting with a $ command
  302. GetToken (true);
  303. if (endofscript)
  304. return;
  305. if (token[0] == '$')
  306. break;
  307. while (TokenAvailable())
  308. GetToken (false);
  309. } while (1);
  310. //
  311. // model commands
  312. //
  313. if (!strcmp (token, "$modelname"))
  314. Cmd_Modelname ();
  315. else if (!strcmp (token, "$base"))
  316. Cmd_Base ();
  317. else if (!strcmp (token, "$cd"))
  318. Cmd_Cd ();
  319. else if (!strcmp (token, "$origin"))
  320. Cmd_Origin ();
  321. else if (!strcmp (token, "$scale"))
  322. Cmd_ScaleUp ();
  323. else if (!strcmp (token, "$frame"))
  324. Cmd_Frame ();
  325. else if (!strcmp (token, "$skin"))
  326. Cmd_Skin ();
  327. else if (!strcmp (token, "$skinsize"))
  328. Cmd_Skinsize ();
  329. //
  330. // sprite commands
  331. //
  332. else if (!strcmp (token, "$spritename"))
  333. Cmd_SpriteName ();
  334. else if (!strcmp (token, "$load"))
  335. Cmd_Load ();
  336. else if (!strcmp (token, "$spriteframe"))
  337. Cmd_SpriteFrame ();
  338. //
  339. // image commands
  340. //
  341. else if (!strcmp (token, "$grab"))
  342. Cmd_Grab ();
  343. else if (!strcmp (token, "$raw"))
  344. Cmd_Raw ();
  345. else if (!strcmp (token, "$colormap"))
  346. Cmd_Colormap ();
  347. else if (!strcmp (token, "$mippal"))
  348. Cmd_Mippal ();
  349. else if (!strcmp (token, "$mipdir"))
  350. Cmd_Mipdir ();
  351. else if (!strcmp (token, "$mip"))
  352. Cmd_Mip ();
  353. else if (!strcmp (token, "$environment"))
  354. Cmd_Environment ();
  355. //
  356. // video
  357. //
  358. else if (!strcmp (token, "$video"))
  359. Cmd_Video ();
  360. //
  361. // misc
  362. //
  363. else if (!strcmp (token, "$file"))
  364. Cmd_File ();
  365. else if (!strcmp (token, "$dir"))
  366. Cmd_Dir ();
  367. else if (!strcmp (token, "$maps"))
  368. Cmd_Maps ();
  369. else if (!strcmp (token, "$alphalight"))
  370. Cmd_Alphalight ();
  371. else if (!strcmp (token, "$inverse16table" ))
  372. Cmd_Inverse16Table();
  373. else
  374. Error ("bad command %s\n", token);
  375. }
  376. }
  377. //=======================================================
  378. /*
  379. ==============
  380. main
  381. ==============
  382. */
  383. int main (int argc, char **argv)
  384. {
  385. static int i; // VC4.2 compiler bug if auto...
  386. char path[1024];
  387. ExpandWildcards (&argc, &argv);
  388. for (i=1 ; i<argc ; i++)
  389. {
  390. if (!strcmp(argv[i], "-archive"))
  391. {
  392. // -archive f:/quake2/release/dump_11_30
  393. archive = true;
  394. strcpy (archivedir, argv[i+1]);
  395. printf ("Archiving source to: %s\n", archivedir);
  396. i++;
  397. }
  398. else if (!strcmp(argv[i], "-release"))
  399. {
  400. g_release = true;
  401. strcpy (g_releasedir, argv[i+1]);
  402. printf ("Copy output to: %s\n", g_releasedir);
  403. i++;
  404. }
  405. else if (!strcmp(argv[i], "-compress"))
  406. {
  407. g_compress_pak = true;
  408. printf ("Compressing pakfile\n");
  409. }
  410. else if (!strcmp(argv[i], "-pak"))
  411. {
  412. g_release = true;
  413. g_pak = true;
  414. printf ("Building pakfile: %s\n", argv[i+1]);
  415. BeginPak (argv[i+1]);
  416. i++;
  417. }
  418. else if (!strcmp(argv[i], "-only"))
  419. {
  420. strcpy (g_only, argv[i+1]);
  421. printf ("Only grabbing %s\n", g_only);
  422. i++;
  423. }
  424. else if (!strcmp(argv[i], "-3ds"))
  425. {
  426. do3ds = true;
  427. printf ("loading .3ds files\n");
  428. }
  429. else if (argv[i][0] == '-')
  430. Error ("Unknown option \"%s\"", argv[i]);
  431. else
  432. break;
  433. }
  434. if (i >= argc)
  435. Error ("usage: qgrab [-archive <directory>] [-release <directory>] [-only <model>] [-3ds] file.qgr");
  436. if (do3ds)
  437. trifileext = ext_3ds;
  438. else
  439. trifileext = ext_tri;
  440. for ( ; i<argc ; i++)
  441. {
  442. printf ("--------------- %s ---------------\n", argv[i]);
  443. // load the script
  444. strcpy (path, argv[i]);
  445. DefaultExtension (path, ".qdt");
  446. SetQdirFromPath (path);
  447. LoadScriptFile (ExpandArg(path));
  448. //
  449. // parse it
  450. //
  451. ParseScript ();
  452. // write out the last model
  453. FinishModel ();
  454. FinishSprite ();
  455. }
  456. if (g_pak)
  457. FinishPak ();
  458. return 0;
  459. }