~ubuntu-branches/debian/sid/astromenace/sid

« back to all changes in this revision

Viewing changes to AstroMenaceSource/Core/VirtualFileSystem/VFS.cpp

  • Committer: Package Import Robot
  • Author(s): Boris Pek
  • Date: 2013-04-09 02:04:25 UTC
  • Revision ID: package-import@ubuntu.com-20130409020425-a7fl9xk4diamw6di
Tags: upstream-1.3.1+repack
Import upstream version 1.3.1+repack

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/************************************************************************************
 
2
 
 
3
        AstroMenace (Hardcore 3D space shooter with spaceship upgrade possibilities)
 
4
        Copyright © 2006-2012 Michael Kurinnoy, Viewizard
 
5
 
 
6
 
 
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.
 
11
 
 
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.
 
16
 
 
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/>.
 
19
 
 
20
 
 
21
        Web Site: http://www.viewizard.com/
 
22
        Project: http://sourceforge.net/projects/openastromenace/
 
23
        E-mail: viewizard@viewizard.com
 
24
 
 
25
*************************************************************************************/
 
26
 
 
27
 
 
28
#include "VFS.h"
 
29
#include "../Math/Math.h"
 
30
 
 
31
 
 
32
// Список подключенных VFS файлов
 
33
struct eVFS
 
34
{
 
35
        char *FileName;         // Имя файла VFS
 
36
        SDL_RWops *File;        // Указатель на файл виртуальной системы
 
37
 
 
38
        // данные для записи в создаваемую VFS
 
39
        int NumberOfFilesVFS;
 
40
        int HeaderLengthVFS;
 
41
        int HeaderOffsetVFS;
 
42
        int DataStartOffsetVFS;
 
43
 
 
44
 
 
45
        eVFS*   Prev;
 
46
        eVFS*   Next;
 
47
};
 
48
eVFS *StartVFS = 0;
 
49
eVFS *EndVFS = 0;
 
50
 
 
51
 
 
52
 
 
53
 
 
54
 
 
55
// Список файлов, доступных в подключенных (открытых) VFS
 
56
struct eVFS_Entry
 
57
{
 
58
        BOOL    Link;           // флаг что это не реальная запись а линк на существующую в VFS
 
59
        DWORD   NameLen;        // Кол-во байт в имени...
 
60
        char    *Name;          // Имя записи (имя файла) (может быть "линком")
 
61
        int             Offset;         // Смещение начала файла относительно начала файловой системы
 
62
        int             Length;         // Длина файла в системе
 
63
        int             RealLength;     // Длина файла после распаковки
 
64
        eVFS    *Parent;
 
65
        BYTE    ArhKeyLen;      // Кол-во байт ключа упаковки
 
66
        char    *ArhKey;        // Ключ-упаковки
 
67
 
 
68
        eVFS_Entry*     Prev;
 
69
        eVFS_Entry*     Next;
 
70
 
 
71
};
 
72
eVFS_Entry *StarVFSArray = 0;
 
73
eVFS_Entry *EndVFSArray = 0;
 
74
 
 
75
 
 
76
 
 
77
 
 
78
 
 
79
// Список файлов (открытых)
 
80
eFILE *StartFileVFS = 0;        // Указатель на первый файл в списке...
 
81
eFILE *EndFileVFS = 0;          // Указатель на последний файл в списке...
 
82
 
 
83
 
 
84
// чтобы при работе не было сбоев в последовательности файлов... блокируем этот участок
 
85
// при создании и закрытии файлов
 
86
bool fileIObusy = false;
 
87
// при чтении из файла вфс
 
88
bool VFSfileIObusy = false;
 
89
 
 
90
 
 
91
 
 
92
 
 
93
 
 
94
//------------------------------------------------------------------------------------
 
95
// тест сжатия
 
96
//------------------------------------------------------------------------------------
 
97
int CheckCompression(int tmpLength, const BYTE *buffer, char *ArhKeyVFS)
 
98
{
 
99
        BYTE *tmp = 0;
 
100
        tmp = new BYTE[tmpLength];
 
101
        memcpy(tmp, buffer, tmpLength);
 
102
 
 
103
        // устанавливаем данные
 
104
        BYTE *dstVFS = 0;
 
105
        BYTE *srcVFS = tmp;
 
106
        srcVFS = new BYTE[tmpLength];
 
107
        memcpy(srcVFS, buffer, tmpLength);
 
108
 
 
109
        int dsizeVFS = tmpLength;
 
110
        int ssizeVFS = tmpLength;
 
111
 
 
112
 
 
113
 
 
114
        // цикл по кол-ву примененных методов сжатия в ArhKeyVFS
 
115
        for (unsigned int i=0; i<strlen(ArhKeyVFS);i++)
 
116
        {
 
117
                // находим, какой текущий метод сжатия
 
118
                char S = ArhKeyVFS[strlen(ArhKeyVFS)-i-1];
 
119
 
 
120
                // если RLE
 
121
                if (S == VFS_DATA_ARH_RLE)
 
122
                {
 
123
                        vw_DATAtoRLE(&dstVFS, srcVFS, &dsizeVFS, ssizeVFS);
 
124
                        delete [] srcVFS; srcVFS = 0;
 
125
                        srcVFS = dstVFS;
 
126
                        ssizeVFS = dsizeVFS;
 
127
                        dstVFS = 0;
 
128
                }
 
129
                // если HAFF
 
130
                if (S == VFS_DATA_ARH_HAFF)
 
131
                {
 
132
                        vw_DATAtoHAFF(&dstVFS, srcVFS, &dsizeVFS, ssizeVFS);
 
133
                        delete [] srcVFS; srcVFS = 0;
 
134
                        srcVFS = dstVFS;
 
135
                        ssizeVFS = dsizeVFS;
 
136
                        dstVFS = 0;
 
137
                }
 
138
        }
 
139
 
 
140
        delete [] srcVFS; srcVFS = 0;
 
141
 
 
142
        return dsizeVFS;
 
143
}
 
144
 
 
145
 
 
146
 
 
147
 
 
148
 
 
149
 
 
150
 
 
151
//------------------------------------------------------------------------------------
 
152
// Создание VFS
 
153
//------------------------------------------------------------------------------------
 
154
int vw_CreateVFS(const char *Name, unsigned int BuildNumber)
 
