public void ConvertScene(bool ConsecutiveRoomInject, bool ForceRGBATextures) { /* Check if collision model is valid */ if (ColModel == null) { throw new Exception("No collision model defined"); } /* Process rooms... */ for (int i = 0; i < _Rooms.Count; i++) { /* Get current room from list */ ZRoom Room = _Rooms[i]; /* Create new room file, DList offset list and texture list */ Room.RoomData = new List <byte>(); Room.DLists = new List <NDisplayList>(); Textures = new List <NTexture>(); /* Create room header */ WriteRoomHeader(Room); /* Write objects */ if (Room.ZObjects.Count != 0) { ObjectOffset = Room.RoomData.Count; foreach (ZUShort Obj in Room.ZObjects) { Helpers.Append16(ref Room.RoomData, Obj.Value); } AddPadding(ref Room.RoomData, 8); } /* Write actors */ if (Room.ZActors.Count != 0) { ActorOffset = Room.RoomData.Count; foreach (ZActor Actor in Room.ZActors) { Helpers.Append16(ref Room.RoomData, Actor.Number); Helpers.Append16(ref Room.RoomData, (ushort)Actor.XPos); Helpers.Append16(ref Room.RoomData, (ushort)Actor.YPos); Helpers.Append16(ref Room.RoomData, (ushort)Actor.ZPos); Helpers.Append16(ref Room.RoomData, (ushort)Actor.XRot); Helpers.Append16(ref Room.RoomData, (ushort)Actor.YRot); Helpers.Append16(ref Room.RoomData, (ushort)Actor.ZRot); Helpers.Append16(ref Room.RoomData, Actor.Variable); } AddPadding(ref Room.RoomData, 8); } /* Prepare dummy mesh header */ MeshHeaderOffset = Room.MeshHeaderOffset = Room.RoomData.Count; Helpers.Append32(ref Room.RoomData, 0); /* Mesh type X, Y meshes */ Helpers.Append32(ref Room.RoomData, 0); /* Start address */ Helpers.Append32(ref Room.RoomData, 0); /* End address */ for (int j = 0; j < Room.ObjModel.Groups.Count; j++) { Helpers.Append64(ref Room.RoomData, 0); Helpers.Append32(ref Room.RoomData, 0); /* Display List offset 1 */ Helpers.Append32(ref Room.RoomData, 0); /* Display List offset 2 */ } AddPadding(ref Room.RoomData, 8); /* Create textures */ for (int M = 0; M < Room.ObjModel.Materials.Count; M++) { /* Get material & force RGBA default */ ObjFile.Material Mat = Room.ObjModel.Materials[M]; Mat.ForceRGBA = ForceRGBATextures; /* ---VERY kludgy RGBA forcing code--- */ for (int x = 0; x < Room.ObjModel.Groups.Count; x++) { /* If group has multitex material number... */ if (Room.ObjModel.Groups[x].MultiTexMaterial != -1) { /* Turn force RGBA ON for multitex material */ Room.ObjModel.Materials[Room.ObjModel.Groups[x].MultiTexMaterial].ForceRGBA = true; /* Scan group's triangles for current material name... */ for (int y = 0; y < Room.ObjModel.Groups[x].Triangles.Count; y++) { if (Room.ObjModel.Groups[x].Triangles[y].MaterialName == Mat.Name) { /* Turn force RGBA ON for current material */ Mat.ForceRGBA = true; goto Cont; } } } } /* Continue here... */ Cont: if (Mat.TexImage == null) { continue; } /* Create new texture, convert current material */ NTexture Texture = new NTexture(); Texture.Convert(Mat); /* Add current offset to texture offset list */ Texture.TexOffset = ((uint)Room.RoomData.Count); /* Write converted data to room file */ Room.RoomData.AddRange(Texture.Data); /* See if we've got a CI-format texture... */ int Format = ((Texture.Type & 0xE0) >> 5); #if DEBUG Console.WriteLine("Texture format N64: " + Format.ToString("X2")); #endif if (Format == GBI.G_IM_FMT_CI) { /* If it's CI, add current offset to palette offset list */ Texture.PalOffset = ((uint)Room.RoomData.Count); /* Write palette data to room file */ Room.RoomData.AddRange(Texture.Palette); } else { /* Add dummy entry to palette offset list */ Texture.PalOffset = Dummy; } Textures.Add(Texture); } /* Create Display Lists */ for (int j = 0; j < Room.ObjModel.Groups.Count; j++) { NDisplayList DList = new NDisplayList(Scale, Room.ObjModel.Groups[j].TintAlpha, 1.0f, IsOutdoors, Room.ObjModel.Groups[j].BackfaceCulling); DList.Convert(Room.ObjModel, j, Textures, (uint)Room.RoomData.Count); if (DList.Data != null) { Room.RoomData.AddRange(DList.Data); } Room.DLists.Add(DList); } /* Fix room header and add missing data */ FixRoomHeader(Room); /* Add some padding for good measure */ AddPadding(ref Room.RoomData, 0x1000); /* Store room data length */ Room.FullDataLength = Room.RoomData.ToArray().Length; /* Put modified room info back into list */ _Rooms[i] = Room; } /* Create new scene file */ SceneData = new List <byte>(); /* Write scene header */ Helpers.Append64(ref SceneData, (ulong)(0x1502000000000000 | Music)); /* Sound settings */ CmdMapListOffset = SceneData.Count; Helpers.Append64(ref SceneData, 0x0400000000000000); /* Map list */ CmdTransitionsOffset = SceneData.Count; Helpers.Append64(ref SceneData, 0x0E00000000000000); /* Transition list */ Helpers.Append64(ref SceneData, 0x1900000000000003); /* Cutscenes */ CmdCollisionOffset = SceneData.Count; Helpers.Append64(ref SceneData, 0x0300000000000000); /* Collision header */ CmdEntranceListOffset = SceneData.Count; Helpers.Append64(ref SceneData, 0x0600000000000000); /* Entrance index */ if (IsOutdoors == true) /* Special objects */ { Helpers.Append64(ref SceneData, 0x0701000000000002); } else { Helpers.Append64(ref SceneData, 0x0702000000000003); } CmdSpawnPointOffset = SceneData.Count; Helpers.Append64(ref SceneData, 0x0000000000000000); /* Spawn point list */ if (IsOutdoors == true) /* Skybox / lighting settings */ { Helpers.Append64(ref SceneData, 0x1100000001000000); } else { Helpers.Append64(ref SceneData, 0x1100000000000100); } CmdExitListOffset = SceneData.Count; Helpers.Append64(ref SceneData, 0x1300000000000000); /* Exit list */ CmdEnvironmentsOffset = SceneData.Count; Helpers.Append64(ref SceneData, 0x0F00000000000000); /* Environments */ Helpers.Append64(ref SceneData, 0x1400000000000000); /* End marker */ /* Fix scene header; map list ... */ Helpers.Overwrite32(ref SceneData, CmdMapListOffset, (uint)(0x04000000 | (_Rooms.Count << 16))); Helpers.Overwrite32(ref SceneData, CmdMapListOffset + 4, (uint)(0x02000000 | SceneData.Count)); if (ConsecutiveRoomInject == true) { int RoomInjectOffset = _Rooms[0].InjectOffset; foreach (ZRoom Room in _Rooms) { Helpers.Append32(ref SceneData, (uint)RoomInjectOffset); Helpers.Append32(ref SceneData, (uint)(RoomInjectOffset + Room.FullDataLength)); RoomInjectOffset += Room.FullDataLength; } } else { foreach (ZRoom Room in _Rooms) { Helpers.Append32(ref SceneData, (uint)Room.InjectOffset); Helpers.Append32(ref SceneData, (uint)(Room.InjectOffset + Room.FullDataLength)); } } AddPadding(ref SceneData, 8); /* ... transition list ... */ Helpers.Overwrite32(ref SceneData, CmdTransitionsOffset, (uint)(0x0E000000 | (Transitions.Count << 16))); Helpers.Overwrite32(ref SceneData, CmdTransitionsOffset + 4, (uint)(0x02000000 | SceneData.Count)); foreach (ZActor Trans in Transitions) { SceneData.Add(Trans.FrontSwitchTo); SceneData.Add(Trans.FrontCamera); SceneData.Add(Trans.BackSwitchTo); SceneData.Add(Trans.BackCamera); Helpers.Append16(ref SceneData, Trans.Number); Helpers.Append16(ref SceneData, (ushort)Trans.XPos); Helpers.Append16(ref SceneData, (ushort)Trans.YPos); Helpers.Append16(ref SceneData, (ushort)Trans.ZPos); Helpers.Append16(ref SceneData, (ushort)Trans.YRot); Helpers.Append16(ref SceneData, Trans.Variable); } AddPadding(ref SceneData, 8); /* ... exit list ... */ Helpers.Overwrite32(ref SceneData, CmdExitListOffset + 4, (uint)(0x02000000 | SceneData.Count)); foreach (ZUShort Exit in ExitList) { Helpers.Append16(ref SceneData, Exit.Value); } AddPadding(ref SceneData, 8); /* ... spawn point list ... */ Helpers.Overwrite32(ref SceneData, CmdSpawnPointOffset, (uint)(0x00000000 | (SpawnPoints.Count << 16))); Helpers.Overwrite32(ref SceneData, CmdSpawnPointOffset + 4, (uint)(0x02000000 | SceneData.Count)); foreach (ZActor Spawn in SpawnPoints) { Helpers.Append16(ref SceneData, Spawn.Number); Helpers.Append16(ref SceneData, (ushort)Spawn.XPos); Helpers.Append16(ref SceneData, (ushort)Spawn.YPos); Helpers.Append16(ref SceneData, (ushort)Spawn.ZPos); Helpers.Append16(ref SceneData, (ushort)Spawn.XRot); Helpers.Append16(ref SceneData, (ushort)Spawn.YRot); Helpers.Append16(ref SceneData, (ushort)Spawn.ZRot); Helpers.Append16(ref SceneData, Spawn.Variable); } AddPadding(ref SceneData, 8); /* ... environments ... */ Helpers.Overwrite32(ref SceneData, CmdEnvironmentsOffset, (uint)(0x0F000000 | (Environments.Count << 16))); Helpers.Overwrite32(ref SceneData, CmdEnvironmentsOffset + 4, (uint)(0x02000000 | SceneData.Count)); foreach (ZEnvironment Env in Environments) { Helpers.Append48(ref SceneData, (ulong)(Env.C1C.ToArgb() & 0xFFFFFF)); Helpers.Append48(ref SceneData, (ulong)(Env.C2C.ToArgb() & 0xFFFFFF)); Helpers.Append48(ref SceneData, (ulong)(Env.C3C.ToArgb() & 0xFFFFFF)); Helpers.Append48(ref SceneData, (ulong)(Env.C4C.ToArgb() & 0xFFFFFF)); Helpers.Append48(ref SceneData, (ulong)(Env.C5C.ToArgb() & 0xFFFFFF)); Helpers.Append48(ref SceneData, (ulong)(Env.FogColorC.ToArgb() & 0xFFFFFF)); Helpers.Append16(ref SceneData, Env.FogDistance); Helpers.Append16(ref SceneData, Env.DrawDistance); } AddPadding(ref SceneData, 8); /* ... entrance list ... */ Helpers.Overwrite32(ref SceneData, CmdEntranceListOffset + 4, (uint)(0x02000000 | SceneData.Count)); Helpers.Append16(ref SceneData, 0x0000); /* Map 0, spawn point 0 */ AddPadding(ref SceneData, 8); /* ... collision */ WriteSceneCollision(); }
public void ConvertScene(bool ConsecutiveRoomInject, bool ForceRGBATextures) { /* Check if collision model is valid */ if (ColModel == null) throw new Exception("No collision model defined"); /* Process rooms... */ for (int i = 0; i < _Rooms.Count; i++) { /* Get current room from list */ ZRoom Room = _Rooms[i]; /* Create new room file, DList offset list and texture list */ Room.RoomData = new List<byte>(); Room.DLists = new List<NDisplayList>(); Textures = new List<NTexture>(); /* Create room header */ WriteRoomHeader(Room); /* Write objects */ if (Room.ZObjects.Count != 0) { ObjectOffset = Room.RoomData.Count; foreach (ZUShort Obj in Room.ZObjects) Helpers.Append16(ref Room.RoomData, Obj.Value); AddPadding(ref Room.RoomData, 8); } /* Write actors */ if (Room.ZActors.Count != 0) { ActorOffset = Room.RoomData.Count; foreach (ZActor Actor in Room.ZActors) { Helpers.Append16(ref Room.RoomData, Actor.Number); Helpers.Append16(ref Room.RoomData, (ushort)Actor.XPos); Helpers.Append16(ref Room.RoomData, (ushort)Actor.YPos); Helpers.Append16(ref Room.RoomData, (ushort)Actor.ZPos); Helpers.Append16(ref Room.RoomData, (ushort)Actor.XRot); Helpers.Append16(ref Room.RoomData, (ushort)Actor.YRot); Helpers.Append16(ref Room.RoomData, (ushort)Actor.ZRot); Helpers.Append16(ref Room.RoomData, Actor.Variable); } AddPadding(ref Room.RoomData, 8); } /* Prepare dummy mesh header */ MeshHeaderOffset = Room.MeshHeaderOffset = Room.RoomData.Count; Helpers.Append32(ref Room.RoomData, 0); /* Mesh type X, Y meshes */ Helpers.Append32(ref Room.RoomData, 0); /* Start address */ Helpers.Append32(ref Room.RoomData, 0); /* End address */ for (int j = 0; j < Room.ObjModel.Groups.Count; j++) { Helpers.Append64(ref Room.RoomData, 0); Helpers.Append32(ref Room.RoomData, 0); /* Display List offset 1 */ Helpers.Append32(ref Room.RoomData, 0); /* Display List offset 2 */ } AddPadding(ref Room.RoomData, 8); /* Create textures */ for (int M = 0; M < Room.ObjModel.Materials.Count; M++) { /* Get material & force RGBA default */ ObjFile.Material Mat = Room.ObjModel.Materials[M]; Mat.ForceRGBA = ForceRGBATextures; /* ---VERY kludgy RGBA forcing code--- */ for (int x = 0; x < Room.ObjModel.Groups.Count; x++) { /* If group has multitex material number... */ if (Room.ObjModel.Groups[x].MultiTexMaterial != -1) { /* Turn force RGBA ON for multitex material */ Room.ObjModel.Materials[Room.ObjModel.Groups[x].MultiTexMaterial].ForceRGBA = true; /* Scan group's triangles for current material name... */ for (int y = 0; y < Room.ObjModel.Groups[x].Triangles.Count; y++) { if (Room.ObjModel.Groups[x].Triangles[y].MaterialName == Mat.Name) { /* Turn force RGBA ON for current material */ Mat.ForceRGBA = true; goto Cont; } } } } /* Continue here... */ Cont: if (Mat.TexImage == null) continue; /* Create new texture, convert current material */ NTexture Texture = new NTexture(); Texture.Convert(Mat); /* Add current offset to texture offset list */ Texture.TexOffset = ((uint)Room.RoomData.Count); /* Write converted data to room file */ Room.RoomData.AddRange(Texture.Data); /* See if we've got a CI-format texture... */ int Format = ((Texture.Type & 0xE0) >> 5); #if DEBUG Console.WriteLine("Texture format N64: " + Format.ToString("X2")); #endif if (Format == GBI.G_IM_FMT_CI) { /* If it's CI, add current offset to palette offset list */ Texture.PalOffset = ((uint)Room.RoomData.Count); /* Write palette data to room file */ Room.RoomData.AddRange(Texture.Palette); } else { /* Add dummy entry to palette offset list */ Texture.PalOffset = Dummy; } Textures.Add(Texture); } /* Create Display Lists */ for (int j = 0; j < Room.ObjModel.Groups.Count; j++) { NDisplayList DList = new NDisplayList(Scale, Room.ObjModel.Groups[j].TintAlpha, 1.0f, IsOutdoors, Room.ObjModel.Groups[j].BackfaceCulling); DList.Convert(Room.ObjModel, j, Textures, (uint)Room.RoomData.Count); if (DList.Data != null) Room.RoomData.AddRange(DList.Data); Room.DLists.Add(DList); } /* Fix room header and add missing data */ FixRoomHeader(Room); /* Add some padding for good measure */ AddPadding(ref Room.RoomData, 0x1000); /* Store room data length */ Room.FullDataLength = Room.RoomData.ToArray().Length; /* Put modified room info back into list */ _Rooms[i] = Room; } /* Create new scene file */ SceneData = new List<byte>(); /* Write scene header */ Helpers.Append64(ref SceneData, (ulong)(0x1502000000000000 | Music)); /* Sound settings */ CmdMapListOffset = SceneData.Count; Helpers.Append64(ref SceneData, 0x0400000000000000); /* Map list */ CmdTransitionsOffset = SceneData.Count; Helpers.Append64(ref SceneData, 0x0E00000000000000); /* Transition list */ Helpers.Append64(ref SceneData, 0x1900000000000003); /* Cutscenes */ CmdCollisionOffset = SceneData.Count; Helpers.Append64(ref SceneData, 0x0300000000000000); /* Collision header */ CmdEntranceListOffset = SceneData.Count; Helpers.Append64(ref SceneData, 0x0600000000000000); /* Entrance index */ if (IsOutdoors == true) /* Special objects */ Helpers.Append64(ref SceneData, 0x0701000000000002); else Helpers.Append64(ref SceneData, 0x0702000000000003); CmdSpawnPointOffset = SceneData.Count; Helpers.Append64(ref SceneData, 0x0000000000000000); /* Spawn point list */ if (IsOutdoors == true) /* Skybox / lighting settings */ Helpers.Append64(ref SceneData, 0x1100000001000000); else Helpers.Append64(ref SceneData, 0x1100000000000100); CmdExitListOffset = SceneData.Count; Helpers.Append64(ref SceneData, 0x1300000000000000); /* Exit list */ CmdEnvironmentsOffset = SceneData.Count; Helpers.Append64(ref SceneData, 0x0F00000000000000); /* Environments */ Helpers.Append64(ref SceneData, 0x1400000000000000); /* End marker */ /* Fix scene header; map list ... */ Helpers.Overwrite32(ref SceneData, CmdMapListOffset, (uint)(0x04000000 | (_Rooms.Count << 16))); Helpers.Overwrite32(ref SceneData, CmdMapListOffset + 4, (uint)(0x02000000 | SceneData.Count)); if (ConsecutiveRoomInject == true) { int RoomInjectOffset = _Rooms[0].InjectOffset; foreach (ZRoom Room in _Rooms) { Helpers.Append32(ref SceneData, (uint)RoomInjectOffset); Helpers.Append32(ref SceneData, (uint)(RoomInjectOffset + Room.FullDataLength)); RoomInjectOffset += Room.FullDataLength; } } else { foreach (ZRoom Room in _Rooms) { Helpers.Append32(ref SceneData, (uint)Room.InjectOffset); Helpers.Append32(ref SceneData, (uint)(Room.InjectOffset + Room.FullDataLength)); } } AddPadding(ref SceneData, 8); /* ... transition list ... */ Helpers.Overwrite32(ref SceneData, CmdTransitionsOffset, (uint)(0x0E000000 | (Transitions.Count << 16))); Helpers.Overwrite32(ref SceneData, CmdTransitionsOffset + 4, (uint)(0x02000000 | SceneData.Count)); foreach (ZActor Trans in Transitions) { SceneData.Add(Trans.FrontSwitchTo); SceneData.Add(Trans.FrontCamera); SceneData.Add(Trans.BackSwitchTo); SceneData.Add(Trans.BackCamera); Helpers.Append16(ref SceneData, Trans.Number); Helpers.Append16(ref SceneData, (ushort)Trans.XPos); Helpers.Append16(ref SceneData, (ushort)Trans.YPos); Helpers.Append16(ref SceneData, (ushort)Trans.ZPos); Helpers.Append16(ref SceneData, (ushort)Trans.YRot); Helpers.Append16(ref SceneData, Trans.Variable); } AddPadding(ref SceneData, 8); /* ... exit list ... */ Helpers.Overwrite32(ref SceneData, CmdExitListOffset + 4, (uint)(0x02000000 | SceneData.Count)); foreach (ZUShort Exit in ExitList) { Helpers.Append16(ref SceneData, Exit.Value); } AddPadding(ref SceneData, 8); /* ... spawn point list ... */ Helpers.Overwrite32(ref SceneData, CmdSpawnPointOffset, (uint)(0x00000000 | (SpawnPoints.Count << 16))); Helpers.Overwrite32(ref SceneData, CmdSpawnPointOffset + 4, (uint)(0x02000000 | SceneData.Count)); foreach (ZActor Spawn in SpawnPoints) { Helpers.Append16(ref SceneData, Spawn.Number); Helpers.Append16(ref SceneData, (ushort)Spawn.XPos); Helpers.Append16(ref SceneData, (ushort)Spawn.YPos); Helpers.Append16(ref SceneData, (ushort)Spawn.ZPos); Helpers.Append16(ref SceneData, (ushort)Spawn.XRot); Helpers.Append16(ref SceneData, (ushort)Spawn.YRot); Helpers.Append16(ref SceneData, (ushort)Spawn.ZRot); Helpers.Append16(ref SceneData, Spawn.Variable); } AddPadding(ref SceneData, 8); /* ... environments ... */ Helpers.Overwrite32(ref SceneData, CmdEnvironmentsOffset, (uint)(0x0F000000 | (Environments.Count << 16))); Helpers.Overwrite32(ref SceneData, CmdEnvironmentsOffset + 4, (uint)(0x02000000 | SceneData.Count)); foreach (ZEnvironment Env in Environments) { Helpers.Append48(ref SceneData, (ulong)(Env.C1C.ToArgb() & 0xFFFFFF)); Helpers.Append48(ref SceneData, (ulong)(Env.C2C.ToArgb() & 0xFFFFFF)); Helpers.Append48(ref SceneData, (ulong)(Env.C3C.ToArgb() & 0xFFFFFF)); Helpers.Append48(ref SceneData, (ulong)(Env.C4C.ToArgb() & 0xFFFFFF)); Helpers.Append48(ref SceneData, (ulong)(Env.C5C.ToArgb() & 0xFFFFFF)); Helpers.Append48(ref SceneData, (ulong)(Env.FogColorC.ToArgb() & 0xFFFFFF)); Helpers.Append16(ref SceneData, Env.FogDistance); Helpers.Append16(ref SceneData, Env.DrawDistance); } AddPadding(ref SceneData, 8); /* ... entrance list ... */ Helpers.Overwrite32(ref SceneData, CmdEntranceListOffset + 4, (uint)(0x02000000 | SceneData.Count)); Helpers.Append16(ref SceneData, 0x0000); /* Map 0, spawn point 0 */ AddPadding(ref SceneData, 8); /* ... collision */ WriteSceneCollision(); }