00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pent_include.h"
00020
00021 #include "util.h"
00022 #include "GameData.h"
00023 #include "FileSystem.h"
00024 #include "IDataSource.h"
00025 #include "UsecodeFlex.h"
00026 #include "MainShapeArchive.h"
00027 #include "FontShapeArchive.h"
00028 #include "GumpShapeArchive.h"
00029 #include "RawArchive.h"
00030 #include "MapGlob.h"
00031 #include "PaletteManager.h"
00032 #include "Shape.h"
00033 #include "MusicFlex.h"
00034 #include "WpnOvlayDat.h"
00035 #include "CoreApp.h"
00036 #include "ConfigFileManager.h"
00037 #include "FontManager.h"
00038 #include "GameInfo.h"
00039 #include "SettingManager.h"
00040 #include "SoundFlex.h"
00041 #include "SpeechFlex.h"
00042 #include "crusader/ConvertShapeCrusader.h"
00043
00044 GameData* GameData::gamedata = 0;
00045
00046
00047 GameData::GameData()
00048 : fixed(0), mainshapes(0), mainusecode(0), globs(0), fonts(0), gumps(0),
00049 mouse(0), music(0), weaponoverlay(0), soundflex(0), speech(1024)
00050 {
00051 con.Print(MM_INFO, "Creating GameData...\n");
00052
00053 assert(gamedata == 0);
00054 gamedata = this;
00055 }
00056
00057 GameData::~GameData()
00058 {
00059 con.Print(MM_INFO, "Destroying GameData...\n");
00060
00061 delete fixed;
00062 fixed = 0;
00063
00064 delete mainshapes;
00065 mainshapes = 0;
00066
00067 delete mainusecode;
00068 mainusecode = 0;
00069
00070 for (unsigned int i = 0; i < globs.size(); ++i)
00071 delete globs[i];
00072 globs.clear();
00073
00074 delete fonts;
00075 fonts = 0;
00076
00077 delete gumps;
00078 gumps = 0;
00079
00080 delete mouse;
00081 mouse = 0;
00082
00083 delete music;
00084 music = 0;
00085
00086 delete weaponoverlay;
00087 weaponoverlay = 0;
00088
00089 delete soundflex;
00090 soundflex = 0;
00091
00092 gamedata = 0;
00093
00094 for (unsigned int i = 0; i < speech.size(); ++i) {
00095 SpeechFlex** s = speech[i];
00096 if (s) delete *s;
00097 delete s;
00098 }
00099 speech.clear();
00100 }
00101
00102 MapGlob* GameData::getGlob(uint32 glob) const
00103 {
00104 if (glob < globs.size())
00105 return globs[glob];
00106 else
00107 return 0;
00108 }
00109
00110 ShapeArchive* GameData::getShapeFlex(uint16 flexId) const
00111 {
00112 switch (flexId) {
00113 case MAINSHAPES:
00114 return mainshapes;
00115 case GUMPS:
00116 return gumps;
00117 default:
00118 break;
00119 };
00120 return 0;
00121 }
00122
00123 Shape* GameData::getShape(FrameID f) const
00124 {
00125 ShapeArchive* sf = getShapeFlex(f.flexid);
00126 if (!sf) return 0;
00127 Shape* shape = sf->getShape(f.shapenum);
00128 return shape;
00129 }
00130
00131 ShapeFrame* GameData::getFrame(FrameID f) const
00132 {
00133 Shape* shape = getShape(f);
00134 if (!shape) return 0;
00135 ShapeFrame* frame = shape->getFrame(f.framenum);
00136 return frame;
00137 }
00138
00139 void GameData::loadTranslation()
00140 {
00141 ConfigFileManager* config = ConfigFileManager::get_instance();
00142 std::string translationfile;
00143
00144 GameInfo* gameinfo = CoreApp::get_instance()->getGameInfo();
00145
00146 if (gameinfo->type == GameInfo::GAME_U8) {
00147 switch (gameinfo->language) {
00148 case GameInfo::GAMELANG_ENGLISH:
00149
00150 break;
00151 case GameInfo::GAMELANG_FRENCH:
00152 translationfile = "u8french.ini";
00153 break;
00154 case GameInfo::GAMELANG_GERMAN:
00155 translationfile = "u8german.ini";
00156 break;
00157 case GameInfo::GAMELANG_SPANISH:
00158 translationfile = "u8spanish.ini";
00159 break;
00160 case GameInfo::GAMELANG_JAPANESE:
00161 translationfile = "u8japanese.ini";
00162 break;
00163 default:
00164 perr << "Unknown language." << std::endl;
00165 break;
00166 }
00167 }
00168
00169 if (!translationfile.empty()) {
00170 translationfile = "@data/" + translationfile;
00171
00172 pout << "Loading translation: " << translationfile << std::endl;
00173
00174 config->readConfigFile(translationfile, "language", true);
00175 }
00176 }
00177
00178 std::string GameData::translate(std::string text)
00179 {
00180
00181
00182 ConfigFileManager* config = ConfigFileManager::get_instance();
00183 Pentagram::istring key = "language/text/" + text;
00184 if (!config->exists(key))
00185 return text;
00186
00187 std::string trans;
00188 config->get(key, trans);
00189 return trans;
00190 }
00191
00192 FrameID GameData::translate(FrameID f)
00193 {
00194
00195
00196
00197
00198 ConfigFileManager* config = ConfigFileManager::get_instance();
00199 Pentagram::istring key = "language/";
00200 switch (f.flexid) {
00201 case GUMPS:
00202 key += "gumps/";
00203 break;
00204 default:
00205 return f;
00206 }
00207
00208 char buf[100];
00209 sprintf(buf, "%d,%d", f.shapenum, f.framenum);
00210
00211 key += buf;
00212 if (!config->exists(key))
00213 return f;
00214
00215 std::string trans;
00216 config->get(key, trans);
00217
00218 FrameID t;
00219 t.flexid = f.flexid;
00220 int n = sscanf(trans.c_str(), "%d,%d", &t.shapenum, &t.framenum);
00221 if (n != 2) {
00222 perr << "Invalid shape translation: " << trans << std::endl;
00223 return f;
00224 }
00225
00226 return t;
00227 }
00228
00229 void GameData::loadU8Data()
00230 {
00231 FileSystem* filesystem = FileSystem::get_instance();
00232
00233 IDataSource *fd = filesystem->ReadFile("@game/static/fixed.dat");
00234 if (!fd) {
00235 perr << "Unable to load static/fixed.dat. Exiting" << std::endl;
00236 std::exit(-1);
00237 }
00238 fixed = new RawArchive(fd);
00239
00240 GameInfo* gameinfo = CoreApp::get_instance()->getGameInfo();
00241 char langletter = gameinfo->getLanguageUsecodeLetter();
00242 if (!langletter) {
00243 perr << "Unknown language. Unable to open usecode." << std::endl;
00244 std::exit(-1);
00245 }
00246 std::string filename = "@game/usecode/";
00247 filename += langletter;
00248 filename += "usecode.flx";
00249
00250
00251 IDataSource* uds = filesystem->ReadFile(filename);
00252 if (!uds) {
00253 perr << "Unable to load " << filename << ". Exiting" << std::endl;
00254 std::exit(-1);
00255 }
00256 mainusecode = new UsecodeFlex(uds);
00257
00258
00259 pout << "Load Shapes" << std::endl;
00260 IDataSource *sf = filesystem->ReadFile("@game/static/u8shapes.flx");
00261 if (!sf) sf = filesystem->ReadFile("@game/static/u8shapes.cmp");
00262
00263 if (!sf) {
00264 perr << "Unable to load static/u8shapes.flx or static/u8shapes.cmp. Exiting" << std::endl;
00265 std::exit(-1);
00266 }
00267 mainshapes = new MainShapeArchive(sf, MAINSHAPES,
00268 PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game));
00269
00270
00271 ConfigFileManager* config = ConfigFileManager::get_instance();
00272 config->readConfigFile("@data/u8weapons.ini", "weapons", true);
00273 config->readConfigFile("@data/u8armour.ini", "armour", true);
00274 config->readConfigFile("@data/u8monsters.ini", "monsters", true);
00275 config->readConfigFile("@data/u8.ini", "game", true);
00276
00277
00278 IDataSource *tfs = filesystem->ReadFile("@game/static/typeflag.dat");
00279 if (!tfs) {
00280 perr << "Unable to load static/typeflag.dat. Exiting" << std::endl;
00281 std::exit(-1);
00282 }
00283 mainshapes->loadTypeFlags(tfs);
00284 delete tfs;
00285
00286
00287 IDataSource *af = filesystem->ReadFile("@game/static/anim.dat");
00288 if (!af) {
00289 perr << "Unable to load static/anim.dat. Exiting" << std::endl;
00290 std::exit(-1);
00291 }
00292 mainshapes->loadAnimDat(af);
00293 delete af;
00294
00295
00296 IDataSource* wod = filesystem->ReadFile("@game/static/wpnovlay.dat");
00297 if (!wod) {
00298 perr << "Unable to load static/wpnovlay.dat. Exiting" << std::endl;
00299 std::exit(-1);
00300 }
00301 RawArchive* overlayflex = new RawArchive(wod);
00302 weaponoverlay = new WpnOvlayDat();
00303 weaponoverlay->load(overlayflex);
00304 delete overlayflex;
00305
00306
00307 IDataSource *gds = filesystem->ReadFile("@game/static/glob.flx");
00308 if (!gds) {
00309 perr << "Unable to load static/glob.flx. Exiting" << std::endl;
00310 std::exit(-1);
00311 }
00312 RawArchive* globflex = new RawArchive(gds);
00313 globs.clear();
00314 globs.resize(globflex->getCount());
00315 for (unsigned int i = 0; i < globflex->getCount(); ++i) {
00316 MapGlob* glob = 0;
00317 IDataSource* globds = globflex->get_datasource(i);
00318
00319 if (globds && globds->getSize()) {
00320 glob = new MapGlob();
00321 glob->read(globds);
00322 }
00323 delete globds;
00324
00325 globs[i] = glob;
00326 }
00327 delete globflex;
00328
00329
00330 IDataSource *fds = filesystem->ReadFile("@game/static/u8fonts.flx");
00331 if (!fds) {
00332 perr << "Unable to load static/u8fonts.flx. Exiting" << std::endl;
00333 std::exit(-1);
00334 }
00335 fonts = new FontShapeArchive(fds, OTHER,
00336 PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game));
00337 fonts->setHVLeads();
00338
00339
00340 IDataSource *msds = filesystem->ReadFile("@game/static/u8mouse.shp");
00341 if (!msds) {
00342 perr << "Unable to load static/u8mouse.shp. Exiting" << std::endl;
00343 std::exit(-1);
00344 }
00345 mouse = new Shape(msds, 0);
00346 mouse->setPalette(PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game));
00347 delete msds;
00348
00349 IDataSource *gumpds = filesystem->ReadFile("@game/static/u8gumps.flx");
00350 if (!gumpds) {
00351 perr << "Unable to load static/u8gumps.flx. Exiting" << std::endl;
00352 std::exit(-1);
00353 }
00354 gumps = new GumpShapeArchive(gumpds, GUMPS,
00355 PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game));
00356
00357 IDataSource *gumpageds = filesystem->ReadFile("@game/static/gumpage.dat");
00358 if (!gumpageds) {
00359 perr << "Unable to load static/gumpage.dat. Exiting" << std::endl;
00360 std::exit(-1);
00361 }
00362 gumps->loadGumpage(gumpageds);
00363 delete gumpageds;
00364
00365
00366 IDataSource *mf = filesystem->ReadFile("@game/sound/music.flx");
00367 if (!mf) {
00368 perr << "Unable to load sound/music.flx. Exiting" << std::endl;
00369 std::exit(-1);
00370 }
00371 music = new MusicFlex(mf);
00372
00373 IDataSource *sndflx = filesystem->ReadFile("@game/sound/sound.flx");
00374 if (!sndflx) {
00375 perr << "Unable to load sound/sound.flx. Exiting" << std::endl;
00376 std::exit(-1);
00377 }
00378 soundflex = new SoundFlex(sndflx);
00379
00380 loadTranslation();
00381 }
00382
00383 void GameData::setupFontOverrides()
00384 {
00385 setupTTFOverrides("game/fontoverride", false);
00386
00387 GameInfo* gameinfo = CoreApp::get_instance()->getGameInfo();
00388 if (gameinfo->language == GameInfo::GAMELANG_JAPANESE)
00389 setupJPOverrides();
00390 }
00391
00392 void GameData::setupJPOverrides()
00393 {
00394 SettingManager* settingman = SettingManager::get_instance();
00395 ConfigFileManager* config = ConfigFileManager::get_instance();
00396 FontManager* fontmanager = FontManager::get_instance();
00397 std::map<Pentagram::istring, std::string> jpkeyvals;
00398 std::map<Pentagram::istring, std::string>::iterator iter;
00399
00400 jpkeyvals = config->listKeyValues("language/jpfonts");
00401 for (iter = jpkeyvals.begin(); iter != jpkeyvals.end(); ++iter)
00402 {
00403 int fontnum = std::atoi(iter->first.c_str());
00404 std::string fontdesc = iter->second;
00405
00406 std::vector<std::string> vals;
00407 Pentagram::SplitString(fontdesc, ',', vals);
00408 if (vals.size() != 2) {
00409 perr << "Invalid jpfont override: " << fontdesc << std::endl;
00410 continue;
00411 }
00412
00413 unsigned int jpfontnum = std::atoi(vals[0].c_str());
00414 uint32 col32 = std::strtol(vals[1].c_str(), 0, 0);
00415
00416 if (!fontmanager->addJPOverride(fontnum, jpfontnum, col32))
00417 {
00418 perr << "failed to setup jpfont override for font " << fontnum
00419 << std::endl;
00420 }
00421 }
00422
00423 bool ttfoverrides = false;
00424 settingman->get("ttf", ttfoverrides);
00425 if (ttfoverrides)
00426 setupTTFOverrides("language/fontoverride", true);
00427 }
00428
00429 void GameData::setupTTFOverrides(const char* configkey, bool SJIS)
00430 {
00431 ConfigFileManager* config = ConfigFileManager::get_instance();
00432 SettingManager* settingman = SettingManager::get_instance();
00433 FontManager* fontmanager = FontManager::get_instance();
00434 std::map<Pentagram::istring, std::string> ttfkeyvals;
00435 std::map<Pentagram::istring, std::string>::iterator iter;
00436
00437 bool ttfoverrides = false;
00438 settingman->get("ttf", ttfoverrides);
00439 if (!ttfoverrides) return;
00440
00441 ttfkeyvals = config->listKeyValues(configkey);
00442 for (iter = ttfkeyvals.begin(); iter != ttfkeyvals.end(); ++iter)
00443 {
00444 int fontnum = std::atoi(iter->first.c_str());
00445 std::string fontdesc = iter->second;
00446
00447 std::vector<std::string> vals;
00448 Pentagram::SplitString(fontdesc, ',', vals);
00449 if (vals.size() != 4) {
00450 perr << "Invalid ttf override: " << fontdesc << std::endl;
00451 continue;
00452 }
00453
00454 std::string filename = vals[0];
00455 int pointsize = std::atoi(vals[1].c_str());
00456 uint32 col32 = std::strtol(vals[2].c_str(), 0, 0);
00457 int border = std::atoi(vals[3].c_str());
00458
00459 if (!fontmanager->addTTFOverride(fontnum, filename, pointsize,
00460 col32, border, SJIS))
00461 {
00462 perr << "failed to setup ttf override for font " << fontnum
00463 << std::endl;
00464 }
00465 }
00466 }
00467
00468 SpeechFlex* GameData::getSpeechFlex(uint32 shapenum)
00469 {
00470 if (shapenum >= speech.size()) return 0;
00471
00472 SpeechFlex** s = speech[shapenum];
00473 if (s) return *s;
00474
00475 s = new SpeechFlex*;
00476 *s = 0;
00477
00478 FileSystem* filesystem = FileSystem::get_instance();
00479
00480 std::string u8_sound_ = "@game/sound/";
00481 char num_flx [32];
00482 snprintf(num_flx ,32,"%i.flx", shapenum);
00483
00484 GameInfo* gameinfo = CoreApp::get_instance()->getGameInfo();
00485 char langletter = gameinfo->getLanguageFileLetter();
00486 if (!langletter) {
00487 perr << "GameData::getSpeechFlex: Unknown language." << std::endl;
00488 return 0;
00489 }
00490
00491 IDataSource* sflx = filesystem->ReadFile(u8_sound_ + langletter + num_flx);
00492 if (sflx) {
00493 *s = new SpeechFlex(sflx);
00494 }
00495
00496 speech[shapenum] = s;
00497
00498 return *s;
00499 }
00500
00501
00502 void GameData::loadRemorseData()
00503 {
00504 FileSystem* filesystem = FileSystem::get_instance();
00505
00506 IDataSource *fd = filesystem->ReadFile("@game/static/fixed.dat");
00507 if (!fd) {
00508 perr << "Unable to load static/fixed.dat. Exiting" << std::endl;
00509 std::exit(-1);
00510 }
00511 fixed = new RawArchive(fd);
00512
00513 GameInfo* gameinfo = CoreApp::get_instance()->getGameInfo();
00514 char langletter = gameinfo->getLanguageUsecodeLetter();
00515 if (!langletter) {
00516 perr << "Unknown language. Unable to open usecode." << std::endl;
00517 std::exit(-1);
00518 }
00519 std::string filename = "@game/usecode/";
00520 filename += langletter;
00521 filename += "usecode.flx";
00522
00523
00524 IDataSource* uds = filesystem->ReadFile(filename);
00525 if (!uds) {
00526 perr << "Unable to load " << filename << ". Exiting" << std::endl;
00527 std::exit(-1);
00528 }
00529 mainusecode = new UsecodeFlex(uds);
00530
00531
00532 pout << "Load Shapes" << std::endl;
00533 IDataSource *sf = filesystem->ReadFile("@game/static/shapes.flx");
00534
00535 if (!sf) {
00536 perr << "Unable to load static/shapes.flx. Exiting" << std::endl;
00537 std::exit(-1);
00538 }
00539 mainshapes = new MainShapeArchive(sf, MAINSHAPES,
00540 PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game),
00541 &CrusaderShapeFormat);
00542
00543 ConfigFileManager* config = ConfigFileManager::get_instance();
00544 #if 0
00545
00546 config->readConfigFile("@data/u8weapons.ini", "weapons", true);
00547 config->readConfigFile("@data/u8armour.ini", "armour", true);
00548 config->readConfigFile("@data/u8monsters.ini", "monsters", true);
00549 #endif
00550 config->readConfigFile("@data/remorse.ini", "game", true);
00551
00552
00553 IDataSource *tfs = filesystem->ReadFile("@game/static/typeflag.dat");
00554 if (!tfs) {
00555 perr << "Unable to load static/typeflag.dat. Exiting" << std::endl;
00556 std::exit(-1);
00557 }
00558 mainshapes->loadTypeFlags(tfs);
00559 delete tfs;
00560
00561
00562 IDataSource *af = filesystem->ReadFile("@game/static/anim.dat");
00563 if (!af) {
00564 perr << "Unable to load static/anim.dat. Exiting" << std::endl;
00565 std::exit(-1);
00566 }
00567 mainshapes->loadAnimDat(af);
00568 delete af;
00569
00570
00571 IDataSource* wod = filesystem->ReadFile("@game/static/wpnovlay.dat");
00572 if (!wod) {
00573 perr << "Unable to load static/wpnovlay.dat. Exiting" << std::endl;
00574 std::exit(-1);
00575 }
00576 RawArchive* overlayflex = new RawArchive(wod);
00577 weaponoverlay = new WpnOvlayDat();
00578 weaponoverlay->load(overlayflex);
00579 delete overlayflex;
00580
00581
00582 IDataSource *gds = filesystem->ReadFile("@game/static/glob.flx");
00583 if (!gds) {
00584 perr << "Unable to load static/glob.flx. Exiting" << std::endl;
00585 std::exit(-1);
00586 }
00587 RawArchive* globflex = new RawArchive(gds);
00588 globs.clear();
00589 globs.resize(globflex->getCount());
00590 for (unsigned int i = 0; i < globflex->getCount(); ++i) {
00591 MapGlob* glob = 0;
00592 IDataSource* globds = globflex->get_datasource(i);
00593
00594 if (globds && globds->getSize()) {
00595 glob = new MapGlob();
00596 glob->read(globds);
00597 }
00598 delete globds;
00599
00600 globs[i] = glob;
00601 }
00602 delete globflex;
00603
00604
00605 IDataSource *fds = filesystem->ReadFile("@game/static/fonts.flx");
00606 if (!fds) {
00607 perr << "Unable to load static/fonts.flx. Exiting" << std::endl;
00608 std::exit(-1);
00609 }
00610 fonts = new FontShapeArchive(fds, OTHER,
00611 PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game));
00612 fonts->setHVLeads();
00613
00614
00615 IDataSource *msds = filesystem->ReadFile("@game/static/mouse.shp");
00616 if (!msds) {
00617 perr << "Unable to load static/mouse.shp. Exiting" << std::endl;
00618 std::exit(-1);
00619 }
00620 mouse = new Shape(msds, 0);
00621 mouse->setPalette(PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game));
00622 delete msds;
00623
00624 IDataSource *gumpds = filesystem->ReadFile("@game/static/gumps.flx");
00625 if (!gumpds) {
00626 perr << "Unable to load static/gumps.flx. Exiting" << std::endl;
00627 std::exit(-1);
00628 }
00629 gumps = new GumpShapeArchive(gumpds, GUMPS,
00630 PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Game));
00631
00632 #if 0
00633 IDataSource *gumpageds = filesystem->ReadFile("@game/static/gumpage.dat");
00634 if (!gumpageds) {
00635 perr << "Unable to load static/gumpage.dat. Exiting" << std::endl;
00636 std::exit(-1);
00637 }
00638 gumps->loadGumpage(gumpageds);
00639 delete gumpageds;
00640 #endif
00641
00642 IDataSource* dummyds = filesystem->ReadFile("@data/empty.flx");
00643 music = 0;
00644 delete dummyds;
00645 #if 0
00646 IDataSource *mf = filesystem->ReadFile("@game/sound/music.flx");
00647 if (!mf) {
00648 perr << "Unable to load sound/music.flx. Exiting" << std::endl;
00649 std::exit(-1);
00650 }
00651 music = new MusicFlex(mf);
00652 #endif
00653
00654 dummyds = filesystem->ReadFile("@data/empty.flx");
00655 soundflex = new SoundFlex(dummyds);
00656 delete dummyds;
00657 #if 0
00658 IDataSource *sndflx = filesystem->ReadFile("@game/sound/sound.flx");
00659 if (!sndflx) {
00660 perr << "Unable to load sound/sound.flx. Exiting" << std::endl;
00661 std::exit(-1);
00662 }
00663 soundflex = new SoundFlex(sndflx);
00664 #endif
00665
00666 loadTranslation();
00667 }