155
{
 
156
        // Начальная подготовка структуры списка...
 
157
        eVFS *TempVFS = 0;
 
158
        TempVFS = new eVFS; if (TempVFS == 0) return -1;
 
159
 
 
160
        TempVFS->NumberOfFilesVFS = 0;
 
161
        TempVFS->HeaderLengthVFS = 0;
 
162
        TempVFS->HeaderOffsetVFS = 0;
 
163
        TempVFS->DataStartOffsetVFS = 0;
 
164
 
 
165
 
 
166
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
167
        // открываем файл VFS
 
168
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
169
        TempVFS->File = 0;
 
170
        TempVFS->File = SDL_RWFromFile(Name, "wb");
 
171
    if (TempVFS->File == NULL)
 
172
    {
 
173
        fprintf(stderr, "Can't open VFS file for write %s\n", Name);
 
174
        return -1; // ERROR
 
175
    }
 
176
 
 
177
 
 
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);
 
184
 
 
185
 
 
186
        // первый в списке...
 
187
        if (EndVFS == 0)
 
188
        {
 
189
                TempVFS->Prev = 0;
 
190
                TempVFS->Next = 0;
 
191
                StartVFS = TempVFS;
 
192
                EndVFS = TempVFS;
 
193
        }
 
194
        else // продолжаем заполнение...
 
195
        {
 
196
                TempVFS->Prev = EndVFS;
 
197
                TempVFS->Next = 0;
 
198
                EndVFS->Next = TempVFS;
 
199
                EndVFS = TempVFS;
 
200
        }
 
201
 
 
202
 
 
203
 
 
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);
 
211
 
 
212
 
 
213
 
 
214
 
 
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
 
220
 
 
221
        SDL_RWwrite(TempVFS->File, &TempVFS->HeaderOffsetVFS, 4, 1);
 
222
        SDL_RWwrite(TempVFS->File, &TempVFS->HeaderLengthVFS, 4, 1);
 
223
 
 
224
        printf("VFS file was created %s\n", Name);
 
225
        return 0;
 
226
}
 
227
 
 
228
 
 
229
 
 
230
 
 
231
//------------------------------------------------------------------------------------
 
232
// запись данных в VFS
 
233
//------------------------------------------------------------------------------------
 
234
int     vw_WriteIntoVFSfromMemory(const char *Name, const BYTE * buffer, int size)
 
235
{
 
236
 
 
237
        // (!) пока работаем только с одной открытой VFS в системе, собственно больше и не нужно
 
238
 
 
239
        eVFS *WritebleVFS = StartVFS;
 
240
 
 
241
        if (WritebleVFS == 0)
 
242
        {
 
243
                fprintf(stderr, "Can't find VFS opened for write\n");
 
244
                return -1;
 
245
        }
 
246
 
 
247
 
 
248
 
 
249
        // Начальная подготовка структуры списка для новых данных
 
250
        eVFS_Entry *NewVFS_Entry = 0;
 
251
        NewVFS_Entry = new eVFS_Entry; if (NewVFS_Entry == 0) return -1;
 
252
 
 
253
        // первый в списке...
 
254
        if (EndVFSArray == 0)
 
255
        {
 
256
                NewVFS_Entry->Prev = 0;
 
257
                NewVFS_Entry->Next = 0;
 
258
                StarVFSArray = NewVFS_Entry;
 
259
                EndVFSArray = NewVFS_Entry;
 
260
        }
 
261
        else // продолжаем заполнение...
 
262
        {
 
263
                NewVFS_Entry->Prev = EndVFSArray;
 
264
                NewVFS_Entry->Next = 0;
 
265
                EndVFSArray->Next = NewVFS_Entry;
 
266
                EndVFSArray = NewVFS_Entry;
 
267
        }
 
268
 
 
269
        NewVFS_Entry->Parent = WritebleVFS;
 
270
 
 
271
        NewVFS_Entry->ArhKeyLen = 0;
 
272
        NewVFS_Entry->ArhKey = 0;
 
273
        NewVFS_Entry->NameLen = (DWORD)strlen(Name);
 
274
 
 
275
        NewVFS_Entry->Name = 0;
 
276
        NewVFS_Entry->Name = new char[NewVFS_Entry->NameLen+1];
 
277
        strcpy(NewVFS_Entry->Name, Name);
 
278
 
 
279
        NewVFS_Entry->Link = false;
 
280
        NewVFS_Entry->Offset = WritebleVFS->HeaderOffsetVFS; // т.к. это будет последний файл в структуре...
 
281
        NewVFS_Entry->Length = size;
 
282
        NewVFS_Entry->RealLength = size;
 
283
 
 
284
 
 
285
 
 
286
 
 
287
 
 
288
 
 
289
 
 
290
 
 
291
        // надо составлять свою ArhKeyVFS
 
292
        // 0 - 0
 
293
        int BestMode = 0;
 
294
 
 
295
#ifdef compression
 
296
 
 
297
        int BestSize = NewVFS_Entry->Length;
 
298
        int TmpSize = 0;
 
299
 
 
300
 
 
301
        // 1 - 1
 
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)
 
307
        {
 
308
                BestMode = 1;
 
309
                BestSize = TmpSize;
 
310
        }
 
311
 
 
312
        // 2 - 2
 
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)
 
319
        {
 
320
                BestMode = 2;
 
321
                BestSize = TmpSize;
 
322
        }
 
323
 
 
324
        // 3 - 12
 
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)
 
332
        {
 
333
                BestMode = 3;
 
334
                BestSize = TmpSize;
 
335
        }
 
336
 
 
337
        // 4 - 21
 
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)
 
345
        {
 
346
                BestMode = 4;
 
347
                BestSize = TmpSize;
 
348
        }
 
349
 
 
350
#endif // compression
 
351
 
 
352
        if (NewVFS_Entry->ArhKey != 0){delete [] NewVFS_Entry->ArhKey; NewVFS_Entry->ArhKey = 0;}
 
353
 
 
354
        switch (BestMode)
 
355
        {
 
356
                case 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;
 
361
                        break;
 
362
                case 1:
 
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;
 
367
                        break;
 
368
                case 2:
 
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;
 
373
                        break;
 
374
                case 3:
 
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;
 
380
                        break;
 
381
                case 4:
 
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;
 
387
                        break;
 
388
        }
 
389
 
 
390
 
 
391
 
 
392
 
 
393
 
 
394
 
 
395
 
 
396
 
 
397
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
398
        // если используется сжатие - запаковываем данные
 
