1
/************************************************************************************
3
AstroMenace (Hardcore 3D space shooter with spaceship upgrade possibilities)
4
Copyright © 2006-2012 Michael Kurinnoy, Viewizard
7
AstroMenace is free software: you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation, either version 3 of the License, or
10
(at your option) any later version.
12
AstroMenace is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with AstroMenace. If not, see <http://www.gnu.org/licenses/>.
21
Web Site: http://www.viewizard.com/
22
Project: http://sourceforge.net/projects/openastromenace/
23
E-mail: viewizard@viewizard.com
25
*************************************************************************************/
29
#include "../Math/Math.h"
32
// Список подключенных VFS файлов
35
char *FileName; // Имя файла VFS
36
SDL_RWops *File; // Указатель на файл виртуальной системы
38
// данные для записи в создаваемую VFS
42
int DataStartOffsetVFS;
55
// Список файлов, доступных в подключенных (открытых) VFS
58
BOOL Link; // флаг что это не реальная запись а линк на существующую в VFS
59
DWORD NameLen; // Кол-во байт в имени...
60
char *Name; // Имя записи (имя файла) (может быть "линком")
61
int Offset; // Смещение начала файла относительно начала файловой системы
62
int Length; // Длина файла в системе
63
int RealLength; // Длина файла после распаковки
65
BYTE ArhKeyLen; // Кол-во байт ключа упаковки
66
char *ArhKey; // Ключ-упаковки
72
eVFS_Entry *StarVFSArray = 0;
73
eVFS_Entry *EndVFSArray = 0;
79
// Список файлов (открытых)
80
eFILE *StartFileVFS = 0; // Указатель на первый файл в списке...
81
eFILE *EndFileVFS = 0; // Указатель на последний файл в списке...
84
// чтобы при работе не было сбоев в последовательности файлов... блокируем этот участок
85
// при создании и закрытии файлов
86
bool fileIObusy = false;
87
// при чтении из файла вфс
88
bool VFSfileIObusy = false;
94
//------------------------------------------------------------------------------------
96
//------------------------------------------------------------------------------------
97
int CheckCompression(int tmpLength, const BYTE *buffer, char *ArhKeyVFS)
100
tmp = new BYTE[tmpLength];
101
memcpy(tmp, buffer, tmpLength);
103
// устанавливаем данные
106
srcVFS = new BYTE[tmpLength];
107
memcpy(srcVFS, buffer, tmpLength);
109
int dsizeVFS = tmpLength;
110
int ssizeVFS = tmpLength;
114
// цикл по кол-ву примененных методов сжатия в ArhKeyVFS
115
for (unsigned int i=0; i<strlen(ArhKeyVFS);i++)
117
// находим, какой текущий метод сжатия
118
char S = ArhKeyVFS[strlen(ArhKeyVFS)-i-1];
121
if (S == VFS_DATA_ARH_RLE)
123
vw_DATAtoRLE(&dstVFS, srcVFS, &dsizeVFS, ssizeVFS);
124
delete [] srcVFS; srcVFS = 0;
130
if (S == VFS_DATA_ARH_HAFF)
132
vw_DATAtoHAFF(&dstVFS, srcVFS, &dsizeVFS, ssizeVFS);
133
delete [] srcVFS; srcVFS = 0;
140
delete [] srcVFS; srcVFS = 0;
151
//------------------------------------------------------------------------------------
153
//------------------------------------------------------------------------------------
154
int vw_CreateVFS(const char *Name, unsigned int BuildNumber)
156
// Начальная подготовка структуры списка...
158
TempVFS = new eVFS; if (TempVFS == 0) return -1;
160
TempVFS->NumberOfFilesVFS = 0;
161
TempVFS->HeaderLengthVFS = 0;
162
TempVFS->HeaderOffsetVFS = 0;
163
TempVFS->DataStartOffsetVFS = 0;
166
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
167
// открываем файл VFS
168
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
170
TempVFS->File = SDL_RWFromFile(Name, "wb");
171
if (TempVFS->File == NULL)
173
fprintf(stderr, "Can't open VFS file for write %s\n", Name);
178
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
179
// выделяем память для имени
180
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
181
TempVFS->FileName = 0;
182
TempVFS->FileName = new char[strlen(Name)+1]; if (TempVFS->FileName == 0) return -1;
183
strcpy(TempVFS->FileName, Name);
186
// первый в списке...
194
else // продолжаем заполнение...
196
TempVFS->Prev = EndVFS;
198
EndVFS->Next = TempVFS;
204
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
205
// пишем VFS_ (4б) + версию (4б) + номер билда (4б)
206
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
207
char tmp1[5] = "VFS_";
208
SDL_RWwrite(TempVFS->File, tmp1, 4, 1);
209
SDL_RWwrite(TempVFS->File, VFS_VER, 4, 1);
210
SDL_RWwrite(TempVFS->File, &BuildNumber, 4, 1);
215
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
216
// пишем смещение начала таблицы
217
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
218
TempVFS->HeaderOffsetVFS = 4+4+4+4+4;//VFS_ ver build offset lenght
219
TempVFS->DataStartOffsetVFS = 4+4+4; //VFS_ ver build
221
SDL_RWwrite(TempVFS->File, &TempVFS->HeaderOffsetVFS, 4, 1);
222
SDL_RWwrite(TempVFS->File, &TempVFS->HeaderLengthVFS, 4, 1);
224
printf("VFS file was created %s\n", Name);
231
//------------------------------------------------------------------------------------
232
// запись данных в VFS
233
//------------------------------------------------------------------------------------
234
int vw_WriteIntoVFSfromMemory(const char *Name, const BYTE * buffer, int size)
237
// (!) пока работаем только с одной открытой VFS в системе, собственно больше и не нужно
239
eVFS *WritebleVFS = StartVFS;
241
if (WritebleVFS == 0)
243
fprintf(stderr, "Can't find VFS opened for write\n");
249
// Начальная подготовка структуры списка для новых данных
250
eVFS_Entry *NewVFS_Entry = 0;
251
NewVFS_Entry = new eVFS_Entry; if (NewVFS_Entry == 0) return -1;
253
// первый в списке...
254
if (EndVFSArray == 0)
256
NewVFS_Entry->Prev = 0;
257
NewVFS_Entry->Next = 0;
258
StarVFSArray = NewVFS_Entry;
259
EndVFSArray = NewVFS_Entry;
261
else // продолжаем заполнение...
263
NewVFS_Entry->Prev = EndVFSArray;
264
NewVFS_Entry->Next = 0;
265
EndVFSArray->Next = NewVFS_Entry;
266
EndVFSArray = NewVFS_Entry;
269
NewVFS_Entry->Parent = WritebleVFS;
271
NewVFS_Entry->ArhKeyLen = 0;
272
NewVFS_Entry->ArhKey = 0;
273
NewVFS_Entry->NameLen = (DWORD)strlen(Name);
275
NewVFS_Entry->Name = 0;
276
NewVFS_Entry->Name = new char[NewVFS_Entry->NameLen+1];
277
strcpy(NewVFS_Entry->Name, Name);
279
NewVFS_Entry->Link = false;
280
NewVFS_Entry->Offset = WritebleVFS->HeaderOffsetVFS; // т.к. это будет последний файл в структуре...
281
NewVFS_Entry->Length = size;
282
NewVFS_Entry->RealLength = size;
291
// надо составлять свою ArhKeyVFS
297
int BestSize = NewVFS_Entry->Length;
302
NewVFS_Entry->ArhKey = new char[1+1];
303
NewVFS_Entry->ArhKey[0] = '1';
304
NewVFS_Entry->ArhKey[1] = 0;
305
TmpSize = CheckCompression(NewVFS_Entry->Length, buffer, NewVFS_Entry->ArhKey);
306
if (TmpSize<BestSize)
313
if (NewVFS_Entry->ArhKey != 0){delete [] NewVFS_Entry->ArhKey; NewVFS_Entry->ArhKey = 0;}
314
NewVFS_Entry->ArhKey = new char[1+1];
315
NewVFS_Entry->ArhKey[0] = '2';
316
NewVFS_Entry->ArhKey[1] = 0;
317
TmpSize = CheckCompression(NewVFS_Entry->Length, buffer, NewVFS_Entry->ArhKey);
318
if (TmpSize<BestSize)
325
if (NewVFS_Entry->ArhKey != 0){delete [] NewVFS_Entry->ArhKey; NewVFS_Entry->ArhKey = 0;}
326
NewVFS_Entry->ArhKey = new char[2+1];
327
NewVFS_Entry->ArhKey[0] = '1';
328
NewVFS_Entry->ArhKey[0] = '2';
329
NewVFS_Entry->ArhKey[1] = 0;
330
TmpSize = CheckCompression(NewVFS_Entry->Length, buffer, NewVFS_Entry->ArhKey);
331
if (TmpSize<BestSize)
338
if (NewVFS_Entry->ArhKey != 0){delete [] NewVFS_Entry->ArhKey; NewVFS_Entry->ArhKey = 0;}
339
NewVFS_Entry->ArhKey = new char[2+1];
340
NewVFS_Entry->ArhKey[0] = '2';
341
NewVFS_Entry->ArhKey[0] = '1';
342
NewVFS_Entry->ArhKey[1] = 0;
343
TmpSize = CheckCompression(NewVFS_Entry->Length, buffer, NewVFS_Entry->ArhKey);
344
if (TmpSize<BestSize)
350
#endif // compression
352
if (NewVFS_Entry->ArhKey != 0){delete [] NewVFS_Entry->ArhKey; NewVFS_Entry->ArhKey = 0;}
357
NewVFS_Entry->ArhKeyLen = 2;
358
NewVFS_Entry->ArhKey = new char[NewVFS_Entry->ArhKeyLen];
359
NewVFS_Entry->ArhKey[0] = '0';
360
NewVFS_Entry->ArhKey[1] = 0;
363
NewVFS_Entry->ArhKeyLen = 2;
364
NewVFS_Entry->ArhKey = new char[NewVFS_Entry->ArhKeyLen];
365
NewVFS_Entry->ArhKey[0] = '1';
366
NewVFS_Entry->ArhKey[1] = 0;
369
NewVFS_Entry->ArhKeyLen = 2;
370
NewVFS_Entry->ArhKey = new char[NewVFS_Entry->ArhKeyLen];
371
NewVFS_Entry->ArhKey[0] = '2';
372
NewVFS_Entry->ArhKey[1] = 0;
375
NewVFS_Entry->ArhKeyLen = 3;
376
NewVFS_Entry->ArhKey = new char[NewVFS_Entry->ArhKeyLen];
377
NewVFS_Entry->ArhKey[0] = '1';
378
NewVFS_Entry->ArhKey[1] = '2';
379
NewVFS_Entry->ArhKey[2] = 0;
382
NewVFS_Entry->ArhKeyLen = 3;
383
NewVFS_Entry->ArhKey = new char[NewVFS_Entry->ArhKeyLen];
384
NewVFS_Entry->ArhKey[0] = '2';
385
NewVFS_Entry->ArhKey[1] = '1';
386
NewVFS_Entry->ArhKey[2] = 0;
397
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
398
// если используется сжатие - запаковываем данные
399
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
401
// устанавливаем данные
404
srcVFS = new BYTE[NewVFS_Entry->Length];
405
memcpy(srcVFS, buffer, NewVFS_Entry->Length);
406
int ssizeVFS = NewVFS_Entry->Length;
408
if (!((NewVFS_Entry->ArhKey[0]=='0')&(strlen(NewVFS_Entry->ArhKey)==1)))
410
// цикл по кол-ву примененных методов сжатия в ArhKeyVFS
411
for (unsigned int i=0; i<strlen(NewVFS_Entry->ArhKey);i++)
413
// находим, какой текущий метод сжатия
414
char S = NewVFS_Entry->ArhKey[strlen(NewVFS_Entry->ArhKey)-i-1];
417
if (S == VFS_DATA_ARH_RLE)
419
vw_DATAtoRLE(&dstVFS, srcVFS, &NewVFS_Entry->Length, ssizeVFS);
420
delete [] srcVFS; srcVFS = 0;
422
ssizeVFS = NewVFS_Entry->Length;
427
if (S == VFS_DATA_ARH_HAFF)
429
vw_DATAtoHAFF(&dstVFS, srcVFS, &NewVFS_Entry->Length, ssizeVFS);
430
delete [] srcVFS; srcVFS = 0;
432
ssizeVFS = NewVFS_Entry->Length;
440
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
441
// пишем данные в VFS
442
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
443
SDL_RWseek(WritebleVFS->File, WritebleVFS->HeaderOffsetVFS, SEEK_SET);
444
SDL_RWwrite(WritebleVFS->File, srcVFS, NewVFS_Entry->Length, 1);
445
delete [] srcVFS; srcVFS = 0;
450
// переписывать все ентри, принадлежащие этому вфс файлу, в конец
451
eVFS_Entry *Tmp = StarVFSArray;
454
eVFS_Entry *Tmp1 = Tmp->Next;
456
// пишем только файлы (не линки)
457
if ((!Tmp->Link) && (NewVFS_Entry->Parent == WritebleVFS))
459
SDL_RWwrite(WritebleVFS->File, &Tmp->ArhKeyLen, 1, 1);
460
if (Tmp->ArhKeyLen > 0)
461
SDL_RWwrite(WritebleVFS->File, Tmp->ArhKey, Tmp->ArhKeyLen, 1);
462
SDL_RWwrite(WritebleVFS->File, &Tmp->NameLen, 2, 1);
463
SDL_RWwrite(WritebleVFS->File, Tmp->Name, Tmp->NameLen, 1);
464
SDL_RWwrite(WritebleVFS->File, &Tmp->Offset, 4, 1);
465
SDL_RWwrite(WritebleVFS->File, &Tmp->Length, 4, 1);
466
SDL_RWwrite(WritebleVFS->File, &Tmp->RealLength, 4, 1);
474
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
476
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
477
WritebleVFS->HeaderOffsetVFS += NewVFS_Entry->Length;
478
WritebleVFS->HeaderLengthVFS += 1+NewVFS_Entry->ArhKeyLen+2+NewVFS_Entry->NameLen+4+4+4;
481
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
482
// переписываем смещение начала таблицы
483
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
484
SDL_RWseek(WritebleVFS->File, WritebleVFS->DataStartOffsetVFS, SEEK_SET);
485
SDL_RWwrite(WritebleVFS->File, &WritebleVFS->HeaderOffsetVFS, 4, 1);
486
SDL_RWwrite(WritebleVFS->File, &WritebleVFS->HeaderLengthVFS, 4, 1);
489
printf("%s file added to VFS.\n", Name);
497
//------------------------------------------------------------------------------------
498
// Открытие (подключение) VFS
499
//------------------------------------------------------------------------------------
500
int vw_OpenVFS(const char *Name, unsigned int BuildNumber)
502
unsigned int vfsBuildNumber = 0;
503
int POS = 0; // указатель позиции в буфере.
509
// Начальная подготовка структуры списка...
511
TempVFS = new eVFS; if (TempVFS == 0) return -1;
513
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
514
// открываем файл VFS
515
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
517
TempVFS->File = SDL_RWFromFile(Name, "rb");
518
if (TempVFS->File == NULL)
520
fprintf(stderr, "Can't find VFS file %s\n", Name);
526
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
527
// выделяем память для имени
528
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
529
TempVFS->FileName = 0;
530
TempVFS->FileName = new char[strlen(Name)+1]; if (TempVFS->FileName == 0) return -1;
531
strcpy(TempVFS->FileName, Name);
536
// первый в списке...
544
else // продолжаем заполнение...
546
TempVFS->Prev = EndVFS;
548
EndVFS->Next = TempVFS;
554
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
555
// Проверяем сигнатуру "VFS_" - 4 байт
556
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
557
char Sign[4]; Sign[4] = 0;
558
if(SDL_RWread(TempVFS->File, &Sign, 4, 1) == -1)
560
// если файл меньше, значит ошибка
561
fprintf(stderr, "VFS file size error %s\n", Name);
562
goto vw_OpenVFS_Error;
564
if (strncmp(Sign, "VFS_", 4) != 0)
567
fprintf(stderr, "VFS file header error %s\n", Name);
568
goto vw_OpenVFS_Error;
572
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
574
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
575
char Version[4]; Version[4] = 0;
576
if(SDL_RWread(TempVFS->File, &Version, 4, 1) == -1)
578
fprintf(stderr, "VFS file corrupted: %s\n", Name);
579
goto vw_OpenVFS_Error;
581
if (strncmp(Version, "v1.5", 4) != 0)
583
fprintf(stderr, "VFS file has wrong version, version %s not supported: %s\n", Version, Name);
584
goto vw_OpenVFS_Error;
589
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
590
// Билд - 4 байт (если предали ноль - проверять билды не нужно)
591
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
592
if(SDL_RWread(TempVFS->File, &vfsBuildNumber, 4, 1) == -1)
594
fprintf(stderr, "VFS file corrupted: %s\n", Name);
595
goto vw_OpenVFS_Error;
597
// если передали ноль - проверка не нужна
598
if (BuildNumber != 0)
600
if (vfsBuildNumber == 0)
602
printf("VFS file build number was not set (0).\n");
606
if (BuildNumber != vfsBuildNumber)
608
fprintf(stderr, "VFS file has wrong build number (%i), you need VFS with build number %i\n", vfsBuildNumber, BuildNumber);
609
goto vw_OpenVFS_Error;
615
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
616
// читаем смещение таблицы данных VFS - 4 байт
617
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
618
HeaderOffsetVFS = SDL_ReadLE32(TempVFS->File);
621
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
622
// читаем длину таблицы данных VFS
623
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
624
HeaderLengthVFS = SDL_ReadLE32(TempVFS->File);
628
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
629
// Читаем в буфер всю таблицу
630
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
631
SDL_RWseek(TempVFS->File, HeaderOffsetVFS, SEEK_SET);
632
buff = new BYTE[HeaderLengthVFS]; if (buff == 0) return -1;
633
SDL_RWread(TempVFS->File, buff, HeaderLengthVFS, 1);
637
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
638
// Составляем (дополняем) список доступных файлов
639
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
640
SDL_RWseek(TempVFS->File, HeaderOffsetVFS, SEEK_SET);
641
while (POS<HeaderLengthVFS)
643
// Начальная подготовка структуры списка...
644
eVFS_Entry *Temp = 0;
645
Temp = new eVFS_Entry; if (Temp == 0) return -1;
647
// первый в списке...
648
if (EndVFSArray == 0)
655
else // продолжаем заполнение...
657
Temp->Prev = EndVFSArray;
659
EndVFSArray->Next = Temp;
663
Temp->Parent = TempVFS;
665
SDL_RWseek(TempVFS->File, 1, SEEK_CUR);
666
Temp->ArhKeyLen = buff[POS];
667
Temp->ArhKey = new char[Temp->ArhKeyLen+1]; if (Temp->ArhKey == 0) return -1;
668
Temp->ArhKey[Temp->ArhKeyLen] = 0;// последний символ всегда ноль - конец строки
669
SDL_RWread(TempVFS->File, Temp->ArhKey, Temp->ArhKeyLen, 1);
671
SDL_RWseek(TempVFS->File, 2, SEEK_CUR);
672
Temp->NameLen = buff[POS+1+Temp->ArhKeyLen+1]*0x100+buff[POS+Temp->ArhKeyLen+1];
673
Temp->Name = new char[Temp->NameLen+1]; if (Temp->Name == 0) return -1;
674
Temp->Name[Temp->NameLen] = 0;// последний символ всегда ноль - конец строки
675
SDL_RWread(TempVFS->File, Temp->Name, Temp->NameLen, 1);
677
Temp->Offset = SDL_ReadLE32(TempVFS->File);
678
Temp->Length = SDL_ReadLE32(TempVFS->File);
679
Temp->RealLength = SDL_ReadLE32(TempVFS->File);
680
POS = POS + 1 + Temp->ArhKeyLen + 2 + Temp->NameLen + 4 + 4 + 4;
683
// Освобождаем память...
684
if (buff != 0){delete [] buff; buff = 0;}
688
// выходим, все хорошо
689
printf("VFS file was opened %s\n", Name);
695
SDL_RWclose(TempVFS->File);
696
if (TempVFS->FileName != 0){delete [] TempVFS->FileName; TempVFS->FileName = 0;}
705
//------------------------------------------------------------------------------------
707
//------------------------------------------------------------------------------------
708
void vw_CloseVFS(void)
711
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
712
// даже если файла нет, все равно освобождаем память
713
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
714
eVFS_Entry *Tmp = StarVFSArray;
717
eVFS_Entry *Tmp1 = Tmp->Next;
719
if (Tmp->Name != 0) {delete [] Tmp->Name; Tmp->Name = 0;}
720
if (Tmp->ArhKey != 0) {delete [] Tmp->ArhKey; Tmp->ArhKey = 0;}
722
// переустанавливаем указатели...
723
if (StarVFSArray == Tmp) StarVFSArray = Tmp->Next;
724
if (EndVFSArray == Tmp) EndVFSArray = Tmp->Prev;
727
if (Tmp->Next != 0) Tmp->Next->Prev = Tmp->Prev;
728
else if (Tmp->Prev != 0) Tmp->Prev->Next = 0;
729
if (Tmp->Prev != 0) Tmp->Prev->Next = Tmp->Next;
730
else if (Tmp->Next != 0) Tmp->Next->Prev = 0;
736
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
737
// устанавливаем указатели в исходное состояние
738
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
744
eVFS *TempVFS = StartVFS;
747
eVFS *TempVFS1 = TempVFS->Next;
750
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
751
// если VFS файл открыт, закрываем его
752
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
753
if (TempVFS->File != NULL)
755
SDL_RWclose(TempVFS->File);
761
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
762
// освобождаем пямять в VFSFileName и пишем сообщение о закрытии
763
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
764
if (TempVFS->FileName != 0)
766
printf("VFS file was closed %s\n", TempVFS->FileName);
767
delete [] TempVFS->FileName; TempVFS->FileName = 0;
782
//------------------------------------------------------------------------------------
783
// Завершаем работу с VFS
784
//------------------------------------------------------------------------------------
785
void vw_ShutdownVFS(void)
787
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
788
// закрываем все открытые файлы
789
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
790
if (StartFileVFS != 0)
792
// берем указатель на первый файл
793
eFILE *Tmp = StartFileVFS;
794
// просматриваем все файлы
797
eFILE *Tmp1 = Tmp->Next;
804
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
805
// устанавливаем указатели в исходное состояние
806
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
811
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
813
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
825
//------------------------------------------------------------------------------------
826
// создаем "симлинк" внутри VFS
827
//------------------------------------------------------------------------------------
828
bool vw_CreateEntryLinkVFS(const char *FileName, const char *FileNameLink)
830
// проверяем, если уже есть такой файл или линк - выходим
831
eVFS_Entry *Tmp = StarVFSArray;
834
eVFS_Entry *Tmp1 = Tmp->Next;
835
if (vw_strcmp(Tmp->Name, FileNameLink) == 0)
837
// нашли, такой файл или симлинк уже есть в системе
838
fprintf(stderr, "VFS link creation error, file or link already present: %s\n", FileNameLink);
845
// находим запись с соотв. RealName и меняем Name
846
eVFS_Entry *OutputEntry = 0;
848
while (Tmp != 0 && OutputEntry == 0)
850
eVFS_Entry *Tmp1 = Tmp->Next;
851
if (vw_strcmp(Tmp->Name, FileName) == 0)
855
// добавляем новую eVFS_Entry запись в конец списка
856
eVFS_Entry *NewTemp = 0;
857
NewTemp = new eVFS_Entry;
859
NewTemp->Link = true;
861
NewTemp->NameLen = strlen(FileNameLink)+1;
862
NewTemp->Name = new char[NewTemp->NameLen];
863
strcpy(NewTemp->Name, FileNameLink);
865
NewTemp->Offset = OutputEntry->Offset;
866
NewTemp->Length = OutputEntry->Length;
867
NewTemp->RealLength = OutputEntry->RealLength;
868
NewTemp->Parent = OutputEntry->Parent;
870
NewTemp->ArhKeyLen = OutputEntry->ArhKeyLen;
871
NewTemp->ArhKey = new char[NewTemp->ArhKeyLen];
872
strcpy(NewTemp->ArhKey, OutputEntry->ArhKey);
874
// добавляем запись в конец списка
875
NewTemp->Prev = EndVFSArray;
877
EndVFSArray->Next = NewTemp;
878
EndVFSArray = NewTemp;
881
printf("VFS link created: %s > %s\n", FileName, FileNameLink);
889
fprintf(stderr, "VFS link creation error, file not found: %s\n", FileName);
896
//------------------------------------------------------------------------------------
897
// удаляем "симлинк" внутри VFS
898
//------------------------------------------------------------------------------------
899
bool vw_DeleteEntryLinkVFS(const char *FileNameLink)
902
// проверяем, если уже есть такой файл или линк - выходим
903
eVFS_Entry *Tmp = StarVFSArray;
906
eVFS_Entry *Tmp1 = Tmp->Next;
907
if (vw_strcmp(Tmp->Name, FileNameLink) == 0)
912
if (Tmp->Name != 0) {delete [] Tmp->Name; Tmp->Name = 0;}
913
if (Tmp->ArhKey != 0) {delete [] Tmp->ArhKey; Tmp->ArhKey = 0;}
915
// переустанавливаем указатели...
916
if (StarVFSArray == Tmp) StarVFSArray = Tmp->Next;
917
if (EndVFSArray == Tmp) EndVFSArray = Tmp->Prev;
919
if (Tmp->Next != 0) Tmp->Next->Prev = Tmp->Prev;
920
else if (Tmp->Prev != 0) Tmp->Prev->Next = 0;
921
if (Tmp->Prev != 0) Tmp->Prev->Next = Tmp->Next;
922
else if (Tmp->Next != 0) Tmp->Next->Prev = 0;
926
printf("VFS link deleted: %s\n", FileNameLink);
932
fprintf(stderr, "VFS link deletion error, can not delete file: %s\n", FileNameLink);
943
fprintf(stderr, "VFS link deletion error, link not found: %s\n", FileNameLink);
952
//------------------------------------------------------------------------------------
953
// удаляем все "симлинки" из VFS
954
//------------------------------------------------------------------------------------
955
bool vw_DeleteAllLinksVFS()
958
// проверяем, если уже есть такой файл или линк - выходим
959
eVFS_Entry *Tmp = StarVFSArray;
962
eVFS_Entry *Tmp1 = Tmp->Next;
966
if (Tmp->Name != 0) printf("VFS link deleted: %s\n", Tmp->Name);
968
if (Tmp->Name != 0) {delete [] Tmp->Name; Tmp->Name = 0;}
969
if (Tmp->ArhKey != 0) {delete [] Tmp->ArhKey; Tmp->ArhKey = 0;}
971
// переустанавливаем указатели...
972
if (StarVFSArray == Tmp) StarVFSArray = Tmp->Next;
973
if (EndVFSArray == Tmp) EndVFSArray = Tmp->Prev;
975
if (Tmp->Next != 0) Tmp->Next->Prev = Tmp->Prev;
976
else if (Tmp->Prev != 0) Tmp->Prev->Next = 0;
977
if (Tmp->Prev != 0) Tmp->Prev->Next = Tmp->Next;
978
else if (Tmp->Next != 0) Tmp->Next->Prev = 0;
1006
//------------------------------------------------------------------------------------
1007
// Проверка наличия файла в VFS или FS
1008
//------------------------------------------------------------------------------------
1009
int FileDetect(const char *FileName)
1011
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1013
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1014
eVFS_Entry *Tmp = StarVFSArray;
1017
eVFS_Entry *Tmp1 = Tmp->Next;
1019
if(vw_strcmp(FileName, Tmp->Name) == 0)
1022
return VFS_FILE_VFS;
1031
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1033
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1034
SDL_RWops *temp = SDL_RWFromFile(FileName, "rb");
1035
// смогли открыть файл
1043
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1045
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1058
//------------------------------------------------------------------------------------
1059
// Открытие файла в VFS (или подгонка файла FS к классу VFS)
1060
//------------------------------------------------------------------------------------
1061
extern char ProgrammDir[MAX_PATH];
1062
eFILE *vw_fopen(const char *FileName)
1066
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1067
// проверяем наличие файла в системе
1068
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1069
int ResTMP = FileDetect(FileName);
1074
fprintf(stderr, "Can't find the file %s\n", FileName);
1079
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1080
// файл в FS , подготовка данных и передача указателя на структуру
1081
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1082
if (ResTMP == VFS_FILE_FS)
1084
// Начальная подготовка структуры списка...
1086
Temp = new eFILE; if (Temp == 0) return 0;
1088
// возможно используется многопоточность, смотрим чтобы не портить данные
1089
while (fileIObusy) SDL_Delay(0);
1090
// говорим, что работаем с это процедурой
1093
// первый в списке...
1094
if (EndFileVFS == 0)
1098
StartFileVFS = Temp;
1101
else // продолжаем заполнение...
1103
Temp->Prev = EndFileVFS;
1105
EndFileVFS->Next = Temp;
1111
Temp->PackLength = 0;
1113
Temp->RealLength = 0;
1114
Temp->VFS_Offset = 0;
1116
// заносим имя файла
1118
Temp->Name = new char[strlen(FileName)+1]; if (Temp->Name == 0) return 0;
1119
strcpy(Temp->Name, FileName);
1121
// открываем физ. файл, проверка в детекте...
1122
SDL_RWops * fTEMP = SDL_RWFromFile(FileName, "rb");
1124
// получаем размер файла
1125
SDL_RWseek(fTEMP, 0, SEEK_END);
1126
Temp->RealLength = SDL_RWtell(fTEMP);
1127
Temp->PackLength = Temp->RealLength;
1128
SDL_RWseek(fTEMP, 0, SEEK_SET);
1130
// резервируем память
1132
Temp->Data = new BYTE[Temp->RealLength]; if (Temp->Data == 0) return 0;
1134
// плолучаем данные...
1135
SDL_RWread(fTEMP, Temp->Data, 1, Temp->RealLength);
1138
// передаем указатель на структуру...
1143
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1144
// файл в VFS , подготовка данных и передача указателя на структуру
1145
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1146
if (ResTMP == VFS_FILE_VFS)
1148
// Начальная подготовка структуры списка...
1150
Temp = new eFILE; if (Temp == 0) return 0;
1152
// возможно используется многопоточность, смотрим чтобы не портить данные
1153
while (fileIObusy) SDL_Delay(0);
1154
// говорим, что работаем с это процедурой
1157
// первый в списке...
1158
if (EndFileVFS == 0)
1162
StartFileVFS = Temp;
1165
else // продолжаем заполнение...
1167
Temp->Prev = EndFileVFS;
1169
EndFileVFS->Next = Temp;
1175
Temp->PackLength = 0;
1177
Temp->RealLength = 0;
1178
Temp->VFS_Offset = 0;
1181
Temp->Name = new char[strlen(FileName)+1]; if (Temp->Name == 0) return 0;
1182
strcpy(Temp->Name, FileName);
1186
// находим указатель на запись в таблице файлов VFS
1187
eVFS_Entry *OutputFile = 0;
1188
eVFS_Entry *Tmp = StarVFSArray;
1189
while (Tmp != 0 && OutputFile == 0)
1191
eVFS_Entry *Tmp1 = Tmp->Next;
1193
if(vw_strcmp(Temp->Name, Tmp->Name) == 0)
1201
if (OutputFile == 0) return 0;
1204
Temp->PackLength = OutputFile->Length;
1205
Temp->VFS_Offset = OutputFile->Offset;
1207
// резервируем память
1209
Temp->Data = new BYTE[Temp->PackLength]; if (Temp->Data == 0) return 0;
1212
// возможно используется многопоточность, смотрим чтобы не портить данные
1213
while (VFSfileIObusy) SDL_Delay(0);
1214
// говорим, что работаем с это процедурой
1215
VFSfileIObusy = true;
1217
// плолучаем данные...
1218
SDL_RWseek(OutputFile->Parent->File, Temp->VFS_Offset, SEEK_SET);
1219
SDL_RWread(OutputFile->Parent->File, Temp->Data, Temp->PackLength, 1);
1220
Temp->RealLength = Temp->PackLength;
1222
VFSfileIObusy = false;
1226
// используем сжатие?
1232
if (!((OutputFile->ArhKey[0]=='0')&(strlen(OutputFile->ArhKey)==1)))
1234
for (size_t i=0; i<OutputFile->ArhKeyLen;i++)
1236
char S = OutputFile->ArhKey[i];
1237
size_t cur_i = OutputFile->ArhKeyLen-1;
1239
if (S == VFS_DATA_ARH_RLE)
1241
ssizeVFS = Temp->RealLength;
1242
srcVFS = Temp->Data;
1245
vw_RLEtoDATA(OutputFile->RealLength, &dstVFS, srcVFS, &dsizeVFS, ssizeVFS);
1247
vw_RLEtoDATA(0, &dstVFS, srcVFS, &dsizeVFS, ssizeVFS);
1249
Temp->RealLength = dsizeVFS;
1250
if (Temp->Data != 0){delete [] Temp->Data; Temp->Data = 0;}
1251
Temp->Data = dstVFS;
1254
if (S == VFS_DATA_ARH_HAFF)
1256
ssizeVFS = Temp->RealLength;
1257
srcVFS = Temp->Data;
1260
vw_HAFFtoDATA(OutputFile->RealLength, &dstVFS, srcVFS, &dsizeVFS, ssizeVFS);
1262
vw_HAFFtoDATA(0, &dstVFS, srcVFS, &dsizeVFS, ssizeVFS);
1264
Temp->RealLength = dsizeVFS;
1265
if (Temp->Data != 0){delete [] Temp->Data; Temp->Data = 0;}
1266
Temp->Data = dstVFS;
1272
// передаем указатель на структуру...
1278
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1279
// в системе нет такого файла, или какие-то проблемы
1280
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1295
//------------------------------------------------------------------------------------
1296
// Закрытие файла в VFS
1297
//------------------------------------------------------------------------------------
1298
int vw_fclose(eFILE *stream)
1301
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1302
// файл не открыли...закрывать нечего...
1303
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1304
if (stream == 0) return -1;
1306
// возможно используется многопоточность, смотрим чтобы не портить данные
1307
while (fileIObusy) SDL_Delay(0);
1308
// говорим, что работаем с это процедурой
1311
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1312
// Освобождаем память
1313
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1314
if (stream->Data != 0) {delete [] stream->Data; stream->Data = 0;}
1315
if (stream->Name != 0) {delete [] stream->Name; stream->Name = 0;}
1318
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1319
// Устанавливаем все у начальное состояние
1320
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1321
stream->PackLength = 0;
1323
stream->RealLength = 0;
1324
stream->VFS_Offset =0;
1327
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1328
// переустанавливаем указатели
1329
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1332
if (StartFileVFS == stream) StartFileVFS = stream->Next;
1333
if (EndFileVFS == stream) EndFileVFS = stream->Prev;
1335
if (stream->Next != 0) stream->Next->Prev = stream->Prev;
1336
else if (stream->Prev != 0) stream->Prev->Next = 0;
1337
if (stream->Prev != 0) stream->Prev->Next = stream->Next;
1338
else if (stream->Next != 0) stream->Next->Prev = 0;
1340
if (stream != 0){delete stream; stream = 0;}
1363
//------------------------------------------------------------------------------------
1364
// чтение блока данных из файла в VFS
1365
//------------------------------------------------------------------------------------
1366
int eFILE::fread(void *buffer, size_t size, size_t count)
1368
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1370
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1371
if (buffer == 0) return -1;
1372
if (Data == 0) return -1;
1374
// Кол-во успешно считанных раз
1377
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1379
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1380
for (size_t i=0; i<count; i++)
1382
// если можем прочитать следующий блок size размера - читаем
1383
if (size <= (unsigned int)(RealLength - Pos))
1386
memcpy((BYTE*)buffer + SecCount*size, Data + Pos, size);
1387
// передвигаем текущий указатель
1389
// устанавливаем успешное чтение
1392
// иначе, уже достигли конца файла - выходим из цикла
1404
//------------------------------------------------------------------------------------
1405
// поиск (установка текущей позиции)
1406
//------------------------------------------------------------------------------------
1407
int eFILE::fseek(long offset, int origin)
1409
// изменяем значение указателя, согласно origin...
1414
if (Pos + offset > RealLength) return 1;
1420
if (RealLength-offset < 0) return 1;
1421
Pos = RealLength-offset;
1426
if (offset < 0 || offset > RealLength) return 1;
1438
//------------------------------------------------------------------------------------
1439
// получить текущую позицию указателя
1440
//------------------------------------------------------------------------------------
1449
//------------------------------------------------------------------------------------
1450
// узнаем, достигли конца файла или нет
1451
//------------------------------------------------------------------------------------
1454
// если указатель больше или равен длине файла - значит он уже за массивом данных файла
1455
if (Pos >= RealLength-1) return 1;
1456
// иначе - все ок, еще можем читать файл
1463
//------------------------------------------------------------------------------------
1464
// Get string from stream
1465
//------------------------------------------------------------------------------------
1466
char *eFILE::fgets(char *str, int num)
1468
// проверка первая, не читаем больше, чем у нас длина файла
1469
if (Pos+num >= RealLength-1) num = (RealLength-1)-Pos;
1471
for (int i=0; i<num; i++)
1475
// конец строки, нужно выйти
1476
if (Data[Pos-1] == '\n') return str;