mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-25 21:39:42 +00:00
94 lines
3.1 KiB
C++
94 lines
3.1 KiB
C++
#include "esm4reader.hpp"
|
|
|
|
ESM::ESM4Reader::ESM4Reader(bool oldHeader)
|
|
{
|
|
// TES4 header size is 4 bytes smaller than TES5 header
|
|
mReader.setRecHeaderSize(oldHeader ? sizeof(ESM4::RecordHeader)-4 : sizeof(ESM4::RecordHeader));
|
|
}
|
|
|
|
ESM::ESM4Reader::~ESM4Reader()
|
|
{
|
|
}
|
|
|
|
void ESM::ESM4Reader::openTes4File(const std::string &name)
|
|
{
|
|
mCtx.filename = name;
|
|
// WARNING: may throw
|
|
mCtx.leftFile = mReader.openTes4File(name);
|
|
mReader.registerForUpdates(this); // for updating mCtx.leftFile
|
|
|
|
mReader.getRecordHeader();
|
|
if (mReader.hdr().record.typeId == ESM4::REC_TES4)
|
|
{
|
|
mReader.loadHeader();
|
|
mCtx.leftFile -= mReader.hdr().record.dataSize;
|
|
|
|
// Hack: copy over values to TES3 header for getVer() and getRecordCount() to work
|
|
mHeader.mData.version = mReader.esmVersion();
|
|
mHeader.mData.records = mReader.numRecords();
|
|
|
|
mReader.buildLStringIndex(); // for localised strings in Skyrim
|
|
}
|
|
else
|
|
fail("Unknown file format");
|
|
}
|
|
|
|
ESM4::ReaderContext ESM::ESM4Reader::getESM4Context()
|
|
{
|
|
return mReader.getContext();
|
|
}
|
|
|
|
void ESM::ESM4Reader::restoreESM4Context(const ESM4::ReaderContext& ctx)
|
|
{
|
|
// Reopen the file if necessary
|
|
if (mCtx.filename != ctx.filename)
|
|
openTes4File(ctx.filename);
|
|
|
|
// mCtx.leftFile is the only thing used in the old context. Strictly speaking, updating it
|
|
// with the correct value is not really necessary since we're not going to load the rest of
|
|
// the file (most likely to load a CELL or LAND then be done with it).
|
|
mCtx.leftFile = mReader.getFileSize() - mReader.getFileOffset();
|
|
|
|
// restore group stack, load the header, etc.
|
|
mReader.restoreContext(ctx);
|
|
}
|
|
|
|
void ESM::ESM4Reader::restoreCellChildrenContext(const ESM4::ReaderContext& ctx)
|
|
{
|
|
// Reopen the file if necessary
|
|
if (mCtx.filename != ctx.filename)
|
|
openTes4File(ctx.filename);
|
|
|
|
mReader.restoreContext(ctx); // restore group stack, load the CELL header, etc.
|
|
if (mReader.hdr().record.typeId != ESM4::REC_CELL) // FIXME: testing only
|
|
fail("Restore Cell Children failed");
|
|
mReader.skipRecordData(); // skip the CELL record
|
|
|
|
mReader.getRecordHeader(); // load the header for cell child group (hopefully)
|
|
// this is a hack to load only the cell child group...
|
|
if (mReader.hdr().group.typeId == ESM4::REC_GRUP && mReader.hdr().group.type == ESM4::Grp_CellChild)
|
|
{
|
|
mCtx.leftFile = mReader.hdr().group.groupSize - ctx.recHeaderSize;
|
|
return;
|
|
}
|
|
|
|
// But some cells may have no child groups...
|
|
// Suspect "ICMarketDistrict" 7 18 is one, followed by cell record 00165F2C "ICMarketDistrict" 6 17
|
|
if (mReader.hdr().group.typeId != ESM4::REC_GRUP && mReader.hdr().record.typeId == ESM4::REC_CELL)
|
|
{
|
|
mCtx.leftFile = 0;
|
|
return;
|
|
}
|
|
|
|
// Maybe the group is completed
|
|
// See "ICMarketDistrict" 9 15 which is followed by a exterior sub-cell block
|
|
ESM4::ReaderContext tempCtx = mReader.getContext();
|
|
if (!tempCtx.groupStack.empty() && tempCtx.groupStack.back().second == 0)
|
|
{
|
|
mCtx.leftFile = 0;
|
|
return;
|
|
}
|
|
else
|
|
fail("Restore Cell Children failed");
|
|
|
|
}
|