399
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
400
 
 
401
        // устанавливаем данные
 
402
        BYTE *dstVFS = 0;
 
403
        BYTE *srcVFS = 0;
 
404
        srcVFS = new BYTE[NewVFS_Entry->Length];
 
405
        memcpy(srcVFS, buffer, NewVFS_Entry->Length);
 
406
        int ssizeVFS = NewVFS_Entry->Length;
 
407
 
 
408
        if (!((NewVFS_Entry->ArhKey[0]=='0')&(strlen(NewVFS_Entry->ArhKey)==1)))
 
409
        {
 
410
                // цикл по кол-ву примененных методов сжатия в ArhKeyVFS
 
411
                for (unsigned int i=0; i<strlen(NewVFS_Entry->ArhKey);i++)
 
412
                {
 
413
                        // находим, какой текущий метод сжатия
 
414
                        char S = NewVFS_Entry->ArhKey[strlen(NewVFS_Entry->ArhKey)-i-1];
 
415
 
 
416
                        // если RLE
 
417
                        if (S == VFS_DATA_ARH_RLE)
 
418
                        {
 
419
                                vw_DATAtoRLE(&dstVFS, srcVFS, &NewVFS_Entry->Length, ssizeVFS);
 
420
                                delete [] srcVFS; srcVFS = 0;
 
421
                                srcVFS = dstVFS;
 
422
                                ssizeVFS = NewVFS_Entry->Length;
 
423
                                dstVFS = 0;
 
424
 
 
425
                        }
 
426
                        // если HAFF
 
427
                        if (S == VFS_DATA_ARH_HAFF)
 
428
                        {
 
429
                                vw_DATAtoHAFF(&dstVFS, srcVFS, &NewVFS_Entry->Length, ssizeVFS);
 
430
                                delete [] srcVFS; srcVFS = 0;
 
431
                                srcVFS = dstVFS;
 
432
                                ssizeVFS = NewVFS_Entry->Length;
 
433
                                dstVFS = 0;
 
434
                        }
 
435
                }
 
436
        }
 
437
 
 
438
 
 
439
 
 
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;
 
446
 
 
447
 
 
448
 
 
449
 
 
450
        // переписывать все ентри, принадлежащие этому вфс файлу, в конец
 
451
        eVFS_Entry *Tmp = StarVFSArray;
 
452
        while (Tmp != 0)
 
453
        {
 
454
                eVFS_Entry *Tmp1 = Tmp->Next;
 
455
 
 
456
                // пишем только файлы (не линки)
 
457
                if ((!Tmp->Link) && (NewVFS_Entry->Parent == WritebleVFS))
 
458
                {
 
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);
 
467
                }
 
468
 
 
469
                Tmp = Tmp1;
 
470
        }
 
471
 
 
472
 
 
473
 
 
474
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
475
        // меняем данные
 
476
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
477
        WritebleVFS->HeaderOffsetVFS += NewVFS_Entry->Length;
 
478
        WritebleVFS->HeaderLengthVFS += 1+NewVFS_Entry->ArhKeyLen+2+NewVFS_Entry->NameLen+4+4+4;
 
479
 
 
480
 
 
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);
 
487
 
 
488
 
 
489
        printf("%s file added to VFS.\n", Name);
 
490
 
 
491
        return 0;
 
492
}
 
493
 
 
494
 
 
495
 
 
496
 
 
497
//------------------------------------------------------------------------------------
 
498
// Открытие (подключение) VFS
 
499
//------------------------------------------------------------------------------------
 
500
int vw_OpenVFS(const char *Name, unsigned int BuildNumber)
 
501
{
 
502
        unsigned int vfsBuildNumber = 0;
 
503
        int POS = 0; // указатель позиции в буфере.
 
504
        BYTE *buff = 0;
 
505
        int HeaderOffsetVFS;
 
506
        int HeaderLengthVFS;
 
507
 
 
508
 
 
509
        // Начальная подготовка структуры списка...
 
510
        eVFS *TempVFS = 0;
 
511
        TempVFS = new eVFS; if (TempVFS == 0) return -1;
 
512
 
 
513
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
514
        // открываем файл VFS
 
515
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
516
        TempVFS->File = 0;
 
517
        TempVFS->File = SDL_RWFromFile(Name, "rb");
 
518
    if (TempVFS->File == NULL)
 
519
    {
 
520
        fprintf(stderr, "Can't find VFS file %s\n", Name);
 
521
        return -1; // ERROR
 
522
    }
 
523
 
 
524
 
 
525
 
 
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);
 
532
 
 
533
 
 
534
 
 
535
 
 
536
        // первый в списке...
 
537
        if (EndVFS == 0)
 
538
        {
 
539
                TempVFS->Prev = 0;
 
540
                TempVFS->Next = 0;
 
541
                StartVFS = TempVFS;
 
542
                EndVFS = TempVFS;
 
543
        }
 
544
        else // продолжаем заполнение...
 
545
        {
 
546
                TempVFS->Prev = EndVFS;
 
547
                TempVFS->Next = 0;
 
548
                EndVFS->Next = TempVFS;
 
549
                EndVFS = TempVFS;
 
550
        }
 
551
 
 
552
 
 
553
 
 
554
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
555
        // Проверяем сигнатуру "VFS_" - 4 байт
 
556
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
557
        char Sign[4]; Sign[4] = 0;
 
558
        if(SDL_RWread(TempVFS->File, &Sign, 4, 1) == -1)
 
559
        {
 
560
                // если файл меньше, значит ошибка
 
561
                fprintf(stderr, "VFS file size error %s\n", Name);
 
562
                goto vw_OpenVFS_Error;
 
563
        }
 
564
        if (strncmp(Sign, "VFS_", 4) != 0)
 
565
        {
 
566
                // нет сигнатуры
 
567
                fprintf(stderr, "VFS file header error %s\n", Name);
 
568
                goto vw_OpenVFS_Error;
 
569
        }
 
570
 
 
571
 
 
572
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
573
        // Bерсия - 4 байт
 
574
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
575
        char Version[4]; Version[4] = 0;
 
576
        if(SDL_RWread(TempVFS->File, &Version, 4, 1) == -1)
 
577
        {
 
578
                fprintf(stderr, "VFS file corrupted: %s\n", Name);
 
579
                goto vw_OpenVFS_Error;
 
580
        }
 
