7 typedef struct KvidFileType
\r
10 unsigned char AtEOF;
\r
11 struct KvidFileType *Parent;
\r
12 unsigned char DataFile;
\r
13 unsigned char ReSeek;
\r
14 unsigned char CanWrite;
\r
15 unsigned long CurFAT;
\r
16 unsigned long CurAU;
\r
17 unsigned short Offset;
\r
18 unsigned short AUSize;
\r
19 unsigned char LastOp;
\r
20 unsigned char CurBit, CurChar;
\r
25 static unsigned long GetFAT(KvidFile *FileStr, unsigned long AU)
\r
27 unsigned long CurFAT, i, TargetFAT;
\r
30 TargetFAT = AU / ((FileStr->AUSize >> 2) - 1);
\r
31 for(i = 0; i < TargetFAT; i++)
\r
33 fseek(FileStr->FilePtr, DAT_START + (CurFAT * FileStr->AUSize), SEEK_SET);
\r
34 fread((void *)&CurFAT, 4, 1, FileStr->FilePtr);
\r
39 static void SetFATEntry(KvidFile *FileStr, unsigned long AU, unsigned long Entry)
\r
41 unsigned long CurFAT, i, TargetFAT;
\r
44 TargetFAT = AU / ((FileStr->AUSize >> 2) - 1);
\r
45 for(i = 0; i < TargetFAT; i++)
\r
47 fseek(FileStr->FilePtr, DAT_START + (CurFAT * FileStr->AUSize), SEEK_SET);
\r
48 fread((void *)&CurFAT, 4, 1, FileStr->FilePtr);
\r
49 if(CurFAT >= 0x80000000)
\r
52 fseek(FileStr->FilePtr, DAT_START + (CurFAT * FileStr->AUSize) + (((AU % ((FileStr->AUSize >> 2) - 1)) + 1) << 2), SEEK_SET);
\r
53 fwrite((void *)&Entry, 4, 1, FileStr->FilePtr);
\r
56 static unsigned long FindFreeAU(KvidFile *FileStr, unsigned char InhibitCreation)
\r
58 unsigned long OldFAT, CurFAT, NumEntries, Entry, i, FATNum;
\r
62 NumEntries = (FileStr->AUSize >> 2) - 1;
\r
63 while(CurFAT < 0x80000000)
\r
66 fseek(FileStr->FilePtr, DAT_START + (CurFAT * FileStr->AUSize), SEEK_SET);
\r
67 fread((void *)&CurFAT, 4, 1, FileStr->FilePtr);
\r
68 for(i = 0; i < NumEntries; i++)
\r
70 fread((void *)&Entry, 4, 1, FileStr->FilePtr);
\r
72 return((FATNum * NumEntries) + i);
\r
76 if(InhibitCreation == 1)
\r
78 fseek(FileStr->FilePtr, DAT_START + (OldFAT * FileStr->AUSize), SEEK_SET);
\r
79 CurFAT = NumEntries * FATNum;
\r
80 fwrite((void *)&CurFAT, 4, 1, FileStr->FilePtr);
\r
81 fseek(FileStr->FilePtr, DAT_START + (CurFAT * FileStr->AUSize), SEEK_SET);
\r
83 fwrite((void *)&Entry, 4, 1, FileStr->FilePtr);
\r
85 for(i = 0; i < NumEntries; i++)
\r
87 fwrite((void *)&Entry, 4, 1, FileStr->FilePtr);
\r
89 SetFATEntry(FileStr, CurFAT, 0xFFFFFFFE);
\r
90 return(FindFreeAU(FileStr, 1));
\r
93 static unsigned char GetDatChar(KvidFile *FileStr)
\r
95 unsigned char RetVal;
\r
96 unsigned short OldAU;
\r
97 unsigned short NumEntries;
\r
100 for(CurFile = FileStr->Parent; CurFile != NULL; CurFile = CurFile->Parent)
\r
101 CurFile->ReSeek = 1;
\r
102 if(FileStr->ReSeek == 1)
\r
104 fseek(FileStr->FilePtr, DAT_START + (FileStr->CurAU * FileStr->AUSize) + FileStr->Offset, SEEK_SET);
\r
105 FileStr->ReSeek = 0;
\r
106 FileStr->CurFAT = 0xFFFFFFFF;
\r
108 RetVal = (unsigned char)fgetc(FileStr->FilePtr);
\r
109 if(FileStr->Offset++ == FileStr->AUSize - 1)
\r
111 if(FileStr->CurFAT == 0xFFFFFFFF)
\r
112 FileStr->CurFAT = GetFAT(FileStr, FileStr->CurAU);
\r
113 OldAU = FileStr->CurAU;
\r
114 fseek(FileStr->FilePtr, DAT_START + (FileStr->CurFAT * FileStr->AUSize) + (((FileStr->CurAU % ((FileStr->AUSize >> 2) - 1)) + 1) << 2), SEEK_SET);
\r
115 fread((void *)&FileStr->CurAU, 4, 1, FileStr->FilePtr);
\r
116 if(FileStr->CurAU == 0xFFFFFFFF)
\r
117 FileStr->AtEOF = 1;
\r
118 FileStr->Offset = 0;
\r
119 NumEntries = (FileStr->AUSize >> 2) - 1;
\r
120 if((FileStr->CurAU / NumEntries) == (OldAU / NumEntries))
\r
122 fseek(FileStr->FilePtr, DAT_START + (FileStr->CurAU * FileStr->AUSize) + FileStr->Offset, SEEK_SET);
\r
124 FileStr->ReSeek = 1;
\r
130 static void PutDatChar(unsigned char c, KvidFile *FileStr)
\r
132 unsigned char RetVal;
\r
133 unsigned long OldAU;
\r
136 for(CurFile = FileStr->Parent; CurFile != NULL; CurFile = CurFile->Parent)
\r
137 CurFile->ReSeek = 1;
\r
138 if(FileStr->ReSeek == 1)
\r
140 fseek(FileStr->FilePtr, DAT_START + (FileStr->CurAU * FileStr->AUSize) + FileStr->Offset, SEEK_SET);
\r
141 FileStr->ReSeek = 0;
\r
142 FileStr->CurFAT = 0xFFFFFFFF;
\r
144 fputc(c, FileStr->FilePtr);
\r
145 if(FileStr->Offset++ == FileStr->AUSize - 1)
\r
147 if(FileStr->CurFAT == 0xFFFFFFFF)
\r
148 FileStr->CurFAT = GetFAT(FileStr, FileStr->CurAU);
\r
149 fseek(FileStr->FilePtr, DAT_START + (FileStr->CurFAT * FileStr->AUSize) + (((FileStr->CurAU % ((FileStr->AUSize >> 2) - 1)) + 1) << 2), SEEK_SET);
\r
150 OldAU = FileStr->CurAU;
\r
151 fread((void *)&FileStr->CurAU, 4, 1, FileStr->FilePtr);
\r
152 if(FileStr->CurAU == 0xFFFFFFFF)
\r
154 FileStr->CurAU = FindFreeAU(FileStr, 0);
\r
155 SetFATEntry(FileStr, OldAU, FileStr->CurAU);
\r
156 SetFATEntry(FileStr, FileStr->CurAU, 0xFFFFFFFF);
\r
158 FileStr->Offset = 0;
\r
159 FileStr->ReSeek = 1;
\r
163 unsigned char FileGetChar(KvidFile *FileStr)
\r
165 signed long RetVal;
\r
167 if(FileStr->AtEOF == 1)
\r
169 if(FileStr->LastOp == 1)
\r
171 FileStr->LastOp = 0;
\r
172 fflush(FileStr->FilePtr);
\r
174 if(FileStr->Parent != NULL)
\r
175 return(GetDatChar(FileStr));
\r
176 if((FileStr->Parent == NULL) && (FileStr->DataFile == 0))
\r
178 if((RetVal = (signed long)fgetc(FileStr->FilePtr)) == EOF)
\r
180 FileStr->AtEOF = 1;
\r
183 return((unsigned char)RetVal);
\r
186 if((FileStr->Parent == NULL) && (FileStr->DataFile == 1))
\r
187 return(GetDatChar(FileStr));
\r
190 void FilePutChar(unsigned char c, KvidFile *FileStr)
\r
192 if(FileStr->CanWrite == 0)
\r
194 FileStr->LastOp = 1;
\r
195 if(FileStr->Parent != NULL)
\r
196 PutDatChar(c, FileStr);
\r
197 if((FileStr->Parent == NULL) && (FileStr->DataFile == 0))
\r
198 fputc(c, FileStr->FilePtr);
\r
199 if((FileStr->Parent == NULL) && (FileStr->DataFile == 1))
\r
200 PutDatChar(c, FileStr);
\r
203 void FileSkip(KvidFile *FileStr, unsigned long NumBytes)
\r
207 if(FileStr->AtEOF == 1)
\r
209 if((FileStr->Parent == NULL) && (FileStr->DataFile == 0))
\r
211 fseek(FileStr->FilePtr, NumBytes, SEEK_CUR);
\r
214 for(CurFile = FileStr->Parent; CurFile != NULL; CurFile = CurFile->Parent)
\r
215 CurFile->ReSeek = 1;
\r
216 if(FileStr->ReSeek == 1)
\r
217 FileStr->CurFAT = 0xFFFFFFFF;
\r
218 while((NumBytes > 0) && (FileStr->AtEOF == 0))
\r
220 if(NumBytes < FileStr->AUSize - FileStr->Offset)
\r
222 if(FileStr->ReSeek == 0)
\r
223 fseek(FileStr->FilePtr, NumBytes, SEEK_CUR);
\r
224 FileStr->Offset += NumBytes;
\r
227 NumBytes -= FileStr->AUSize - FileStr->Offset;
\r
228 if(FileStr->CurFAT == 0xFFFFFFFF)
\r
229 FileStr->CurFAT = GetFAT(FileStr, FileStr->CurAU);
\r
230 fseek(FileStr->FilePtr, DAT_START + (FileStr->CurFAT * FileStr->AUSize) + (((FileStr->CurAU % ((FileStr->AUSize >> 2) - 1)) + 1) << 2), SEEK_SET);
\r
231 fread((void *)&FileStr->CurAU, 4, 1, FileStr->FilePtr);
\r
232 if(FileStr->CurAU == 0xFFFFFFFF)
\r
233 FileStr->AtEOF = 1;
\r
234 FileStr->Offset = 0;
\r
235 FileStr->ReSeek = 1;
\r
238 if(FileStr->ReSeek == 1)
\r
240 fseek(FileStr->FilePtr, DAT_START + (FileStr->CurAU * FileStr->AUSize) + FileStr->Offset, SEEK_SET);
\r
241 FileStr->ReSeek = 0;
\r
242 FileStr->CurFAT = 0xFFFFFFFF;
\r
246 unsigned long FileReadBits(unsigned char NumBits, KvidFile *FileStr)
\r
249 unsigned long Value;
\r
252 for(i = NumBits; i > 0; i--)
\r
254 if(FileStr->CurBit > 7)
\r
256 FileStr->CurChar = fgetc(FileStr->FilePtr);
\r
257 FileStr->CurBit = 7;
\r
259 if((FileStr->CurChar & (1 << FileStr->CurBit)) != 0)
\r
260 Value += 1 << (i - 1);
\r
266 void FileRead(void *Buffer, unsigned long NumBytes, KvidFile *FileStr)
\r
268 if((FileStr->Parent == NULL) && (FileStr->DataFile == 0))
\r
270 fread(Buffer, NumBytes, 1, FileStr->FilePtr);
\r
273 while(NumBytes-- > 0)
\r
274 *(unsigned char *)Buffer++ = FileGetChar(FileStr);
\r
277 void FileWrite(void *Buffer, unsigned long NumBytes, KvidFile *FileStr)
\r
279 if(FileStr->CanWrite == 0)
\r
281 if((FileStr->Parent == NULL) && (FileStr->DataFile == 0))
\r
283 fwrite(Buffer, NumBytes, 1, FileStr->FilePtr);
\r
286 while(NumBytes-- > 0)
\r
287 FilePutChar(*(unsigned char *)Buffer++, FileStr);
\r
290 void FileClose(KvidFile *FileStr)
\r
292 if(FileStr->Parent == NULL)
\r
293 fclose(FileStr->FilePtr);
\r
296 unsigned char OpenRootDir(KvidFile *FileStr, KvidFile *ParentFile)
\r
298 if(ParentFile->DataFile == 0)
\r
300 FileStr->DataFile = 0;
\r
301 FileStr->CanWrite = ParentFile->CanWrite;
\r
302 FileStr->Parent = ParentFile;
\r
303 FileStr->FilePtr = ParentFile->FilePtr;
\r
304 FileStr->AtEOF = 0;
\r
305 FileStr->LastOp = 0;
\r
306 FileStr->ReSeek = 1;
\r
307 FileStr->CurAU = 1;
\r
308 FileStr->Offset = 0;
\r
309 FileStr->AUSize = ParentFile->AUSize;
\r
310 FileStr->CurBit = 255;
\r
314 unsigned char OpenNestedFile(unsigned char *FileName, KvidFile *FileStr, KvidFile *ParentFile, unsigned long *TimeBuffer)
\r
316 unsigned char FileNameBuffer[20];
\r
319 if(OpenRootDir(&RootDir, ParentFile) == 0)
\r
321 FileStr->DataFile = 0;
\r
322 FileStr->CanWrite = ParentFile->CanWrite;
\r
323 FileStr->Parent = ParentFile;
\r
324 FileStr->FilePtr = ParentFile->FilePtr;
\r
325 FileStr->AtEOF = 0;
\r
326 FileStr->LastOp = 0;
\r
327 FileStr->ReSeek = 1;
\r
328 FileStr->Offset = 0;
\r
329 FileStr->AUSize = ParentFile->AUSize;
\r
330 FileStr->CurBit = 255;
\r
333 FileRead((void *)FileNameBuffer, 20, &RootDir);
\r
334 if((FileNameBuffer[0] == 0) || (RootDir.AtEOF == 1))
\r
336 if(strcmp(FileNameBuffer, FileName) == 0)
\r
338 FileRead((void *)FileNameBuffer, 4, &RootDir);
\r
339 FileNameBuffer[4] = 0;
\r
340 if(TimeBuffer == NULL)
\r
341 FileSkip(&RootDir, 4);
\r
343 FileRead((void *)TimeBuffer, 4, &RootDir);
\r
344 FileRead((void *)&FileStr->CurAU, 4, &RootDir);
\r
345 if(strcmp(FileNameBuffer, "SDIR") == 0)
\r
347 FileRead((void *)FileNameBuffer, 5, FileStr);
\r
348 FileNameBuffer[5] = 0;
\r
349 if(strcmp(FileNameBuffer, "KFDAT") != 0)
\r
351 FileRead((void *)&FileStr->AUSize, 2, FileStr);
\r
352 FileStr->DataFile = 1;
\r
356 FileSkip(&RootDir, 12);
\r
361 unsigned char OpenFile(unsigned char *FileName, KvidFile *FileStr)
\r
363 FileStr->DataFile = 0;
\r
364 FileStr->Parent = NULL;
\r
365 FileStr->AtEOF = 0;
\r
366 FileStr->LastOp = 0;
\r
367 FileStr->CurBit = 255;
\r
368 if((FileStr->FilePtr = fopen(FileName, "rb+")) == NULL)
\r
370 if((FileStr->FilePtr = fopen(FileName, "rb")) == NULL)
\r
371 return((MainDat == NULL)?0:OpenNestedFile(FileName, FileStr, MainDat, NULL));
\r
373 FileStr->CanWrite = 0;
\r
375 FileStr->CanWrite = 1;
\r
380 unsigned char DeleteFile(unsigned char *FileName, KvidFile *ParentFile)
\r
382 unsigned char FileNameBuffer[20];
\r
383 unsigned short OldOffset;
\r
384 unsigned long OldAU, CurAU, CurFAT;
\r
387 if(OpenRootDir(&RootDir, ParentFile) == 0)
\r
391 OldOffset = RootDir.Offset;
\r
392 OldAU = RootDir.CurAU;
\r
393 FileRead((void *)FileNameBuffer, 20, &RootDir);
\r
394 if((FileNameBuffer[0] == 0) || (RootDir.AtEOF == 1))
\r
396 if(strcmp(FileNameBuffer, FileName) == 0)
\r
398 FileSkip(&RootDir, 8);
\r
399 FileRead(&CurAU, 4, &RootDir);
\r
400 RootDir.Offset = OldOffset;
\r
401 RootDir.CurAU = OldAU;
\r
402 RootDir.ReSeek = 1;
\r
403 FilePutChar(1, &RootDir);
\r
404 while(CurAU < 0x80000000)
\r
406 CurFAT = GetFAT(&RootDir, CurAU);
\r
407 fseek(RootDir.FilePtr, DAT_START + (CurFAT * RootDir.AUSize) + ((CurAU % ((RootDir.AUSize >> 2) - 1)) << 2) + 4, SEEK_SET);
\r
409 fread((void *)&CurAU, 4, 1, RootDir.FilePtr);
\r
410 fseek(RootDir.FilePtr, DAT_START + (CurFAT * RootDir.AUSize) + ((OldAU % ((RootDir.AUSize >> 2) - 1)) << 2) + 4, SEEK_SET);
\r
412 fwrite((void *)&CurFAT, 4, 1, RootDir.FilePtr);
\r
416 FileSkip(&RootDir, 12);
\r
421 unsigned char CreateFile(unsigned char *FileName, KvidFile *FileStr, KvidFile *ParentFile, unsigned long FileType)
\r
424 unsigned char FileNameBuffer[20];
\r
425 unsigned char Existing;
\r
426 unsigned long OldAU;
\r
427 unsigned short OldOffset;
\r
429 unsigned long CurTime;
\r
430 unsigned long NewAU;
\r
432 if(ParentFile == NULL)
\r
434 FileStr->DataFile = 0;
\r
435 FileStr->Parent = NULL;
\r
436 FileStr->AtEOF = 1;
\r
437 FileStr->LastOp = 0;
\r
438 FileStr->CanWrite = 1;
\r
439 if((FileStr->FilePtr = fopen(FileName, "wb+")) == NULL)
\r
444 if((OpenRootDir(&RootDir, ParentFile) == 0) || (RootDir.CanWrite == 0))
\r
446 FileStr->DataFile = 0;
\r
447 FileStr->CanWrite = ParentFile->CanWrite;
\r
448 FileStr->Parent = ParentFile;
\r
449 FileStr->FilePtr = ParentFile->FilePtr;
\r
450 FileStr->AtEOF = 0;
\r
451 FileStr->LastOp = 0;
\r
452 FileStr->ReSeek = 1;
\r
453 FileStr->Offset = 0;
\r
454 FileStr->AUSize = ParentFile->AUSize;
\r
455 FileStr->CurBit = 255;
\r
458 OldAU = RootDir.CurAU;
\r
459 OldOffset = RootDir.Offset;
\r
460 FileRead((void *)FileNameBuffer, 20, &RootDir);
\r
461 if(((Existing = FileNameBuffer[0]) < 2) || (RootDir.AtEOF == 1))
\r
463 RootDir.CurAU = OldAU;
\r
464 RootDir.Offset = OldOffset;
\r
465 RootDir.ReSeek = 1;
\r
466 for(i = 0; FileName[i] != 0; i++)
\r
467 FileNameBuffer[i] = FileName[i];
\r
469 FileNameBuffer[i++] = 0;
\r
470 FileWrite((void *)FileNameBuffer, 20, &RootDir);
\r
471 FileWrite((void *)&FileType, 4, &RootDir);
\r
472 CurTime = (unsigned long)time(NULL);
\r
473 FileWrite((void *)&CurTime, 4, &RootDir);
\r
474 NewAU = FindFreeAU(ParentFile, 0);
\r
475 SetFATEntry(ParentFile, NewAU, 0xFFFFFFFF);
\r
476 RootDir.ReSeek = 1;
\r
477 FileWrite((void *)&NewAU, 4, &RootDir);
\r
479 for(i = 0; i < 32; i++)
\r
480 FilePutChar(0, &RootDir);
\r
481 FileStr->CurAU = NewAU;
\r
484 FileSkip(&RootDir, 12);
\r
488 unsigned char OpenDatFile(unsigned char *FileName, KvidFile *FileStr)
\r
490 unsigned char Signature[6];
\r
491 FileStr->DataFile = 1;
\r
492 FileStr->Parent = NULL;
\r
493 FileStr->ReSeek = 0;
\r
494 FileStr->AtEOF = 0;
\r
495 FileStr->LastOp = 0;
\r
496 FileStr->CurBit = 255;
\r
497 if((FileStr->FilePtr = fopen(FileName, "rb+")) == NULL)
\r
499 if((FileStr->FilePtr = fopen(FileName, "rb")) == NULL)
\r
502 FileStr->CanWrite = 0;
\r
504 FileStr->CanWrite = 1;
\r
506 fread((void *)Signature, 1, 5, FileStr->FilePtr);
\r
508 if(strcmp(Signature, "KFDAT") != 0)
\r
510 fclose(FileStr->FilePtr);
\r
513 fread((void *)&FileStr->AUSize, 2, 1, FileStr->FilePtr);
\r
514 if((FileStr->AUSize % 4) != 0)
\r
516 fclose(FileStr->FilePtr);
\r
519 FileStr->CurFAT = 0;
\r
520 FileStr->CurAU = 0;
\r
521 FileStr->Offset = 0;
\r