public static PhysicalObject Read(Reader reader, Pointer offset, SuperObject so = null, Radiosity radiosity = null) { PhysicalObject po = new PhysicalObject(offset, so); //MapLoader.Loader.print("PO @ " + offset); // Header po.off_visualSet = Pointer.Read(reader); po.off_collideSet = Pointer.Read(reader); po.off_visualBoundingVolume = Pointer.Read(reader); if (Settings.s.engineVersion > Settings.EngineVersion.TT && Settings.s.game != Settings.Game.LargoWinch) { if (Settings.s.engineVersion < Settings.EngineVersion.R3) { po.off_collideBoundingVolume = po.off_visualBoundingVolume; reader.ReadUInt32(); } else { po.off_collideBoundingVolume = Pointer.Read(reader); } } // Parse visual set Pointer.DoAt(ref reader, po.off_visualSet, () => { ushort numberOfLOD = 1; po.visualSetType = 0; if (Settings.s.game == Settings.Game.LargoWinch) { po.visualSet = new VisualSetLOD[1]; po.visualSet[0] = new VisualSetLOD(); po.visualSet[0].obj = null; po.visualSet[0].off_data = po.off_visualSet; po.visualSet[0].LODdistance = 5f; } else if (Settings.s.game == Settings.Game.R2Revolution) { po.visualSet = new VisualSetLOD[1]; po.visualSet[0] = new VisualSetLOD(); po.visualSet[0].obj = MapLoader.Loader.meshObjects.FirstOrDefault(p => p.offset == po.off_visualSet); po.visualSet[0].off_data = po.off_visualSet; po.visualSet[0].LODdistance = 5f; } else { if (Settings.s.platform != Settings.Platform.DC) { reader.ReadUInt32(); // 0 numberOfLOD = reader.ReadUInt16(); //if (numberOfLOD > 1) MapLoader.Loader.print("Found a PO with " + numberOfLOD + " levels of detail @ " + offset); po.visualSetType = reader.ReadUInt16(); if (numberOfLOD > 0) { Pointer off_LODDistances = Pointer.Read(reader); Pointer off_LODDataOffsets = Pointer.Read(reader); reader.ReadUInt32(); // always 0? RLI table offset if (Settings.s.engineVersion > Settings.EngineVersion.Montreal) { reader.ReadUInt32(); // always 0? number of RLI } po.visualSet = new VisualSetLOD[numberOfLOD]; for (uint i = 0; i < numberOfLOD; i++) { po.visualSet[i] = new VisualSetLOD(); } Pointer.DoAt(ref reader, off_LODDistances, () => { for (uint i = 0; i < numberOfLOD; i++) { // if distance > the float at this offset, game engine uses next LOD if there is one po.visualSet[i].LODdistance = reader.ReadSingle(); } }); Pointer.DoAt(ref reader, off_LODDataOffsets, () => { for (uint i = 0; i < numberOfLOD; i++) { po.visualSet[i].off_data = Pointer.Read(reader); } }); } } else { // Platform = Dreamcast Pointer.Read(reader); // Material pointer? Pointer off_data = Pointer.Read(reader); reader.ReadUInt32(); // always 0? reader.ReadUInt32(); // always 0? po.visualSet = new VisualSetLOD[1]; po.visualSet[0].off_data = off_data; po.visualSet[0].LODdistance = 5f; } } int radiosityLODIndex = 0; for (uint i = 0; i < numberOfLOD; i++) { Pointer.DoAt(ref reader, po.visualSet[i].off_data, () => { switch (po.visualSetType) { case 0: if (po.visualSet[i].obj == null) { po.visualSet[i].obj = GeometricObject.Read(reader, po.visualSet[i].off_data, radiosity: radiosity?.lod?[radiosityLODIndex++]); } break; case 1: if (po.visualSet[i].obj == null) { po.visualSet[i].obj = PatchGeometricObject.Read(reader, po, po.visualSet[i].off_data); } break; default: MapLoader.Loader.print("unknown type " + po.visualSetType + " at offset: " + offset); break; } }); } }); // Parse collide set Pointer.DoAt(ref reader, po.off_collideSet, () => { if (Settings.s.game == Settings.Game.R2Revolution) { // Read collide mesh object here directly po.collideMesh = GeometricObjectCollide.Read(reader, po.off_collideSet); } else { // Read collide set containing collide mesh uint u1 = reader.ReadUInt32(); // 0, zdm uint u2 = reader.ReadUInt32(); // 0, zdd uint u3 = reader.ReadUInt32(); // 0, zde Pointer off_zdr = Pointer.Read(reader); Pointer.DoAt(ref reader, off_zdr, () => { po.collideMesh = GeometricObjectCollide.Read(reader, off_zdr); }); } }); MapLoader.Loader.physicalObjects.Add(po); return(po); }
public static PhysicalObject Read(Reader reader, Pointer offset, SuperObject so = null) { PhysicalObject po = new PhysicalObject(offset, so); //MapLoader.Loader.print("PO @ " + offset); // Header po.off_visualSet = Pointer.Read(reader); po.off_collideSet = Pointer.Read(reader); po.off_visualBoundingVolume = Pointer.Read(reader); if (Settings.s.engineVersion > Settings.EngineVersion.TT && Settings.s.game != Settings.Game.LargoWinch) { if (Settings.s.engineVersion < Settings.EngineVersion.R3) { po.off_collideBoundingVolume = po.off_visualBoundingVolume; reader.ReadUInt32(); } else { po.off_collideBoundingVolume = Pointer.Read(reader); } } // Parse visual set Pointer.DoAt(ref reader, po.off_visualSet, () => { ushort numberOfLOD = 1; po.visualSetType = 0; if (Settings.s.game == Settings.Game.LargoWinch) { po.visualSet = new VisualSetLOD[1]; po.visualSet[0] = new VisualSetLOD(); po.visualSet[0].obj = null; po.visualSet[0].off_data = po.off_visualSet; po.visualSet[0].LODdistance = 5f; } else if (Settings.s.game == Settings.Game.R2Revolution) { po.visualSet = new VisualSetLOD[1]; po.visualSet[0] = new VisualSetLOD(); po.visualSet[0].obj = MapLoader.Loader.meshObjects.FirstOrDefault(p => p.offset == po.off_visualSet); po.visualSet[0].off_data = po.off_visualSet; po.visualSet[0].LODdistance = 5f; } else { if (Settings.s.platform != Settings.Platform.DC) { reader.ReadUInt32(); // 0 numberOfLOD = reader.ReadUInt16(); //if (numberOfLOD > 1) MapLoader.Loader.print("Found a PO with " + numberOfLOD + " levels of detail @ " + offset); po.visualSetType = reader.ReadUInt16(); if (numberOfLOD > 0) { Pointer off_LODDistances = Pointer.Read(reader); Pointer off_LODDataOffsets = Pointer.Read(reader); reader.ReadUInt32(); // always 0? RLI table offset if (Settings.s.engineVersion > Settings.EngineVersion.Montreal) { reader.ReadUInt32(); // always 0? number of RLI } po.visualSet = new VisualSetLOD[numberOfLOD]; for (uint i = 0; i < numberOfLOD; i++) { po.visualSet[i] = new VisualSetLOD(); } Pointer.DoAt(ref reader, off_LODDistances, () => { for (uint i = 0; i < numberOfLOD; i++) { // if distance > the float at this offset, game engine uses next LOD if there is one po.visualSet[i].LODdistance = reader.ReadSingle(); } }); Pointer.DoAt(ref reader, off_LODDataOffsets, () => { for (uint i = 0; i < numberOfLOD; i++) { po.visualSet[i].off_data = Pointer.Read(reader); } }); } } else { // Platform = Dreamcast Pointer.Read(reader); // Material pointer? Pointer off_data = Pointer.Read(reader); reader.ReadUInt32(); // always 0? reader.ReadUInt32(); // always 0? po.visualSet = new VisualSetLOD[1]; po.visualSet[0].off_data = off_data; po.visualSet[0].LODdistance = 5f; } } for (uint i = 0; i < numberOfLOD; i++) { Pointer.DoAt(ref reader, po.visualSet[i].off_data, () => { switch (po.visualSetType) { case 0: if (po.visualSet[i].obj == null) { po.visualSet[i].obj = GeometricObject.Read(reader, po.visualSet[i].off_data); } GeometricObject m = ((GeometricObject)po.visualSet[i].obj); if (m.name != "Mesh") { po.Gao.name = "[PO] " + m.name; } break; case 1: if (po.visualSet[i].obj == null) { po.visualSet[i].obj = MeshModificationObject.Read(reader, po, po.visualSet[i].off_data); } MeshModificationObject mod = po.visualSet[i].obj as MeshModificationObject; if (mod != null && mod.mesh != null && mod.mesh.name != "Mesh") { po.Gao.name = "[PO] " + mod.mesh.name; } break; default: MapLoader.Loader.print("unknown type " + po.visualSetType + " at offset: " + offset); break; } if (po.visualSet[i].obj.Gao != null) { po.visualSet[i].obj.Gao.transform.parent = po.Gao.transform; } }); } if (numberOfLOD > 1) { float bestLOD = po.visualSet.Min(v => v.LODdistance); foreach (VisualSetLOD lod in po.visualSet) { if (lod.obj.Gao != null && lod.LODdistance != bestLOD) { lod.obj.Gao.SetActive(false); } } } }); // Parse collide set Pointer.DoAt(ref reader, po.off_collideSet, () => { if (Settings.s.game == Settings.Game.R2Revolution) { // Read collide mesh object here directly po.collideMesh = GeometricObjectCollide.Read(reader, po.off_collideSet); po.collideMesh.gao.transform.parent = po.Gao.transform; } else { // Read collide set containing collide mesh uint u1 = reader.ReadUInt32(); // 0, zdm uint u2 = reader.ReadUInt32(); // 0, zdd uint u3 = reader.ReadUInt32(); // 0, zde Pointer off_zdr = Pointer.Read(reader); Pointer.DoAt(ref reader, off_zdr, () => { po.collideMesh = GeometricObjectCollide.Read(reader, off_zdr); po.collideMesh.gao.transform.parent = po.Gao.transform; }); } }); MapLoader.Loader.physicalObjects.Add(po); return(po); }
async Task LoadPS2() { await WaitIfNecessary(); textures = new TextureInfo[0]; loadingState = "Loading fixed memory"; await WaitIfNecessary(); files_array[Mem.Fix].GotoHeader(); Reader reader = files_array[Mem.Fix].reader; Pointer off_base_fix = Pointer.Current(reader); loadingState = "Loading input struct"; await WaitIfNecessary(); for (int i = 0; i < Settings.s.numEntryActions; i++) { Pointer.Read(reader); // 3DOS_EntryActions } inputStruct = InputStructure.Read(reader, Pointer.Current(reader)); foreach (EntryAction ea in inputStruct.entryActions) { print(ea.ToString()); } localization = FromOffsetOrRead <LocalizationStructure>(reader, Pointer.Current(reader), inline: true); /* * Pointer off_inputStructure = Pointer.Read(reader); * Pointer.DoAt(ref reader, off_inputStructure, () => { * inputStruct = InputStructure.Read(reader, off_inputStructure); * foreach (EntryAction ea in inputStruct.entryActions) { * print(ea.ToString()); * } * });*/ /*uint base_language = reader.ReadUInt32(); //Pointer off_language = Pointer.Read(reader); * reader.ReadUInt32(); * uint num_text_language = reader.ReadUInt32(); * reader.ReadUInt16(); * reader.ReadUInt16(); * reader.ReadUInt32(); // base * Pointer off_text_general = Pointer.Read(reader); * Pointer.DoAt(ref reader, off_text_general, () => { * fontStruct = FontStructure.Read(reader, off_text_general); * }); * Pointer off_inputStructure = Pointer.Read(reader); * Pointer.DoAt(ref reader, off_inputStructure, () => { * inputStruct = InputStructure.Read(reader, off_inputStructure); * foreach (EntryAction ea in inputStruct.entryActions) { * print(ea.ToString()); * } * }); * * await WaitIfNecessary(); * Pointer.Read(reader); * Pointer.Read(reader); * Pointer.Read(reader); * Pointer.Read(reader); * Pointer.Read(reader); * Pointer.Read(reader); * Pointer.Read(reader); * Pointer.Read(reader); * Pointer.Read(reader); * Pointer.Read(reader); * Pointer.Read(reader); * Pointer.Read(reader); * reader.ReadUInt32(); * reader.ReadUInt32(); * reader.ReadUInt32(); * reader.ReadUInt32(); * reader.ReadUInt32(); * reader.ReadUInt32(); * reader.ReadUInt32(); * reader.ReadUInt32(); * reader.ReadUInt32(); * reader.ReadUInt32(); * Pointer.Read(reader); * Pointer off_levelNames = Pointer.Read(reader); * Pointer off_languages = Pointer.Read(reader); * uint num_levelNames = reader.ReadUInt32(); * uint num_languages = reader.ReadUInt32(); * reader.ReadUInt32(); // same as num_levelNames * Pointer.DoAt(ref reader, off_levelNames, () => { * lvlNames = new string[num_levelNames]; * for (uint i = 0; i < num_levelNames; i++) { * lvlNames[i] = reader.ReadString(0x1E); * } * }); * Pointer.DoAt(ref reader, off_languages, () => { * ReadLanguages(reader, off_languages, num_languages); * }); * if (languages != null && fontStruct != null) { * for (int i = 0; i < num_languages; i++) { * loadingState = "Loading text files: " + (i+1) + "/" + num_languages; * string langFilePath = gameDataBinFolder + "TEXTS/" + languages[i].ToUpper() + ".LNG"; * await PrepareFile(langFilePath)); * files_array[2] = new DCDAT(languages[i], langFilePath, 2); * ((DCDAT)files_array[2]).SetHeaderOffset(base_language); * files_array[2].GotoHeader(); * fontStruct.ReadLanguageTableDreamcast(files_array[2].reader, i, (ushort)num_text_language); * files_array[2].Dispose(); * } * } * * loadingState = "Loading fixed textures"; * await WaitIfNecessary(); * Pointer off_events_fix = Pointer.Read(reader); * uint num_events_fix = reader.ReadUInt32(); * uint num_textures_fix = reader.ReadUInt32(); * Pointer off_textures_fix = Pointer.Read(reader); * Pointer.DoAt(ref reader, off_textures_fix, () => { * Array.Resize(ref textures, (int)num_textures_fix); * for (uint i = 0; i < num_textures_fix; i++) { * Pointer off_texture = Pointer.Read(reader); * textures[i] = null; * Pointer.DoAt(ref reader, off_texture, () => { * textures[i] = TextureInfo.Read(reader, off_texture); * }); * } * TEX tex = new TEX(tplPaths[0]); * for (uint i = 0; i < num_textures_fix; i++) { * if (textures[i] != null && tex.Count > i) { * textures[i].Texture = tex.textures[i]; * } * } * });*/ loadingState = "Loading level memory"; await WaitIfNecessary(); files_array[Mem.Lvl].GotoHeader(); reader = files_array[Mem.Lvl].reader; string build = reader.ReadString(0x20); reader.ReadUInt32(); reader.ReadUInt32(); // 0xc reader.ReadUInt32(); // 0 Pointer.Read(reader); Pointer.Read(reader); // Globals globals.off_actualWorld = Pointer.Read(reader); globals.off_dynamicWorld = Pointer.Read(reader); globals.off_fatherSector = Pointer.Read(reader); globals.num_always = reader.ReadUInt32(); globals.spawnablePersos = LinkedList <Perso> .ReadHeader(reader, Pointer.Current(reader), LinkedList.Type.Double); //globals.spawnablePersos.FillPointers(reader, globals.spawnablePersos.off_tail, globals.spawnablePersos.offset); Pointer.Read(reader); // format: (0x4 number, number * 0x4: null) globals.off_always_reusableSO = Pointer.Read(reader); // There are (num_always) empty SuperObjects starting with this one. Pointer.Read(reader); Pointer.Read(reader); Pointer.Read(reader); Pointer.Read(reader); Pointer.Read(reader); LinkedList <Perso> cameras = LinkedList <Perso> .ReadHeader(reader, Pointer.Current(reader), LinkedList.Type.Double); families = LinkedList <Family> .ReadHeader(reader, Pointer.Current(reader), type : LinkedList.Type.Double); LinkedList <Perso> mainChars = LinkedList <Perso> .ReadHeader(reader, Pointer.Current(reader), LinkedList.Type.Double); Pointer.Read(reader); // Rayman reader.ReadUInt32(); globals.off_camera = Pointer.Read(reader); // Camera Pointer.Read(reader); Pointer.Read(reader); Pointer.Read(reader); uint numMeshes = (uint)files_array[Mem.Lvl].extraData["numMeshes"]; uint numMaterials = (uint)files_array[Mem.Lvl].extraData["numMaterials"]; uint numTextures = (uint)files_array[Mem.Lvl].extraData["numTextures"]; uint numLightmappedObjects = (uint)files_array[Mem.Lvl].extraData["numLightmappedObjects"]; //print("numTextures " + numTextures + " - " + txds[0].Count + " - " + numMeshes + " - " + ato.numAtomics + " - " + numLightmappedObjects); textures = new TextureInfo[numTextures]; Pointer[] off_meshes = new Pointer[numMeshes]; off_materials = new Pointer[numMaterials]; for (int i = 0; i < numMeshes; i++) { off_meshes[i] = Pointer.Read(reader); } for (int i = 0; i < numMaterials; i++) { off_materials[i] = Pointer.Read(reader); } for (int i = 0; i < numTextures; i++) { Pointer off_textureInfo = Pointer.Read(reader); int texture_index = reader.ReadInt32(); Pointer.DoAt(ref reader, off_textureInfo, () => { textures[i] = TextureInfo.Read(reader, off_textureInfo); textures[i].Texture = txds[0].Lookup(texture_index.ToString("D3")); //textures[i].Texture = txds[0].textures[txds[0].Count - 1 - texture_index]; }); } Pointer.Read(reader); reader.ReadUInt32(); reader.ReadUInt32(); Pointer.Read(reader); uint num_unk = reader.ReadUInt32(); for (int i = 0; i < num_unk; i++) { Pointer.Read(reader); } uint num_unk2 = reader.ReadUInt32(); for (int i = 0; i < num_unk2; i++) { Pointer.Read(reader); } Pointer.Read(reader); reader.ReadSingle(); // a bounding volume most likely reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); Pointer.Read(reader); reader.ReadUInt32(); // 2? uint num_poTable = reader.ReadUInt32(); Pointer off_poTable = Pointer.Read(reader); reader.ReadUInt32(); // 1. 10x 0 reader.ReadUInt32(); // 2 reader.ReadUInt32(); // 3 reader.ReadUInt32(); // 4 reader.ReadUInt32(); // 5 reader.ReadUInt32(); // 6 reader.ReadUInt32(); // 7 reader.ReadUInt32(); // 8 reader.ReadUInt32(); // 9 reader.ReadUInt32(); // 10 uint num_lightCookies = reader.ReadUInt32(); lightCookieColors = new Color[num_lightCookies]; for (int i = 0; i < num_lightCookies; i++) { reader.ReadUInt32(); reader.ReadUInt32(); reader.ReadUInt32(); reader.ReadUInt32(); byte b = reader.ReadByte(); byte g = reader.ReadByte(); byte r = reader.ReadByte(); reader.ReadByte(); lightCookieColors[i] = new Color(r / 255f, g / 255f, b / 255f, 1f); reader.ReadUInt32(); reader.ReadInt32(); reader.ReadUInt32(); } for (int i = 0; i < num_lightCookies; i++) { reader.ReadByte(); } reader.Align(0x4); Pointer off_lightCookieMaterial = Pointer.Read(reader); lightCookieMaterial = VisualMaterial.FromOffsetOrRead(off_lightCookieMaterial, reader); off_lightmapUV = new Pointer[numLightmappedObjects]; for (int i = 0; i < numLightmappedObjects; i++) { reader.ReadUInt32(); reader.ReadUInt32(); reader.ReadUInt32(); off_lightmapUV[i] = Pointer.Read(reader); } for (int i = 0; i < numMaterials; i++) { VisualMaterial.FromOffsetOrRead(off_materials[i], reader); } for (int i = 0; i < numMeshes; i++) { Pointer.DoAt(ref reader, off_meshes[i], () => { GeometricObject mesh = GeometricObject.Read(reader, off_meshes[i]); meshObjects.Add(mesh); //print("Mesh " + i + ": " + mesh.num_vertices + " - " + mesh.subblock_types[0] + " - " + mesh.num_subblocks); }); } loadingState = "Loading families"; await WaitIfNecessary(); ReadFamilies(reader); //print("Families: " + families.Count); loadingState = "Loading superobject hierarchy"; await WaitIfNecessary(); ReadSuperObjects(reader); loadingState = "Loading always structure"; await WaitIfNecessary(); ReadAlways(reader); loadingState = "Filling in cross-references"; await WaitIfNecessary(); ReadCrossReferences(reader); await WaitIfNecessary(); }