Beispiel #1
0
        public static FreeSpaceAnalyzeResult Analyze(List <PatchedByteArray> innerPatches, PatchRange freeSpaceRange, bool isSorted = true)
        {
            if (!isSorted)
            {
                innerPatches = new List <PatchedByteArray>(innerPatches);
                innerPatches.Sort(
                    delegate(PatchedByteArray patchedByteArray1, PatchedByteArray patchedByteArray2)
                {
                    return(patchedByteArray1.Offset.CompareTo(patchedByteArray2.Offset));
                }
                    );
            }

            FreeSpaceAnalyzeResult result = new FreeSpaceAnalyzeResult();

            result.ConflictIndexes = new HashSet <int>();

            if (innerPatches.Count == 0)
            {
                return(result);
            }

            result.LargestGapOffset = (int)freeSpaceRange.StartOffset;
            result.LargestGapSize   = (int)(innerPatches[0].Offset - freeSpaceRange.StartOffset);

            int endIndex = innerPatches.Count - 1;

            for (int index = 0; index < endIndex; index++)
            {
                PatchedByteArray patchedByteArray = innerPatches[index];
                int  length            = patchedByteArray.GetBytes().Length;
                long nextAddress       = patchedByteArray.Offset + length;
                long nextPatchLocation = innerPatches[index + 1].Offset;
                long spaceToNextPatch  = nextPatchLocation - nextAddress;

                if (spaceToNextPatch > result.LargestGapSize)
                {
                    result.LargestGapOffset = (int)nextAddress;
                    result.LargestGapSize   = (int)spaceToNextPatch;
                }

                if ((innerPatches[index + 1].Offset - nextAddress) < 0)
                {
                    if (innerPatches[index].HasConflict(innerPatches[index + 1]))
                    {
                        result.HasConflicts = true;
                        result.ConflictIndexes.Add(index);
                    }
                }
            }

            int finalNextAddress = (int)(innerPatches[endIndex].Offset + innerPatches[endIndex].GetBytes().Length);
            int endGapSize       = (int)(freeSpaceRange.EndOffset - finalNextAddress);

            if (endGapSize > result.LargestGapSize)
            {
                result.LargestGapOffset = finalNextAddress;
                result.LargestGapSize   = endGapSize;
            }

            return(result);
        }
        public static ConflictResolveResult ResolveConflicts(IList <AsmPatch> patchList, ASMEncoding.ASMEncodingUtility asmUtility, int maxConflictResolveAttempts = MaxConflictResolveAttempts)
        {
            List <AsmPatch>            resultPatchList = new List <AsmPatch>();
            Dictionary <AsmPatch, int> patchIndexMap   = new Dictionary <AsmPatch, int>();
            StringBuilder sbMessage    = new StringBuilder();
            bool          hasConflicts = false;

            for (int index = 0; index < patchList.Count; index++)
            {
                resultPatchList.Add(patchList[index]);
                patchIndexMap.Add(patchList[index], index);
            }

            Context       context       = (asmUtility.EncodingMode == ASMEncoding.ASMEncodingMode.PSP) ? Context.US_PSP : Context.US_PSX;
            FreeSpaceMode mode          = FreeSpace.GetMode(context);
            FreeSpaceMaps freeSpaceMaps = FreeSpace.GetFreeSpaceMaps(resultPatchList, mode);

            foreach (PatchRange freeSpaceRange in freeSpaceMaps.PatchRangeMap.Keys)
            {
                List <PatchedByteArray> innerPatches  = freeSpaceMaps.PatchRangeMap[freeSpaceRange];
                FreeSpaceAnalyzeResult  analyzeResult = FreeSpace.Analyze(innerPatches, freeSpaceRange, true);
                int conflictResolveAttempts           = 0;

                /*
                 * Type sectorType = ISOHelper.GetSectorType(context);
                 * Enum sector = (Enum)Enum.ToObject(sectorType, freeSpaceRange.Sector);
                 * string strSector = (mode == FreeSpaceMode.PSP) ? PspIso.GetSectorName((PspIso.Sectors)sector) : PsxIso.GetSectorName((PsxIso.Sectors)sector);
                 */

                string strSector = ISOHelper.GetSectorName(freeSpaceRange.Sector, context);

                while ((analyzeResult.HasConflicts) && (conflictResolveAttempts < maxConflictResolveAttempts))
                {
                    bool isStatic   = false;
                    bool stayStatic = false;

                    int endIndex = innerPatches.Count - 1;
                    for (int index = 0; index < endIndex; index++)
                    {
                        PatchedByteArray innerPatch = innerPatches[index];
                        isStatic   = innerPatch.IsStatic || stayStatic;
                        stayStatic = (innerPatch.IsStatic) && (innerPatch.IsPatchEqual(innerPatches[index + 1]));

                        if ((analyzeResult.ConflictIndexes.Contains(index)) && (!isStatic))
                        {
                            long           moveOffset     = analyzeResult.LargestGapOffset - innerPatch.Offset;
                            MovePatchRange movePatchRange = new MovePatchRange(new PatchRange(innerPatch), moveOffset);

                            AsmPatch asmPatch         = freeSpaceMaps.InnerPatchMap[innerPatch];
                            int      resultPatchIndex = patchIndexMap[asmPatch];
                            patchIndexMap.Remove(asmPatch);

                            asmPatch = asmPatch.Copy();
                            resultPatchList[resultPatchIndex] = asmPatch;
                            patchIndexMap.Add(asmPatch, resultPatchIndex);
                            asmPatch.MoveBlock(asmUtility, movePatchRange);
                            asmPatch.Update(asmUtility);

                            sbMessage.AppendLine("Conflict resolved by moving segment of patch \"" + asmPatch.Name + "\" in sector " + strSector + " from offset "
                                                 + innerPatch.Offset.ToString("X") + " to " + analyzeResult.LargestGapOffset.ToString("X") + ".");

                            freeSpaceMaps = FreeSpace.GetFreeSpaceMaps(resultPatchList, mode);
                            innerPatches  = freeSpaceMaps.PatchRangeMap[freeSpaceRange];
                            analyzeResult = FreeSpace.Analyze(innerPatches, freeSpaceRange, false);
                            conflictResolveAttempts++;
                            break;
                        }
                    }
                }

                if (analyzeResult.HasConflicts)
                {
                    hasConflicts = true;
                    int endIndex = innerPatches.Count - 1;
                    for (int index = 0; index < endIndex; index++)
                    {
                        if (analyzeResult.ConflictIndexes.Contains(index))
                        {
                            sbMessage.Length = 0;
                            sbMessage.AppendLine("Conflict in sector " + strSector + " at offset " + innerPatches[index].Offset.ToString("X") + "!");
                            break;
                        }
                    }
                }
            }

            return(new ConflictResolveResult(resultPatchList, hasConflicts, sbMessage.ToString()));
        }