From a9e6e63c4ee2a2fda7f92558990d8fb09237e0a3 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sun, 17 Dec 2023 13:00:14 +0100 Subject: [PATCH 1/7] Remove fixed size reads --- apps/esmtool/record.cpp | 24 ++++--- apps/opencs/model/tools/racecheck.cpp | 8 +-- apps/opencs/model/world/columnimp.hpp | 31 ++++++--- .../model/world/nestedcoladapterimp.cpp | 16 ++--- apps/openmw/mwclass/npc.cpp | 24 +++---- apps/openmw/mwmechanics/character.cpp | 2 +- .../mwmechanics/mechanicsmanagerimp.cpp | 8 +-- apps/openmw/mwworld/projectilemanager.cpp | 2 +- components/esm/defs.hpp | 6 +- components/esm3/cellref.cpp | 4 +- components/esm3/esmreader.cpp | 5 +- components/esm3/esmreader.hpp | 2 +- components/esm3/loadfact.cpp | 47 ++++++++++++-- components/esm3/loadfact.hpp | 6 ++ components/esm3/loadrace.cpp | 64 ++++++++++++++++--- components/esm3/loadrace.hpp | 24 +++---- components/esm3/loadtes3.cpp | 3 +- components/esm3/loadtes3.hpp | 5 -- components/esm3/player.cpp | 4 +- components/esm3/projectilestate.cpp | 6 +- components/esm3/savedgame.cpp | 2 +- 21 files changed, 189 insertions(+), 104 deletions(-) diff --git a/apps/esmtool/record.cpp b/apps/esmtool/record.cpp index 96c418c0c4..71158299aa 100644 --- a/apps/esmtool/record.cpp +++ b/apps/esmtool/record.cpp @@ -1169,19 +1169,23 @@ namespace EsmTool std::cout << " Description: " << mData.mDescription << std::endl; std::cout << " Flags: " << raceFlags(mData.mData.mFlags) << std::endl; - for (int i = 0; i < 2; ++i) + std::cout << " Male:" << std::endl; + for (int j = 0; j < ESM::Attribute::Length; ++j) { - bool male = i == 0; - - std::cout << (male ? " Male:" : " Female:") << std::endl; - - for (int j = 0; j < ESM::Attribute::Length; ++j) - std::cout << " " << ESM::Attribute::indexToRefId(j) << ": " - << mData.mData.mAttributeValues[j].getValue(male) << std::endl; + ESM::RefId id = ESM::Attribute::indexToRefId(j); + std::cout << " " << id << ": " << mData.mData.getAttribute(id, true) << std::endl; + } + std::cout << " Height: " << mData.mData.mMaleHeight << std::endl; + std::cout << " Weight: " << mData.mData.mMaleWeight << std::endl; - std::cout << " Height: " << mData.mData.mHeight.getValue(male) << std::endl; - std::cout << " Weight: " << mData.mData.mWeight.getValue(male) << std::endl; + std::cout << " Female:" << std::endl; + for (int j = 0; j < ESM::Attribute::Length; ++j) + { + ESM::RefId id = ESM::Attribute::indexToRefId(j); + std::cout << " " << id << ": " << mData.mData.getAttribute(id, false) << std::endl; } + std::cout << " Height: " << mData.mData.mFemaleHeight << std::endl; + std::cout << " Weight: " << mData.mData.mFemaleWeight << std::endl; for (const auto& bonus : mData.mData.mBonus) // Not all races have 7 skills. diff --git a/apps/opencs/model/tools/racecheck.cpp b/apps/opencs/model/tools/racecheck.cpp index 78f72f44c5..8f0df823c3 100644 --- a/apps/opencs/model/tools/racecheck.cpp +++ b/apps/opencs/model/tools/racecheck.cpp @@ -41,17 +41,17 @@ void CSMTools::RaceCheckStage::performPerRecord(int stage, CSMDoc::Messages& mes messages.add(id, "Description is missing", "", CSMDoc::Message::Severity_Warning); // test for positive height - if (race.mData.mHeight.mMale <= 0) + if (race.mData.mMaleHeight <= 0) messages.add(id, "Male height is non-positive", "", CSMDoc::Message::Severity_Error); - if (race.mData.mHeight.mFemale <= 0) + if (race.mData.mFemaleHeight <= 0) messages.add(id, "Female height is non-positive", "", CSMDoc::Message::Severity_Error); // test for non-negative weight - if (race.mData.mWeight.mMale < 0) + if (race.mData.mMaleWeight < 0) messages.add(id, "Male weight is negative", "", CSMDoc::Message::Severity_Error); - if (race.mData.mWeight.mFemale < 0) + if (race.mData.mFemaleWeight < 0) messages.add(id, "Female weight is negative", "", CSMDoc::Message::Severity_Error); /// \todo check data members that can't be edited in the table view diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index 5e5ff83fcf..da805d5c6d 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -570,19 +570,34 @@ namespace CSMWorld QVariant get(const Record& record) const override { - const ESM::Race::MaleFemaleF& value = mWeight ? record.get().mData.mWeight : record.get().mData.mHeight; - - return mMale ? value.mMale : value.mFemale; + if (mWeight) + { + if (mMale) + return record.get().mData.mMaleWeight; + return record.get().mData.mFemaleWeight; + } + if (mMale) + return record.get().mData.mMaleHeight; + return record.get().mData.mFemaleHeight; } void set(Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); - - ESM::Race::MaleFemaleF& value = mWeight ? record2.mData.mWeight : record2.mData.mHeight; - - (mMale ? value.mMale : value.mFemale) = data.toFloat(); - + if (mWeight) + { + if (mMale) + record2.mData.mMaleWeight = data.toFloat(); + else + record2.mData.mFemaleWeight = data.toFloat(); + } + else + { + if (mMale) + record2.mData.mMaleHeight = data.toFloat(); + else + record2.mData.mFemaleHeight = data.toFloat(); + } record.setModified(record2); } diff --git a/apps/opencs/model/world/nestedcoladapterimp.cpp b/apps/opencs/model/world/nestedcoladapterimp.cpp index b96cf46465..13ae821a77 100644 --- a/apps/opencs/model/world/nestedcoladapterimp.cpp +++ b/apps/opencs/model/world/nestedcoladapterimp.cpp @@ -741,8 +741,8 @@ namespace CSMWorld QVariant RaceAttributeAdapter::getData(const Record& record, int subRowIndex, int subColIndex) const { ESM::Race race = record.get(); - - if (subRowIndex < 0 || subRowIndex >= ESM::Attribute::Length) + ESM::RefId attribute = ESM::Attribute::indexToRefId(subRowIndex); + if (attribute.empty()) throw std::runtime_error("index out of range"); switch (subColIndex) @@ -750,9 +750,9 @@ namespace CSMWorld case 0: return subRowIndex; case 1: - return race.mData.mAttributeValues[subRowIndex].mMale; + return race.mData.getAttribute(attribute, true); case 2: - return race.mData.mAttributeValues[subRowIndex].mFemale; + return race.mData.getAttribute(attribute, false); default: throw std::runtime_error("Race Attribute subcolumn index out of range"); } @@ -762,8 +762,8 @@ namespace CSMWorld Record& record, const QVariant& value, int subRowIndex, int subColIndex) const { ESM::Race race = record.get(); - - if (subRowIndex < 0 || subRowIndex >= ESM::Attribute::Length) + ESM::RefId attribute = ESM::Attribute::indexToRefId(subRowIndex); + if (attribute.empty()) throw std::runtime_error("index out of range"); switch (subColIndex) @@ -771,10 +771,10 @@ namespace CSMWorld case 0: return; // throw an exception here? case 1: - race.mData.mAttributeValues[subRowIndex].mMale = value.toInt(); + race.mData.setAttribute(attribute, true, value.toInt()); break; case 2: - race.mData.mAttributeValues[subRowIndex].mFemale = value.toInt(); + race.mData.setAttribute(attribute, false, value.toInt()); break; default: throw std::runtime_error("Race Attribute subcolumn index out of range"); diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 95a3b713fa..c6276753de 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -92,13 +92,7 @@ namespace const auto& attributes = MWBase::Environment::get().getESMStore()->get(); int level = creatureStats.getLevel(); for (const ESM::Attribute& attribute : attributes) - { - auto index = ESM::Attribute::refIdToIndex(attribute.mId); - assert(index >= 0); - - const ESM::Race::MaleFemale& value = race->mData.mAttributeValues[static_cast(index)]; - creatureStats.setAttribute(attribute.mId, male ? value.mMale : value.mFemale); - } + creatureStats.setAttribute(attribute.mId, race->mData.getAttribute(attribute.mId, male)); // class bonus const ESM::Class* class_ = MWBase::Environment::get().getESMStore()->get().find(npc->mClass); @@ -1199,24 +1193,24 @@ namespace MWClass if (ptr == MWMechanics::getPlayer() && ptr.isInCell() && MWBase::Environment::get().getWorld()->isFirstPerson()) { if (ref->mBase->isMale()) - scale *= race->mData.mHeight.mMale; + scale *= race->mData.mMaleHeight; else - scale *= race->mData.mHeight.mFemale; + scale *= race->mData.mFemaleHeight; return; } if (ref->mBase->isMale()) { - scale.x() *= race->mData.mWeight.mMale; - scale.y() *= race->mData.mWeight.mMale; - scale.z() *= race->mData.mHeight.mMale; + scale.x() *= race->mData.mMaleWeight; + scale.y() *= race->mData.mMaleWeight; + scale.z() *= race->mData.mMaleHeight; } else { - scale.x() *= race->mData.mWeight.mFemale; - scale.y() *= race->mData.mWeight.mFemale; - scale.z() *= race->mData.mHeight.mFemale; + scale.x() *= race->mData.mFemaleWeight; + scale.y() *= race->mData.mFemaleWeight; + scale.z() *= race->mData.mFemaleHeight; } } diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 713add719b..3d9f4352ec 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1966,7 +1966,7 @@ namespace MWMechanics { const ESM::NPC* npc = mPtr.get()->mBase; const ESM::Race* race = world->getStore().get().find(npc->mRace); - float weight = npc->isMale() ? race->mData.mWeight.mMale : race->mData.mWeight.mFemale; + float weight = npc->isMale() ? race->mData.mMaleWeight : race->mData.mFemaleWeight; scale *= weight; } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index f95df16855..9a5b09ffe2 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -152,13 +152,7 @@ namespace MWMechanics bool male = (player->mFlags & ESM::NPC::Female) == 0; for (const ESM::Attribute& attribute : esmStore.get()) - { - auto index = ESM::Attribute::refIdToIndex(attribute.mId); - assert(index >= 0); - - const ESM::Race::MaleFemale& value = race->mData.mAttributeValues[static_cast(index)]; - creatureStats.setAttribute(attribute.mId, male ? value.mMale : value.mFemale); - } + creatureStats.setAttribute(attribute.mId, race->mData.getAttribute(attribute.mId, male)); for (const ESM::Skill& skill : esmStore.get()) { diff --git a/apps/openmw/mwworld/projectilemanager.cpp b/apps/openmw/mwworld/projectilemanager.cpp index d873f16a59..b36d2a3221 100644 --- a/apps/openmw/mwworld/projectilemanager.cpp +++ b/apps/openmw/mwworld/projectilemanager.cpp @@ -453,7 +453,7 @@ namespace MWWorld { const auto npc = caster.get()->mBase; const auto race = store.get().find(npc->mRace); - speed *= npc->isMale() ? race->mData.mWeight.mMale : race->mData.mWeight.mFemale; + speed *= npc->isMale() ? race->mData.mMaleWeight : race->mData.mFemaleWeight; } osg::Vec3f direction = orient * osg::Vec3f(0, 1, 0); direction.normalize(); diff --git a/components/esm/defs.hpp b/components/esm/defs.hpp index 55404ee768..6254830f63 100644 --- a/components/esm/defs.hpp +++ b/components/esm/defs.hpp @@ -18,9 +18,9 @@ namespace ESM struct EpochTimeStamp { float mGameHour; - int mDay; - int mMonth; - int mYear; + int32_t mDay; + int32_t mMonth; + int32_t mYear; }; // Pixel color value. Standard four-byte rr,gg,bb,aa format. diff --git a/components/esm3/cellref.cpp b/components/esm3/cellref.cpp index c4c2fca986..42edec8f1f 100644 --- a/components/esm3/cellref.cpp +++ b/components/esm3/cellref.cpp @@ -116,7 +116,7 @@ namespace ESM cellRef.mTeleport = true; } else - esm.skipHTSized<24, ESM::Position>(); + esm.skipHSub(); break; case fourCC("DNAM"): getHStringOrSkip(cellRef.mDestCell); @@ -134,7 +134,7 @@ namespace ESM if constexpr (load) esm.getHT(cellRef.mPos.pos, cellRef.mPos.rot); else - esm.skipHTSized<24, decltype(cellRef.mPos)>(); + esm.skipHSub(); break; case fourCC("NAM0"): { diff --git a/components/esm3/esmreader.cpp b/components/esm3/esmreader.cpp index 77468f22d5..92a04fb487 100644 --- a/components/esm3/esmreader.cpp +++ b/components/esm3/esmreader.cpp @@ -263,7 +263,7 @@ namespace ESM { FormId res; if (wide) - getHNTSized<8>(res, tag); + getHNT(tag, res.mIndex, res.mContentFile); else getHNT(res.mIndex, tag); return res; @@ -496,7 +496,8 @@ namespace ESM case RefIdType::FormId: { FormId formId{}; - getTSized<8>(formId); + getT(formId.mIndex); + getT(formId.mContentFile); if (applyContentFileMapping(formId)) return RefId(formId); else diff --git a/components/esm3/esmreader.hpp b/components/esm3/esmreader.hpp index 63db1634fc..53af8f69e6 100644 --- a/components/esm3/esmreader.hpp +++ b/components/esm3/esmreader.hpp @@ -333,7 +333,7 @@ namespace ESM mEsm->read(static_cast(x), static_cast(size)); } - void getName(NAME& name) { getTSized<4>(name); } + void getName(NAME& name) { getT(name.mData); } void getUint(uint32_t& u) { getT(u); } std::string getMaybeFixedStringSize(std::size_t size); diff --git a/components/esm3/loadfact.cpp b/components/esm3/loadfact.cpp index 9d4b832f97..1dd1fe1a0e 100644 --- a/components/esm3/loadfact.cpp +++ b/components/esm3/loadfact.cpp @@ -17,6 +17,47 @@ namespace ESM return mSkills.at(index); } + void RankData::load(ESMReader& esm) + { + esm.getT(mAttribute1); + esm.getT(mAttribute2); + esm.getT(mPrimarySkill); + esm.getT(mFavouredSkill); + esm.getT(mFactReaction); + } + + void RankData::save(ESMWriter& esm) const + { + esm.writeT(mAttribute1); + esm.writeT(mAttribute2); + esm.writeT(mPrimarySkill); + esm.writeT(mFavouredSkill); + esm.writeT(mFactReaction); + } + + void Faction::FADTstruct::load(ESMReader& esm) + { + esm.getSubHeader(); + esm.getT(mAttribute); + for (auto& rank : mRankData) + rank.load(esm); + esm.getT(mSkills); + esm.getT(mIsHidden); + if (mIsHidden > 1) + esm.fail("Unknown flag!"); + } + + void Faction::FADTstruct::save(ESMWriter& esm) const + { + esm.startSubRecord("FADT"); + esm.writeT(mAttribute); + for (const auto& rank : mRankData) + rank.save(esm); + esm.writeT(mSkills); + esm.writeT(mIsHidden); + esm.endRecord("FADT"); + } + void Faction::load(ESMReader& esm, bool& isDeleted) { isDeleted = false; @@ -47,9 +88,7 @@ namespace ESM mRanks[rankCounter++] = esm.getHString(); break; case fourCC("FADT"): - esm.getHTSized<240>(mData); - if (mData.mIsHidden > 1) - esm.fail("Unknown flag!"); + mData.load(esm); hasData = true; break; case fourCC("ANAM"): @@ -101,7 +140,7 @@ namespace ESM esm.writeHNString("RNAM", rank, 32); } - esm.writeHNT("FADT", mData, 240); + mData.save(esm); for (auto it = mReactions.begin(); it != mReactions.end(); ++it) { diff --git a/components/esm3/loadfact.hpp b/components/esm3/loadfact.hpp index 2359d276a2..eef2126514 100644 --- a/components/esm3/loadfact.hpp +++ b/components/esm3/loadfact.hpp @@ -30,6 +30,9 @@ namespace ESM int32_t mPrimarySkill, mFavouredSkill; int32_t mFactReaction; // Reaction from faction members + + void load(ESMReader& esm); + void save(ESMWriter& esm) const; }; struct Faction @@ -60,6 +63,9 @@ namespace ESM int32_t getSkill(size_t index, bool ignored = false) const; ///< Throws an exception for invalid values of \a index. + + void load(ESMReader& esm); + void save(ESMWriter& esm) const; }; // 240 bytes FADTstruct mData; diff --git a/components/esm3/loadrace.cpp b/components/esm3/loadrace.cpp index eb8faf40e9..8c7b89d07d 100644 --- a/components/esm3/loadrace.cpp +++ b/components/esm3/loadrace.cpp @@ -3,16 +3,61 @@ #include "esmreader.hpp" #include "esmwriter.hpp" +#include + namespace ESM { - int Race::MaleFemale::getValue(bool male) const + int32_t Race::RADTstruct::getAttribute(ESM::RefId attribute, bool male) const + { + int index = ESM::Attribute::refIdToIndex(attribute); + if (index < 0) + return 0; + if (!male) + index++; + return mAttributeValues[static_cast(index)]; + } + + void Race::RADTstruct::setAttribute(ESM::RefId attribute, bool male, int32_t value) + { + int index = ESM::Attribute::refIdToIndex(attribute); + if (index < 0) + return; + if (!male) + index++; + mAttributeValues[static_cast(index)] = value; + } + + void Race::RADTstruct::load(ESMReader& esm) { - return male ? mMale : mFemale; + esm.getSubHeader(); + for (auto& bonus : mBonus) + { + esm.getT(bonus.mSkill); + esm.getT(bonus.mBonus); + } + esm.getT(mAttributeValues); + esm.getT(mMaleHeight); + esm.getT(mFemaleHeight); + esm.getT(mMaleWeight); + esm.getT(mFemaleWeight); + esm.getT(mFlags); } - float Race::MaleFemaleF::getValue(bool male) const + void Race::RADTstruct::save(ESMWriter& esm) const { - return male ? mMale : mFemale; + esm.startSubRecord("RADT"); + for (const auto& bonus : mBonus) + { + esm.writeT(bonus.mSkill); + esm.writeT(bonus.mBonus); + } + esm.writeT(mAttributeValues); + esm.writeT(mMaleHeight); + esm.writeT(mFemaleHeight); + esm.writeT(mMaleWeight); + esm.writeT(mFemaleWeight); + esm.writeT(mFlags); + esm.endRecord("RADT"); } void Race::load(ESMReader& esm, bool& isDeleted) @@ -37,7 +82,7 @@ namespace ESM mName = esm.getHString(); break; case fourCC("RADT"): - esm.getHTSized<140>(mData); + mData.load(esm); hasData = true; break; case fourCC("DESC"): @@ -71,7 +116,7 @@ namespace ESM } esm.writeHNOCString("FNAM", mName); - esm.writeHNT("RADT", mData, 140); + mData.save(esm); mPowers.save(esm); esm.writeHNOString("DESC", mDescription); } @@ -90,11 +135,10 @@ namespace ESM bonus.mBonus = 0; } - for (auto& attribute : mData.mAttributeValues) - attribute.mMale = attribute.mFemale = 1; + mData.mAttributeValues.fill(1); - mData.mHeight.mMale = mData.mHeight.mFemale = 1; - mData.mWeight.mMale = mData.mWeight.mFemale = 1; + mData.mMaleHeight = mData.mFemaleHeight = 1; + mData.mMaleWeight = mData.mFemaleWeight = 1; mData.mFlags = 0; } diff --git a/components/esm3/loadrace.hpp b/components/esm3/loadrace.hpp index 8cb9d76118..4493240ac8 100644 --- a/components/esm3/loadrace.hpp +++ b/components/esm3/loadrace.hpp @@ -31,20 +31,6 @@ namespace ESM int32_t mBonus; }; - struct MaleFemale - { - int32_t mMale, mFemale; - - int getValue(bool male) const; - }; - - struct MaleFemaleF - { - float mMale, mFemale; - - float getValue(bool male) const; - }; - enum Flags { Playable = 0x01, @@ -57,14 +43,20 @@ namespace ESM std::array mBonus; // Attribute values for male/female - std::array mAttributeValues; + std::array mAttributeValues; // The actual eye level height (in game units) is (probably) given // as 'height' times 128. This has not been tested yet. - MaleFemaleF mHeight, mWeight; + float mMaleHeight, mFemaleHeight, mMaleWeight, mFemaleWeight; int32_t mFlags; // 0x1 - playable, 0x2 - beast race + int32_t getAttribute(ESM::RefId attribute, bool male) const; + void setAttribute(ESM::RefId attribute, bool male, int32_t value); + + void load(ESMReader& esm); + void save(ESMWriter& esm) const; + }; // Size = 140 bytes RADTstruct mData; diff --git a/components/esm3/loadtes3.cpp b/components/esm3/loadtes3.cpp index 86b62234da..131510ce89 100644 --- a/components/esm3/loadtes3.cpp +++ b/components/esm3/loadtes3.cpp @@ -45,7 +45,8 @@ namespace ESM if (esm.isNextSub("GMDT")) { - esm.getHTSized<124>(mGameData); + esm.getHT(mGameData.mCurrentHealth, mGameData.mMaximumHealth, mGameData.mHour, mGameData.unknown1, + mGameData.mCurrentCell.mData, mGameData.unknown2, mGameData.mPlayerName.mData); } if (esm.isNextSub("SCRD")) { diff --git a/components/esm3/loadtes3.hpp b/components/esm3/loadtes3.hpp index 8b14d41645..2f7493e15f 100644 --- a/components/esm3/loadtes3.hpp +++ b/components/esm3/loadtes3.hpp @@ -11,9 +11,6 @@ namespace ESM class ESMReader; class ESMWriter; -#pragma pack(push) -#pragma pack(1) - struct Data { /* File format version. This is actually a float, the supported @@ -38,8 +35,6 @@ namespace ESM NAME32 mPlayerName; }; -#pragma pack(pop) - /// \brief File header record struct Header { diff --git a/components/esm3/player.cpp b/components/esm3/player.cpp index 3b52f8d779..901b52ce1d 100644 --- a/components/esm3/player.cpp +++ b/components/esm3/player.cpp @@ -13,12 +13,12 @@ namespace ESM mCellId = esm.getCellId(); - esm.getHNTSized<12>(mLastKnownExteriorPosition, "LKEP"); + esm.getHNT("LKEP", mLastKnownExteriorPosition); if (esm.isNextSub("MARK")) { mHasMark = true; - esm.getHTSized<24>(mMarkedPosition); + esm.getHT(mMarkedPosition.pos, mMarkedPosition.rot); mMarkedCell = esm.getCellId(); } else diff --git a/components/esm3/projectilestate.cpp b/components/esm3/projectilestate.cpp index bed9073999..e20cefa882 100644 --- a/components/esm3/projectilestate.cpp +++ b/components/esm3/projectilestate.cpp @@ -17,8 +17,8 @@ namespace ESM void BaseProjectileState::load(ESMReader& esm) { mId = esm.getHNRefId("ID__"); - esm.getHNTSized<12>(mPosition, "VEC3"); - esm.getHNTSized<16>(mOrientation, "QUAT"); + esm.getHNT("VEC3", mPosition.mValues); + esm.getHNT("QUAT", mOrientation.mValues); esm.getHNT(mActorId, "ACTO"); } @@ -58,7 +58,7 @@ namespace ESM BaseProjectileState::load(esm); mBowId = esm.getHNRefId("BOW_"); - esm.getHNTSized<12>(mVelocity, "VEL_"); + esm.getHNT("VEL_", mVelocity.mValues); mAttackStrength = 1.f; esm.getHNOT(mAttackStrength, "STR_"); diff --git a/components/esm3/savedgame.cpp b/components/esm3/savedgame.cpp index cec2b5e189..3ffe062d76 100644 --- a/components/esm3/savedgame.cpp +++ b/components/esm3/savedgame.cpp @@ -17,7 +17,7 @@ namespace ESM mPlayerCellName = esm.getHNRefId("PLCE").toString(); else mPlayerCellName = esm.getHNString("PLCE"); - esm.getHNTSized<16>(mInGameTime, "TSTM"); + esm.getHNT("TSTM", mInGameTime.mGameHour, mInGameTime.mDay, mInGameTime.mMonth, mInGameTime.mYear); esm.getHNT(mTimePlayed, "TIME"); mDescription = esm.getHNString("DESC"); From dbf9d42cc5ce3f3f782a47daa98a80c7b959d470 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sun, 17 Dec 2023 14:03:45 +0100 Subject: [PATCH 2/7] Remove sized reads from essimporter --- apps/essimporter/converter.cpp | 8 ++++---- apps/essimporter/importacdt.hpp | 7 ++----- apps/essimporter/importcellref.cpp | 19 +++++++++++++------ apps/essimporter/importcntc.hpp | 2 +- apps/essimporter/importcrec.hpp | 2 +- apps/essimporter/importdial.cpp | 4 ++-- apps/essimporter/importdial.hpp | 2 +- apps/essimporter/importgame.cpp | 22 +++++++++++----------- apps/essimporter/importgame.hpp | 8 ++++---- apps/essimporter/importinventory.cpp | 10 +++++----- apps/essimporter/importinventory.hpp | 6 +++--- apps/essimporter/importklst.cpp | 2 +- apps/essimporter/importklst.hpp | 4 ++-- apps/essimporter/importnpcc.cpp | 2 +- apps/essimporter/importnpcc.hpp | 2 +- apps/essimporter/importplayer.cpp | 14 ++++++++++---- apps/essimporter/importplayer.hpp | 27 ++++++++++++--------------- apps/essimporter/importproj.cpp | 4 +++- apps/essimporter/importproj.h | 5 +---- apps/essimporter/importscpt.cpp | 3 ++- apps/essimporter/importscpt.hpp | 2 +- apps/essimporter/importscri.cpp | 6 +++--- apps/essimporter/importsplm.cpp | 6 ++++-- apps/essimporter/importsplm.h | 16 ++++++---------- 24 files changed, 94 insertions(+), 89 deletions(-) diff --git a/apps/essimporter/converter.cpp b/apps/essimporter/converter.cpp index 4751fd9497..00c24514ea 100644 --- a/apps/essimporter/converter.cpp +++ b/apps/essimporter/converter.cpp @@ -90,14 +90,14 @@ namespace ESSImport struct MAPH { - unsigned int size; - unsigned int value; + uint32_t size; + uint32_t value; }; void ConvertFMAP::read(ESM::ESMReader& esm) { MAPH maph; - esm.getHNTSized<8>(maph, "MAPH"); + esm.getHNT("MAPH", maph.size, maph.value); std::vector data; esm.getSubNameIs("MAPD"); esm.getSubHeader(); @@ -278,7 +278,7 @@ namespace ESSImport while (esm.isNextSub("MPCD")) { float notepos[3]; - esm.getHTSized<3 * sizeof(float)>(notepos); + esm.getHT(notepos); // Markers seem to be arranged in a 32*32 grid, notepos has grid-indices. // This seems to be the reason markers can't be placed everywhere in interior cells, diff --git a/apps/essimporter/importacdt.hpp b/apps/essimporter/importacdt.hpp index 785e988200..54910ac82c 100644 --- a/apps/essimporter/importacdt.hpp +++ b/apps/essimporter/importacdt.hpp @@ -25,14 +25,12 @@ namespace ESSImport }; /// Actor data, shared by (at least) REFR and CellRef -#pragma pack(push) -#pragma pack(1) struct ACDT { // Note, not stored at *all*: // - Level changes are lost on reload, except for the player (there it's in the NPC record). unsigned char mUnknown[12]; - unsigned int mFlags; + uint32_t mFlags; float mBreathMeter; // Seconds left before drowning unsigned char mUnknown2[20]; float mDynamic[3][2]; @@ -41,7 +39,7 @@ namespace ESSImport float mMagicEffects[27]; // Effect attributes: // https://wiki.openmw.org/index.php?title=Research:Magic#Effect_attributes unsigned char mUnknown4[4]; - unsigned int mGoldPool; + uint32_t mGoldPool; unsigned char mCountDown; // seen the same value as in ACSC.mCorpseClearCountdown, maybe // this one is for respawning? unsigned char mUnknown5[3]; @@ -60,7 +58,6 @@ namespace ESSImport unsigned char mUnknown[3]; float mTime; }; -#pragma pack(pop) struct ActorData { diff --git a/apps/essimporter/importcellref.cpp b/apps/essimporter/importcellref.cpp index a900440a96..d9639eb0dd 100644 --- a/apps/essimporter/importcellref.cpp +++ b/apps/essimporter/importcellref.cpp @@ -48,14 +48,18 @@ namespace ESSImport if (esm.isNextSub("ACDT")) { mActorData.mHasACDT = true; - esm.getHTSized<264>(mActorData.mACDT); + esm.getHT(mActorData.mACDT.mUnknown, mActorData.mACDT.mFlags, mActorData.mACDT.mBreathMeter, + mActorData.mACDT.mUnknown2, mActorData.mACDT.mDynamic, mActorData.mACDT.mUnknown3, + mActorData.mACDT.mAttributes, mActorData.mACDT.mMagicEffects, mActorData.mACDT.mUnknown4, + mActorData.mACDT.mGoldPool, mActorData.mACDT.mCountDown, mActorData.mACDT.mUnknown5); } mActorData.mHasACSC = false; if (esm.isNextSub("ACSC")) { mActorData.mHasACSC = true; - esm.getHTSized<112>(mActorData.mACSC); + esm.getHT(mActorData.mACSC.mUnknown1, mActorData.mACSC.mFlags, mActorData.mACSC.mUnknown2, + mActorData.mACSC.mCorpseClearCountdown, mActorData.mACSC.mUnknown3); } if (esm.isNextSub("ACSL")) @@ -137,7 +141,7 @@ namespace ESSImport if (esm.isNextSub("ANIS")) { mActorData.mHasANIS = true; - esm.getHTSized<8>(mActorData.mANIS); + esm.getHT(mActorData.mANIS.mGroupIndex, mActorData.mANIS.mUnknown, mActorData.mANIS.mTime); } if (esm.isNextSub("LVCR")) @@ -155,13 +159,16 @@ namespace ESSImport // DATA should occur for all references, except levelled creature spawners // I've seen DATA *twice* on a creature record, and with the exact same content too! weird // alarmvoi0000.ess - esm.getHNOTSized<24>(mPos, "DATA"); - esm.getHNOTSized<24>(mPos, "DATA"); + for (int i = 0; i < 2; ++i) + { + if (esm.isNextSub("DATA")) + esm.getHNT("DATA", mPos.pos, mPos.rot); + } mDeleted = 0; if (esm.isNextSub("DELE")) { - unsigned int deleted; + uint32_t deleted; esm.getHT(deleted); mDeleted = ((deleted >> 24) & 0x2) != 0; // the other 3 bytes seem to be uninitialized garbage } diff --git a/apps/essimporter/importcntc.hpp b/apps/essimporter/importcntc.hpp index 1bc7d94bd5..6ee843805e 100644 --- a/apps/essimporter/importcntc.hpp +++ b/apps/essimporter/importcntc.hpp @@ -14,7 +14,7 @@ namespace ESSImport /// Changed container contents struct CNTC { - int mIndex; + int32_t mIndex; Inventory mInventory; diff --git a/apps/essimporter/importcrec.hpp b/apps/essimporter/importcrec.hpp index 77933eafe8..87a2d311c8 100644 --- a/apps/essimporter/importcrec.hpp +++ b/apps/essimporter/importcrec.hpp @@ -15,7 +15,7 @@ namespace ESSImport /// Creature changes struct CREC { - int mIndex; + int32_t mIndex; Inventory mInventory; ESM::AIPackageList mAiPackages; diff --git a/apps/essimporter/importdial.cpp b/apps/essimporter/importdial.cpp index 6c45f9d059..43905738a1 100644 --- a/apps/essimporter/importdial.cpp +++ b/apps/essimporter/importdial.cpp @@ -8,11 +8,11 @@ namespace ESSImport void DIAL::load(ESM::ESMReader& esm) { // See ESM::Dialogue::Type enum, not sure why we would need this here though - int type = 0; + int32_t type = 0; esm.getHNOT(type, "DATA"); // Deleted dialogue in a savefile. No clue what this means... - int deleted = 0; + int32_t deleted = 0; esm.getHNOT(deleted, "DELE"); mIndex = 0; diff --git a/apps/essimporter/importdial.hpp b/apps/essimporter/importdial.hpp index 9a1e882332..2a09af9f2a 100644 --- a/apps/essimporter/importdial.hpp +++ b/apps/essimporter/importdial.hpp @@ -10,7 +10,7 @@ namespace ESSImport struct DIAL { - int mIndex; // Journal index + int32_t mIndex; // Journal index void load(ESM::ESMReader& esm); }; diff --git a/apps/essimporter/importgame.cpp b/apps/essimporter/importgame.cpp index 5295d2a1e8..8161a20031 100644 --- a/apps/essimporter/importgame.cpp +++ b/apps/essimporter/importgame.cpp @@ -9,17 +9,17 @@ namespace ESSImport { esm.getSubNameIs("GMDT"); esm.getSubHeader(); - if (esm.getSubSize() == 92) - { - esm.getExact(&mGMDT, 92); - mGMDT.mSecundaPhase = 0; - } - else if (esm.getSubSize() == 96) - { - esm.getTSized<96>(mGMDT); - } - else - esm.fail("unexpected subrecord size for GAME.GMDT"); + bool hasSecundaPhase = esm.getSubSize() == 96; + esm.getT(mGMDT.mCellName); + esm.getT(mGMDT.mFogColour); + esm.getT(mGMDT.mFogDensity); + esm.getT(mGMDT.mCurrentWeather); + esm.getT(mGMDT.mNextWeather); + esm.getT(mGMDT.mWeatherTransition); + esm.getT(mGMDT.mTimeOfNextTransition); + esm.getT(mGMDT.mMasserPhase); + if (hasSecundaPhase) + esm.getT(mGMDT.mSecundaPhase); mGMDT.mWeatherTransition &= (0x000000ff); mGMDT.mSecundaPhase &= (0x000000ff); diff --git a/apps/essimporter/importgame.hpp b/apps/essimporter/importgame.hpp index 8b26b9d8bd..e880166b45 100644 --- a/apps/essimporter/importgame.hpp +++ b/apps/essimporter/importgame.hpp @@ -15,12 +15,12 @@ namespace ESSImport struct GMDT { char mCellName[64]{}; - int mFogColour{ 0 }; + int32_t mFogColour{ 0 }; float mFogDensity{ 0.f }; - int mCurrentWeather{ 0 }, mNextWeather{ 0 }; - int mWeatherTransition{ 0 }; // 0-100 transition between weathers, top 3 bytes may be garbage + int32_t mCurrentWeather{ 0 }, mNextWeather{ 0 }; + int32_t mWeatherTransition{ 0 }; // 0-100 transition between weathers, top 3 bytes may be garbage float mTimeOfNextTransition{ 0.f }; // weather changes when gamehour == timeOfNextTransition - int mMasserPhase{ 0 }, mSecundaPhase{ 0 }; // top 3 bytes may be garbage + int32_t mMasserPhase{ 0 }, mSecundaPhase{ 0 }; // top 3 bytes may be garbage }; GMDT mGMDT; diff --git a/apps/essimporter/importinventory.cpp b/apps/essimporter/importinventory.cpp index 9d71c04f2a..f1db301bd0 100644 --- a/apps/essimporter/importinventory.cpp +++ b/apps/essimporter/importinventory.cpp @@ -12,7 +12,7 @@ namespace ESSImport while (esm.isNextSub("NPCO")) { ContItem contItem; - esm.getHTSized<36>(contItem); + esm.getHT(contItem.mCount, contItem.mItem.mData); InventoryItem item; item.mId = contItem.mItem.toString(); @@ -28,7 +28,7 @@ namespace ESSImport bool newStack = esm.isNextSub("XIDX"); if (newStack) { - unsigned int idx; + uint32_t idx; esm.getHT(idx); separateStacks = true; item.mCount = 1; @@ -40,7 +40,7 @@ namespace ESSImport bool isDeleted = false; item.ESM::CellRef::loadData(esm, isDeleted); - int charge = -1; + int32_t charge = -1; esm.getHNOT(charge, "XHLT"); item.mChargeInt = charge; @@ -60,7 +60,7 @@ namespace ESSImport // this is currently not handled properly. esm.getSubHeader(); - int itemIndex; // index of the item in the NPCO list + int32_t itemIndex; // index of the item in the NPCO list esm.getT(itemIndex); if (itemIndex < 0 || itemIndex >= int(mItems.size())) @@ -68,7 +68,7 @@ namespace ESSImport // appears to be a relative index for only the *possible* slots this item can be equipped in, // i.e. 0 most of the time - int slotIndex; + int32_t slotIndex; esm.getT(slotIndex); mItems[itemIndex].mRelativeEquipmentSlot = slotIndex; diff --git a/apps/essimporter/importinventory.hpp b/apps/essimporter/importinventory.hpp index 7a11b3f0a0..9e0dcbb30a 100644 --- a/apps/essimporter/importinventory.hpp +++ b/apps/essimporter/importinventory.hpp @@ -19,7 +19,7 @@ namespace ESSImport struct ContItem { - int mCount; + int32_t mCount; ESM::NAME32 mItem; }; @@ -28,8 +28,8 @@ namespace ESSImport struct InventoryItem : public ESM::CellRef { std::string mId; - int mCount; - int mRelativeEquipmentSlot; + int32_t mCount; + int32_t mRelativeEquipmentSlot; SCRI mSCRI; }; std::vector mItems; diff --git a/apps/essimporter/importklst.cpp b/apps/essimporter/importklst.cpp index d4cfc7f769..2d5e09e913 100644 --- a/apps/essimporter/importklst.cpp +++ b/apps/essimporter/importklst.cpp @@ -10,7 +10,7 @@ namespace ESSImport while (esm.isNextSub("KNAM")) { std::string refId = esm.getHString(); - int count; + int32_t count; esm.getHNT(count, "CNAM"); mKillCounter[refId] = count; } diff --git a/apps/essimporter/importklst.hpp b/apps/essimporter/importklst.hpp index 7c1ff03bb6..8a098ac501 100644 --- a/apps/essimporter/importklst.hpp +++ b/apps/essimporter/importklst.hpp @@ -18,9 +18,9 @@ namespace ESSImport void load(ESM::ESMReader& esm); /// RefId, kill count - std::map mKillCounter; + std::map mKillCounter; - int mWerewolfKills; + int32_t mWerewolfKills; }; } diff --git a/apps/essimporter/importnpcc.cpp b/apps/essimporter/importnpcc.cpp index c115040074..c1a53b6cef 100644 --- a/apps/essimporter/importnpcc.cpp +++ b/apps/essimporter/importnpcc.cpp @@ -7,7 +7,7 @@ namespace ESSImport void NPCC::load(ESM::ESMReader& esm) { - esm.getHNTSized<8>(mNPDT, "NPDT"); + esm.getHNT("NPDT", mNPDT.mDisposition, mNPDT.unknown, mNPDT.mReputation, mNPDT.unknown2, mNPDT.mIndex); while (esm.isNextSub("AI_W") || esm.isNextSub("AI_E") || esm.isNextSub("AI_T") || esm.isNextSub("AI_F") || esm.isNextSub("AI_A")) diff --git a/apps/essimporter/importnpcc.hpp b/apps/essimporter/importnpcc.hpp index 762add1906..f3532f2103 100644 --- a/apps/essimporter/importnpcc.hpp +++ b/apps/essimporter/importnpcc.hpp @@ -21,7 +21,7 @@ namespace ESSImport unsigned char unknown; unsigned char mReputation; unsigned char unknown2; - int mIndex; + int32_t mIndex; } mNPDT; Inventory mInventory; diff --git a/apps/essimporter/importplayer.cpp b/apps/essimporter/importplayer.cpp index 165926d15a..b9e1d4f291 100644 --- a/apps/essimporter/importplayer.cpp +++ b/apps/essimporter/importplayer.cpp @@ -19,7 +19,12 @@ namespace ESSImport mMNAM = esm.getHString(); } - esm.getHNTSized<212>(mPNAM, "PNAM"); + esm.getHNT("PNAM", mPNAM.mPlayerFlags, mPNAM.mLevelProgress, mPNAM.mSkillProgress, mPNAM.mSkillIncreases, + mPNAM.mTelekinesisRangeBonus, mPNAM.mVisionBonus, mPNAM.mDetectKeyMagnitude, + mPNAM.mDetectEnchantmentMagnitude, mPNAM.mDetectAnimalMagnitude, mPNAM.mMarkLocation.mX, + mPNAM.mMarkLocation.mY, mPNAM.mMarkLocation.mZ, mPNAM.mMarkLocation.mRotZ, mPNAM.mMarkLocation.mCellX, + mPNAM.mMarkLocation.mCellY, mPNAM.mUnknown3, mPNAM.mVerticalRotation.mData, mPNAM.mSpecIncreases, + mPNAM.mUnknown4); if (esm.isNextSub("SNAM")) esm.skipHSub(); @@ -54,7 +59,7 @@ namespace ESSImport if (esm.isNextSub("ENAM")) { mHasENAM = true; - esm.getHTSized<8>(mENAM); + esm.getHT(mENAM.mCellX, mENAM.mCellY); } if (esm.isNextSub("LNAM")) @@ -63,7 +68,8 @@ namespace ESSImport while (esm.isNextSub("FNAM")) { FNAM fnam; - esm.getHTSized<44>(fnam); + esm.getHT( + fnam.mRank, fnam.mUnknown1, fnam.mReputation, fnam.mFlags, fnam.mUnknown2, fnam.mFactionName.mData); mFactions.push_back(fnam); } @@ -71,7 +77,7 @@ namespace ESSImport if (esm.isNextSub("AADT")) // Attack animation data? { mHasAADT = true; - esm.getHTSized<44>(mAADT); + esm.getHT(mAADT.animGroupIndex, mAADT.mUnknown5); } if (esm.isNextSub("KNAM")) diff --git a/apps/essimporter/importplayer.hpp b/apps/essimporter/importplayer.hpp index 0fb820cb64..3602abd9c3 100644 --- a/apps/essimporter/importplayer.hpp +++ b/apps/essimporter/importplayer.hpp @@ -17,7 +17,7 @@ namespace ESSImport /// Other player data struct PCDT { - int mBounty; + int32_t mBounty; std::string mBirthsign; std::vector mKnownDialogueTopics; @@ -41,13 +41,11 @@ namespace ESSImport PlayerFlags_LevitationDisabled = 0x80000 }; -#pragma pack(push) -#pragma pack(1) struct FNAM { unsigned char mRank; unsigned char mUnknown1[3]; - int mReputation; + int32_t mReputation; unsigned char mFlags; // 0x1: unknown, 0x2: expelled unsigned char mUnknown2[3]; ESM::NAME32 mFactionName; @@ -59,7 +57,7 @@ namespace ESSImport { float mX, mY, mZ; // worldspace position float mRotZ; // Z angle in radians - int mCellX, mCellY; // grid coordinates; for interior cells this is always (0, 0) + int32_t mCellX, mCellY; // grid coordinates; for interior cells this is always (0, 0) }; struct Rotation @@ -67,15 +65,15 @@ namespace ESSImport float mData[3][3]; }; - int mPlayerFlags; // controls, camera and draw state - unsigned int mLevelProgress; + int32_t mPlayerFlags; // controls, camera and draw state + uint32_t mLevelProgress; float mSkillProgress[27]; // skill progress, non-uniform scaled unsigned char mSkillIncreases[8]; // number of skill increases for each attribute - int mTelekinesisRangeBonus; // in units; seems redundant + int32_t mTelekinesisRangeBonus; // in units; seems redundant float mVisionBonus; // range: <0.0, 1.0>; affected by light spells and Get/Mod/SetPCVisionBonus - int mDetectKeyMagnitude; // seems redundant - int mDetectEnchantmentMagnitude; // seems redundant - int mDetectAnimalMagnitude; // seems redundant + int32_t mDetectKeyMagnitude; // seems redundant + int32_t mDetectEnchantmentMagnitude; // seems redundant + int32_t mDetectAnimalMagnitude; // seems redundant MarkLocation mMarkLocation; unsigned char mUnknown3[4]; Rotation mVerticalRotation; @@ -85,16 +83,15 @@ namespace ESSImport struct ENAM { - int mCellX; - int mCellY; + int32_t mCellX; + int32_t mCellY; }; struct AADT // 44 bytes { - int animGroupIndex; // See convertANIS() for the mapping. + int32_t animGroupIndex; // See convertANIS() for the mapping. unsigned char mUnknown5[40]; }; -#pragma pack(pop) std::vector mFactions; PNAM mPNAM; diff --git a/apps/essimporter/importproj.cpp b/apps/essimporter/importproj.cpp index f9a92095e0..a09ade81dd 100644 --- a/apps/essimporter/importproj.cpp +++ b/apps/essimporter/importproj.cpp @@ -10,7 +10,9 @@ namespace ESSImport while (esm.isNextSub("PNAM")) { PNAM pnam; - esm.getHTSized<184>(pnam); + esm.getHT(pnam.mAttackStrength, pnam.mSpeed, pnam.mUnknown, pnam.mFlightTime, pnam.mSplmIndex, + pnam.mUnknown2, pnam.mVelocity.mValues, pnam.mPosition.mValues, pnam.mUnknown3, pnam.mActorId.mData, + pnam.mArrowId.mData, pnam.mBowId.mData); mProjectiles.push_back(pnam); } } diff --git a/apps/essimporter/importproj.h b/apps/essimporter/importproj.h index d1c544f66f..01592af3e3 100644 --- a/apps/essimporter/importproj.h +++ b/apps/essimporter/importproj.h @@ -16,15 +16,13 @@ namespace ESSImport struct PROJ { -#pragma pack(push) -#pragma pack(1) struct PNAM // 184 bytes { float mAttackStrength; float mSpeed; unsigned char mUnknown[4 * 2]; float mFlightTime; - int mSplmIndex; // reference to a SPLM record (0 for ballistic projectiles) + int32_t mSplmIndex; // reference to a SPLM record (0 for ballistic projectiles) unsigned char mUnknown2[4]; ESM::Vector3 mVelocity; ESM::Vector3 mPosition; @@ -35,7 +33,6 @@ namespace ESSImport bool isMagic() const { return mSplmIndex != 0; } }; -#pragma pack(pop) std::vector mProjectiles; diff --git a/apps/essimporter/importscpt.cpp b/apps/essimporter/importscpt.cpp index 746d0b90e7..8fe4afd336 100644 --- a/apps/essimporter/importscpt.cpp +++ b/apps/essimporter/importscpt.cpp @@ -7,7 +7,8 @@ namespace ESSImport void SCPT::load(ESM::ESMReader& esm) { - esm.getHNTSized<52>(mSCHD, "SCHD"); + esm.getHNT("SCHD", mSCHD.mName.mData, mSCHD.mData.mNumShorts, mSCHD.mData.mNumLongs, mSCHD.mData.mNumFloats, + mSCHD.mData.mScriptDataSize, mSCHD.mData.mStringTableSize); mSCRI.load(esm); diff --git a/apps/essimporter/importscpt.hpp b/apps/essimporter/importscpt.hpp index 8f60532447..a75a3e38da 100644 --- a/apps/essimporter/importscpt.hpp +++ b/apps/essimporter/importscpt.hpp @@ -29,7 +29,7 @@ namespace ESSImport SCRI mSCRI; bool mRunning; - int mRefNum; // Targeted reference, -1: no reference + int32_t mRefNum; // Targeted reference, -1: no reference void load(ESM::ESMReader& esm); }; diff --git a/apps/essimporter/importscri.cpp b/apps/essimporter/importscri.cpp index b6c1d4094c..c0425cef32 100644 --- a/apps/essimporter/importscri.cpp +++ b/apps/essimporter/importscri.cpp @@ -9,7 +9,7 @@ namespace ESSImport { mScript = esm.getHNOString("SCRI"); - int numShorts = 0, numLongs = 0, numFloats = 0; + int32_t numShorts = 0, numLongs = 0, numFloats = 0; if (esm.isNextSub("SLCS")) { esm.getSubHeader(); @@ -23,7 +23,7 @@ namespace ESSImport esm.getSubHeader(); for (int i = 0; i < numShorts; ++i) { - short val; + int16_t val; esm.getT(val); mShorts.push_back(val); } @@ -35,7 +35,7 @@ namespace ESSImport esm.getSubHeader(); for (int i = 0; i < numLongs; ++i) { - int val; + int32_t val; esm.getT(val); mLongs.push_back(val); } diff --git a/apps/essimporter/importsplm.cpp b/apps/essimporter/importsplm.cpp index a0478f4d92..6019183f83 100644 --- a/apps/essimporter/importsplm.cpp +++ b/apps/essimporter/importsplm.cpp @@ -11,13 +11,15 @@ namespace ESSImport { ActiveSpell spell; esm.getHT(spell.mIndex); - esm.getHNTSized<160>(spell.mSPDT, "SPDT"); + esm.getHNT("SPDT", spell.mSPDT.mType, spell.mSPDT.mId.mData, spell.mSPDT.mUnknown, + spell.mSPDT.mCasterId.mData, spell.mSPDT.mSourceId.mData, spell.mSPDT.mUnknown2); spell.mTarget = esm.getHNOString("TNAM"); while (esm.isNextSub("NPDT")) { ActiveEffect effect; - esm.getHTSized<56>(effect.mNPDT); + esm.getHT(effect.mNPDT.mAffectedActorId.mData, effect.mNPDT.mUnknown, effect.mNPDT.mMagnitude, + effect.mNPDT.mSecondsActive, effect.mNPDT.mUnknown2); // Effect-specific subrecords can follow: // - INAM for disintegration and bound effects diff --git a/apps/essimporter/importsplm.h b/apps/essimporter/importsplm.h index 8187afb131..39405db6d3 100644 --- a/apps/essimporter/importsplm.h +++ b/apps/essimporter/importsplm.h @@ -15,11 +15,9 @@ namespace ESSImport struct SPLM { -#pragma pack(push) -#pragma pack(1) struct SPDT // 160 bytes { - int mType; // 1 = spell, 2 = enchantment, 3 = potion + int32_t mType; // 1 = spell, 2 = enchantment, 3 = potion ESM::NAME32 mId; // base ID of a spell/enchantment/potion unsigned char mUnknown[4 * 4]; ESM::NAME32 mCasterId; @@ -31,31 +29,29 @@ namespace ESSImport { ESM::NAME32 mAffectedActorId; unsigned char mUnknown[4 * 2]; - int mMagnitude; + int32_t mMagnitude; float mSecondsActive; unsigned char mUnknown2[4 * 2]; }; struct INAM // 40 bytes { - int mUnknown; + int32_t mUnknown; unsigned char mUnknown2; ESM::FixedString<35> mItemId; // disintegrated item / bound item / item to re-equip after expiration }; struct CNAM // 36 bytes { - int mUnknown; // seems to always be 0 + int32_t mUnknown; // seems to always be 0 ESM::NAME32 mSummonedOrCommandedActor[32]; }; struct VNAM // 4 bytes { - int mUnknown; + int32_t mUnknown; }; -#pragma pack(pop) - struct ActiveEffect { NPDT mNPDT; @@ -63,7 +59,7 @@ namespace ESSImport struct ActiveSpell { - int mIndex; + int32_t mIndex; SPDT mSPDT; std::string mTarget; std::vector mActiveEffects; From c10b9297f0b7ee7208e891d34759d870c6b34a69 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sun, 17 Dec 2023 14:05:10 +0100 Subject: [PATCH 3/7] Remove Sized methods from ESMReader --- components/esm3/esmreader.hpp | 49 ++++------------------------------- 1 file changed, 5 insertions(+), 44 deletions(-) diff --git a/components/esm3/esmreader.hpp b/components/esm3/esmreader.hpp index 53af8f69e6..d753023645 100644 --- a/components/esm3/esmreader.hpp +++ b/components/esm3/esmreader.hpp @@ -131,10 +131,10 @@ namespace ESM ESM::RefId getCellId(); // Read data of a given type, stored in a subrecord of a given name - template >> + template void getHNT(X& x, NAME name) { - getHNTSized(x, name); + getHNT(name, x); } template @@ -149,26 +149,11 @@ namespace ESM } // Optional version of getHNT - template >> + template void getHNOT(X& x, NAME name) - { - getHNOTSized(x, name); - } - - // Version with extra size checking, to make sure the compiler - // doesn't mess up our struct padding. - template - void getHNTSized(X& x, NAME name) - { - getSubNameIs(name); - getHTSized(x); - } - - template - void getHNOTSized(X& x, NAME name) { if (isNextSub(name)) - getHTSized(x); + getHT(x); } // Get data of a given type/size, including subrecord header @@ -185,37 +170,13 @@ namespace ESM template >> void skipHT() { - skipHTSized(); - } - - // Version with extra size checking, to make sure the compiler - // doesn't mess up our struct padding. - template - void getHTSized(X& x) - { - getSubHeader(); - if (mCtx.leftSub != size) - reportSubSizeMismatch(size, mCtx.leftSub); - getTSized(x); - } - - template - void skipHTSized() - { - static_assert(sizeof(T) == size); + constexpr size_t size = sizeof(T); getSubHeader(); if (mCtx.leftSub != size) reportSubSizeMismatch(size, mCtx.leftSub); skip(size); } - template - void getTSized(X& x) - { - static_assert(sizeof(X) == size); - getExact(&x, size); - } - // Read a string by the given name if it is the next record. std::string getHNOString(NAME name); From 37415b0382df3853caa3aac689db74e41d26176d Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sun, 17 Dec 2023 15:16:32 +0100 Subject: [PATCH 4/7] Don't use getExact to read structs --- apps/esmtool/record.cpp | 10 +--- .../opencs/model/tools/referenceablecheck.cpp | 22 ++----- apps/opencs/model/world/refidadapterimp.cpp | 59 ++----------------- apps/openmw/mwclass/npc.cpp | 10 +--- .../mwmechanics/mechanicsmanagerimp.cpp | 11 +--- components/esm3/loadnpc.cpp | 31 ++++++---- components/esm3/loadnpc.hpp | 3 +- components/esm3/loadpgrd.cpp | 7 ++- components/esm3/loadrace.cpp | 2 + 9 files changed, 47 insertions(+), 108 deletions(-) diff --git a/apps/esmtool/record.cpp b/apps/esmtool/record.cpp index 71158299aa..044fbf9f93 100644 --- a/apps/esmtool/record.cpp +++ b/apps/esmtool/record.cpp @@ -1084,14 +1084,8 @@ namespace EsmTool std::cout << " Rank: " << (int)mData.mNpdt.mRank << std::endl; std::cout << " Attributes:" << std::endl; - std::cout << " Strength: " << (int)mData.mNpdt.mStrength << std::endl; - std::cout << " Intelligence: " << (int)mData.mNpdt.mIntelligence << std::endl; - std::cout << " Willpower: " << (int)mData.mNpdt.mWillpower << std::endl; - std::cout << " Agility: " << (int)mData.mNpdt.mAgility << std::endl; - std::cout << " Speed: " << (int)mData.mNpdt.mSpeed << std::endl; - std::cout << " Endurance: " << (int)mData.mNpdt.mEndurance << std::endl; - std::cout << " Personality: " << (int)mData.mNpdt.mPersonality << std::endl; - std::cout << " Luck: " << (int)mData.mNpdt.mLuck << std::endl; + for (size_t i = 0; i != mData.mNpdt.mAttributes.size(); i++) + std::cout << " " << attributeLabel(i) << ": " << int(mData.mNpdt.mAttributes[i]) << std::endl; std::cout << " Skills:" << std::endl; for (size_t i = 0; i != mData.mNpdt.mSkills.size(); i++) diff --git a/apps/opencs/model/tools/referenceablecheck.cpp b/apps/opencs/model/tools/referenceablecheck.cpp index e2e178f90a..d25568fd0a 100644 --- a/apps/opencs/model/tools/referenceablecheck.cpp +++ b/apps/opencs/model/tools/referenceablecheck.cpp @@ -693,22 +693,12 @@ void CSMTools::ReferenceableCheckStage::npcCheck( } else if (npc.mNpdt.mHealth != 0) { - if (npc.mNpdt.mStrength == 0) - messages.add(id, "Strength is equal to zero", "", CSMDoc::Message::Severity_Warning); - if (npc.mNpdt.mIntelligence == 0) - messages.add(id, "Intelligence is equal to zero", "", CSMDoc::Message::Severity_Warning); - if (npc.mNpdt.mWillpower == 0) - messages.add(id, "Willpower is equal to zero", "", CSMDoc::Message::Severity_Warning); - if (npc.mNpdt.mAgility == 0) - messages.add(id, "Agility is equal to zero", "", CSMDoc::Message::Severity_Warning); - if (npc.mNpdt.mSpeed == 0) - messages.add(id, "Speed is equal to zero", "", CSMDoc::Message::Severity_Warning); - if (npc.mNpdt.mEndurance == 0) - messages.add(id, "Endurance is equal to zero", "", CSMDoc::Message::Severity_Warning); - if (npc.mNpdt.mPersonality == 0) - messages.add(id, "Personality is equal to zero", "", CSMDoc::Message::Severity_Warning); - if (npc.mNpdt.mLuck == 0) - messages.add(id, "Luck is equal to zero", "", CSMDoc::Message::Severity_Warning); + for (size_t i = 0; i < npc.mNpdt.mAttributes.size(); ++i) + { + if (npc.mNpdt.mAttributes[i] == 0) + messages.add(id, ESM::Attribute::indexToRefId(i).getRefIdString() + " is equal to zero", {}, + CSMDoc::Message::Severity_Warning); + } } if (level <= 0) diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index 0ddfbbb051..c6179facb8 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -938,30 +938,9 @@ QVariant CSMWorld::NpcAttributesRefIdAdapter::getNestedData( if (subColIndex == 0) return subRowIndex; - else if (subColIndex == 1) - switch (subRowIndex) - { - case 0: - return static_cast(npcStruct.mStrength); - case 1: - return static_cast(npcStruct.mIntelligence); - case 2: - return static_cast(npcStruct.mWillpower); - case 3: - return static_cast(npcStruct.mAgility); - case 4: - return static_cast(npcStruct.mSpeed); - case 5: - return static_cast(npcStruct.mEndurance); - case 6: - return static_cast(npcStruct.mPersonality); - case 7: - return static_cast(npcStruct.mLuck); - default: - return QVariant(); // throw an exception here? - } - else - return QVariant(); // throw an exception here? + else if (subColIndex == 1 && subRowIndex >= 0 && subRowIndex < ESM::Attribute::Length) + return static_cast(npcStruct.mAttributes[subRowIndex]); + return QVariant(); // throw an exception here? } void CSMWorld::NpcAttributesRefIdAdapter::setNestedData( @@ -972,36 +951,8 @@ void CSMWorld::NpcAttributesRefIdAdapter::setNestedData( ESM::NPC npc = record.get(); ESM::NPC::NPDTstruct52& npcStruct = npc.mNpdt; - if (subColIndex == 1) - switch (subRowIndex) - { - case 0: - npcStruct.mStrength = static_cast(value.toInt()); - break; - case 1: - npcStruct.mIntelligence = static_cast(value.toInt()); - break; - case 2: - npcStruct.mWillpower = static_cast(value.toInt()); - break; - case 3: - npcStruct.mAgility = static_cast(value.toInt()); - break; - case 4: - npcStruct.mSpeed = static_cast(value.toInt()); - break; - case 5: - npcStruct.mEndurance = static_cast(value.toInt()); - break; - case 6: - npcStruct.mPersonality = static_cast(value.toInt()); - break; - case 7: - npcStruct.mLuck = static_cast(value.toInt()); - break; - default: - return; // throw an exception here? - } + if (subColIndex == 1 && subRowIndex >= 0 && subRowIndex < ESM::Attribute::Length) + npcStruct.mAttributes[subRowIndex] = static_cast(value.toInt()); else return; // throw an exception here? diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index c6276753de..7c6f16b06f 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -313,14 +313,8 @@ namespace MWClass for (size_t i = 0; i < ref->mBase->mNpdt.mSkills.size(); ++i) data->mNpcStats.getSkill(ESM::Skill::indexToRefId(i)).setBase(ref->mBase->mNpdt.mSkills[i]); - data->mNpcStats.setAttribute(ESM::Attribute::Strength, ref->mBase->mNpdt.mStrength); - data->mNpcStats.setAttribute(ESM::Attribute::Intelligence, ref->mBase->mNpdt.mIntelligence); - data->mNpcStats.setAttribute(ESM::Attribute::Willpower, ref->mBase->mNpdt.mWillpower); - data->mNpcStats.setAttribute(ESM::Attribute::Agility, ref->mBase->mNpdt.mAgility); - data->mNpcStats.setAttribute(ESM::Attribute::Speed, ref->mBase->mNpdt.mSpeed); - data->mNpcStats.setAttribute(ESM::Attribute::Endurance, ref->mBase->mNpdt.mEndurance); - data->mNpcStats.setAttribute(ESM::Attribute::Personality, ref->mBase->mNpdt.mPersonality); - data->mNpcStats.setAttribute(ESM::Attribute::Luck, ref->mBase->mNpdt.mLuck); + for (size_t i = 0; i < ref->mBase->mNpdt.mAttributes.size(); ++i) + data->mNpcStats.setAttribute(ESM::Attribute::indexToRefId(i), ref->mBase->mNpdt.mAttributes[i]); data->mNpcStats.setHealth(ref->mBase->mNpdt.mHealth); data->mNpcStats.setMagicka(ref->mBase->mNpdt.mMana); diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 9a5b09ffe2..39b5286139 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -134,14 +134,9 @@ namespace MWMechanics for (size_t i = 0; i < player->mNpdt.mSkills.size(); ++i) npcStats.getSkill(ESM::Skill::indexToRefId(i)).setBase(player->mNpdt.mSkills[i]); - creatureStats.setAttribute(ESM::Attribute::Strength, player->mNpdt.mStrength); - creatureStats.setAttribute(ESM::Attribute::Intelligence, player->mNpdt.mIntelligence); - creatureStats.setAttribute(ESM::Attribute::Willpower, player->mNpdt.mWillpower); - creatureStats.setAttribute(ESM::Attribute::Agility, player->mNpdt.mAgility); - creatureStats.setAttribute(ESM::Attribute::Speed, player->mNpdt.mSpeed); - creatureStats.setAttribute(ESM::Attribute::Endurance, player->mNpdt.mEndurance); - creatureStats.setAttribute(ESM::Attribute::Personality, player->mNpdt.mPersonality); - creatureStats.setAttribute(ESM::Attribute::Luck, player->mNpdt.mLuck); + for (size_t i = 0; i < player->mNpdt.mAttributes.size(); ++i) + npcStats.setAttribute(ESM::Attribute::indexToRefId(i), player->mNpdt.mSkills[i]); + const MWWorld::ESMStore& esmStore = *MWBase::Environment::get().getESMStore(); // race diff --git a/components/esm3/loadnpc.cpp b/components/esm3/loadnpc.cpp index d844f7d2bc..8a86780fe2 100644 --- a/components/esm3/loadnpc.cpp +++ b/components/esm3/loadnpc.cpp @@ -59,23 +59,31 @@ namespace ESM if (esm.getSubSize() == 52) { mNpdtType = NPC_DEFAULT; - esm.getExact(&mNpdt, 52); + esm.getT(mNpdt.mLevel); + esm.getT(mNpdt.mAttributes); + esm.getT(mNpdt.mSkills); + esm.getT(mNpdt.mUnknown1); + esm.getT(mNpdt.mHealth); + esm.getT(mNpdt.mMana); + esm.getT(mNpdt.mFatigue); + esm.getT(mNpdt.mDisposition); + esm.getT(mNpdt.mReputation); + esm.getT(mNpdt.mRank); + esm.getT(mNpdt.mUnknown2); + esm.getT(mNpdt.mGold); } else if (esm.getSubSize() == 12) { - // Reading into temporary NPDTstruct12 object - NPDTstruct12 npdt12; mNpdtType = NPC_WITH_AUTOCALCULATED_STATS; - esm.getExact(&npdt12, 12); // Clearing the mNdpt struct to initialize all values blankNpdt(); - // Swiching to an internal representation - mNpdt.mLevel = npdt12.mLevel; - mNpdt.mDisposition = npdt12.mDisposition; - mNpdt.mReputation = npdt12.mReputation; - mNpdt.mRank = npdt12.mRank; - mNpdt.mGold = npdt12.mGold; + esm.getT(mNpdt.mLevel); + esm.getT(mNpdt.mDisposition); + esm.getT(mNpdt.mReputation); + esm.getT(mNpdt.mRank); + esm.skip(3); + esm.getT(mNpdt.mGold); } else esm.fail("NPC_NPDT must be 12 or 52 bytes long"); @@ -213,8 +221,7 @@ namespace ESM void NPC::blankNpdt() { mNpdt.mLevel = 0; - mNpdt.mStrength = mNpdt.mIntelligence = mNpdt.mWillpower = mNpdt.mAgility = mNpdt.mSpeed = mNpdt.mEndurance - = mNpdt.mPersonality = mNpdt.mLuck = 0; + mNpdt.mAttributes.fill(0); mNpdt.mSkills.fill(0); mNpdt.mReputation = 0; mNpdt.mHealth = mNpdt.mMana = mNpdt.mFatigue = 0; diff --git a/components/esm3/loadnpc.hpp b/components/esm3/loadnpc.hpp index af8c2a8574..c50dd3414d 100644 --- a/components/esm3/loadnpc.hpp +++ b/components/esm3/loadnpc.hpp @@ -6,6 +6,7 @@ #include #include "aipackage.hpp" +#include "components/esm/attr.hpp" #include "components/esm/defs.hpp" #include "components/esm/refid.hpp" #include "loadcont.hpp" @@ -80,7 +81,7 @@ namespace ESM struct NPDTstruct52 { int16_t mLevel; - unsigned char mStrength, mIntelligence, mWillpower, mAgility, mSpeed, mEndurance, mPersonality, mLuck; + std::array mAttributes; // mSkill can grow up to 200, it must be unsigned std::array mSkills; diff --git a/components/esm3/loadpgrd.cpp b/components/esm3/loadpgrd.cpp index 8d60d25524..4f0a62a9d4 100644 --- a/components/esm3/loadpgrd.cpp +++ b/components/esm3/loadpgrd.cpp @@ -70,7 +70,12 @@ namespace ESM for (uint16_t i = 0; i < mData.mPoints; ++i) { Point p; - esm.getExact(&p, sizeof(Point)); + esm.getT(p.mX); + esm.getT(p.mY); + esm.getT(p.mZ); + esm.getT(p.mAutogenerated); + esm.getT(p.mConnectionNum); + esm.getT(p.mUnknown); mPoints.push_back(p); edgeCount += p.mConnectionNum; } diff --git a/components/esm3/loadrace.cpp b/components/esm3/loadrace.cpp index 8c7b89d07d..0996a5ac48 100644 --- a/components/esm3/loadrace.cpp +++ b/components/esm3/loadrace.cpp @@ -12,6 +12,7 @@ namespace ESM int index = ESM::Attribute::refIdToIndex(attribute); if (index < 0) return 0; + index *= 2; if (!male) index++; return mAttributeValues[static_cast(index)]; @@ -22,6 +23,7 @@ namespace ESM int index = ESM::Attribute::refIdToIndex(attribute); if (index < 0) return; + index *= 2; if (!male) index++; mAttributeValues[static_cast(index)] = value; From 88731f864e46b8f7f7cd38802738465e2c6f835b Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sun, 17 Dec 2023 15:21:12 +0100 Subject: [PATCH 5/7] Add imports --- apps/essimporter/converter.cpp | 1 + apps/essimporter/importacdt.hpp | 1 + apps/essimporter/importcellref.cpp | 1 + apps/essimporter/importcntc.cpp | 1 + apps/essimporter/importcrec.hpp | 1 + apps/essimporter/importdial.hpp | 3 +++ apps/essimporter/importgame.hpp | 2 ++ apps/essimporter/importinventory.hpp | 1 + apps/essimporter/importklst.hpp | 1 + apps/essimporter/importnpcc.hpp | 1 + apps/essimporter/importplayer.hpp | 1 + apps/essimporter/importproj.h | 1 + apps/essimporter/importscpt.hpp | 2 ++ apps/essimporter/importscri.hpp | 1 + apps/essimporter/importsplm.h | 1 + 15 files changed, 19 insertions(+) diff --git a/apps/essimporter/converter.cpp b/apps/essimporter/converter.cpp index 00c24514ea..b44d376842 100644 --- a/apps/essimporter/converter.cpp +++ b/apps/essimporter/converter.cpp @@ -1,6 +1,7 @@ #include "converter.hpp" #include +#include #include #include diff --git a/apps/essimporter/importacdt.hpp b/apps/essimporter/importacdt.hpp index 54910ac82c..65519c6a6c 100644 --- a/apps/essimporter/importacdt.hpp +++ b/apps/essimporter/importacdt.hpp @@ -1,6 +1,7 @@ #ifndef OPENMW_ESSIMPORT_ACDT_H #define OPENMW_ESSIMPORT_ACDT_H +#include #include #include "importscri.hpp" diff --git a/apps/essimporter/importcellref.cpp b/apps/essimporter/importcellref.cpp index d9639eb0dd..756770d0b5 100644 --- a/apps/essimporter/importcellref.cpp +++ b/apps/essimporter/importcellref.cpp @@ -1,6 +1,7 @@ #include "importcellref.hpp" #include +#include namespace ESSImport { diff --git a/apps/essimporter/importcntc.cpp b/apps/essimporter/importcntc.cpp index 41f4e50101..34c99babef 100644 --- a/apps/essimporter/importcntc.cpp +++ b/apps/essimporter/importcntc.cpp @@ -1,6 +1,7 @@ #include "importcntc.hpp" #include +#include namespace ESSImport { diff --git a/apps/essimporter/importcrec.hpp b/apps/essimporter/importcrec.hpp index 87a2d311c8..5217f4edc4 100644 --- a/apps/essimporter/importcrec.hpp +++ b/apps/essimporter/importcrec.hpp @@ -3,6 +3,7 @@ #include "importinventory.hpp" #include +#include namespace ESM { diff --git a/apps/essimporter/importdial.hpp b/apps/essimporter/importdial.hpp index 2a09af9f2a..b8b6fd536a 100644 --- a/apps/essimporter/importdial.hpp +++ b/apps/essimporter/importdial.hpp @@ -1,5 +1,8 @@ #ifndef OPENMW_ESSIMPORT_IMPORTDIAL_H #define OPENMW_ESSIMPORT_IMPORTDIAL_H + +#include + namespace ESM { class ESMReader; diff --git a/apps/essimporter/importgame.hpp b/apps/essimporter/importgame.hpp index e880166b45..276060ae4c 100644 --- a/apps/essimporter/importgame.hpp +++ b/apps/essimporter/importgame.hpp @@ -1,6 +1,8 @@ #ifndef OPENMW_ESSIMPORT_GAME_H #define OPENMW_ESSIMPORT_GAME_H +#include + namespace ESM { class ESMReader; diff --git a/apps/essimporter/importinventory.hpp b/apps/essimporter/importinventory.hpp index 9e0dcbb30a..7261e64f68 100644 --- a/apps/essimporter/importinventory.hpp +++ b/apps/essimporter/importinventory.hpp @@ -1,6 +1,7 @@ #ifndef OPENMW_ESSIMPORT_IMPORTINVENTORY_H #define OPENMW_ESSIMPORT_IMPORTINVENTORY_H +#include #include #include diff --git a/apps/essimporter/importklst.hpp b/apps/essimporter/importklst.hpp index 8a098ac501..9cdb2d701b 100644 --- a/apps/essimporter/importklst.hpp +++ b/apps/essimporter/importklst.hpp @@ -1,6 +1,7 @@ #ifndef OPENMW_ESSIMPORT_KLST_H #define OPENMW_ESSIMPORT_KLST_H +#include #include #include diff --git a/apps/essimporter/importnpcc.hpp b/apps/essimporter/importnpcc.hpp index f3532f2103..47925226e4 100644 --- a/apps/essimporter/importnpcc.hpp +++ b/apps/essimporter/importnpcc.hpp @@ -2,6 +2,7 @@ #define OPENMW_ESSIMPORT_NPCC_H #include +#include #include "importinventory.hpp" diff --git a/apps/essimporter/importplayer.hpp b/apps/essimporter/importplayer.hpp index 3602abd9c3..89957bf4b4 100644 --- a/apps/essimporter/importplayer.hpp +++ b/apps/essimporter/importplayer.hpp @@ -1,6 +1,7 @@ #ifndef OPENMW_ESSIMPORT_PLAYER_H #define OPENMW_ESSIMPORT_PLAYER_H +#include #include #include diff --git a/apps/essimporter/importproj.h b/apps/essimporter/importproj.h index 01592af3e3..a2e03b5ba3 100644 --- a/apps/essimporter/importproj.h +++ b/apps/essimporter/importproj.h @@ -3,6 +3,7 @@ #include #include +#include #include namespace ESM diff --git a/apps/essimporter/importscpt.hpp b/apps/essimporter/importscpt.hpp index a75a3e38da..af383b674c 100644 --- a/apps/essimporter/importscpt.hpp +++ b/apps/essimporter/importscpt.hpp @@ -3,6 +3,8 @@ #include "importscri.hpp" +#include + #include #include diff --git a/apps/essimporter/importscri.hpp b/apps/essimporter/importscri.hpp index 73d8942f81..0c83a4d3be 100644 --- a/apps/essimporter/importscri.hpp +++ b/apps/essimporter/importscri.hpp @@ -3,6 +3,7 @@ #include +#include #include namespace ESM diff --git a/apps/essimporter/importsplm.h b/apps/essimporter/importsplm.h index 39405db6d3..762e32d9da 100644 --- a/apps/essimporter/importsplm.h +++ b/apps/essimporter/importsplm.h @@ -2,6 +2,7 @@ #define OPENMW_ESSIMPORT_IMPORTSPLM_H #include +#include #include namespace ESM From 9f38ee82f45707ec5d9f937f6359ca8495797ab3 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sun, 17 Dec 2023 21:30:04 +0100 Subject: [PATCH 6/7] Fix misaligned address --- components/esm3/loadnpc.cpp | 34 +++++++++++++++++++++++----------- components/esm3/loadnpc.hpp | 15 --------------- 2 files changed, 23 insertions(+), 26 deletions(-) diff --git a/components/esm3/loadnpc.cpp b/components/esm3/loadnpc.cpp index 8a86780fe2..4a30649372 100644 --- a/components/esm3/loadnpc.cpp +++ b/components/esm3/loadnpc.cpp @@ -154,20 +154,32 @@ namespace ESM if (mNpdtType == NPC_DEFAULT) { - esm.writeHNT("NPDT", mNpdt, 52); + esm.startSubRecord("NPDT"); + esm.writeT(mNpdt.mLevel); + esm.writeT(mNpdt.mAttributes); + esm.writeT(mNpdt.mSkills); + esm.writeT(mNpdt.mUnknown1); + esm.writeT(mNpdt.mHealth); + esm.writeT(mNpdt.mMana); + esm.writeT(mNpdt.mFatigue); + esm.writeT(mNpdt.mDisposition); + esm.writeT(mNpdt.mReputation); + esm.writeT(mNpdt.mRank); + esm.writeT(mNpdt.mUnknown2); + esm.writeT(mNpdt.mGold); + esm.endRecord("NPDT"); } else if (mNpdtType == NPC_WITH_AUTOCALCULATED_STATS) { - NPDTstruct12 npdt12; - npdt12.mLevel = mNpdt.mLevel; - npdt12.mDisposition = mNpdt.mDisposition; - npdt12.mReputation = mNpdt.mReputation; - npdt12.mRank = mNpdt.mRank; - npdt12.mUnknown1 = 0; - npdt12.mUnknown2 = 0; - npdt12.mUnknown3 = 0; - npdt12.mGold = mNpdt.mGold; - esm.writeHNT("NPDT", npdt12, 12); + esm.startSubRecord("NPDT"); + esm.writeT(mNpdt.mLevel); + esm.writeT(mNpdt.mDisposition); + esm.writeT(mNpdt.mReputation); + esm.writeT(mNpdt.mRank); + constexpr char padding[] = { 0, 0, 0 }; + esm.writeT(padding); + esm.writeT(mNpdt.mGold); + esm.endRecord("NPDT"); } esm.writeHNT("FLAG", ((mBloodType << 10) + mFlags)); diff --git a/components/esm3/loadnpc.hpp b/components/esm3/loadnpc.hpp index c50dd3414d..76930365c8 100644 --- a/components/esm3/loadnpc.hpp +++ b/components/esm3/loadnpc.hpp @@ -75,9 +75,6 @@ namespace ESM NPC_DEFAULT = 52 }; -#pragma pack(push) -#pragma pack(1) - struct NPDTstruct52 { int16_t mLevel; @@ -93,18 +90,6 @@ namespace ESM int32_t mGold; }; // 52 bytes - // Structure for autocalculated characters. - // This is only used for load and save operations. - struct NPDTstruct12 - { - int16_t mLevel; - // see above - unsigned char mDisposition, mReputation, mRank; - char mUnknown1, mUnknown2, mUnknown3; - int32_t mGold; - }; // 12 bytes -#pragma pack(pop) - unsigned char mNpdtType; // Worth noting when saving the struct: // Although we might read a NPDTstruct12 in, we use NPDTstruct52 internally From 3e101ab409b25a5dd475527f7971d7f9482e108c Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Wed, 20 Dec 2023 12:28:34 +0100 Subject: [PATCH 7/7] Add a variadic getHNOT --- apps/essimporter/importcellref.cpp | 36 ++++++++---------------------- apps/essimporter/importplayer.cpp | 14 ++---------- components/esm3/aisequence.cpp | 7 +----- components/esm3/cellid.cpp | 14 +++--------- components/esm3/esmreader.hpp | 12 +++++++++- components/esm3/loadtes3.cpp | 13 ++++------- components/esm3/objectstate.cpp | 11 ++------- components/esm3/player.cpp | 9 ++------ 8 files changed, 34 insertions(+), 82 deletions(-) diff --git a/apps/essimporter/importcellref.cpp b/apps/essimporter/importcellref.cpp index 756770d0b5..56e888d3f6 100644 --- a/apps/essimporter/importcellref.cpp +++ b/apps/essimporter/importcellref.cpp @@ -45,23 +45,14 @@ namespace ESSImport bool isDeleted = false; ESM::CellRef::loadData(esm, isDeleted); - mActorData.mHasACDT = false; - if (esm.isNextSub("ACDT")) - { - mActorData.mHasACDT = true; - esm.getHT(mActorData.mACDT.mUnknown, mActorData.mACDT.mFlags, mActorData.mACDT.mBreathMeter, + mActorData.mHasACDT + = esm.getHNOT("ACDT", mActorData.mACDT.mUnknown, mActorData.mACDT.mFlags, mActorData.mACDT.mBreathMeter, mActorData.mACDT.mUnknown2, mActorData.mACDT.mDynamic, mActorData.mACDT.mUnknown3, mActorData.mACDT.mAttributes, mActorData.mACDT.mMagicEffects, mActorData.mACDT.mUnknown4, mActorData.mACDT.mGoldPool, mActorData.mACDT.mCountDown, mActorData.mACDT.mUnknown5); - } - mActorData.mHasACSC = false; - if (esm.isNextSub("ACSC")) - { - mActorData.mHasACSC = true; - esm.getHT(mActorData.mACSC.mUnknown1, mActorData.mACSC.mFlags, mActorData.mACSC.mUnknown2, - mActorData.mACSC.mCorpseClearCountdown, mActorData.mACSC.mUnknown3); - } + mActorData.mHasACSC = esm.getHNOT("ACSC", mActorData.mACSC.mUnknown1, mActorData.mACSC.mFlags, + mActorData.mACSC.mUnknown2, mActorData.mACSC.mCorpseClearCountdown, mActorData.mACSC.mUnknown3); if (esm.isNextSub("ACSL")) esm.skipHSubSize(112); @@ -127,23 +118,17 @@ namespace ESSImport } // FIXME: not all actors have this, add flag - if (esm.isNextSub("CHRD")) // npc only - esm.getHExact(mActorData.mSkills, 27 * 2 * sizeof(int)); + esm.getHNOT("CHRD", mActorData.mSkills); // npc only - if (esm.isNextSub("CRED")) // creature only - esm.getHExact(mActorData.mCombatStats, 3 * 2 * sizeof(int)); + esm.getHNOT("CRED", mActorData.mCombatStats); // creature only mActorData.mSCRI.load(esm); if (esm.isNextSub("ND3D")) esm.skipHSub(); - mActorData.mHasANIS = false; - if (esm.isNextSub("ANIS")) - { - mActorData.mHasANIS = true; - esm.getHT(mActorData.mANIS.mGroupIndex, mActorData.mANIS.mUnknown, mActorData.mANIS.mTime); - } + mActorData.mHasANIS + = esm.getHNOT("ANIS", mActorData.mANIS.mGroupIndex, mActorData.mANIS.mUnknown, mActorData.mANIS.mTime); if (esm.isNextSub("LVCR")) { @@ -161,10 +146,7 @@ namespace ESSImport // I've seen DATA *twice* on a creature record, and with the exact same content too! weird // alarmvoi0000.ess for (int i = 0; i < 2; ++i) - { - if (esm.isNextSub("DATA")) - esm.getHNT("DATA", mPos.pos, mPos.rot); - } + esm.getHNOT("DATA", mPos.pos, mPos.rot); mDeleted = 0; if (esm.isNextSub("DELE")) diff --git a/apps/essimporter/importplayer.cpp b/apps/essimporter/importplayer.cpp index b9e1d4f291..f4c280541d 100644 --- a/apps/essimporter/importplayer.cpp +++ b/apps/essimporter/importplayer.cpp @@ -55,12 +55,7 @@ namespace ESSImport if (esm.isNextSub("NAM3")) esm.skipHSub(); - mHasENAM = false; - if (esm.isNextSub("ENAM")) - { - mHasENAM = true; - esm.getHT(mENAM.mCellX, mENAM.mCellY); - } + mHasENAM = esm.getHNOT("ENAM", mENAM.mCellX, mENAM.mCellY); if (esm.isNextSub("LNAM")) esm.skipHSub(); @@ -73,12 +68,7 @@ namespace ESSImport mFactions.push_back(fnam); } - mHasAADT = false; - if (esm.isNextSub("AADT")) // Attack animation data? - { - mHasAADT = true; - esm.getHT(mAADT.animGroupIndex, mAADT.mUnknown5); - } + mHasAADT = esm.getHNOT("AADT", mAADT.animGroupIndex, mAADT.mUnknown5); // Attack animation data? if (esm.isNextSub("KNAM")) esm.skipHSub(); // assigned Quick Keys, I think diff --git a/components/esm3/aisequence.cpp b/components/esm3/aisequence.cpp index 21973acd1d..bbd42c400e 100644 --- a/components/esm3/aisequence.cpp +++ b/components/esm3/aisequence.cpp @@ -15,12 +15,7 @@ namespace ESM { esm.getHNT("DATA", mData.mDistance, mData.mDuration, mData.mTimeOfDay, mData.mIdle, mData.mShouldRepeat); esm.getHNT("STAR", mDurationData.mRemainingDuration, mDurationData.unused); // was mStartTime - mStoredInitialActorPosition = false; - if (esm.isNextSub("POS_")) - { - mStoredInitialActorPosition = true; - esm.getHT(mInitialActorPosition.mValues); - } + mStoredInitialActorPosition = esm.getHNOT("POS_", mInitialActorPosition.mValues); } void AiWander::save(ESMWriter& esm) const diff --git a/components/esm3/cellid.cpp b/components/esm3/cellid.cpp index 3df1336c6c..9a5be3aada 100644 --- a/components/esm3/cellid.cpp +++ b/components/esm3/cellid.cpp @@ -11,17 +11,9 @@ namespace ESM { mWorldspace = esm.getHNString("SPAC"); - if (esm.isNextSub("CIDX")) - { - esm.getHT(mIndex.mX, mIndex.mY); - mPaged = true; - } - else - { - mPaged = false; - mIndex.mX = 0; - mIndex.mY = 0; - } + mIndex.mX = 0; + mIndex.mY = 0; + mPaged = esm.getHNOT("CIDX", mIndex.mX, mIndex.mY); } void CellId::save(ESMWriter& esm) const diff --git a/components/esm3/esmreader.hpp b/components/esm3/esmreader.hpp index d753023645..bafc89a74c 100644 --- a/components/esm3/esmreader.hpp +++ b/components/esm3/esmreader.hpp @@ -151,9 +151,19 @@ namespace ESM // Optional version of getHNT template void getHNOT(X& x, NAME name) + { + getHNOT(name, x); + } + + template + bool getHNOT(NAME name, Args&... args) { if (isNextSub(name)) - getHT(x); + { + getHT(args...); + return true; + } + return false; } // Get data of a given type/size, including subrecord header diff --git a/components/esm3/loadtes3.cpp b/components/esm3/loadtes3.cpp index 131510ce89..b6fbe76553 100644 --- a/components/esm3/loadtes3.cpp +++ b/components/esm3/loadtes3.cpp @@ -20,10 +20,8 @@ namespace ESM void Header::load(ESMReader& esm) { - if (esm.isNextSub("FORM")) - esm.getHT(mFormatVersion); - else - mFormatVersion = DefaultFormatVersion; + mFormatVersion = DefaultFormatVersion; + esm.getHNOT("FORM", mFormatVersion); if (esm.isNextSub("HEDR")) { @@ -43,11 +41,8 @@ namespace ESM mMaster.push_back(m); } - if (esm.isNextSub("GMDT")) - { - esm.getHT(mGameData.mCurrentHealth, mGameData.mMaximumHealth, mGameData.mHour, mGameData.unknown1, - mGameData.mCurrentCell.mData, mGameData.unknown2, mGameData.mPlayerName.mData); - } + esm.getHNOT("GMDT", mGameData.mCurrentHealth, mGameData.mMaximumHealth, mGameData.mHour, mGameData.unknown1, + mGameData.mCurrentCell.mData, mGameData.unknown2, mGameData.mPlayerName.mData); if (esm.isNextSub("SCRD")) { esm.getSubHeader(); diff --git a/components/esm3/objectstate.cpp b/components/esm3/objectstate.cpp index 6e2621df29..a46200944a 100644 --- a/components/esm3/objectstate.cpp +++ b/components/esm3/objectstate.cpp @@ -32,15 +32,8 @@ namespace ESM mCount = 1; esm.getHNOT(mCount, "COUN"); - if (esm.isNextSub("POS_")) - { - std::array pos; - esm.getHT(pos); - memcpy(mPosition.pos, pos.data(), sizeof(float) * 3); - memcpy(mPosition.rot, pos.data() + 3, sizeof(float) * 3); - } - else - mPosition = mRef.mPos; + mPosition = mRef.mPos; + esm.getHNOT("POS_", mPosition.pos, mPosition.rot); mFlags = 0; esm.getHNOT(mFlags, "FLAG"); diff --git a/components/esm3/player.cpp b/components/esm3/player.cpp index 901b52ce1d..aa6b59abb9 100644 --- a/components/esm3/player.cpp +++ b/components/esm3/player.cpp @@ -15,14 +15,9 @@ namespace ESM esm.getHNT("LKEP", mLastKnownExteriorPosition); - if (esm.isNextSub("MARK")) - { - mHasMark = true; - esm.getHT(mMarkedPosition.pos, mMarkedPosition.rot); + mHasMark = esm.getHNOT("MARK", mMarkedPosition.pos, mMarkedPosition.rot); + if (mHasMark) mMarkedCell = esm.getCellId(); - } - else - mHasMark = false; // Automove, no longer used. if (esm.isNextSub("AMOV"))