/* Copyright (C) 1999-2006 Id Software, Inc. and contributors. For a list of contributors, see the accompanying CONTRIBUTORS file. This file is part of GtkRadiant. GtkRadiant is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GtkRadiant is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GtkRadiant; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "qdata.h" #include "inout.h" qboolean g_compress_pak; qboolean g_release; // don't grab, copy output data to new tree qboolean g_pak; // if true, copy to pak instead of release char g_releasedir[1024]; // c:\quake2\baseq2, etc qboolean g_archive; // don't grab, copy source data to new tree qboolean do3ds; char g_only[256]; // if set, only grab this cd qboolean g_skipmodel; // set true when a cd is not g_only char *ext_3ds = "3ds"; char *ext_tri= "tri"; char *trifileext; char game[64] = "quake2"; void InitPaths( int *argc, char **argv ); /* ======================================================= PAK FILES ======================================================= */ unsigned Com_BlockChecksum (void *buffer, int length); typedef struct { char name[56]; int filepos, filelen; } packfile_t; typedef struct { char id[4]; int dirofs; int dirlen; } packheader_t; packfile_t pfiles[16384]; FILE *pakfile; packfile_t *pf; packheader_t pakheader; /* ============== BeginPak ============== */ void BeginPak (char *outname) { if (!g_pak) return; pakfile = SafeOpenWrite (outname); // leave space for header SafeWrite (pakfile, &pakheader, sizeof(pakheader)); pf = pfiles; } /* ============== ReleaseFile Filename should be gamedir reletive. Either copies the file to the release dir, or adds it to the pak file. ============== */ void ReleaseFile (char *filename) { int len; byte *buf; char source[1024]; char dest[1024]; if (!g_release) return; sprintf (source, "%s%s", gamedir, filename); if (!g_pak) { // copy it sprintf (dest, "%s/%s", g_releasedir, filename); printf ("copying to %s\n", dest); QCopyFile (source, dest); return; } // pak it printf ("paking %s\n", filename); if (strlen(filename) >= sizeof(pf->name)) Error ("Filename too long for pak: %s", filename); len = LoadFile (source, (void **)&buf); if (g_compress_pak && len < 4096*1024 ) { cblock_t in, out; cblock_t Huffman (cblock_t in); in.count = len; in.data = buf; out = Huffman (in); if (out.count < in.count) { printf (" compressed from %i to %i\n", in.count, out.count); free (in.data); buf = out.data; len = out.count; } else free (out.data); } strcpy (pf->name, filename); pf->filepos = LittleLong(ftell(pakfile)); pf->filelen = LittleLong(len); pf++; SafeWrite (pakfile, buf, len); free (buf); } /* ============== FinishPak ============== */ void FinishPak (void) { int dirlen; int d; int i; unsigned checksum; if (!g_pak) return; pakheader.id[0] = 'P'; pakheader.id[1] = 'A'; pakheader.id[2] = 'C'; pakheader.id[3] = 'K'; dirlen = (byte *)pf - (byte *)pfiles; pakheader.dirofs = LittleLong(ftell(pakfile)); pakheader.dirlen = LittleLong(dirlen); checksum = Com_BlockChecksum ( (void *)pfiles, dirlen ); SafeWrite (pakfile, pfiles, dirlen); i = ftell (pakfile); fseek (pakfile, 0, SEEK_SET); SafeWrite (pakfile, &pakheader, sizeof(pakheader)); fclose (pakfile); d = pf - pfiles; printf ("%i files packed in %i bytes\n",d, i); printf ("checksum: 0x%x\n", checksum); } /* =============== Cmd_File This is only used to cause a file to be copied during a release build (default.cfg, maps, etc) =============== */ void Cmd_File (void) { GetToken (false); ReleaseFile (token); } /* =============== PackDirectory_r =============== */ #ifdef _WIN32 #include "io.h" void PackDirectory_r (char *dir) { struct _finddata_t fileinfo; int handle; char dirstring[1024]; char filename[1024]; sprintf (dirstring, "%s%s/*.*", gamedir, dir); handle = _findfirst (dirstring, &fileinfo); if (handle == -1) return; do { sprintf (filename, "%s/%s", dir, fileinfo.name); if (fileinfo.attrib & _A_SUBDIR) { // directory if (fileinfo.name[0] != '.') // don't pak . and .. PackDirectory_r (filename); continue; } // copy or pack the file ReleaseFile (filename); } while (_findnext( handle, &fileinfo ) != -1); _findclose (handle); } #else #include #include void PackDirectory_r (char *dir) { #ifdef NeXT struct direct **namelist, *ent; #else struct dirent **namelist, *ent; #endif int count; struct stat st; int i; int len; char fullname[1024]; char dirstring[1024]; char *name; sprintf (dirstring, "%s%s", gamedir, dir); count = scandir(dirstring, &namelist, NULL, NULL); for (i=0 ; id_name; if (name[0] == '.') continue; sprintf (fullname, "%s/%s", dir, name); sprintf (dirstring, "%s%s/%s", gamedir, dir, name); if (stat (dirstring, &st) == -1) Error ("fstating %s", pf->name); if (st.st_mode & S_IFDIR) { // directory PackDirectory_r (fullname); continue; } // copy or pack the file ReleaseFile (fullname); } } #endif /* =============== Cmd_Dir This is only used to cause a directory to be copied during a release build (sounds, etc) =============== */ void Cmd_Dir (void) { GetToken (false); PackDirectory_r (token); } //======================================================================== #define MAX_RTEX 16384 int numrtex; char rtex[MAX_RTEX][64]; void ReleaseTexture (char *name) { int i; char path[1024]; for (i=0 ; i= argc) Error ("usage: %s [-archive ] [-release ] [-only ] [-3ds] file.qgr", argv[ 0 ] ); if (do3ds) trifileext = ext_3ds; else trifileext = ext_tri; for ( ; i