public static int Main() { Directory.CreateDirectory("GAMEDATA"); if (File.Exists(@"GAMEDATA\vars.txt")) { vars.Load(@"GAMEDATA\vars.txt"); } if (!File.Exists(@"GAMEDATA\LISTTRAK.PAK")) { return(-1); } using (var writer = new StreamWriter("output.txt")) using (var pak = new UnPAK(@"GAMEDATA\LISTTRAK.PAK")) { for (int i = 0; i < pak.EntryCount; i++) { writer.WriteLine("--------------------------------------------------"); writer.WriteLine("#{0} {1}", i, vars.GetText(VarEnum.TRACKS, i, string.Empty)); writer.WriteLine("--------------------------------------------------"); Dump(pak.GetEntry(i), writer); } } return(0); }
Texture2D LoadTexture(UnPAK pak, int textureIndex, Color32[] paletteColors) { if (textureIndex >= 0 && textureIndex < textureCount) { var tex256 = pak.GetEntry(textureIndex); FixBlackBorders(tex256); var texSize = tex256.Length; Color32[] textureData = new Color32[texSize]; for (int i = 0; i < tex256.Length; i++) { textureData[i] = paletteColors[tex256[i]]; } Texture2D tex = new Texture2D(256, texSize / 256, TextureFormat.ARGB32, false); tex.filterMode = DetailsLevel.BoolValue ? FilterMode.Bilinear : FilterMode.Point; tex.SetPixels32(textureData); tex.Apply(); return(tex); } return(EmptyTexture()); }
void LoadTextures(byte[] buffer, Color32[] paletteColors, out int uvStart, out int texAHeight, out int texBHeight) { var offset = buffer[0xE]; Texture2D texA, texB; if (File.Exists(textureFolder)) { paletteColors[0] = Color.clear; using (var pak = new UnPAK(textureFolder)) { texA = LoadTexture(pak, buffer.ReadUnsignedShort(offset + 12), paletteColors); texB = LoadTexture(pak, buffer.ReadUnsignedShort(offset + 14), paletteColors); } } else { texA = EmptyTexture(); texB = EmptyTexture(); } uvStart = buffer.ReadShort(offset + 6); texAHeight = texA.height; texBHeight = texB.height; var materials = GetComponent <SkinnedMeshRenderer>().materials; materials[5].mainTexture = texA; materials[6].mainTexture = texB; }
void LoadRoomsSingle(string filePath) { using (var pak = new UnPAK(filePath)) { var buffer = pak.GetEntry(0); int maxrooms = buffer.ReadInt(0) / 4; for (int currentroom = 0; currentroom < maxrooms; currentroom++) { int roomheader = buffer.ReadInt(currentroom * 4); if (roomheader <= 0 || roomheader >= buffer.Length) { //all rooms parsed break; } LoadRoom(buffer, roomheader, currentroom); } buffer = pak.GetEntry(1); foreach (int cameraID in camerasPerRoom.SelectMany(x => x).Distinct()) { int cameraHeader = buffer.ReadInt(cameraID * 4); LoadCamera(buffer, cameraHeader, cameraID); } } }
void LoadTextures(string filePath) { if (File.Exists(filePath)) { using (var pak = new UnPAK(filePath)) { textureCount = pak.EntryCount; } } }
void LoadModels(string filePath) { if (File.Exists(filePath)) { using (var pak = new UnPAK(filePath)) { modelCount = pak.EntryCount; } SetPalette(); LoadBody(); } }
int GetEntriesCount(string filePath) { string firstFloorFilePath = Config.GetPath(filePath); if (File.Exists(firstFloorFilePath)) { using (var pak = new UnPAK(firstFloorFilePath)) { return(pak.EntryCount); } } return(0); }
void LoadAnims(string filePath) { if (File.Exists(filePath)) { using (var pak = new UnPAK(filePath)) { animCount = pak.EntryCount; } if (EnableAnimation.BoolValue) { LoadAnim(); } } }
void LoadRoomsMulti(string filePath) { using (var pak = new UnPAK(filePath)) { for (int i = 0; i < pak.EntryCount; i++) { byte[] buffer = pak.GetEntry(i); LoadRoom(buffer, 0, i); } } filePath = Config.GetPath("CAMSAL{0:D2}.PAK", floor); if (File.Exists(filePath)) { using (var pak = new UnPAK(filePath)) { for (int i = 0; i < pak.EntryCount; i++) { byte[] buffer = pak.GetEntry(i); LoadCamera(buffer, 0, i); } } } }
void LoadAnim() { string filePath = animFolders[modelFolderIndex]; int i = 0; byte[] buffer; using (var pak = new UnPAK(filePath)) { buffer = pak.GetEntry(animIndex); } int frameCount = buffer.ReadShort(i + 0); int boneCount = buffer.ReadShort(i + 2); i += 4; var isAITD2 = ((boneCount * 16 + 8) * frameCount + 4) == buffer.Length; animFrames = new List <Frame>(); for (int frame = 0; frame < frameCount; frame++) { Frame f = new Frame(); f.Time = buffer.ReadShort(i + 0); f.Offset = buffer.ReadVector(i + 2); f.Bones = new List <Bone>(); i += 8; for (int bone = 0; bone < boneCount; bone++) { Bone b = new Bone(); b.Type = buffer.ReadShort(i + 0); Vector3 boneTransform = buffer.ReadVector(i + 2); switch (b.Type) { case 0: //rotate if (!isAITD2) { b.Rotate = new Vector3(-boneTransform.x * 360 / 1024.0f, -boneTransform.y * 360 / 1024.0f, -boneTransform.z * 360 / 1024.0f); } break; case 1: //translate b.Position = new Vector3(boneTransform.x / 1000.0f, -boneTransform.y / 1000.0f, boneTransform.z / 1000.0f); break; case 2: //scale b.Scale = new Vector3(boneTransform.x / 1024.0f + 1.0f, boneTransform.y / 1024.0f + 1.0f, boneTransform.z / 1024.0f + 1.0f); break; } i += 8; if (isAITD2) { boneTransform = buffer.ReadVector(i + 0); b.Rotate = new Vector3(-boneTransform.x * 360 / 1024.0f, -boneTransform.y * 360 / 1024.0f, -boneTransform.z * 360 / 1024.0f); i += 8; } f.Bones.Add(b); } animFrames.Add(f); } RefreshLeftText(); }
void LoadBody(bool resetcamera = true) { string filePath = modelFolders[modelFolderIndex]; //camera if (resetcamera) { cameraPosition = Vector2.zero; } //clear model SkinnedMeshRenderer filter = this.gameObject.GetComponent <SkinnedMeshRenderer>(); filter.sharedMesh = null; //delete all bones foreach (Transform child in transform) { GameObject.Destroy(child.gameObject); } //load data byte[] buffer; using (var pak = new UnPAK(filePath)) { buffer = pak.GetEntry(modelIndex); } int i = 0; //header modelFlags = buffer.ReadShort(i + 0); //bounding box buffer.ReadBoundingBox(i + 2, out boundingLower, out boundingUpper); BoundingBox.transform.localScale = (boundingUpper - boundingLower) / 1000.0f; var pos = (boundingUpper + boundingLower) / 2000.0f; BoundingBox.transform.localPosition = new Vector3(pos.x, -pos.y, pos.z); i += 0xE; i += buffer.ReadShort(i + 0) + 2; //vertexes int count = buffer.ReadShort(i + 0); i += 2; List <Vector3> vertices = new List <Vector3>(); for (int j = 0; j < count; j++) { Vector3 position = new Vector3(buffer.ReadShort(i + 0), -buffer.ReadShort(i + 2), buffer.ReadShort(i + 4)); vertices.Add(position / 1000.0f); i += 6; } bones = new List <Transform>(); List <Matrix4x4> bindPoses = new List <Matrix4x4>(); Dictionary <int, int> bonesPerVertex = new Dictionary <int, int>(); List <Vector3> vertexNoTransform = vertices.ToList(); if ((modelFlags & 2) == 2) //check if model has bones { //bones count = buffer.ReadShort(i + 0); i += 2; i += count * 2; Dictionary <int, Transform> bonesPerIndex = new Dictionary <int, Transform>(); bonesPerIndex.Add(255, transform); for (int n = 0; n < count; n++) { int startindex = buffer.ReadShort(i + 0) / 6; int numpoints = buffer.ReadShort(i + 2); int vertexindex = buffer.ReadShort(i + 4) / 6; int parentindex = buffer[i + 6]; int boneindex = buffer[i + 7]; //create bone Transform bone = new GameObject("BONE").transform; bonesPerIndex.Add(boneindex, bone); bone.parent = bonesPerIndex[parentindex]; bone.localRotation = Quaternion.identity; bone.localPosition = vertexNoTransform[vertexindex]; bones.Add(bone); //create pose Matrix4x4 bindPose = new Matrix4x4(); bindPose = bone.worldToLocalMatrix * transform.localToWorldMatrix; bindPoses.Add(bindPose); //apply bone transformation Vector3 position = vertices[vertexindex]; for (int u = 0; u < numpoints; u++) { vertices[startindex] += position; bonesPerVertex.Add(startindex, bones.Count - 1); startindex++; } if ((modelFlags & 8) == 8) { i += 0x18; } else { i += 0x10; } } } else { //if no bones add dummy values for (int u = 0; u < vertices.Count; u++) { bonesPerVertex.Add(u, 0); } } //compute line size Bounds bounds = new Bounds(); foreach (Vector3 vector in vertices) { bounds.Encapsulate(vector); } float linesize = bounds.size.magnitude / 250.0f; float noisesize = 0.8f / bounds.size.magnitude; //primitives count = buffer.ReadUnsignedShort(i + 0); i += 2; //load palette Color32[] paletteColors = PaletteTexture[paletteIndex].GetPixels32(); //load texture int texAHeight = 1; int texBHeight = 1; int uvStart = 0; if (paletteIndex == 4) //TIMEGATE { LoadTextures(buffer, paletteColors, out uvStart, out texAHeight, out texBHeight); } List <BoneWeight> boneWeights = new List <BoneWeight>(); allVertices = new List <Vector3>(); uv = new List <Vector2>(); uvDepth = new List <Vector2>(); List <Color32> colors = new List <Color32>(); List <int>[] indices = new List <int> [7]; for (int n = 0; n < indices.Length; n++) { indices[n] = new List <int>(); } gradientPolygonList = new List <List <int> >(); gradientPolygonType = new List <int>(); for (int n = 0; n < count; n++) { int primitiveType = buffer[i + 0]; i++; switch (primitiveType) { //line case 0: { i++; int colorIndex = buffer[i + 0]; i += 2; Color32 color = paletteColors[colorIndex]; int pointIndexA = buffer.ReadShort(i + 0) / 6; int pointIndexB = buffer.ReadShort(i + 2) / 6; Vector3 directionVector = vertices[pointIndexA] - vertices[pointIndexB]; Vector3 middle = (vertices[pointIndexA] + vertices[pointIndexB]) / 2.0f; Quaternion rotation = Quaternion.LookRotation(directionVector); uv.AddRange(CubeMesh.uv); uvDepth.AddRange(CubeMesh.vertices.Select(x => Vector2.zero)); indices[0].AddRange(CubeMesh.triangles.Select(x => x + allVertices.Count)); allVertices.AddRange(CubeMesh.vertices.Select(x => rotation * (Vector3.Scale(x, new Vector3(linesize, linesize, directionVector.magnitude))) + middle)); colors.AddRange(CubeMesh.vertices.Select(x => color)); boneWeights.AddRange(CubeMesh.vertices.Select(x => new BoneWeight() { boneIndex0 = bonesPerVertex[x.z > 0 ? pointIndexA : pointIndexB], weight0 = 1 })); i += 4; break; } //polygon case 1: { int numPoints = buffer[i + 0]; int polyType = buffer[i + 1]; int colorIndex = buffer[i + 2]; i += 3; Color32 color = GetPaletteColor(paletteColors, colorIndex, polyType); List <int> triangleList = indices[GetTriangleListIndex(polyType)]; //add vertices List <int> polyVertices = new List <int>(); int verticesCount = allVertices.Count; for (int m = 0; m < numPoints; m++) { int pointIndex = buffer.ReadShort(i + 0) / 6; i += 2; colors.Add(color); polyVertices.Add(allVertices.Count); allVertices.Add(vertices[pointIndex]); boneWeights.Add(new BoneWeight() { boneIndex0 = bonesPerVertex[pointIndex], weight0 = 1 }); } gradientPolygonType.Add(polyType); gradientPolygonList.Add(polyVertices); if (polyType == 1 && DetailsLevel.BoolValue) { Vector3 forward, left; ComputeUV(polyVertices, out forward, out left); foreach (int pointIndex in polyVertices) { Vector3 poly = allVertices[pointIndex]; uv.Add(new Vector2( Vector3.Dot(poly, left) * noisesize, Vector3.Dot(poly, forward) * noisesize )); } } else { uv.AddRange(polyVertices.Select(x => Vector2.zero)); } uvDepth.AddRange(polyVertices.Select(x => Vector2.zero)); //triangulate int v0 = 0; int v1 = 1; int v2 = numPoints - 1; bool swap = true; while (v1 < v2) { triangleList.Add(verticesCount + v0); triangleList.Add(verticesCount + v1); triangleList.Add(verticesCount + v2); if (swap) { v0 = v1; v1++; } else { v0 = v2; v2--; } swap = !swap; } break; } //sphere case 3: { int polyType = buffer[i]; i++; int colorIndex = buffer[i]; Color32 color = GetPaletteColor(paletteColors, colorIndex, polyType); List <int> triangleList = indices[GetTriangleListIndex(polyType)]; i += 2; int size = buffer.ReadShort(i + 0); i += 2; int pointSphereIndex = buffer.ReadShort(i + 0) / 6; i += 2; Vector3 position = vertices[pointSphereIndex]; float scale = size / 500.0f; float uvScale = noisesize * size / 200.0f; if ((polyType == 3 || polyType == 4 || polyType == 5 || polyType == 6) && DetailsLevel.BoolValue) { gradientPolygonType.Add(polyType); gradientPolygonList.Add(Enumerable.Range(allVertices.Count, SphereMesh.vertices.Length).ToList()); } uv.AddRange(SphereMesh.uv.Select(x => x * uvScale)); uvDepth.AddRange(SphereMesh.vertices.Select(x => Vector2.zero)); triangleList.AddRange(SphereMesh.triangles.Select(x => x + allVertices.Count)); allVertices.AddRange(SphereMesh.vertices.Select(x => x * scale + position)); colors.AddRange(SphereMesh.vertices.Select(x => color)); boneWeights.AddRange(SphereMesh.vertices.Select(x => new BoneWeight() { boneIndex0 = bonesPerVertex[pointSphereIndex], weight0 = 1 })); break; } case 2: //1x1 pixel case 6: //2x2 square case 7: //NxN square, size depends projected z-value { i++; int colorIndex = buffer[i]; i += 2; int cubeIndex = buffer.ReadShort(i + 0) / 6; i += 2; Color32 color = paletteColors[colorIndex]; Vector3 position = vertices[cubeIndex]; float pointsize; if (primitiveType == 2) { pointsize = linesize; } else { pointsize = linesize * 2.5f; } uv.AddRange(CubeMesh.uv); uvDepth.AddRange(CubeMesh.vertices.Select(x => Vector2.zero)); indices[0].AddRange(CubeMesh.triangles.Select(x => x + allVertices.Count)); allVertices.AddRange(CubeMesh.vertices.Select(x => x * pointsize + position)); colors.AddRange(CubeMesh.vertices.Select(x => color)); boneWeights.AddRange(CubeMesh.vertices.Select(x => new BoneWeight() { boneIndex0 = bonesPerVertex[cubeIndex], weight0 = 1 })); break; } //triangle case 8: //texture case 9: //normals case 10: //normals + texture { float textureHeight = 1.0f; int uvIndex = 0, indicesIndex = 0; Color color = Color.white; if (primitiveType == 8 || primitiveType == 10) { uvIndex = uvStart + (buffer.ReadUnsignedShort(i + 1) / 16) * 3; bool texModel = (buffer[i + 1] & 0xF) == 0; textureHeight = (float)(texModel ? texAHeight : texBHeight); indicesIndex = texModel ? 5 : 6; } else { int colorIndex = buffer[i + 2]; color = paletteColors[colorIndex]; } i += 3; for (int k = 0; k < 3; k++) { int pointIndex = buffer.ReadShort(i + 0) / 6; i += 2; uvDepth.Add(Vector2.zero); indices[indicesIndex].Add(allVertices.Count); colors.Add(color); allVertices.Add(vertices[pointIndex]); boneWeights.Add(new BoneWeight() { boneIndex0 = bonesPerVertex[pointIndex], weight0 = 1 }); if (primitiveType == 8 || primitiveType == 10) { uv.Add(new Vector2( buffer.ReadShort(uvIndex + 0) / 256.0f, buffer.ReadShort(uvIndex + 2) / textureHeight)); uvIndex += 4; } else { uv.Add(Vector2.zero); } } if (primitiveType == 9 || primitiveType == 10) { i += 6; //normals } } break; case 4: case 5: //should be ignored break; default: throw new UnityException("unknown primitive " + primitiveType.ToString() + " at " + i.ToString()); } } // Create the mesh Mesh msh = new Mesh(); msh.vertices = allVertices.ToArray(); msh.colors32 = colors.ToArray(); //separate triangles depending their material msh.subMeshCount = 7; msh.SetTriangles(indices[0], 0); msh.SetTriangles(indices[1], 1); msh.SetTriangles(indices[2], 2); msh.SetTriangles(indices[3], 3); msh.SetTriangles(indices[4], 4); msh.SetTriangles(indices[5], 5); msh.SetTriangles(indices[6], 6); msh.SetUVs(0, uv); msh.SetUVs(1, uvDepth); msh.RecalculateNormals(); msh.RecalculateBounds(); //apply bones if (bones.Count > 0) { msh.boneWeights = boneWeights.ToArray(); msh.bindposes = bindPoses.ToArray(); GetComponent <SkinnedMeshRenderer>().bones = bones.ToArray(); initialBonesPosition = bones.Select(x => x.localPosition).ToList(); } filter.localBounds = msh.bounds; filter.sharedMesh = msh; RefreshLeftText(); }
public static int Main(string[] args) { string version = Shared.Tools.GetArgument <string>(args, "-version"); config = gameConfigs.FirstOrDefault(x => string.Equals(x.Version.ToString(), version, StringComparison.InvariantCultureIgnoreCase)); if (version == null) { Console.WriteLine("Usage: LifeDISA -version {{{0}}} [-raw]", string.Join("|", gameConfigs.Select(x => x.Version.ToString().ToLowerInvariant()))); return(-1); } NoOptimize |= Shared.Tools.HasArgument(args, "-raw"); Directory.CreateDirectory("GAMEDATA"); //parse vars if (File.Exists(@"GAMEDATA\vars.txt")) { vars.Load(@"GAMEDATA\vars.txt", VarEnum.LIFES, VarEnum.BODYS, VarEnum.MUSIC, VarEnum.ANIMS, VarEnum.SPECIAL, VarEnum.TRACKS, VarEnum.POSREL, VarEnum.VARS, VarEnum.CVARS, VarEnum.SOUNDS, VarEnum.ACTIONS, VarEnum.KEYBOARD_INPUT, VarEnum.TRACKMODE); } int fileCount = 0; if (File.Exists(@"GAMEDATA\LISTLIFE.PAK")) { using (var pak = new UnPAK(@"GAMEDATA\LISTLIFE.PAK")) { fileCount = pak.EntryCount; } } //dump names var languagePakFiles = new [] { "ENGLISH.PAK", "FRANCAIS.PAK", "DEUTSCH.PAK", "ESPAGNOL.PAK", "ITALIANO.PAK", "USA.PAK" }; string languageFile = languagePakFiles .Select(x => Path.Combine("GAMEDATA", x)) .FirstOrDefault(File.Exists); if (languageFile != null) { byte[] buffer; using (var pak = new UnPAK(languageFile)) { buffer = pak.GetEntry(0); } foreach (var item in Tools.ReadLines(buffer, Encoding.GetEncoding(850)) .Where(x => x.Contains(":")) .Select(x => x.Split(':')) .Where(x => x[1] != string.Empty)) { namesByIndex[int.Parse(item[0].TrimStart('@'))] = item[1]; } } if (File.Exists(@"GAMEDATA\OBJETS.ITD")) { allBytes = File.ReadAllBytes(@"GAMEDATA\OBJETS.ITD"); int count = allBytes.ReadShort(0); for (int i = 0; i < count; i++) { string name = null; int n = i * config.Offset + 2; int body = allBytes.ReadShort(n + 2); if (body != -1) { name = vars.GetText(VarEnum.BODYS, body, string.Empty); } if (string.IsNullOrEmpty(name)) { int index = allBytes.ReadShort(n + 10); if (index != -1 && index != 0 && namesByIndex.TryGetValue(index, out name)) { name = name.ToLowerInvariant(); name = string.Join("_", name.Split(' ').Where(x => x != "an" && x != "a").ToArray()); } } if (string.IsNullOrEmpty(name)) { int life = allBytes.ReadShort(n + 34); if (life != -1) { name = vars.GetText(VarEnum.LIFES, life, string.Empty); } } if (!string.IsNullOrEmpty(name)) { objectsByIndex.Add(i, name.ToLowerInvariant()); } } } using (var writer = new StreamWriter("scripts.life")) using (var pak = new UnPAK(@"GAMEDATA\LISTLIFE.PAK")) { //dump all for (int i = 0; i < pak.EntryCount; i++) { writer.WriteLine("--------------------------------------------------"); writer.WriteLine("#{0} {1}", i, vars.GetText(VarEnum.LIFES, i, string.Empty)); writer.WriteLine("--------------------------------------------------"); allBytes = pak.GetEntry(i); try { ParseFile(); if (!NoOptimize) { var optimizer = new Optimizer(nodes, nodesMap); optimizer.Run(); if (nodes.Count(x => x.IndentDec) != nodes.Count(x => x.IndentInc)) { throw new Exception("Indentation should be equal to zero"); } if (nodes.Any(x => x.Type == LifeEnum.GOTO)) { throw new Exception("Unexpected gotos"); } ProcessCaseStatements(); } else { ProcessGotos(); } Dump(writer); } catch (Exception ex) { writer.WriteLine(ex); } } } return(0); }