Skip to content

Releases: purelogiccode/CHDStudio

3.9.0

Choose a tag to compare

@github-actions github-actions released this 04 Oct 02:02
CHD Studio 3 9 0 Release Poster

3.9.0 (2026-10-03)

Renamed to CHD Studio

  • The project, application and executable are now CHD Studio (CHDStudio): the GitHub repository moved to https://github.com/purelogiccode/CHDStudio (the old URL redirects), the solution is CHDStudio.sln, the project folder is CHDStudio/ and the Windows executable is CHDStudio.exe. The five NuGet libraries keep their names; their repository links point at the new URL from the next package release.
  • Logs and screenshots now live under %LocalAppData%\CHDStudio (old %LocalAppData%\BatchConvertToCHD logs are not migrated); the temporary work folder fallback is now CHDStudio_Temp.

Avalonia becomes the application front end

  • The Windows-only WPF front end is gone; the cross-platform Avalonia app is now the base project and builds CHDStudio.exe. It runs on Windows, Linux and macOS; official release zips remain the two Windows architectures.
  • The application project was renamed BatchConvertToCHD.Avalonia → CHDStudio, so the folder, project and executable all carry the product name.
  • Shared code and the bundled tools moved into CHDStudio/, so the project no longer links files from another folder. Windows keeps the bundled chdman/7za/CHDSharp; Linux and macOS discover them (plus ffmpeg for MP3 tracks) on PATH.
  • UI parity with the old WPF build was restored: Alt+letter button mnemonics, click-to-sort grid columns with the original header tooltips, and accessibility names on the main controls.
  • F8 screenshots are now window-scoped: while the app window is focused, F8 captures it with RenderTargetBitmap on every platform (previously a system-wide hotkey captured the foreground window on Windows only). Screenshots are saved into the screenshots folder inside %LocalAppData%\CHDStudio, beside the logs folder, with a screenshots folder next to the app as fallback.
  • The main window has a Donate button (left of About) that opens the project's donation page, and the About window now scrolls so every acknowledgement is reachable on short screens.
  • The Close button always closes the app again: shutting down from inside the window's Closing event re-entered the close in a loop, so the window never actually closed while an operation was idle.
  • The activity log is batched and capped: log lines are flushed in batches instead of one dispatcher call per line, and the on-screen text is capped, so a very large log can no longer freeze the window. The Explorer tab now hides the log panel entirely instead of leaving a clipped strip of it over the window edge.
  • The About window is complete: it now carries the full third-party acknowledgements (CHDSharp, CHDMAN, Avalonia, the in-house image libraries, VideoGameFileSystemParser, SharpCompress, NAudio, Serilog and 7-Zip), a License section (GPL-3.0 with a link), the copyright line, and donate/release links.

