2 Copyright (C) 1998 BJ Eirich (aka vecna)
\r
3 This program is free software; you can redistribute it and/or
\r
4 modify it under the terms of the GNU General Public License
\r
5 as published by the Free Software Foundation; either version 2
\r
6 of the License, or (at your option) any later version.
\r
7 This program is distributed in the hope that it will be useful,
\r
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
\r
10 See the GNU General Public Lic
\r
11 See the GNU General Public License for more details.
\r
12 You should have received a copy of the GNU General Public License
\r
13 along with this program; if not, write to the Free Software
\r
14 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
\r
21 // ================================= Data ====================================
\r
25 FILE *fp; // real file pointer.
\r
26 byte s; // 0=real file 1=vfile;
\r
27 byte v; // if vfile, which vfile index
\r
28 byte i; // which file index in vfile is it?
\r
29 byte p; // data alignment pad. :)
\r
34 char fname[84]; // pathname thingo
\r
35 int size; // size of the file
\r
36 int packofs; // where the file can be found in PACK
\r
37 int curofs; // current file offset.
\r
38 char extractable; // irrelevant to runtime, but...
\r
39 char override; // should we override?
\r
44 char mountname[80]; // name of VRG packfile.
\r
45 FILE *vhandle; // Real file-handle of packfile.
\r
46 struct filestruct *files; // File record array.
\r
47 int numfiles; // number of files in pack.
\r
48 int curofs; // Current filepointer.
\r
51 struct mountstruct pack[3]; // packfile structs
\r
52 byte filesmounted=0; // Number of VRG files to check.
\r
53 char headertag[]={ 'V','R','G','P','A','C','K',0 };
\r
55 // ================================= Code ====================================
\r
57 int Exist(char *fname)
\r
60 tempf=fopen(fname,"rb");
\r
69 void DecryptHeader()
\r
70 { byte lastvalue, precodebyte, *ptr;
\r
72 ptr=(byte *) pack[filesmounted].files;
\r
76 while (ptr < (byte *) (int) pack[filesmounted].files + (int) pack[filesmounted].numfiles*100)
\r
80 lastvalue=precodebyte;
\r
85 void MountVFile(char *fname)
\r
88 if (!(pack[filesmounted].vhandle = fopen(fname,"rb")))
\r
90 printf("*error* Unable to mount %s; file not found. \n",fname);
\r
95 memset(&buffer, 0, 10);
\r
96 fread(&buffer, 1, 7, pack[filesmounted].vhandle);
\r
97 if (strcmp(buffer,headertag))
\r
99 printf("*error* %s is not a valid packfile. \n",fname);
\r
103 fread(&buffer, 1, 1, pack[filesmounted].vhandle);
\r
106 printf("*error* %s is an incompatible packfile version. (ver reported: %d) \n",fname,buffer[0]);
\r
110 fread(&pack[filesmounted].numfiles, 1, 4, pack[filesmounted].vhandle);
\r
111 memcpy(pack[filesmounted].mountname,fname,strlen(fname)+1);
\r
113 // Allocate memory for headers and read them in.
\r
115 pack[filesmounted].files = (struct filestruct *) valloc(pack[filesmounted].numfiles*100, "pack[filesmounted].files", OID_VFILE);
\r
116 fread(pack[filesmounted].files, pack[filesmounted].numfiles, 100, pack[filesmounted].vhandle);
\r
121 VFILE *vopen(char *fname)
\r
126 // All files using V* are read-only. To write a file, use regular i/o.
\r
127 // First we'll see if a real file exists, then we'll check for one in VFiles,
\r
128 // if we don't find one in VFile or it's overridable then a real file will
\r
129 // be used. That's the general logic progression.
\r
131 if (Exist(fname)) rf=1;
\r
133 // Search the VFiles.
\r
134 for (i=filesmounted-1; i>=0; i--)
\r
136 for (j=0; j<pack[i].numfiles; j++)
\r
137 if (!strcasecmp(fname,pack[i].files[j].fname)) { vf=1; break; }
\r
141 if (!vf && !rf) return 0;
\r
143 tmp=(VFILE *) valloc(sizeof(VFILE), "vopen:tmp", OID_VFILE);
\r
147 if (pack[i].files[j].override) vf=0;
\r
153 tmp->fp=pack[i].vhandle;
\r
157 pack[i].files[j].curofs=0;
\r
158 fseek(tmp->fp, pack[i].files[j].packofs, 0);
\r
159 pack[i].curofs=pack[i].files[j].packofs;
\r
163 tmp->fp=fopen(fname,"rb");
\r
164 tmp->s=0; tmp->v=0; tmp->i=0;
\r
168 void vread(char *dest, int len, VFILE *f)
\r
170 // This is fairly simple.. Just make sure our filepointer is at the right
\r
171 // place, then do a straight fread.
\r
175 if (pack[f->v].curofs != (pack[f->v].files[f->i].packofs + pack[f->v].files[f->i].curofs))
\r
176 fseek(f->fp, pack[f->v].files[f->i].curofs+pack[f->v].files[f->i].packofs, 0);
\r
177 pack[f->v].files[f->i].curofs+=len;
\r
178 pack[f->v].curofs+=len;
\r
180 fread(dest, 1, len, f->fp);
\r
183 void vclose(VFILE *f)
\r
186 if (!f->s) fclose(f->fp);
\r
191 int filesize(VFILE *f)
\r
195 // Filesize for Vfiles is real simple.
\r
196 if (f->s) return pack[f->v].files[f->i].size;
\r
198 // It's a bit more complex for external files.
\r
199 oldpos=ftell(f->fp);
\r
200 fseek(f->fp, 0, 2);
\r
202 fseek(f->fp, oldpos, 0);
\r
206 int vtell(VFILE *f)
\r
210 return ftell(f->fp);
\r
213 return pack[f->v].files[f->i].curofs;
\r
216 void vseek(VFILE *f, int offset, int origin)
\r
220 fseek(f->fp, offset, origin);
\r
226 case 0: pack[f->v].files[f->i].curofs=offset;
\r
227 fseek(f->fp, offset+pack[f->v].files[f->i].packofs, 0);
\r
229 case 1: pack[f->v].files[f->i].curofs+=offset;
\r
230 fseek(f->fp, offset, 1);
\r
232 case 2: pack[f->v].files[f->i].curofs=pack[f->v].files[f->i].size-offset;
\r
233 fseek(f->fp, pack[f->v].files[f->i].curofs+pack[f->v].files[f->i].packofs, 0);
\r
238 void _vscanf(VFILE *f, char *format, char *dest)
\r
240 fscanf(f->fp, format, dest);
\r
242 pack[f->v].files[f->i].curofs=ftell(f->fp)-pack[f->v].files[f->i].packofs;
\r
245 char vgetc(VFILE *f)
\r
252 word vgetw(VFILE *f)
\r
255 vread((char *) &c, 2, f);
\r
259 void vgets(char *str, int len, VFILE *f)
\r
263 if (pack[f->v].curofs != (pack[f->v].files[f->i].packofs + pack[f->v].files[f->i].curofs))
\r
264 fseek(f->fp, pack[f->v].files[f->i].curofs+pack[f->v].files[f->i].packofs, 0);
\r
265 pack[f->v].files[f->i].curofs+=len;
\r
266 pack[f->v].curofs+=len;
\r
268 fgets(str, len, f->fp);
\r