00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00049 #include <string>
00050
00051 #include "zlib.h"
00052
00053 #include "omicron/internal.h"
00054 #include "omicron/file.h"
00055 #include "omicron/list.h"
00056 #include "omicron/array.h"
00057
00058
00059
00060 #undef DBGSTAMP
00061 #define DBGSTAMP
00062
00063
00064
00065
00066 static const char _pak_mark1[] = "-@@A";
00067 static const char _pak_mark2[] = "-@PK";
00068 static char _pak_mark[9];
00069 static ulong attachedpakpos = 0;
00070
00071
00072
00073
00074
00075
00076
00077 file_manager_c::file_manager_c()
00078 {
00079 int i;
00080
00081 SafeDelete(gv.fileman);
00082
00083 gv.fileman = this;
00084 async_files = new list_c<file_t>;
00085 files = new array_c<file_t>;
00086 pak_names = new array_c<char>;
00087
00088
00089 for (i=0; i<8; i++)
00090 _pak_mark[i] = i%2?_pak_mark2[i/2]:_pak_mark1[i/2];
00091
00092 _pak_mark[i] = 0;
00093
00094 FILE *f = fopen(gv.init.argv[0], "rb");
00095
00096 if (f)
00097 {
00098 ulong fit = 0;
00099 ulong p = 0;
00100 char ch = 0;
00101
00102 ch = fgetc(f);
00103
00104 while(!feof(f))
00105 {
00106 if (ch==_pak_mark[fit])
00107 fit++;
00108 else
00109 fit = 0;
00110
00111 if (fit == 8)
00112 break;
00113
00114 ch = fgetc(f);
00115 p++;
00116 }
00117
00118 if (fit == 8)
00119 attachedpakpos = p+1;
00120 else
00121 attachedpakpos = 0;
00122
00123 if (attachedpakpos)
00124 _log_printf(MSG_DEBUG, "attached pak found at %08x", attachedpakpos);
00125 else
00126 _log_printf(MSG_DEBUG, "attached pak not found");
00127
00128 fclose(f);
00129 }
00130
00131 sprintf(datadir, "data");
00132 }
00133
00134 file_manager_c::~file_manager_c()
00135 {
00136 AssertThis;
00137
00138 close_paks();
00139
00140 for (slong i=0; i<files->get_count(); i++)
00141 {
00142 file_t *f = files->get(i);
00143 if (f) close(f);
00144 }
00145
00146 SafeDelete(files);
00147 SafeDelete(pak_names);
00148 SafeDelete(async_files);
00149 gv.fileman = NULL;
00150 }
00151
00152
00153
00154
00155
00156
00157
00158 file_t *
00159 file_manager_c::load_from_disk
00160 (
00161 const char *filename,
00162 bool async
00163 )
00164 {
00165 AssertThisV;
00166
00167 FILE *f;
00168 ulong s;
00169 file_t *file;
00170 std::string szFile;
00171
00172 szFile = datadir;
00173 szFile += "/";
00174 szFile += filename;
00175
00176 #if defined(WIN32)
00177 int i;
00178
00179 for (i=0; i<szFile.length(); i++)
00180 if (szFile.at(i)=='/')
00181 szFile.replace(i,1,"\\");
00182 #endif
00183
00184 _log_printf(MSG_DEBUG, "trying to load file '%s' from disk", szFile.c_str());
00185
00186 file = new file_t;
00187 AssertReturnValue1(file, NULL);
00188
00189 file->asyncloading = async?1:0;
00190 file->size = 0;
00191 file->pos = 0;
00192 file->buf = NULL;
00193
00194
00195 f = fopen(szFile.c_str(), "rb");
00196 if (!f)
00197 {
00198 _log_printf(MSG_DEBUG, "file not found");
00199 SafeDelete(file);
00200 return NULL;
00201 }
00202
00203
00204 fseek(f, 0, SEEK_END);
00205 s = ftell(f);
00206 fseek(f, 0, SEEK_SET);
00207 file->size = s;
00208
00209 if (async)
00210 {
00211 file->f = f;
00212 async_files->add_first(file);
00213 }
00214 else
00215 {
00216
00217 file->buf = new char[s];
00218 if (!file->buf)
00219 {
00220 fclose(f);
00221 SafeDelete(file);
00222 return NULL;
00223 }
00224 fread( file->buf, 1, (unsigned)s, f );
00225 fclose(f);
00226
00227 file->f = NULL;
00228 }
00229
00230 _log_printf(MSG_NORMAL, "successfully loaded file: %s", szFile.c_str());
00231 file->pos = 0;
00232 return file;
00233 }
00234
00235 file_t *
00236 file_manager_c::load_from_pak
00237 (
00238 const char *filename
00239 )
00240 {
00241 AssertThisV;
00242
00243 file_t *file = NULL;
00244
00245 std::string szFile;
00246
00247 szFile = filename;
00248
00249 #if defined(WIN32)
00250 int i;
00251
00252 for (i=0; i<szFile.length(); i++)
00253 if (szFile.at(i)=='\\')
00254 szFile.replace(i,1,"/");
00255 #endif
00256
00257 _log_printf(MSG_DEBUG, "trying to load file '%s' from pak", szFile.c_str());
00258
00259 for ( slong pak=0; pak<pak_names->get_count(); pak++)
00260 {
00261 char *pname = pak_names->get(pak);
00262
00263 if (!pname)
00264 break;
00265
00266 FILE *f = fopen(pname, "rb");
00267
00268 pak_header_t h;
00269 fileentry_t fe;
00270
00271 fread(&h, sizeof(h), 1, f);
00272
00273 for (ulong e = 0; e<h.entrycount; e++)
00274 {
00275 fread(&fe, sizeof(fe), 1, f);
00276 if (!strcmpi( szFile.c_str(), fe.filename ))
00277 {
00278 file = create();
00279
00280 file->size = fe.realsize;
00281
00282
00283 file->buf = new char[fe.realsize];
00284
00285 if (!file->buf)
00286 {
00287 SafeDelete(file);
00288 continue;
00289 }
00290
00291
00292 if (fe.size ==
00293 fe.realsize)
00294 {
00295 fseek(f, fe.offset, SEEK_SET);
00296 fread(file->buf, 1, file->size, f);
00297
00298 fclose(f);
00299 return file;
00300 }
00301 else
00302 {
00303 char *tmpbuf = new char[fe.size];
00304 fseek(f, fe.offset, SEEK_SET);
00305 fread(tmpbuf, 1, fe.size, f);
00306
00307
00308 uncompress((uchar*)file->buf,
00309 (ulong*)&file->size,
00310 (uchar*)(tmpbuf),
00311 (ulong)fe.size);
00312
00313 fclose(f);
00314 SafeArrayDelete(tmpbuf);
00315
00316 _log_printf(MSG_NORMAL,
00317 "successfully loaded file: %s", szFile.c_str());
00318 return file;
00319 }
00320 }
00321 }
00322
00323 fclose(f);
00324 }
00325
00326
00327 if (attachedpakpos)
00328 {
00329 FILE *f = fopen(gv.init.argv[0], "rb");
00330
00331 fseek(f, attachedpakpos, SEEK_SET);
00332
00333 pak_header_t h;
00334 fileentry_t fe;
00335
00336 fread(&h, sizeof(h), 1, f);
00337 for (ulong e = 0; e<h.entrycount; e++)
00338 {
00339 fread(&fe, sizeof(fe), 1, f);
00340 if (!strcmpi( szFile.c_str(), fe.filename ))
00341 {
00342 file = create();
00343
00344 file->size = fe.realsize;
00345
00346
00347 file->buf = new char[fe.realsize];
00348
00349 if (!file->buf)
00350 {
00351 SafeDelete(file);
00352 continue;
00353 }
00354
00355
00356 if (fe.size ==
00357 fe.realsize)
00358 {
00359 fseek(f, fe.offset+attachedpakpos, SEEK_SET);
00360 fread(file->buf, 1, file->size, f);
00361
00362 fclose(f);
00363 return file;
00364 }
00365 else
00366 {
00367 char *tmpbuf = new char[fe.size];
00368 fseek(f, fe.offset+attachedpakpos, SEEK_SET);
00369 fread(tmpbuf, 1, fe.size, f);
00370
00371
00372 uncompress((uchar*)file->buf,
00373 (ulong*)&file->size,
00374 (uchar*)(tmpbuf),
00375 (ulong)fe.size);
00376
00377 fclose(f);
00378 SafeArrayDelete(tmpbuf);
00379
00380 _log_printf(MSG_NORMAL,
00381 "successfully loaded file: %s", szFile.c_str());
00382 return file;
00383 }
00384 }
00385 }
00386
00387 fclose(f);
00388 }
00389
00390 if (file) SafeDelete(file);
00391 return NULL;
00392 }
00393
00394
00395 file_t *
00396 file_manager_c::load
00397 (
00398 const char *filename,
00399 bool async
00400 )
00401 {
00402 AssertThisV;
00403
00404 file_t *f;
00405
00406
00407 f = load_from_disk( filename, async );
00408
00409 if (f) return f;
00410
00411
00412 f = load_from_pak( filename );
00413
00414 if (!f)
00415 _log_printf(MSG_WARNING, "file not found: %s", filename);
00416
00417 return f;
00418 }
00419
00420 ulong
00421 file_manager_c::load_pak
00422 (
00423 const char *filename
00424 )
00425 {
00426 AssertThisV;
00427
00428 char *str = new char[strlen(filename)+1+strlen(datadir)+1];
00429
00430 sprintf(str, "%s/%s", datadir, filename);
00431 _convert_file_path(str);
00432
00433 FILE *f = fopen(str, "rb");
00434 if (!f)
00435 {
00436 _log_printf(MSG_NORMAL, "loadpak() - file not found - '%s'", str);
00437
00438 SafeArrayDelete(str);
00439 return 0;
00440 }
00441 fclose(f);
00442
00443 pak_names->add(str);
00444
00445 return 1;
00446 }
00447
00448 void
00449 file_manager_c::save
00450 (
00451 file_t *file,
00452 const char *filename
00453 )
00454 {
00455 AssertThis;
00456
00457 std::string fname;
00458
00459 AssertReturn2(file, filename);
00460
00461 fname = filename;
00462
00463 #if defined(WIN32)
00464 int i;
00465
00466 for (i=0; i<fname.length(); i++)
00467 if (fname.at(i)=='/')
00468 fname.replace(i,1,"\\");
00469 #endif
00470
00471 FILE *f = fopen(fname.c_str(), "wb");
00472 if (!f) return;
00473
00474 if (file->buf)
00475 fwrite(file->buf, 1, file->size, f);
00476
00477 fclose(f);
00478 }
00479
00480 void
00481 file_manager_c::resize
00482 (
00483 file_t *file,
00484 ulong newsize
00485 )
00486 {
00487 AssertThis;
00488
00489 if (!file)
00490 return;
00491
00492 if (!newsize)
00493 {
00494 SafeArrayDelete(file->buf);
00495 file->size = file->pos = 0;
00496 return;
00497 }
00498
00499 char *buf = new char[newsize];
00500 long copysize = newsize>file->size?file->size:newsize;
00501
00502 memcpy(buf, file->buf, copysize);
00503 file->size = newsize;
00504 SafeArrayDelete(file->buf);
00505 file->buf = buf;
00506 }
00507
00508 file_t *
00509 file_manager_c::create
00510 (
00511 )
00512 {
00513 AssertThisV;
00514
00515 file_t *f;
00516
00517 f = new file_t;
00518 AssertReturnValue1(f, NULL);
00519
00520 f->buf = NULL;
00521 f->pos = 0;
00522 f->size = 0;
00523 f->asyncloading = 0;
00524
00525 return f;
00526 }
00527
00528
00529 void
00530 file_manager_c::close
00531 (
00532 file_t *file
00533 )
00534 {
00535 AssertThis;
00536
00537 AssertReturn1(file);
00538
00539 files->remove_ptr(file);
00540 SafeArrayDelete(file->buf);
00541 SafeDelete(file);
00542 }
00543
00544 ulong
00545 file_manager_c::tell
00546 (
00547 file_t *f
00548 )
00549 {
00550 AssertThisV;
00551
00552 return f->pos;
00553 }
00554
00555 void
00556 file_manager_c::close_paks
00557 ()
00558 {
00559 AssertThis;
00560
00561 for (slong i=0; i<pak_names->get_count(); i++)
00562 {
00563 char *pname = pak_names->get(i);
00564 if (!pname) continue;
00565
00566 _log_printf(MSG_DEBUG2, "closing pak file %u (%s)", i, pname);
00567 pak_names->remove(i);
00568 SafeArrayDelete(pname);
00569 }
00570 }
00571
00572 void
00573 file_manager_c::unload_pak
00574 (
00575 ulong n
00576 )
00577 {
00578 AssertThis;
00579
00580 char *pname = pak_names->get(n);
00581 if (!pname) return;
00582
00583 _log_printf(MSG_DEBUG2, "closing pak file %u (%s)", n, pname);
00584 pak_names->remove(n);
00585 SafeArrayDelete(pname);
00586 }
00587
00588 ulong
00589 file_manager_c::seek
00590 (
00591 file_t *f,
00592 slong offset,
00593 ulong origin
00594 )
00595 {
00596 AssertThisV;
00597
00598 if (!f || !f->buf)
00599 return 0;
00600
00601 switch(origin)
00602 {
00603 case SEEK_CUR: f->pos += (slong)offset; break;
00604 case SEEK_END: f->pos = f->size-offset; break;
00605 case SEEK_SET: f->pos = offset; break;
00606 default: return 0;
00607 }
00608
00609 if (f->pos<0 || f->pos>f->size || !f->buf)
00610 return 0;
00611
00612 return 1;
00613 }
00614
00615 bool
00616 file_manager_c::eof
00617 (
00618 file_t *file
00619 )
00620 {
00621 AssertThisValue(true);
00622
00623 AssertReturnValue1(file, true);
00624
00625 return file->pos>=file->size;
00626 }
00627
00628 void
00629 file_manager_c::update
00630 ()
00631 {
00632 AssertThis;
00633
00634
00635 if (async_files)
00636 {
00637 file_t *f = (file_t *)async_files->get_first();
00638
00639
00640 while(f)
00641 {
00642 if (f->f)
00643 {
00644 ulong l = 0;
00645
00646 if (f->pos<f->size)
00647 {
00648
00649 l = fread(f->buf+f->pos, 1, 1024, f->f);
00650 f->pos += l;
00651 f = (file_t *)async_files->get_next();
00652 }
00653 else
00654 {
00655
00656 fclose(f->f);
00657
00658
00659 f->pos = 0;
00660 f->asyncloading = 0;
00661
00662
00663 async_files->remove(f);
00664 f = (file_t *)async_files->get_first();
00665 }
00666 }
00667 else
00668 {
00669
00670 f->pos = 0;
00671 f->asyncloading = 0;
00672 async_files->remove(f);
00673 f = (file_t *)async_files->get_first();
00674 }
00675 }
00676 }
00677 }