581
        if (strncmp(Version, "v1.5", 4) != 0)
 
582
        {
 
583
                fprintf(stderr, "VFS file has wrong version, version %s not supported: %s\n", Version, Name);
 
584
                goto vw_OpenVFS_Error;
 
585
        }
 
586
 
 
587
 
 
588
 
 
589
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
590
        // Билд - 4 байт (если предали ноль - проверять билды не нужно)
 
591
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
592
        if(SDL_RWread(TempVFS->File, &vfsBuildNumber, 4, 1) == -1)
 
593
        {
 
594
                fprintf(stderr, "VFS file corrupted: %s\n", Name);
 
595
                goto vw_OpenVFS_Error;
 
596
        }
 
597
        // если передали ноль - проверка не нужна
 
598
        if (BuildNumber != 0)
 
599
        {
 
600
                if (vfsBuildNumber == 0)
 
601
                {
 
602
                        printf("VFS file build number was not set (0).\n");
 
603
                }
 
604
                else
 
605
                {
 
606
                        if (BuildNumber != vfsBuildNumber)
 
607
                        {
 
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;
 
610
                        }
 
611
                }
 
612
        }
 
613
 
 
614
 
 
615
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
616
        // читаем смещение таблицы данных VFS - 4 байт
 
617
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
618
        HeaderOffsetVFS = SDL_ReadLE32(TempVFS->File);
 
619
 
 
620
 
 
621
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
622
        // читаем длину таблицы данных VFS
 
623
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
624
        HeaderLengthVFS = SDL_ReadLE32(TempVFS->File);
 
625
 
 
626
 
 
627
 
 
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);
 
634
 
 
635
 
 
636
 
 
637
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
638
        // Составляем (дополняем) список доступных файлов
 
639
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
640
        SDL_RWseek(TempVFS->File, HeaderOffsetVFS, SEEK_SET);
 
641
        while (POS<HeaderLengthVFS)
 
642
        {
 
643
                // Начальная подготовка структуры списка...
 
644
                eVFS_Entry *Temp = 0;
 
645
                Temp = new eVFS_Entry; if (Temp == 0) return -1;
 
646
 
 
647
                // первый в списке...
 
648
                if (EndVFSArray == 0)
 
649
                {
 
650
                        Temp->Prev = 0;
 
651
                        Temp->Next = 0;
 
652
                        StarVFSArray = Temp;
 
653
                        EndVFSArray = Temp;
 
654
                }
 
655
                else // продолжаем заполнение...
 
656
                {
 
657
                        Temp->Prev = EndVFSArray;
 
658
                        Temp->Next = 0;
 
659
                        EndVFSArray->Next = Temp;
 
660
                        EndVFSArray = Temp;
 
661
                }
 
662
 
 
663
                Temp->Parent = TempVFS;
 
664
 
 
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);
 
670
 
 
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);
 
676
                Temp->Link = false;
 
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;
 
681
        }
 
682
 
 
683
        // Освобождаем память...
 
684
        if (buff != 0){delete [] buff; buff = 0;}
 
685
 
 
686
 
 
687
 
 
688
        // выходим, все хорошо
 
689
        printf("VFS file was opened %s\n", Name);
 
690
        return 0;
 
691
 
 
692
 
 
693
        // была ошибка
 
694
vw_OpenVFS_Error:
 
695
        SDL_RWclose(TempVFS->File);
 
696
        if (TempVFS->FileName != 0){delete [] TempVFS->FileName; TempVFS->FileName = 0;}
 
697
        return -1;
 
698
}
 
699
 
 
700
 
 
701
 
 
702
 
 
703
 
 
704
 
 
705
//------------------------------------------------------------------------------------
 
706
// Закрываем VFS
 
707
//------------------------------------------------------------------------------------
 
708
void vw_CloseVFS(void)
 
709
{
 
710
 
 
711
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
712
        // даже если файла нет, все равно освобождаем память
 
713
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
714
        eVFS_Entry *Tmp = StarVFSArray;
 
715
        while (Tmp != 0)
 
716
        {
 
717
                eVFS_Entry *Tmp1 = Tmp->Next;
 
718
 
 
719
                if (Tmp->Name != 0) {delete [] Tmp->Name; Tmp->Name = 0;}
 
720
                if (Tmp->ArhKey != 0) {delete [] Tmp->ArhKey; Tmp->ArhKey = 0;}
 
721
 
 
722
                // переустанавливаем указатели...
 
723
                if (StarVFSArray == Tmp) StarVFSArray = Tmp->Next;
 
724
                if (EndVFSArray == Tmp) EndVFSArray = Tmp->Prev;
 
725
 
 
726
 
 
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;
 
731
 
 
732
                delete Tmp;
 
733
                Tmp = Tmp1;
 
734
        }
 
735
 
 
736
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
737
        // устанавливаем указатели в исходное состояние
 
738
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
739
        StarVFSArray = 0;
 
740
        EndVFSArray = 0;
 
741
 
 
742
 
 
743
 
 
744
        eVFS *TempVFS = StartVFS;
 
745
        while (TempVFS != 0)
 
746
        {
 
747
                eVFS *TempVFS1 = TempVFS->Next;
 
748
 
 
749
 
 
750
                //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
751
                // если VFS файл открыт, закрываем его
 
752
                //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
753
                if (TempVFS->File != NULL)
 
754
                {
 
755
                        SDL_RWclose(TempVFS->File);
 
756
                        TempVFS->File = 0;
 
757
                }
 
758
 
 
759
 
 
760
 
 
761
                //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
762
                // освобождаем пямять в VFSFileName и пишем сообщение о закрытии
 
763
                //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
764
                if (TempVFS->FileName != 0)
 
765
                {
 
766
                        printf("VFS file was closed %s\n", TempVFS->FileName);
 
767
                        delete [] TempVFS->FileName; TempVFS->FileName = 0;
 
768
                }
 
769
 
 
770
                TempVFS = TempVFS1;
 
771
        }
 
772
 
 
773
        StartVFS = 0;
 
774
        EndVFS = 0;
 
775
}
 
776
 
 
777
 
 
778
 
 
779
 
 
780
 
 
781
 
 
782
//------------------------------------------------------------------------------------
 
783
// Завершаем работу с VFS
 
784
//------------------------------------------------------------------------------------
 
785
void vw_ShutdownVFS(void)
 
