#include "pch.h" #ifdef DREAMCAST #define _UNALIGNED __unaligned #else #define _UNALIGNED #endif ////////////////////////////////////////////////////////////////////////////// // // // ////////////////////////////////////////////////////////////////////////////// class MDLBinaryNameSpace : public INameSpace, public IBinaryReaderSite { private: ////////////////////////////////////////////////////////////////////////////// // // types // ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// // // data members // ////////////////////////////////////////////////////////////////////////////// ZString m_strName; TRef m_pmodeler; TRef m_pfile; BYTE* m_pdata; TVector > m_pnsImports; TVector m_strExportNames; TVector > m_pobjectImports; TVector > m_pobjects; ////////////////////////////////////////////////////////////////////////////// // // methods // ////////////////////////////////////////////////////////////////////////////// bool Error(const ZString& str) { ZError(str); return false; } DWORD ReadDWORD() { ZAssert(m_pdata); m_pdata += sizeof(DWORD); return *(_UNALIGNED DWORD*)(m_pdata - sizeof(DWORD)); } float ReadFloat() { ZAssert(m_pdata); m_pdata += sizeof(float); return *(_UNALIGNED float*)(m_pdata - sizeof(float)); } ZString ReadString() { ZAssert(m_pdata); // : this will cause an exception if the NameSpace is freed before // All of the objects that reference the string // // ZString str((PCC)m_pdata, true); ZString str((PCC)m_pdata); int length = str.GetLength() + 1; int paddedlength = (length + 3) & (~0x3); m_pdata += paddedlength; return str; } ////////////////////////////////////////////////////////////////////////////// // // // ////////////////////////////////////////////////////////////////////////////// TRef ReadList() { TRef plist = new IObjectList(); DWORD count = ReadDWORD(); for (DWORD index = 0; index < count; index++) { TRef pobject = ReadObject(); plist->PushEnd(pobject); } return plist; } ////////////////////////////////////////////////////////////////////////////// // // // ////////////////////////////////////////////////////////////////////////////// TRef ReadApply(ObjectStack& stack) { TRef pfunction; CastTo(pfunction, stack.Pop()); return pfunction->Apply(stack); } ////////////////////////////////////////////////////////////////////////////// // // // ////////////////////////////////////////////////////////////////////////////// TRef ReadBinary(ObjectStack& stack) { TRef pfunction; CastTo(pfunction, stack.Pop()); return pfunction->Read(this, stack); } ////////////////////////////////////////////////////////////////////////////// // // // ////////////////////////////////////////////////////////////////////////////// TRef ReadPair(ObjectStack& stack) { TRef pobject1 = stack.Pop(); TRef pobject2 = stack.Pop(); return new IObjectPair(pobject1, pobject2); } ////////////////////////////////////////////////////////////////////////////// // // // ////////////////////////////////////////////////////////////////////////////// TRef ReadObject() { ObjectStack stack; while (true) { DWORD token = GetDWORD(); switch (token) { case ObjectFloat: stack.Push(new Number(ReadFloat())); break; case ObjectString: stack.Push(new StringValue(ReadString())); break; case ObjectTrue: stack.Push(new Boolean(true)); break; case ObjectFalse: stack.Push(new Boolean(false)); break; case ObjectList: stack.Push(ReadList()); break; case ObjectApply: stack.Push(ReadApply(stack)); break; case ObjectBinary: stack.Push(ReadBinary(stack)); break; case ObjectReference: stack.Push(m_pobjects[ReadDWORD()]); break; case ObjectImport: stack.Push(m_pobjectImports[ReadDWORD()]); break; case ObjectPair: stack.Push(ReadPair(stack)); break; case ObjectEnd: ZAssert(stack.GetCount() == 1); return stack.Pop(); default: ZError("ReadObject: Bad token"); break; } }; } ////////////////////////////////////////////////////////////////////////////// // // // ////////////////////////////////////////////////////////////////////////////// bool ReadFile() { DWORD index; DWORD magic = ReadDWORD(); DWORD version = ReadDWORD(); DWORD countNameSpaces = ReadDWORD(); DWORD countImports = ReadDWORD(); DWORD countExports = ReadDWORD(); DWORD countDefinitions = ReadDWORD(); if (magic != MDLMagic) { return Error("Invalid file type"); } if (version != MDLVersion) { return Error("Invalid version number"); } // // Imported NameSpaces // m_pnsImports.SetCount(countNameSpaces); for(index = 0; index < countNameSpaces; index++) { ZString str = ReadString(); TRef pns = m_pmodeler->GetNameSpace(str); ZAssert(pns != NULL); m_pnsImports.Set(index, pns); } // // Imports // m_pobjectImports.SetCount(countImports); for(index = 0; index < countImports; index++) { DWORD indexLibrary = ReadDWORD(); ZString str = ReadString(); ZAssert(indexLibrary < countNameSpaces); TRef pobject = m_pnsImports[indexLibrary]->FindMemberLocal(str); ZAssert(pobject != NULL); m_pobjectImports.Set(index, pobject); } // // Exports // m_pobjects.SetCount(countExports + countDefinitions); m_strExportNames.SetCount(countExports); for(index = 0; index < countExports; index++) { m_strExportNames.Set(index, ReadString()); } // // Definitions // for(index = 0; index < countExports + countDefinitions; index++) { DWORD indexObject = ReadDWORD(); m_pobjects.Set(indexObject, ReadObject()); } // // Set the namespace info's on any values // // !!! this is a total hack, only do this on Debug builds since it // requires dynamic casting. MDLC is always built debug so it's // ok. // #if defined(_DEBUG) && !defined(DREAMCAST) for(index = 0; index < countExports; index++) { Value* pvalue = dynamic_cast((IObject*)m_pobjects[index]); if (pvalue != NULL) { pvalue->SetNameSpaceInfo(CreateNameSpaceInfo(this, m_strExportNames[index])); } } #endif return true; } public: MDLBinaryNameSpace(const ZString& strName, Modeler* pmodeler, ZFile* pfile) : m_pmodeler(pmodeler), m_strName(strName) { m_pfile = pfile; m_pdata = pfile->GetPointer(false, false); ReadFile(); m_pdata = NULL; pfile = NULL; } ////////////////////////////////////////////////////////////////////////////// // // INameSpace members // ////////////////////////////////////////////////////////////////////////////// const ZString& GetName() { return m_strName; } void AddMember(const ZString& strName, IObject* pobject) { ZUnimplemented(); } IObject* FindMemberAndNameSpace(const ZString& strName, INameSpace*& pns) { IObject* pobject = FindMemberLocal(strName); if (pobject != NULL) { pns = this; return pobject; } int count = m_pnsImports.GetCount(); for(int index = 0; index < count; index++) { pobject = m_pnsImports[index]->FindMemberAndNameSpace(strName, pns); if (pobject != NULL) { return pobject; } } return NULL; } IObject* FindMember(const ZString& strName) { INameSpace* pns; return FindMemberAndNameSpace(strName, pns); } IObject* FindMemberLocal(const ZString& strName) { int count = m_strExportNames.GetCount(); for(int index = 0; index < count; index++) { if (m_strExportNames[index] == strName) { return m_pobjects[index]; } } return NULL; } void AddType(const ZString& strName, MDLType* ptype) { ZUnimplemented(); } MDLType* FindType(const ZString& strName) { ZUnimplemented(); return NULL; } MDLType* FindTypeLocal(const ZString& strName) { ZUnimplemented(); return NULL; } void WriteTypeHeader(ZFile* pfile) { ZUnimplemented(); } void WriteToTextFile(int indent, ZFile* pfile) { ZUnimplemented(); } void WriteToBinaryFile(ZFile* pfile) { ZUnimplemented(); } ////////////////////////////////////////////////////////////////////////////// // // IBinaryReaderSite methods // ////////////////////////////////////////////////////////////////////////////// ZString GetString() { return ReadString(); } DWORD GetDWORD() { return ReadDWORD(); } BYTE* GetPointer() { ZAssert(m_pdata); return m_pdata; } void MovePointer(int count) { ZAssert(m_pdata); m_pdata += count; } IObject* GetMemoryObject() { ZAssert(m_pfile); return m_pfile; } IObject* GetObject() { return m_pobjects[ReadDWORD()]; } }; TRef CreateBinaryNameSpace(const ZString& strName, Modeler* pmodeler, ZFile* pfile) { return new MDLBinaryNameSpace(strName, pmodeler, pfile); }