Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ObjectDir work, also we (or more like Nathan) matched PopRev! #243

Merged
merged 7 commits into from
Jun 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
256 changes: 230 additions & 26 deletions src/system/obj/Dir.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
#include "obj/Dir.h"
#include "obj/Object.h"
#include "obj/ObjVersion.h"

#include "decomp.h"
#include "utl/Messages.h"
#include "utl/Symbols.h"

const char* kNotObjectMsg = "Could not find %s in dir \"%s\"";

namespace {
int gPreloadIdx = 0;
ObjDirPtr<ObjectDir> gPreloaded[128];

void DeleteShared(){

}
}

INIT_REVS(ObjectDir);

BinStream& operator>>(BinStream& bs, InlineDirType& ty){
Expand Down Expand Up @@ -33,8 +43,22 @@ void ObjectDir::SetSubDir(bool b){
}
}

bool ObjectDir::IsProxy() const {
return this != mDir;
bool ObjectDir::HasSubDir(ObjectDir* dir){
ObjectDir* subdir;
int i = 0;
do {
subdir = NextSubDir(i);
if(!subdir) return false;
} while(subdir != dir);
return true;
}

bool ObjectDir::SaveSubdirs(){
bool ret = false;
if(!IsProxy() || mProxyFile.empty() || gLoadingProxyFromDisk){
ret = true;
}
return ret;
}

SAVE_OBJ(ObjectDir, 0x1A2)
Expand Down Expand Up @@ -181,33 +205,99 @@ bool ObjectDir::AllowsInlineProxy(){
#pragma push
#pragma dont_inline on
void ObjectDir::PostLoad(BinStream& bs){
for(int i = mInlinedDirs.size(); i >= 0; i--){
ObjDirPtr<ObjectDir>& ptr = mInlinedDirs[i].dir;
ptr.IsLoaded();
ptr->Dir();
ptr.GetFile();
ptr.PostLoad(0);
ptr = ObjDirPtr<ObjectDir>();
int revs = PopRev(this);
gRev = getHmxRev(revs);
gAltRev = getAltRev(revs);
for(int i = mInlinedDirs.size() - 1; i >= 0; i--){
InlinedDir& iDir = mInlinedDirs[i];
int tempgRev = gRev;
iDir.dir.PostLoad(mLoader);
gRev = tempgRev;
if(iDir.inlineDirType == (InlineDirType)3){
iDir.shared = true;
}
if(iDir.shared){
FilePath& fp = iDir.file;
DirLoader* last = DirLoader::FindLast(fp);
if(last){
if(last->IsLoaded()){
iDir.dir = last->GetDir();
}
else {
MILO_WARN("Can't share unloaded dir %s", fp);
}
}
}
else {
if(iDir.dir.IsLoaded()){
delete iDir.dir->mLoader;
iDir.dir->mLoader = 0;
}
}
}
}
#pragma pop

extern std::vector<ObjVersion> sRevStack;

int PopRev(Hmx::Object* o){
while(sRevStack.back().obj != 0){
sRevStack.pop_back();
if(gRev > 0x17){
int revs2 = bs.Cached() ? 0 : PopRev(this);
int offset = PopRev(this);
MILO_ASSERT(( 0) <= (offset) && (offset) <= ( mSubDirs.size()), 0x466);
if(revs2 != 2){
for(int i = mSubDirs.size() - offset - 1; i >= 0; i--){
bool bbb = false;
if(revs2 == 1){
bbb = PopRev(this) != 0;
}
ObjDirPtr<ObjectDir> inlinedDirPtr = PostLoadInlined();
ObjDirPtr<ObjectDir>& curDirPtr = mSubDirs[i + offset];
if(revs2 == 0 || bbb){
curDirPtr = inlinedDirPtr;
}
AddedSubDir(curDirPtr);
}
for(offset = offset - 1; offset >= 0; offset--){
ObjDirPtr<ObjectDir>& offsetPtr = mSubDirs[offset];
offsetPtr.PostLoad(mLoader);
AddedSubDir(offsetPtr);
}
}
}
else {
for(int i = 0; i < mSubDirs.size(); i++){
ObjDirPtr<ObjectDir>& curDirPtr = mSubDirs[i];
curDirPtr.PostLoad(mLoader);
AddedSubDir(curDirPtr);
if(curDirPtr.IsLoaded()){
if(curDirPtr->InlineSubDirType() != kInlineNever){
delete curDirPtr->mLoader;
curDirPtr->mLoader = 0;
}
}
}
}
ObjVersion& back = sRevStack.back();
if(o != back.obj){
TheDebug << MakeString("rev stack $this mismatch (%08x != %08x\n", o, &back.obj);
TheDebug << MakeString("curr obj: %s %s\n", o->ClassName(), PathName(o));
TheDebug << MakeString("stack obj: %s %s\n", back.obj->ClassName(), PathName(back.obj));
TheDebug << MakeString("rev stack (%08x %s %s != %08x %s %s)\n", o, o->ClassName(), PathName(o), &back.obj, back.obj->ClassName(), PathName(back.obj));
if(gRev > 10){
char buf[0x80];
bs.ReadString(buf, 0x80);
bs.ReadString(buf, 0x80);
mCurCam = FindObject(buf, true);
}
if(gRev > 0x15) LoadRest(bs);
else if(gRev > 0x10) Hmx::Object::Load(bs);
HandleType(change_proxies_msg);
if(mProxyOverride){
bool overridden = false;
mProxyOverride = false;
if(TheLoadMgr.EditMode() || (IsProxy() && !AllowsInlineProxy())){
overridden = true;
}
if(!overridden) MILO_FAIL("You cannot override an inlined proxy!");
}
else {
if(IsProxy() && !mProxyFile.empty()){
DeleteObjects();
DeleteSubDirs();
DirLoader* dl = new DirLoader(mProxyFile, kLoadFront, 0, InlineProxy(bs) ? &bs : 0, this, false);
}
}
sRevStack.pop_back();
return back.revs;
}
#pragma pop

void ObjectDir::TransferLoaderState(ObjectDir* otherDir){
mProxyFile = otherDir->mProxyFile;
Expand All @@ -233,6 +323,52 @@ void ObjectDir::SetProxyFile(const FilePath& fp, bool b){
}
}

BEGIN_COPYS(ObjectDir)
COPY_SUPERCLASS(Hmx::Object)
if(ty != kCopyFromMax){
CREATE_COPY(ObjectDir)
BEGIN_COPYING_MEMBERS
if(this == Dir()){
for(int i = 0; i < mSubDirs.size(); i++){
RemovingSubDir(mSubDirs[i]);
}
COPY_MEMBER(mSubDirs)
for(int i = 0; i < mSubDirs.size(); i++){
AddedSubDir(mSubDirs[i]);
}
}
COPY_MEMBER(mInlineProxy)
COPY_MEMBER(mInlineSubDirType)
END_COPYING_MEMBERS
}
END_COPYS

Hmx::Object* ObjectDir::FindObject(const char* name, bool parentDirs){
Entry* entry = FindEntry(name, false);
if(entry && entry->obj) return entry->obj;
for(int i = 0; i < mSubDirs.size(); i++){
if(mSubDirs[i]){
Hmx::Object* found = mSubDirs[i]->FindObject(name, false);
if(found) return found;
}
}
if(strlen(name) != 0){
if(strcmp(name, Name()) == 0){
return this;
}
}
if(parentDirs){
ObjectDir* thisDir = Dir();
if(thisDir && thisDir != this){
return thisDir->FindObject(name, parentDirs);
}
if(this != sMainDir){
return sMainDir->FindObject(name, false);
}
}
return 0;
}

void ObjectDir::RemovingObject(Hmx::Object* obj){
if(obj != mCurCam) return;
else mCurCam = 0;
Expand All @@ -246,6 +382,74 @@ bool ObjectDir::InlineProxy(BinStream& bs){
return ret;
}

#pragma push
#pragma dont_inline on
// the KeylessHash methods should NOT be inlined, but the Entry ctor should
ObjectDir::Entry* ObjectDir::FindEntry(const char* name, bool add){
if(name == 0 || *name == '\0') return 0;
else {
Entry* entry = mHashTable.Find(name);
if(!entry && add){
Entry newEntry;
newEntry.name = SymbolCacheLookup(name);
if(!newEntry.name){
mStringTable.Add(newEntry.name);
}
entry = mHashTable.Insert(newEntry);
}
return entry;
}
}
#pragma pop

ObjectDir* ObjectDir::NextSubDir(int& which){
MILO_ASSERT(which >= 0, 0x695);
ObjectDir* ret = this;
if(which == 0) return ret;
else {
which--;
ret = 0;
for(int i = 0; i < mSubDirs.size(); i++){
if(mSubDirs[i]){
ret = mSubDirs[i]->NextSubDir(which);
if(ret) break;
}
}
}
return ret;
}

bool ObjectDir::HasDirPtrs() const {
std::vector<ObjRef*>::const_reverse_iterator rit = Refs().rbegin();
std::vector<ObjRef*>::const_reverse_iterator ritEnd = Refs().rend();
for(; rit != ritEnd; ++rit){
if((*rit)->IsDirPtr()) return true;
}
return false;
}

BEGIN_HANDLERS(ObjectDir)
HANDLE_ACTION(iterate, Iterate(_msg, true))
HANDLE_ACTION(iterate_self, Iterate(_msg, false))
HANDLE_ACTION(save_objects, DirLoader::SaveObjects(_msg->Str(2), this))
HANDLE(find, OnFind)
HANDLE_EXPR(exists, FindObject(_msg->Str(2), false) != 0)
HANDLE_ACTION(sync_objects, SyncObjects())
HANDLE_EXPR(is_proxy, Dir() != this)
HANDLE_EXPR(proxy_dir, mLoader ? mLoader->mProxyDir : (Hmx::Object*)0)
HANDLE_EXPR(proxy_name, mLoader ? (mLoader->mProxyName ? mLoader->mProxyName : "") : "")
END_HANDLERS

DataNode ObjectDir::OnFind(DataArray* da){
Hmx::Object* found = FindObject(da->Str(2), false);
if(da->Size() > 3){
if(da->Int(3) != 0 && !found){
MILO_FAIL("Couldn't find %s in %s", da->Str(2), Name());
}
}
return DataNode(found);
}

#pragma push
#pragma dont_inline on
// Here to test KeylessHash
Expand Down
40 changes: 25 additions & 15 deletions src/system/obj/Dir.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ template <class T> class ObjDirPtr : public ObjRef {
// }
}

operator bool() const { return mDir != 0; }

T* mDir;
class DirLoader* mLoader;
};
Expand All @@ -121,17 +123,18 @@ class ObjectDir : public virtual Hmx::Object {
obj = entry.obj;
return *this;
}
operator const char*(){ return name; } // may not need this

const char* name;
Hmx::Object* obj;
};

struct InlinedDir {
// Note: names are fabricated, no DWARF info
ObjDirPtr<ObjectDir> dir;
FilePath file;
bool shared;
InlineDirType inlineDirType;
ObjDirPtr<ObjectDir> dir; // 0x0
FilePath file; // 0xc
bool shared; // 0x18
InlineDirType inlineDirType; // 0x1c
};

class Viewport {
Expand Down Expand Up @@ -169,7 +172,7 @@ class ObjectDir : public virtual Hmx::Object {
virtual void OldLoadProxies(BinStream&, int);

void Reserve(int, int);
bool IsProxy() const;
bool IsProxy() const { return this != mDir; }
bool HasSubDir(ObjectDir*);
bool HasDirPtrs() const;
Entry* FindEntry(const char*, bool);
Expand All @@ -179,6 +182,13 @@ class ObjectDir : public virtual Hmx::Object {
void DeleteObjects();
void DeleteSubDirs();
bool InlineProxy(BinStream&);
void AddedSubDir(ObjDirPtr<ObjectDir>&);
void RemovingSubDir(ObjDirPtr<ObjectDir>&);
ObjDirPtr<ObjectDir> PostLoadInlined();
ObjectDir* NextSubDir(int&);
void Iterate(DataArray*, bool);

DataNode OnFind(DataArray*);

Hmx::Object* FindObject(const char*, bool);
template <class T> T* Find(const char* name, bool b) {
Expand All @@ -187,19 +197,19 @@ class ObjectDir : public virtual Hmx::Object {

DECLARE_REVS;

KeylessHash<const char*, Entry> mHashTable;
StringTable mStringTable;
FilePath mProxyFile;
bool mProxyOverride;
KeylessHash<const char*, Entry> mHashTable; // 0x8
StringTable mStringTable; // 0x28
FilePath mProxyFile; // 0x38
bool mProxyOverride; // 0x44
bool mInlineProxy; // 0x45
DirLoader* mLoader;
DirLoader* mLoader; // 0x48
std::vector<ObjDirPtr<ObjectDir> > mSubDirs; // 0x4c
bool mIsSubDir;
InlineDirType mInlineSubDirType;
bool mIsSubDir; // 0x54
InlineDirType mInlineSubDirType; // 0x58
const char* mPathName; // 0x5c
FilePath mStoredFile;
std::vector<InlinedDir> mInlinedDirs;
Hmx::Object* mCurCam;
FilePath mStoredFile; // 0x60
std::vector<InlinedDir> mInlinedDirs; // 0x6c
Hmx::Object* mCurCam; // 0x74
int mAlwaysInlined; // appears to be a word? - 0x78
const char* mAlwaysInlineHash;
};
Expand Down
2 changes: 1 addition & 1 deletion src/system/obj/DirLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class DirLoader : public Loader, public ObjRef {

void Cleanup(const char*);
class ObjectDir* GetDir();
bool SaveObjects(const char*, class ObjectDir*);
static bool SaveObjects(const char*, class ObjectDir*);
Symbol FixClassName(Symbol);
bool SetupDir(Symbol);

Expand Down
Loading
Loading