00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifdef HAVE_CONFIG_H
00022 # include <config.h>
00023 #endif
00024
00025 #ifdef WIN32
00026 #ifndef UNDER_CE
00027 #include <io.h>
00028 #endif
00029 #endif
00030
00031 #ifndef ALPHA_LINUX_CXX
00032 # include <fstream>
00033 # include <cstdio>
00034 # include <cstdlib>
00035 # include <cstring>
00036 # include <ctime>
00037 #endif
00038
00039 #if (defined(XWIN) || defined(BEOS))
00040 #include <sys/stat.h>
00041 #elif defined(MACOS)
00042 #include <stat.h>
00043 #endif
00044
00045 #include "exceptions.h"
00046 #include "fnames.h"
00047 #include "gamewin.h"
00048 #include "gameclk.h"
00049 #include "gamemap.h"
00050 #include "utils.h"
00051 #include "gump_utils.h"
00052 #include "game.h"
00053 #include "Flex.h"
00054 #include "databuf.h"
00055 #include "Newfile_gump.h"
00056 #include "Yesno_gump.h"
00057 #include "actors.h"
00058 #include "party.h"
00059 #include "version.h"
00060
00061 #ifndef UNDER_CE
00062 using std::cerr;
00063 using std::cout;
00064 using std::endl;
00065 using std::ifstream;
00066 using std::ios;
00067 using std::localtime;
00068 using std::memset;
00069 using std::ofstream;
00070 using std::ostream;
00071 using std::size_t;
00072 using std::strchr;
00073 using std::strcmp;
00074 using std::strcpy;
00075 using std::strlen;
00076 using std::strncpy;
00077 using std::time_t;
00078 using std::tm;
00079 using std::time_t;
00080 #endif
00081
00082
00083 extern int save_compression;
00084
00085
00086
00087
00088
00089
00090
00091 void Game_window::restore_gamedat
00092 (
00093 const char *fname
00094 )
00095 {
00096
00097 char *id = get_game_identity(fname);
00098 char *static_identity = get_game_identity(INITGAME);
00099
00100 if(!id || (*id != '*' && strcmp(static_identity, id) != 0))
00101 {
00102 std::string msg("Wrong identity '");
00103 msg += id; msg += "'. Open anyway?";
00104 int ok = Yesno_gump::ask(msg.c_str());
00105 if (!ok)
00106 return;
00107 }
00108
00109 #ifdef HAVE_ZIP_SUPPORT
00110 if (restore_gamedat_zip(fname) != false)
00111 return;
00112 #endif
00113
00114 ifstream in_stream;
00115
00116 #ifdef RED_PLASMA
00117
00118 setup_load_palette();
00119 #endif
00120
00121 U7mkdir("<GAMEDAT>", 0755);
00122
00123
00124 try
00125 {
00126 U7open(in_stream, fname);
00127 }
00128 catch(const file_exception & f)
00129 {
00130 if (!Game::is_editing())
00131 throw f;
00132 std::cerr << "Warning (map-editing): Couldn't open '" <<
00133 fname << "'" << endl;
00134 return;
00135 }
00136
00137 StreamDataSource in(&in_stream);
00138
00139 U7remove (USEDAT);
00140 U7remove (USEVARS);
00141 U7remove (U7NBUF_DAT);
00142 U7remove (NPC_DAT);
00143 U7remove (MONSNPCS);
00144 U7remove (FLAGINIT);
00145 U7remove (GWINDAT);
00146 U7remove (IDENTITY);
00147 U7remove (GSCHEDULE);
00148 U7remove ("<STATIC>/flags.flg");
00149 U7remove (GSCRNSHOT);
00150 U7remove (GSAVEINFO);
00151 U7remove (GNEWGAMEVER);
00152 U7remove (GEXULTVER);
00153 U7remove (KEYRINGDAT);
00154
00155 cout.flush();
00156
00157 in.seek(0x54);
00158 int numfiles = in.read4();
00159 in.seek(0x80);
00160
00161 long *finfo = new long[2*numfiles];
00162 int i;
00163 for (i = 0; i < numfiles; i++)
00164 {
00165 finfo[2*i] = in.read4();
00166 finfo[2*i + 1] = in.read4();
00167 }
00168 for (i = 0; i < numfiles; i++)
00169 {
00170
00171 int len = finfo[2*i + 1] - 13;
00172 if (len <= 0)
00173 continue;
00174 in.seek(finfo[2*i]);
00175 char fname[50];
00176 strcpy(fname, GAMEDAT);
00177 in.read(&fname[sizeof(GAMEDAT) - 1], 13);
00178 int namelen = strlen(fname);
00179
00180 if (fname[namelen - 1] == '.')
00181 fname[namelen - 1] = 0;
00182 ofstream out;
00183 U7open(out, fname);
00184
00185 char *buf = new char[len];
00186 in.read(buf, len);
00187 out.write(buf, len);
00188 delete [] buf;
00189 if (!out.good())
00190 abort("Error writing '%s'.", fname);
00191 out.close();
00192 CYCLE_RED_PLASMA();
00193 }
00194 delete [] finfo;
00195 cout.flush();
00196
00197 #ifdef RED_PLASMA
00198 load_palette_timer = 0;
00199 #endif
00200 }
00201
00202
00203
00204
00205
00206
00207
00208 void Game_window::restore_gamedat
00209 (
00210 int num
00211 )
00212 {
00213 char fname[50];
00214 snprintf(fname, 50, SAVENAME, num,
00215 Game::get_game_type() == BLACK_GATE ? "bg" : "si");
00216 restore_gamedat(fname);
00217 }
00218
00219
00220
00221
00222 static const char *bgsavefiles[] = {
00223 GSCRNSHOT, GSAVEINFO,
00224 IDENTITY,
00225 GEXULTVER, GNEWGAMEVER,
00226 NPC_DAT, MONSNPCS,
00227 USEVARS, USEDAT,
00228 FLAGINIT, GWINDAT,
00229 GSCHEDULE
00230 };
00231 static const int bgnumsavefiles = sizeof(bgsavefiles)/sizeof(bgsavefiles[0]);
00232
00233 static const char *sisavefiles[] = {
00234 GSCRNSHOT, GSAVEINFO,
00235 IDENTITY,
00236 GEXULTVER, GNEWGAMEVER,
00237 NPC_DAT, MONSNPCS,
00238 USEVARS, USEDAT,
00239 FLAGINIT, GWINDAT,
00240 GSCHEDULE, KEYRINGDAT
00241 };
00242 static const int sinumsavefiles = sizeof(sisavefiles)/sizeof(sisavefiles[0]);
00243
00244
00245
00246
00247
00248
00249
00250
00251 static long Savefile
00252 (
00253 ostream& out,
00254 const char *fname
00255 )
00256 {
00257 ifstream in_stream;
00258 try {
00259 U7open(in_stream, fname);
00260 } catch (exult_exception& e) {
00261 if (Game::is_editing())
00262 return 0;
00263 throw e;
00264 }
00265 StreamDataSource in(&in_stream);
00266 long len = in.getSize();
00267 in.seek(0);
00268 char namebuf[13];
00269 memset(namebuf, 0, sizeof(namebuf));
00270 const char *base = strchr(fname, '/');
00271 if (!base)
00272 base = strchr(fname, '\\');
00273 if (base)
00274 base++;
00275 else
00276 base = fname;
00277 strncpy(namebuf, base, sizeof(namebuf));
00278 out.write(namebuf, sizeof(namebuf));
00279 char *buf = new char[len];
00280 in.read(buf, len);
00281 out.write(buf, len);
00282 delete [] buf;
00283 if (!in_stream.good())
00284 throw file_read_exception(fname);
00285 return len + 13;
00286 }
00287
00288 static long SavefileFromDataSource(
00289 ostream& out,
00290 DataSource& source,
00291 const char *fname
00292 )
00293 {
00294 long len = source.getSize();
00295 char namebuf[13];
00296 memset(namebuf, 0, sizeof(namebuf));
00297 strncpy(namebuf, fname, sizeof(namebuf));
00298 out.write(namebuf, sizeof(namebuf));
00299 char *buf = new char[len];
00300 source.read(buf, len);
00301 out.write(buf, len);
00302 delete [] buf;
00303 return len + 13;
00304 }
00305
00306
00307
00308
00309
00310
00311
00312 void Game_window::save_gamedat
00313 (
00314 const char *fname,
00315 const char *savename
00316 )
00317 {
00318
00319
00320 #ifdef HAVE_ZIP_SUPPORT
00321 if (save_compression > 0 && save_gamedat_zip(fname, savename) != false)
00322 return;
00323 #endif
00324
00325
00326 int numsavefiles = (Game::get_game_type() == BLACK_GATE) ?
00327 bgnumsavefiles : sinumsavefiles;
00328 const char **savefiles = (Game::get_game_type() == BLACK_GATE) ?
00329 bgsavefiles : sisavefiles;
00330
00331 ofstream out;
00332 U7open(out, fname);
00333
00334 int count = 12*12 + numsavefiles;
00335
00336 Flex_writer flex(out, savename, count);
00337 int i;
00338 for (i = 0; i < numsavefiles; i++)
00339 {
00340 Savefile(out, savefiles[i]);
00341 flex.mark_section_done();
00342 }
00343
00344 for (int schunk = 0; schunk < 12*12; schunk++, i++)
00345 {
00346 char iname[80];
00347 Savefile(out, map->get_schunk_file_name(U7IREG,
00348 schunk, iname));
00349 flex.mark_section_done();
00350 }
00351 bool result = flex.close();
00352 if (!result)
00353 throw file_write_exception(fname);
00354 return;
00355 }
00356
00357
00358
00359
00360
00361
00362
00363 void Game_window::save_gamedat
00364 (
00365 int num,
00366 const char *savename
00367 )
00368 {
00369 char fname[50];
00370 snprintf(fname, 50, SAVENAME, num,
00371 Game::get_game_type() == BLACK_GATE ? "bg" : "si");
00372 save_gamedat(fname, savename);
00373 if (num >=0 && num < 10)
00374 {
00375 delete [] save_names[num];
00376 save_names[num] = newstrdup(savename);
00377 }
00378 }
00379
00380
00381
00382
00383 void Game_window::read_save_names
00384 (
00385 )
00386 {
00387 for (size_t i = 0; i < sizeof(save_names)/sizeof(save_names[0]); i++)
00388 {
00389 char fname[50];
00390 snprintf(fname, 50, SAVENAME, i,
00391 Game::get_game_type() == BLACK_GATE ? "bg" : "si");
00392 ifstream in;
00393 try
00394 {
00395 U7open(in, fname);
00396 char buf[0x50];
00397 memset(buf, 0, sizeof(buf));
00398 in.read(buf, sizeof(buf) - 1);
00399 if (in.good())
00400 save_names[i] = newstrdup(buf);
00401 else
00402 save_names[i] = newstrdup("");
00403 in.close();
00404 }
00405 catch(const file_exception & f)
00406 {
00407 save_names[i] = newstrdup("");
00408 }
00409 }
00410 }
00411
00412
00413 void Game_window::write_saveinfo()
00414 {
00415 ofstream out_stream;
00416 int i, j;
00417
00418 int save_count = 1;
00419
00420 try
00421 {
00422 ifstream in;
00423 U7open(in, GSAVEINFO);
00424
00425 StreamDataSource ds(&in);
00426 ds.skip(10);
00427 save_count += ds.read2();
00428
00429 in.close();
00430 }
00431 catch(const file_exception & f)
00432 {
00433 }
00434
00435 int party_size = party_man->get_count()+1;
00436
00437 time_t t = std::time(0);
00438 struct tm *timeinfo = localtime (&t);
00439
00440 U7open(out_stream, GSAVEINFO);
00441 StreamDataSource out(&out_stream);
00442
00443
00444
00445
00446 out.write1(timeinfo->tm_min);
00447 out.write1(timeinfo->tm_hour);
00448 out.write1(timeinfo->tm_mday);
00449 out.write1(timeinfo->tm_mon+1);
00450 out.write2(timeinfo->tm_year + 1900);
00451
00452
00453 out.write1(clock->get_minute());
00454 out.write1(clock->get_hour());
00455 out.write2(clock->get_day());
00456
00457 out.write2(save_count);
00458 out.write1(party_size);
00459
00460 out.write1(0);
00461
00462 out.write1(timeinfo->tm_sec);
00463
00464
00465 for (j = reinterpret_cast<long>(&(((SaveGame_Details *)0)->reserved0)); j < sizeof(SaveGame_Details); j++)
00466 out.write1(0);
00467
00468 for (i=0; i<party_size ; i++)
00469 {
00470 Actor *npc;
00471 if (i == 0)
00472 npc = main_actor;
00473 else
00474 npc = (Npc_actor *)get_npc(party_man->get_member(i-1));
00475
00476 char name[18];
00477 std::string namestr = npc->get_npc_name();
00478 strncpy (name, namestr.c_str(), 18);
00479 out.write(name, 18);
00480 out.write2(npc->get_shapenum());
00481
00482 out.write4(npc->get_property(Actor::exp));
00483 out.write4(npc->get_flags());
00484 out.write4(npc->get_flags2());
00485
00486 out.write1(npc->get_property(Actor::food_level));
00487 out.write1(npc->get_property(Actor::strength));
00488 out.write1(npc->get_property(Actor::combat));
00489 out.write1(npc->get_property(Actor::dexterity));
00490 out.write1(npc->get_property(Actor::intelligence));
00491 out.write1(npc->get_property(Actor::magic));
00492 out.write1(npc->get_property(Actor::mana));
00493 out.write1(npc->get_property(Actor::training));
00494
00495 out.write2(npc->get_property(Actor::health));
00496 out.write2(npc->get_shapefile());
00497
00498
00499 for (j = reinterpret_cast<long>(&(((SaveGame_Party *)0)->reserved1)); j < sizeof(SaveGame_Party); j++)
00500 out.write1(0);
00501 }
00502
00503 out_stream.close();
00504
00505
00506 Shape_file *map = create_mini_screenshot();
00507 U7open(out_stream, GSCRNSHOT);
00508 map->save(&out);
00509 out_stream.close();
00510 delete map;
00511
00512
00513
00514 U7open(out_stream, GEXULTVER);
00515 getVersionInfo(out_stream);
00516 out_stream.close();
00517
00518
00519 if (!U7exists(GNEWGAMEVER)) {
00520 U7open(out_stream, GNEWGAMEVER);
00521 out_stream << "Unknown" << endl;
00522 out_stream.close();
00523 }
00524 }
00525
00526
00527 void Game_window::read_saveinfo(DataSource *in,
00528 SaveGame_Details *&details,
00529 SaveGame_Party *& party)
00530 {
00531 int i;
00532 details = new SaveGame_Details;
00533
00534
00535
00536 details->real_minute = in->read1();
00537 details->real_hour = in->read1();
00538 details->real_day = in->read1();
00539 details->real_month = in->read1();
00540 details->real_year = in->read2();
00541
00542
00543
00544 details->game_minute = in->read1();
00545 details->game_hour = in->read1();
00546 details->game_day = in->read2();
00547
00548 details->save_count = in->read2();
00549 details->party_size = in->read1();
00550
00551 details->unused = in->read1();
00552
00553 details->real_second = in->read1();
00554
00555
00556 in->skip(sizeof(SaveGame_Details) - reinterpret_cast<long>(&(((SaveGame_Details *)0)->reserved0)));
00557
00558 party = new SaveGame_Party[details->party_size];
00559 for (i=0; i<8 && i<details->party_size ; i++)
00560 {
00561 in->read(party[i].name, 18);
00562 party[i].shape = in->read2();
00563
00564 party[i].exp = in->read4();
00565 party[i].flags = in->read4();
00566 party[i].flags2 = in->read4();
00567
00568 party[i].food = in->read1();
00569 party[i].str = in->read1();
00570 party[i].combat = in->read1();
00571 party[i].dext = in->read1();
00572 party[i].intel = in->read1();
00573 party[i].magic = in->read1();
00574 party[i].mana = in->read1();
00575 party[i].training = in->read1();
00576
00577 party[i].health = in->read2();
00578 party[i].shape_file = in->read2();
00579
00580
00581 in->skip (sizeof(SaveGame_Party) - reinterpret_cast<long>(&(((SaveGame_Party *)0)->reserved1)));
00582 }
00583 }
00584
00585 bool Game_window::get_saveinfo(int num, char *&name, Shape_file *&map, SaveGame_Details *&details, SaveGame_Party *& party)
00586 {
00587 char fname[50];
00588 snprintf(fname, 50, SAVENAME, num,
00589 Game::get_game_type() == BLACK_GATE ? "bg" : "si");
00590
00591
00592 #ifdef HAVE_ZIP_SUPPORT
00593 if (get_saveinfo_zip(fname, name, map, details, party) != false)
00594 return true;
00595 #endif
00596
00597 ifstream in_stream;
00598 U7open(in_stream, fname);
00599 StreamDataSource in(&in_stream);
00600
00601
00602 char buf[0x50];
00603 memset(buf, 0, sizeof(buf));
00604 in.read(buf, sizeof(buf) - 1);
00605 name = new char [strlen (buf)+1];
00606 strcpy (name, buf);
00607
00608
00609 if (!Flex::is_flex(&in)) return false;
00610
00611
00612 in.seek(0x54);
00613 int numfiles = in.read4();
00614 in.seek(0x80);
00615
00616 long *finfo = new long[2*numfiles];
00617 int i;
00618 for (i = 0; i < numfiles; i++)
00619 {
00620 finfo[2*i] = in.read4();
00621 finfo[2*i + 1] = in.read4();
00622 }
00623
00624
00625 for (i = 0; i < 2; i++)
00626 {
00627
00628 int len = finfo[2*i + 1] - 13;
00629 if (len <= 0)
00630 continue;
00631 in.seek(finfo[2*i]);
00632 char fname[50];
00633 strcpy(fname, GAMEDAT);
00634 in.read(&fname[sizeof(GAMEDAT) - 1], 13);
00635 int namelen = strlen(fname);
00636
00637 if (fname[namelen - 1] == '.')
00638 fname[namelen - 1] = 0;
00639
00640 if (!strcmp (fname, GSCRNSHOT))
00641 {
00642 char *buf = new char[len];
00643 in.read(buf, len);
00644 BufferDataSource ds(buf, len);
00645 map = new Shape_file(&ds);
00646 delete [] buf;
00647 }
00648 else if (!strcmp (fname, GSAVEINFO))
00649 {
00650 read_saveinfo (&in, details, party);
00651 }
00652
00653 }
00654 in_stream.close();
00655
00656 delete [] finfo;
00657
00658 return true;
00659 }
00660
00661 void Game_window::get_saveinfo(Shape_file *&map, SaveGame_Details *&details, SaveGame_Party *& party)
00662 {
00663 try
00664 {
00665 ifstream in;
00666 U7open(in, GSAVEINFO);
00667 StreamDataSource ds(&in);
00668 read_saveinfo (&ds, details, party);
00669 in.close();
00670 }
00671 catch(const file_exception & f)
00672 {
00673 details = NULL;
00674 party = NULL;
00675 }
00676
00677 try
00678 {
00679 ifstream in;
00680 U7open(in, GSCRNSHOT);
00681 StreamDataSource ds(&in);
00682 map = new Shape_file(&ds);
00683 in.close();
00684 }
00685 catch(const file_exception & f)
00686 {
00687
00688
00689 map = 0; map = 0;
00690 }
00691 }
00692
00693
00694
00695
00696
00697
00698
00699
00700 char *Game_window::get_game_identity(const char *savename)
00701 {
00702 char *game_identity = 0;
00703 #ifdef HAVE_ZIP_SUPPORT
00704 game_identity = get_game_identity_zip(savename);
00705 if (game_identity)
00706 return game_identity;
00707 #endif
00708 ifstream in_stream;
00709 try {
00710 U7open(in_stream, savename);
00711 } catch (const exult_exception &e) {
00712 if (Game::is_editing()) {
00713 std::string titlestr = Game::get_gametitle();
00714 return newstrdup(titlestr.c_str());
00715 }
00716 throw e;
00717 }
00718 StreamDataSource in(&in_stream);
00719
00720 in.seek(0x54);
00721 int numfiles = in.read4();
00722 in.seek(0x80);
00723
00724 sint32 *finfo = new sint32[2*numfiles];
00725 int i;
00726 for (i = 0; i < numfiles; i++)
00727 {
00728 finfo[2*i] = in.read4();
00729 finfo[2*i + 1] = in.read4();
00730 }
00731 for (i = 0; i < numfiles; i++)
00732 {
00733
00734 int len = finfo[2*i + 1] - 13;
00735 if (len <= 0)
00736 continue;
00737 in.seek(finfo[2*i]);
00738 char fname[50];
00739 in.read(fname, 13);
00740 if (!strcmp("identity",fname))
00741 {
00742 game_identity = new char[len];
00743 in.read(game_identity, len);
00744
00745 char *ptr = game_identity;
00746 for(; (*ptr!=0x1a && *ptr!=0x0d); ptr++)
00747 ;
00748 *ptr = 0;
00749 break;
00750 }
00751 }
00752 delete [] finfo;
00753 return game_identity;
00754 }
00755
00756
00757 #ifdef HAVE_ZIP_SUPPORT
00758
00759 #include "files/zip/unzip.h"
00760 #include "files/zip/zip.h"
00761
00762 static const char *remove_dir(const char *fname)
00763 {
00764 const char *base = strchr(fname, '/');
00765 if (!base)
00766 base = strchr(fname, '\\');
00767 if (base)
00768 return base+1;
00769
00770 return fname;
00771 }
00772
00773
00774 bool Game_window::get_saveinfo_zip(const char *fname, char *&name, Shape_file *&map, SaveGame_Details *&details, SaveGame_Party *& party)
00775 {
00776
00777 if (Flex::is_flex(fname)) return false;
00778
00779 std::string filestr = get_system_path(fname);
00780 unzFile unzipfile = unzOpen(filestr.c_str());
00781 if (!unzipfile) return false;
00782
00783
00784 char namebuf[0x50];
00785 if (unzGetGlobalComment(unzipfile, namebuf, 0x50) <= 0) strncpy (namebuf, "UNNAMED", 0x50);
00786 name = new char [strlen (namebuf)+1];
00787 strcpy (name, namebuf);
00788
00789
00790
00791 unz_file_info file_info;
00792 char *buf = 0;
00793
00794
00795 if (unzLocateFile(unzipfile, remove_dir(GSCRNSHOT), 2) == UNZ_OK)
00796 {
00797 unzGetCurrentFileInfo(unzipfile, &file_info, NULL, 0, NULL, 0, NULL, 0);
00798 buf = new char[file_info.uncompressed_size];
00799
00800 unzOpenCurrentFile(unzipfile);
00801 unzReadCurrentFile(unzipfile, buf, file_info.uncompressed_size);
00802 if (unzCloseCurrentFile(unzipfile) == UNZ_OK)
00803 {
00804 BufferDataSource ds(buf, file_info.uncompressed_size);
00805 map = new Shape_file(&ds);
00806 }
00807
00808 delete [] buf;
00809 }
00810
00811
00812 if (unzLocateFile(unzipfile, remove_dir(GSAVEINFO), 2) == UNZ_OK)
00813 {
00814 unzGetCurrentFileInfo(unzipfile, &file_info, NULL, 0, NULL, 0, NULL, 0);
00815 buf = new char[file_info.uncompressed_size];
00816
00817 unzOpenCurrentFile(unzipfile);
00818 unzReadCurrentFile(unzipfile, buf, file_info.uncompressed_size);
00819 if (unzCloseCurrentFile(unzipfile) == UNZ_OK)
00820 {
00821 BufferDataSource ds(buf, file_info.uncompressed_size);
00822 read_saveinfo (&ds, details, party);
00823 }
00824
00825 delete [] buf;
00826 }
00827
00828 unzClose (unzipfile);
00829
00830 return true;
00831 }
00832
00833
00834
00835 bool Game_window::Restore_level2 (void *uzf)
00836 {
00837 unzFile unzipfile = static_cast<unzFile>(uzf);
00838
00839 char oname[50];
00840 char *oname2 = oname+sizeof(GAMEDAT) - 1;
00841 char size_buffer[4];
00842 int size;
00843 strcpy(oname, GAMEDAT);
00844
00845 if (unzOpenCurrentFile(unzipfile) != UNZ_OK)
00846 {
00847 std::cerr << "Couldn't open current file" << std::endl;
00848 return false;
00849 }
00850
00851 while (!unzeof(unzipfile))
00852 {
00853
00854 oname2[12] = 0;
00855 if (unzReadCurrentFile(unzipfile, oname2, 12) != 12)
00856 {
00857 std::cerr << "Couldn't read for filename" << std::endl;
00858 return false;
00859 }
00860
00861
00862 if (*oname2 == 0) break;
00863
00864
00865 if (unzReadCurrentFile(unzipfile, size_buffer, 4) != 4)
00866 {
00867 std::cerr << "Couldn't read for size" << std::endl;
00868 return false;
00869 }
00870 BufferDataSource ds(size_buffer, 4);
00871 size = ds.read4();
00872
00873 if (size)
00874 {
00875
00876 int namelen = strlen(oname);
00877 if (oname[namelen - 1] == '.')
00878 oname[namelen - 1] = 0;
00879
00880
00881
00882 char *buf = new char[size];
00883 if (unzReadCurrentFile(unzipfile, buf, size) != size)
00884 {
00885 delete [] buf;
00886 std::cerr << "Couldn't read for buf" << std::endl;
00887 return false;
00888 }
00889
00890
00891 ofstream out;
00892 U7open(out, oname);
00893 out.write(buf, size);
00894
00895 delete [] buf;
00896 if (!out.good())
00897 {
00898 std::cerr << "out was bad" << std::endl;
00899 return false;
00900 }
00901 out.close();
00902 CYCLE_RED_PLASMA();
00903 }
00904 }
00905
00906 return unzCloseCurrentFile(unzipfile) == UNZ_OK;
00907 }
00908
00909
00910
00911
00912
00913
00914
00915
00916 bool Game_window::restore_gamedat_zip
00917 (
00918 const char *fname
00919 )
00920 {
00921
00922 try
00923 {
00924 if (Flex::is_flex(fname)) return false;
00925 }
00926 catch(const file_exception & f)
00927 {
00928 return false;
00929 }
00930 #ifdef RED_PLASMA
00931
00932 setup_load_palette();
00933 #endif
00934 std::string filestr = get_system_path(fname);
00935 unzFile unzipfile = unzOpen(filestr.c_str());
00936 if (!unzipfile) return false;
00937
00938 U7mkdir("<GAMEDAT>", 0755);
00939
00940
00941 U7remove (USEDAT);
00942 U7remove (USEVARS);
00943 U7remove (U7NBUF_DAT);
00944 U7remove (NPC_DAT);
00945 U7remove (MONSNPCS);
00946 U7remove (FLAGINIT);
00947 U7remove (GWINDAT);
00948 U7remove (IDENTITY);
00949 U7remove (GSCHEDULE);
00950 U7remove ("<STATIC>/flags.flg");
00951 U7remove (GSCRNSHOT);
00952 U7remove (GSAVEINFO);
00953 U7remove (GNEWGAMEVER);
00954 U7remove (GEXULTVER);
00955 U7remove (KEYRINGDAT);
00956
00957 cout.flush();
00958
00959 unz_global_info global;
00960 unzGetGlobalInfo(unzipfile, &global);
00961
00962
00963 char oname[50];
00964 char *oname2 = oname + sizeof(GAMEDAT) - 1;
00965 strcpy(oname, GAMEDAT);
00966
00967 do
00968 {
00969 unz_file_info file_info;
00970
00971 unzGetCurrentFileInfo(unzipfile, &file_info,
00972 oname2, 13,
00973 NULL, 0,
00974 NULL, 0);
00975
00976
00977 int len = file_info.uncompressed_size;
00978 if (len <= 0)
00979 continue;
00980
00981
00982 if (!std::strcmp("GAMEDAT", oname2))
00983 {
00984 if (Restore_level2(unzipfile) == false)
00985 abort("Error reading level2 from zip '%s'.", fname);
00986
00987 continue;
00988 }
00989
00990
00991 int namelen = strlen(oname);
00992 if (oname[namelen - 1] == '.')
00993 oname[namelen - 1] = 0;
00994
00995
00996
00997 if (unzOpenCurrentFile(unzipfile) != UNZ_OK)
00998 abort("Error opening current from zipfile '%s'.", fname);
00999
01000
01001 char *buf = new char[len];
01002 if (unzReadCurrentFile(unzipfile, buf, len) != len)
01003 abort("Error reading current from zip '%s'.", fname);
01004
01005
01006 ofstream out;
01007 U7open(out, oname);
01008 out.write(buf, len);
01009 if (!out.good()) abort("Error writing to '%s'.", oname);
01010 out.close();
01011
01012
01013 if (unzCloseCurrentFile(unzipfile) != UNZ_OK)
01014 abort("Error closing current in zip '%s'.", fname);
01015 delete [] buf;
01016
01017 CYCLE_RED_PLASMA();
01018 }
01019 while (unzGoToNextFile(unzipfile) == UNZ_OK);
01020
01021 unzClose(unzipfile);
01022
01023 cout.flush();
01024
01025 #ifdef RED_PLASMA
01026 load_palette_timer = 0;
01027 #endif
01028
01029 return true;
01030 }
01031
01032
01033
01034 static bool Save_level1 (zipFile zipfile, const char *fname)
01035 {
01036 ifstream in;
01037 try {
01038 U7open (in, fname);
01039 } catch (exult_exception& e) {
01040 if (Game::is_editing())
01041 return false;
01042 throw e;
01043 }
01044
01045
01046 StreamDataSource ds(&in);
01047
01048 unsigned int size = ds.getSize();
01049 char *buf = new char[size];
01050 ds.read(buf, size);
01051
01052
01053 zipOpenNewFileInZip (zipfile, remove_dir(fname), NULL, NULL, 0,
01054 NULL, 0, NULL, Z_DEFLATED, Z_BEST_COMPRESSION);
01055
01056 zipWriteInFileInZip (zipfile, buf, size);
01057 delete [] buf;
01058
01059 return zipCloseFileInZip (zipfile) == ZIP_OK;
01060 }
01061
01062
01063 static bool Begin_level2 (zipFile zipfile)
01064 {
01065 return zipOpenNewFileInZip (zipfile, "GAMEDAT", NULL, NULL, 0,
01066 NULL, 0, NULL, Z_DEFLATED, Z_BEST_COMPRESSION) == ZIP_OK;
01067 }
01068
01069 static bool Save_level2 (zipFile zipfile, const char *fname)
01070 {
01071 ifstream in;
01072 try {
01073 U7open (in, fname);
01074 } catch (exult_exception& e) {
01075 if (Game::is_editing())
01076 return false;
01077 throw e;
01078 }
01079
01080 StreamDataSource ds(&in);
01081
01082 uint32 size = ds.getSize();
01083 char *buf = new char[size<13?13:size];
01084
01085
01086 memset (buf, 0, 13);
01087 strncpy (buf, remove_dir(fname), 13);
01088 int err = zipWriteInFileInZip (zipfile, buf, 12);
01089
01090
01091 if (err == ZIP_OK)
01092 {
01093
01094 BufferDataSource bds(buf, 4);
01095 bds.write4(size);
01096 err = zipWriteInFileInZip (zipfile, buf, 4);
01097 }
01098
01099
01100 if (err == ZIP_OK)
01101 {
01102 ds.read(buf, size);
01103 err = zipWriteInFileInZip (zipfile, buf, size);
01104 }
01105
01106 delete [] buf;
01107
01108 return err == ZIP_OK;
01109 }
01110
01111 static bool End_level2 (zipFile zipfile)
01112 {
01113 uint32 zeros = 0;
01114
01115
01116 int err = zipWriteInFileInZip (zipfile, &zeros, 4);
01117 if (err == ZIP_OK) err = zipWriteInFileInZip (zipfile, &zeros, 4);
01118 if (err == ZIP_OK) err = zipWriteInFileInZip (zipfile, &zeros, 4);
01119
01120 return zipCloseFileInZip (zipfile) == ZIP_OK;
01121 }
01122
01123
01124 bool Game_window::save_gamedat_zip
01125 (
01126 const char *fname,
01127 const char *savename
01128 )
01129 {
01130
01131 if (save_compression < 1) return false;
01132
01133
01134 int numsavefiles = (Game::get_game_type() == BLACK_GATE) ?
01135 bgnumsavefiles : sinumsavefiles;
01136 const char **savefiles = (Game::get_game_type() == BLACK_GATE) ?
01137 bgsavefiles : sisavefiles;
01138
01139
01140 {
01141 ofstream out;
01142 char title[0x50];
01143 memset (title, 0, 0x50);
01144 std::strncpy (title, savename, 0x50);
01145 U7open(out, fname);
01146 out.write(title, 0x50);
01147 out.close();
01148 }
01149
01150 std::string filestr = get_system_path(fname);
01151 zipFile zipfile = zipOpen(filestr.c_str(), 1);
01152
01153
01154 if (save_compression != 2)
01155 {
01156 for (int i = 0; i < numsavefiles; i++)
01157 Save_level1(zipfile, savefiles[i]);
01158
01159
01160 for (int schunk = 0; schunk < 12*12; schunk++)
01161 {
01162 char iname[80];
01163 Save_level1(zipfile,
01164 map->get_schunk_file_name(U7IREG, schunk, iname));
01165 }
01166 }
01167
01168 else
01169 {
01170
01171
01172 Save_level1(zipfile, GSCRNSHOT);
01173 Save_level1(zipfile, GSAVEINFO);
01174 Save_level1(zipfile, IDENTITY);
01175
01176 Begin_level2(zipfile);
01177
01178 for (int i = 3; i < numsavefiles; i++)
01179 Save_level2(zipfile, savefiles[i]);
01180
01181
01182 for (int schunk = 0; schunk < 12*12; schunk++)
01183 {
01184 char iname[80];
01185 Save_level2(zipfile, map->get_schunk_file_name(
01186 U7IREG, schunk, iname));
01187 }
01188
01189 End_level2(zipfile);
01190 }
01191
01192
01193 if (zipClose(zipfile, savename) != ZIP_OK)
01194 throw file_write_exception(fname);
01195
01196 return true;
01197 }
01198
01199
01200
01201
01202
01203
01204
01205
01206 char *Game_window::get_game_identity_zip
01207 (
01208 const char *savename
01209 )
01210 {
01211
01212 try
01213 {
01214 if (Flex::is_flex(savename))
01215 return 0;
01216 }
01217 catch(const file_exception & f)
01218 {
01219 return 0;
01220 }
01221 unzFile unzipfile = unzOpen(get_system_path(savename).c_str());
01222 if (!unzipfile)
01223 return 0;
01224
01225 if (unzLocateFile(unzipfile, "identity", 2) != UNZ_OK)
01226 {
01227 unzClose(unzipfile);
01228 return "*";
01229 }
01230
01231 if (unzOpenCurrentFile(unzipfile) != UNZ_OK)
01232 {
01233 unzClose(unzipfile);
01234 throw file_read_exception(savename);
01235 }
01236
01237 char buf[256];
01238 int cnt = unzReadCurrentFile(unzipfile, buf, sizeof(buf) - 1);
01239 if (cnt <= 0)
01240 {
01241 unzCloseCurrentFile(unzipfile);
01242 unzClose(unzipfile);
01243 throw file_read_exception(savename);
01244 }
01245 buf[cnt] = 0;
01246 unzCloseCurrentFile(unzipfile);
01247 unzClose(unzipfile);
01248 char *ptr = buf;
01249 for(; (*ptr != 0 && *ptr!=0x1a && *ptr!=0x0d); ptr++)
01250 ;
01251 *ptr = 0;
01252 return newstrdup(buf);
01253 }
01254
01255 #endif