From e69880f77eae0a8668e1b6c160a107c3bad8e734 Mon Sep 17 00:00:00 2001 From: greye Date: Thu, 20 Sep 2012 20:33:30 +0400 Subject: [PATCH] almost perfect byte copies, has redundant data --- apps/esmtool/esmtool.cpp | 14 +++++-- components/esm/esm_writer.cpp | 2 +- components/esm/loadcell.cpp | 66 ++++++++++++++++++------------ components/esm/loadcell.hpp | 2 + components/esm/loadinfo.cpp | 20 ++++----- components/esm/loadingr.cpp | 3 +- components/esm/loadland.cpp | 77 ++++++++++++++++++++++++++++------- components/esm/loadland.hpp | 4 ++ components/esm/loadmgef.cpp | 4 +- components/esm/loadpgrd.cpp | 2 +- components/esm/loadsndg.cpp | 4 +- components/esm/loadsscr.cpp | 5 +-- components/esm/loadsscr.hpp | 1 + 13 files changed, 140 insertions(+), 64 deletions(-) diff --git a/apps/esmtool/esmtool.cpp b/apps/esmtool/esmtool.cpp index 36ad95a31..cd0e8e1c1 100644 --- a/apps/esmtool/esmtool.cpp +++ b/apps/esmtool/esmtool.cpp @@ -714,6 +714,15 @@ int load(Arguments& info) << " Value: " << w.mData.mValue << endl; break; } + case REC_SSCR: + { + rec = new StartScript(); + StartScript &sscr = *(StartScript *) rec; + sscr.load(esm); + if (quiet) break; + cout << "Start script: " << sscr.mScript << endl; + break; + } default: if (find(skipped.begin(), skipped.end(), n.val) == skipped.end()) { @@ -832,16 +841,15 @@ int clone(Arguments& info) esm.startRecord(n.toString(), rec->getFlags()); string id = rec->getId(); + // TODO wrap this with std::set if (n.val == REC_GLOB || n.val == REC_CLAS || n.val == REC_FACT || n.val == REC_RACE || n.val == REC_SOUN || n.val == REC_REGN || n.val == REC_BSGN || n.val == REC_LTEX || n.val == REC_STAT || n.val == REC_DOOR || n.val == REC_MISC || n.val == REC_WEAP || n.val == REC_CONT || n.val == REC_SPEL || n.val == REC_CREA || n.val == REC_BODY || n.val == REC_LIGH || n.val == REC_ENCH || n.val == REC_NPC_ || n.val == REC_ARMO || n.val == REC_CLOT || n.val == REC_REPA || n.val == REC_ACTI || n.val == REC_APPA || n.val == REC_LOCK || n.val == REC_PROB || n.val == REC_INGR || n.val == REC_BOOK || n.val == REC_ALCH || n.val == REC_LEVI - || n.val == REC_LEVC) + || n.val == REC_LEVC || n.val == REC_SNDG || n.val == REC_CELL || n.val == REC_DIAL) esm.writeHNCString("NAME", id); - else if (n.val == REC_CELL) - esm.writeHNString("NAME", id); else esm.writeHNOString("NAME", id); diff --git a/components/esm/esm_writer.cpp b/components/esm/esm_writer.cpp index ef8a9c1b8..5bb9e286d 100644 --- a/components/esm/esm_writer.cpp +++ b/components/esm/esm_writer.cpp @@ -64,7 +64,7 @@ void ESMWriter::save(std::ostream& file) for (std::list::iterator it = m_masters.begin(); it != m_masters.end(); ++it) { - writeHNString("MAST", it->name); + writeHNCString("MAST", it->name); writeHNT("DATA", it->size); } diff --git a/components/esm/loadcell.cpp b/components/esm/loadcell.cpp index 8fe1c82f6..c83c5f400 100644 --- a/components/esm/loadcell.cpp +++ b/components/esm/loadcell.cpp @@ -18,12 +18,12 @@ void CellRef::save(ESMWriter &esm) esm.writeHNT("XSCL", mScale); } - esm.writeHNOString("ANAM", mOwner); - esm.writeHNOString("BNAM", mGlob); - esm.writeHNOString("XSOL", mSoul); + esm.writeHNOCString("ANAM", mOwner); + esm.writeHNOCString("BNAM", mGlob); + esm.writeHNOCString("XSOL", mSoul); - esm.writeHNOString("CNAM", mFaction); - if (mFactIndex != -1) { + esm.writeHNOCString("CNAM", mFaction); + if (mFactIndex != -2) { esm.writeHNT("INDX", mFactIndex); } @@ -31,7 +31,7 @@ void CellRef::save(ESMWriter &esm) esm.writeHNT("XCHG", mCharge); } - if (mIntv != 0) { + if (mIntv != -1) { esm.writeHNT("INTV", mIntv); } if (mNam9 != 0) { @@ -44,13 +44,13 @@ void CellRef::save(ESMWriter &esm) esm.writeHNOCString("DNAM", mDestCell); } - if (mLockLevel != 0) { + if (mLockLevel != -1) { esm.writeHNT("FLTV", mLockLevel); } - esm.writeHNOString("KNAM", mKey); - esm.writeHNOString("TNAM", mTrap); + esm.writeHNOCString("KNAM", mKey); + esm.writeHNOCString("TNAM", mTrap); - if (mUnam != 0) { + if (mUnam != -1) { esm.writeHNT("UNAM", mUnam); } if (mFltv != 0) { @@ -58,6 +58,9 @@ void CellRef::save(ESMWriter &esm) } esm.writeHNT("DATA", mPos, 24); + if (mNam0 != 0) { + esm.writeHNT("NAM0", mNam0); + } } void Cell::load(ESMReader &esm) @@ -71,7 +74,7 @@ void Cell::load(ESMReader &esm) esm.getHNT(mData, "DATA", 12); // Water level - mWater = 0; + mWater = -1; mNAM0 = 0; if (mData.mFlags & Interior) @@ -82,6 +85,7 @@ void Cell::load(ESMReader &esm) int waterl; esm.getHT(waterl); mWater = (float) waterl; + mWaterInt = true; } else if (esm.isNextSub("WHGT")) esm.getHT(mWater); @@ -114,11 +118,18 @@ void Cell::save(ESMWriter &esm) esm.writeHNT("DATA", mData, 12); if (mData.mFlags & Interior) { - if (mWater != 0) - esm.writeHNT("WHGT", mWater); + if (mWater != -1) { + if (mWaterInt) { + int water = + (mWater >= 0) ? (int) (mWater + 0.5) : (int) (mWater - 0.5); + esm.writeHNT("INTV", water); + } else { + esm.writeHNT("WHGT", mWater); + } + } if (mData.mFlags & QuasiEx) - esm.writeHNOString("RGNN", mRegion); + esm.writeHNOCString("RGNN", mRegion); else esm.writeHNT("AMBI", mAmbi, 16); } @@ -157,15 +168,6 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref) if (!esm.hasMoreSubs()) return false; - // Number of references in the cell? Maximum once in each cell, - // but not always at the beginning, and not always right. In other - // words, completely useless. - if (esm.isNextSub("NAM0")) - { - esm.skipHSubSize(4); - //esm.getHNOT(NAM0, "NAM0"); - } - esm.getHNT(ref.mRefnum, "FRMR"); ref.mRefID = esm.getHNString("NAME"); @@ -179,13 +181,13 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref) ref.mSoul = esm.getHNOString("XSOL"); ref.mFaction = esm.getHNOString("CNAM"); - ref.mFactIndex = -1; + ref.mFactIndex = -2; esm.getHNOT(ref.mFactIndex, "INDX"); ref.mCharge = -1.0; esm.getHNOT(ref.mCharge, "XCHG"); - ref.mIntv = 0; + ref.mIntv = -1; ref.mNam9 = 0; esm.getHNOT(ref.mIntv, "INTV"); esm.getHNOT(ref.mNam9, "NAM9"); @@ -201,18 +203,28 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref) } // Integer, despite the name suggesting otherwise - ref.mLockLevel = 0; + ref.mLockLevel = -1; esm.getHNOT(ref.mLockLevel, "FLTV"); ref.mKey = esm.getHNOString("KNAM"); ref.mTrap = esm.getHNOString("TNAM"); - ref.mUnam = 0; + ref.mUnam = -1; ref.mFltv = 0; esm.getHNOT(ref.mUnam, "UNAM"); esm.getHNOT(ref.mFltv, "FLTV"); esm.getHNT(ref.mPos, "DATA", 24); + // Number of references in the cell? Maximum once in each cell, + // but not always at the beginning, and not always right. In other + // words, completely useless. + ref.mNam0 = 0; + if (esm.isNextSub("NAM0")) + { + esm.getHT(ref.mNam0); + //esm.getHNOT(NAM0, "NAM0"); + } + return true; } diff --git a/components/esm/loadcell.hpp b/components/esm/loadcell.hpp index b22daeb03..b9d85cb9e 100644 --- a/components/esm/loadcell.hpp +++ b/components/esm/loadcell.hpp @@ -71,6 +71,7 @@ public: // Brindisi Dorom", where it has the value 100. Also only for // activators. int mFltv; + int mNam0; // Position and rotation of this object within the cell Position mPos; @@ -120,6 +121,7 @@ struct Cell : public Record DATAstruct mData; AMBIstruct mAmbi; float mWater; // Water level + bool mWaterInt; int mMapColor; int mNAM0; diff --git a/components/esm/loadinfo.cpp b/components/esm/loadinfo.cpp index 9fe3668be..b29c1dd94 100644 --- a/components/esm/loadinfo.cpp +++ b/components/esm/loadinfo.cpp @@ -136,17 +136,17 @@ void DialInfo::load(ESMReader &esm) void DialInfo::save(ESMWriter &esm) { - esm.writeHNString("INAM", mSelfId); - esm.writeHNString("PNAM", mPrev); - esm.writeHNString("NNAM", mNext); + esm.writeHNCString("INAM", mSelfId); + esm.writeHNCString("PNAM", mPrev); + esm.writeHNCString("NNAM", mNext); esm.writeHNT("DATA", mData, 12); - esm.writeHNOString("ONAM", mActor); - esm.writeHNOString("RNAM", mRace); - esm.writeHNOString("CNAM", mClass); - esm.writeHNOString("FNAM", mNpcFaction); - esm.writeHNOString("ANAM", mCell); - esm.writeHNOString("DNAM", mPcFaction); - esm.writeHNOString("SNAM", mSound); + esm.writeHNOCString("ONAM", mActor); + esm.writeHNOCString("RNAM", mRace); + esm.writeHNOCString("CNAM", mClass); + esm.writeHNOCString("FNAM", mNpcFaction); + esm.writeHNOCString("ANAM", mCell); + esm.writeHNOCString("DNAM", mPcFaction); + esm.writeHNOCString("SNAM", mSound); esm.writeHNOString("NAME", mResponse); for (std::vector::iterator it = mSelects.begin(); it != mSelects.end(); ++it) diff --git a/components/esm/loadingr.cpp b/components/esm/loadingr.cpp index 65d0a6259..13d66a632 100644 --- a/components/esm/loadingr.cpp +++ b/components/esm/loadingr.cpp @@ -13,7 +13,7 @@ void Ingredient::load(ESMReader &esm) esm.getHNT(mData, "IRDT", 56); mScript = esm.getHNOString("SCRI"); mIcon = esm.getHNOString("ITEX"); - +/* // horrible hack to fix broken data in records for (int i=0; i<4; ++i) { @@ -36,6 +36,7 @@ void Ingredient::load(ESMReader &esm) mData.mSkills[i] = -1; } } +*/ } void Ingredient::save(ESMWriter &esm) diff --git a/components/esm/loadland.cpp b/components/esm/loadland.cpp index 13c640972..fb7c94fcf 100644 --- a/components/esm/loadland.cpp +++ b/components/esm/loadland.cpp @@ -10,18 +10,61 @@ void Land::LandData::save(ESMWriter &esm) { // TODO: Make this actually work. - esm.writeHNT("VNML", mNormals, sizeof(VNML)); - esm.writeHNT("VHGT", mHeights, sizeof(VHGT)); + if (mDataTypes & Land::DATA_VNML) { + esm.writeHNT("VNML", mNormals, sizeof(VNML)); + } + + if (mDataTypes & Land::DATA_VHGT) { + VHGT offsets; + offsets.mHeightOffset = mHeights[0] / HEIGHT_SCALE; + offsets.mUnknown1 = mUnk1; + offsets.mUnknown2 = mUnk2; + + float prevY = mHeights[0], prevX; + int number = 0; // avoid multiplication + for (int i = 0; i < LAND_SIZE; ++i) { + float diff = (mHeights[number] - prevY) / HEIGHT_SCALE; + offsets.mHeightData[number] = + (diff >= 0) ? (int8_t) (diff + 0.5) : (int8_t) (diff - 0.5); + + prevX = prevY = mHeights[number]; + ++number; + + for (int j = 1; j < LAND_SIZE; ++j) { + diff = (mHeights[number] - prevX) / HEIGHT_SCALE; + offsets.mHeightData[number] = + (diff >= 0) ? (int8_t) (diff + 0.5) : (int8_t) (diff - 0.5); + + prevX = mHeights[number]; + ++number; + } + } + esm.writeHNT("VHGT", offsets, sizeof(VHGT)); + } //esm.writeHNT("WNAM", 0, 81); - esm.startSubRecord("WNAM"); +/* esm.startSubRecord("WNAM"); for (int i = 0; i < 81; i++) esm.writeT((char)0x80, 1); esm.endRecord("WNAM"); +*/ + if (mDataTypes & Land::DATA_WNAM) { + esm.writeHNT("WNAM", mWnam, 81); + } if (mDataTypes & Land::DATA_VCLR) esm.writeHNT("VCLR", mColours, 3*LAND_NUM_VERTS); - if (mDataTypes & Land::DATA_VTEX) - esm.writeHNT("VTEX", mTextures, 512); + if (mDataTypes & Land::DATA_VTEX) { + uint16_t vtex[256]; + + int readPos = 0; //bit ugly, but it works + for ( int y1 = 0; y1 < 4; y1++ ) + for ( int x1 = 0; x1 < 4; x1++ ) + for ( int y2 = 0; y2 < 4; y2++) + for ( int x2 = 0; x2 < 4; x2++ ) + vtex[(y1*4+y2)*16+(x1*4+x2)] = mTextures[readPos++]; + + esm.writeHNT("VTEX", vtex, 512); + } } Land::Land() @@ -87,7 +130,7 @@ void Land::load(ESMReader &esm) // We need all three of VNML, VHGT and VTEX in order to use the // landscape. (Though Morrowind seems to accept terrain without VTEX/VCLR entries) - mHasData = mDataTypes & (DATA_VNML|DATA_VHGT|DATA_WNAM); + mHasData = mDataTypes & (DATA_VNML|DATA_VHGT|DATA_WNAM|DATA_VTEX|DATA_VCLR); mDataLoaded = false; mLandData = NULL; @@ -130,32 +173,38 @@ void Land::loadData() memset(mLandData->mNormals, 0, LAND_NUM_VERTS * 3); - //esm.getHNExact(landData->normals, sizeof(VNML), "VNML"); + if (mEsm->isNextSub("VNML")) { + mEsm->getHExact(mLandData->mNormals, sizeof(VNML)); + }/* if (mEsm->isNextSub("VNML")) { mEsm->skipHSubSize(12675); - } + } */ + if (mEsm->isNextSub("VHGT")) { VHGT rawHeights; - mEsm->getHNExact(&rawHeights, sizeof(VHGT), "VHGT"); - int currentHeightOffset = rawHeights.mHeightOffset; + mEsm->getHExact(&rawHeights, sizeof(VHGT)); + float currentHeightOffset = rawHeights.mHeightOffset; for (int y = 0; y < LAND_SIZE; y++) { currentHeightOffset += rawHeights.mHeightData[y * LAND_SIZE]; mLandData->mHeights[y * LAND_SIZE] = currentHeightOffset * HEIGHT_SCALE; - int tempOffset = currentHeightOffset; + float tempOffset = currentHeightOffset; for (int x = 1; x < LAND_SIZE; x++) { tempOffset += rawHeights.mHeightData[y * LAND_SIZE + x]; mLandData->mHeights[x + y * LAND_SIZE] = tempOffset * HEIGHT_SCALE; } } + mLandData->mUnk1 = rawHeights.mUnknown1; + mLandData->mUnk2 = rawHeights.mUnknown2; + } if (mEsm->isNextSub("WNAM")) { - mEsm->skipHSubSize(81); + mEsm->getHExact(mLandData->mWnam, 81); } if (mEsm->isNextSub("VCLR")) { @@ -167,7 +216,7 @@ void Land::loadData() if (mEsm->isNextSub("VTEX")) { //TODO fix magic numbers - uint16_t vtex[512]; + uint16_t vtex[256]; mEsm->getHExact(&vtex, 512); int readPos = 0; //bit ugly, but it works @@ -181,7 +230,7 @@ void Land::loadData() else { mLandData->mUsingColours = false; - memset(&mLandData->mTextures, 0, 512 * sizeof(uint16_t)); + memset(mLandData->mTextures, 0, sizeof(mLandData->mTextures)); for (int i = 0; i < LAND_NUM_VERTS; i++) { mLandData->mHeights[i] = -256.0f * HEIGHT_SCALE; diff --git a/components/esm/loadland.hpp b/components/esm/loadland.hpp index 3575a79ce..f51ccc780 100644 --- a/components/esm/loadland.hpp +++ b/components/esm/loadland.hpp @@ -79,6 +79,10 @@ struct Land : public Record char mColours[3 * LAND_NUM_VERTS]; int mDataTypes; + uint8_t mWnam[81]; + short mUnk1; + uint8_t mUnk2; + void save(ESMWriter &esm); }; diff --git a/components/esm/loadmgef.cpp b/components/esm/loadmgef.cpp index 126556143..c18833e01 100644 --- a/components/esm/loadmgef.cpp +++ b/components/esm/loadmgef.cpp @@ -36,10 +36,10 @@ void MagicEffect::load(ESMReader &esm) esm.getHNT(mIndex, "INDX"); esm.getHNT(mData, "MEDT", 36); - +/* if (mIndex>=0 && mIndex