public static void ParseUVTRs(byte[] romBytes) { //Directory.CreateDirectory(outputDir + "Converted"); //string fullOutputPath = outputDir + "Converted/UVTR/"; //Directory.CreateDirectory(fullOutputPath); // ok this is dumb i need to fix this Filesystem.Filesystem filesystem = new Filesystem.Filesystem(romBytes); foreach (Filesystem.Filesystem.File file in filesystem.AllFiles.Where(file => file.fileTypeFromFileHeader == "UVTR")) { PowerByteArray data = new PowerByteArray(file.Section("COMM")); UVTR uvtr = new UVTR(); uvtr.h_6float = data.NextSubArray(24).AsFloats(); uvtr.h_b1 = data.NextU8(); uvtr.h_b2 = data.NextU8(); uvtr.h_f1 = data.NextFloat(); uvtr.h_f2 = data.NextFloat(); uvtr.h_f3 = data.NextFloat(); using (ThreeDDisplayWindow window = new ThreeDDisplayWindow()) { Console.WriteLine(uvtr.h_b1 * uvtr.h_b2); uvtr.pB1xB2Mem = new UVTR140Struct[uvtr.h_b1 * uvtr.h_b2]; for (int i = 0; i < uvtr.pB1xB2Mem.Length; i++) { UVTR140Struct oneFourty = new UVTR140Struct(); if (data.NextU8() == 0) { continue; } oneFourty.m1 = new Matrix(data.NextSubArray(64).AsFloats()); byte unkByte = data.NextU8(); // m2 = identity matrix oneFourty.m2 = new Matrix(new float[] { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }); // Copy translation from m1 to m2 oneFourty.m2[12] = oneFourty.m1[12]; oneFourty.m2[13] = oneFourty.m1[13]; oneFourty.m2[14] = oneFourty.m1[14]; /* FUN_801360cc(m2, m2) */ Console.WriteLine(oneFourty.m1); oneFourty.uvctFileIndex = data.NextU16(); var uvct = filesystem.GetFile("UVCT", oneFourty.uvctFileIndex); Console.WriteLine($"{uvct.formLocationInROM:x6}"); var uvctFile = new UVCTFile(new PowerByteArray(uvct.Section("COMM")), filesystem); uvctFile.AddToWindow(window, oneFourty.m1); /* oneFourty.pUVCT = processed filesystem.GetFile("UVCT", oneFourty.uvctFileIndex); */ /* if uvct does not exist, set oneFourty.unkFloat to 0 and move to next loop*/ /* at this point some stuff happens with the UVCT, idk what exactly */ uvtr.pB1xB2Mem[i] = oneFourty; } window.Run(); } uvtr.ushort1 = data.NextU16(); uvtr.uvrwFileIndex = data.NextU16(); /* * if (DAT_8002d1a8 == 0) { * uvtrObj->ushort1 = 0; * uVar1 = uvtrObj->ushort1; * } * else { * uVar1 = uvtrObj->ushort1; * } */ if (uvtr.ushort1 != 0) { /* Load UVRW COMM section */ uvtr.unk4Bytes = data.NextU32(); data.NextU16(); data.NextU16(); data.NextU16(); /* a whole bunch of nonsense */ /* includes reading a few more shorts (maybe) */ } } }
public UVMDFile(PowerByteArray fileBytes, Filesystem.Filesystem filesystem) { Console.WriteLine("NEW UVMD"); { lodCount = fileBytes.NextU8(); partsPerLOD = fileBytes.NextU8(); b3 = fileBytes.NextU8(); byte alwaysZero = fileBytes.NextU8(); if (alwaysZero != 0) { throw new Exception(); } vertexCount = fileBytes.NextU16(); // These are here for memory allocation, but we don't care! ushort totalMaterials = fileBytes.NextU16(); //24 structs ushort totalCommands = fileBytes.NextU16(); if ((b3 & 0x80) != 0) { // appears to be 10 floats, 3 signed shorts, 1 byte // TODO UnknownOptionalHeaderData unknownOptionalData = new UnknownOptionalHeaderData(fileBytes.NextSubArray(0x2F)); } float1 = fileBytes.NextFloat(); float2 = fileBytes.NextFloat(); float3 = fileBytes.NextFloat(); } // Lets allocate all memory here since this is where it happens anyway // 36 bytes: already done, that's the response struct // b1 * 12: subsections pLODs = new LOD[lodCount]; // b2 * 64: matrices pMatrices = new Matrix[partsPerLOD]; // b1 * b2 * 44: parts // this is initialized in the loop // short1 * 16 // this is initialized in the loop // short2 * 24 // this is initialized in the loop // short3 * 8 // this is initialized in the loop //////////////////////////////// // Overall structure here is correct, but the processing is not implemented yet for (int i = 0; i < lodCount; i++) { Console.WriteLine(" LOD " + i); LOD lodInfo; lodInfo.partCount = fileBytes.NextU8(); lodInfo.b2 = fileBytes.NextU8(); lodInfo.f = fileBytes.NextFloat(); lodInfo.f = lodInfo.f * lodInfo.f; lodInfo.pModelParts = new ModelPart[lodInfo.partCount]; for (int j = 0; j < lodInfo.partCount; j++) { Console.WriteLine(" PART " + j); ModelPart modelPart; modelPart.b5 = fileBytes.NextU8(); modelPart.b6 = fileBytes.NextU8(); modelPart.b7 = fileBytes.NextU8(); modelPart.sixFloats = fileBytes.NextSubArray(24).AsFloats(); modelPart.sixFloats = modelPart.sixFloats.Select(fl => fl * float2).ToArray(); byte stackByte1 = fileBytes.NextU8(); byte stackByte2 = fileBytes.NextU8(); modelPart.materialCount = fileBytes.NextU8(); modelPart.pMaterials = new Material[modelPart.materialCount]; byte firstWordEverHadHighBitSet = 0; for (int k = 0; k < modelPart.materialCount; k++) { Console.WriteLine(" MATERIAL " + k); Material material = new Material(); material.unk4 = fileBytes.NextU32(); float unk2 = fileBytes.NextFloat(); float unk3 = fileBytes.NextFloat(); float unk4 = fileBytes.NextFloat(); material.vertCount = fileBytes.NextU16(); material.unksh18 = fileBytes.NextU16(); material.unksh16 = fileBytes.NextU16(); material.unksh20 = fileBytes.NextU16(); ushort shortsCount = fileBytes.NextU16(); ushort commandCount = fileBytes.NextU16(); uint textureRef = material.unk4 & 0xFFF; Console.WriteLine($" {material.unk4:X8}"); if (textureRef != 0xFFF) { //Filesystem.Filesystem.File textureFile = filesystem.GetFile("UVTX", (int)textureRef); // TODO: load texture Console.WriteLine(" Textured!"); } if ((int)(material.unk4 << 13) < 0) { //Console.WriteLine($"{twentyFourStruct.unk4:X8} {twentyFourStruct.unk4 << 13:X8}"); // TODO: lighting information? // twentyFourStruct.unksh12 = response from light function Console.WriteLine(" Lit!"); } else { material.unk_someLightingThing = -1; } if ((material.unk4 & 0x08_000000) != 0) { firstWordEverHadHighBitSet = 1; } material.pVertices = fileBytes.NextSubArray(material.vertCount * 16).InGroupsOf(16).Select(d => new Vertex(d)).ToArray(); if (textureRef != 0xFFF) { foreach (var x in material.pVertices) { Console.WriteLine(x); } } RSPCommand[] commands = UnpackTriangleCommands(fileBytes, shortsCount, commandCount); material.pCommandsInRDRAM = commands; modelPart.pMaterials[k] = material; } modelPart.unk1 = firstWordEverHadHighBitSet; lodInfo.pModelParts[j] = modelPart; } pLODs[i] = lodInfo; } for (int m = 0; m < partsPerLOD; m++) { pMatrices[m] = new Matrix(fileBytes.NextSubArray(64).AsFloats()); } if (fileBytes.Length != (int)Math.Ceiling(fileBytes.Position / 8f) * 8) { throw new Exception(); } //////////////////////////////// using (ThreeDDisplayWindow window = new ThreeDDisplayWindow()) { foreach (LOD lod in pLODs) { bool hadTextured = false; for (int i = 0; i < lod.partCount; i++) { ModelPart part = lod.pModelParts[i]; Matrix m = pMatrices[i]; foreach (Material material in part.pMaterials) { List <Vertex> verts = MaterialToVertexData(material.pVertices, material.pCommandsInRDRAM, m); uint textureRef = material.unk4 & 0xFFF; if (textureRef != 0xFFF) { Filesystem.Filesystem.File textureFile = filesystem.GetFile("UVTX", (int)textureRef) !; Console.WriteLine($"{textureFile.formLocationInROM:x6}"); window.AddTexturedVertices(verts, new UVTX.UVTXFile(textureFile.Section("COMM"))); hadTextured = true; } else { window.AddVertices(verts); } } //lodData.AddRange(part.pMaterials.SelectMany(material => MaterialToVertexData(material.pVertices, material.pCommandsInRDRAM, m))); } if (hadTextured) { window.Run(); } } } }