- Concurrent creation and extraction:
XisoWriter.CreateXiso/PackFromDirectoryresolve the source to absolute host paths, keep byte/file progress in per-operation state and take no process-wide lock. Concurrent creates run independently and never change the process working directory; output is byte-identical. A caller-suppliedinRootwithoutHostPathis resolved once against the caller's CWD.XisoReader.Extract/UnpackImageextract through a rootedLocalFilesysteminstead ofDirectory.SetCurrentDirectory, so concurrent extracts are independent too;UnpackImage(..., IFilesystem)still accepts any custom destination. - FATX-safe split default:
Constants.FatxMaxFileSize(0xFF000000, 4 GiB − 16 MiB) is now the default maximum part size for plain-ISO splits. An explicit--sizeabove it is still honoured with a warning. CISO/CCI keep their0xffbf6000xdvdfs-compatible compression default. - Parallel CISO compression:
CisoWriter.CompressToCso/CompressStreamgainjobsoverloads (1..64) that compress sector batches on a bounded worker pool and write payloads in sector order, so output is byte-identical to the sequential writer and progress stays ordered.MaxParallelismis the shared ceiling; CCI remains single-threaded until CCISharp 1.1. - Parallel extraction:
UnpackOptions.MaxDegreeOfParallelism(1..64, default1) queues independent files during the sequential tree walk and copies them on a bounded pool. Output is byte-identical to a sequential run; per-fileFileAddedprogress and completion logs stay in traversal order, andSkipExisting/ContinueOnErrorkeep their semantics. Plain ISO sources are read positionally throughRandomAccess; CISO/CCI/GOD/split and in-memory sources serialize reads, and destination filesystem calls are serialized soMemoryFilesystemand other non-thread-safe stores stay safe.UnpackOptions.MaxParallelismis the shared64ceiling. - GOD read-only sector input:
GodBlockDevicemaps a GOD/SVOD header plus itsDataNNNNfragments into the decompressed sector view, so every read verb (list, tree, extract, checksum, hash, validate, sector-layout, ranges) accepts a GOD container.GodHeader.TryReadVolume/GodVolumeInfoexpose the SVOD mapping, andXisoImageSourcedetects both a header file and its.datafolder. In-place repair/copy-in/set-filetime/rewrite refuse GOD and ask for a decompress first. - GOD title metadata:
GodHeader/GodTitleInforead the plaintextXContentheader of a GOD/SVOD container (title name, title ID, disc number/count) without mounting it. Names are sanitised for FATX and fall back to the hex title ID when empty. - XBLA/XBLIG header metadata:
StfsHeader/StfsTitleInforead the same XContent fields from single-file Xbox 360 STFS packages (XBLA0x000D0000, XBLIG0x00000002), which have no.datadirectory. - XBLA/XBLIG package listing and extraction:
StfsPackagereads the STFS file table, follows contiguous and hash-chain block lists through the level-0/level-1/level-2 hash interleave, and exposesEntries,Find,ReadAllBytes,CopyToandExtractTo.StfsPackageInforeports theXContenttitle fields and the volume layout.XisoChecksum.ComputeStfsChecksumuses the same sorted-path SHA3-256 tree hash as ISO and ZAR, so equivalent trees compare equal. Read-only: STFS writing/rebuilding stays out of scope. - STFS hash-tree validation:
StfsPackage.Validatehashes every logical data block and compares it with its level-0 hash entry, walks each file's block chain for truncation/cycles, verifies every level-0 table against its level-1 parent (and level-1 tables against level 2), and checks the top hash and header hash in the volume descriptor.StfsValidationReportcarries the counts and every mismatch as aStfsValidationIssue. Read-only: package signatures are not verified, and STFS writing/rebuilding remains out of scope. - Xbox 360 title metadata:
XexDbdfreads the plaintext XDBF/XSTR/XSRC resources from the XEX header-section table.XexTitleInfocarries title name, publisher, developer, genre, description and optional thumbnail;GetXexTitleInfoexposes it directly.TitleInfogains additiveKind(Xbe/Xex) andXexproperties, andGetTitleInforesolvesdefault.xbe→default.xex→default_mp.xbe. - XBE image assets:
XbeAssetsreads the logo bitmap and the$$XTIMAGE/$$XSIMAGEsections. DXT1/3/5, BGR24/BGRA32 and XPR0 payloads are decoded to PNG by the new BCL-onlyDxtDecoder/PngWriter; DDS is passed through or generated.XbeInfogainsHasLogoBitmap,HasTitleImageandHasSaveImageinit properties. - Safe-extract name policy:
ExtractNamePolicy(Rejectdefault,Sanitize,Skip) andUnpackOptions.NamePolicychoose how hostile entry names are handled.Sanitizereplaces unsafe characters with_and adds~Non collisions;Skipomits the entry (and a skipped directory's subtree).StfsPackage.ExtractToandXisoZarchive.ExtractZargained matchingExtractNamePolicyoverloads. The existing overloads keep the fail-fast default.
- GOD input: every read verb accepts a GOD header or its
.datafolder;decompresswrites a plain ISO (named after the header title) andconvertaccepts GOD →.iso/.cci/.cso. Redump modes and in-place write verbs refuse GOD with a "decompress first" message. - XBLA/XBLIG STFS packages:
-l,-t,-x,--unpack,checksumand-l/--jsonaccept a single-file XBLA/XBLIG STFS package and read its file table directly. Extraction honours-dand--skip-existing;checksumuses the ISO/ZAR-compatible tree hash.compress,decompress,convert, rewrite and the raw redump modes refuse STFS with an "extract first" message.-V/audit verifies the package's SHA-1 hash tree (per-block hashes, level tables, top hash and header hash) and reportsFiles checked/Blocks checked/Hash tables/Result. title-infoaccepts a GOD header or its.datafolder, a single-file XBLA/XBLIG STFS package, or an XISO image'sdefault.xbe/default.xex/default_mp.xbeand reports the available title name, title ID, disc and version fields in text and--jsonform. Xbox 360 titles also report publisher, developer, genre, description and thumbnail presence.--xbe-image <image> <path> --type logo|title|save -o out.png|out.ddsextracts XBE artwork.--xbe-info --jsonaddshasLogoBitmap,hasTitleImageandhasSaveImage;--xex-infoprints the XDBF title name, publisher, developer, genre and description when present.--delete-sourceon batchcompress,decompress,convertandsplit: deletes each source only after a successful conversion, requires-y/--yes(refused with-n/--no), removes every part of a split set, and reports the deleted count in the batch summary.--jobson CISO compression:compress/cso --jobs 1..64compresses sectors on a bounded worker pool (default1); output is byte-identical to the sequential writer. With--batch,--jobsstill selects concurrent conversions; single-file CCI compression is single-threaded.--jobson extraction:-xand--unpackaccept--jobs 1..64(default1) to copy independent files in parallel. Output is byte-identical, per-fileFileAddedprogress stays in traversal order, and--skip-existing/--continue-on-errorwork unchanged. ZAR/STFS unpacking and non-extract modes reject the flag with a clear message.--name-policy reject|sanitize|skipon-x/--unpack: choose fail-fast rejection (default), collision-safe sanitized names, or skipping hostile entries during ISO/CISO/CCI/GOD/ZAR/STFS extraction.splitwarns when an explicit--sizeexceeds the conservative FATX cap.
CCISharp1.0.1: the CCI reader now rejects oversized or hostile indexes withInvalidIndexinstead of allocating a buffer sized by the part file. No API change.
- The CLI is no longer published as a NuGet dotnet tool (
XISOSharp.Tool).XISOSharp(the library) remains the only NuGet package; get the CLI from the GitHub release bundles (release_<version>_<rid>.zip) or build it from source withpublish-cli.ps1.
World-class library release. This merges everything from the unreleased
1.5.0/1.6.0 tree (CCI, split ISO, ZAR input, traversal hardening, batch
conversion, JSON, preallocation and explicit layout packing) with the Phase 9
productization work: an open-once XisoImage facade, full-image
CRC32/MD5/SHA-1/SHA-256/SHA3-256, .hash verification, title metadata,
Windows long-path/reserved-name hardening, ZAR extraction caps, mutation
fuzzing, AOT smoke, 3-OS tests, a dotnet tool, SBOM and provenance.
Full suite green on all three targets: 1979 passed / 1 opt-in skip (1980) on net8.0/net9.0 and 2043 passed / 1 opt-in skip (2044) on net10.0.
XisoImage(XISOSharp):Open/OpenAsync,List/ListFlat,ReadFile/OpenReadStream,Extract/ExtractAsync,Validate,GetTitleInfo,ComputeImageHash,IDisposable/IAsyncDisposable.- Full-image hashes:
XisoImageHash.Computestreams CRC32, MD5, SHA-1, SHA-256 and SHA3-256 in one pass through the decompressed view. verify-hashes: verifies a--petrify/XboxKit.hashsidecar for ISO, CISO, CCI, split ISO and ZAR inputs.- Title metadata:
title-info/XisoReader.GetTitleInfofinddefault.xbeand report title name, ID, region, disc and version. - Hardening: Windows
longPathAwaremanifests, reserved device-name rejection/sanitization, ZAR extraction byte/entry caps, CISO malformed-index and alignment validation (found by the new mutation fuzzer). - Quality gates: 3-OS test matrix,
dotnet formatgate, AOT publish smoke, mutation fuzz job, 70% line / 60% branch coverage floors, package validation against 1.4.4 with a reviewed suppression baseline. - Packaging:
XISOSharp.Tooldotnet tool, SBOM + build provenance on releases, community files and a console sample.
Sector-layout packing release (PlanToEnhance Phase 8), plus the Phase 4 TOC
hardening follow-up. Images can now be repacked at
an explicit layout: XisoLayoutSpec accepts the JSON emitted by
--sector-layout --json (or a compact path=sector text spec), fixes the sectors of
matching files and directory tables, and allocates every other entry first-fit around
the reserved extents. -c, --pack <dir> and build-image gain --layout <file>.
The audit, sector-range, repair, salvage and ZAR walks now use the same explicit
in-order table traversal as extract/list/rewrite, so MaxTocDepth bounds real
subdirectory nesting only. The raw-sector redump modes also reject compressed
and split containers up front, and the GUI ZAR tab converts a .zar back to a
plain ISO. ZAR extraction is now depth-bounded, pre-sized and exact-length, and
CISO compression reads split/container sources through the decompressed view
instead of a joined temporary ISO.
Full suite green on all three targets: 1979 passed / 1 opt-in skip (1980) on net8.0/net9.0 and 2043 passed / 1 opt-in skip (2044) on net10.0.
XisoLayoutSpec/XisoLayoutEntry(XISOSharp.Models):FromSectorLayout,Load(JSON/text auto-detect),Parse,ParseJsonandParseText. JSON accepts the full--sector-layoutpayload, a bareentriesarray, camelCase or PascalCase names, andstartSector/sectoraliases; the text form supports#/;comments,total-sectors=Nand0xhex sectors.XisoWriterlayout packing:CreateXiso,CreateXisoAsync,PackFromDirectory,PackFromDirectoryAsyncandRemapFilesystem.BuildImageaccept an optionallayout. A two-pass planner validates every fixed extent (overlap, reserved system area, bounds, too-small extents), assigns the requested sectors, then seedsSectorAllocatorso unplaced entries fill gaps first-fit.- Layout fidelity: a JSON layout round-trips an unchanged source tree
byte-for-byte;
TotalSectorsis preserved (subject to the writer's final 64 KiB alignment); partition-relative sectors stay correct underprependSectors. - Strict/lenient paths: the compact text form rejects paths missing from the source tree; JSON extra entries are reserved (with a warning) so a subset repack cannot reuse their bytes.
XisoReader.AuditWalk,XisoRanges.GetValidSectorsCore/CollectFileEntries,XisoRepairer.CollectWalk,XisoSalvager.SalvageWalkandXisoZarchive.ParseNodenow walk each directory table with an explicit in-order stack (left subtree, entry, right siblings) instead of recursing on the left child.MaxTocDepth(64) bounds real subdirectory nesting only.- A 4,096-entry left-skewed table now audits, maps (
--ranges,GetFileEntries), repairs a reserved-attribute bit on its deepest entry, salvages into a fresh image and packs to ZAR; cycles and out-of-table pointers still hit the existing named errors or report/drop gates. - The visited-offset set and
MaxTocEntriesPerTable/MaxTocStackFramesbackstops are unchanged; a shared (DAG) subtree now reports the same cycle error the reader has always raised.
XisoValidator.ValidateConversionaccepts a ZArchive (.zar) on either side: the tree comes fromXisoZarchive.ListZar, and--validate-checksumshashes each name-tree entry through the newXisoZarchive.ComputeFileHash(no extraction to disk). ISO↔ZAR conversions can now be verified directly.- The CLI
validateverb accepts.zar(including--jsonand--validate-report), matching the-l/-t/-x/checksumZAR input support. - A
.zarhanded to a sector-only verb (-i,--ls,-V,--filetime,--sector-layout,--ranges,--repair,--copy-in/--copy-out, …) now reports a cleanError:naming the archive verbs instead of an unhandledNotSupportedExceptionstack trace.
XisoZarchive.ExtractZarnow bounds directory nesting atConstants.MaxTocDepth, matchingListZarandComputeZarChecksum; a malicious or corrupt archive fails with a namedInvalidDataExceptioninstead of recursing until the stack overflows.- Each extracted destination is pre-sized from the name tree and copied with
XisoFileCopier.CopyExact, so a truncated entry throwsTruncatedCopyExceptioninstead of silently producing a short file. Failed or canceled entries delete their partial output (Windows-safe: the handle is closed first).
CisoWriter.CompressToCsoreads split ISO, CISO and CCI sources through the seekable decompressed view fromXisoImageSourceinstead of writing a joined temporary ISO first. Split output still goes throughCisoSplitOutput.- The split-output collision guard now compares every source part (not just the entry path), so recompressing a split CISO/ISO set cannot truncate one of its own parts.
--layout <file>on-c <dir>,--pack <dir>andbuild-image; rejected for rewrite/extract/list modes and for--pack <iso>.- Help text and the misplaced-flag guard cover
--layout. --sector-layout --json game.iso > layout.jsonfollowed by-c game_dir out.iso --layout layout.jsonreproduces the source layout.- The raw-sector redump modes (
--video,--random,--seed,--wipe,--trim,--petrify,--update,--zar) refuse.cso/.cci, split ISO and.zarinputs with a clear "decompress/convert/join first" message instead of parsing container bytes as an XISO. - Expected overwrite refusals (
-n, redirected stdin) stay in the local log and no longer reach the bug-report API. - CCI split sets opened through any numbered part (
.2.cci….9.cci) name outputs after the game: extraction createsgame/, rewrite writesgame.iso, andcompressderivesgame.cciinstead of refusing the source as its own output. Plain ISO/CISO sets still strip only.1, andarchive.1.zarkeeps its number.
- The ZAR tab is bidirectional: a
.zarsource runsconvertand writes a plain ISO (output auto-derived next to the archive); an image source keeps the existing pack + overwrite/skip/auto-rename behavior. The output picker and labels follow the detected direction, and the self-test covers the new argv.
LayoutPackingTests(41): JSON/text parsing and validation,FromSectorLayout, byte-identical JSON round-trips, fixed-extent placement, first-fit gaps, reserved unmatched JSON extents, total-sector preservation, prepended partitions, case- insensitive paths, empty files/directories,build-image, and CLI-c/--pack/build-imageend-to-end plus usage errors.SectorAllocatorTests(+7SeedUsedRangescases): one-pass bulk seeding sorts/coalesces, rejects overlaps and out-of-bounds ranges, refuses to seed after allocations, handles null and zero-count ranges.PathologicalTocTests(+5): the 4,096-entry left spine audits and maps, repairs its deepest entry, salvages to a passing image, and packs to a valid ZAR.ZarValidateTests(10): ZAR↔ISO/CCI tree comparison, per-entry SHA-256/MD5 hashing (case-insensitive paths, missing/directory paths), missing-file and checksum-mismatch detection, CLIvalidate --json/--validate-report, and a clean sector-only rejection for.zarinputs.ZarInputTests(+1): a 65-level name tree is rejected by bothListZarandExtractZarwith the depth message; the existing list/extract/checksum/ convert tests still pass with pre-sized, exact-length extraction.CisoTests(+1): recompressing a CISO throughCompressToCsonow reads the decompressed view directly and round-trips to the same ISO hash.RedumpInputGuardTests(11): every redump mode refuses.cci/.cso, split ISO and.zarinputs with the documented message, while a plain ISO still runs.CliCommandsTests.Convert,MainViewModelTestsand the GUI self-test cover the ZAR→ISO direction/argv;OverwritePromptExtraTestsasserts expected refusals carryNoBugReport.CisoAutoDetectTests.ReaderVerbs_CsoMatchIsoand the split-ISO reader test now compare--rangesand sector-layout output.XisoImageSourceTests(+7 part-suffix cases),CciAutoDetectTests.SecondCciPart_NamesOutputsAfterGameStemandXisoRepairerRefusalTests.Salvage_DefaultOutputPath_Namingcover numbered CCI part naming: extraction, rewrite, recompress and salvage from.2.cciall use the game stem;.10.cci/.0.ccistay ordinary names, and.1.zarkeeps its number.- net8.0/net9.0 - 1980 tests (1979 passed, 1 opt-in skip); net10.0 - 2044 tests (2043 passed, 1 opt-in skip, adds the GUI tests).
Machine-readable-output and I/O-efficiency release. Read-only verbs gain a
stable --json schema (source-generated, trim/AOT-safe) with human logs moved
to stderr, and extraction/creation now pre-size known-length destinations and
use sequential-scan hints. -v/--version also reports the CCISharp,
ZArchiveSharp, runtime and commit metadata.
Full suite green on all three targets: 1860 passed / 1 opt-in skip (1861) on net8.0/net9.0 and 1922 passed / 1 opt-in skip (1923) on net10.0.
- Preallocation / sequential I/O (PlanToEnhance Phase 7): new additive
IFilesystem.CreateFile(string path, long? expectedLength)default member.LocalFilesystemopens withFileOptions.SequentialScanand appliesSetLengthbefore the first write;MemoryFilesystempreallocates its buffer; custom stores keep the old behavior through the default member.XisoReader.ExtractFile/CopyOutFilepass each entry's size, and plain-ISO sources open withSequentialScan. XisoWriterpre-sizing: after the sector layout is computed, the output is sized once to the exact post-layout extent (plus any prepended partition) before the data phase. The final 64 KiB alignment padding and image bytes are unchanged.- Offset-aware read helpers: new overloads
GetVolumeInfo(string, int?),GetVolumeInfo(Stream, string, int?),ListDirectory(string, string, int?),ListDirectory(Stream, string, string, int?)andGetSectorLayout(string, int?)probe the XISO header at an explicit Redump/XGD partition offset instead of the automatic candidates. - Container-aware ranges:
XisoRanges.GetXisoRanges/GetFileEntriesgainedStreamoverloads and open throughXisoImageSource, so--rangesand range-based archival helpers read split ISO, CISO and CCI inputs. Logger.RouteInfoToError: optional switch that sendsLog/LogLine/FlushtoError, keeping stdout free for machine-readable output.
--jsonon-i,-l,-t,--checksum/checksum,--sector-layout,--ranges,--filetime,--xex-info,--xbe-info,validateand-v/--version. Every document carries"schemaVersion": 1and acommand; list/tree wrap results in animagesarray (one document for multiple inputs), checksum returns achecksumsarray. JSON goes to stdout; banners/progress/warnings/errors go to stderr.- Serialization uses the source-generated
JsonOutputContext(camelCase, nulls omitted), so the trimmed single-file CLI has no reflection fallback. --jsonis rejected for mutating modes (extract, rewrite, create, compress/decompress, redump) with a clear error.- Version enrichment:
-vkeeps its historical first line, then prints XISOSharp, CCISharp, ZArchiveSharp, runtime, OS, architecture and the MinVer commit.-v --jsonemits the same data as a JSON document. - Help text documents
--json,--version, and the new read-only schema.
CliJsonTests(12): every JSON payload parses, stdout/stderr are separated, multi-image list output stays one document, CCI input matches the ISO tree, checksum matches the library digest,validatereports summaries, version metadata is populated, and--jsonrejects extract mode.XbeInfoTests/XexInfoTests: JSON payloads for--xbe-info/--xex-info(plus the existing end-to-end text checks).PreallocationTests(5):LocalFilesystempre-sizing, empty default,MemoryFilesystemcapacity behavior, the default interface-member fallback, and extraction passing each entry size to a customIFilesystem.CliHelpFlagTestsnow asserts the enriched version output while keeping the first-line banner contract.- net8.0/net9.0 - 1861 tests (1860 passed, 1 opt-in skip); net10.0 - 1923 tests (1922 passed, 1 opt-in skip, adds the GUI tests).
Container-input, traversal-hardening and batch-conversion release. XISOSharp now
reads CCI/CCIM images (via the new CCISharp 1.0.0 dependency), split
plain-ISO sets (game.1.iso …), and ZArchive (.zar) inputs, and exposes
one unified detection/open layer (XisoImageSource) for every sector-based
format. The CLI gains compress --format cci, --cci-level/--cci-split,
cci/uncci aliases, convert for ZAR ↔ ISO, ZAR-aware
list/extract/checksum, and --batch conversion on compress, decompress,
convert and split; the GUI gains a CISO/CCI format selector and routes
.cci/.zar drops to the matching tab. The reader's directory walk is now an
explicit in-order stack, so a pathological left-skewed table can no longer
exhaust the process stack or trip the subdirectory depth cap.
Full suite green on all three targets: 1841 passed / 1 opt-in skip (1842) on net8.0/net9.0 and 1903 passed / 1 opt-in skip (1904) on net10.0.
XisoImageSource(XisoImageFormat,XisoImageSourceInfo): extension-led detection with aCISO/CCIMmagic sniff fallback;OpenRead/OpenBlockDevicereturn the decompressed/concatenated view for ISO, split ISO, CISO, CCI and their split variants. Plain files remain ISO candidates.- CCI/CCIM:
XisoCci(CompressToCci,DecompressToIso,DeriveDefaultCciPath,DeriveDefaultIsoPath),CciBlockDevice, andCciNaming; backed by CCISharp 1.0.0 (MIT, pure managed, LZ4). Single-part and.1.cci….9.ccisets are supported. - Split ISO input:
SplitIsoFile/SplitIsoStreamconcatenate<base>.1.iso,.2.iso, … (multi-digit indices included); a missing middle part raisesInvalidDataExceptioninstead of silently truncating. - ZAR input:
XisoZarchive.ListZar,ExtractZar,ConvertZarToIso;XisoChecksum.ComputeZarChecksum/ComputeZarChecksumHexproduce the same SHA3-256 tree hash as the equivalent ISO. Unsafe entry names are rejected. - Unified readers:
XisoReader.OpenImageStreamnow routes CCI and split ISO through the factory;XisoChecksumopens every format throughOpenBlockDevice. Output naming strips.cso/.cci/.1.*suffixes. - In-place guards:
Repair,CopyIntoImageandSetFileTimerefuse CISO and CCI containers with a clear "decompress first" error, even when the file is missing or corrupt. - Recompression:
CisoWriter.CompressToCsoandXisoCci.CompressToCciaccept split ISO/CISO/CCI sources by materializing the decompressed image to a temporary ISO; directory sources still pack then compress. StreamBlockDeviceexposes any seekable stream as anIBlockDevice.- Pathological TOC traversal:
TraverseXisonow walks each directory table with an explicit in-order stack instead of left-subtree recursion.MaxTocDepthbounds subdirectory nesting only; intra-table depth is bounded byMaxTocEntriesPerTableandConstants.MaxTocStackFrames(100k). A 4,096-entry left-skewed chain lists/trees/extracts/rewrites, and the rewrite checksum matches the balanced form.ContinueOnErrorstill skips just the corrupt subtree. - Runtime dependencies are now
ZArchiveSharp1.4.0 andCCISharp1.0.0.
compress --format cso|cci(defaultcso),--cci-level 0..9,--cci-split <bytes>;-l/--leveland--splitremain format-neutral.ccialias forcompress --format cci;unccijoinsdecompress.- Format-specific flag validation:
--ciso-*is rejected for CCI output and--cci-*for CISO output. decompressauto-detects CISO vs CCI (extension plus magic sniff).convert <src.zar|src.iso> <out.iso|out.zar>;-l,-t,-x,--unpackandchecksumaccept.zardirectly.- Batch conversion:
--batch <dir>/--batch-recursiveoncompress,decompress,convertandsplit;--skip-existingresumes,--continue-on-errorkeeps going after a failed file (partial outputs are removed),--jobs 1..64converts in parallel, and--output-namesupports{name}/{ext}/{format}. Duplicate outputs and outputs that would clobber another input are refused before any write.convert --batch --format iso|zarcovers both directions. - Help text and the GUI self-test cover the new flags.
- Compress tab: Format selector (CISO/CCI); output/save dialog and split placeholder follow the selected format.
- Picker filters and drop routing include
.cci/.1.cci; a dropped.zaropens the Extract tab for list/extract/checksum, and compressed drops route to Decompress. - Decompress picker accepts CISO and CCI; collision guards use the matching default output naming.
XisoImageSourceTests: detection table for ISO/XISO/IMG/CISO/split CISO/ CCI/split CCI/split ISO, CCI round-trip, cross-part seeks, magic sniffing, suffix stripping and missing files.CciAutoDetectTests: list/tree/extract/unpack/rewrite/checksum parity, default output naming, CCI decompression and the in-place refusal contracts.SplitIsoAutoDetectTests: extract/list/checksum parity, split CISO/CCI recompression, defaultgame/naming and missing-middle-part errors.CliCciTests: CCI compress/decompress, split sets, aliases, list and format-specific flag rejection.ZarInputTests: ZAR listing/extraction/checksum/convert and CLI wiring.PathologicalTocTests: 4,096-entry left-skewed, right-skewed, alternating and balanced tables; list/tree/extract/rewrite parity, a left self-cycle, and continue-on-error subtree skipping.CliBatchConvertTests: CISO/CCI batch compress, batch decompress, ISO to ZAR convert, batch split, recursive discovery, naming templates (including subdirectories), duplicate-output refusal,--skip-existingresume,--continue-on-errorpartial-output cleanup, and parallel--jobs.- net8.0/net9.0 - 1842 tests (1841 passed, 1 opt-in skip); net10.0 - 1904 tests (1903 passed, 1 opt-in skip, adds the GUI tests).
Extraction-cleanup and static-analysis release. A failed or cancelled extraction no
longer leaves a truncated destination file behind: ExtractFile/CopyOutFile
delete the partial output through the new IFilesystem.DeleteFile member, which
custom destination stores can override (the default keeps the previous no-op
behavior). The solution is clean under JetBrains InspectCode - 0 errors and 0
warnings across every project - and dead members found by the inspection were
removed from the Tester. Full suite green on all three targets: 1760 passed / 1
opt-in skip (1761) on net8.0/net9.0, 1821 passed / 1 opt-in skip (1822) on net10.0.
- Partial-destination cleanup: a copy that throws, reports truncation, or is cancelled removes the destination it wrote, so callers (drag-and-drop prep, batch extraction, resume runs) can never mistake a partial file for a complete one. Cleanup is best-effort and never masks the extraction error.
IFilesystem.DeleteFile: new member with a default no-op implementation - existing custom stores still compile and keep their partial content if they cannot delete.LocalFilesystemdeletes from disk (a missing file is a no-op);MemoryFilesystemremoves the stored snapshot.- Static-analysis cleanup across the library, CLI, GUI, Tester, benchmarks and
tests: redundant default arguments, redundant casts and assignments, dead null
guards, unused fields/properties, and simplified nullability in
Logger.Out/Logger.Error(assigningnullnow storesTextWriter.Null, so the getters never returnnull). No output or format changes.
ExtractRobustnessTests: a truncated copy and a mid-write failure both leave no destination file, including through a customIFilesystem.XisoFilesystemTests:LocalFilesystem.DeleteFileremoves files and treats a missing path as a no-op.- Suite: net8.0/net9.0 - 1761 tests (1760 passed, 1 opt-in skip); net10.0 - 1822 tests (1821 passed, 1 opt-in skip, adds the GUI tests).
Split CISO part sets honor the caller-chosen FileShare when opening images.
CisoSplitFile.OpenParts was hardcoded to FileShare.Read, so
XisoReader.OpenImageStream(path, FileShare.ReadWrite) and
XisoExplorerOptions.Share reached plain ISOs and single-file .cso containers
but not the individual *.1.cso part files - a split set held open by a writer
(sync client, in-progress copy, antivirus) still failed with a sharing violation
on Windows. The share mode now threads to every part. Defaults are unchanged
(FileShare.Read). Full suite green on all three targets: 1758 passed / 1
opt-in skip (1759) on net8.0/net9.0, 1819 passed / 1 opt-in skip (1820) on
net10.0.
- Split CISO share mode:
CisoSplitFile.OpenParts(firstPart, share)accepts a share mode, andCisoBlockDevicethreads the caller'sFileSharethrough to every part file.XisoExplorerOptions.Sharenow covers plain ISOs, single.csocontainers, and split*.1.csopart sets alike.
CisoOpenParts_HonorsCallerShareModepins the share plumbing, including that the default stays read-shared;SplitCso_ExplorerWithReadWriteShare_ CoexistsWithWriterHoldingPartcovers the end-to-endXisoExplorerflow with a writer holding the first part.
Deep-review hardening and GUI experience release. An 80-item review of the whole
repository (path escapes, patch-layout collisions, CWD leaks, partial artifacts,
CLI contract mismatches, vacuous tests, doc drift) is resolved, together with
the follow-up regressions found while re-reviewing those fixes and a final pass
over the fix commits. The desktop app gains Donate/About/Exit header actions, F8
window screenshots, and a startup update prompt backed by the same UpdateCore
- 24-hour cache the CLI uses. Namespace note:
UnpackOptions,ProcessRunResult,ExplorerNode, andXisoExplorerOptionsmoved fromXISOSharptoXISOSharp.Models— addusing XISOSharp.Models;when upgrading from 1.4.1. Targets remainnet8.0/net9.0/net10.0; full suite green on all three (1818 tests on net10.0: 1817 passed, 1 opt-in skip; 1757 on net8.0/net9.0: 1756 passed, 1 opt-in skip). The suite runs fully sequentially (assembly-wideDisableTestParallelization) because create/extract mutate the process CWD.
- Path safety: crafted image names (separators, Windows drive-relative colons, any trailing dot/space) are rejected at extract on Windows or sanitized by repair/salvage; listing, tree, rewrite, and ZAR packing accept every structurally valid name on every host, matching the reference tool (the colon stays valid on Unix where the writer/patcher accept it).
- Patching: the allocator reserves the optimized tag (sector 15), the
ECMA-119 descriptor pair (16-17), and the layout-tool signature sector — also
for header-only volumes; sector counts use 64-bit math; the root table size
is recorded even when the table stays in place; a child offset that would
encode the
0xFFFFempty-child sentinel fails instead of truncating. - Walkers: all child offsets are bounded by the recorded table size, the
all-zero empty-table sentinel is honored,
./..records are skipped consistently, truncated names fail instead of truncating the walk (includingCollectFileEntries), and zero-size directory entries list as empty. - Writing/containers: CWD is restored on every path; a cwd source
(
-c ./-c ..) defaults its output next to the source instead of aborting on the same-leaf guard; relative-dresolves against the caller CWD; failed/cancelled runs delete partial.iso/.cso/.zaroutput (including thebuild-imageremap writer, and closing split-part handles first on Windows) but never a pre-existing file the call did not create; CISO headers/indexes are validated; split part naming handles dotted bases;Latin1Encodingrange checks are overflow-safe. - Repair/audit: a missing optimized tag is written at the disc offset for prepended images; path and device audits agree on trailing magic, empty-image tag probing, and an oversized root table (audit now matches extraction).
XisoPathsresolves both sides of an input==output check against one CWD snapshot;XisoExplorer.Disposeserializes with keep-open reads.
--silentis order-independent in every position, including with-v/--help, and still requires--checksum;--file-time/--preserve-attrs/--jobs/--policyare rejected outside their modes, and--jobsis rejected with--compressor a multi-mode redump run where it cannot take effect;--wipe/--trimhonor-o;--is-optimizedhonors--skip-sectors;--ciso-splitrefuses a source named like its own first part.-Ddeletes.oldonly after a fully successful (validated) rewrite, and a failed file no longer suppresses a later file's success or keeps its backup.- Help shows
-o <output>for the redump modes instead of a positional second file (which is parsed as another input). - stdout/stderr are always UTF-8 instead of the host console code page, so
Latin-1 filenames (
café.txt) render and pipe identically on every platform (matching xdvdfs's UTF-8 output); the battle harness now decodes each tool with its real encoding (extract-xiso Latin-1; xdvdfs, xboxkit, and the CLI UTF-8) so non-ASCII names compare equal instead of collapsing toU+FFFD.
- Donate/About/Exit header actions with an About dialog; F8 screenshots; startup update prompt (subscribed before probing so a fast show cannot hang it); tooltips.
- Drag-and-drop routing fixed (only
*.isofolders go to Batch;.zardrops go to Rebuild in single- and multi-item drops); Wipe/Trim pass-obefore the image;CliStatusupdates on the UI thread; settings persist again; screenshot environment warnings stay local and the fallback folder is tried for security exceptions.
- Shared Serilog pipeline; expected operational warnings are tagged
NoBugReport; the shared API key is double-Base64 encoded (ApiKeyStore); the dedupe map is bounded;ProcessRunnerfalls back to a stable working directory when the inherited CWD was deleted.
- List comparison parses the real
\name (N bytes)format and decodes extract-xiso's Latin-1 output; two empty parses fail instead of passing; remaining dead wrappers (RunQuietAsync) removed.
- Drift fixed (test counts,
--help, Release packing, battle default, coverage OS/figures, Tester CI, sequential-suite description, missing scripts,ConversionPlan.md, namespace samples); publish scripts stage into%TEMP%and merge instead of deleting the protectedpublish*/trees, andpublish-cli.ps1 -Ziprequires an exact tag or-Version <x.y.z>so a pre-release run cannot overwrite a shippedrelease_*.zip;docs/serves Pages (Docsify_sidebar.md) and syncs to the wiki (Home.md+_Sidebar.md) via.github/workflows/wiki.yml.
Dependency and legal maintenance release. ZArchiveSharp moves 1.3.0 → 1.4.0
(drop-in: upstream rewrote its pipeline layer as original MIT work with no
public-surface, wire-format, or CLI changes), and the ZArchiveSharp notice is
refreshed — the library, including the ZArchiveSharp.Pipeline pack/extract
layer XISOSharp uses, is fully MIT. No XISOSharp API or CLI behavior changes;
targets remain net8.0 / net9.0 / net10.0; full suite green on all three
(1427 tests: 1426 passed, 1 opt-in skip, 0 failed).
ZArchiveSharp1.3.0 → 1.4.0. Upstream highlights: original MIT pipeline layer (ZarPipeline,ZarPackEngine,ProcessRunner), stricter per-item batch isolation, and a robust stderr drain that no longer stalls on an inherited pipe. The public surface is unchanged, so ZAR output, CLI semantics, and exit codes are untouched.
LICENSEitem 4 records ZArchiveSharp as fully MIT as of v1.4.0 (Copyright (c) 2026 PureLogicCode.com; lead developer Peterson Fernandes), includingZArchiveSharp.Pipeline.- The packaged library license (
XISOSharp/LICENSE) is synced with the rootLICENSE, so the NuGet package now carries the full third-party notices (extract-xiso BSD-4-clause, xdvdfs, XboxKit, ZArchiveSharp).
- Root
README.mdanddocs/building.mddependency references updated 1.3.0 → 1.4.0.
Integrity-audit release. The CLI's -V audit no longer fails a structurally
sound image just because the optimized tag is missing: it reports the tag
(Optimized: yes/no) and passes raw/unconverted dumps, while structural damage
still fails. Audits now accept .cso images (previously compressed bytes were
read as sectors), the library gains a requireOptimizedTag overload plus the
AuditResult.IsOptimized property, and empty (zero-root) images report tag
presence instead of always false. Targets remain net8.0 / net9.0 /
net10.0; full suite green on all three (1427 tests: 1426 passed, 1 opt-in
skip, 0 failed).
- New overloads
AuditXiso(string isoPath, bool requireOptimizedTag)andAuditXiso(IBlockDevice dev, string isoName, bool requireOptimizedTag). WithrequireOptimizedTag: falsea missing tag is not an audit issue, so raw (unconverted) images audit as valid; the 1-arg overloads keep the original strict behavior (true). - New
AuditResult.IsOptimizedproperty reports whether the tag was found. The empty/zero-root early-return paths previously skipped the tag probe, so an image whose root fields are zero but whose tag is intact reportedfalse; both the path and block-device overloads now probe and report it. AuditXiso(string)now opens throughOpenImageStream(CISO-aware) instead of a plainFileStream, matchingGetVolumeInfo. A.csoinput used to be audited as compressed bytes, producing bogus tree/bounds issues.
-Vis an integrity audit: it printsOptimized: yes/no, a missing tag no longer fails the run, and raw/unconverted images exit 0. Use--is-optimizedfor the strict tag-only probe or--repairto write a missing tag. Help text updated.
- 1427 tests across
net8.0/net9.0/net10.0: 1426 passed, 1 opt-in skip (XISO_UPDATE_FIXTURE=1fixture validator), 0 failed. - New:
CliAuditTests(3 end-to-end-Vruns: optimized, raw passing withOptimized: no, corrupt tree failing),AuditXisoTestsintegrity/tag/CISO cases (4, incl. plain-vs-CISO parity), and device empty-root tag coverage.
coverlet.collector10.0.1 → 10.1.0 (Tests). No library dependency changes.
README.md,XISOSharp/README.md,XISOSharp.Cli/README.md,docs/cli.md, anddocs/api-xisoreader.mddocument the integrity audit, therequireOptimizedTagoverload, andIsOptimized;docs/troubleshooting.mdanddocs/getting-started.mdrefreshed; suite counts updated.- Release bundles now include
WhatsNew.mdnext toREADME.mdandLICENSE.
Correctness and maintenance release. The rewrite -o output name is now
honored for real — including rooted/absolute paths — and a rewrite that fails
to write reports an error instead of exiting 0. Wrapped exceptions carry their
cause, the reference-binary interop tests resolve the current References/
drop again, and the bug-report wire format is locked by tests. Targets remain
net8.0 / net9.0 / net10.0; full suite green on all three (1419 tests:
1418 passed, 1 opt-in skip, 0 failed).
XisoWriter.CreateXisoignoredinNamein rewrite mode, soXisoReader.Rewrite(..., outputName:)(CLI-o) had no effect on the output filename. The name is now used verbatim: relative names resolve against the-ddirectory, and rooted names are kept intact. The Windows drive-letter strip used for legacy names no longer applies to a rooted-o, which turnedC:\out\game.isointo:\out\game.isoand failed with a path-syntax error.XisoReader.DecodeXiso(and thereforeRewrite) now returns the writer's non-zero result when the output cannot be written. Previously the writer logged the failure but the rewrite still reported success and returned 0.- Regression tests:
Rewrite_WithAbsoluteOutputName_UsesProvidedName,Rewrite_UnwritableOutput_ReturnsError.
- Wrapped rethrows embed the caught exception as
InnerException(Meziantou MA0054):ProcessRunnertimeout →TimeoutException,XisoReadertruncated file copy →IOException, GUIMainViewModeloutput-verification failures →InvalidOperationException. Message text is unchanged, so existing diagnostics and exception filters keep working.
- Rewrite (
-r) now checks the decode result: a failed rewrite exits 1 and does not printsuccessfully rewritten(the input stays at<name>.old, exactly as before the fix). -oaccepts relative and rooted paths and uses them as-is.
UpdateCheckerdebug-logs every previously silent catch (offline checks and API/cache failures stay belowWarning, so they never file bug reports); GUICliLocator.ProductVersiondebug-logs unreadable CLI metadata.BugReporterextractsComposeReportand exposesBuildExceptionBlockto tests; newBugReportFormatTests(5) lock the Environment / Error / Exception sections required by the bug-report service.
- 1419 tests across
net8.0/net9.0/net10.0: 1418 passed, 1 opt-in skip (XISO_UPDATE_FIXTURE=1fixture validator), 0 failed. TestConditionsresolves the compiledextract-xiso.exefrom the currentReferences/drop (canonicalReferences/extract-xiso.exe, dated drop root, or in-tree CMake build) instead of the removed202505152050artifact path; the legacyllCompatinterop tests run and pass again.RegenerateFixtureIso_WhenRequestedrenamed toValidateFixtureIso_WhenRequested(it validates only; regeneration stays manual) —docs/testing.mdupdated.
Meziantou.Analyzer3.0.257 → 3.0.290 (all projects),Avalonia12.1.2 → 12.1.3 (GUI),QuestPDF2026.8.0 → 2026.9.1 (Tester),Microsoft.NET.Test.Sdk18.10.0 → 18.10.1 (Tests). No library dependency changes.
- Badge rows (CI, NuGet version/downloads, release, .NET, platform/RIDs,
license, docs site, per-project) added to the root, library, CLI, Tests,
Tester, and docs READMEs; suite counts refreshed;
-orooted-path behavior documented in the CLI reference.
Additive release for VFS-consumer parity (SimpleXisoDrive/Dokan): the probe and
read stack now accepts the rebuilt "sector-0" XISO layout (volume descriptor at
the very start of the image instead of partition sector 32), and the in-place
patcher, sector ranges, and ZAR packing understand it end-to-end. Targets remain
net8.0 / net9.0 / net10.0; full suite green on all three (1412 tests:
1408 passed, 4 pre-existing skips, 0 failed).
VerifyXiso(stream and block-device overloads),GetVolumeInfo,GetFileTimeRaw/SetFileTime(both overloads), andOffsetBlockDevice.Probedetect a volume descriptor at absolute offset 0. Such images reportDiscLseek = 0andDescriptorSector = 0; sector numbers stay partition-relative, soXisoExplorer, directory listing, and bounded file reads work unchanged on them.XisoReader.TryFindHeaderBaseresolves the descriptor base for callers that take a partition offset (standard sector-32 candidate first, then sector-0).GetSectorLayoutmarks the detected descriptor sector as used instead of hardcoding partition sector 32, soSectorAllocator.FromLayoutcan no longer hand out the live header to the in-place patcher.PatchVolumeHeaderRootwrites the relocated root pointer to the active header base (DiscLseek + DescriptorSector * 2048), fixing a silent-corruption path whereCopyInon a sector-0 image overwrote the descriptor or left the header pointing at the old root table.XisoRanges.GetXisoRanges/GetFileEntriesandXisoZarchive.CreateZarresolve the descriptor with the same helper; invalid images keep the historical fallback base and failure behavior.XisoRedump.RebuildRedumprejects sector-0 inputs with an explicit error (repack to the standard sector-32 layout first) because a verbatim embed would place the descriptor at partition sector 0;HasXisoMagicrecognizes sector-0 images so they keep working as.zarsidecar inputs.
- The brute-force seed search now checks the cancellation token inside each worker's candidate chunk. A canceled search stops promptly instead of grinding through the rest of the chunk — removing the coverage-instrumented stall that tripped CI's 15-minute blame-hang watchdog on the net8.0 test host.
- New
XisoRebuiltSector0Tests(12 tests): probe/verify/volume-info parity, explorer listing +OpenReadStream, filetime read/write, block-device probe, sector layout used/free ranges, in-place add/replace/root-table-move, andGetXisoRanges/CreateZarround-trips on sector-0 images.
docs/xiso-format.mddocuments the rebuilt sector-0 variant; theapi-xisoreader.mdprobe table,DescriptorSectorcontract, and the library/CLI READMEs cover the accepted layout and the Redump rebuild restriction.
- Test runs always publish a
.trxartifact for post-mortems and skip hang-dump collection (--blame-hang-dump-type none); the instrumented seed-search stall that aborted the net8.0 job is gone (windows tests dropped from ~15 min to ~1.5 min per TFM).
Additive release for VFS-consumer parity (SimpleXisoDrive/Dokan): the public API
gains bounded in-place file reads, a keep-open explorer mode, descriptor
creation-time/sector surfacing, FileShare control, and Windows attribute
mapping — no behavior change to existing APIs. Targets remain net8.0 /
net9.0 / net10.0; full suite green on all three (1400 tests: 1396 passed,
4 pre-existing skips, 0 failed).
XisoExplorer.OpenReadStream(string)/OpenReadStream(ExplorerNode)return a read-only, seekableStreamover a file's data extent inside the image. Reads are clamped to the entry'sFileSize(not the image length), so a corrupt TOC cannot leak the next file's sectors; seeking at/past the end reads 0 bytes perStreamconventions; CISO/split-CISO images work transparently through the decompressed block device. No copy is made, so 4 GB files stream in place.XisoReader.ReadFileBytes(isoPath, internalPath, Span<byte>, fileOffset)and the stream overload are one-shot conveniences over the same bounds; the stream overload leaves the caller's stream open, and missing paths/directories throwInvalidDataException.- A stateless explorer's read stream owns the image handle (dispose it); a keep-open explorer's read streams stay valid until the explorer is disposed.
- New
XisoExplorerOptions { KeepOpen, Share }andXisoExplorer(string, XisoExplorerOptions):KeepOpenholds one image stream for the explorer's lifetime (metadata calls use the held stream), serializes operations with an internal lock, andDispose()closes the stream — the mount/VFS shape that avoids re-opening the image for every lookup.KeepOpen: falsestays byte-for-byte identical to 1.0.2.
XisoReader.OpenImageStream(path, FileShare)andXisoExplorerOptions.Share: plain-ISO streams pass the share mode through (defaultFileShare.Read, unchanged), and CISO inputs thread it to the container file.FileShare.ReadWritelets a mounted image coexist with AV scanners or sync clients that open the.isofor write.
VolumeInfogainsCreationTime(DateTimeOffset?,nullwhen invalid; raw 0 maps to 1601-01-01),FileTimeRaw, andDescriptorSector(partition-relative sector32for every supported layout — the partition shift isDiscLseek; −1 when invalid) — all populated by the same probeGetVolumeInfoalready performs, so no second open is needed.GetVolumeInfoagrees withGetFileTimefor the same image.
- New
XisoAttributes.ToWindowsFileAttributes(byte): pure bit math mapping the raw XDVDFS attribute byte toSystem.IO.FileAttributes(ReadOnlyalways set;Directory/Hidden/System/ArchiveOR'd in;Normalwhen nothing else applies; reserved bits masked), matching SimpleXisoDrive's locked expectations.
- Modern dark theme: left navigation rail with an accent pill, card layout, green accent palette, rounded inputs and log console, and a dark native title bar on Windows.
- New ZAR tab: packs an ISO/XISO/Redump image into a
.zar(ZArchive/zstd, loadable in Xenia canary) with overwrite/skip/auto-rename collision policies; drop routing and tab-order shortcuts account for the new tab.
XisoExplorer.OpenReadStream(string)and the keep-open constructor no longer leak the image handle when a lookup or probe throws.BoundedSubStreamrejects seeks before the window start withIOException(perStreamconventions) instead of reading preceding image bytes.ReadFileBytesvalidates the path even when the buffer is empty.GetVolumeInfoskips probe candidates past EOF instead of aborting, so a trimmed XGD3 image (smaller than the global candidate offset) is detected.
- Library/Getting-Started quick samples for the VFS use case, and the Utilities
page documents explorer options, the read-bounds contract, and
XisoAttributes.
ZArchiveSharpNuGet dependency updated 1.0.2 → 1.3.0 (mount-friendly reader API, specific open-failure reasons; additive, no wire-format changes).
Release tag 1.0.2.
Targets remain net8.0 / net9.0 / net10.0; full suite green on all three
(1338 tests: 1334 passed, 4 pre-existing skips, 0 failed).
-v (and the usage header) now prints
XISOSharp v<version> for <win|linux|macos|cross-platform> - https://github.com/purelogiccode/XISOSharp
instead of the extract-xiso compatibility line. The version is the MinVer
build stamp with +build metadata trimmed, so it matches the package/assembly
version. Constants.ExisoVersion is kept for provenance and the on-disk
optimized tag (in!xiso!2.7.1 (01.11.14)) is unchanged, so image compatibility
is unaffected. The extract-xiso BSD-4-clause acknowledgement remains in the
shipped LICENSE.
Every interactive launch compares the running version against the latest
GitHub release — at most one request per 24 hours, cached at
%LocalAppData%/XISOSharp/update-check.json. A newer release prints an
[UPDATE] notice with the release page and the matching
release_<version>_<rid>.zip asset, and on an interactive console you are
offered to open the release page in your browser. The check is skipped for
-q/-Q/-v runs and test hosts, never fails the run, and can be disabled
with XISO_NO_UPDATE_CHECK=1.
--sector-layout (volume summary, per-file extents, used/free ranges),
--ranges (system/bone vs file sector ranges), and --is-optimized
(optimized-tag probe, --skip-sectors aware).
Double-clicking XISOSharp.exe with no arguments prints usage and waits for a
keypress instead of closing the console window. Scripts, pipes, test hosts, and
XISO_NO_PAUSE=1 are never blocked.
The shared Serilog pipeline in the CLI, GUI, and Tester forwards
Warning-and-above events to the bug-report API with environment, error, and
exception sections; opt out with XISO_DISABLE_BUGREPORT=1.
- CLI discovery fix for single-file bundles:
ToolLocatornow also probes the directory of the real executable (Environment.ProcessPath) afterAppContext.BaseDirectory, since self-extracting bundles run from%TEMP%\.net\.... This resolves the "CLI not found" state when the GUI runs from a published bundle. - The legacy
XISOSharp.Clifile-name fallback was removed; resolution isXISOSharp(.exe)only. - Status bar and log show a branded product label (
XISOSharp <version>) read from the CLI binary's version metadata instead of echoing the-vbanner. - The app icon is embedded in both the executable and the window.
- Framework-dependent publish builds and stages the CLI beside the GUI
automatically (previous attempts failed with
NETSDK1151).
ToolLocatoris now the shared resolver/probe used by the GUI, Tester, and BattleTests: explicit override → app directory → process directory →PATH, with a bounded, tree-killed-vprobe viaProcessRunner, plus a newToolLocatorTestssuite.Constants.Bannerreports the XISOSharp product version; the extract-xiso baseline constant is retained for provenance.
- GitHub Pages publishes the Docsify documentation, and a workflow syncs the wiki (sidebar included).
LICENSEnow carries the full third-party notices (extract-xiso BSD-4-clause, xdvdfs, XboxKit, ZArchiveSharp); distributed bundles includeLICENSEandREADME.md.- Docs and readmes refreshed for the branded banner, the new inspection verbs, update checks, the GUI bundle layout, and the shared tool locator.
No library dependency changes: ZArchiveSharp stays at 1.0.2, analyzer/Roslynator
versions are unchanged from 1.0.1.
Release tag 1.0.1.
Targets remain net8.0 / net9.0 / net10.0; full suite green on all three
(1290 tests: 1286 passed, 4 pre-existing skips, 0 failed).
Optimizing (-r / Rewrite) an image containing a zero-size directory entry —
seen in the wild in e.g. Marvel vs Capcom 2 — used to write that entry back as a
file (ARC attribute, file data) instead of a directory, breaking the game.
Cause: XisoReader.TraverseXiso in GenerateAvl mode only recursed into
subdirectories with fileSize > 0 and left AvlNode.Subdirectory as null for
zero-size ones; the writer treats null as "file". The fix assigns
AvlNode.EmptySubdirectory, matching upstream extract-xiso build
202609111233, which fixed the same bug in traverse_xiso() (subdirectory left
NULL instead of EMPTY_SUBDIRECTORY). See Rewrite mode
and XISO Format.
XisoChecksum.ComputeImageChecksum used only the BCL
IncrementalHash SHA3-256, which throws PlatformNotSupportedException on OSes
without a SHA3 provider (Windows 10 CNG, OpenSSL 1.x) — all checksum tests
failed there. New pure-managed FIPS 202 SHA3-256 (XISOSharp/Sha3.cs, no new
dependencies, trim/AOT-safe) is now used as a fallback whenever
SHA3_256.IsSupported is false; digests are identical either way (verified
against OpenSSL 3.0, including rate-boundary sizes). See
Checksums.
ZArchiveSharp1.0.1 → 1.0.2, now consumed purely as a NuGet package — the sibling-checkoutProjectReferencefallback was removed, so no side-by-sideCSharp_ZArchiveSharpclone is needed to build. See Building.Meziantou.Analyzer3.0.235 → 3.0.236 (all projects),Avalonia.Diagnostics11.3.21 → 11.3.22 (GUI, Debug-only). Dev-only, no runtime impact.
- Checksum docs (xdvdfs Compat, XisoReader, Utilities) describe the BCL/managed-fallback behavior.
- Rewrite docs (XisoWriter) and the format reference (XISO Format) document the zero-size-directory handling and upstream parity.
- Reference/build docs updated for the NuGet-only ZArchiveSharp consumption and
the
extract-xiso-build-202609111233reference drop. - Library README intro no longer pins a single extract-xiso version number.
Solution-wide Roslynator formatting cleanup (line wrapping, Fill(0) →
Clear(), internal Sha3_256 → Sha3256 rename).
Initial NuGet release: pure-C# port of extract-xiso v2.7.1 (byte-identical
output) extended with XboxKit archival workflows and xdvdfs packing
(build-image remapping, CISO, SHA3-256 checksums). See the
README for the full feature list.