786
{
 
787
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
788
        // закрываем все открытые файлы
 
789
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
790
        if (StartFileVFS != 0)
 
791
        {
 
792
                // берем указатель на первый файл
 
793
                eFILE *Tmp = StartFileVFS;
 
794
                // просматриваем все файлы
 
795
                while (Tmp != 0)
 
796
                {
 
797
                        eFILE *Tmp1 = Tmp->Next;
 
798
                        vw_fclose(Tmp);
 
799
                        Tmp = Tmp1;
 
800
                }
 
801
        }
 
802
 
 
803
 
 
804
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
805
        // устанавливаем указатели в исходное состояние
 
806
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
807
        StartFileVFS = 0;
 
808
        EndFileVFS = 0;
 
809
 
 
810
 
 
811
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
812
        // Закрываем VFS
 
813
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
814
        vw_CloseVFS();
 
815
}
 
816
 
 
817
 
 
818
 
 
819
 
 
820
 
 
821
 
 
822
 
 
823
 
 
824
 
 
825
//------------------------------------------------------------------------------------
 
826
// создаем "симлинк" внутри VFS
 
827
//------------------------------------------------------------------------------------
 
828
bool vw_CreateEntryLinkVFS(const char *FileName, const char *FileNameLink)
 
829
{
 
830
        // проверяем, если уже есть такой файл или линк - выходим
 
831
        eVFS_Entry *Tmp = StarVFSArray;
 
832
        while (Tmp != 0)
 
833
        {
 
834
                eVFS_Entry *Tmp1 = Tmp->Next;
 
835
                if (vw_strcmp(Tmp->Name, FileNameLink) == 0)
 
836
                {
 
837
                        // нашли, такой файл или симлинк уже есть в системе
 
838
                        fprintf(stderr, "VFS link creation error, file or link already present: %s\n", FileNameLink);
 
839
                        return false;
 
840
                }
 
841
                Tmp = Tmp1;
 
842
        }
 
843
 
 
844
 
 
845
        // находим запись с соотв. RealName и меняем Name
 
846
        eVFS_Entry *OutputEntry = 0;
 
847
        Tmp = StarVFSArray;
 
848
        while (Tmp != 0 && OutputEntry == 0)
 
849
        {
 
850
                eVFS_Entry *Tmp1 = Tmp->Next;
 
851
                if (vw_strcmp(Tmp->Name, FileName) == 0)
 
852
                {
 
853
                        OutputEntry = Tmp;
 
854
 
 
855
                        // добавляем новую eVFS_Entry запись в конец списка
 
856
                        eVFS_Entry *NewTemp = 0;
 
857
                        NewTemp = new eVFS_Entry;
 
858
 
 
859
                        NewTemp->Link = true;
 
860
 
 
861
                        NewTemp->NameLen = strlen(FileNameLink)+1;
 
862
                        NewTemp->Name = new char[NewTemp->NameLen];
 
863
                        strcpy(NewTemp->Name, FileNameLink);
 
864
 
 
865
                        NewTemp->Offset = OutputEntry->Offset;
 
866
                        NewTemp->Length = OutputEntry->Length;
 
867
                        NewTemp->RealLength = OutputEntry->RealLength;
 
868
                        NewTemp->Parent = OutputEntry->Parent;
 
869
 
 
870
                        NewTemp->ArhKeyLen = OutputEntry->ArhKeyLen;
 
871
                        NewTemp->ArhKey = new char[NewTemp->ArhKeyLen];
 
872
                        strcpy(NewTemp->ArhKey, OutputEntry->ArhKey);
 
873
 
 
874
                        // добавляем запись в конец списка
 
875
                        NewTemp->Prev = EndVFSArray;
 
876
                        NewTemp->Next = 0;
 
877
                        EndVFSArray->Next = NewTemp;
 
878
                        EndVFSArray = NewTemp;
 
879
 
 
880
 
 
881
                        printf("VFS link created: %s > %s\n", FileName, FileNameLink);
 
882
                        return true;
 
883
                }
 
884
                Tmp = Tmp1;
 
885
        }
 
886
 
 
887
 
 
888
        // не нашли ничего
 
889
        fprintf(stderr, "VFS link creation error, file not found: %s\n", FileName);
 
890
        return false;
 
891
}
 
892
 
 
893
 
 
894
 
 
895
 
 
896
//------------------------------------------------------------------------------------
 
897
// удаляем "симлинк" внутри VFS
 
898
//------------------------------------------------------------------------------------
 
899
bool vw_DeleteEntryLinkVFS(const char *FileNameLink)
 
900
{
 
901
 
 
902
        // проверяем, если уже есть такой файл или линк - выходим
 
903
        eVFS_Entry *Tmp = StarVFSArray;
 
904
        while (Tmp != 0)
 
905
        {
 
906
                eVFS_Entry *Tmp1 = Tmp->Next;
 
907
                if (vw_strcmp(Tmp->Name, FileNameLink) == 0)
 
908
                {
 
909
                        if (Tmp->Link)
 
910
                        {
 
911
 
 
912
                                if (Tmp->Name != 0) {delete [] Tmp->Name; Tmp->Name = 0;}
 
913
                                if (Tmp->ArhKey != 0) {delete [] Tmp->ArhKey; Tmp->ArhKey = 0;}
 
914
 
 
915
                                // переустанавливаем указатели...
 
916
                                if (StarVFSArray == Tmp) StarVFSArray = Tmp->Next;
 
917
                                if (EndVFSArray == Tmp) EndVFSArray = Tmp->Prev;
 
918
 
 
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;
 
923
 
 
924
                                delete Tmp;
 
925
 
 
926
                                printf("VFS link deleted: %s\n", FileNameLink);
 
927
                                return true;
 
928
 
 
929
                        }
 
930
                        else
 
931
                        {
 
932
                                fprintf(stderr, "VFS link deletion error, can not delete file: %s\n", FileNameLink);
 
933
                                return false;
 
934
                        }
 
935
                }
 
936
 
 
937
 
 
938
                Tmp = Tmp1;
 
939
        }
 
940
 
 
941
 
 
942
        // не нашли ничего
 
943
        fprintf(stderr, "VFS link deletion error, link not found: %s\n", FileNameLink);
 
944
        return false;
 
945
}
 
946
 
 
947
 
 
948
 
 
949
 
 
950
 
 
951
 
 
952
//------------------------------------------------------------------------------------
 