New CHD Explorer tab

  • Browse a CHD like a disc: pick a .chd, choose the file-system parser matching its console/system (35 formats, PlayStation auto-detection by default), and navigate the folder tree in a grid. Double-click a folder to open it, a file to extract and open it, or use Extract to save a folder to disk.
  • Image Info: an expander under the parser drop-down shows a read-only report built from the CHD header and map — version, hunk/unit sizes, logical size, image type (CD/GD-ROM/DVD/HDD/A-V), codecs, metadata tags, the CD/GD-ROM track table and the per-codec hunk distribution (the scan is capped at the first 1,000,000 hunks for very large images).
  • Backed by VideoGameFileSystemParser 1.3.0 (https://www.nuget.org/packages/VideoGameFileSystemParser), rebuilt against CHDSharp 1.4.3 and published for this release.

Laserdisc A/V support

  • .avi laserdisc captures convert with createld: the built-in CHDSharp encoder assembles every video frame into MAME's raw chav layout and compresses it with the avhu codec (delta-RLE Huffman video + per-channel mono FLAC audio), one frame per hunk, exactly like chdman createld; the Force CD/DVD overrides are ignored for an AVI.
  • A/V CHDs extract back to AVI in-process: the Extract tab gained a Laserdisc (.avi) format, and Auto-detection now reads the CHD's own flags — a CHD with no CD/DVD/HDD metadata is an A/V image and is extracted with CHDSharp's MAME-parity ExtractLaserDisc writer (YUY2 video + PCM audio). chdman extractld/extractraw remain the automatic fallback when the library cannot decode the CHD.

Verification checksum reports

  • Optional <name>.checksums.txt next to each verified CHD (checkbox on the Verify tab): one whole-image SHA-1, CRC-32 and XXH3-64 plus per-track SHA-1, CRC-32 and XXH3-64 for CD/GD-ROM images. The whole-image hashes are computed over the decompressed image, so they match a hash of the extracted data rather than the CHD header's combined hash. The report follows the CHD into the Success folder, and a report that cannot be written is a warning — never a verification failure.

Live tool output, progress and read-ahead

  • Every chdman output line now reaches the activity log, progress included, with completion lines ("Compression complete"/"Extraction complete"/"final ratio") marked with a check. The on-screen log caps a single line at 2,000 characters and appends at most 200 lines per flush, so a chatty tool cannot stall the UI, and the file sink rolls at 10 MB.
  • The built-in CHDSharp encoder and reader log progress every 10% for conversion (ratio=), verification, extraction and checksum hashing, so long library operations visibly keep running without one line per hunk.
  • Extraction pre-decompresses 16 hunks in the background (ChdFile.ConfigureReadAhead), so sequential reads overlap the disk writes on the single-file (DVD/HDD) and multi-track (CD/GDI) paths.

Built-in CHD encoder — no CHDSharp CLI

  • CHDSharp now runs in-process (the NuGet library, not the bundled CHDSharp.exe CLI, which has been removed). On Linux and macOS it is the encoder, so those builds need no bundled native tool; on Windows the bundled chdman remains the primary encoder and the built-in CHDSharp is the automatic fallback. It mirrors chdman's commands and defaults (createcd/createdvd/createhd/createraw) and produces byte-identical CHDs.
  • Conversion can no longer fail for a missing encoder; a missing Windows chdman.exe only logs that the built-in encoder will be used. The status bar shows CHDSharp as always available.
  • Official 7-Zip 26.03 console binaries for Linux and macOS are now bundled (7zz, static builds on Linux and a universal binary on macOS) and copied next to the app for the matching runtime; 7-Zip-License.txt is included. Windows keeps 7za.exe.

Reliability fixes

  • CSO v2 / ZSO images decode correctly. The reader applied CSO v1 index semantics to version 2: LZ4 blocks (high bit set) were returned as raw compressed bytes and stored or deflate blocks were pushed through the LZ4 decoder. Blocks are now classified the way the format defines them — compressed only when smaller than a full block, with the high bit selecting LZ4 over deflate — and a short final stored block is zero-padded instead of failing.
  • A truncated CHD is never accepted as a success. When chdman exited nonzero but left a non-empty file (the classic disk-full case), the app treated it as success and could delete the source. The output is now validated with the built-in reader first, and a partial file is discarded.
  • Deleting originals never reaches outside the input folder. A descriptor naming ..\..\other\game.bin (or an absolute path) could make the batch delete files it never converted; referenced files outside the selected input folder are now kept and reported.
  • Archived discs keep their folder structure. Two same-named discs in different archive subfolders (Disc1/game.cue, Disc2/game.cue) both produced game.chd, and the second silently replaced the first; the archive's internal path is now preserved. The same-batch duplicate guard keeps the first product and reports any remaining collision.
  • Extracting next to an existing disc set no longer replaces it. The "extract into a subfolder instead of overwriting" rule now also covers cue/gdi sets (checking their BIN too) and applies to the chdman fallback, not just the built-in reader. Cancelling a fallback extraction now kills the chdman child instead of leaving it running.
  • A PBP whose volume descriptor declares zero sectors no longer extracts an empty BIN and reports success; every index entry is written when the size is unknown.
  • Expected network and user conditions no longer file bug reports: an update check that times out (now bounded to 30 seconds instead of the shared client's 100) and a CHD Explorer parse failure caused by choosing the wrong file-system parser are logged as network/user conditions instead of being sent to the bug tracker.
  • PBP I/O failures carry the underlying OS error (PBPSharp 1.1.3): an open or extraction that fails with IoError records the file, the OS message and whether it was a read or a write, so a locked file, a failing disk or a full drive is identifiable from the log and the bug report.
  • CD-R/CD-RW MDS v2 descriptors read their track lengths from the extra block like pressed CDs, and a .ccd claiming a huge TocEntries value can no longer make the parser allocate unbounded tracks.
  • MP3 decoding on Linux/macOS is cancellable: ffmpeg is awaited with the operation token and killed on cancel instead of blocking the window in an uncancellable `WaitForExit()...
Read more

3.8.0

Choose a tag to compare

@github-actions github-actions released this 20 Sep 01:57

3.8.0 (2026-09-19)

Multi-part RAR archives now convert end to end (#67305)

  • A .partNN.rar set is decoded from its first volume, whether the batch lists the first part or a later one. SharpCompress can only follow the whole set when it is opened by path through the first volume, so a later part is redirected to the first volume found beside it; when the first volume is missing the file is skipped with a message naming it instead of failing inside the decoder. This supersedes the 3.7.0 note that multi-part RAR still needed manual extraction.
  • RAR sets renamed to .001 are extracted by content instead of being refused, because the extension hides what the content says.
  • A set is offered once: only the first volume stays in the batch, filtered both at the folder scan and again before the batch starts, so a multi-part RAR is no longer extracted once per volume.
  • Malformed archives are classified as data, not app bugs: SharpCompress decoder crashes (NullReferenceException, ArgumentOutOfRangeException, IndexOutOfRangeException) on corrupt data no longer trigger the temp-copy retry or an automatic bug report.
  • Volume discovery covers new-style .partNN.rar, numbered .001 sets and old-style .rar + .r00 volumes, and the disk-space preflight measures the whole set. A real WinRAR-built multi-volume fixture is committed so the path is tested without WinRAR at test time.

Alcohol 120% support upgraded — MDSSharp 1.1.0

  • The library was renamed Alcohol120Sharp → MDSSharp and published as MDSSharp 1.1.0 (https://www.nuget.org/packages/MDSSharp) with package metadata, a README and an icon matching the other embedded libraries.
  • Pregaps are now described: when the descriptor records pregap and track length, the generated cue carries INDEX 00 if the data file already contains the pregap sectors, and pregaps the file does not contain are rebuilt as zeros so the cue can still express them without shifting the tracks that follow.
  • Multi-file descriptors are joined in track order before preparation, and the temp-space preflight accounts for the rebuilt or joined image.
  • The descriptor is read more completely: medium type (CD/CD-R/CD-RW/DVD/DVD-R), each track's extra block (pregap and length) and the footer data-file names (single-byte or UTF-16, *.mdf wildcards) are parsed, and the track mode now uses the low nibble of the mode byte exactly as libMirage's reverse engineering established.
  • A CD descriptor whose sectors are the cooked 2048 bytes is converted through a MODE1/2048 cue instead of being treated as a DVD image.

ISZ support upgraded, library renamed to ISZSharp

  • Genuine UltraISO files now decode. The ISZ library was checked against libMirage's ISZ filter and isz-tool, the two independent open-source readers, and now handles the real-file behaviours the published specification omits: the segment and chunk tables are de-obfuscated (XOR with B6 8C A5 DE, the complement of IsZ!) and bzip2 chunks get their stripped BZh header restored before decompression. Without those, a real .isz could not be decoded at all — the old test fixtures mirrored the same omission, so the suite passed while the reader could not open a genuine file.
  • More layouts are read: images whose header declares no chunk table (one raw run), and split images named game.part01.isz/game.part02.isz as well as the spec's game.i01/game.i02.
  • UltraISO's checksum is validated when the 64-byte header carries one; a mismatch is reported as damaged and the output deleted, like a size shortfall. A failed or cancelled decode now always deletes its partial output.
  • A split image whose cut lands inside a chunk now decodes. A later segment stores the tail of the straddling chunk (left_size) between its header and its chunk data; the reader started at the chunk data offset and skipped that tail, so a complete split image was rejected as truncated. Fixed in ISZSharp 1.0.1, and the split fixtures now use UltraISO's real segment layout, so the round-trip tests exercise it.
  • The library now matches the other embedded packages' shape: renamed UltraIsoSharp → ISZSharp, multi-targeting net8.0;net9.0;net10.0, shipping XML docs, a README and an icon, and published on NuGet (https://www.nuget.org/packages/ISZSharp) as 1.0.0, then 1.0.1 with the split-boundary fix.

Smaller fixes

  • Deleting originals for an Alcohol image now removes every data file the descriptor names and every volume of a split set, not just the first.
  • A multi-file .mds descriptor with one declared file missing is reported by name instead of silently falling back to the file that happens to be present, which could convert a truncated image.
  • A folder holding both .part1.rar and .part01.rar keeps the spelling whose next volume exists, so the set is still decodable.

Housekeeping

  • Version bumps: application 3.8.0, MDSSharp 1.1.0, ISZSharp 1.0.1.
  • Library updates: Meziantou.Analyzer 3.0.264.
  • Test suite grew to 896 tests (real multi-part RAR extraction, ISZ real-layout splits and checksums, MDS pregap/multi-file handling, RAR volume filtering).

3.7.2

Choose a tag to compare

@github-actions github-actions released this 16 Sep 13:59

3.7.2 (2026-09-16)

Recovered images with Mode 2 or subchannel layouts now convert (#67139)

  • A decoded ECM whose source was not a plain 2352-byte image is no longer reported as damaged. Alcohol .mdf rips can store 2336-byte Mode 2 sectors, or 2448/2368-byte sectors carrying subchannel data, and all three were skipped with "the decoded image is not a whole number of 2352-byte CD sectors or 2048-byte data sectors" even though the ECM trailing checksum had already proved the file intact. The new RecoveredImageClassifier routes every recovered image (ECM, ISZ, archive, split set) by its actual layout: raw 2352-byte CD sectors get a generated cue as before, 2048-byte sectors convert as a DVD image as before, 2336 and 2324-byte Mode 2 sectors get a MODE2/2336/MODE2/2324 cue (both round-trip losslessly through chdman 0.289), and 2448/2368-byte rips have their subchannel tail stripped to 2352 and are then sniffed and cued — the same strip the .mds path already used. Only a size that fits no standard layout is still reported as damaged.
  • The "not a whole number of 2352-byte CD sectors..." skip is now excluded from automatic bug reports, like the other user-data conditions.

Housekeeping

  • Test suite grew to 851 tests (recovered-image layout routing: 2336/2324 cues, 2448/2368 stripping, skip reasons).

3.7.1

Choose a tag to compare

@github-actions github-actions released this 16 Sep 03:52

3.7.1 (2026-09-16)

MDS descriptors find renamed and nested data files (#66955, #66989)

  • A .mdf no longer has to sit beside its .mds under the exact same name. The descriptor's data file is now found when it was renamed with a decoration (Game.mds beside Game (USA).mdf — but never when the name continues with a letter or digit, so Game 2 never matches Game), when it sits one folder down (only an unambiguous exact-name match, so a sibling game's image is never picked up), and split .i00 sets are located by base name even when other sets share the folder. File names that differ only in Unicode composition (Cafe\u0301 vs Café) are treated as equal.
  • Ambiguity is refused, not guessed: with Game (Disc 1).mdf and Game (Disc 2).mdf both beside Game.mds, the disc is skipped with the existing "data file was not found" message instead of converting the wrong disc.

Transient network/NAS failures no longer abort a batch (#66854)

  • Archive copies retry transient I/O errors before the temp-copy fallback runs: a failed direct extraction (for example an SMB hiccup while streaming from a NAS) is demoted to a debug notice, and the automatic copy that precedes the fallback retries up to four times with increasing delays. Missing-source errors are never retried.
  • Network-unavailability detection is locale-independent: the Win32 error codes (bad netpath, unexpected network error, netname deleted, …) are now read from the exception's HResult, so non-English Windows builds (e.g. French "Erreur réseau inattendue.") are recognized without relying on localized message text.

Startup crash suppressed: desktop composition disabled (#67014, #67084)

  • A user with desktop composition disabled (registry/DWM tweak or third-party theming tool) got a COMException 0x80263001 from WindowChromeWorker.DwmExtendFrameIntoClientArea reported as an unhandled dispatcher exception. It is now suppressed like the other known-benign WPF-internal exceptions: the window simply runs without the glass frame effect.

Bug-report noise reduction (#67027)

  • "The output folder is not writable" (root of C:\, Program Files, a read-only drive) is excluded from automatic reports — the batch-start probe already shows one actionable dialog and nothing was converted.

Housekeeping

  • Release zips are leaner: the library .xml IntelliSense doc files (CCDSharp.xml, CSOSharp.xml, PBPSharp.xml) are no longer included — nothing at runtime uses them.
  • Library updates: Meziantou.Analyzer 3.0.259, Microsoft.NET.Test.Sdk 18.10.1.
  • Test suite grew to 842 tests (decorated/ambiguous/subdirectory/split/Unicode .mdf lookup, transient network copy retries, SFO size bounds, the new bug-report exclusion).

3.7.0

Choose a tag to compare

@drpetersonfernandes drpetersonfernandes released this 10 Sep 00:35

3.7.0 (2026-09-09)

Split archive volume sets now convert end to end

  • Extract split 7-Zip and ZIP sets in-app (.7z.001/.zip.001 style): what used to be skipped with "extract the set manually" is now extracted with the bundled 7za.exe and converted like any other input. The whole set is located from the first volume, disk space is checked against the total size of all volumes, and the extracted image is classified (cue/gdi/toc convert directly, bare images get the same recovery path as joined sets). Multi-part RAR still needs manual extraction, since the app does not carry RAR tooling.
  • Split-set skip notices (missing volume, no convertible image inside, missing 7za) are user-data conditions and are excluded from automatic bug reports.

Output folder convenience and resilience

  • Output folder auto-fill: selecting a source folder (browse or command line) now sets the Output CHD destination to the same folder when the output path is still empty. This is safe by construction — outputs are staged <name>.chdtmp and moved into place only on success, and existing CHDs are never inputs.
  • Disconnected output drive detected up front: a batch whose output folder sits on an unplugged USB stick or a dropped network drive now probes the folder once and reports a single actionable message, instead of failing every file with a confusing path error mid-batch.
  • Temp-folder cleanup is best effort: staged files carrying the read-only attribute (or locked by antivirus) no longer abort the batch or get reported as app bugs — attributes are cleared before deleting, directory read-only flags included, and a leftover temp folder is only logged as a warning.

PBP extraction — PBPSharp 1.1.0

The bundled PBP library was aligned with all four reference implementations (popstation, PSX2PSP, iPoPS, pop-fe), so PBP files that earlier versions rejected now extract:

  • pop-fe multi-disc PBPs no longer rejected: pop-fe leaves the four "template" DWORDs of the PSTITLEIMG000000 header zero (popstation/PSX2PSP write fixed magic values there). The header values are no longer validated — the disc position table, which is what actually locates the discs, is honoured regardless.
  • PARAM.SFO is no longer required: a missing or corrupt SFO leaves title/disc-id metadata empty instead of rejecting the whole file. None of the reference tools read the SFO when extracting disc images.
  • zlib-wrapped PSAR blocks decompress: blocks authored with zlib.compress (2-byte header + Adler-32) instead of raw deflate are retried as zlib streams after the raw inflate fails.
  • pop-fe index layout supported: the official 16-bit index entry (size uint16 at bytes 4–5, stored-flag byte at 6, SHA-1 at 8–23) is read directly; tools that write the size as a 32-bit int (popstation/PSX2PSP/iPoPS) are still covered because bytes 6–7 stay zero there.
  • Stored/uncompressed blocks flagged in the index (pop-fe --compression 0) are copied verbatim instead of being inflated.
  • Incompressible blocks accepted: index entries a few bytes larger than the raw 16-sector block (deflate framing on incompressible data) are no longer rejected.
  • 64-bit offset math for block reads, so multi-gigabyte files cannot overflow the 32-bit offset computation.
  • Hardened against corrupt indexes: an entry claiming to be a stored block larger than a full block is reported as corrupt data instead of overrunning the read buffer, and the split-set disk-space check now uses the whole volume set rather than the first volume alone.

Bug-report filtering additions

  • chdman crashes during the startup probe (entry-point-not-found / illegal-instruction exit codes — an installation incompatibility, not app logic) are excluded.
  • "Output folder is not available" notices (unplugged drive) are excluded.

Housekeeping

  • Version bumps: application 3.7.0, PBPSharp 1.1.0.
  • Library updates: Meziantou.Analyzer 3.0.231, Microsoft.NET.Test.Sdk 18.10.0.
  • Test suite grew to 835 tests (split-volume-set extraction, PBP index/deflate variants, pop-fe multi-disc, SFO tolerance, bug-report exclusions).


Contributors

Thanks to everyone who contributed to this release:

  • @drpetersonfernandes (Peterson Fernandes) — split 7z/zip volume-set extraction, PBPSharp 1.1.0 (pop-fe compatibility, zlib-wrapped and stored PSAR blocks, hardened block reader), resilient temp cleanup, output-folder availability probe, bug-report filtering, documentation.
  • @catchem88 (Adrian Liunardo) — automatic Output CHD destination fill when selecting a source folder (#10).

release_3.6.0

Choose a tag to compare

@drpetersonfernandes drpetersonfernandes released this 07 Sep 20:07

What's New in 3.6.0

Released: 2026-09-07

Fixed

  • Closing the app during startup no longer reports a bug. A window closed while the startup sequence was still running produced a TaskCanceledException report; cancellation during shutdown is now recognised as the normal exit path and logged silently.
  • Corrupt PBP deflate streams are classified correctly. A malformed compressed block inside a PSAR could drive the SharpZipLib inflater into a raw IndexOutOfRangeException, which escaped the typed error handling and surfaced as an unclassified "Index was outside the bounds of the array" failure. It is now normalised to DecompressionError, so the caller reports a decompression failure the way any other bad block is reported.

Improved

  • Bug reports carry less noise. Conditions that describe the user's environment or data — chdman rejecting a cue or image with a parse error, I/O failures on failing or disconnected drives, files whose content does not match their extension, CHD open/read failures during extraction, file-move failures after a conversion, and encoder start failures — are no longer sent to the bug API. The application still logs each with per-cause guidance; the classified failure at the end of a file's attempt still reaches the developer.
  • Fewer warnings for routine outcomes. Notices that describe expected behaviour rather than trouble are now logged as information: the automatic chdman → CHDSharp fallback after chdman fails on a file, cue generation falling back to converting an image as-is (read-only media, cross-volume path), and the low-free-space heads-up shown before a large conversion starts.
  • chdman crash codes are easier to read. 0xC0000139 (STATUS_ENTRYPOINT_NOT_FOUND) is now decoded with guidance: the bundled build is incompatible with the installed Windows version — install updates / the latest Visual C++ redistributable or use a chdman build for your OS. The "incompatible CPU" guidance also names the Windows version as a possible cause.
  • Missing-encoder messages trimmed. The download URL for chdman was removed from the startup notices and the critical-missing-encoders dialog; the message now states plainly what is missing and what to place in the application folder.

Internal

  • Analyzers and libraries upgraded: Meziantou.Analyzer 3.0.226, NAudio 3.1.0.
  • Code style normalised across all projects (brace indentation rules), with whatsnew.md retired in favour of this WhatsNew.md.
  • Test suite grown to 820 passing tests, including a regression test for the corrupt-PBP-block classification and coverage for the new bug-report exclusion patterns.

Packaging

  • Binaries ship as a single-file, framework-dependent executable — the .NET 10.0 Desktop Runtime must be installed. chdman, CHDSharp and 7za for your architecture are bundled next to the app exe, together with the readme and license.

release_3.5.1

Choose a tag to compare

@drpetersonfernandes drpetersonfernandes released this 02 Sep 04:18

What's New in 3.5.1

Released: 2026-09-02

Changed

  • chdman is now the primary encoder. Conversions run on the bundled chdman, the reference MAME CHD encoder. If chdman fails on a file, the conversion automatically falls back to CHDSharp.exe — the managed encoder whose output is byte-identical to chdman. The fallback reuses the already-prepared cue work directory and ASCII staging, so a cue's work set stays valid and nothing is re-prepared.
  • A batch is no longer blocked when only one encoder is present. If chdman.exe is missing but CHDSharp.exe is available, every file is converted with CHDSharp; if CHDSharp is missing, chdman carries the batch alone. The startup notice now shows a critical error only when both encoders are missing.
  • Duplicate output targets are skipped, not overwritten. When two inputs in the same batch would produce the same .chd (for example Game.7z and Game.iso sitting side by side), the redundant input is skipped up front and the resolution is logged — the first non-archive input wins, and the redundant archive is no longer extracted and converted just to be overwritten.

Fixed

  • PSP .pbp extraction now uses the reference-compatible SharpZipLib inflater for PSAR block decompression, so images that the stricter .NET DeflateStream rejected with InvalidDataException extract correctly. The bundled CHDSharp was updated as part of this fix.
  • A bare .bin with no cue and no readable sector header (for example a console BIOS dropped into the input folder) is again treated as informational only — it logs guidance instead of triggering a bug report.
  • Live write-speed (MB/s) stat card now updates during CHDSharp-driven conversions (it previously froze at 0.0 MB/s), and the elapsed-time card ticks every second during long single-file conversions.
  • chdman Input/output error messages now include actionable guidance (failing or disconnected drive, antivirus/cloud-sync file locks, damaged image).

Improved

  • Bug reports are de-duplicated: an identical warning repeated inside a 10-minute window (a failing batch retrying the same input, a loop logging the same warning per file) is sent once.
  • Alcohol 120% (.mds/.mdf) and UltraISO (.isz) support moved into standalone. No functional change.

Internal

  • Analyzers upgraded: Meziantou.Analyzer 3.0.200, Roslynator.Analyzers 5.0.0 added, with analyzer fixes applied across the solution.
  • Removed the internal CHDBattleTest battleground project (its parity results live on in the CHDSharp documentation); updated the bundled 7-Zip binaries.
  • Test suite grown to 813 passing tests, including new coverage for duplicate-output resolution and ISZ header sizing.

Full Changelog: release_3.5.0...release_3.5.1

release_3.5.0

Choose a tag to compare

@drpetersonfernandes drpetersonfernandes released this 31 Aug 03:24

What's New in Batch Convert to CHD 3.5.0

Released August 31, 2026 — previous release 3.4.2

New Features

Smart input routing by content (PR #8)

Every input is now identified by its leading bytes, not by its file extension. A raw 2352-byte CD dump named .iso, .img, .bin or .isz converts correctly as the CD it is, instead of failing with "Data size is not divisible by sector size". Sector-size validation now also understands the 2448 and 2368 subchannel layouts.

Three new image formats — all decoded in-process, no external tools

  • ISZ (EZB Systems spec 1.00) — zlib, bzip2, stored and all-zero chunks, including images split across .i01/.i02 segments matched by volume serial number
  • ECM — full in-process decoding with EDC and Reed–Solomon parity regeneration, verified byte-for-byte against Neill Corlett's reference implementation; the external unecm.exe dependency is gone and ARM64 gets the same feature set
  • Alcohol 120% .mds/.mdf — track table parsed into a matching cue, subchannel tail stripped from 2448/2368-byte sectors, and a 2048-byte .mdf converts as a DVD image

Split-volume and split-track support

  • Multi-part sets (.001/.002, .i00/.i01) are rejoined before conversion; a missing part is reported instead of handing the encoder a partial image (only the first volume is listed)
  • A bare .bin is accepted as an input with a generated cue, and split-track (Track N) bin sets get a multi-FILE cue so the CDDA audio survives
  • Raw images already covered by a sibling descriptor (cue/bin, CloneCD) are dropped from the batch, so a set converts once through its descriptor rather than once per file

CHDSharp encoder with chdman fallback

Conversions now run on CHDSharp (v1.4.3), the project's own managed CHD encoder, which produces byte-identical output to chdman (verified by an exhaustive battleground comparison across the full corpus of CD, GD-ROM, DVD and HDD images). If CHDSharp fails for any reason, the conversion automatically falls back to the bundled chdman 0.289. ARM64 builds use OS-native binaries with fallback to the other architecture.

Safer conversion staging

Conversions are written to a .chdtmp file and moved into place only on success — a failed or retried conversion can no longer truncate a working CHD that shares its output name. Free-space is checked immediately before the encoder starts, and inputs that collide on the same output name are warned about at batch start.

Extraction no longer overwrites

Extraction never overwrites existing files and never asks. If a disc's output would land on same-named files, the whole set is diverted into a subfolder named after the disc instead — cue/gdi FILE entries stay valid without rewriting. Discs with nothing in their way are unaffected.

Update check with redundant sources

Update checks try the purelogiccode releases API first and fall back to the legacy releases URL; GitHub rate limits (403/429) skip the check silently instead of logging errors.

Static dark theme

The window background is now a solid dark color. The previous adaptive Mica backdrop tinted the window with your desktop wallpaper — it doesn't anymore.

Bug Fixes

  • Non-ASCII / overlong paths — chdman is now routed around them anywhere in the path (not just file names); conversions are staged in ASCII-safe temp directories and cue work directories avoid a non-ASCII %TEMP%
  • chdman startup crashes (e.g. 0xC000001D) are detected with actionable guidance instead of a silent hang; the encoder-lock probe is relaxed and output-folder writability is pre-flighted
  • Folders accidentally passed as disc images are skipped
  • cue-referenced .raw audio tracks are auto-detected and converted with -us 2352
  • Generated cues are written on the image's own volume (chdman cannot follow absolute FILE paths), and CCDSharp cue output no longer writes a BOM that chdman's cue parser can't skip
  • Broken cue FILE lines are resolved by name beside the cue, by extension swap, or — for single-FILE cues — by elimination
  • Encoder failure messages are descriptive even when chdman only prints a fatal-error summary
  • Fixed a trailing-period removal loop in filename sanitization, a CTS disposal leak, an OCE on cancellation during file loading, GDI handle leaks in screenshots, endianness issues (BinaryPrimitives), and 17 other issues found in a deep code audit
  • Failed extractions and conversions clean up after themselves; file copies retry on transient locks

Engineering & Housekeeping

  • New CHDBattleTest battleground harness — benchmarking and verifying chdman vs. CHDSharp decode/encode parity across a 56-file corpus (CD, GD-ROM, DVD, HDD), including head-to-head byte-parity, SHA1 and decode verify rows
  • NAudio 3.0.1 migration with a corrected MPEG-2 L3 test fixture; WPF-UI 4.3.0
  • Repository migrated to the purelogiccode organization
  • Documentation wiki overhauled and published at https://purelogiccode.github.io/BatchConvertToCHD/ (13 pages covering user guide, architecture, services, testing and troubleshooting)
  • Full path/crash hardening documented in the wiki; PBPSharp error codes (TruncatedPsar/InvalidSfo) are now distinguishable
  • 151 new tests — 751 total

Upgrade Notes

  • The external unecm.exe dependency has been removed — no action needed, ECM files just work
  • If you relied on extraction overwriting existing files, note that duplicates are now diverted to a disc-named subfolder instead
  • Update-check URLs now point at purelogiccode; the old drpetersonfernandes releases remain as a fallback

What's Changed

  • feat: route inputs by content and add ISZ, ECM and Alcohol support by @catchem88 in #8

New Contributors

Full Changelog: release_3.4.2...release_3.5.0

release_3.4.2

Choose a tag to compare

@drpetersonfernandes drpetersonfernandes released this 13 Aug 04:57

Bug Fixes

ToolTip/Popup crash on some Windows systems

Fixed the WPF-internal crash (FileNotFoundException from PopupSecurityHelper.ForceMsaaToUiaBridge) that occurred when a tooltip or popup tried to open on systems where the Windows accessibility bridge (MSAA → UIA) cannot be loaded — e.g. broken/missing UIAutomationCore.dll or third-party accessibility/security software. This was an OS-level condition the application cannot act on: the tooltip simply never appeared. It is now suppressed gracefully instead of being reported as an application crash.

chdman conversion failures now show the real error

When chdman rejected an input file it printed the actual cause before its generic Fatal error occurred: N exit summary — but the app only surfaced the last line. The error picker now skips the exit summary and reports the real cause, so the log tells you why a conversion failed (e.g. an unrecognized track type, a missing bin file, an unsupported format).

chdman fallback extraction

If the built-in CHD reader cannot decode a CHD — a corrupt file or an A/V (laserdisc) CHD (Dragon's Lair, Cliff Hanger, Mach 3, Firefox, Cube Quest, …) — the app now retries automatically with chdman instead of failing with a cryptic Failed to read hunk 0: Chderrdecompressionerror message:

  • Disc CHDs fall back to extractcd / extractdvd / extracthd (cue/bin, iso, img).
  • Laserdisc CHDs (no CD/DVD/HDD metadata) fall back to extractld (AVI, MAME 0.285+) or extractraw (raw dump) on older chdman builds.

No more leftover temp files after failed extractions

Failed extractions no longer leave _extract_temp_* debris behind in your output folder. Leftover files are cleaned up automatically (locked files are skipped with a warning).

Quieter, more accurate bug reporting

Known user-data and environment conditions — corrupt files, chdman's own crashes and exit summaries, rate limits — no longer generate bug reports. CHDSharp and PBPSharp extraction failures are still reported, with debug details (file size, disc index/count, numeric error codes): both readers are under active development, and their extraction failures are exactly the signal needed to fix them.

Hardened PBP extraction (PBPSharp)

The built-in PBP (PlayStation EBOOT) reader received a robustness pass:

  • Multi-disc header validation — the fixed magic values of the PSTITLEIMG000000 header are now checked, so corrupted/foreign multi-disc PBPs are rejected with a clear error instead of failing later with a vague one.
  • SFO validation — the SFO metadata magic is verified; a corrupt SFO region now reports CorruptFile instead of parsing garbage.
  • Empty ISO index — discs without ISO data (PSP applications, truncated files) are rejected cleanly instead of crashing with an out-of-range exception.
  • Corrupt block lengths — negative/oversized index lengths can no longer crash the reader; they map to proper error codes.
  • Read-only contract — the library's package description now states explicitly that it can open and extract PBP files but cannot create or modify them.

Maintenance

  • Updated Meziantou.Analyzer to 3.0.151 (build-time only, no runtime impact).

Tests

  • 590 tests, all passing (new tests covering the error-line selection, extraction messages, chdman fallback command building, the refined bug-report filters, and the PBPSharp validation/error paths).

Full Changelog: release_3.4.1...release_3.4.2

release_3.4.1

Choose a tag to compare

@drpetersonfernandes drpetersonfernandes released this 11 Aug 04:29

Meaningful conversion errors

When chdman fails, the application now reports the real error line instead of a progress line. Previously, failures could surface as Failed to convert '...': Compressing, 0.0% complete... (ratio=100.0%) — the actual error (e.g. couldn't find bin file [...]) was buried at the end of chdman's output and is now correctly selected.

Resilient file moves

Moves performed after verification (into Success/Failed folders), during multi-track extraction, and when moving the final CHD into place now retry automatically with backoff (~45 seconds) when the file is briefly locked by antivirus software or the Windows file indexer. Transient locks no longer fail a verification move or abort a disc extraction midway.

Better PBP failure diagnostics

Failed to extract PBP file: <name> reports now include the underlying PBPSharp reason (e.g. Failed to open PBP file: ...), so the real cause is diagnosable instead of a bare filename.

Less bug-report noise

The automatic bug-reporting pipeline no longer treats user-data conditions as application bugs. Corrupt or unopenable CHD files (Not a valid CHD file, Invalid or corrupt data, Cannot open file), partial extractions, and missing referenced files remain visible in the in-app log but are no longer submitted as bug reports.

Cleaner temp-folder fallback

Selected temp root ... is not writable, falling back to system temp is now an informational message — the graceful fallback is expected behavior, not an error, and no longer generates bug reports.

Project wiki

A complete documentation wiki was added under docs/ — 14 pages covering the user guide, architecture, conversion pipeline, extraction & verification, services and utilities references, the bug-reporting system, the embedded libraries (CCDSharp/CSOSharp/PBPSharp), testing, application data, and troubleshooting. The wiki is also deployable to GitHub Pages via a bundled workflow.

🔧 Updates

Component From To
SharpCompress 0.50.3 0.50.4
Meziantou.Analyzer (build-time) 3.0.138 3.0.141

Full Changelog: release_3.4.0...release_3.4.1