From 2365ba2ce0268ad90751da961dc2ca957049720d Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Sat, 8 Apr 2023 15:51:47 +0200 Subject: [PATCH 1/2] Disable lazy loading --- apps/openmw/mwworld/cellstore.cpp | 51 +++++-------------------------- apps/openmw/mwworld/esmstore.hpp | 3 +- 2 files changed, 9 insertions(+), 45 deletions(-) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index eef9e757ee..6f0b83c3a7 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -762,55 +762,18 @@ namespace MWWorld template static void visitCell4References(const ESM4::Cell& cell, ESM::ReadersCache& readers, ReferenceInvocable&& invocable) { - auto stream = Files::openBinaryInputFileStream(cell.mReaderContext.filename); - stream->seekg(0); - - ESM4::Reader readerESM4( - std::move(stream), cell.mReaderContext.filename, MWBase::Environment::get().getResourceSystem()->getVFS()); - - readerESM4.setEncoder(readers.getStatelessEncoder()); - bool contextValid = cell.mReaderContext.filePos != std::streampos(-1); - if (contextValid) - readerESM4.restoreContext(cell.mReaderContext); - - while ( - (ESM::RefId::formIdRefId(readerESM4.currCell()) == cell.mId || !contextValid) && readerESM4.hasMoreRecs()) + for (const ESM4::Reference& ref : MWBase::Environment::get().getWorld()->getStore().get()) { - if (!contextValid) - readerESM4.exitGroupCheck(); - - auto onRecord = [&](ESM4::Reader& reader) { - auto recordType = static_cast(reader.hdr().record.typeId); - ESM::RecNameInts esm4RecName = static_cast(ESM::esm4Recname(recordType)); - if (esm4RecName == ESM::RecNameInts::REC_REFR4 && contextValid) - { - reader.getRecordData(); - ESM4::Reference ref; - ref.load(reader); - invocable(ref); - return true; - } - else if (esm4RecName == ESM::RecNameInts::REC_CELL4) - { - reader.getRecordData(); - ESM4::Cell cellToLoad; - cellToLoad.load(reader); // This is necessary to exit or to find the correct cell - if (cellToLoad.mId == cell.mId) - contextValid = true; - return true; - } - - return false; - }; - - if (!ESM4::ReaderUtils::readItem(readerESM4, onRecord, [&](ESM4::Reader& reader) {})) - break; + if (ref.mParent == cell.mId) + { + invocable(ref); + } } } void CellStore::listRefs(const ESM4::Cell& cell) { - visitCell4References(cell, mReaders, [&](ESM4::Reference& ref) { mIds.push_back(ref.mBaseObj); }); + visitCell4References(cell, mReaders, [&](const ESM4::Reference& ref) { mIds.push_back(ref.mBaseObj); }); } void CellStore::listRefs() @@ -874,7 +837,7 @@ namespace MWWorld void CellStore::loadRefs(const ESM4::Cell& cell, std::map& refNumToID) { - visitCell4References(cell, mReaders, [&](ESM4::Reference& ref) { loadRef(ref, false); }); + visitCell4References(cell, mReaders, [&](const ESM4::Reference& ref) { loadRef(ref, false); }); } void CellStore::loadRefs() diff --git a/apps/openmw/mwworld/esmstore.hpp b/apps/openmw/mwworld/esmstore.hpp index 5fff40262b..a2375859f0 100644 --- a/apps/openmw/mwworld/esmstore.hpp +++ b/apps/openmw/mwworld/esmstore.hpp @@ -30,6 +30,7 @@ namespace ESM4 struct Static; struct Cell; struct Light; + struct Reference; } namespace ESM @@ -105,7 +106,7 @@ namespace MWWorld // Special entry which is hardcoded and not loaded from an ESM Store, - Store, Store, Store>; + Store, Store, Store, Store>; private: template From f09a689a4f8b70be98f86825c873e9cbb64e7f64 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Fri, 7 Apr 2023 02:14:32 +0200 Subject: [PATCH 2/2] Merge ESM::RefNum and ESM4::FormId --- apps/opencs/model/doc/savingstages.cpp | 2 +- apps/openmw/mwlua/luaevents.cpp | 5 +- apps/openmw/mwlua/worldview.cpp | 6 +- apps/openmw/mwrender/renderingmanager.hpp | 3 +- apps/openmw/mwscript/globalscripts.hpp | 3 +- apps/openmw/mwworld/cellref.cpp | 45 +++++++------ apps/openmw/mwworld/cellstore.cpp | 5 +- apps/openmw/mwworld/cellstore.hpp | 3 +- apps/openmw/mwworld/esmloader.cpp | 4 ++ apps/openmw/mwworld/esmloader.hpp | 2 + apps/openmw/mwworld/worldimp.cpp | 3 +- apps/openmw/mwworld/worldmodel.hpp | 1 - apps/openmw_test_suite/esm/testrefid.cpp | 33 +++++----- apps/openmw_test_suite/esm3/testesmwriter.cpp | 2 +- components/CMakeLists.txt | 1 + components/esm/formid.cpp | 15 +++++ components/esm/formid.hpp | 63 +++++++++++++++++++ components/esm/formidrefid.cpp | 15 +++-- components/esm/formidrefid.hpp | 13 ++-- components/esm/refid.cpp | 7 ++- components/esm/refid.hpp | 4 +- components/esm3/activespells.cpp | 4 +- components/esm3/cellref.cpp | 32 +--------- components/esm3/cellref.hpp | 50 +-------------- components/esm3/esmreader.cpp | 12 +++- components/esm3/esmreader.hpp | 2 + components/esm3/esmwriter.cpp | 8 +++ components/esm3/esmwriter.hpp | 2 + components/esm3/globalscript.cpp | 4 +- components/esm4/actor.hpp | 2 +- components/esm4/cellgrid.hpp | 8 +-- components/esm4/effect.hpp | 2 +- components/esm4/formid.cpp | 42 +------------ components/esm4/formid.hpp | 15 ++--- components/esm4/inventory.hpp | 4 +- components/esm4/loadachr.cpp | 6 +- components/esm4/loadacre.cpp | 6 +- components/esm4/loadacti.cpp | 2 +- components/esm4/loadalch.cpp | 2 +- components/esm4/loadalch.hpp | 4 +- components/esm4/loadaloc.cpp | 2 +- components/esm4/loadammo.cpp | 2 +- components/esm4/loadanio.cpp | 2 +- components/esm4/loadappa.cpp | 2 +- components/esm4/loadarma.cpp | 2 +- components/esm4/loadarmo.cpp | 2 +- components/esm4/loadaspc.cpp | 2 +- components/esm4/loadbook.cpp | 2 +- components/esm4/loadbptd.cpp | 2 +- components/esm4/loadbptd.hpp | 12 ++-- components/esm4/loadcell.cpp | 12 ++-- components/esm4/loadcell.hpp | 1 - components/esm4/loadclas.cpp | 2 +- components/esm4/loadclfm.cpp | 2 +- components/esm4/loadclot.cpp | 2 +- components/esm4/loadcont.cpp | 2 +- components/esm4/loadcrea.cpp | 2 +- components/esm4/loaddial.cpp | 2 +- components/esm4/loaddobj.cpp | 2 +- components/esm4/loaddoor.cpp | 2 +- components/esm4/loadeyes.cpp | 2 +- components/esm4/loadflor.cpp | 2 +- components/esm4/loadflst.cpp | 2 +- components/esm4/loadfurn.cpp | 2 +- components/esm4/loadglob.cpp | 2 +- components/esm4/loadgmst.cpp | 11 ++-- components/esm4/loadgras.cpp | 2 +- components/esm4/loadhair.cpp | 2 +- components/esm4/loadhdpt.cpp | 2 +- components/esm4/loadidle.cpp | 2 +- components/esm4/loadidlm.cpp | 2 +- components/esm4/loadimod.cpp | 2 +- components/esm4/loadinfo.cpp | 2 +- components/esm4/loadingr.cpp | 2 +- components/esm4/loadkeym.cpp | 2 +- components/esm4/loadland.cpp | 9 +-- components/esm4/loadlgtm.cpp | 2 +- components/esm4/loadlgtm.hpp | 1 - components/esm4/loadligh.cpp | 2 +- components/esm4/loadltex.cpp | 2 +- components/esm4/loadlvlc.cpp | 2 +- components/esm4/loadlvli.cpp | 2 +- components/esm4/loadlvln.cpp | 2 +- components/esm4/loadmato.cpp | 2 +- components/esm4/loadmisc.cpp | 2 +- components/esm4/loadmset.cpp | 2 +- components/esm4/loadmstt.cpp | 2 +- components/esm4/loadmusc.cpp | 2 +- components/esm4/loadnavi.cpp | 17 +++-- components/esm4/loadnavi.hpp | 2 +- components/esm4/loadnavm.cpp | 14 +++-- components/esm4/loadnavm.hpp | 4 +- components/esm4/loadnote.cpp | 2 +- components/esm4/loadnpc.cpp | 2 +- components/esm4/loadotft.cpp | 4 +- components/esm4/loadpack.cpp | 2 +- components/esm4/loadpack.hpp | 8 +-- components/esm4/loadpgrd.cpp | 2 +- components/esm4/loadpgre.cpp | 2 +- components/esm4/loadpwat.cpp | 2 +- components/esm4/loadqust.cpp | 2 +- components/esm4/loadrace.cpp | 8 +-- components/esm4/loadrace.hpp | 1 - components/esm4/loadrefr.cpp | 6 +- components/esm4/loadregn.cpp | 2 +- components/esm4/loadregn.hpp | 2 +- components/esm4/loadroad.cpp | 2 +- components/esm4/loadsbsp.cpp | 2 +- components/esm4/loadscol.cpp | 2 +- components/esm4/loadscpt.cpp | 2 +- components/esm4/loadscrl.cpp | 2 +- components/esm4/loadsgst.cpp | 2 +- components/esm4/loadslgm.cpp | 2 +- components/esm4/loadsndr.cpp | 2 +- components/esm4/loadsoun.cpp | 2 +- components/esm4/loadstat.cpp | 2 +- components/esm4/loadtact.cpp | 2 +- components/esm4/loadterm.cpp | 2 +- components/esm4/loadtes4.cpp | 8 ++- components/esm4/loadtree.cpp | 2 +- components/esm4/loadtxst.cpp | 2 +- components/esm4/loadweap.cpp | 2 +- components/esm4/loadwrld.cpp | 2 +- components/esm4/reader.cpp | 63 +++++++------------ components/esm4/reader.hpp | 11 +++- components/esm4/reference.hpp | 2 +- components/esm4/script.hpp | 6 +- 127 files changed, 382 insertions(+), 394 deletions(-) create mode 100644 components/esm/formid.cpp create mode 100644 components/esm/formid.hpp diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index 64319d320e..4015a4b8bf 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -340,7 +340,7 @@ void CSMDoc::WriteCellCollectionStage::writeReferences( char ignore; istream >> ignore >> moved.mTarget[0] >> moved.mTarget[1]; - refRecord.mRefNum.save(writer, false, "MVRF"); + writer.writeFormId(refRecord.mRefNum, false, "MVRF"); writer.writeHNT("CNDT", moved.mTarget); } diff --git a/apps/openmw/mwlua/luaevents.cpp b/apps/openmw/mwlua/luaevents.cpp index 37828d4b13..b036fea3b6 100644 --- a/apps/openmw/mwlua/luaevents.cpp +++ b/apps/openmw/mwlua/luaevents.cpp @@ -55,7 +55,7 @@ namespace MWLua static void saveEvent(ESM::ESMWriter& esm, const ESM::RefNum& dest, const Event& event) { esm.writeHNString("LUAE", event.mEventName); - dest.save(esm, true); + esm.writeFormId(dest, true); if (!event.mEventData.empty()) saveLuaBinaryData(esm, event.mEventData); } @@ -67,8 +67,7 @@ namespace MWLua while (esm.isNextSub("LUAE")) { std::string name = esm.getHString(); - ESM::RefNum dest; - dest.load(esm, true); + ESM::RefNum dest = esm.getFormId(true); std::string data = loadLuaBinaryData(esm); try { diff --git a/apps/openmw/mwlua/worldview.cpp b/apps/openmw/mwlua/worldview.cpp index ba3c9e1a3c..9ccc1caaf8 100644 --- a/apps/openmw/mwlua/worldview.cpp +++ b/apps/openmw/mwlua/worldview.cpp @@ -82,15 +82,13 @@ namespace MWLua void WorldView::load(ESM::ESMReader& esm) { esm.getHNT(mSimulationTime, "LUAW"); - ObjectId lastAssignedId; - lastAssignedId.load(esm, true); - MWBase::Environment::get().getWorldModel()->setLastGeneratedRefNum(lastAssignedId); + MWBase::Environment::get().getWorldModel()->setLastGeneratedRefNum(esm.getFormId(true)); } void WorldView::save(ESM::ESMWriter& esm) const { esm.writeHNT("LUAW", mSimulationTime); - MWBase::Environment::get().getWorldModel()->getLastGeneratedRefNum().save(esm, true); + esm.writeFormId(MWBase::Environment::get().getWorldModel()->getLastGeneratedRefNum(), true); } void WorldView::ObjectGroup::updateList() diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 75da41af3f..b038e76b16 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -42,7 +42,8 @@ namespace osgViewer namespace ESM { struct Cell; - struct RefNum; + struct FormId; + using RefNum = FormId; } namespace Terrain diff --git a/apps/openmw/mwscript/globalscripts.hpp b/apps/openmw/mwscript/globalscripts.hpp index 27d81e1ea1..74d8c94f98 100644 --- a/apps/openmw/mwscript/globalscripts.hpp +++ b/apps/openmw/mwscript/globalscripts.hpp @@ -21,7 +21,8 @@ namespace ESM { class ESMWriter; class ESMReader; - struct RefNum; + struct FormId; + using RefNum = FormId; } namespace Loading diff --git a/apps/openmw/mwworld/cellref.cpp b/apps/openmw/mwworld/cellref.cpp index ced128db40..7442dfe6a4 100644 --- a/apps/openmw/mwworld/cellref.cpp +++ b/apps/openmw/mwworld/cellref.cpp @@ -25,7 +25,7 @@ namespace MWWorld const ESM::RefNum& CellRef::getRefNum() const { return std::visit(ESM::VisitOverload{ - [&](const ESM4::Reference& /*ref*/) -> const ESM::RefNum& { return emptyRefNum; }, + [&](const ESM4::Reference& ref) -> const ESM::RefNum& { return ref.mFormId; }, [&](const ESM::CellRef& ref) -> const ESM::RefNum& { return ref.mRefNum; }, }, mCellRef.mVariant); @@ -33,36 +33,33 @@ namespace MWWorld const ESM::RefNum& CellRef::getOrAssignRefNum(ESM::RefNum& lastAssignedRefNum) { - auto esm3Visit = [&](ESM::CellRef& ref) -> const ESM::RefNum& { - if (!ref.mRefNum.isSet()) + ESM::RefNum& refNum = std::visit(ESM::VisitOverload{ + [&](ESM4::Reference& ref) -> ESM::RefNum& { return ref.mFormId; }, + [&](ESM::CellRef& ref) -> ESM::RefNum& { return ref.mRefNum; }, + }, + mCellRef.mVariant); + if (!refNum.isSet()) + { + // Generated RefNums have negative mContentFile + assert(lastAssignedRefNum.mContentFile < 0); + lastAssignedRefNum.mIndex++; + if (lastAssignedRefNum.mIndex == 0) // mIndex overflow, so mContentFile should be changed { - // Generated RefNums have negative mContentFile - assert(lastAssignedRefNum.mContentFile < 0); - lastAssignedRefNum.mIndex++; - if (lastAssignedRefNum.mIndex == 0) // mIndex overflow, so mContentFile should be changed - { - if (lastAssignedRefNum.mContentFile > std::numeric_limits::min()) - lastAssignedRefNum.mContentFile--; - else - Log(Debug::Error) << "RefNum counter overflow in CellRef::getOrAssignRefNum"; - } - ref.mRefNum = lastAssignedRefNum; - mChanged = true; + if (lastAssignedRefNum.mContentFile > std::numeric_limits::min()) + lastAssignedRefNum.mContentFile--; + else + Log(Debug::Error) << "RefNum counter overflow in CellRef::getOrAssignRefNum"; } - return ref.mRefNum; - }; - return std::visit( - ESM::VisitOverload{ - [&](ESM4::Reference& /*ref*/) -> const ESM::RefNum& { return emptyRefNum; }, - esm3Visit, - }, - mCellRef.mVariant); + refNum = lastAssignedRefNum; + mChanged = true; + } + return refNum; } void CellRef::unsetRefNum() { std::visit(ESM::VisitOverload{ - [&](ESM4::Reference& /*ref*/) {}, + [&](ESM4::Reference& ref) { ref.mFormId = emptyRefNum; }, [&](ESM::CellRef& ref) { ref.mRefNum = emptyRefNum; }, }, mCellRef.mVariant); diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 6f0b83c3a7..82e310c156 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -983,7 +983,7 @@ namespace MWWorld ESM::RefNum refNum = base->mRef.getRefNum(); ESM::RefId movedTo = store->getCell()->getId(); - refNum.save(writer, true, "MVRF"); + writer.writeFormId(refNum, true, "MVRF"); writer.writeCellId(movedTo); } } @@ -1039,8 +1039,7 @@ namespace MWWorld while (reader.isNextSub("MVRF")) { reader.cacheSubName(); - ESM::RefNum refnum; - refnum.load(reader, true, "MVRF"); + ESM::RefNum refnum = reader.getFormId(true, "MVRF"); ESM::RefId movedToId = reader.getCellId(); if (refnum.hasContentFile()) { diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 451f480e51..23b0a84443 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -27,7 +27,8 @@ namespace ESM class ReadersCache; struct Cell; struct CellState; - struct RefNum; + struct FormId; + using RefNum = FormId; struct Activator; struct Potion; struct Apparatus; diff --git a/apps/openmw/mwworld/esmloader.cpp b/apps/openmw/mwworld/esmloader.cpp index 24f63eafc4..9190d53ea5 100644 --- a/apps/openmw/mwworld/esmloader.cpp +++ b/apps/openmw/mwworld/esmloader.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "../mwbase/environment.hpp" @@ -66,10 +67,13 @@ namespace MWWorld ESM4::Reader readerESM4( std::move(stream), filepath, MWBase::Environment::get().getResourceSystem()->getVFS()); readerESM4.setEncoder(mReaders.getStatelessEncoder()); + readerESM4.setModIndex(index); + readerESM4.updateModIndices(mNameToIndex); mStore.loadESM4(readerESM4); break; } } + mNameToIndex[Misc::StringUtils::lowerCase(Files::pathToUnicodeString(filepath.filename()))] = index; } } /* namespace MWWorld */ diff --git a/apps/openmw/mwworld/esmloader.hpp b/apps/openmw/mwworld/esmloader.hpp index 253c58db70..53bff939c4 100644 --- a/apps/openmw/mwworld/esmloader.hpp +++ b/apps/openmw/mwworld/esmloader.hpp @@ -1,6 +1,7 @@ #ifndef ESMLOADER_HPP #define ESMLOADER_HPP +#include #include #include @@ -38,6 +39,7 @@ namespace MWWorld ESM::Dialogue* mDialogue; std::optional mMasterFileFormat; std::vector& mESMVersions; + std::map mNameToIndex; }; } /* namespace MWWorld */ diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index d756d5a5b8..df0b0bcb3e 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2848,8 +2848,9 @@ namespace MWWorld { foundCell = findInteriorPosition(cellName, pos); } - catch (std::exception&) + catch (std::exception& e) { + Log(Debug::Error) << e.what(); } if (foundCell.empty()) { diff --git a/apps/openmw/mwworld/worldmodel.hpp b/apps/openmw/mwworld/worldmodel.hpp index 10292c3ca5..f415a9d48a 100644 --- a/apps/openmw/mwworld/worldmodel.hpp +++ b/apps/openmw/mwworld/worldmodel.hpp @@ -18,7 +18,6 @@ namespace ESM class ESMWriter; class ReadersCache; struct Cell; - struct RefNum; } namespace ESM4 diff --git a/apps/openmw_test_suite/esm/testrefid.cpp b/apps/openmw_test_suite/esm/testrefid.cpp index 65fe27605c..8e25ddbb6d 100644 --- a/apps/openmw_test_suite/esm/testrefid.cpp +++ b/apps/openmw_test_suite/esm/testrefid.cpp @@ -26,7 +26,7 @@ namespace ESM TEST(ESMRefIdTest, formIdRefIdIsNotEmpty) { - const RefId refId = RefId::formIdRefId(42); + const RefId refId = RefId::formIdRefId({ 42, 0 }); EXPECT_FALSE(refId.empty()); } @@ -53,7 +53,7 @@ namespace ESM TEST(ESMRefIdTest, defaultConstructedIsNotEqualToFormIdRefId) { const RefId a; - const RefId b = RefId::formIdRefId(42); + const RefId b = RefId::formIdRefId({ 42, 0 }); EXPECT_NE(a, b); } @@ -98,8 +98,8 @@ namespace ESM TEST(ESMRefIdTest, equalityIsDefinedForFormRefIdAndRefId) { - const FormIdRefId formIdRefId(42); - const RefId refId = RefId::formIdRefId(42); + const FormIdRefId formIdRefId({ 42, 0 }); + const RefId refId = RefId::formIdRefId({ 42, 0 }); EXPECT_EQ(formIdRefId, refId); } @@ -125,8 +125,8 @@ namespace ESM TEST(ESMRefIdTest, lessThanIsDefinedForFormRefIdAndRefId) { - const FormIdRefId formIdRefId(13); - const RefId refId = RefId::formIdRefId(42); + const FormIdRefId formIdRefId({ 13, 0 }); + const RefId refId = RefId::formIdRefId({ 42, 0 }); EXPECT_LT(formIdRefId, refId); } @@ -164,14 +164,14 @@ namespace ESM TEST(ESMRefIdTest, stringRefIdHasStrongOrderWithFormId) { const RefId stringRefId = RefId::stringRefId("a"); - const RefId formIdRefId = RefId::formIdRefId(42); + const RefId formIdRefId = RefId::formIdRefId({ 42, 0 }); EXPECT_TRUE(stringRefId < formIdRefId); EXPECT_FALSE(formIdRefId < stringRefId); } TEST(ESMRefIdTest, formIdRefIdHasStrongOrderWithStringView) { - const RefId formIdRefId = RefId::formIdRefId(42); + const RefId formIdRefId = RefId::formIdRefId({ 42, 0 }); const std::string_view stringView = "42"; EXPECT_TRUE(stringView < formIdRefId); EXPECT_FALSE(formIdRefId < stringView); @@ -192,7 +192,7 @@ namespace ESM TEST(ESMRefIdTest, stringRefIdIsNotEqualToFormId) { const RefId stringRefId = RefId::stringRefId("\0"); - const RefId formIdRefId = RefId::formIdRefId(0); + const RefId formIdRefId = RefId::formIdRefId({ 0, 0 }); EXPECT_NE(stringRefId, formIdRefId); } @@ -235,7 +235,7 @@ namespace ESM { RefId(), std::string() }, { RefId::stringRefId("foo"), "foo" }, { RefId::stringRefId(std::string({ 'a', 0, -1, '\n', '\t' })), { 'a', 0, -1, '\n', '\t' } }, - { RefId::formIdRefId(42), "0x2a" }, + { RefId::formIdRefId({ 42, 0 }), "0x2a" }, { RefId::generated(42), "0x2a" }, { RefId::index(REC_ARMO, 42), "ARMO:0x2a" }, { RefId::esm3ExteriorCell(-13, 42), "-13:42" }, @@ -268,7 +268,7 @@ namespace ESM { RefId::stringRefId("foo"), "\"foo\"" }, { RefId::stringRefId("BAR"), "\"BAR\"" }, { RefId::stringRefId(std::string({ 'a', 0, -1, '\n', '\t' })), "\"a\\x0\\xFF\\xA\\x9\"" }, - { RefId::formIdRefId(42), "FormId:0x2a" }, + { RefId::formIdRefId({ 42, 0 }), "FormId:0x2a" }, { RefId::generated(42), "Generated:0x2a" }, { RefId::index(REC_ARMO, 42), "Index:ARMO:0x2a" }, { RefId::esm3ExteriorCell(-13, 42), "Esm3ExteriorCell:-13:42" }, @@ -295,10 +295,11 @@ namespace ESM { RefId::stringRefId("foo"), "foo" }, { RefId::stringRefId("BAR"), "bar" }, { RefId::stringRefId(std::string({ 'a', 0, -1, '\n', '\t' })), { 'a', 0, -1, '\n', '\t' } }, - { RefId::formIdRefId(0), "FormId:0x0" }, - { RefId::formIdRefId(1), "FormId:0x1" }, - { RefId::formIdRefId(0x1f), "FormId:0x1f" }, - { RefId::formIdRefId(std::numeric_limits::max()), "FormId:0xffffffff" }, + { RefId::formIdRefId({ 0, 0 }), "FormId:0x0" }, + { RefId::formIdRefId({ 1, 0 }), "FormId:0x1" }, + { RefId::formIdRefId({ 0x1f, 0 }), "FormId:0x1f" }, + { RefId::formIdRefId({ 0x1f, 2 }), "FormId:0x200001f" }, + { RefId::formIdRefId({ 0xffffff, 0x1abc }), "FormId:0x1abcffffff" }, { RefId::generated(0), "Generated:0x0" }, { RefId::generated(1), "Generated:0x1" }, { RefId::generated(0x1f), "Generated:0x1f" }, @@ -344,7 +345,7 @@ namespace ESM template <> struct GenerateRefId { - static RefId call() { return RefId::formIdRefId(42); } + static RefId call() { return RefId::formIdRefId({ 42, 0 }); } }; template <> diff --git a/apps/openmw_test_suite/esm3/testesmwriter.cpp b/apps/openmw_test_suite/esm3/testesmwriter.cpp index 7ea5be14fc..9e9ae9947e 100644 --- a/apps/openmw_test_suite/esm3/testesmwriter.cpp +++ b/apps/openmw_test_suite/esm3/testesmwriter.cpp @@ -76,7 +76,7 @@ namespace ESM const std::vector> refIdSizes = { { RefId(), 57 }, { RefId::stringRefId(std::string(32, 'a')), 89 }, - { RefId::formIdRefId(0x1f), 61 }, + { RefId::formIdRefId({ 0x1f, 0 }), 65 }, { RefId::generated(0x1f), 65 }, { RefId::index(REC_INGR, 0x1f), 65 }, { RefId::esm3ExteriorCell(-42, 42), 65 }, diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 8435fa342d..58f0981e7f 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -86,6 +86,7 @@ add_component_dir (to_utf8 ) add_component_dir(esm attr common defs esmcommon records util luascripts format refid esmbridge + formid formidrefid stringrefid generatedrefid diff --git a/components/esm/formid.cpp b/components/esm/formid.cpp new file mode 100644 index 0000000000..a0b4c56a70 --- /dev/null +++ b/components/esm/formid.cpp @@ -0,0 +1,15 @@ +#include "formid.hpp" + +std::string ESM::FormId::toString() const +{ + return std::to_string(mIndex) + "_" + std::to_string(mContentFile); +} + +uint32_t ESM::FormId::toUint32() const +{ + if (isSet() && !hasContentFile()) + throw std::runtime_error("Generated FormId can not be converted to 32bit format"); + if (mContentFile > 0xfe) + throw std::runtime_error("FormId with mContentFile > 0xFE can not be converted to 32bit format"); + return (mIndex & 0xffffff) | ((hasContentFile() ? mContentFile : 0xff) << 24); +} diff --git a/components/esm/formid.hpp b/components/esm/formid.hpp new file mode 100644 index 0000000000..ba25a0fa26 --- /dev/null +++ b/components/esm/formid.hpp @@ -0,0 +1,63 @@ +#ifndef COMPONENT_ESM_FORMID_H +#define COMPONENT_ESM_FORMID_H + +#include +#include +#include +#include +#include + +namespace ESM +{ + using FormId32 = uint32_t; + struct FormId + { + uint32_t mIndex = 0; + int32_t mContentFile = -1; + + bool hasContentFile() const { return mContentFile >= 0; } + bool isSet() const { return mIndex != 0 || mContentFile != -1; } + + // Used in ESM4 as a null reference + bool isZero() const { return mIndex == 0 && mContentFile == 0; } + + std::string toString() const; + FormId32 toUint32() const; + static FormId fromUint32(FormId32 v) { return { v & 0xffffff, static_cast(v >> 24) }; } + }; + + inline constexpr bool operator==(const FormId& left, const FormId& right) + { + return left.mIndex == right.mIndex && left.mContentFile == right.mContentFile; + } + + inline constexpr bool operator<(const FormId& left, const FormId& right) + { + return std::tie(left.mIndex, left.mContentFile) < std::tie(right.mIndex, right.mContentFile); + } + + inline std::ostream& operator<<(std::ostream& stream, const FormId& formId) + { + return stream << formId.toString(); + } +} + +namespace std +{ + + // Needed to use ESM::FormId as a key in std::unordered_map + template <> + struct hash + { + size_t operator()(const ESM::FormId& formId) const + { + static_assert(sizeof(ESM::FormId) == sizeof(size_t)); + size_t s; + memcpy(&s, &formId, sizeof(size_t)); + return hash()(s); + } + }; + +} + +#endif // COMPONENT_ESM_FORMID_H diff --git a/components/esm/formidrefid.cpp b/components/esm/formidrefid.cpp index 91790e503a..8e452d6ecd 100644 --- a/components/esm/formidrefid.cpp +++ b/components/esm/formidrefid.cpp @@ -1,23 +1,28 @@ #include "formidrefid.hpp" -#include "serializerefid.hpp" - +#include #include +#include "serializerefid.hpp" + namespace ESM { std::string FormIdRefId::toString() const { std::string result; - result.resize(getHexIntegralSize(mValue) + 2, '\0'); - serializeHexIntegral(mValue, 0, result); + assert((mValue.mIndex & 0xff000000) == 0); + size_t v = (static_cast(mValue.mContentFile) << 24) | mValue.mIndex; + result.resize(getHexIntegralSize(v) + 2, '\0'); + serializeHexIntegral(v, 0, result); return result; } std::string FormIdRefId::toDebugString() const { std::string result; - serializeRefIdValue(mValue, formIdRefIdPrefix, result); + assert((mValue.mIndex & 0xff000000) == 0); + size_t v = (static_cast(mValue.mContentFile) << 24) | mValue.mIndex; + serializeRefIdValue(v, formIdRefIdPrefix, result); return result; } diff --git a/components/esm/formidrefid.hpp b/components/esm/formidrefid.hpp index 30f868f4da..176dc4ec84 100644 --- a/components/esm/formidrefid.hpp +++ b/components/esm/formidrefid.hpp @@ -4,7 +4,7 @@ #include #include -#include +#include namespace ESM { @@ -13,12 +13,12 @@ namespace ESM public: constexpr FormIdRefId() = default; - constexpr explicit FormIdRefId(ESM4::FormId value) noexcept + constexpr explicit FormIdRefId(ESM::FormId value) noexcept : mValue(value) { } - ESM4::FormId getValue() const { return mValue; } + ESM::FormId getValue() const { return mValue; } std::string toString() const; @@ -33,7 +33,7 @@ namespace ESM friend struct std::hash; private: - ESM4::FormId mValue = 0; + ESM::FormId mValue; }; } @@ -42,10 +42,7 @@ namespace std template <> struct hash { - std::size_t operator()(ESM::FormIdRefId value) const noexcept - { - return std::hash{}(value.mValue); - } + std::size_t operator()(ESM::FormIdRefId value) const noexcept { return std::hash{}(value.mValue); } }; } diff --git a/components/esm/refid.cpp b/components/esm/refid.cpp index b24ef82cf6..4011fca8ec 100644 --- a/components/esm/refid.cpp +++ b/components/esm/refid.cpp @@ -225,7 +225,12 @@ namespace ESM return ESM::RefId(); if (value.starts_with(formIdRefIdPrefix)) - return ESM::RefId::formIdRefId(deserializeHexIntegral(formIdRefIdPrefix.size(), value)); + { + uint64_t v = deserializeHexIntegral(formIdRefIdPrefix.size(), value); + uint32_t index = static_cast(v) & 0xffffff; + int contentFile = static_cast(v >> 24); + return ESM::RefId::formIdRefId({ index, contentFile }); + } if (value.starts_with(generatedRefIdPrefix)) return ESM::RefId::generated(deserializeHexIntegral(generatedRefIdPrefix.size(), value)); diff --git a/components/esm/refid.hpp b/components/esm/refid.hpp index 3fafdb0b74..3722c8db68 100644 --- a/components/esm/refid.hpp +++ b/components/esm/refid.hpp @@ -62,8 +62,8 @@ namespace ESM // Constructs RefId from a string using a pointer to a static set of strings. static RefId stringRefId(std::string_view value); - // Constructs RefId from ESM4 FormId storing the value in-place. - static RefId formIdRefId(ESM4::FormId value) noexcept { return RefId(FormIdRefId(value)); } + // Constructs RefId from FormId storing the value in-place. + static RefId formIdRefId(FormId value) noexcept { return RefId(FormIdRefId(value)); } // Constructs RefId from uint64 storing the value in-place. Should be used for generated records where id is a // global counter. diff --git a/components/esm3/activespells.cpp b/components/esm3/activespells.cpp index c03200d3ae..97d56d1a2b 100644 --- a/components/esm3/activespells.cpp +++ b/components/esm3/activespells.cpp @@ -17,7 +17,7 @@ namespace ESM esm.writeHNString("DISP", params.mDisplayName); esm.writeHNT("TYPE", params.mType); if (params.mItem.isSet()) - params.mItem.save(esm, true, "ITEM"); + esm.writeFormId(params.mItem, true, "ITEM"); if (params.mWorsenings >= 0) { esm.writeHNT("WORS", params.mWorsenings); @@ -56,7 +56,7 @@ namespace ESM { esm.getHNT(params.mType, "TYPE"); if (esm.peekNextSub("ITEM")) - params.mItem.load(esm, true, "ITEM"); + params.mItem = esm.getFormId(true, "ITEM"); } if (esm.isNextSub("WORS")) { diff --git a/components/esm3/cellref.cpp b/components/esm3/cellref.cpp index d765497948..fafab6bcac 100644 --- a/components/esm3/cellref.cpp +++ b/components/esm3/cellref.cpp @@ -24,7 +24,7 @@ namespace ESM if constexpr (load) { cellRef.blank(); - cellRef.mRefNum.load(esm, wideRefNum); + cellRef.mRefNum = esm.getFormId(wideRefNum); cellRef.mRefID = esm.getHNORefId("NAME"); if (cellRef.mRefID.empty()) @@ -33,7 +33,7 @@ namespace ESM } else { - RefNum{}.load(esm, wideRefNum); + esm.getFormId(wideRefNum); esm.skipHNORefId("NAME"); } } @@ -154,32 +154,6 @@ namespace ESM } } - void RefNum::load(ESMReader& esm, bool wide, NAME tag) - { - if (wide) - esm.getHNTSized<8>(*this, tag); - else - esm.getHNT(mIndex, tag); - } - - void RefNum::save(ESMWriter& esm, bool wide, NAME tag) const - { - if (wide) - esm.writeHNT(tag, *this, 8); - else - { - if (isSet() && !hasContentFile()) - throw std::runtime_error("Generated RefNum can not be saved in 32bit format"); - int refNum = (mIndex & 0xffffff) | ((hasContentFile() ? mContentFile : 0xff) << 24); - esm.writeHNT(tag, refNum, 4); - } - } - - std::string RefNum::toString() const - { - return std::to_string(mIndex) + "_" + std::to_string(mContentFile); - } - void CellRef::load(ESMReader& esm, bool& isDeleted, bool wideRefNum) { loadId(esm, wideRefNum); @@ -198,7 +172,7 @@ namespace ESM void CellRef::save(ESMWriter& esm, bool wideRefNum, bool inInventory, bool isDeleted) const { - mRefNum.save(esm, wideRefNum); + esm.writeFormId(mRefNum, wideRefNum); esm.writeHNCRefId("NAME", mRefID); diff --git a/components/esm3/cellref.hpp b/components/esm3/cellref.hpp index 0ea118178f..8a5416d674 100644 --- a/components/esm3/cellref.hpp +++ b/components/esm3/cellref.hpp @@ -4,6 +4,7 @@ #include #include +#include "components/esm/common.hpp" #include "components/esm/defs.hpp" #include "components/esm/esmcommon.hpp" #include "components/esm/refid.hpp" @@ -15,21 +16,7 @@ namespace ESM const int UnbreakableLock = std::numeric_limits::max(); - struct RefNum - { - unsigned int mIndex = 0; - int mContentFile = -1; - - void load(ESMReader& esm, bool wide = false, NAME tag = "FRMR"); - - void save(ESMWriter& esm, bool wide = false, NAME tag = "FRMR") const; - - inline bool hasContentFile() const { return mContentFile >= 0; } - - inline bool isSet() const { return mIndex != 0 || mContentFile != -1; } - - std::string toString() const; - }; + using RefNum = ESM::FormId; /* Cell reference. This represents ONE object (of many) inside the cell. The cell references are not loaded as part of the normal @@ -119,39 +106,6 @@ namespace ESM }; void skipLoadCellRef(ESMReader& esm, bool wideRefNum = false); - - inline bool operator==(const RefNum& left, const RefNum& right) - { - return left.mIndex == right.mIndex && left.mContentFile == right.mContentFile; - } - - inline bool operator<(const RefNum& left, const RefNum& right) - { - if (left.mIndex < right.mIndex) - return true; - if (left.mIndex > right.mIndex) - return false; - return left.mContentFile < right.mContentFile; - } - -} - -namespace std -{ - - // Needed to use ESM::RefNum as a key in std::unordered_map - template <> - struct hash - { - size_t operator()(const ESM::RefNum& refNum) const - { - assert(sizeof(ESM::RefNum) == sizeof(size_t)); - size_t s; - memcpy(&s, &refNum, sizeof(size_t)); - return hash()(s); - } - }; - } #endif diff --git a/components/esm3/esmreader.cpp b/components/esm3/esmreader.cpp index 42a2b2898a..1cafac7e78 100644 --- a/components/esm3/esmreader.cpp +++ b/components/esm3/esmreader.cpp @@ -248,6 +248,16 @@ namespace ESM getHExact(p, size); } + FormId ESMReader::getFormId(bool wide, NAME tag) + { + FormId res; + if (wide) + getHNTSized<8>(res, tag); + else + getHNT(res.mIndex, tag); + return res; + } + // Get the next subrecord name and check if it matches the parameter void ESMReader::getSubNameIs(NAME name) { @@ -473,7 +483,7 @@ namespace ESM return RefId::stringRefId(getStringView(size - sizeof(refIdType))); case RefIdType::FormId: { - ESM4::FormId formId{}; + FormId formId{}; getT(formId); return RefId::formIdRefId(formId); } diff --git a/components/esm3/esmreader.hpp b/components/esm3/esmreader.hpp index 703f10be0c..71611e58be 100644 --- a/components/esm3/esmreader.hpp +++ b/components/esm3/esmreader.hpp @@ -195,6 +195,8 @@ namespace ESM // Read the given number of bytes from a named subrecord void getHNExact(void* p, int size, NAME name); + ESM::FormId getFormId(bool wide = false, NAME tag = "FRMR"); + /************************************************************************* * * Low level sub-record methods diff --git a/components/esm3/esmwriter.cpp b/components/esm3/esmwriter.cpp index 59a3711b2d..2a64948d24 100644 --- a/components/esm3/esmwriter.cpp +++ b/components/esm3/esmwriter.cpp @@ -340,6 +340,14 @@ namespace ESM mStream->write(data, size); } + void ESMWriter::writeFormId(const FormId& formId, bool wide, NAME tag) + { + if (wide) + writeHNT(tag, formId, 8); + else + writeHNT(tag, formId.toUint32(), 4); + } + void ESMWriter::setEncoder(ToUTF8::Utf8Encoder* encoder) { mEncoder = encoder; diff --git a/components/esm3/esmwriter.hpp b/components/esm3/esmwriter.hpp index acf9488d9a..5086005b1f 100644 --- a/components/esm3/esmwriter.hpp +++ b/components/esm3/esmwriter.hpp @@ -179,6 +179,8 @@ namespace ESM void write(const char* data, size_t size); + void writeFormId(const ESM::FormId&, bool wide = false, NAME tag = "FRMR"); + private: std::list mRecords; std::ostream* mStream; diff --git a/components/esm3/globalscript.cpp b/components/esm3/globalscript.cpp index 73ca10018c..b0436c0e61 100644 --- a/components/esm3/globalscript.cpp +++ b/components/esm3/globalscript.cpp @@ -18,7 +18,7 @@ namespace ESM mTargetRef = RefNum{}; mTargetId = esm.getHNORefId("TARG"); if (esm.peekNextSub("FRMR")) - mTargetRef.load(esm, true, "FRMR"); + mTargetRef = esm.getFormId(true, "FRMR"); } void GlobalScript::save(ESMWriter& esm) const @@ -34,7 +34,7 @@ namespace ESM { esm.writeHNORefId("TARG", mTargetId); if (mTargetRef.isSet()) - mTargetRef.save(esm, true, "FRMR"); + esm.writeFormId(mTargetRef, true, "FRMR"); } } diff --git a/components/esm4/actor.hpp b/components/esm4/actor.hpp index 1020008240..e8a946f134 100644 --- a/components/esm4/actor.hpp +++ b/components/esm4/actor.hpp @@ -109,7 +109,7 @@ namespace ESM4 struct ActorFaction { - FormId faction; + FormId32 faction; std::int8_t rank; std::uint8_t unknown1; std::uint8_t unknown2; diff --git a/components/esm4/cellgrid.hpp b/components/esm4/cellgrid.hpp index 70f2546e3d..7f1a2e8452 100644 --- a/components/esm4/cellgrid.hpp +++ b/components/esm4/cellgrid.hpp @@ -27,18 +27,14 @@ #ifndef OPENMW_COMPONENTS_ESM4_CELLGRID_H #define OPENMW_COMPONENTS_ESM4_CELLGRID_H -#include +#include #include "formid.hpp" #include "grid.hpp" namespace ESM4 { - union CellGrid - { - FormId cellId; - Grid grid; - }; + using CellGrid = std::variant; } #endif // OPENMW_COMPONENTS_ESM4_CELLGRID_H diff --git a/components/esm4/effect.hpp b/components/esm4/effect.hpp index c83f9790fb..f49a6749b4 100644 --- a/components/esm4/effect.hpp +++ b/components/esm4/effect.hpp @@ -42,7 +42,7 @@ namespace ESM4 struct ScriptEffect { - FormId formId; // Script effect (Magic effect must be SEFF) + FormId32 formId; // Script effect (Magic effect must be SEFF) std::int32_t school; // Magic school. See Magic schools for more information. EFI_Label visualEffect; // Visual effect name or 0x00000000 if None std::uint8_t flags; // 0x01 = Hostile diff --git a/components/esm4/formid.cpp b/components/esm4/formid.cpp index c7655ce816..d091bdf8be 100644 --- a/components/esm4/formid.cpp +++ b/components/esm4/formid.cpp @@ -22,56 +22,20 @@ */ #include "formid.hpp" -#include #include #include -#include namespace ESM4 { - void formIdToString(FormId formId, std::string& str) + std::string formIdToString(const FormId& formId) { + std::string str; char buf[8 + 1]; - int res = snprintf(buf, 8 + 1, "%08X", formId); + int res = snprintf(buf, 8 + 1, "%08X", formId.toUint32()); if (res > 0 && res < 8 + 1) str.assign(buf); else throw std::runtime_error("Possible buffer overflow while converting formId"); - } - - std::string formIdToString(FormId formId) - { - std::string str; - formIdToString(formId, str); return str; } - - bool isFormId(const std::string& str, FormId* id) - { - if (str.size() != 8) - return false; - - unsigned long value = 0; - - if (auto [_ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), value, 16); ec != std::errc()) - return false; - - if (id != nullptr) - *id = static_cast(value); - - return true; - } - - FormId stringToFormId(const std::string& str) - { - if (str.size() != 8) - throw std::out_of_range("StringToFormId: incorrect string size"); - - unsigned long value = 0; - - if (auto [_ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), value, 16); ec != std::errc()) - throw std::invalid_argument("StringToFormId: string not a valid hexadecimal number"); - - return static_cast(value); - } } diff --git a/components/esm4/formid.hpp b/components/esm4/formid.hpp index d2baaa989d..284da67ad7 100644 --- a/components/esm4/formid.hpp +++ b/components/esm4/formid.hpp @@ -23,20 +23,15 @@ #ifndef ESM4_FORMID_H #define ESM4_FORMID_H -#include #include +#include + namespace ESM4 { - typedef std::uint32_t FormId; - - void formIdToString(FormId formId, std::string& str); - - std::string formIdToString(FormId formId); - - bool isFormId(const std::string& str, FormId* id = nullptr); - - FormId stringToFormId(const std::string& str); + using FormId = ESM::FormId; + using FormId32 = uint32_t; + std::string formIdToString(const FormId& formId); } #endif // ESM4_FORMID_H diff --git a/components/esm4/inventory.hpp b/components/esm4/inventory.hpp index d072749b47..eb49c5ef06 100644 --- a/components/esm4/inventory.hpp +++ b/components/esm4/inventory.hpp @@ -39,14 +39,14 @@ namespace ESM4 { std::int16_t level; std::uint16_t unknown; // sometimes missing - FormId item; + FormId32 item; std::int16_t count; std::uint16_t unknown2; // sometimes missing }; struct InventoryItem // NPC_, CREA, CONT { - FormId item; + FormId32 item; std::uint32_t count; }; #pragma pack(pop) diff --git a/components/esm4/loadachr.cpp b/components/esm4/loadachr.cpp index 97f23e9c49..d947b7c4d8 100644 --- a/components/esm4/loadachr.cpp +++ b/components/esm4/loadachr.cpp @@ -34,7 +34,7 @@ void ESM4::ActorCharacter::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; mParent = reader.currCell(); // NOTE: only for persistent achr? (aren't they all persistent?) @@ -64,8 +64,8 @@ void ESM4::ActorCharacter::load(ESM4::Reader& reader) break; case ESM4::SUB_XESP: { - reader.get(mEsp); - reader.adjustFormId(mEsp.parent); + reader.getFormId(mEsp.parent); + reader.get(mEsp.flags); break; } case ESM4::SUB_XRGD: // ragdoll diff --git a/components/esm4/loadacre.cpp b/components/esm4/loadacre.cpp index 8dfa9104a1..e152376757 100644 --- a/components/esm4/loadacre.cpp +++ b/components/esm4/loadacre.cpp @@ -34,7 +34,7 @@ void ESM4::ActorCreature::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; @@ -57,8 +57,8 @@ void ESM4::ActorCreature::load(ESM4::Reader& reader) break; case ESM4::SUB_XESP: { - reader.get(mEsp); - reader.adjustFormId(mEsp.parent); + reader.getFormId(mEsp.parent); + reader.get(mEsp.flags); break; } case ESM4::SUB_XOWN: diff --git a/components/esm4/loadacti.cpp b/components/esm4/loadacti.cpp index 3b86a2e3c4..c69c6d0fd6 100644 --- a/components/esm4/loadacti.cpp +++ b/components/esm4/loadacti.cpp @@ -34,7 +34,7 @@ void ESM4::Activator::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadalch.cpp b/components/esm4/loadalch.cpp index 7a2427dc45..0c8205fba7 100644 --- a/components/esm4/loadalch.cpp +++ b/components/esm4/loadalch.cpp @@ -35,7 +35,7 @@ void ESM4::Potion::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadalch.hpp b/components/esm4/loadalch.hpp index 73d399df05..6ba720ab32 100644 --- a/components/esm4/loadalch.hpp +++ b/components/esm4/loadalch.hpp @@ -49,9 +49,9 @@ namespace ESM4 { std::int32_t value; std::uint32_t flags; - FormId withdrawl; + FormId32 withdrawl; float chanceAddition; - FormId sound; + FormId32 sound; }; #pragma pack(pop) diff --git a/components/esm4/loadaloc.cpp b/components/esm4/loadaloc.cpp index a8c6de2432..3f1ada6e0f 100644 --- a/components/esm4/loadaloc.cpp +++ b/components/esm4/loadaloc.cpp @@ -38,7 +38,7 @@ void ESM4::MediaLocationController::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadammo.cpp b/components/esm4/loadammo.cpp index d0ad2e1709..de2a99eb80 100644 --- a/components/esm4/loadammo.cpp +++ b/components/esm4/loadammo.cpp @@ -33,7 +33,7 @@ void ESM4::Ammunition::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadanio.cpp b/components/esm4/loadanio.cpp index 2fadc6c9c2..3a540d1634 100644 --- a/components/esm4/loadanio.cpp +++ b/components/esm4/loadanio.cpp @@ -33,7 +33,7 @@ void ESM4::AnimObject::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadappa.cpp b/components/esm4/loadappa.cpp index 72369b7e0e..68991b8cc1 100644 --- a/components/esm4/loadappa.cpp +++ b/components/esm4/loadappa.cpp @@ -33,7 +33,7 @@ void ESM4::Apparatus::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadarma.cpp b/components/esm4/loadarma.cpp index aaed806ff5..f801ab2d35 100644 --- a/components/esm4/loadarma.cpp +++ b/components/esm4/loadarma.cpp @@ -34,7 +34,7 @@ void ESM4::ArmorAddon::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadarmo.cpp b/components/esm4/loadarmo.cpp index eebacb516f..dde2fe6768 100644 --- a/components/esm4/loadarmo.cpp +++ b/components/esm4/loadarmo.cpp @@ -34,7 +34,7 @@ void ESM4::Armor::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; std::uint32_t esmVer = reader.esmVersion(); diff --git a/components/esm4/loadaspc.cpp b/components/esm4/loadaspc.cpp index acfa28085b..4fef48359c 100644 --- a/components/esm4/loadaspc.cpp +++ b/components/esm4/loadaspc.cpp @@ -34,7 +34,7 @@ void ESM4::AcousticSpace::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadbook.cpp b/components/esm4/loadbook.cpp index 3419ad4c12..d8b4004aef 100644 --- a/components/esm4/loadbook.cpp +++ b/components/esm4/loadbook.cpp @@ -33,7 +33,7 @@ void ESM4::Book::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; // std::uint32_t esmVer = reader.esmVersion(); // currently unused diff --git a/components/esm4/loadbptd.cpp b/components/esm4/loadbptd.cpp index 9bc6844388..8fb17cceb8 100644 --- a/components/esm4/loadbptd.cpp +++ b/components/esm4/loadbptd.cpp @@ -46,7 +46,7 @@ void ESM4::BodyPartData::BodyPart::clear() void ESM4::BodyPartData::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadbptd.hpp b/components/esm4/loadbptd.hpp index d92727743f..6d86c36499 100644 --- a/components/esm4/loadbptd.hpp +++ b/components/esm4/loadbptd.hpp @@ -66,14 +66,14 @@ namespace ESM4 std::uint8_t explExplosionChance; // % std::uint16_t explDebrisCount; - FormId explDebris; - FormId explExplosion; + FormId32 explDebris; + FormId32 explExplosion; float trackingMaxAngle; float explDebrisScale; std::int32_t sevDebrisCount; - FormId sevDebris; - FormId sevExplosion; + FormId32 sevDebris; + FormId32 sevExplosion; float sevDebrisScale; // Struct - Gore Effects Positioning @@ -84,8 +84,8 @@ namespace ESM4 float rotY; float rotZ; - FormId sevImpactDataSet; - FormId explImpactDataSet; + FormId32 sevImpactDataSet; + FormId32 explImpactDataSet; uint8_t sevDecalCount; uint8_t explDecalCount; uint16_t Unknown; diff --git a/components/esm4/loadcell.cpp b/components/esm4/loadcell.cpp index 421c20f91c..22d9a1035d 100644 --- a/components/esm4/loadcell.cpp +++ b/components/esm4/loadcell.cpp @@ -50,7 +50,7 @@ // longer/shorter/same as loading the subrecords. void ESM4::Cell::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mId = ESM::RefId::formIdRefId(mFormId); mFlags = reader.hdr().record.flags; @@ -66,8 +66,7 @@ void ESM4::Cell::load(ESM4::Reader& reader) && reader.grp().label.grid[0] == 0) { ESM4::CellGrid currCellGrid; - currCellGrid.grid.x = 0; - currCellGrid.grid.y = 0; + currCellGrid = Grid{ 0, 0 }; reader.setCurrCellGrid(currCellGrid); // side effect: sets mCellGridValid true } @@ -123,10 +122,7 @@ void ESM4::Cell::load(ESM4::Reader& reader) // Remember cell grid for later (loading LAND, NAVM which should be CELL temporary children) // Note that grids only apply for external cells. For interior cells use the cell's formid. - ESM4::CellGrid currCell; - currCell.grid.x = (int16_t)mX; - currCell.grid.y = (int16_t)mY; - reader.setCurrCellGrid(currCell); + reader.setCurrCellGrid(Grid{ static_cast(mX), static_cast(mY) }); break; } @@ -156,7 +152,7 @@ void ESM4::Cell::load(ESM4::Reader& reader) } case ESM4::SUB_XCLR: // for exterior cells { - mRegions.resize(subHdr.dataSize / sizeof(FormId)); + mRegions.resize(subHdr.dataSize / sizeof(FormId32)); for (std::vector::iterator it = mRegions.begin(); it != mRegions.end(); ++it) { reader.getFormId(*it); diff --git a/components/esm4/loadcell.hpp b/components/esm4/loadcell.hpp index fd1a3043ec..97abb88751 100644 --- a/components/esm4/loadcell.hpp +++ b/components/esm4/loadcell.hpp @@ -44,7 +44,6 @@ namespace ESM4 class Writer; struct ReaderContext; struct CellGroup; - typedef std::uint32_t FormId; enum CellFlags // TES4 TES5 { // ----------------------- ------------------------------------ diff --git a/components/esm4/loadclas.cpp b/components/esm4/loadclas.cpp index c037260218..a5c571e9a2 100644 --- a/components/esm4/loadclas.cpp +++ b/components/esm4/loadclas.cpp @@ -39,7 +39,7 @@ void ESM4::Class::load(ESM4::Reader& reader) { // mFormId = reader.adjustFormId(reader.hdr().record.id); // FIXME: use master adjusted? - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); mFlags = reader.hdr().record.flags; while (reader.getSubRecordHeader()) diff --git a/components/esm4/loadclfm.cpp b/components/esm4/loadclfm.cpp index 259bfb6104..61223dd5d4 100644 --- a/components/esm4/loadclfm.cpp +++ b/components/esm4/loadclfm.cpp @@ -34,7 +34,7 @@ void ESM4::Colour::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadclot.cpp b/components/esm4/loadclot.cpp index e29f81c032..1d7dc72474 100644 --- a/components/esm4/loadclot.cpp +++ b/components/esm4/loadclot.cpp @@ -34,7 +34,7 @@ void ESM4::Clothing::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadcont.cpp b/components/esm4/loadcont.cpp index 34b2279446..4cb00d83a1 100644 --- a/components/esm4/loadcont.cpp +++ b/components/esm4/loadcont.cpp @@ -33,7 +33,7 @@ void ESM4::Container::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadcrea.cpp b/components/esm4/loadcrea.cpp index 803a5f3615..86bf3d2f78 100644 --- a/components/esm4/loadcrea.cpp +++ b/components/esm4/loadcrea.cpp @@ -42,7 +42,7 @@ void ESM4::Creature::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loaddial.cpp b/components/esm4/loaddial.cpp index bc9b859609..b2a1040cea 100644 --- a/components/esm4/loaddial.cpp +++ b/components/esm4/loaddial.cpp @@ -35,7 +35,7 @@ void ESM4::Dialogue::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loaddobj.cpp b/components/esm4/loaddobj.cpp index d5d8a2569a..c324df5ae0 100644 --- a/components/esm4/loaddobj.cpp +++ b/components/esm4/loaddobj.cpp @@ -39,7 +39,7 @@ void ESM4::DefaultObj::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loaddoor.cpp b/components/esm4/loaddoor.cpp index 828a04adf5..f3f261e5fc 100644 --- a/components/esm4/loaddoor.cpp +++ b/components/esm4/loaddoor.cpp @@ -33,7 +33,7 @@ void ESM4::Door::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadeyes.cpp b/components/esm4/loadeyes.cpp index 0120479dcc..253d7d3109 100644 --- a/components/esm4/loadeyes.cpp +++ b/components/esm4/loadeyes.cpp @@ -33,7 +33,7 @@ void ESM4::Eyes::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadflor.cpp b/components/esm4/loadflor.cpp index 2d250cd933..68591b4b97 100644 --- a/components/esm4/loadflor.cpp +++ b/components/esm4/loadflor.cpp @@ -33,7 +33,7 @@ void ESM4::Flora::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadflst.cpp b/components/esm4/loadflst.cpp index 90356d6afc..8bc30d7d05 100644 --- a/components/esm4/loadflst.cpp +++ b/components/esm4/loadflst.cpp @@ -34,7 +34,7 @@ void ESM4::FormIdList::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadfurn.cpp b/components/esm4/loadfurn.cpp index f32b907d45..5e0ad81c0d 100644 --- a/components/esm4/loadfurn.cpp +++ b/components/esm4/loadfurn.cpp @@ -33,7 +33,7 @@ void ESM4::Furniture::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadglob.cpp b/components/esm4/loadglob.cpp index 605a1cb683..e49446eef2 100644 --- a/components/esm4/loadglob.cpp +++ b/components/esm4/loadglob.cpp @@ -34,7 +34,7 @@ void ESM4::GlobalVariable::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadgmst.cpp b/components/esm4/loadgmst.cpp index 7fb5d7af5c..e2e4694922 100644 --- a/components/esm4/loadgmst.cpp +++ b/components/esm4/loadgmst.cpp @@ -11,8 +11,7 @@ namespace ESM4 GameSetting::Data readData(FormId formId, std::string_view editorId, Reader& reader) { if (editorId.empty()) - throw std::runtime_error( - "Unknown ESM4 GMST (" + std::to_string(formId) + ") data type: editor id is empty"); + throw std::runtime_error("Unknown ESM4 GMST (" + formId.toString() + ") data type: editor id is empty"); const char type = editorId[0]; switch (type) { @@ -36,14 +35,14 @@ namespace ESM4 } default: throw std::runtime_error( - "Unsupported ESM4 GMST (" + std::to_string(formId) + ") data type: " + std::string(editorId)); + "Unsupported ESM4 GMST (" + formId.toString() + ") data type: " + std::string(editorId)); } } } void GameSetting::load(Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; @@ -59,8 +58,8 @@ namespace ESM4 mData = readData(mFormId, mEditorId, reader); break; default: - throw std::runtime_error("Unknown ESM4 GMST (" + std::to_string(mFormId) + ") subrecord " - + ESM::printName(subHdr.typeId)); + throw std::runtime_error( + "Unknown ESM4 GMST (" + mFormId.toString() + ") subrecord " + ESM::printName(subHdr.typeId)); } } } diff --git a/components/esm4/loadgras.cpp b/components/esm4/loadgras.cpp index 547589236f..7a6bf629e2 100644 --- a/components/esm4/loadgras.cpp +++ b/components/esm4/loadgras.cpp @@ -33,7 +33,7 @@ void ESM4::Grass::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadhair.cpp b/components/esm4/loadhair.cpp index 4da4203387..6fee6a4c1c 100644 --- a/components/esm4/loadhair.cpp +++ b/components/esm4/loadhair.cpp @@ -34,7 +34,7 @@ void ESM4::Hair::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadhdpt.cpp b/components/esm4/loadhdpt.cpp index 69cb3bb674..f308a6a3a2 100644 --- a/components/esm4/loadhdpt.cpp +++ b/components/esm4/loadhdpt.cpp @@ -35,7 +35,7 @@ void ESM4::HeadPart::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadidle.cpp b/components/esm4/loadidle.cpp index cf0e993207..1b12b220d0 100644 --- a/components/esm4/loadidle.cpp +++ b/components/esm4/loadidle.cpp @@ -33,7 +33,7 @@ void ESM4::IdleAnimation::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadidlm.cpp b/components/esm4/loadidlm.cpp index 801cd9465b..571c9c8a85 100644 --- a/components/esm4/loadidlm.cpp +++ b/components/esm4/loadidlm.cpp @@ -34,7 +34,7 @@ void ESM4::IdleMarker::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadimod.cpp b/components/esm4/loadimod.cpp index ad043978bd..939c377b82 100644 --- a/components/esm4/loadimod.cpp +++ b/components/esm4/loadimod.cpp @@ -36,7 +36,7 @@ void ESM4::ItemMod::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadinfo.cpp b/components/esm4/loadinfo.cpp index b37411accc..c232d80e52 100644 --- a/components/esm4/loadinfo.cpp +++ b/components/esm4/loadinfo.cpp @@ -35,7 +35,7 @@ void ESM4::DialogInfo::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadingr.cpp b/components/esm4/loadingr.cpp index 4756be8e63..33ced513bc 100644 --- a/components/esm4/loadingr.cpp +++ b/components/esm4/loadingr.cpp @@ -34,7 +34,7 @@ void ESM4::Ingredient::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadkeym.cpp b/components/esm4/loadkeym.cpp index 0ac8ae22e8..d179f15dcc 100644 --- a/components/esm4/loadkeym.cpp +++ b/components/esm4/loadkeym.cpp @@ -33,7 +33,7 @@ void ESM4::Key::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadland.cpp b/components/esm4/loadland.cpp index 0d09fe8332..201fd7a96f 100644 --- a/components/esm4/loadland.cpp +++ b/components/esm4/loadland.cpp @@ -55,7 +55,7 @@ // void ESM4::Land::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; mDataTypes = 0; @@ -181,8 +181,9 @@ void ESM4::Land::load(ESM4::Reader& reader) } case ESM4::SUB_VTEX: // only in Oblivion? { - int count = (int)reader.subRecordHeader().dataSize / sizeof(FormId); - assert((reader.subRecordHeader().dataSize % sizeof(FormId)) == 0 && "ESM4::LAND VTEX data size error"); + int count = (int)reader.subRecordHeader().dataSize / sizeof(FormId32); + assert( + (reader.subRecordHeader().dataSize % sizeof(FormId32)) == 0 && "ESM4::LAND VTEX data size error"); if (count) { @@ -212,7 +213,7 @@ void ESM4::Land::load(ESM4::Reader& reader) bool missing = false; for (int i = 0; i < 4; ++i) { - if (mTextures[i].base.formId == 0) + if (mTextures[i].base.formId.isZero()) { // std::cout << "ESM4::LAND " << ESM4::formIdToString(mFormId) << " missing base, quad " << i << std::endl; // std::cout << "layers " << mTextures[i].layers.size() << std::endl; diff --git a/components/esm4/loadlgtm.cpp b/components/esm4/loadlgtm.cpp index 1382a7237b..7706277109 100644 --- a/components/esm4/loadlgtm.cpp +++ b/components/esm4/loadlgtm.cpp @@ -37,7 +37,7 @@ void ESM4::LightingTemplate::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadlgtm.hpp b/components/esm4/loadlgtm.hpp index d835ef7a67..ef32b24242 100644 --- a/components/esm4/loadlgtm.hpp +++ b/components/esm4/loadlgtm.hpp @@ -39,7 +39,6 @@ namespace ESM4 { class Reader; class Writer; - typedef std::uint32_t FormId; struct LightingTemplate { diff --git a/components/esm4/loadligh.cpp b/components/esm4/loadligh.cpp index 6c222a6f60..f0b15e5a2a 100644 --- a/components/esm4/loadligh.cpp +++ b/components/esm4/loadligh.cpp @@ -33,7 +33,7 @@ void ESM4::Light::load(ESM4::Reader& reader) { - FormId formId = reader.hdr().record.id; + FormId formId = reader.hdr().record.getFormId(); reader.adjustFormId(formId); mId = ESM::RefId::formIdRefId(formId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadltex.cpp b/components/esm4/loadltex.cpp index d36f492cce..866ae49d28 100644 --- a/components/esm4/loadltex.cpp +++ b/components/esm4/loadltex.cpp @@ -39,7 +39,7 @@ void ESM4::LandTexture::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; std::uint32_t esmVer = reader.esmVersion(); diff --git a/components/esm4/loadlvlc.cpp b/components/esm4/loadlvlc.cpp index 3a3a2cc42a..af3b36232b 100644 --- a/components/esm4/loadlvlc.cpp +++ b/components/esm4/loadlvlc.cpp @@ -34,7 +34,7 @@ void ESM4::LevelledCreature::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadlvli.cpp b/components/esm4/loadlvli.cpp index 637814641c..a199bc1b38 100644 --- a/components/esm4/loadlvli.cpp +++ b/components/esm4/loadlvli.cpp @@ -34,7 +34,7 @@ void ESM4::LevelledItem::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadlvln.cpp b/components/esm4/loadlvln.cpp index cf5f70c27c..6705e18921 100644 --- a/components/esm4/loadlvln.cpp +++ b/components/esm4/loadlvln.cpp @@ -34,7 +34,7 @@ void ESM4::LevelledNpc::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; // std::uint32_t esmVer = reader.esmVersion(); // currently unused diff --git a/components/esm4/loadmato.cpp b/components/esm4/loadmato.cpp index 41b78d4e23..921db78214 100644 --- a/components/esm4/loadmato.cpp +++ b/components/esm4/loadmato.cpp @@ -34,7 +34,7 @@ void ESM4::Material::load(ESM4::Reader& reader) { // mFormId = reader.adjustFormId(reader.hdr().record.id); // FIXME: use master adjusted? - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); mFlags = reader.hdr().record.flags; while (reader.getSubRecordHeader()) diff --git a/components/esm4/loadmisc.cpp b/components/esm4/loadmisc.cpp index 62ad5c5396..dbb136298c 100644 --- a/components/esm4/loadmisc.cpp +++ b/components/esm4/loadmisc.cpp @@ -33,7 +33,7 @@ void ESM4::MiscItem::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadmset.cpp b/components/esm4/loadmset.cpp index 02b5a8dc0a..d76791a0d5 100644 --- a/components/esm4/loadmset.cpp +++ b/components/esm4/loadmset.cpp @@ -34,7 +34,7 @@ void ESM4::MediaSet::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadmstt.cpp b/components/esm4/loadmstt.cpp index 0f6a3d6cdb..73782f70d8 100644 --- a/components/esm4/loadmstt.cpp +++ b/components/esm4/loadmstt.cpp @@ -34,7 +34,7 @@ void ESM4::MovableStatic::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadmusc.cpp b/components/esm4/loadmusc.cpp index 4b554807a6..77201959f5 100644 --- a/components/esm4/loadmusc.cpp +++ b/components/esm4/loadmusc.cpp @@ -38,7 +38,7 @@ void ESM4::Music::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadnavi.cpp b/components/esm4/loadnavi.cpp index 7b8f669f17..3a0d630abe 100644 --- a/components/esm4/loadnavi.cpp +++ b/components/esm4/loadnavi.cpp @@ -151,10 +151,12 @@ void ESM4::Navigation::NavMeshInfo::load(ESM4::Reader& reader) reader.get(worldSpaceId); // FLG_Tamriel = 0x0000003c, // grid info follows, possibly Tamriel? // FLG_Morrowind = 0x01380000, // grid info follows, probably Skywind - if (worldSpaceId == 0x0000003c || worldSpaceId == 0x01380000) + if (worldSpaceId == FormId{ 0x3c, 0 } || worldSpaceId == FormId{ 0x380000, 1 }) { - reader.get(cellGrid.grid.y); // NOTE: reverse order - reader.get(cellGrid.grid.x); + Grid grid; + reader.get(grid.y); // NOTE: reverse order + reader.get(grid.x); + cellGrid = grid; // FIXME: debugging only #if 0 std::string padding; @@ -167,7 +169,9 @@ void ESM4::Navigation::NavMeshInfo::load(ESM4::Reader& reader) } else { - reader.get(cellGrid.cellId); + FormId cellId; + reader.get(cellId); + cellGrid = cellId; #if 0 if (worldSpaceId == 0) // interior @@ -237,7 +241,7 @@ void ESM4::Navigation::NavMeshInfo::load(ESM4::Reader& reader) // void ESM4::Navigation::load(ESM4::Reader& reader) { - // mFormId = reader.hdr().record.id; + // mFormId = reader.hdr().record.getFormId(); // mFlags = reader.hdr().record.flags; std::uint32_t esmVer = reader.esmVersion(); bool isFONV = esmVer == ESM::VER_132 || esmVer == ESM::VER_133 || esmVer == ESM::VER_134; @@ -312,8 +316,9 @@ void ESM4::Navigation::load(ESM4::Reader& reader) std::cout << "node " << std::hex << node // FIXME: debugging only << ", index " << index << ", i " << std::dec << total+i << std::endl; #endif + FormId nodeFormId = FormId::fromUint32(node); // should we apply reader.adjustFormId? // std::pair::iterator, bool> res = - mPathIndexMap.insert(std::make_pair(node, index)); + mPathIndexMap.emplace(nodeFormId, index); // FIXME: this throws if more than one file is being loaded // if (!res.second) // throw std::runtime_error ("node already exists in the preferred path index map"); diff --git a/components/esm4/loadnavi.hpp b/components/esm4/loadnavi.hpp index 9a804efe0a..12022dd9ec 100644 --- a/components/esm4/loadnavi.hpp +++ b/components/esm4/loadnavi.hpp @@ -45,7 +45,7 @@ namespace ESM4 struct DoorRef { std::uint32_t unknown; - FormId formId; + FormId32 formId; }; struct Triangle diff --git a/components/esm4/loadnavm.cpp b/components/esm4/loadnavm.cpp index 0def0dbdb7..0c9b0f5dc6 100644 --- a/components/esm4/loadnavm.cpp +++ b/components/esm4/loadnavm.cpp @@ -47,7 +47,7 @@ void ESM4::NavMesh::NVNMstruct::load(ESM4::Reader& reader) reader.get(worldSpaceId); // FLG_Tamriel = 0x0000003c, // grid info follows, possibly Tamriel? // FLG_Morrowind = 0x01380000, // grid info follows, probably Skywind - if (worldSpaceId == 0x0000003c || worldSpaceId == 0x01380000) + if (worldSpaceId == FormId{ 0x3c, 0 } || worldSpaceId == FormId{ 380000, 1 }) { // ^ // Y | X Y Index @@ -65,8 +65,10 @@ void ESM4::NavMesh::NVNMstruct::load(ESM4::Reader& reader) // // Formula seems to be floor(Skywind coord / 2) // - reader.get(cellGrid.grid.y); // NOTE: reverse order - reader.get(cellGrid.grid.x); + Grid grid; + reader.get(grid.y); // NOTE: reverse order + reader.get(grid.x); + cellGrid = grid; // FIXME: debugging only #if 0 std::string padding; @@ -79,7 +81,9 @@ void ESM4::NavMesh::NVNMstruct::load(ESM4::Reader& reader) } else { - reader.get(cellGrid.cellId); + FormId cellId; + reader.get(cellId); + cellGrid = cellId; #if 0 std::string padding; // FIXME @@ -186,7 +190,7 @@ void ESM4::NavMesh::NVNMstruct::load(ESM4::Reader& reader) void ESM4::NavMesh::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); mFlags = reader.hdr().record.flags; // std::cout << "NavMesh 0x" << std::hex << this << std::endl; // FIXME diff --git a/components/esm4/loadnavm.hpp b/components/esm4/loadnavm.hpp index a62ed47854..d134db006d 100644 --- a/components/esm4/loadnavm.hpp +++ b/components/esm4/loadnavm.hpp @@ -56,7 +56,7 @@ namespace ESM4 struct ExtConnection { std::uint32_t unknown; - FormId navMesh; + FormId32 navMesh; std::uint16_t triangleIndex; }; @@ -64,7 +64,7 @@ namespace ESM4 { std::uint16_t triangleIndex; std::uint32_t unknown; - FormId doorRef; + FormId32 doorRef; }; #pragma pack(pop) diff --git a/components/esm4/loadnote.cpp b/components/esm4/loadnote.cpp index f0611758c7..8403931db7 100644 --- a/components/esm4/loadnote.cpp +++ b/components/esm4/loadnote.cpp @@ -34,7 +34,7 @@ void ESM4::Note::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadnpc.cpp b/components/esm4/loadnpc.cpp index 2b8f953127..c6428177c9 100644 --- a/components/esm4/loadnpc.cpp +++ b/components/esm4/loadnpc.cpp @@ -42,7 +42,7 @@ void ESM4::Npc::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadotft.cpp b/components/esm4/loadotft.cpp index f8035d5082..f7e8390bae 100644 --- a/components/esm4/loadotft.cpp +++ b/components/esm4/loadotft.cpp @@ -34,7 +34,7 @@ void ESM4::Outfit::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; @@ -48,7 +48,7 @@ void ESM4::Outfit::load(ESM4::Reader& reader) break; case ESM4::SUB_INAM: { - std::size_t numObj = subHdr.dataSize / sizeof(FormId); + std::size_t numObj = subHdr.dataSize / sizeof(FormId32); for (std::size_t i = 0; i < numObj; ++i) { FormId formId; diff --git a/components/esm4/loadpack.cpp b/components/esm4/loadpack.cpp index 90515c5b05..885e4a8c5f 100644 --- a/components/esm4/loadpack.cpp +++ b/components/esm4/loadpack.cpp @@ -35,7 +35,7 @@ void ESM4::AIPackage::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadpack.hpp b/components/esm4/loadpack.hpp index 002782dd08..c0968aa207 100644 --- a/components/esm4/loadpack.hpp +++ b/components/esm4/loadpack.hpp @@ -60,14 +60,14 @@ namespace ESM4 { std::int32_t type = 0xff; // 0 = near ref, 1 = in cell, 2 = current loc, 3 = editor loc, 4 = obj id, 5 = obj // type, 0xff = no location data - FormId location; // uint32_t if type = 5 + FormId32 location; // uint32_t if type = 5 std::int32_t radius; }; struct PTDT // target { std::int32_t type = 0xff; // 0 = specific ref, 1 = obj id, 2 = obj type, 0xff = no target data - FormId target; // uint32_t if type = 2 + FormId32 target; // uint32_t if type = 2 std::int32_t distance; }; @@ -81,8 +81,8 @@ namespace ESM4 std::uint8_t unknown3; // probably padding float compValue; std::int32_t fnIndex; - FormId param1; - FormId param2; + FormId32 param1; + FormId32 param2; std::uint32_t unknown4; // probably padding }; #pragma pack(pop) diff --git a/components/esm4/loadpgrd.cpp b/components/esm4/loadpgrd.cpp index 5f0ee69df3..19b6df822a 100644 --- a/components/esm4/loadpgrd.cpp +++ b/components/esm4/loadpgrd.cpp @@ -36,7 +36,7 @@ void ESM4::Pathgrid::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadpgre.cpp b/components/esm4/loadpgre.cpp index faf701300b..1cbea4c572 100644 --- a/components/esm4/loadpgre.cpp +++ b/components/esm4/loadpgre.cpp @@ -36,7 +36,7 @@ void ESM4::PlacedGrenade::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadpwat.cpp b/components/esm4/loadpwat.cpp index 8c10ab0146..5056c86280 100644 --- a/components/esm4/loadpwat.cpp +++ b/components/esm4/loadpwat.cpp @@ -36,7 +36,7 @@ void ESM4::PlaceableWater::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadqust.cpp b/components/esm4/loadqust.cpp index 992f3b5993..fe0e63e979 100644 --- a/components/esm4/loadqust.cpp +++ b/components/esm4/loadqust.cpp @@ -35,7 +35,7 @@ void ESM4::Quest::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadrace.cpp b/components/esm4/loadrace.cpp index f81130a4ce..ae0af2cd4f 100644 --- a/components/esm4/loadrace.cpp +++ b/components/esm4/loadrace.cpp @@ -37,7 +37,7 @@ void ESM4::Race::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; @@ -418,7 +418,7 @@ void ESM4::Race::load(ESM4::Reader& reader) // case ESM4::SUB_HNAM: { - std::size_t numHairChoices = subHdr.dataSize / sizeof(FormId); + std::size_t numHairChoices = subHdr.dataSize / sizeof(FormId32); mHairChoices.resize(numHairChoices); for (unsigned int i = 0; i < numHairChoices; ++i) reader.get(mHairChoices.at(i)); @@ -427,7 +427,7 @@ void ESM4::Race::load(ESM4::Reader& reader) } case ESM4::SUB_ENAM: { - std::size_t numEyeChoices = subHdr.dataSize / sizeof(FormId); + std::size_t numEyeChoices = subHdr.dataSize / sizeof(FormId32); mEyeChoices.resize(numEyeChoices); for (unsigned int i = 0; i < numEyeChoices; ++i) reader.get(mEyeChoices.at(i)); @@ -538,7 +538,7 @@ void ESM4::Race::load(ESM4::Reader& reader) break; case ESM4::SUB_KWDA: { - std::uint32_t formid; + FormId formid; for (unsigned int i = 0; i < mNumKeywords; ++i) reader.getFormId(formid); break; diff --git a/components/esm4/loadrace.hpp b/components/esm4/loadrace.hpp index d5ce25ab40..ad2c92e43c 100644 --- a/components/esm4/loadrace.hpp +++ b/components/esm4/loadrace.hpp @@ -39,7 +39,6 @@ namespace ESM4 { class Reader; class Writer; - typedef std::uint32_t FormId; struct Race { diff --git a/components/esm4/loadrefr.cpp b/components/esm4/loadrefr.cpp index 0d61dac9a6..23b4f68c54 100644 --- a/components/esm4/loadrefr.cpp +++ b/components/esm4/loadrefr.cpp @@ -34,7 +34,7 @@ void ESM4::Reference::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mId = ESM::RefId::formIdRefId(mFormId); mFlags = reader.hdr().record.flags; @@ -93,8 +93,8 @@ void ESM4::Reference::load(ESM4::Reader& reader) break; case ESM4::SUB_XESP: { - reader.get(mEsp); - reader.adjustFormId(mEsp.parent); + reader.getFormId(mEsp.parent); + reader.get(mEsp.flags); // std::cout << "REFR parent: " << formIdToString(mEsp.parent) << " ref " << formIdToString(mFormId) //<< ", 0x" << std::hex << (mEsp.flags & 0xff) << std::endl;// FIXME break; diff --git a/components/esm4/loadregn.cpp b/components/esm4/loadregn.cpp index da1a9f08fc..a2eeebce68 100644 --- a/components/esm4/loadregn.cpp +++ b/components/esm4/loadregn.cpp @@ -41,7 +41,7 @@ void ESM4::Region::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadregn.hpp b/components/esm4/loadregn.hpp index 30576dbf8e..521e1c8dba 100644 --- a/components/esm4/loadregn.hpp +++ b/components/esm4/loadregn.hpp @@ -63,7 +63,7 @@ namespace ESM4 struct RegionSound { - FormId sound; + FormId32 sound; std::uint32_t flags; // 0 pleasant, 1 cloudy, 2 rainy, 3 snowy std::uint32_t chance; }; diff --git a/components/esm4/loadroad.cpp b/components/esm4/loadroad.cpp index e4707d3877..24d39c94cc 100644 --- a/components/esm4/loadroad.cpp +++ b/components/esm4/loadroad.cpp @@ -35,7 +35,7 @@ void ESM4::Road::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; mParent = reader.currWorld(); diff --git a/components/esm4/loadsbsp.cpp b/components/esm4/loadsbsp.cpp index 0182500924..89c4f58754 100644 --- a/components/esm4/loadsbsp.cpp +++ b/components/esm4/loadsbsp.cpp @@ -33,7 +33,7 @@ void ESM4::SubSpace::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadscol.cpp b/components/esm4/loadscol.cpp index 14eaab5f5c..e33ba71ab2 100644 --- a/components/esm4/loadscol.cpp +++ b/components/esm4/loadscol.cpp @@ -36,7 +36,7 @@ void ESM4::StaticCollection::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadscpt.cpp b/components/esm4/loadscpt.cpp index 6a06bcdec2..6d74e2f7ee 100644 --- a/components/esm4/loadscpt.cpp +++ b/components/esm4/loadscpt.cpp @@ -35,7 +35,7 @@ void ESM4::Script::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadscrl.cpp b/components/esm4/loadscrl.cpp index ed0a1e9205..30cc8818fd 100644 --- a/components/esm4/loadscrl.cpp +++ b/components/esm4/loadscrl.cpp @@ -34,7 +34,7 @@ void ESM4::Scroll::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadsgst.cpp b/components/esm4/loadsgst.cpp index 27402f520e..580e5ba59c 100644 --- a/components/esm4/loadsgst.cpp +++ b/components/esm4/loadsgst.cpp @@ -34,7 +34,7 @@ void ESM4::SigilStone::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadslgm.cpp b/components/esm4/loadslgm.cpp index 8d42c06169..a1d6fdf235 100644 --- a/components/esm4/loadslgm.cpp +++ b/components/esm4/loadslgm.cpp @@ -33,7 +33,7 @@ void ESM4::SoulGem::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadsndr.cpp b/components/esm4/loadsndr.cpp index f5a74fd091..d0f9fac3b4 100644 --- a/components/esm4/loadsndr.cpp +++ b/components/esm4/loadsndr.cpp @@ -34,7 +34,7 @@ void ESM4::SoundReference::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadsoun.cpp b/components/esm4/loadsoun.cpp index 7e69cc952c..44cfc24776 100644 --- a/components/esm4/loadsoun.cpp +++ b/components/esm4/loadsoun.cpp @@ -34,7 +34,7 @@ void ESM4::Sound::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadstat.cpp b/components/esm4/loadstat.cpp index c0ab630a13..5dcff407ec 100644 --- a/components/esm4/loadstat.cpp +++ b/components/esm4/loadstat.cpp @@ -34,7 +34,7 @@ void ESM4::Static::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mId = ESM::RefId::formIdRefId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadtact.cpp b/components/esm4/loadtact.cpp index 362ea65a3c..29bbdc6bca 100644 --- a/components/esm4/loadtact.cpp +++ b/components/esm4/loadtact.cpp @@ -34,7 +34,7 @@ void ESM4::TalkingActivator::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadterm.cpp b/components/esm4/loadterm.cpp index 91b056bc92..db4107b2e9 100644 --- a/components/esm4/loadterm.cpp +++ b/components/esm4/loadterm.cpp @@ -34,7 +34,7 @@ void ESM4::Terminal::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadtes4.cpp b/components/esm4/loadtes4.cpp index 8549a1bf02..86334910ae 100644 --- a/components/esm4/loadtes4.cpp +++ b/components/esm4/loadtes4.cpp @@ -85,11 +85,13 @@ void ESM4::Header::load(ESM4::Reader& reader) } case ESM4::SUB_ONAM: { - mOverrides.resize(subHdr.dataSize / sizeof(FormId)); - for (unsigned int& mOverride : mOverrides) + mOverrides.resize(subHdr.dataSize / sizeof(FormId32)); + for (FormId& mOverride : mOverrides) { - if (!reader.getExact(mOverride)) + uint32_t v; + if (!reader.getExact(v)) throw std::runtime_error("TES4 ONAM data read error"); + mOverride = FormId::fromUint32(v); #if 0 std::string padding; padding.insert(0, reader.stackSize()*2, ' '); diff --git a/components/esm4/loadtree.cpp b/components/esm4/loadtree.cpp index b0c2656595..fa8dfbca49 100644 --- a/components/esm4/loadtree.cpp +++ b/components/esm4/loadtree.cpp @@ -33,7 +33,7 @@ void ESM4::Tree::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadtxst.cpp b/components/esm4/loadtxst.cpp index 20e058ebbc..73d5611653 100644 --- a/components/esm4/loadtxst.cpp +++ b/components/esm4/loadtxst.cpp @@ -34,7 +34,7 @@ void ESM4::TextureSet::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/loadweap.cpp b/components/esm4/loadweap.cpp index d8fdfe26f7..5feec1c8ba 100644 --- a/components/esm4/loadweap.cpp +++ b/components/esm4/loadweap.cpp @@ -33,7 +33,7 @@ void ESM4::Weapon::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; std::uint32_t esmVer = reader.esmVersion(); diff --git a/components/esm4/loadwrld.cpp b/components/esm4/loadwrld.cpp index 9cc56cd9fd..dd80b6aaf7 100644 --- a/components/esm4/loadwrld.cpp +++ b/components/esm4/loadwrld.cpp @@ -34,7 +34,7 @@ void ESM4::World::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; + mFormId = reader.hdr().record.getFormId(); reader.adjustFormId(mFormId); mFlags = reader.hdr().record.flags; diff --git a/components/esm4/reader.cpp b/components/esm4/reader.cpp index f62cd36262..220cf6914e 100644 --- a/components/esm4/reader.cpp +++ b/components/esm4/reader.cpp @@ -64,13 +64,11 @@ namespace ESM4 , filePos(0) , fileRead(0) , recordRead(0) - , currWorld(0) - , currCell(0) + , currWorld({ 0, 0 }) + , currCell({ 0, 0 }) + , currCellGrid(FormId{ 0, 0 }) , cellGridValid(false) { - currCellGrid.cellId = 0; - currCellGrid.grid.x = 0; - currCellGrid.grid.y = 0; subRecordHeader.typeId = 0; subRecordHeader.dataSize = 0; } @@ -260,7 +258,7 @@ namespace ESM4 stream->read((char*)&stringId, sizeof(stringId)); stream->read((char*)&sp.offset, sizeof(sp.offset)); sp.offset += (std::uint32_t)dataStart; - mLStringIndex[stringId] = sp; + mLStringIndex[FormId::fromUint32(stringId)] = sp; } // assert (dataStart - stream->tell() == 0 && "String file start of data section mismatch"); } @@ -273,7 +271,7 @@ namespace ESM4 std::uint32_t stringId; // FormId get(stringId); if (stringId) // TES5 FoxRace, BOOK - getLocalizedStringImpl(stringId, str); + getLocalizedStringImpl(FormId::fromUint32(stringId), str); } // FIXME: very messy and probably slow/inefficient @@ -577,31 +575,15 @@ namespace ESM4 return mCtx.currCellGrid; } - // NOTE: the parameter 'files' must have the file names in the loaded order - void Reader::updateModIndices(const std::vector& files) + void Reader::updateModIndices(const std::map& fileToModIndex) { - if (files.size() >= 0xff) - throw std::runtime_error("ESM4::Reader::updateModIndices too many files"); // 0xff is reserved - - // NOTE: this map is rebuilt each time this method is called (i.e. each time a file is loaded) - // Perhaps there is an opportunity to optimize this by saving the result somewhere. - // But then, the number of files is at most around 250 so perhaps keeping it simple might be better. - - // build a lookup map - std::unordered_map fileIndex; - - for (size_t i = 0; i < files.size(); ++i) // ATTENTION: assumes current file is not included - fileIndex[Misc::StringUtils::lowerCase(files[i])] = i; - mCtx.parentFileIndices.resize(mHeader.mMaster.size()); for (unsigned int i = 0; i < mHeader.mMaster.size(); ++i) { // locate the position of the dependency in already loaded files - std::unordered_map::const_iterator it - = fileIndex.find(Misc::StringUtils::lowerCase(mHeader.mMaster[i].name)); - - if (it != fileIndex.end()) - mCtx.parentFileIndices[i] = (std::uint32_t)((it->second << 24) & 0xff000000); + auto it = fileToModIndex.find(Misc::StringUtils::lowerCase(mHeader.mMaster[i].name)); + if (it != fileToModIndex.end()) + mCtx.parentFileIndices[i] = it->second; else throw std::runtime_error("ESM4::Reader::updateModIndices required dependency file not loaded"); #if 0 @@ -609,9 +591,6 @@ namespace ESM4 << formIdToString(mCtx.parentFileIndices[i]) << std::endl; #endif } - - if (!mCtx.parentFileIndices.empty() && mCtx.parentFileIndices[0] != 0) - throw std::runtime_error("ESM4::Reader::updateModIndices base modIndex is not zero"); } // ModIndex adjusted formId according to master file dependencies @@ -626,21 +605,25 @@ namespace ESM4 // (see https://www.uesp.net/wiki/Tes4Mod:Formid#ModIndex_Zero) void Reader::adjustFormId(FormId& id) { - if (mCtx.parentFileIndices.empty()) - return; - - std::size_t index = (id >> 24) & 0xff; - - if (index < mCtx.parentFileIndices.size()) - id = mCtx.parentFileIndices[index] | (id & 0x00ffffff); + if (id.hasContentFile() && id.mContentFile < static_cast(mCtx.parentFileIndices.size())) + id.mContentFile = mCtx.parentFileIndices[id.mContentFile]; else - id = mCtx.modIndex | (id & 0x00ffffff); + id.mContentFile = mCtx.modIndex; + } + + void Reader::adjustFormId(FormId32& id) + { + FormId formId = FormId::fromUint32(id); + adjustFormId(formId); + id = formId.toUint32(); } bool Reader::getFormId(FormId& id) { - if (!getExact(id)) + FormId32 v; + if (!getExact(v)) return false; + id = FormId::fromUint32(v); adjustFormId(id); return true; @@ -796,7 +779,7 @@ namespace ESM4 case ESM4::Grp_CellTemporaryChild: case ESM4::Grp_CellVisibleDistChild: { - ss << ": FormId 0x" << formIdToString(label.value); + ss << ": FormId 0x" << formIdToString(FormId::fromUint32(label.value)); break; } default: diff --git a/components/esm4/reader.hpp b/components/esm4/reader.hpp index 3caaf66f6d..b6b4b6017e 100644 --- a/components/esm4/reader.hpp +++ b/components/esm4/reader.hpp @@ -69,10 +69,12 @@ namespace ESM4 std::uint32_t typeId; std::uint32_t dataSize; // does *not* include 24 bytes (20 for TES4) of header std::uint32_t flags; - FormId id; + FormId32 id; std::uint32_t revision; std::uint16_t version; // not in TES4 std::uint16_t unknown; // not in TES4 + + FormId getFormId() const { return FormId::fromUint32(id); } }; union RecordHeader @@ -255,8 +257,8 @@ namespace ESM4 // The object setting up this reader needs to supply the file's load order index // so that the formId's in this file can be adjusted with the file (i.e. mod) index. - void setModIndex(std::uint32_t index) { mCtx.modIndex = (index << 24) & 0xff000000; } - void updateModIndices(const std::vector& files); + void setModIndex(std::uint32_t index) { mCtx.modIndex = index; } + void updateModIndices(const std::map& fileToModIndex); // Maybe should throw an exception if called when not valid? const CellGrid& currCellGrid() const; @@ -333,6 +335,9 @@ namespace ESM4 // ModIndex adjusted formId according to master file dependencies void adjustFormId(FormId& id); + // Temporary. Doesn't support mod index > 255 + void adjustFormId(FormId32& id); + bool getFormId(FormId& id); void adjustGRUPFormId(); diff --git a/components/esm4/reference.hpp b/components/esm4/reference.hpp index 0a0c96e712..6987e811f9 100644 --- a/components/esm4/reference.hpp +++ b/components/esm4/reference.hpp @@ -48,6 +48,7 @@ namespace ESM4 Vector3 pos; Vector3 rot; // angles are in radian, rz applied first and rx applied last }; +#pragma pack(pop) // REFR, ACHR, ACRE struct EnableParent @@ -55,7 +56,6 @@ namespace ESM4 FormId parent; std::uint32_t flags; // 0x0001 = Set Enable State Opposite Parent, 0x0002 = Pop In }; -#pragma pack(pop) struct LODReference { diff --git a/components/esm4/script.hpp b/components/esm4/script.hpp index d1cd18018d..cc9bf993b6 100644 --- a/components/esm4/script.hpp +++ b/components/esm4/script.hpp @@ -33,6 +33,8 @@ #include #include +#include "formid.hpp" + namespace ESM4 { enum EmotionType @@ -324,7 +326,7 @@ namespace ESM4 std::uint32_t unknown1; std::uint32_t responseNo; // 1 byte + padding // below FO3/FONV - FormId sound; // when 20 bytes usually 0 but there are exceptions (FO3 INFO FormId = 0x0002241f) + FormId32 sound; // when 20 bytes usually 0 but there are exceptions (FO3 INFO FormId = 0x0002241f) std::uint32_t flags; // 1 byte + padding (0x01 = use emotion anim) }; @@ -337,7 +339,7 @@ namespace ESM4 std::uint32_t param2; std::uint32_t runOn; // 0 subject, 1 target, 2 reference, 3 combat target, 4 linked reference // below FO3/FONV/TES5 - FormId reference; + FormId32 reference; }; struct ScriptHeader