953
// удаляем все "симлинки" из VFS
 
954
//------------------------------------------------------------------------------------
 
955
bool vw_DeleteAllLinksVFS()
 
956
{
 
957
 
 
958
        // проверяем, если уже есть такой файл или линк - выходим
 
959
        eVFS_Entry *Tmp = StarVFSArray;
 
960
        while (Tmp != 0)
 
961
        {
 
962
                eVFS_Entry *Tmp1 = Tmp->Next;
 
963
 
 
964
                if (Tmp->Link)
 
965
                {
 
966
                        if (Tmp->Name != 0) printf("VFS link deleted: %s\n", Tmp->Name);
 
967
 
 
968
                        if (Tmp->Name != 0) {delete [] Tmp->Name; Tmp->Name = 0;}
 
969
                        if (Tmp->ArhKey != 0) {delete [] Tmp->ArhKey; Tmp->ArhKey = 0;}
 
970
 
 
971
                        // переустанавливаем указатели...
 
972
                        if (StarVFSArray == Tmp) StarVFSArray = Tmp->Next;
 
973
                        if (EndVFSArray == Tmp) EndVFSArray = Tmp->Prev;
 
974
 
 
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;
 
979
 
 
980
                        delete Tmp;
 
981
                }
 
982
 
 
983
                Tmp = Tmp1;
 
984
        }
 
985
 
 
986
 
 
987
        return true;
 
988
}
 
989
 
 
990
 
 
991
 
 
992
 
 
993
 
 
994
 
 
995
 
 
996
 
 
997
 
 
998
 
 
999
 
 
1000
 
 
1001
 
 
1002
 
 
1003
 
 
1004
 
 
1005
 
 
1006
//------------------------------------------------------------------------------------
 
1007
// Проверка наличия файла в VFS или FS
 
1008
//------------------------------------------------------------------------------------
 
1009
int FileDetect(const char *FileName)
 
1010
{
 
1011
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1012
        // поиск в VFS
 
1013
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1014
        eVFS_Entry *Tmp = StarVFSArray;
 
1015
        while (Tmp != 0)
 
1016
        {
 
1017
                eVFS_Entry *Tmp1 = Tmp->Next;
 
1018
 
 
1019
                if(vw_strcmp(FileName, Tmp->Name) == 0)
 
1020
                {
 
1021
                        // нашли
 
1022
                        return VFS_FILE_VFS;
 
1023
                }
 
1024
 
 
1025
                Tmp = Tmp1;
 
1026
        }
 
1027
 
 
1028
 
 
1029
 
 
1030
 
 
1031
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1032
        // поиск в FS
 
1033
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1034
        SDL_RWops *temp = SDL_RWFromFile(FileName, "rb");
 
1035
        // смогли открыть файл
 
1036
        if (temp != NULL)
 
1037
        {
 
1038
                SDL_RWclose(temp);
 
1039
        return VFS_FILE_FS;
 
1040
        }
 
1041
 
 
1042
 
 
1043
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1044
        // Файл не найден
 
1045
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1046
        return -1;
 
1047
}
 
1048
 
 
1049
 
 
1050
 
 
1051
 
 
1052
 
 
1053
 
 
1054
 
 
1055
 
 
1056
 
 
1057
 
 
1058
//------------------------------------------------------------------------------------
 
1059
// Открытие файла в VFS (или подгонка файла FS к классу VFS)
 
1060
//------------------------------------------------------------------------------------
 
1061
extern char ProgrammDir[MAX_PATH];
 
1062
eFILE *vw_fopen(const char *FileName)
 
1063
{
 
1064
 
 
1065
 
 
1066
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1067
        // проверяем наличие файла в системе
 
1068
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1069
        int ResTMP = FileDetect(FileName);
 
1070
 
 
1071
 
 
1072
        if (ResTMP == -1)
 
1073
        {
 
1074
                fprintf(stderr, "Can't find the file %s\n", FileName);
 
1075
                goto FOP_ERR;
 
1076
        }
 
1077
 
 
1078
 
 
1079
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1080
        // файл в FS , подготовка данных и передача указателя на структуру
 
1081
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1082
    if (ResTMP == VFS_FILE_FS)
 
1083
        {
 
1084
                // Начальная подготовка структуры списка...
 
1085
                eFILE *Temp = 0;
 
1086
                Temp = new eFILE; if (Temp == 0) return 0;
 
1087
 
 
1088
                // возможно используется многопоточность, смотрим чтобы не портить данные
 
1089
                while (fileIObusy) SDL_Delay(0);
 
1090
                // говорим, что работаем с это процедурой
 
1091
                fileIObusy = true;
 
1092
 
 
1093
                // первый в списке...
 
1094
                if (EndFileVFS == 0)
 
1095
                {
 
1096
                        Temp->Prev = 0;
 
1097
                        Temp->Next = 0;
 
1098
                        StartFileVFS = Temp;
 
1099
                        EndFileVFS = Temp;
 
1100
                }
 
1101
                else // продолжаем заполнение...
 
1102
                {
 
1103
                        Temp->Prev = EndFileVFS;
 
1104
                        Temp->Next = 0;
 
1105
                        EndFileVFS->Next = Temp;
 
1106
                        EndFileVFS = Temp;
 
1107
                }
 
1108
 
 
1109
                fileIObusy = false;
 
1110
 
 
1111
                Temp->PackLength = 0;
 
1112
                Temp->Pos = 0;
 
1113
                Temp->RealLength = 0;
 
1114
                Temp->VFS_Offset = 0;
 
1115
 
 
1116
                // заносим имя файла
 
1117
                Temp->Name = 0;
 
1118
                Temp->Name = new char[strlen(FileName)+1]; if (Temp->Name == 0) return 0;
 
1119
                strcpy(Temp->Name, FileName);
 
1120
 
 
1121
                // открываем физ. файл, проверка в детекте...
 
1122
                SDL_RWops * fTEMP = SDL_RWFromFile(FileName, "rb");
 
1123
 
 
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);
 
1129
 
 
1130
                // резервируем память
 
1131
                Temp->Data = 0;
 
1132
                Temp->Data = new BYTE[Temp->RealLength]; if (Temp->Data == 0) return 0;
 
1133
 
 
1134
                // плолучаем данные...
 
1135
                SDL_RWread(fTEMP, Temp->Data, 1, Temp->RealLength);
 
1136
                SDL_RWclose(fTEMP);
 
1137
 
 
1138
                // передаем указатель на структуру...
 
1139
                return Temp;
 
1140
        }
 
