From ba1d8902fcc5fbf25e1399368f7a307250f3592f Mon Sep 17 00:00:00 2001 From: Darryl Pogue Date: Sat, 4 Mar 2023 14:06:17 -0800 Subject: [PATCH] Add ResMgr option to preserve Object IDs After several attempts to address issues around Object ID mismatches, we've adopted a stance of libHSPlasma reassigning all Object IDs on read. This generally works okay (with caveats around cross-page references) but causes problems if you're wanting to round-trip data through libHSPlasma without modifying it. This adds a `preserveObjIDs` parameter to plResManager that tells it not to change object IDs when reading. This is **not safe** if you are adding or removing any objects from the PRP file, but should be safe if you're only wanting to edit some object data. This also sets up the `prcdc` tool to always dump out the original Object IDs to get an accurate view of the data. When running `prcc` to compile from PRC files, there's a new `--keep-ids` option to use the object ID values as read from the PRC. This enables us to round-trip through `prcdc/prcc` without renumbering all the data, which should help us to track down any PRC parsing issues. Co-Authored-By: Michael Hansen --- Tools/src/prcc.cpp | 13 ++++++++----- Tools/src/prcdc.cpp | 3 +-- core/PRP/KeyedObject/plUoid.cpp | 4 ++++ core/ResManager/plResManager.cpp | 23 +++++++++++++++-------- core/ResManager/plResManager.h | 5 +++-- 5 files changed, 31 insertions(+), 17 deletions(-) diff --git a/Tools/src/prcc.cpp b/Tools/src/prcc.cpp index 1c6b77b32..bb2646bc5 100644 --- a/Tools/src/prcc.cpp +++ b/Tools/src/prcc.cpp @@ -27,9 +27,10 @@ static void doHelp(const char* exename) ST::printf("Usage: {} infile [options]\n", exename); puts(""); puts("Options:"); - puts("\t-o file Write output to `file`"); - puts("\t-v ver Select output version (prime, pots, moul, eoa, hex, universal)"); - puts("\t--help Display this help and then exit"); + puts("\t-o file Write output to `file`"); + puts("\t-v ver Select output version (prime, pots, moul, eoa, hex, universal)"); + puts("\t--keep-ids Preserve the object IDs in the prc file"); + puts("\t--help Display this help and then exit"); puts(""); } @@ -37,6 +38,7 @@ int main(int argc, char* argv[]) { ST::string inputFile, outputFile; PlasmaVer outVer = PlasmaVer::pvUnknown; + bool keepIDs = false; if (argc == 1) { doHelp(argv[0]); @@ -64,6 +66,8 @@ int main(int argc, char* argv[]) ST::printf(stderr, "Error: unrecognized version: {}\n", ver); return 1; } + } else if (strcmp(argv[i], "--keep-ids") == 0) { + keepIDs = true; } else if (strcmp(argv[i], "-?") == 0 || strcmp(argv[i], "--help") == 0) { doHelp(argv[0]); return 0; @@ -82,8 +86,7 @@ int main(int argc, char* argv[]) } plDebug::Init(plDebug::kDLAll); - plResManager rm; - rm.setVer(outVer, true); + plResManager rm(outVer, keepIDs); hsFileStream S; if (!S.open(inputFile, fmRead)) { fputs("Error opening input file\n", stderr); diff --git a/Tools/src/prcdc.cpp b/Tools/src/prcdc.cpp index 34fde2ea8..fd9d781a3 100644 --- a/Tools/src/prcdc.cpp +++ b/Tools/src/prcdc.cpp @@ -127,8 +127,7 @@ int main(int argc, char* argv[]) } plDebug::Init(plDebug::kDLAll); - plResManager rm; - rm.setVer(inVer, true); + plResManager rm(inVer, true); hsFileStream out; out.open(outputFile, fmCreate); diff --git a/core/PRP/KeyedObject/plUoid.cpp b/core/PRP/KeyedObject/plUoid.cpp index 7d2e37f46..c0ef5b9ee 100644 --- a/core/PRP/KeyedObject/plUoid.cpp +++ b/core/PRP/KeyedObject/plUoid.cpp @@ -136,6 +136,10 @@ void plUoid::prcParse(const pfPrcTag* tag) loadMask.prcParse(tag); cloneID = tag->getParam("CloneID", "0").to_uint(); clonePlayerID = tag->getParam("ClonePlayerID", "0").to_uint(); + + unsigned int oid = tag->getParam("ObjID", "0").to_uint(); + if (oid != 0) + objID = oid; } ST::string plUoid::toString() const diff --git a/core/ResManager/plResManager.cpp b/core/ResManager/plResManager.cpp index 0f77dbf4e..8890d7794 100644 --- a/core/ResManager/plResManager.cpp +++ b/core/ResManager/plResManager.cpp @@ -243,7 +243,10 @@ void plResManager::WritePage(hsStream* S, plPageInfo* page) S->setVer(getVer()); std::vector types = keys.getTypes(page->getLocation()); page->setClassList(types); - //keys.sortKeys(page->getLocation()); + + if (preserveIDs) + keys.sortKeys(page->getLocation()); + page->write(S); page->setDataStart(S->pos()); page->setNumObjects(WriteObjects(S, page->getLocation())); @@ -510,7 +513,8 @@ unsigned int plResManager::ReadKeyring(hsStream* S, const plLocation& loc) keys.setFlags(loc, type, flags); } - keys.sortKeys(loc); + if (!preserveIDs) + keys.sortKeys(loc); return pageKeys; } @@ -638,13 +642,16 @@ unsigned int plResManager::WriteObjects(hsStream* S, const plLocation& loc) #endif for (unsigned int j=0; jsetFileOff(S->pos()); - unsigned int objID = j + 1; - if (kList[j]->getID() != objID) { - plDebug::Warning("Object ID changing ({} -> {}) during write: [{04X}]:{}", - kList[j]->getID(), objID, kList[j]->getType(), - kList[j]->getUoid().getName()); + if (!preserveIDs) { + unsigned int objID = j + 1; + if (kList[j]->getID() != objID) { + plDebug::Warning("Object ID changing ({} -> {}) during write: [{04X}]:{}", + kList[j]->getID(), objID, kList[j]->getType(), + kList[j]->getUoid().getName()); + } + kList[j]->setID(objID); } - kList[j]->setID(objID); + if (kList[j]->getObj()) { try { #ifdef RMTRACE diff --git a/core/ResManager/plResManager.h b/core/ResManager/plResManager.h index 9281e6498..87936828e 100644 --- a/core/ResManager/plResManager.h +++ b/core/ResManager/plResManager.h @@ -65,6 +65,7 @@ class HSPLASMA_EXPORT plResManager LoadProgressCallback progressFunc; PageUnloadCallback pageUnloadFunc; bool mustStub; + bool preserveIDs; private: unsigned int ReadKeyring(hsStream* S, const plLocation& loc); @@ -82,8 +83,8 @@ class HSPLASMA_EXPORT plResManager * ReadPage() or ReadAge() * \sa setVer(), getVer() */ - plResManager(PlasmaVer pv = PlasmaVer::pvUnknown) - : fPlasmaVer(PlasmaVer::pvUnknown), mustStub(false) + plResManager(PlasmaVer pv = PlasmaVer::pvUnknown, bool preserveObjIDs = false) + : fPlasmaVer(PlasmaVer::pvUnknown), mustStub(), preserveIDs(preserveObjIDs) { setVer(pv); }