/*
* Copyright 2010 OpenXcom Developers.
*
* This file is part of OpenXcom.
*
* OpenXcom is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenXcom is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenXcom. If not, see .
*/
#include "XcomResourcePack.h"
#include
#include
#include "../Engine/Palette.h"
#include "../Engine/Font.h"
#include "../Engine/Surface.h"
#include "../Engine/SurfaceSet.h"
#include "../Engine/Language.h"
#include "../Engine/Music.h"
#include "../Engine/GMCat.h"
#include "../Engine/SoundSet.h"
#include "../Geoscape/Globe.h"
#include "../Geoscape/Polygon.h"
#include "../Geoscape/Polyline.h"
#include "../Interface/TextButton.h"
#include "../Interface/Window.h"
#include "../Savegame/SavedBattleGame.h"
#include "../Savegame/Tile.h"
#include "../Savegame/Node.h"
#include "../Savegame/NodeLink.h"
#include "../Battlescape/Position.h"
namespace OpenXcom
{
/**
* Initializes the resource pack by loading all the resources
* contained in the original game folder.
* @param folder Subfolder to load resources from.
*/
XcomResourcePack::XcomResourcePack(const std::string &folder) : ResourcePack(folder)
{
// Load palettes
for (int i = 0; i < 5; i++)
{
std::stringstream s1, s2;
s1 << folder << "GEODATA/PALETTES.DAT";
s2 << "PALETTES.DAT_" << i;
_palettes[s2.str()] = new Palette();
_palettes[s2.str()]->loadDat(insensitive(s1.str()), 256, Palette::palOffset(i));
}
std::stringstream s1, s2;
s1 << folder << "GEODATA/BACKPALS.DAT";
s2 << "BACKPALS.DAT";
_palettes[s2.str()] = new Palette();
_palettes[s2.str()]->loadDat(insensitive(s1.str()), 128);
// Load fonts
std::string font[] = {"BIGLETS.DAT",
"SMALLSET.DAT"};
for (int i = 0; i < 2; i++)
{
std::stringstream s;
s << folder << "GEODATA/" << font[i];
if (font[i] == "BIGLETS.DAT")
_fonts[font[i]] = new Font(16, 16, 173);
else if (font[i] == "SMALLSET.DAT")
_fonts[font[i]] = new Font(8, 9, 173, -1);
_fonts[font[i]]->getSurface()->loadScr(insensitive(s.str()));
_fonts[font[i]]->load();
}
// Load language graphics
std::string lang[] = {"English",
"French",
"German",
"Italian",
"Spanish"};
for (int i = 1; i < 5; i++)
{
std::stringstream s1, s2;
s1 << folder << "Language/" << lang[i] << ".geo";
s2 << lang[i] << ".geo";
_surfaces[s2.str()] = new Surface(64, 154);
_surfaces[s2.str()]->loadScr(insensitive(s1.str()));
}
// Load surfaces
{
std::stringstream s;
s << folder << "GEODATA/" << "INTERWIN.DAT";
_surfaces["INTERWIN.DAT"] = new Surface(160, 556);
_surfaces["INTERWIN.DAT"]->loadScr(insensitive(s.str()));
}
std::string scrs[] = {"BACK01.SCR",
"BACK02.SCR",
"BACK03.SCR",
"BACK04.SCR",
"BACK05.SCR",
"BACK06.SCR",
"BACK07.SCR",
"BACK08.SCR",
"BACK09.SCR",
"BACK10.SCR",
"BACK11.SCR",
"BACK12.SCR",
"BACK13.SCR",
"BACK14.SCR",
"BACK15.SCR",
"BACK16.SCR",
"BACK17.SCR",
"GEOBORD.SCR",
"UP_BORD2.SCR"};
for (int i = 0; i < 19; i++)
{
std::stringstream s;
s << folder << "GEOGRAPH/" << scrs[i];
_surfaces[scrs[i]] = new Surface(320, 200);
_surfaces[scrs[i]]->loadScr(insensitive(s.str()));
}
std::string spks[] = {"UP001.SPK",
"UP002.SPK",
"UP003.SPK",
"UP004.SPK",
"UP005.SPK",
"UP006.SPK",
"UP007.SPK",
"UP008.SPK",
"UP009.SPK",
"UP010.SPK",
"UP011.SPK",
"UP012.SPK",
"UP013.SPK",
"UP014.SPK",
"UP015.SPK",
"UP016.SPK",
"UP017.SPK",
"UP018.SPK",
"UP019.SPK",
"UP020.SPK",
"UP021.SPK",
"UP022.SPK",
"UP023.SPK",
"UP024.SPK",
"UP025.SPK",
"UP026.SPK",
"UP027.SPK",
"UP028.SPK",
"UP029.SPK",
"UP030.SPK",
"UP031.SPK",
"UP032.SPK",
"UP033.SPK",
"UP034.SPK",
"UP035.SPK",
"UP036.SPK",
"UP037.SPK",
"UP038.SPK",
"UP039.SPK",
"UP040.SPK",
"UP041.SPK",
"UP042.SPK",
"GRAPHS.SPK"};
for (int i = 0; i < 43; i++)
{
std::stringstream s;
s << folder << "GEOGRAPH/" << spks[i];
_surfaces[spks[i]] = new Surface(320, 200);
_surfaces[spks[i]]->loadSpk(insensitive(s.str()));
}
// Load surface sets
std::string sets[] = {"BASEBITS.PCK",
"INTICON.PCK",
"TEXTURE.DAT"};
for (int i = 0; i < 3; i++)
{
std::stringstream s;
s << folder << "GEOGRAPH/" << sets[i];
std::string ext = sets[i].substr(sets[i].length()-3, sets[i].length());
if (ext == "PCK")
{
std::string tab = sets[i].substr(0, sets[i].length()-4) + ".TAB";
std::stringstream s2;
s2 << folder << "GEOGRAPH/" << tab;
_sets[sets[i]] = new SurfaceSet(32, 40);
_sets[sets[i]]->loadPck(insensitive(s.str()), insensitive(s2.str()));
}
else
{
_sets[sets[i]] = new SurfaceSet(32, 32);
_sets[sets[i]]->loadDat(insensitive(s.str()));
}
}
// Load polygons
std::stringstream s;
s << folder << "GEODATA/" << "WORLD.DAT";
Globe::loadDat(insensitive(s.str()), &_polygons);
// Load polylines (extracted from game)
// -10 = Start of line
// -20 = End of data
double lines[] = {-10, 1.18901, -0.412334, 1.23918, -0.425424, 1.213, -0.471239, 1.22828, -0.490874, 1.23482, -0.482147, 1.30245, -0.541052, 1.29373,
-0.608684, 1.35918, -0.61741, 1.38099, -0.53887, 1.41154, -0.530144, 1.39626, -0.503964, 1.53153, -0.460331, 1.54025, -0.488692,
1.55116, -0.490874, 1.55334, -0.466876, 1.60352, -0.469057, 1.59916, -0.488692, 1.67552, -0.517054, 1.69515, -0.475602, 1.61661,
-0.386154, 1.61225, -0.436332, 1.56861, -0.440696, 1.56425, -0.460331, 1.54243, -0.462512, 1.53589, -0.449422, 1.55552, -0.373064,
-10, 6.13047, -0.726493, 6.17628, -0.726493, 6.1501, -0.645772, -10, 6.25264, -0.759218, 0.0109083, -0.73522, 0.0567232, -0.741765,
-10, 0.128718, -0.7614, 0.122173, -0.80067, 0.102538, -0.807215, 0.1309, -0.829031, 0.14399, -0.85303, 0.111265, -0.863938, 0.0719948,
-0.870483, 0.0501782, -0.885755, -10, 0.122173, -0.80067, 0.148353, -0.811578, 0.159261, -0.80067, 0.211621, -0.820305, 0.239983,
-0.811578, 0.239983, -0.794125, -10, 0.111265, -0.863938, 0.102538, -0.907571, 0.11781, -0.90539, 0.122173, -0.938114, -10, 0.139626,
-0.959931, 0.181078, -0.953386, -10, 0.248709, -0.942478, 0.261799, -0.887936, 0.213803, -0.877028, 0.242164, -0.85303, 0.229074,
-0.829031, 0.1309, -0.829031, -10, 0.0458149, -0.109083, 0.0479966, -0.148353, 0.0654498, -0.185441, 0.0698132, -0.237801, 0.0981748,
-0.244346, 0.122173, -0.224711, 0.17017, -0.222529, 0.231256, -0.235619, 0.257436, -0.211621, 0.19635, -0.113446, 0.176715, -0.126536,
0.148353, -0.0763582, -10, 0.438514, -0.554142, 0.436332, -0.383972, 0.595594, -0.383972, 0.628319, -0.410152, -10, 0.59123, -0.547597,
0.619592, -0.493056, -10, 0.283616, 0.4996, 0.349066, 0.495237, 0.349066, 0.434151, 0.362156, 0.469057, 0.407971, 0.440696, 0.447241,
0.449422, 0.510509, 0.386154, 0.545415, 0.390517, 0.558505, 0.469057, 0.575959, 0.464694, -10, 5.36252, 0.580322, 5.27962, 0.523599,
5.34071, 0.449422, 5.27089, 0.386154, 5.26653, 0.283616, 5.14436, 0.174533, 5.05491, 0.194168, 4.996, 0.14399, 5.01564, 0.0872665,
5.06364, 0.0763582, 5.06582, -0.0305433, 5.18145, -0.0370882, 5.15527, -0.0698132, 5.2229, -0.0938114, 5.2578, -0.019635, 5.35816,
-0.0327249, 5.38652, -0.0741765, -10, 4.10152, -0.85303, 4.45059, -0.85303, 4.62512, -0.855211, 4.71893, -0.837758, -10, 5.116, -0.776672,
5.08545, -0.824668, 5.03309, -0.785398, 4.97419, -0.785398, 4.95019, -0.770127, -10, 3.82227, -1.21519, 3.82227, -1.05374, 4.01426,
-0.977384, 3.95972, -0.949023, -10, 4.23897, -0.569414, 4.42659, -0.554142, 4.48113, -0.503964, 4.51386, -0.519235, 4.55531, -0.460331,
4.59022, -0.455967, -10, 4.82584, -0.728675, 4.84983, -0.750492, -10, 4.8062, -0.81376, 4.82802, -0.80067, -10, 0.545415, -1.21955, 0.549779,
-1.09738, 0.490874, -1.05156, -10, 0.488692, -1.04283, 0.490874, -0.981748, 0.569414, -0.933751, 0.554142, -0.909753, 0.698132, -0.863938,
0.665407, -0.818123, -10, 0.693768, -0.763582, 0.857393, -0.730857, -10, 0.861756, -0.805033, 0.831213, -0.87921, 1.0472, -0.885755, 1.0712,
-0.944659, 1.2021, -0.966476, 1.34172, -0.951204, 1.39626, -0.885755, 1.53589, -0.857393, 1.71042, -0.872665, 1.72569, -0.909753, 1.91986,
-0.859575, 2.03767, -0.870483, 2.08131, -0.872665, 2.09658, -0.922843, 2.19693, -0.925025, 2.23184, -0.86612, 2.34747, -0.842121, 2.32129,
-0.785398, 2.28638, -0.783217, 2.27984, -0.73522, 2.16857, -0.698132, -10, 1.88277, -0.375246, 1.8435, -0.407971, 1.77587, -0.370882,
1.73006, -0.386154, 1.72569, -0.423242, 1.7017, -0.418879, 1.72569, -0.477784, 1.69515, -0.475602, -10, 1.59916, -0.488692, 1.55116,
-0.490874, -10, 1.54025, -0.488692, 1.41154, -0.530144, -10, 1.35918, -0.61741, 1.28064, -0.687223, 1.40499, -0.737402, 1.39626, -0.785398,
1.4399, -0.78758, 1.44644, -0.824668, 1.49662, -0.822486, 1.50753, -0.857393, 1.53589, -0.857393, 1.5817, -0.789761, 1.67988, -0.746128,
1.8326, -0.724312, 1.95477, -0.7614, 1.95695, -0.785398, 2.09221, -0.815941, 2.02022, -0.833395, 2.03767, -0.870483, -20};
Polyline *l = 0;
int start = 0;
for (int i = 0; lines[i] > -19.999; i++)
{
if (lines[i] < -9.999 && lines[i] > -10.001)
{
if (l != 0)
{
_polylines.push_back(l);
}
int points = 0;
for (int j = i + 1; lines[j] > -9.999; j++)
{
points++;
}
points /= 2;
l = new Polyline(points);
start = i + 1;
}
else
{
if ((i - start) % 2 == 0)
{
l->setLongitude((i - start) / 2, lines[i]);
}
else
{
l->setLatitude((i - start) / 2, lines[i]);
}
}
}
_polylines.push_back(l);
// Load musics
std::string mus[] = {"GMDEFEND",
"GMENBASE",
"GMGEO1",
"GMGEO2",
"GMINTER",
"GMINTRO1",
"GMINTRO2",
"GMINTRO3",
"GMLOSE",
"GMMARS",
"GMNEWMAR",
"GMSTORY",
"GMTACTIC",
"GMWIN"};
std::string exts[] = {"OGG", "MP3", "MID"};
int tracks[] = {3, 6, 0, 18, 2, 19, 20, 21, 10, 8, 9, 12, 17, 11};
// Check which music version is available
bool cat = true;
GMCatFile *gmcat = 0;
std::stringstream musDos;
musDos << folder << "SOUND/GM.CAT";
struct stat musInfo;
if (stat(insensitive(musDos.str()).c_str(), &musInfo) == 0)
{
cat = true;
gmcat = new GMCatFile(insensitive(musDos.str()).c_str());
}
else
{
cat = false;
}
for (int i = 0; i < 14; i++)
{
if (cat)
{
_musics[mus[i]] = gmcat->loadMIDI(tracks[i]);
}
else
{
_musics[mus[i]] = new Music();
for (int j = 0; j < 3; j++)
{
std::stringstream s;
s << folder << "SOUND/" << mus[i] << "." << exts[j];
struct stat info;
if (stat(insensitive(s.str()).c_str(), &info) == 0)
{
_musics[mus[i]]->load(insensitive(s.str()));
break;
}
}
}
}
delete gmcat;
// Load sounds
std::string catsId[] = {"GEO.CAT",
"BATTLE.CAT",
"INTRO.CAT"};
std::string catsDos[] = {"SOUND2.CAT",
"SOUND1.CAT",
"INTRO.CAT"};
std::string catsWin[] = {"SAMPLE.CAT",
"SAMPLE2.CAT",
"SAMPLE3.CAT"};
// Check which sound version is available
std::string *cats = 0;
bool wav = true;
std::stringstream win, dos;
win << folder << "SOUND/" << catsWin[0];
dos << folder << "SOUND/" << catsDos[0];
struct stat sndInfo;
if (stat(insensitive(win.str()).c_str(), &sndInfo) == 0)
{
cats = catsWin;
wav = true;
}
else if (stat(insensitive(dos.str()).c_str(), &sndInfo) == 0)
{
cats = catsDos;
wav = false;
}
for (int i = 0; i < 3; i++)
{
if (cats == 0)
{
_sounds[catsId[i]] = new SoundSet();
}
else
{
std::stringstream s;
s << folder << "SOUND/" << cats[i];
_sounds[catsId[i]] = new SoundSet();
_sounds[catsId[i]]->loadCat(insensitive(s.str()), wav);
}
}
TextButton::soundPress = _sounds["GEO.CAT"]->getSound(0);
Window::soundPopup[0] = _sounds["GEO.CAT"]->getSound(1);
Window::soundPopup[1] = _sounds["GEO.CAT"]->getSound(2);
Window::soundPopup[2] = _sounds["GEO.CAT"]->getSound(3);
loadBattlescapeResources(); // TODO load this at battlescape start, unload at battlescape end?
}
/**
*
*/
XcomResourcePack::~XcomResourcePack()
{
}
void XcomResourcePack::loadBattlescapeResources()
{
// Load Battlescape ICONS
std::stringstream s;
s << _folder << "UFOGRAPH/" << "ICONS.PCK";
_surfaces["ICONS.PCK"] = new Surface(320, 200);
_surfaces["ICONS.PCK"]->loadSpk(insensitive(s.str()));
s.str("");
std::stringstream s2;
s << _folder << "UFOGRAPH/" << "CURSOR.PCK";
s2 << _folder << "UFOGRAPH/" << "CURSOR.TAB";
_sets["CURSOR.PCK"] = new SurfaceSet(32, 40);
_sets["CURSOR.PCK"]->loadPck(insensitive(s.str()), insensitive(s2.str()));
s.str("");
s2.str("");
s << _folder << "UFOGRAPH/" << "SMOKE.PCK";
s2 << _folder << "UFOGRAPH/" << "SMOKE.TAB";
_sets["SMOKE.PCK"] = new SurfaceSet(32, 40);
_sets["SMOKE.PCK"]->loadPck(insensitive(s.str()), insensitive(s2.str()));
// Load Battlescape Terrain (only blacks are loaded, others are loaded at runtime)
std::string bsets[] = {"BLANKS.PCK"};
for (int i = 0; i < 1; i++)
{
std::stringstream s;
s << _folder << "TERRAIN/" << bsets[i];
std::string tab = bsets[i].substr(0, bsets[i].length()-4) + ".TAB";
std::stringstream s2;
s2 << _folder << "TERRAIN/" << tab;
_sets[bsets[i]] = new SurfaceSet(32, 40);
_sets[bsets[i]]->loadPck(insensitive(s.str()), insensitive(s2.str()));
}
// Load Battlescape units
std::string usets[] = {"SILACOID.PCK",
"CELATID.PCK",
"HANDOB.PCK",
"CYBER.PCK",
"FLOOROB.PCK",
"SECTOID.PCK",
"CIVF.PCK",
"CIVM.PCK",
"XCOM_1.PCK",
"SNAKEMAN.PCK",
"XCOM_0.PCK",
"CHRYS.PCK",
"TANKS.PCK",
"FLOATER.PCK",
"XCOM_2.PCK",
"ZOMBIE.PCK",
"MUTON.PCK",
"X_REAP.PCK",
"ETHEREAL.PCK",
"X_ROB.PCK"
};
for (int i = 0; i < 20; i++)
{
std::stringstream s;
s << _folder << "UNITS/" << usets[i];
std::string tab = usets[i].substr(0, usets[i].length()-4) + ".TAB";
std::stringstream s2;
s2 << _folder << "UNITS/" << tab;
_sets[usets[i]] = new SurfaceSet(32, 40);
_sets[usets[i]]->loadPck(insensitive(s.str()), insensitive(s2.str()));
}
}
}