Files
2025-12-14 19:11:45 -07:00

735 lines
30 KiB
C#

using Microsoft.VisualBasic;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using XboxToolkit;
using XboxToolkit.Interface;
namespace XboxToolkitTest
{
internal class Program
{
//public static bool GetSecuritySectorsFromXiso(ContainerReader input, bool compareMode, out HashSet<uint> securitySectors)
//{
// securitySectors = new HashSet<uint>();
// var decoder = input.GetDecoder();
// var xgdInfo = decoder.GetXgdInfo();
// for (var j = 12544; j < 16640; j++)
// {
// if (decoder.TryReadSector(j, out var sectorData2) == false)
// {
// return false;
// }
// var isEmptySector = true;
// for (var i = 0; i < sectorData2.Length; i++)
// {
// if (sectorData2[i] != 0)
// {
// isEmptySector = false;
// break;
// }
// }
// }
// var flag = false;
// var start = 0U;
// var totalSectors = decoder.TotalSectors();
// for (uint sectorIndex = xgdInfo.BaseSector; sectorIndex <= totalSectors; sectorIndex++)
// {
// if (decoder.TryReadSector(sectorIndex, out var sectorData) == false)
// {
// return false;
// }
// var isEmptySector = true;
// for (var i = 0; i < sectorData.Length; i++)
// {
// if (sectorData[i] != 0)
// {
// isEmptySector = false;
// break;
// }
// }
// var isDataSector = securitySectors.Contains(sectorIndex);
// if (isEmptySector == true && flag == false && !isDataSector)
// {
// start = sectorIndex;
// flag = true;
// }
// else if (isEmptySector == false && flag == true)
// {
// var end = sectorIndex - 1;
// flag = false;
// if (end - start == 0xFFF)
// {
// for (var i = start; i <= end; i++)
// {
// securitySectors.Add(i);
// }
// }
// else if (compareMode && end - start > 0xFFF) // if more than 0xFFF, we "guess" this image is scrubbed so we stop
// {
// return true;
// }
// }
// }
// return true;
//}
public static void ProcessPngs()
{
//var input = @"J:\FailedXEX";
var input = @"J:\XEXDump\XEXDump";
var output = @"J:\XEXDump\PNGS";
var files = Directory.GetFiles(input, "*.xex");
foreach (var file in files)
{
try
{
var defaultData = File.ReadAllBytes(file);
if (XexUtility.TryExtractXexMetaData(defaultData, out var metadata) == false)
{
File.Copy(file, $"J:\\FailedXEX\\{Path.GetFileName(file)}");
System.Diagnostics.Debug.Print($"Failed: {file}");
continue;
}
File.WriteAllBytes(Path.Combine(output, Path.GetFileNameWithoutExtension(file) + ".png"), metadata.Thumbnail);
}
catch (Exception ex)
{
File.Copy(file, $"J:\\FailedXEX\\{Path.GetFileName(file)}");
System.Diagnostics.Debug.Print(ex.ToString());
}
}
}
static void MainOld()
{
ProcessPngs();
var z = ContainerUtility.TryAutoDetectContainerType(@"U:\Done\Gun (USA) (En,Fr,Es,It).cci", out var cc);
{
var m = cc.TryMount();
var n = cc.TryGetDefault(out var defaultData2, out var container);
File.WriteAllBytes(@"J:\iso.xex", defaultData2);
var qq = XexUtility.TryExtractXexMetaData(defaultData2, out var metadata);
//XboxToolkit.ContainerUtility.ConvertContainerToCCI(cc, ProcessingOptions.All, @"J:\Army of Two (USA)\Army of Two (USA).cci", null);
//var x = ContainerUtility.ConvertContainerToCCI(isoContainer, ProcessingOptions.All, @"G:\Xbox360\Test\Fifa.cci", p =>
//{
// Console.WriteLine(p.ToString());
//});
var filePath3 = @"G:\Xbox360\Test\Fifa.cci";
using var CCIContainer = new CCIContainerReader(filePath3);
var q = CCIContainer.TryMount();
var xx = ContainerUtility.ExtractFilesFromContainer(CCIContainer, @"G:\Xbox360\Test3");
}
// var x = ContainerUtility.ConvertContainerToCCI(isoContainer, ProcessingOptions.All, @"G:\Xbox360\far cry.cci");
///3597756
//var cciContainer = new GODContainerReader(@"G:\Xbox360CCi's\Crysis.1.RF.X360-ZTM\45410968\00007000\801FA873A37D786F8DB0879D89FCEF5245");
// var cciContainer = new CCIContainerReader(@"G:\Xbox360\Crysis-trim.cci");
// var y = cciContainer.Mount();
// var q = cciContainer.TryGetDefault(out var d, out var xx);
////var x = ContainerUtility.ConvertContainerToISO(cciContainer, false, @"G:\Xbox360\Crysis.iso");
// var x = ContainerUtility.ConvertContainerToCCI(cciContainer, false, true, @"G:\Xbox360\Crysis-trim.cci");
//var isoContainer = new ISOContainerReader(@"G:\Xbox360\Crysis.iso");
//isoContainer.Mount();
//// var x = ContainerUtility.ConvertContainerToCCI(cciContainer, true, @"G:\Xbox360\Crysis.cci");
//isoContainer.TryGetDefault(out var xdefaultData, out var xcontainerType);
var isoTest = true;
var defaultData = Array.Empty<byte>();
var containerType = ContainerType.Unknown;
if (isoTest)
{
//var filePath = @"G:\Xbox360\Crysis.1.RF.X360-ZTM\45410968\00007000\801FA873A37D786F8DB0879D89FCEF5245";
//var filePath = @"G:\Xbox360\MEMORICK - KNIGHTS APPRENT (USA-PAL).iso";
//var filePath = @"G:\Xbox360\Barbie Horse Adventures - Wild Horse Rescue (USA).iso";
//var filePath = @"G:\Xbox360\Far Cry 3 (USA, Europe) (En,Fr,De,Es,It,Nl,Pt,Sv,No,Da).iso";
//var filePath = @"G:\Xbox360\007 Legends (USA) (En,Fr,De).iso";
//var filePath = @"G:\Xbox360\MEMORICK - KNIGHTS APPRENT (USA-PAL).iso";
var filePath = @"G:\Xbox360\Burnout Paradise (USA).iso";
using var xisoContainerUtility = new ISOContainerReader(filePath);
if (xisoContainerUtility.TryMount() == true && xisoContainerUtility.TryGetDefault(out defaultData, out containerType) == true)
{
//CCIUtility.ConvertContainerToCCI(xisoContainerUtility, false, @"G:\Xbox360\Burnout Paradise (USA)-noscrub.cci");
//CCIUtility.ConvertContainerToCCI(xisoContainerUtility, true, @"G:\Xbox360\Burnout Paradise (USA)-scrub.cci");
Console.WriteLine("Xiso format detected.");
}
else
{
using var godContainerUtility = new GODContainerReader(filePath);
if (godContainerUtility.TryMount() == true && godContainerUtility.TryGetDefault(out defaultData, out containerType) == true)
{
Console.WriteLine("God format detected.");
}
else
{
Console.WriteLine("Unrecognized file format.");
return;
}
}
}
else
{
defaultData = File.ReadAllBytes("default.xex");
}
var result = XexUtility.TryExtractXexMetaData(defaultData, out var metaData);
if (result == false)
{
Console.WriteLine("Failed.");
return;
}
Console.WriteLine($"GameRegion: {metaData.GameRegion}");
Console.WriteLine();
Console.WriteLine($"TitleName: {metaData.TitleName}");
Console.WriteLine();
Console.WriteLine($"TitleId: {metaData.TitleId}");
Console.WriteLine();
Console.WriteLine($"MediaId: {metaData.MediaId}");
Console.WriteLine();
Console.WriteLine($"Version: {metaData.Version}");
Console.WriteLine();
Console.WriteLine($"BaseVersion: {metaData.BaseVersion}");
Console.WriteLine();
Console.WriteLine($"DiscNum: {metaData.DiscNum}");
Console.WriteLine();
Console.WriteLine($"DiscTotal: {metaData.DiscTotal}");
Console.WriteLine();
Console.WriteLine($"Description: {metaData.Description}");
Console.WriteLine();
Console.WriteLine($"Developer: {metaData.Developer}");
Console.WriteLine();
Console.WriteLine($"Genre: {metaData.Genre}");
Console.WriteLine();
Console.WriteLine($"ThumbnailLength: {metaData.Thumbnail.Length}");
Console.WriteLine();
File.WriteAllBytes("thumb.png", metaData.Thumbnail);
Console.WriteLine("Success.");
}
static void Main()
{
// Skip directory structure test for now
// DirectoryStructureTest.TestDirectoryStructure();
// Console.WriteLine();
// Console.WriteLine("Press any key to continue to ISO test...");
// Console.ReadKey();
// Console.WriteLine();
TestFolderToISO();
Console.WriteLine();
Console.WriteLine("Press any key to continue to CCI test...");
Console.ReadKey();
Console.WriteLine();
TestFolderToCCI();
}
static void TestFolderToISO()
{
// Hardcoded folder path - change this to your test folder
var sourceFolder = @"E:\isotest\game";
var isoOutputPath = @"E:\isotest\TestFolder.iso";
var extractOutputPath = @"E:\isotest\TestFolder_Extracted";
var comparisonOutputPath = @"E:\isotest\TestFolder_Comparison.txt";
Console.WriteLine("=== Xbox Original ISO Creation and Verification Test ===");
Console.WriteLine();
// Step 1: Create ISO from folder
Console.WriteLine($"Step 1: Creating Xbox Original ISO from folder: {sourceFolder}");
if (!Directory.Exists(sourceFolder))
{
Console.WriteLine($"ERROR: Source folder does not exist: {sourceFolder}");
return;
}
// Get file info before creating ISO
var sourceFilesInfo = Directory.GetFiles(sourceFolder, "*", SearchOption.AllDirectories);
var sourceDirsInfo = Directory.GetDirectories(sourceFolder, "*", SearchOption.AllDirectories);
var totalSourceSize = sourceFilesInfo.Sum(f => new FileInfo(f).Length);
Console.WriteLine($"Source folder contains:");
Console.WriteLine($" {sourceFilesInfo.Length} files");
Console.WriteLine($" {sourceDirsInfo.Length} directories");
Console.WriteLine($" Total size: {totalSourceSize / 1024.0 / 1024.0:F2} MB");
Console.WriteLine();
// List all files and directories for debugging
Console.WriteLine("Source files:");
foreach (var file in sourceFilesInfo.OrderBy(f => f))
{
var relPath = Path.GetRelativePath(sourceFolder, file).Replace('\\', '/');
Console.WriteLine($" {relPath}");
}
Console.WriteLine();
Console.WriteLine("Source directories:");
foreach (var dir in sourceDirsInfo.OrderBy(d => d))
{
var relPath = Path.GetRelativePath(sourceFolder, dir).Replace('\\', '/');
Console.WriteLine($" {relPath}/");
}
Console.WriteLine();
var createSuccess = ContainerUtility.ConvertFolderToISO(
sourceFolder,
ISOFormat.XboxOriginal,
isoOutputPath,
0, // No split point
progress => Console.Write($"\rProgress: {progress:P2}")
);
Console.WriteLine();
if (!createSuccess)
{
Console.WriteLine("ERROR: Failed to create ISO file.");
return;
}
if (!File.Exists(isoOutputPath))
{
Console.WriteLine("ERROR: ISO file was not created.");
return;
}
var isoFileInfo = new FileInfo(isoOutputPath);
Console.WriteLine($"SUCCESS: ISO created at: {isoOutputPath}");
Console.WriteLine($"ISO file size: {isoFileInfo.Length / 1024.0:F2} KB ({isoFileInfo.Length / 1024.0 / 1024.0:F2} MB)");
Console.WriteLine($"Expected size (approx): {totalSourceSize / 1024.0 / 1024.0:F2} MB + overhead");
Console.WriteLine();
// Step 2: Extract files from ISO
Console.WriteLine($"Step 2: Extracting files from ISO to: {extractOutputPath}");
using var isoContainer = new ISOContainerReader(isoOutputPath);
if (!isoContainer.TryMount())
{
Console.WriteLine("ERROR: Failed to mount ISO container.");
return;
}
var extractSuccess = ContainerUtility.ExtractFilesFromContainer(isoContainer, extractOutputPath);
if (!extractSuccess)
{
Console.WriteLine("ERROR: Failed to extract files from ISO.");
return;
}
Console.WriteLine($"SUCCESS: Files extracted to: {extractOutputPath}");
Console.WriteLine();
// List extracted files for debugging
var extractedFilesInfo = Directory.GetFiles(extractOutputPath, "*", SearchOption.AllDirectories);
var extractedDirsInfo = Directory.GetDirectories(extractOutputPath, "*", SearchOption.AllDirectories);
Console.WriteLine($"Extracted folder contains:");
Console.WriteLine($" {extractedFilesInfo.Length} files");
Console.WriteLine($" {extractedDirsInfo.Length} directories");
Console.WriteLine();
Console.WriteLine("Extracted files:");
foreach (var file in extractedFilesInfo.OrderBy(f => f))
{
var relPath = Path.GetRelativePath(extractOutputPath, file).Replace('\\', '/');
Console.WriteLine($" {relPath}");
}
Console.WriteLine();
Console.WriteLine("Extracted directories:");
foreach (var dir in extractedDirsInfo.OrderBy(d => d))
{
var relPath = Path.GetRelativePath(extractOutputPath, dir).Replace('\\', '/');
Console.WriteLine($" {relPath}/");
}
Console.WriteLine();
// Step 3: Compare original and extracted files
Console.WriteLine("Step 3: Comparing original and extracted files...");
var comparisonResults = new List<string>();
var totalFiles = 0;
var matchingFiles = 0;
var mismatchedFiles = 0;
var missingFiles = 0;
var extraFiles = 0;
// Get all files from source folder
var sourceFilesList = Directory.GetFiles(sourceFolder, "*", SearchOption.AllDirectories)
.Select(f => new
{
FullPath = f,
RelativePath = Path.GetRelativePath(sourceFolder, f).Replace('\\', '/')
})
.ToList();
// Get all files from extracted folder
var extractedFiles = Directory.GetFiles(extractOutputPath, "*", SearchOption.AllDirectories)
.Select(f => new
{
FullPath = f,
RelativePath = Path.GetRelativePath(extractOutputPath, f).Replace('\\', '/')
})
.ToDictionary(f => f.RelativePath, f => f.FullPath);
// Compare each source file
foreach (var sourceFile in sourceFilesList)
{
totalFiles++;
var relativePath = sourceFile.RelativePath;
if (!extractedFiles.ContainsKey(relativePath))
{
missingFiles++;
comparisonResults.Add($"MISSING: {relativePath} (exists in source but not in extracted)");
continue;
}
var extractedPath = extractedFiles[relativePath];
extractedFiles.Remove(relativePath); // Mark as found
// Compare file contents
var sourceBytes = File.ReadAllBytes(sourceFile.FullPath);
var extractedBytes = File.ReadAllBytes(extractedPath);
if (sourceBytes.Length != extractedBytes.Length)
{
mismatchedFiles++;
comparisonResults.Add($"SIZE MISMATCH: {relativePath} (Source: {sourceBytes.Length} bytes, Extracted: {extractedBytes.Length} bytes)");
continue;
}
var bytesMatch = true;
var firstMismatch = -1;
for (var i = 0; i < sourceBytes.Length; i++)
{
if (sourceBytes[i] != extractedBytes[i])
{
bytesMatch = false;
firstMismatch = i;
break;
}
}
if (!bytesMatch)
{
mismatchedFiles++;
comparisonResults.Add($"CONTENT MISMATCH: {relativePath} (First difference at byte offset: {firstMismatch})");
}
else
{
matchingFiles++;
}
}
// Check for extra files in extracted folder
foreach (var extraFile in extractedFiles)
{
extraFiles++;
comparisonResults.Add($"EXTRA: {extraFile.Key} (exists in extracted but not in source)");
}
// Write comparison results
using var writer = new StreamWriter(comparisonOutputPath);
writer.WriteLine("=== File Comparison Results ===");
writer.WriteLine($"Total files in source: {totalFiles}");
writer.WriteLine($"Matching files: {matchingFiles}");
writer.WriteLine($"Mismatched files: {mismatchedFiles}");
writer.WriteLine($"Missing files: {missingFiles}");
writer.WriteLine($"Extra files: {extraFiles}");
writer.WriteLine();
if (comparisonResults.Count > 0)
{
writer.WriteLine("=== Detailed Results ===");
foreach (var result in comparisonResults)
{
writer.WriteLine(result);
}
}
else
{
writer.WriteLine("All files match perfectly!");
}
// Print summary to console
Console.WriteLine($"Total files: {totalFiles}");
Console.WriteLine($"Matching: {matchingFiles}");
Console.WriteLine($"Mismatched: {mismatchedFiles}");
Console.WriteLine($"Missing: {missingFiles}");
Console.WriteLine($"Extra: {extraFiles}");
Console.WriteLine();
if (mismatchedFiles == 0 && missingFiles == 0 && extraFiles == 0)
{
Console.WriteLine("SUCCESS: All files match perfectly!");
}
else
{
Console.WriteLine($"WARNING: Found {mismatchedFiles + missingFiles + extraFiles} issues. See {comparisonOutputPath} for details.");
}
Console.WriteLine($"Detailed results written to: {comparisonOutputPath}");
}
static void TestFolderToCCI()
{
// Hardcoded folder path - change this to your test folder
var sourceFolder = @"E:\isotest\game";
var cciOutputPath = @"E:\isotest\TestFolder.cci";
var extractOutputPath = @"E:\isotest\TestFolder_CCI_Extracted";
var comparisonOutputPath = @"E:\isotest\TestFolder_CCI_Comparison.txt";
Console.WriteLine("=== Xbox Original CCI Creation and Verification Test ===");
Console.WriteLine();
// Step 1: Create CCI from folder
Console.WriteLine($"Step 1: Creating Xbox Original CCI from folder: {sourceFolder}");
if (!Directory.Exists(sourceFolder))
{
Console.WriteLine($"ERROR: Source folder does not exist: {sourceFolder}");
return;
}
// Get file info before creating CCI
var sourceFilesInfo = Directory.GetFiles(sourceFolder, "*", SearchOption.AllDirectories);
var sourceDirsInfo = Directory.GetDirectories(sourceFolder, "*", SearchOption.AllDirectories);
var totalSourceSize = sourceFilesInfo.Sum(f => new FileInfo(f).Length);
Console.WriteLine($"Source folder contains:");
Console.WriteLine($" {sourceFilesInfo.Length} files");
Console.WriteLine($" {sourceDirsInfo.Length} directories");
Console.WriteLine($" Total size: {totalSourceSize / 1024.0 / 1024.0:F2} MB");
Console.WriteLine();
// List all files and directories for debugging
Console.WriteLine("Source files:");
foreach (var file in sourceFilesInfo.OrderBy(f => f))
{
var relPath = Path.GetRelativePath(sourceFolder, file).Replace('\\', '/');
Console.WriteLine($" {relPath}");
}
Console.WriteLine();
Console.WriteLine("Source directories:");
foreach (var dir in sourceDirsInfo.OrderBy(d => d))
{
var relPath = Path.GetRelativePath(sourceFolder, dir).Replace('\\', '/');
Console.WriteLine($" {relPath}/");
}
Console.WriteLine();
var createSuccess = ContainerUtility.ConvertFolderToCCI(
sourceFolder,
ISOFormat.XboxOriginal,
cciOutputPath,
0, // No split point
progress => Console.Write($"\rProgress: {progress:P2}")
);
Console.WriteLine();
if (!createSuccess)
{
Console.WriteLine("ERROR: Failed to create CCI file.");
return;
}
if (!File.Exists(cciOutputPath))
{
Console.WriteLine("ERROR: CCI file was not created.");
return;
}
var cciFileInfo = new FileInfo(cciOutputPath);
Console.WriteLine($"SUCCESS: CCI created at: {cciOutputPath}");
Console.WriteLine($"CCI file size: {cciFileInfo.Length / 1024.0:F2} KB ({cciFileInfo.Length / 1024.0 / 1024.0:F2} MB)");
Console.WriteLine($"Expected size (approx): {totalSourceSize / 1024.0 / 1024.0:F2} MB + overhead");
Console.WriteLine();
// Step 2: Extract files from CCI
Console.WriteLine($"Step 2: Extracting files from CCI to: {extractOutputPath}");
using var cciContainer = new CCIContainerReader(cciOutputPath);
if (!cciContainer.TryMount())
{
Console.WriteLine("ERROR: Failed to mount CCI container.");
return;
}
var extractSuccess = ContainerUtility.ExtractFilesFromContainer(cciContainer, extractOutputPath);
if (!extractSuccess)
{
Console.WriteLine("ERROR: Failed to extract files from CCI.");
return;
}
Console.WriteLine($"SUCCESS: Files extracted to: {extractOutputPath}");
Console.WriteLine();
// List extracted files for debugging
var extractedFilesInfo = Directory.GetFiles(extractOutputPath, "*", SearchOption.AllDirectories);
var extractedDirsInfo = Directory.GetDirectories(extractOutputPath, "*", SearchOption.AllDirectories);
Console.WriteLine($"Extracted folder contains:");
Console.WriteLine($" {extractedFilesInfo.Length} files");
Console.WriteLine($" {extractedDirsInfo.Length} directories");
Console.WriteLine();
Console.WriteLine("Extracted files:");
foreach (var file in extractedFilesInfo.OrderBy(f => f))
{
var relPath = Path.GetRelativePath(extractOutputPath, file).Replace('\\', '/');
Console.WriteLine($" {relPath}");
}
Console.WriteLine();
Console.WriteLine("Extracted directories:");
foreach (var dir in extractedDirsInfo.OrderBy(d => d))
{
var relPath = Path.GetRelativePath(extractOutputPath, dir).Replace('\\', '/');
Console.WriteLine($" {relPath}/");
}
Console.WriteLine();
// Step 3: Compare original and extracted files
Console.WriteLine("Step 3: Comparing original and extracted files...");
var comparisonResults = new List<string>();
var totalFiles = 0;
var matchingFiles = 0;
var mismatchedFiles = 0;
var missingFiles = 0;
var extraFiles = 0;
// Get all files from source folder
var sourceFilesList = Directory.GetFiles(sourceFolder, "*", SearchOption.AllDirectories)
.Select(f => new
{
FullPath = f,
RelativePath = Path.GetRelativePath(sourceFolder, f).Replace('\\', '/')
})
.ToList();
// Get all files from extracted folder
var extractedFiles = Directory.GetFiles(extractOutputPath, "*", SearchOption.AllDirectories)
.Select(f => new
{
FullPath = f,
RelativePath = Path.GetRelativePath(extractOutputPath, f).Replace('\\', '/')
})
.ToDictionary(f => f.RelativePath, f => f.FullPath);
// Compare each source file
foreach (var sourceFile in sourceFilesList)
{
totalFiles++;
var relativePath = sourceFile.RelativePath;
if (!extractedFiles.ContainsKey(relativePath))
{
missingFiles++;
comparisonResults.Add($"MISSING: {relativePath} (exists in source but not in extracted)");
continue;
}
var extractedPath = extractedFiles[relativePath];
extractedFiles.Remove(relativePath); // Mark as found
// Compare file contents
var sourceBytes = File.ReadAllBytes(sourceFile.FullPath);
var extractedBytes = File.ReadAllBytes(extractedPath);
if (sourceBytes.Length != extractedBytes.Length)
{
mismatchedFiles++;
comparisonResults.Add($"SIZE MISMATCH: {relativePath} (Source: {sourceBytes.Length} bytes, Extracted: {extractedBytes.Length} bytes)");
continue;
}
var bytesMatch = true;
var firstMismatch = -1;
for (var i = 0; i < sourceBytes.Length; i++)
{
if (sourceBytes[i] != extractedBytes[i])
{
bytesMatch = false;
firstMismatch = i;
break;
}
}
if (!bytesMatch)
{
mismatchedFiles++;
comparisonResults.Add($"CONTENT MISMATCH: {relativePath} (First difference at byte offset: {firstMismatch})");
}
else
{
matchingFiles++;
}
}
// Check for extra files in extracted folder
foreach (var extraFile in extractedFiles)
{
extraFiles++;
comparisonResults.Add($"EXTRA: {extraFile.Key} (exists in extracted but not in source)");
}
// Write comparison results
using var writer = new StreamWriter(comparisonOutputPath);
writer.WriteLine("=== File Comparison Results ===");
writer.WriteLine($"Total files in source: {totalFiles}");
writer.WriteLine($"Matching files: {matchingFiles}");
writer.WriteLine($"Mismatched files: {mismatchedFiles}");
writer.WriteLine($"Missing files: {missingFiles}");
writer.WriteLine($"Extra files: {extraFiles}");
writer.WriteLine();
if (comparisonResults.Count > 0)
{
writer.WriteLine("=== Detailed Results ===");
foreach (var result in comparisonResults)
{
writer.WriteLine(result);
}
}
else
{
writer.WriteLine("All files match perfectly!");
}
// Print summary to console
Console.WriteLine($"Total files: {totalFiles}");
Console.WriteLine($"Matching: {matchingFiles}");
Console.WriteLine($"Mismatched: {mismatchedFiles}");
Console.WriteLine($"Missing: {missingFiles}");
Console.WriteLine($"Extra: {extraFiles}");
Console.WriteLine();
if (mismatchedFiles == 0 && missingFiles == 0 && extraFiles == 0)
{
Console.WriteLine("SUCCESS: All files match perfectly!");
}
else
{
Console.WriteLine($"WARNING: Found {mismatchedFiles + missingFiles + extraFiles} issues. See {comparisonOutputPath} for details.");
}
Console.WriteLine($"Detailed results written to: {comparisonOutputPath}");
}
}
}