Initiate Mage
- Joined
- Jul 13, 2024
- Messages
- 3
- Reaction score
- 0
Of course, it's there:
does anyone know how to change 3d models from .mesh format to another? does anyone know the original .mesh file format?
Of course, it's there:
Of course, it's there:
Hello, can you tell me how to edit the game models for this game? Or perhaps you know their original format?I was making space on my HDD and found some files of luvinia I worked on when it was first seen in the wild. I don't know how far anybody got with these files (looking through posts nobody tried running the MapEditor and tools yet?) so I'm sharing what I've got, if anybody still has interested in this game, and tell me what he needs I can upload it before deleting it from my HDD forever.
Since I didn't found anything back then to extract the DP files, I made my own using C# so now I'm releasing it:
Code:public class DataPack { public class FileListEntry { public string fileName; public int offset; public int size; public int originalSize; public int validSize; public int crc32; public int compressType; public byte[] Data; public void LoadFileData(byte[] bytes) { using (var ms = new MemoryStream(bytes)) { if (!((compressType & 0x1) == 1)) { if ((compressType & 0x4) == 1) // Standard compress { Console.WriteLine("Compressed!"); } else { Data = new byte[size]; ms.Read(Data, 0, size); Data = lzoCompress.Decompress(Data, size*2); } } else { Data = bytes; } } } public void Extract(string folderPath) { var filePath = folderPath + fileName; if(File.Exists(filePath)) return; filePath = filePath.Replace('?', '_'); var fi = new FileInfo(filePath); Directory.CreateDirectory(fi.DirectoryName); File.WriteAllBytes(filePath, Data); } }; /// <summary> /// The offset of all file data in the current package /// </summary> int offset; /// <summary> /// File index header size /// </summary> int indexHeadSize; int maxIndexNum; /// <summary> /// The size of the empty file index header /// </summary> int emptyIndexHeadSize; int maxEmptyIndexNum; int emptyIndexCount; FileListEntry[] FileEntries; FileListEntry[] EmptyFileEntries; private const int HeadSize = 280; public void ExtractFiles(string filePath, string extractPath) { using (var fs = File.OpenRead(filePath)) { var br = new BinaryReader(fs); offset = br.ReadInt32(); indexHeadSize = br.ReadInt32(); maxIndexNum = indexHeadSize / HeadSize; var indexCount = br.ReadInt32(); Debug.Assert(indexCount <= maxIndexNum, "dwIndexCount <= m_dwMaxIndexNum"); FileEntries = new FileListEntry[indexCount]; for (int i = 0; i < indexCount; i++) { var fileEntry = new FileListEntry(); fileEntry.fileName = ReadAsciiStatic(br, 256); // 24 var bs = br.ReadBytes(24); bs = Decrypt(bs); fileEntry.offset = BitConverter.ToInt32(bs, 0); fileEntry.size = BitConverter.ToInt32(bs, 3); fileEntry.originalSize = BitConverter.ToInt32(bs, 7); fileEntry.validSize = BitConverter.ToInt32(bs, 11); fileEntry.crc32 = BitConverter.ToInt32(bs, 15); fileEntry.compressType = BitConverter.ToInt32(bs, 19); var oldPos = br.BaseStream.Position; br.BaseStream.Seek(fileEntry.offset, SeekOrigin.Begin); fileEntry.LoadFileData(br.ReadBytes(fileEntry.size)); fileEntry.Extract(extractPath); br.BaseStream.Seek(oldPos, SeekOrigin.Begin); } } } public void Load(string filePath) { using (var fs = File.OpenRead(filePath)) { var br = new BinaryReader(fs); offset = br.ReadInt32(); indexHeadSize = br.ReadInt32(); maxIndexNum = indexHeadSize / HeadSize; var indexCount = br.ReadInt32(); Debug.Assert(indexCount <= maxIndexNum, "dwIndexCount <= m_dwMaxIndexNum"); FileEntries = new FileListEntry[indexCount]; for (int i = 0; i < indexCount; i++) { FileEntries[i] = new FileListEntry(); FileEntries[i].fileName = ReadAsciiStatic(br, 256); // 24 var bs = br.ReadBytes(24); bs = Decrypt(bs); FileEntries[i].offset = BitConverter.ToInt32(bs, 0); FileEntries[i].size = BitConverter.ToInt32(bs, 3); FileEntries[i].originalSize = BitConverter.ToInt32(bs, 7); FileEntries[i].validSize = BitConverter.ToInt32(bs, 11); FileEntries[i].crc32 = BitConverter.ToInt32(bs, 15); FileEntries[i].compressType = BitConverter.ToInt32(bs, 19); var oldPos = br.BaseStream.Position; br.BaseStream.Seek(FileEntries[i].offset, SeekOrigin.Begin); FileEntries[i].LoadFileData(br.ReadBytes(FileEntries[i].size)); br.BaseStream.Seek(oldPos, SeekOrigin.Begin); } br.BaseStream.Seek(4 + 4 + 4 + indexHeadSize, SeekOrigin.Begin); emptyIndexHeadSize = br.ReadInt32(); maxEmptyIndexNum = emptyIndexHeadSize / HeadSize; emptyIndexCount = br.ReadInt32(); Debug.Assert(emptyIndexCount <= maxEmptyIndexNum, "dwIndexCount2 <= m_dwMaxEmptyIndexNum"); EmptyFileEntries = new FileListEntry[emptyIndexCount]; for (int i = 0; i < emptyIndexCount; i++) { EmptyFileEntries[i] = new FileListEntry(); EmptyFileEntries[i].fileName = ReadAsciiStatic(br, 256); // 24 var bs = br.ReadBytes(24); bs = Decrypt(bs); EmptyFileEntries[i].offset = BitConverter.ToInt32(bs, 0); EmptyFileEntries[i].size = BitConverter.ToInt32(bs, 3); EmptyFileEntries[i].originalSize = BitConverter.ToInt32(bs, 7); EmptyFileEntries[i].validSize = BitConverter.ToInt32(bs, 11); EmptyFileEntries[i].crc32 = BitConverter.ToInt32(bs, 15); EmptyFileEntries[i].compressType = BitConverter.ToInt32(bs, 19); var oldPos = br.BaseStream.Position; br.BaseStream.Seek(EmptyFileEntries[i].offset, SeekOrigin.Begin); EmptyFileEntries[i].LoadFileData(br.ReadBytes(EmptyFileEntries[i].size)); br.BaseStream.Seek(oldPos, SeekOrigin.Begin); } } } public void Extract(string folderPath) { if(!Directory.Exists(folderPath)) Directory.CreateDirectory(folderPath); foreach(var entry in FileEntries) { entry.Extract(folderPath); } } public static byte[] Decrypt(byte[] encrypted) { var decrypted = encrypted; for (var i = 0; i < decrypted.Length; i++) { decrypted[i] ^= 0xFF; } return decrypted; } public static string ReadAsciiStatic(BinaryReader br, int maxLength) { var buf = br.ReadBytes(maxLength); buf = Decrypt(buf); var str = Encoding.ASCII.GetString(buf); if (str.Contains("\0")) str = str.Substring(0, str.IndexOf('\0')); return str; } };
MapEditor:
View attachment 221919
PackageTool (I think I translated this one myself since there are clear differences between mine and the one shared before):
View attachment 221920
GameModel Viewer:
View attachment 221921