public Header(byte[] bytes) { magic = EndianBytesOperator.readString(bytes, 0, 4); if (magic != "PrOD") { throw new InvalidDataException(); } constNum1 = EndianBytesOperator.readUInt(bytes, 0x04); if (constNum1 != 0x01000000) { throw new InvalidDataException(); } constNum2 = EndianBytesOperator.readUInt(bytes, 0x08); if (constNum2 != 0x00000001) { throw new InvalidDataException(); } lstUSOffset = EndianBytesOperator.readUInt(bytes, 0x0C); fileSize = EndianBytesOperator.readUInt(bytes, 0x10); meshCount = EndianBytesOperator.readUInt(bytes, 0x14); STOffset = EndianBytesOperator.readUInt(bytes, 0x18); NullPadding = EndianBytesOperator.readUInt(bytes, 0x1C); if (NullPadding != 0x00000000) { throw new InvalidDataException(); } }
public byte[] getBytes() { if (m_bytes != null) { return(m_bytes); } m_bytes = new byte[m_header.fileSize]; m_header.writeToBytes(m_bytes); uint offset = Header.size; foreach (var mesh in m_meshes) { mesh.writeToBytes(m_bytes, offset); offset += mesh.size; } offset = m_header.STOffset; EndianBytesOperator.writeUInt(m_bytes, (int)offset + 0x00, (uint)names.Count); EndianBytesOperator.writeUInt(m_bytes, (int)offset + 0x04, m_namesSize - 0x08); offset += 0x08; foreach (var str in names) { offset += (uint)EndianBytesOperator.writeString_PrOD(m_bytes, (int)offset, str); } return(m_bytes); }
public void writeToBytes(byte[] bytes) { EndianBytesOperator.writeString(bytes, 0x0, magic, 4); EndianBytesOperator.writeUInt(bytes, 0x04, constNum1); EndianBytesOperator.writeUInt(bytes, 0x08, constNum2); EndianBytesOperator.writeUInt(bytes, 0x0C, lstUSOffset); EndianBytesOperator.writeUInt(bytes, 0x10, fileSize); EndianBytesOperator.writeUInt(bytes, 0x14, meshCount); EndianBytesOperator.writeUInt(bytes, 0x18, STOffset); EndianBytesOperator.writeUInt(bytes, 0x1C, NullPadding); }
public MeshInstance(byte[] bytes, uint offset) { position = new float[3]; position[0] = EndianBytesOperator.readFloat(bytes, (int)offset + 0x0); position[1] = EndianBytesOperator.readFloat(bytes, (int)offset + 0x04); position[2] = EndianBytesOperator.readFloat(bytes, (int)offset + 0x08); rotation = new float[3]; rotation[0] = EndianBytesOperator.readFloat(bytes, (int)offset + 0x0C); rotation[1] = EndianBytesOperator.readFloat(bytes, (int)offset + 0x10); rotation[2] = EndianBytesOperator.readFloat(bytes, (int)offset + 0x14); uniformScale = EndianBytesOperator.readFloat(bytes, (int)offset + 0x18); }
public void writeToBytes(byte[] bytes, uint offset) { EndianBytesOperator.writeFloat(bytes, (int)offset + 0x00, position[0]); EndianBytesOperator.writeFloat(bytes, (int)offset + 0x04, position[1]); EndianBytesOperator.writeFloat(bytes, (int)offset + 0x08, position[2]); EndianBytesOperator.writeFloat(bytes, (int)offset + 0x0C, rotation[0]); EndianBytesOperator.writeFloat(bytes, (int)offset + 0x10, rotation[1]); EndianBytesOperator.writeFloat(bytes, (int)offset + 0x14, rotation[2]); EndianBytesOperator.writeFloat(bytes, (int)offset + 0x18, uniformScale); EndianBytesOperator.writeUInt(bytes, (int)offset + 0x1C, NullPadding); }
public void writeToBytes(byte[] bytes, uint offset) { EndianBytesOperator.writeUInt(bytes, (int)offset + 0x00, instancesSize); EndianBytesOperator.writeUInt(bytes, (int)offset + 0x04, instancesCount); EndianBytesOperator.writeUInt(bytes, (int)offset + 0x08, nameOffset); EndianBytesOperator.writeUInt(bytes, (int)offset + 0x0C, NullPadding); uint t_offset = offset + 0x10; foreach (MeshInstance meshIns in instances) { meshIns.writeToBytes(bytes, t_offset); t_offset += MeshInstance.size; } }
public Mesh(byte[] bytes, uint offset, List <string> names, uint stOffset) { instancesSize = EndianBytesOperator.readUInt(bytes, (int)offset + 0x0); size = 0x10 + instancesSize; instancesCount = EndianBytesOperator.readUInt(bytes, (int)offset + 0x04); nameOffset = EndianBytesOperator.readUInt(bytes, (int)offset + 0x08); name = EndianBytesOperator.readString(bytes, (int)(stOffset + nameOffset)); names.Add(name); instances = new List <MeshInstance>(); for (int i = 0; i < instancesCount; i++) { instances.Add(new MeshInstance(bytes, (uint)(offset + 0x10 + MeshInstance.size * i))); } }
public static bool IsYaz0(byte[] bytes) { return(EndianBytesOperator.readString(bytes, 0, 4) == "Yaz0"); }
public static byte[] decode(byte[] src) { if (!IsYaz0(src)) { return(src); } uint decompressedSize = EndianBytesOperator.readUInt(src, 0x04); byte[] dst = new byte[decompressedSize]; uint srcPos = 0x10; uint dstPos = 0; byte Opcode = 0x00; List <KeyValuePair <int, KeyValuePair <int, int> > > finds = new List <KeyValuePair <int, KeyValuePair <int, int> > >(); while (true) { Opcode = src[srcPos]; srcPos++; for (int i = 0; i < 8; i++, Opcode <<= 1) { if ((Opcode & 0x80) != 0) { dst[dstPos] = src[srcPos]; dstPos++; srcPos++; } else { byte b1 = src[srcPos]; byte b2 = src[srcPos + 1]; srcPos += 2; uint copyLen = 0; if ((b1 >> 4) == 0) { copyLen = (uint)src[srcPos] + 0x12; srcPos++; } else { copyLen = (uint)(b1 >> 4) + 0x02; } uint dist = (uint)((b1 & 0x0F) << 8 | b2) + 1; uint copyPos = dstPos - dist; finds.Add(new KeyValuePair <int, KeyValuePair <int, int> >((int)dstPos, new KeyValuePair <int, int>((int)copyPos, (int)copyLen))); for (int j = 0; j < copyLen; j++) { dst[dstPos] = dst[copyPos]; dstPos++; copyPos++; } } if (dstPos >= decompressedSize) { return(dst); } } } }
public static byte[] encode(byte[] src) { //find need compressed position uint curPos = 0; uint endPos = (uint)src.Length; List <KeyValuePair <uint, KeyValuePair <uint, uint> > > finds = new List <KeyValuePair <uint, KeyValuePair <uint, uint> > >(); while (curPos + 0x03 <= endPos) { var find = searchNextNCPoses(src, curPos, endPos); if (find[0].Value.Value != 0) { finds.AddRange(find); } curPos = find[find.Count - 1].Key + find[find.Count - 1].Value.Value; } //compress byte[] temp = new byte[src.Length + src.Length / 8]; uint writeLen = 0; uint srcPos = 0; uint dstPos = 0x01; uint opcodePos = 0; uint cycle = 0x00; foreach (var find in finds) { //write data that does not need to be compressed while (srcPos < find.Key) { if (cycle == 8) { opcodePos = dstPos; dstPos++; cycle = 0x00; } temp[opcodePos] = (byte)(temp[opcodePos] | 0x80 >> (int)cycle); cycle++; temp[dstPos] = src[srcPos]; dstPos++; srcPos++; } //write data that need to compressed if (cycle == 8) { opcodePos = dstPos; dstPos++; cycle = 0x00; } cycle++; uint findLen = find.Value.Value; uint findPos = find.Value.Key; uint pos = find.Key; uint dist = pos - findPos - 1; if (findLen < 0x12) { byte b1 = (byte)((findLen - 2) << 4 | dist >> 8); byte b2 = (byte)(dist & 0xFF); temp[dstPos] = b1; temp[dstPos + 1] = b2; dstPos += 2; } else { byte b1 = (byte)(dist >> 8); byte b2 = (byte)(dist & 0xFF); byte b3 = (byte)(findLen - 0x12); temp[dstPos] = b1; temp[dstPos + 1] = b2; temp[dstPos + 2] = b3; dstPos += 3; } srcPos += findLen; } //write data that does not need to be compressed while (srcPos < src.Length) { if (cycle == 8) { opcodePos = dstPos; dstPos++; cycle = 0x00; } temp[opcodePos] = (byte)(temp[opcodePos] | 0x80 >> (int)cycle); cycle++; temp[dstPos] = src[srcPos]; dstPos++; srcPos++; } writeLen = dstPos; byte[] ret = new byte[writeLen + 0x10]; EndianBytesOperator.writeString(ret, 0, "Yaz0", 4); EndianBytesOperator.writeUInt(ret, 0x04, (uint)src.Length); for (int i = 0; i < writeLen; i++) { ret[i + 0x10] = temp[i]; } return(ret); }