Пример #1
0
        public static BCMFile FromUassetFile(string fileName)
        {
            byte[] fileBytes = File.ReadAllBytes(fileName);

            byte[] UassetHeaderBytes = GetUassetHeader(fileBytes);
            fileBytes = CreateGameBCMFromFile(fileBytes);

               List<Move> MoveList = new List<Move>();
               List<CancelList> CancelLists = new List<CancelList>();
               List<Input> InputList = new List<Input>();
               List<Charge> ChargeList = new List<Charge>();

            Debug.WriteLine("READING");
            using (var ms = new MemoryStream(fileBytes))
            using (var inFile = new BinaryReader(ms))
            {
                string bcmString = new string(inFile.ReadChars(4));

                if (bcmString != "#BCM")
                {
                    throw new Exception("Error: Not a valid KWBCM file!");
                }

                Debug.WriteLine(bcmString);

                inFile.BaseStream.Seek(0xC, SeekOrigin.Begin);

                short ChargeCount = inFile.ReadInt16();
                Debug.WriteLine("ChargeCount: " + ChargeCount);
                short InputCount = inFile.ReadInt16();
                Debug.WriteLine("InputCount: " + InputCount);
                short MoveCount = inFile.ReadInt16();
                Debug.WriteLine("Movecount: " + MoveCount);
                short CancelCount = inFile.ReadInt16(); //last cancel index
                Debug.WriteLine("Cancelcount: " + CancelCount);

                int startOfCharges = inFile.ReadInt32();
                int startOfInputs = inFile.ReadInt32();
                int startOfMoves = inFile.ReadInt32();
                int startOfNames = inFile.ReadInt32();
                int startOfCancelLists = inFile.ReadInt32();
                Debug.WriteLine("StartOfCharges: " + startOfCharges);
                Debug.WriteLine("StartOfInputs: " + startOfInputs);

                Debug.WriteLine("StartOfMoves: " + startOfMoves);
                Debug.WriteLine("StartOfNames: " + startOfNames);

                Debug.WriteLine("StartOfCancelLists: " + startOfCancelLists);

                Debug.WriteLine("Current pos: " + inFile.BaseStream.Position.ToString("X"));
                Debug.WriteLine("\n\n");

                inFile.BaseStream.Seek(startOfCharges, SeekOrigin.Begin);

                List<int> ChargeAddresses = new List<int>();

                for (int i = 0; i < ChargeCount; i++)
                {
                    ChargeAddresses.Add(inFile.ReadInt32());
                }

                for (int i = 0; i < ChargeAddresses.Count; i++)
                {
                    Charge thisCharge = new Charge();
                    int thisChargeAddress = ChargeAddresses[i];
                    inFile.BaseStream.Seek(thisChargeAddress, SeekOrigin.Begin);
                    Debug.WriteLine("ChargeAddress: " + thisChargeAddress.ToString("X"));

                    thisCharge.ChargeDirection = inFile.ReadInt16();
                    thisCharge.Unknown1 = inFile.ReadInt16();
                    thisCharge.Unknown2 = inFile.ReadInt16();
                    thisCharge.Unknown3 = inFile.ReadInt16();
                    thisCharge.ChargeFrames = inFile.ReadInt16();
                    thisCharge.Flags = inFile.ReadInt16();
                    thisCharge.ChargeIndex = inFile.ReadInt16();
                    thisCharge.Unknown4 = inFile.ReadInt16();

                    thisCharge.Index = i;
                    ChargeList.Add(thisCharge);
                }

                inFile.BaseStream.Seek(startOfInputs, SeekOrigin.Begin);

                List<int> InputAddresses = new List<int>();

                for (int i = 0; i < InputCount; i++)
                {
                    InputAddresses.Add(inFile.ReadInt32());
                }

                for (int i = 0; i < InputAddresses.Count; i++)
                {
                    Input thisInput = new Input();
                    int thisInputAddress = InputAddresses[i];
                    inFile.BaseStream.Seek(thisInputAddress, SeekOrigin.Begin);
                    Debug.WriteLine("InputAddress: " + thisInputAddress.ToString("X"));

                    List<int> moveEntryOffsets = new List<int>();

                    moveEntryOffsets.Add(inFile.ReadInt32());
                    moveEntryOffsets.Add(inFile.ReadInt32());
                    moveEntryOffsets.Add(inFile.ReadInt32());
                    moveEntryOffsets.Add(inFile.ReadInt32());

                    var entries = new List<InputEntry>();

                    foreach (var entryOffset in moveEntryOffsets)
                    {
                        if (entryOffset == 0)
                        {
                            entries.Add(new InputEntry());
                            continue;
                        }

                        inFile.BaseStream.Seek(entryOffset + thisInputAddress, SeekOrigin.Begin);
                        var partCount = inFile.ReadInt32();

                        InputEntry thisInputEntry = new InputEntry();
                        List<InputPart> parts = new List<InputPart>();

                        for (int j = 0; j < partCount; j++)
                        {
                            InputPart thisPart = new InputPart()
                            {
                                InputType = (InputType)inFile.ReadInt16(),
                                Buffer = inFile.ReadInt16(),
                                InputDirection = (InputDirection)inFile.ReadInt16(),
                                Unknown1 = inFile.ReadInt16(),
                                Unknown2 = inFile.ReadInt16(),
                                Unknown3 = inFile.ReadInt16(),
                                Unknown4 = inFile.ReadInt16(),
                                Unknown5 = inFile.ReadInt16(),
                            };

                            parts.Add(thisPart);
                        }

                        for (int j = 0; j < 16-partCount; j++) //There can be up to 16 parts, but even if they are empty they are still there, only filled with 0x00
                        {
                            var unused = inFile.ReadBytes(16);
                            foreach (var b in unused)
                            {
                                if (b != 0)
                                {
                                    Debug.WriteLine("Read unexpected byte in what was thought to be an empty part of an input.");
                                }
                            }
                        }

                        thisInputEntry.InputParts = parts.ToArray();
                        entries.Add(thisInputEntry);
                    }

                    thisInput.InputEntries = entries.ToArray();

                    thisInput.Index = i;
                    InputList.Add(thisInput);
                    Debug.WriteLine("Created input with index: " + i);
                }

                for (int i = 0; i < MoveCount*4; i+=0x4)
                {
                    long thisMovePosition = startOfMoves + i;
                    long thisNamePosition = startOfNames + i;

                    inFile.BaseStream.Seek(thisNamePosition, SeekOrigin.Begin);
                    int NameAddress = inFile.ReadInt32();
                    string Name = GetName(NameAddress, inFile);

                    inFile.BaseStream.Seek(thisMovePosition, SeekOrigin.Begin);
                    int offset = inFile.ReadInt32();
                    Debug.WriteLine("Adding move at: " + offset.ToString("X"));

                    inFile.BaseStream.Seek(offset, SeekOrigin.Begin);

                    short input = inFile.ReadInt16();
                    short inputFlags = inFile.ReadInt16();
                    int restrict = inFile.ReadInt32();
                    int restrict2 = inFile.ReadInt32();
                    float restrictDistance = inFile.ReadSingle();
                    int projectileRestrict = inFile.ReadInt32();
                    int unknown6 = inFile.ReadInt16();
                    int unknown7 = inFile.ReadInt16();
                    short unknown8 = inFile.ReadInt16();
                    short unknown9 = inFile.ReadInt16();

                    short MeterRequirement = inFile.ReadInt16();
                    short MeterUsed = inFile.ReadInt16();
                    short unknown10 = inFile.ReadInt16();
                    short unknown11 = inFile.ReadInt16();
                    int VtriggerRequirement = inFile.ReadInt16();
                    int VtriggerUsed = inFile.ReadInt16();
                    int Unknown16 = inFile.ReadInt32();
                    int InputMotionIndex = inFile.ReadInt16();
                    int ScriptIndex = inFile.ReadInt16();

                    Move thisMove = new Move()
                    {
                        Name = Name,
                        Index = (short)(i == 0 ? 0 : (i / 4)),
                        Input = input,
                        InputFlags = inputFlags,
                        PositionRestriction = restrict,
                        Unknown3 = restrict2,
                        RestrictionDistance = restrictDistance,
                        ProjectileLimit = projectileRestrict,
                        Unknown6 = (short)unknown6,
                        Unknown7 = (short)unknown7,
                        Unknown8 = unknown8,
                        Unknown9 = unknown9,
                        Unknown10 = unknown10,
                        Unknown11 = unknown11,
                        MeterRequirement =  (short)MeterRequirement,
                        MeterUsed = (short)MeterUsed,
                        VtriggerRequirement = (short)VtriggerRequirement,
                        VtriggerUsed = (short)VtriggerUsed,
                        Unknown16 = Unknown16,
                        InputMotionIndex = (short)InputMotionIndex,
                        ScriptIndex = (short)ScriptIndex,
                        Unknown17 = inFile.ReadInt32(),
                        Unknown18 = inFile.ReadInt32(),
                        Unknown19 = inFile.ReadInt32(),
                        Unknown20 = inFile.ReadSingle(),
                        Unknown21 = inFile.ReadSingle(),
                        Unknown22 = inFile.ReadInt32(),
                        Unknown23 = inFile.ReadInt32(),
                        Unknown24 = inFile.ReadInt32(),
                        Unknown25 = inFile.ReadInt32(),
                        Unknown26 = inFile.ReadInt16(),
                        Unknown27 = inFile.ReadInt16(),
                        Unknown28 = inFile.ReadInt32()
                    };

                    if (thisMove.InputMotionIndex != -1) //Just for debugging...
                    {
                        InputList.Where(x => x.Index == thisMove.InputMotionIndex).ToList()[0].Name += thisMove.Name + ", ";
                    }

                    MoveList.Add(thisMove);

                    Debug.WriteLine("MOVE: " + "Index: " + (i == 0 ? 0 : (i/4)) +
                                    "\nName: " + Name +
                                    "\nOffset: " + offset.ToString("X") +
                                    "\nNameOffet: " + NameAddress.ToString("X") +
                                    "\nInput: " + input +
                                    "\nflags: " + inputFlags
                                    + "\nRestrict: " + restrict
                                    + "\nRestrict2: " + restrict2
                                    + "\nRestrictDistance: " + restrictDistance
                                    + "\nProjectileRestrict: " + projectileRestrict
                                    + "\nUnknown6: " + unknown6
                                    + "\nUnknown7: " + unknown7
                                    + "\nUnknown8: " + unknown8
                                    + "\nUnknown9: " + unknown9
                                    + "\nUnknown10: " + unknown10
                                    + "\nUnknown11: " + unknown11
                                    + "\nMeterReq: " + MeterRequirement
                                    + "\nMeterUsed: " + MeterUsed
                                    + "\nVtriggerReq: " + VtriggerRequirement
                                    + "\nVtriggerUsed: " + VtriggerUsed
                                    + "\nUnknown16: " + Unknown16
                                    + "\nInputMotionIndex: " + InputMotionIndex
                                    + "\nScriptIndex: " + ScriptIndex
                                    +"\nUnknown17: " + thisMove.Unknown17
                                    + "\nUnknown18: " + thisMove.Unknown18
                                    + "\nUnknown19: " + thisMove.Unknown19
                                    + "\nUnknown20: " + thisMove.Unknown20
                                    + "\nUnknown21: " + thisMove.Unknown21
                                    + "\nUnknown22: " + thisMove.Unknown22
                                    + "\nUnknown23: " + thisMove.Unknown23
                                    + "\nUnknown24: " + thisMove.Unknown24
                                    + "\nUnknown25: " + thisMove.Unknown25
                                    + "\nUnknown26: " + thisMove.Unknown26
                                    + "\nUnknown27: " + thisMove.Unknown27
                                    + "\nUnknown28: " + thisMove.Unknown28
                                    + "\n\n");
                }

                inFile.BaseStream.Seek(startOfCancelLists, SeekOrigin.Begin);
                List<int> CancelAddresses = new List<int>();
                for (int i = 0; i < CancelCount; i++)
                {
                    int thisCancelAddress = inFile.ReadInt32();
                    Debug.WriteLine("Cancel " + (i) + ": " + thisCancelAddress.ToString("X"));
                    CancelAddresses.Add(thisCancelAddress);
                }

                for (int i = 0; i < CancelAddresses.Count; i++)
                {
                    CancelList thisCancelList = new CancelList();
                    int thisAddress = CancelAddresses[i];

                    if (thisAddress == 0)
                    {
                        CancelLists.Add(new CancelList());
                        continue;
                    }

                    inFile.BaseStream.Seek(thisAddress, SeekOrigin.Begin);

                    thisCancelList.Unknown1 = inFile.ReadInt32();
                    int MovesInList = inFile.ReadInt32();
                    int LastIndex = inFile.ReadInt32(); //last move index in list -1...
                    int StartOffset = inFile.ReadInt32(); //offset until real list FROM START OF CANCEL!!!
                    int StartOfCancelInts = inFile.ReadInt32();
                    int StartOfCancelBytes = inFile.ReadInt32();

                    Debug.WriteLine("ThisCancelAddress: " + thisAddress.ToString("X"));
                    Debug.WriteLine("Cancel {6}:\nCU1: {0}\nMovesInList: {1}\nNumberOfSomethingInList: {2}\nStartOffset: {3}\nCU5: {4}\nEndOffset: {5}\n", thisCancelList.Unknown1, MovesInList, LastIndex, StartOffset.ToString("X"), StartOfCancelInts.ToString("X"), StartOfCancelBytes.ToString("X"), i);

                    inFile.BaseStream.Seek(thisAddress + StartOffset, SeekOrigin.Begin);
                    Debug.WriteLine("ListAddress: " + (thisAddress + StartOffset).ToString("X"));
                    Debug.WriteLine("ListAddressEnd: " + (thisAddress + StartOfCancelBytes).ToString("X"));

                    List<Cancel> cancels = new List<Cancel>();
                    thisCancelList.Index = i;

                    for (int j = 0; j < MovesInList; j++)
                    {
                        int thisMoveInList = inFile.ReadInt16();
                        Debug.WriteLine("Move: " + thisMoveInList);

                        Move cancelMove = MoveList.Where(x => x.Index == thisMoveInList).ToList()[0];

                        Cancel thisCancel = new Cancel();
                        thisCancel.Index = (short)thisMoveInList;
                        thisCancel.Name = cancelMove.Name;
                        thisCancel.ScriptIndex = cancelMove.ScriptIndex;

                        cancels.Add(thisCancel);
                    }

                    thisCancelList.Cancels = cancels.ToArray();

                    //All lists should have Moves divisible by 2. If it doesn't, simply add an empty one (0x00, 0x00)
                    if (MovesInList % 2 != 0)
                    {
                        Debug.WriteLine("READING EMPTY MOVE");
                        inFile.ReadInt16();
                    }

                    if (StartOfCancelInts != 0)
                    {
                        Debug.WriteLine("We got something!!!" + inFile.BaseStream.Position.ToString("X") + " - Should be: " + (thisAddress + StartOfCancelInts).ToString("X"));
                        Debug.WriteLine(((thisAddress + StartOfCancelBytes) - (thisAddress + StartOfCancelInts)) / MovesInList);

                        for (int j = 0; j < MovesInList; j++)
                        {
                            int value1 = inFile.ReadInt32();
                            int value2 = inFile.ReadInt32();

                            thisCancelList.Cancels[j].CancelInts = new CancelInts()
                            {
                                Unknown1 = value1,
                                Unknown2 = value2
                            };
                        }
                    }

                    Debug.WriteLine("Position is " + inFile.BaseStream.Position.ToString("X") + " - Should be: " + (thisAddress + StartOfCancelBytes).ToString("X"));

                    if (inFile.BaseStream.Position != thisAddress + StartOfCancelBytes) //NOT a good idea
                    {
                        Debug.WriteLine("We are not where we're supposed to be, reading bytes until we are...");

                        while (inFile.BaseStream.Position != thisAddress + StartOfCancelBytes)
                        {
                            Debug.WriteLine(inFile.ReadByte());
                        }

                        Debug.WriteLine("Position is " + inFile.BaseStream.Position.ToString("X") + " - Should be: " + (thisAddress + StartOfCancelBytes).ToString("X"));
                    }

                    for (int j = 0; j < LastIndex; j++)
                    {
                        inFile.BaseStream.Seek((thisAddress + StartOfCancelBytes) + (j * 4), SeekOrigin.Begin);

                        var offset = inFile.ReadInt32();

                        if (offset == 0)
                        {
                            continue;
                        }

                        Debug.WriteLine("SomethingElseInCancelList(offsets?): " + offset.ToString("X") + " Pos: " + (inFile.BaseStream.Position - 4).ToString("X") + " - Index: " + j + "  added offset:" + (offset+thisAddress).ToString("X"));

                        var address = offset + thisAddress;

                        inFile.BaseStream.Seek(address, SeekOrigin.Begin);

                        var cancelBytesBelongsTo = thisCancelList.Cancels.First(x => x.Index == j);

                        cancelBytesBelongsTo.UnknownBytes = inFile.ReadBytes(0x24);
                    }

                    CancelLists.Add(thisCancelList);
                    Debug.WriteLine("\n");
                }

                foreach (var cancelList in CancelLists)
                {
                    if (cancelList.Cancels == null)
                    {
                        continue;
                    }

                    foreach (var cancel in cancelList.Cancels)
                    {
                        if (cancel == null)
                        {
                            continue;
                        }
                        Debug.WriteLine("Cancel: " + cancel.Index + " ScriptIndex:" + cancel.ScriptIndex);
                        foreach (var unknownByte in cancel.UnknownBytes)
                        {
                            Debug.Write(unknownByte.ToString("X") + " ");
                        }
                        Debug.WriteLine("");
                    }
                }

                Debug.WriteLine("\nCharges\n");

                foreach (var charge in ChargeList)
                {
                    Debug.WriteLine("CHARGE: " + charge.Index);
                    Debug.WriteLine("Dir: " + charge.ChargeDirection);
                    Debug.WriteLine("u1: " + charge.Unknown1);
                    Debug.WriteLine("u2: " + charge.Unknown2);
                    Debug.WriteLine("u3: " + charge.Unknown3);
                    Debug.WriteLine("ChargeFrames: " + charge.ChargeFrames);
                    Debug.WriteLine("Flags: " + charge.Flags);
                    Debug.WriteLine("CINDEX: " + charge.ChargeIndex);
                    Debug.WriteLine("u4: " + charge.Unknown4);
                    Debug.WriteLine("\n");
                }

                foreach (var input in InputList)
                {
                    Debug.WriteLine("Input: " + input.Index);
                    Debug.WriteLine("Name: " + input.Name);
                    Debug.WriteLine("Entries: " + input.InputEntries.Length);

                    WriteInputToDebug(input);

                    Debug.WriteLine("\n");
                }
            }

            Debug.WriteLine("Done");

            BCMFile bcm = new BCMFile()
            {
                Inputs = InputList.ToArray(),
                CancelLists = CancelLists.ToArray(),
                Charges = ChargeList.ToArray(),
                Moves = MoveList.ToArray(),
                RawUassetHeaderDontTouch = UassetHeaderBytes
            };

            return bcm;
        }