1141
 
 
1142
 
 
1143
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1144
        // файл в VFS , подготовка данных и передача указателя на структуру
 
1145
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1146
        if (ResTMP == VFS_FILE_VFS)
 
1147
        {
 
1148
                // Начальная подготовка структуры списка...
 
1149
                eFILE *Temp = 0;
 
1150
                Temp = new eFILE; if (Temp == 0) return 0;
 
1151
 
 
1152
                // возможно используется многопоточность, смотрим чтобы не портить данные
 
1153
                while (fileIObusy) SDL_Delay(0);
 
1154
                // говорим, что работаем с это процедурой
 
1155
                fileIObusy = true;
 
1156
 
 
1157
                // первый в списке...
 
1158
                if (EndFileVFS == 0)
 
1159
                {
 
1160
                        Temp->Prev = 0;
 
1161
                        Temp->Next = 0;
 
1162
                        StartFileVFS = Temp;
 
1163
                        EndFileVFS = Temp;
 
1164
                }
 
1165
                else // продолжаем заполнение...
 
1166
                {
 
1167
                        Temp->Prev = EndFileVFS;
 
1168
                        Temp->Next = 0;
 
1169
                        EndFileVFS->Next = Temp;
 
1170
                        EndFileVFS = Temp;
 
1171
                }
 
1172
 
 
1173
                fileIObusy = false;
 
1174
 
 
1175
                Temp->PackLength = 0;
 
1176
                Temp->Pos = 0;
 
1177
                Temp->RealLength = 0;
 
1178
                Temp->VFS_Offset = 0;
 
1179
 
 
1180
                Temp->Name = 0;
 
1181
                Temp->Name = new char[strlen(FileName)+1]; if (Temp->Name == 0) return 0;
 
1182
                strcpy(Temp->Name, FileName);
 
1183
 
 
1184
 
 
1185
 
 
1186
                // находим указатель на запись в таблице файлов VFS
 
1187
                eVFS_Entry *OutputFile = 0;
 
1188
                eVFS_Entry *Tmp = StarVFSArray;
 
1189
                while (Tmp != 0 && OutputFile == 0)
 
1190
                {
 
1191
                        eVFS_Entry *Tmp1 = Tmp->Next;
 
1192
 
 
1193
                        if(vw_strcmp(Temp->Name, Tmp->Name) == 0)
 
1194
                        {
 
1195
                                // нашли
 
1196
                                OutputFile = Tmp;
 
1197
                        }
 
1198
 
 
1199
                        Tmp = Tmp1;
 
1200
                }
 
1201
                if (OutputFile == 0) return 0;
 
1202
 
 
1203
 
 
1204
                Temp->PackLength = OutputFile->Length;
 
1205
                Temp->VFS_Offset = OutputFile->Offset;
 
1206
 
 
1207
                // резервируем память
 
1208
                Temp->Data = 0;
 
1209
                Temp->Data = new BYTE[Temp->PackLength]; if (Temp->Data == 0) return 0;
 
1210
 
 
1211
 
 
1212
                // возможно используется многопоточность, смотрим чтобы не портить данные
 
1213
                while (VFSfileIObusy) SDL_Delay(0);
 
1214
                // говорим, что работаем с это процедурой
 
1215
                VFSfileIObusy = true;
 
1216
 
 
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;
 
1221
 
 
1222
                VFSfileIObusy = false;
 
1223
 
 
1224
 
 
1225
 
 
1226
                // используем сжатие?
 
1227
                BYTE *srcVFS = 0;
 
1228
                BYTE *dstVFS = 0;
 
1229
                int ssizeVFS = 0;
 
1230
                int dsizeVFS = 0;
 
1231
 
 
1232
                if (!((OutputFile->ArhKey[0]=='0')&(strlen(OutputFile->ArhKey)==1)))
 
1233
                {
 
1234
                        for (size_t i=0; i<OutputFile->ArhKeyLen;i++)
 
1235
                        {
 
1236
                                char S = OutputFile->ArhKey[i];
 
1237
                                size_t cur_i = OutputFile->ArhKeyLen-1;
 
1238
 
 
1239
                                if (S == VFS_DATA_ARH_RLE)
 
1240
                                {
 
1241
                                        ssizeVFS = Temp->RealLength;
 
1242
                                        srcVFS = Temp->Data;
 
1243
 
 
1244
                                        if (i == cur_i)
 
1245
                                                vw_RLEtoDATA(OutputFile->RealLength, &dstVFS, srcVFS, &dsizeVFS, ssizeVFS);
 
1246
                                        else
 
1247
                                                vw_RLEtoDATA(0, &dstVFS, srcVFS, &dsizeVFS, ssizeVFS);
 
1248
                                        srcVFS = 0;
 
1249
                                        Temp->RealLength = dsizeVFS;
 
1250
                                        if (Temp->Data != 0){delete [] Temp->Data; Temp->Data = 0;}
 
1251
                                        Temp->Data = dstVFS;
 
1252
                                        dstVFS = 0;
 
1253
                                }
 
1254
                                if (S == VFS_DATA_ARH_HAFF)
 
1255
                                {
 
1256
                                        ssizeVFS = Temp->RealLength;
 
1257
                                        srcVFS = Temp->Data;
 
1258
 
 
1259
                                        if (i == cur_i)
 
1260
                                                vw_HAFFtoDATA(OutputFile->RealLength, &dstVFS, srcVFS, &dsizeVFS, ssizeVFS);
 
1261
                                        else
 
1262
                                                vw_HAFFtoDATA(0, &dstVFS, srcVFS, &dsizeVFS, ssizeVFS);
 
1263
                                        srcVFS = 0;
 
1264
                                        Temp->RealLength = dsizeVFS;
 
1265
                                        if (Temp->Data != 0){delete [] Temp->Data; Temp->Data = 0;}
 
1266
                                        Temp->Data = dstVFS;
 
1267
                                        dstVFS = 0;
 
1268
                                }
 
1269
                        }
 
1270
                }
 
1271
 
 
1272
                // передаем указатель на структуру...
 
1273
                return Temp;
 
1274
        }
 
1275
 
 
1276
 
 
1277
 
 
1278
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1279
        // в системе нет такого файла, или какие-то проблемы
 
