public static byte[] CreateExePackedImage() { var egaCmn = Resource.Load("EGA.CMN"); var mcgaCod = Resource.Load("MCGA.COD"); var mcgaDif = Resource.Load("MCGA.DIF"); var mcgaHdr = Resource.Load("MCGA.HDR"); var bytesInLastPage = ReadUshortAt(mcgaHdr, 2); var pagesInExecutable = ReadUshortAt(mcgaHdr, 4); var paragraphsInHeader = ReadUshortAt(mcgaHdr, 8); int executableSize = pagesInExecutable << 9; if (bytesInLastPage > 0) { executableSize += bytesInLastPage - 0x1f0; } int headerSize = paragraphsInHeader << 4; var executableImage = new byte[executableSize]; mcgaHdr.CopyTo(executableImage, 0); egaCmn.CopyTo(executableImage, headerSize); mcgaCod.CopyTo(executableImage, headerSize + egaCmn.Length); var difStream = new ReadStream(mcgaDif); int writeOffset = headerSize - 1; while (true) { var jump = (ushort)difStream.ReadShort(); if (jump == 0) { break; } writeOffset += jump & 0x7fff; executableImage[writeOffset] = difStream.ReadByte(); executableImage[writeOffset + 1] = difStream.ReadByte(); if ((jump & 0x8000) != 0) { executableImage[writeOffset + 2] = difStream.ReadByte(); executableImage[writeOffset + 3] = difStream.ReadByte(); } } return(executableImage); }
public static IEnumerable <ProgressStatus> ImportMeshes() { var importSettings = FindOrCreateAssetAtPath <ImportSettings>(ImportSettingsPath); var carCodes = GetCarCodes(); float progress = 0; float progressStep = 1f / carCodes.Count; Directory.CreateDirectory("Assets/Resources/Cars/InGameMeshes"); Directory.CreateDirectory("Assets/Resources/Cars/ShowRoomMeshes"); Directory.CreateDirectory("Assets/Resources/Cars/CollisionMeshes"); Directory.CreateDirectory("Assets/Resources/Terrain"); foreach (var carCode in carCodes) { var dataResource = Resource.ReadResourceMap(Resource.Load("CAR" + carCode + ".RES")); var carName = new ReadStream(dataResource["gnam"]).ReadString().Replace('/', '-'); yield return(new ProgressStatus("Importing cars (" + carName + ")", progress)); progress += progressStep; var modelResource = Resource.ReadResourceMap(Resource.Load("ST" + carCode + ".P3S")); var inGameModel = new Model(new ReadStream(modelResource["car1"])); var showRoomModel = new Model(new ReadStream(modelResource["car0"])); var collisionModel = new Model(new ReadStream(modelResource["car2"])); var inGameMesh = inGameModel.ToMesh(importSettings); var showRoomMesh = showRoomModel.ToMesh(importSettings); var collisionMesh = collisionModel.ToMesh(importSettings); AssetDatabase.CreateAsset(inGameMesh, "Assets/Resources/Cars/InGameMeshes/" + carName + ".asset"); AssetDatabase.CreateAsset(showRoomMesh, "Assets/Resources/Cars/ShowRoomMeshes/" + carName + ".asset"); AssetDatabase.CreateAsset(collisionMesh, "Assets/Resources/Cars/CollisionMeshes/" + carName + ".asset"); } var resourceMap1 = Resource.ReadResourceMap(Resource.Load("GAME1.P3S")); var resourceMap2 = Resource.ReadResourceMap(Resource.Load("GAME2.P3S")); progress = 0; progressStep = 1f / (resourceMap1.Count + resourceMap2.Count); foreach (var resource in resourceMap1.Concat(resourceMap2)) { yield return(new ProgressStatus("Importing tiles (" + resource.Key + ")", progress)); progress += progressStep; var mesh = new Model(new ReadStream(resource.Value)).ToMesh(importSettings); AssetDatabase.CreateAsset(mesh, "Assets/Resources/Terrain/" + resource.Key + ".asset"); } yield return(null); }
public Primitive(int paintJobCount, ReadStream input) { var primitiveCode = input.ReadByte(); int indexCount = primitiveCode; switch (primitiveCode) { case 1: Type = PrimitiveType.Particle; break; case 2: Type = PrimitiveType.Line; break; case 11: Type = PrimitiveType.Sphere; indexCount = 2; break; case 12: Type = PrimitiveType.Wheel; indexCount = 6; break; default: if (3 <= primitiveCode && primitiveCode <= 10) { Type = PrimitiveType.Polygon; } else { Type = PrimitiveType.Ignored; indexCount = 0; } break; } var flags = input.ReadByte(); IsTwoSided = (flags & 1) != 0; HasZBias = (flags & 2) != 0; Materials = input.ReadByteArray(paintJobCount); Indices = input.ReadByteArray(indexCount); }
public static void GenerateTileMapping() { const int baseAddress = 0xabcc; const int nameBaseAddress = 0x9584; const int nameSize = 5; const int shapeBaseAddress = 0x764c; const int shapeSize = 22; var importSettings = FindOrCreateAssetAtPath <ImportSettings>(ImportSettingsPath); UnpackCode(); importSettings.tileDescriptions = new List <TileDescription>(); for (int i = 0; i < 0xf7; i++) { var tileDescription = new TileDescription(); int structAddress = baseAddress + i * 14; tileDescription.orientation = unpackedCode[structAddress + 3] & 0x03; tileDescription.otherPartIndex = unpackedCode[structAddress + 8]; tileDescription.materialIndex = unpackedCode[structAddress + 9]; int sizeFlags = unpackedCode[structAddress + 11]; tileDescription.xSize = (sizeFlags & 2) == 0 ? 1 : 2; tileDescription.ySize = (sizeFlags & 1) == 0 ? 1 : 2; int shapeAddress = unpackedCode[structAddress + 4] + unpackedCode[structAddress + 5] * 0x100; int nameOffset = (shapeAddress - shapeBaseAddress) * nameSize / shapeSize + nameBaseAddress; string meshName = new ReadStream(unpackedCode, nameOffset).ReadFixedLengthString(4); if (!meshName.All(c => c > 0x20 && c < 0x80)) { meshName = ""; } tileDescription.meshName = meshName; tileDescription.name = string.Format("{0} ({1})", i, tileDescription.Displayname); importSettings.tileDescriptions.Add(tileDescription); } }
public Model(ReadStream input) { var vertexCount = input.ReadByte(); var primitiveCount = input.ReadByte(); PaintJobCount = input.ReadByte(); input.Skip(1); Vertices = new Vector3[vertexCount]; for (int i = 0; i < vertexCount; i++) { Vertices[i] = input.ReadVertex(); } input.Skip(8 * primitiveCount); Primitives = new Primitive[primitiveCount]; for (int i = 0; i < primitiveCount; i++) { Primitives[i] = new Primitive(PaintJobCount, input); } }
public static Dictionary <string, byte[]> ReadResourceMap(byte[] rawResource) { var result = new Dictionary <string, byte[]>(); var input = new ReadStream(rawResource); input.Skip(4); var resourceCount = input.ReadShort(); var ids = new string[resourceCount]; for (int i = 0; i < resourceCount; i++) { ids[i] = input.ReadFixedLengthString(4); } var sortedIds = new SortedDictionary <int, string>(); for (int i = 0; i < resourceCount; i++) { sortedIds[input.ReadInt()] = ids[i]; } var data = new ReadBuffer(rawResource).Drop(6 + 8 * resourceCount); var sortedOffsets = new List <int>(sortedIds.Keys); sortedOffsets.Add(data.Length); for (int i = 0; i < resourceCount; i++) { var startOffset = sortedOffsets[i]; var endOffset = sortedOffsets[i + 1]; result[sortedIds[startOffset]] = data.Slice(startOffset, endOffset - startOffset).ToArray(); } return(result); }