1280
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1281
FOP_ERR:
 
1282
        fileIObusy = false;
 
1283
        return 0;
 
1284
}
 
1285
 
 
1286
 
 
1287
 
 
1288
 
 
1289
 
 
1290
 
 
1291
 
 
1292
 
 
1293
 
 
1294
 
 
1295
//------------------------------------------------------------------------------------
 
1296
// Закрытие файла в VFS
 
1297
//------------------------------------------------------------------------------------
 
1298
int vw_fclose(eFILE *stream)
 
1299
{
 
1300
 
 
1301
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1302
        // файл не открыли...закрывать нечего...
 
1303
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1304
        if (stream == 0) return -1;
 
1305
 
 
1306
        // возможно используется многопоточность, смотрим чтобы не портить данные
 
1307
        while (fileIObusy) SDL_Delay(0);
 
1308
        // говорим, что работаем с это процедурой
 
1309
        fileIObusy = true;
 
1310
 
 
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;}
 
1316
 
 
1317
 
 
1318
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1319
        // Устанавливаем все у начальное состояние
 
1320
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1321
    stream->PackLength = 0;
 
1322
        stream->Pos = 0;
 
1323
        stream->RealLength = 0;
 
1324
        stream->VFS_Offset =0;
 
1325
 
 
1326
 
 
1327
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1328
        // переустанавливаем указатели
 
1329
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1330
 
 
1331
 
 
1332
        if (StartFileVFS == stream) StartFileVFS = stream->Next;
 
1333
        if (EndFileVFS == stream) EndFileVFS = stream->Prev;
 
1334
 
 
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;
 
1339
 
 
1340
        if (stream != 0){delete stream; stream = 0;}
 
1341
 
 
1342
 
 
1343
        fileIObusy = false;
 
1344
        return 0;
 
1345
}
 
1346
 
 
1347
 
 
1348
 
 
1349
 
 
1350
 
 
1351
 
 
1352
 
 
1353
 
 
1354
 
 
1355
 
 
1356
 
 
1357
 
 
1358
 
 
1359
 
 
1360
 
 
1361
 
 
1362
 
 
1363
//------------------------------------------------------------------------------------
 
1364
// чтение блока данных из файла в VFS
 
1365
//------------------------------------------------------------------------------------
 
1366
int eFILE::fread(void *buffer, size_t size, size_t count)
 
1367
{
 
1368
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1369
        // проверки
 
1370
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1371
        if (buffer == 0) return -1;
 
1372
        if (Data == 0) return -1;
 
1373
 
 
1374
        // Кол-во успешно считанных раз
 
1375
        int SecCount = 0;
 
1376
 
 
1377
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1378
        // считываем данные
 
1379
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
1380
        for (size_t i=0; i<count; i++)
 
1381
        {
 
1382
                // если можем прочитать следующий блок size размера - читаем
 
1383
                if (size <= (unsigned int)(RealLength - Pos))
 
1384
                {
 
1385
                        // считываем байты
 
1386
                        memcpy((BYTE*)buffer + SecCount*size, Data + Pos, size);
 
1387
                        // передвигаем текущий указатель
 
1388
                        Pos += size;
 
1389
                        // устанавливаем успешное чтение
 
1390
                        SecCount++;
 
1391
                }
 
1392
                // иначе, уже достигли конца файла - выходим из цикла
 
1393
                else break;
 
1394
        }
 
1395
 
 
1396
        return SecCount;
 
1397
}
 
1398
 
 
1399
 
 
1400
 
 
1401
 
 
1402
 
 
1403
 
 
1404
//------------------------------------------------------------------------------------
 
1405
// поиск (установка текущей позиции)
 
1406
//------------------------------------------------------------------------------------
 
1407
int eFILE::fseek(long offset, int origin)
 
1408
{
 
1409
        // изменяем значение указателя, согласно origin...
 
1410
        switch (origin)
 
1411
        {
 
1412
                case SEEK_CUR:
 
1413
                {
 
1414
                        if (Pos + offset > RealLength) return 1;
 
1415
                        Pos += offset;
 
1416
                        break;
 
1417
                }
 
1418
                case SEEK_END:
 
1419
                {
 
1420
                        if (RealLength-offset < 0) return 1;
 
1421
                        Pos = RealLength-offset;
 
1422
                        break;
 
1423
                }
 
1424
                case SEEK_SET:
 
1425
                {
 
1426
                        if (offset < 0 || offset > RealLength) return 1;
 
1427
                        Pos = offset;
 
1428
                        break;
 
1429
                }
 
1430
        }
 
1431
 
 
1432
        return 0;
 
1433
}
 
1434
 
 
1435
 
 
1436
 
 
1437
 
 
1438
//------------------------------------------------------------------------------------
 
1439
// получить текущую позицию указателя
 
1440
//------------------------------------------------------------------------------------
 
1441
long eFILE::ftell()
 
1442
{
 
1443
        return Pos;
 
1444
}
 
1445
 
 
1446
 
 
1447
 
 
1448
 
 
1449
//------------------------------------------------------------------------------------
 
1450
// узнаем, достигли конца файла или нет
 
1451
//------------------------------------------------------------------------------------
 
1452
int eFILE::feof()
 
1453
{
 
1454
        // если указатель больше или равен длине файла - значит он уже за массивом данных файла
 
1455
        if (Pos >= RealLength-1) return 1;
 
1456
        // иначе - все ок, еще можем читать файл
 
1457
        return 0;
 
1458
}
 
1459
 
 
1460
 
 
1461
 
 
1462
 
 
1463
//------------------------------------------------------------------------------------
 
1464
// Get string from stream
 
1465
//------------------------------------------------------------------------------------
 
1466
char *eFILE::fgets(char *str, int num)
 
1467
{
 
1468
        // проверка первая, не читаем больше, чем у нас длина файла
 
1469
        if (Pos+num >= RealLength-1) num = (RealLength-1)-Pos;
 
1470
 
 
1471
        for (int i=0; i<num; i++)
 
1472
        {
 
1473
                str[i] = Data[Pos];
 
1474
                Pos++;
 
1475
                // конец строки, нужно выйти
 
1476
                if (Data[Pos-1] == '\n') return str;
 
1477
        }
 
1478
 
 
1479
        return str;
 
1480
}
 
1481
 
 
1482
 
 
1483
 
 
1484
 
 
1485