diff --git a/CHDSharpCli/README.md b/CHDSharpCli/README.md index 24d8953..5953957 100644 --- a/CHDSharpCli/README.md +++ b/CHDSharpCli/README.md @@ -17,7 +17,7 @@ The binary is named `CHDSharp` (e.g. `CHDSharp.exe` on Windows). It accepts the same subcommands and options as MAME's `chdman`, plus additional convenience commands. -> **v1.6.1** - expected user errors (bad flags, missing paths, sector-misaligned input, an existing output without `--force`) are logged locally but no longer posted to the Bug Report API; real failures still are. Six platform bundles are attached to every release (`CHDSharp_-_v.zip`). Release bundles are framework-dependent single-file binaries and require the .NET 10 runtime; the library targets `net8.0` / `net9.0` / `net10.0`. +> **v1.6.2** - extraction failures keep their real cause: the underlying exception is logged, data/codec errors map to `Chderrdecompressionerror` and output I/O to `Chderrwriteerror`. Read-ahead teardown can no longer race a disposed semaphore, and damaged GD-ROM metadata returns `Chderrinvaliddata`. Six platform bundles are attached to every release (`CHDSharp_-_v.zip`). Release bundles are framework-dependent single-file binaries and require the .NET 10 runtime; the library targets `net8.0` / `net9.0` / `net10.0`. --- diff --git a/CHDSharpLib/CHDFile.cs b/CHDSharpLib/CHDFile.cs index 6025f53..a369f63 100644 --- a/CHDSharpLib/CHDFile.cs +++ b/CHDSharpLib/CHDFile.cs @@ -3986,9 +3986,12 @@ public ChdError ExtractToc(string tocPath, string binPath, IProgress 0 }) + return new ExtractResult(created, trackResults, ChdError.Chderrinvaliddata); + var gdTrackFiles = new List(); foreach (var track in Tracks!) { @@ -4169,8 +4177,14 @@ public ExtractResult ExtractToDirectoryWithReporting( File.WriteAllText(gdiFile, GenerateGdiDescriptor(trackNames, cooked)); created.Add(gdiFile); } - catch (Exception) + catch (Exception ex) { + Log.LogWarning( + ex, + "Failed to write the GDI descriptor for '{BaseFileName}' in '{OutputDir}'", + baseFileName, + outputDir + ); return new ExtractResult(created, trackResults, ChdError.Chderrwriteerror); } @@ -4228,6 +4242,7 @@ public ExtractResult ExtractToDirectoryWithReporting( } catch (Exception ex) { + Log.LogWarning(ex, "Failed to write extracted data"); return new ExtractResult( created, trackResults, @@ -4369,9 +4384,12 @@ CancellationToken cancellationToken { throw; } - catch (Exception) + catch (Exception ex) { - return ChdError.Chderrwriteerror; + Log.LogWarning(ex, "Failed to write extracted data"); + return ex is InvalidDataException + ? ChdError.Chderrdecompressionerror + : ChdError.Chderrwriteerror; } } @@ -4473,9 +4491,12 @@ CancellationToken cancellationToken { throw; } - catch (Exception) + catch (Exception ex) { - return ChdError.Chderrwriteerror; + Log.LogWarning(ex, "Failed to write extracted data"); + return ex is InvalidDataException + ? ChdError.Chderrdecompressionerror + : ChdError.Chderrwriteerror; } } @@ -4602,9 +4623,12 @@ CancellationToken cancellationToken { throw; } - catch (Exception) + catch (Exception ex) { - return ChdError.Chderrwriteerror; + Log.LogWarning(ex, "Failed to write extracted data"); + return ex is InvalidDataException + ? ChdError.Chderrdecompressionerror + : ChdError.Chderrwriteerror; } } @@ -4772,9 +4796,12 @@ CancellationToken cancellationToken { throw; } - catch (Exception) + catch (Exception ex) { - return ChdError.Chderrwriteerror; + Log.LogWarning(ex, "Failed to write extracted data"); + return ex is InvalidDataException + ? ChdError.Chderrdecompressionerror + : ChdError.Chderrwriteerror; } } @@ -4848,7 +4875,19 @@ internal bool TryGet(uint hunknum, byte[] buffer) return false; Array.Copy(data, 0, buffer, 0, _chd._chd.Blocksize); - _semaphore.Release(); + + // Disposal may release the semaphore while a cached hunk is still being consumed. + // The permit is irrelevant once the manager is gone, so a disposed semaphore is not + // an error and must never surface as an unobserved exception. + try + { + _semaphore.Release(); + } + catch (ObjectDisposedException) + { + // The manager was disposed after the cache entry was removed. + } + return true; } @@ -4952,8 +4991,17 @@ internal void Clear() // Each cached entry owns a semaphore permit; release it when discarding. foreach (var key in _cache.Keys) { - if (_cache.TryRemove(key, out _)) + if (!_cache.TryRemove(key, out _)) + continue; + + try + { _semaphore.Release(); + } + catch (ObjectDisposedException) + { + // The manager was disposed while the cache was being cleared. + } } } diff --git a/CHDSharpLib/CHDSharpLib.csproj b/CHDSharpLib/CHDSharpLib.csproj index b85eece..7a6f436 100644 --- a/CHDSharpLib/CHDSharpLib.csproj +++ b/CHDSharpLib/CHDSharpLib.csproj @@ -18,7 +18,7 @@ git LICENSE.txt - v1.6.1: bug-fix release. Expected user/usage errors in the CLI (bad flags, missing paths, sector-misaligned input, an existing output without --force, overridden format options) are now logged through ILogger.UserError and tagged so BugReportSink never posts them to the Bug Report API; genuine runtime failures are still reported. Adds a DocFX-generated per-member API reference published with the docs site (0 metadata warnings) and moves Pages deployment to a dedicated workflow. Console text and exit codes are unchanged (chdman parity). No public API changes. Pure C# - zero native dependencies. Targets net8.0/net9.0/net10.0. + v1.6.2: extraction diagnostics release. File-writing failures during extraction now log the real exception and return Chderrdecompressionerror for data/codec failures or Chderrwriteerror for output I/O instead of flattening every failure to Chderrwriteerror. Read-ahead teardown no longer races a disposed semaphore, and damaged GD-ROM metadata returns Chderrinvaliddata instead of throwing. No encoder output changes: the quick battle harness stays 3,174/3,174 checks byte-identical to chdman 0.289, and CD/GD-ROM extraction is verified byte-identical to chdman extractcd. No public API changes. Pure C# - zero native dependencies. Targets net8.0/net9.0/net10.0. true $(WarningsAsErrors);CS1591 diff --git a/CHDSharpLib/README.md b/CHDSharpLib/README.md index 92e914e..ff1aac7 100644 --- a/CHDSharpLib/README.md +++ b/CHDSharpLib/README.md @@ -20,6 +20,12 @@ --- +## What's New in v1.6.2 + +- **Extraction failures keep their real cause** - a failed extracted-file write now logs the underlying exception and returns `Chderrdecompressionerror` for data/codec failures or `Chderrwriteerror` for output I/O instead of reporting every exception as a write error. +- **Read-ahead teardown race fixed** - `ReadAheadManager.TryGet`/`Clear` ignore a semaphore released after disposal, so teardown cannot surface an unobserved `ObjectDisposedException`. +- **Damaged GD-ROM metadata is reported** - `ExtractToDirectoryWithReporting` returns `Chderrinvaliddata` when a GD-ROM CHD has no readable tracks instead of dereferencing a null track list. +- **No public API changes** - 4,219 library tests + 455 encoder tests, `jb inspectcode` 0 findings, quick battle harness 3,174/3,174 checks with byte-identical `chdman` output. ## What's New in v1.6.1 - **Automatic bug reports now only cover real bugs** - CLI diagnostics for expected user input (bad flags, invalid numbers, missing paths, sector-misaligned sources, an existing output without `--force`, overridden format options) are logged at warning level but tagged so the Bug Report API never receives them; runtime failures are still reported. No library code changed. diff --git a/CHDSharpTest/ExtractionFailureLoggingTests.cs b/CHDSharpTest/ExtractionFailureLoggingTests.cs new file mode 100644 index 0000000..5b41dab --- /dev/null +++ b/CHDSharpTest/ExtractionFailureLoggingTests.cs @@ -0,0 +1,106 @@ +using Microsoft.Extensions.Logging; + +namespace CHDSharp.Tests; + +public sealed class ExtractionFailureLoggingTests +{ + private static readonly string TestDataDir = Path.Combine(AppContext.BaseDirectory, "TestData"); + + [Fact] + public void ExtractToDirectoryWithReporting_UnwritableTarget_LogsRealException() + { + var outputDir = Path.Combine(Path.GetTempPath(), $"chd_extract_fail_{Guid.NewGuid():N}"); + var previous = Chd.LoggerFactory; + var capture = new CaptureLoggerFactory(); + Chd.LoggerFactory = capture; + try + { + Directory.CreateDirectory(outputDir); + // A directory where the output BIN must go makes FileStream creation fail. + Directory.CreateDirectory(Path.Combine(outputDir, "test.bin")); + + var err = ChdFile.Open(Path.Combine(TestDataDir, "v5_cd_default.chd"), out var chd); + Assert.Equal(ChdError.Chderrnone, err); + using (chd) + { + var result = chd!.ExtractToDirectoryWithReporting( + outputDir, + "test", + cooked: true + ); + Assert.Equal(ChdError.Chderrwriteerror, result.Error); + } + + lock (capture.Entries) + { + Assert.Contains( + capture.Entries, + e => + e.Level == LogLevel.Warning + && e.Message.Contains( + "Failed to write extracted data", + StringComparison.Ordinal + ) + && e.Exception is not null + ); + } + } + finally + { + Chd.LoggerFactory = previous; + try + { + if (Directory.Exists(outputDir)) + Directory.Delete(outputDir, true); + } + catch + { + // ignored + } + } + } + + private sealed class CaptureLoggerFactory : ILoggerFactory + { + public List<(LogLevel Level, string Message, Exception? Exception)> Entries { get; } = []; + + public void AddProvider(ILoggerProvider provider) + { + ArgumentNullException.ThrowIfNull(provider); + } + + public ILogger CreateLogger(string categoryName) + { + ArgumentNullException.ThrowIfNull(categoryName); + return new CaptureLogger(this); + } + + public void Dispose() { } + + private sealed class CaptureLogger(CaptureLoggerFactory owner) : ILogger + { + public IDisposable? BeginScope(TState state) + where TState : notnull + { + return null; + } + + public bool IsEnabled(LogLevel logLevel) + { + return true; + } + + public void Log( + LogLevel logLevel, + EventId eventId, + TState state, + Exception? exception, + Func formatter + ) + { + lock (owner.Entries) + owner.Entries.Add((logLevel, formatter(state, exception), exception)); + } + } + } +} diff --git a/CHDSharpTest/README.md b/CHDSharpTest/README.md index 32eca94..34ae1e9 100644 --- a/CHDSharpTest/README.md +++ b/CHDSharpTest/README.md @@ -14,7 +14,7 @@ **xUnit unit and corpus test suite for CHDSharp — tests header parsing, CRC checksums, and full decompression against a deterministic 30-file CHD corpus (V1–V5, all codecs).** -> **v1.6.1** - targets `net8.0` / `net9.0` / `net10.0`. 4,216 tests per target framework; encoder suite 455 tests; full battle harness 3,174/3,174 checks vs `chdman` 0.289; solution clean under `jb inspectcode`. v1.6.1 adds CLI regression tests for the `createdvd` validation paths. +> **v1.6.2** - targets `net8.0` / `net9.0` / `net10.0`. 4,219 tests per target framework; encoder suite 455 tests; full battle harness 3,174/3,174 checks vs `chdman` 0.289; solution clean under `jb inspectcode`. v1.6.2 adds extraction-failure logging and read-ahead teardown-race regression tests. --- diff --git a/CHDSharpTestDataGeneration/README.md b/CHDSharpTestDataGeneration/README.md index 4945307..b2ae906 100644 --- a/CHDSharpTestDataGeneration/README.md +++ b/CHDSharpTestDataGeneration/README.md @@ -14,7 +14,7 @@ **Deterministic CHD test corpus generator for the CHDSharp xUnit test suite.** -> **v1.6.1** - targets `net8.0` / `net9.0` / `net10.0`. Generates the 30-file corpus for V1-V5 via MAME 0.289 `chdman`; version-aligned with the v1.6.1 release. +> **v1.6.2** - targets `net8.0` / `net9.0` / `net10.0`. Generates the 30-file corpus for V1-V5 via MAME 0.289 `chdman`; version-aligned with the v1.6.2 release. Generates the 30-file CHD corpus in `CHDSharpTest/TestData/`, covering every format version (V1–V5), all compression codecs (zlib, lzma, huffman, flac, zstd, avhu + CD variants), every map type, and parent/child chains. All source images are built deterministically (seeded PRNG) so regenerating the corpus produces byte-identical output. diff --git a/Directory.Build.props b/Directory.Build.props index 4adcb08..6cbf6c2 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,8 +1,8 @@ - 1.6.1 - 1.6.1 - 1.6.1 + 1.6.2 + 1.6.2 + 1.6.2 enable enable embedded diff --git a/README.md b/README.md index c0328e1..85cf236 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,13 @@ Supports every CHD format version (V1–V5), all 10 compression codecs, parent/c --- +## What's New in v1.6.2 + +- **Extraction failures keep their real cause** - the extraction writers no longer flatten every exception to `Chderrwriteerror`. The underlying exception is logged at warning level, data/codec failures return `Chderrdecompressionerror`, and genuine output I/O failures return `Chderrwriteerror`. This is the fix behind the opaque `track N: Chderrwriteerror` reports. +- **Read-ahead teardown no longer races a cached hunk** - `ReadAheadManager.TryGet` and `Clear` tolerate a semaphore disposed between cache removal and permit release, so teardown cannot throw `ObjectDisposedException`. +- **Damaged GD-ROM metadata returns an error instead of crashing** - `ExtractToDirectoryWithReporting` returns `Chderrinvaliddata` when a GD-ROM CHD yields no tracks. +- **No encoder output changes** - quick battle harness 3,174/3,174 checks, byte-identical to `chdman` 0.289; CD (V3/V4/V5, cdfl/cdlz/cdzl/cdzs/default) and synthetic GD-ROM GDI extraction verified byte-identical to `chdman extractcd`. +- **Verification** - 4,219 library tests + 455 encoder tests, `jb inspectcode` 0 findings. ## What's New in v1.6.1 - **The bug-report API only receives real bugs** - expected user/usage errors are tagged via `logger.UserError(...)` and stay in the console and file logs without being posted as defects. That covers bad flags, invalid numbers, missing paths, sector-misaligned input, an existing output without `--force`, overridden format options and unsupported combinations (216 call sites). Genuine failures (`Open failed`, `* failed: {Message}`, verification and extraction failures) are still reported. diff --git a/WhatsNew.md b/WhatsNew.md index 584ece6..b6ce6ba 100644 --- a/WhatsNew.md +++ b/WhatsNew.md @@ -1,10 +1,11 @@ -# CHDSharp v1.6.1 - What's New +# CHDSharp v1.6.2 - What's New -**Released:** 2026-11-02 - [Full changelog](docs/ReleaseNotes.md) - [NuGet](https://www.nuget.org/packages/CHDSharp/1.6.1) +**Released:** 2026-11-02 - [Full changelog](docs/ReleaseNotes.md) - [NuGet](https://www.nuget.org/packages/CHDSharp/1.6.2) -CHDSharp v1.6.1 is a bug-fix release for the CLI's automatic bug reporting and a documentation -release for the API reference. Expected user mistakes no longer reach the Bug Report API, and the -full per-member API reference is now generated by DocFX and published with the docs site. +CHDSharp v1.6.2 is a diagnostics and extraction-robustness release. Extracted-file failures keep +their real cause instead of being flattened to `Chderrwriteerror`, read-ahead teardown cannot race +a disposed semaphore, and damaged GD-ROM metadata returns an error instead of crashing. Encoder +output is unchanged and remains byte-identical to MAME `chdman` 0.289. --- @@ -12,12 +13,12 @@ full per-member API reference is now generated by DocFX and published with the d | Platform | Bundle | |----------|--------| -| Windows x64 | [`CHDSharp_win-x64_v1.6.1.zip`](https://github.com/purelogiccode/CHDSharp/releases/download/v1.6.1/CHDSharp_win-x64_v1.6.1.zip) | -| Windows ARM64 | [`CHDSharp_win-arm64_v1.6.1.zip`](https://github.com/purelogiccode/CHDSharp/releases/download/v1.6.1/CHDSharp_win-arm64_v1.6.1.zip) | -| Linux x64 | [`CHDSharp_linux-x64_v1.6.1.zip`](https://github.com/purelogiccode/CHDSharp/releases/download/v1.6.1/CHDSharp_linux-x64_v1.6.1.zip) | -| Linux ARM64 | [`CHDSharp_linux-arm64_v1.6.1.zip`](https://github.com/purelogiccode/CHDSharp/releases/download/v1.6.1/CHDSharp_linux-arm64_v1.6.1.zip) | -| macOS Intel | [`CHDSharp_osx-x64_v1.6.1.zip`](https://github.com/purelogiccode/CHDSharp/releases/download/v1.6.1/CHDSharp_osx-x64_v1.6.1.zip) | -| macOS Apple Silicon | [`CHDSharp_osx-arm64_v1.6.1.zip`](https://github.com/purelogiccode/CHDSharp/releases/download/v1.6.1/CHDSharp_osx-arm64_v1.6.1.zip) | +| Windows x64 | [`CHDSharp_win-x64_v1.6.2.zip`](https://github.com/purelogiccode/CHDSharp/releases/download/v1.6.2/CHDSharp_win-x64_v1.6.2.zip) | +| Windows ARM64 | [`CHDSharp_win-arm64_v1.6.2.zip`](https://github.com/purelogiccode/CHDSharp/releases/download/v1.6.2/CHDSharp_win-arm64_v1.6.2.zip) | +| Linux x64 | [`CHDSharp_linux-x64_v1.6.2.zip`](https://github.com/purelogiccode/CHDSharp/releases/download/v1.6.2/CHDSharp_linux-x64_v1.6.2.zip) | +| Linux ARM64 | [`CHDSharp_linux-arm64_v1.6.2.zip`](https://github.com/purelogiccode/CHDSharp/releases/download/v1.6.2/CHDSharp_linux-arm64_v1.6.2.zip) | +| macOS Intel | [`CHDSharp_osx-x64_v1.6.2.zip`](https://github.com/purelogiccode/CHDSharp/releases/download/v1.6.2/CHDSharp_osx-x64_v1.6.2.zip) | +| macOS Apple Silicon | [`CHDSharp_osx-arm64_v1.6.2.zip`](https://github.com/purelogiccode/CHDSharp/releases/download/v1.6.2/CHDSharp_osx-arm64_v1.6.2.zip) | Every bundle contains a **framework-dependent single-file** `CHDSharp` / `CHDSharp.exe` build (the .NET runtime is **not** embedded) plus `LICENSE.txt`, `README.md`, `README.txt` @@ -26,45 +27,34 @@ is required. --- -## Fixed: the bug-report API only receives real bugs - -The Bug Report API had 383 `CHDSharpCli` reports and every one was a normal validation outcome, not -a defect: 382 `Data size ... is not divisible by sector size 2048` and one -`createdvd requires --input --output `. Both paths already matched `chdman` -(`chdman.cpp:2263`, `chdman.cpp:2088`): same console text, same exit code `1`, no partial output. -They were logged at `Warning`, and the sink forwards every `Warning+` event. - -- The CLI now logs expected user/usage errors through `logger.UserError(...)`, which keeps them at - warning level in the console and in the rolling file log but tags them so `BugReportSink` does - not post them. -- 216 call sites were reclassified: unknown options, invalid numeric arguments, missing paths, - sector-misaligned input, an existing output file without `--force`, overridden format options, - unsupported option combinations, and similar usage diagnostics. -- Genuine runtime failures stay on `logger.Warning(...)` and are still reported: `Open failed`, - `* failed: {Message}`, verification failures, TOC and track extraction failures, and - access-denied errors. -- Console text and exit codes are unchanged, so `chdman` parity is untouched (quick battle harness: - 905/905 checks). - -## New: generated API reference on the documentation site - -The public surface is now documented per member at -[purelogiccode.github.io/CHDSharp/api/](https://purelogiccode.github.io/CHDSharp/api/), generated by -DocFX from the XML documentation of `CHDSharpLib`. - -- DocFX is pinned in `.config/dotnet-tools.json` and driven by `scripts/build-api-docs.ps1`, so the - same command produces the same output locally and in CI. -- A new `Pages` workflow builds the Jekyll guides and the DocFX reference into one artifact and - deploys it (Pages now uses `build_type: workflow`); the wiki sync no longer requests a legacy - Pages rebuild. -- The reference uses the same GitHub-dark palette as the rest of the site. -- 14 duplicate `` XML-documentation blocks in `CHD.cs` were removed, so DocFX metadata now - generates with **0 warnings**. +## Fixed: extraction failures keep their real cause + +Every exception raised while writing extracted data was folded into +`ChdError.Chderrwriteerror`, so a codec, path, permission or disk failure all looked the same and +callers could not tell a damaged CHD from an unwritable output volume. This is what produced the +opaque `track 3: Chderrwriteerror` reports in consuming applications. + +- The extraction writers now log the underlying exception at warning level. +- `InvalidDataException` (data/codec failure) maps to `Chderrdecompressionerror`; output I/O maps to + `Chderrwriteerror`. +- A regression test forces an unwritable target and asserts the warning and the returned code. + +## Fixed: read-ahead teardown race + +`ReadAheadManager.TryGet` and `Clear` can run while `Dispose` releases the semaphore. A permit +release after disposal is now ignored, so teardown cannot surface an unobserved +`ObjectDisposedException`. + +## Fixed: damaged GD-ROM metadata + +`ExtractToDirectoryWithReporting` returns `Chderrinvaliddata` when a GD-ROM CHD has no readable +tracks instead of dereferencing a null track list. ## Verification - `dotnet build -c Release`: 0 warnings, 0 errors; `jb inspectcode --severity=WARNING`: 0 findings. -- Quick `chdman` parity battle: 905/905 checks passed. -- `CI gate`: three-OS build/test across `net8.0`/`net9.0`/`net10.0`, InspectCode, NuGet packaging, - merged coverage, Jekyll + DocFX docs build, and the `chdman` parity smoke. -- No public API changes - behavior, diagnostics and documentation only. +- Library tests: **4,219 passed**. Encoder tests: **455 passed**. +- Quick `chdman` parity battle: **3,174/3,174 checks passed**, byte-identical output. +- CD (V3/V4/V5, all CD codecs) and synthetic GD-ROM GDI extraction compared byte-for-byte with + `chdman extractcd`. +- No public API changes - behavior and diagnostics only. \ No newline at end of file diff --git a/docs/ReleaseNotes.md b/docs/ReleaseNotes.md index 3ab2a2c..37d1dbf 100644 --- a/docs/ReleaseNotes.md +++ b/docs/ReleaseNotes.md @@ -1,5 +1,42 @@ # CHDSharp Release Notes +## CHDSharp v1.6.2 + +Diagnostics and extraction-robustness release on top of v1.6.1. No public API changes. + +**Released:** 2026-11-02 - [NuGet](https://www.nuget.org/packages/CHDSharp/1.6.2) - +[CLI bundles](https://github.com/purelogiccode/CHDSharp/releases/tag/v1.6.2) + +### Extraction failures keep their real cause + +Every exception raised while writing extracted data was folded into +`ChdError.Chderrwriteerror`, so a codec, path, permission or disk failure all looked the same and +callers could not tell a damaged CHD from an unwritable output volume. + +- `TryWriteCdCooked`, `TryWriteTrackCooked`, `TryWriteGdRomTrackCooked`, `TryWriteTrackToFile`, + `ExtractToc` and the descriptor writers now log the exception at warning level. +- A data/codec exception (`InvalidDataException`) maps to `Chderrdecompressionerror`; output I/O + maps to `Chderrwriteerror`, preserving the caller's ability to classify the failure. +- Regression test `ExtractionFailureLoggingTests` pins the warning and the returned code. + +### Read-ahead teardown race + +`ReadAheadManager.TryGet` and `Clear` can run while `Dispose` releases the semaphore. A permit +release after disposal is now ignored, so teardown cannot surface an unobserved +`ObjectDisposedException`. + +### Damaged GD-ROM metadata + +`ExtractToDirectoryWithReporting` returns `Chderrinvaliddata` when a GD-ROM CHD has no readable +tracks instead of dereferencing a null track list. + +### Verification + +- 4,219 library tests + 455 encoder tests. +- Quick battle harness: 3,174/3,174 checks, byte-identical `chdman` output. +- `jb inspectcode`: 0 findings. +- CD (V3/V4/V5, cdfl/cdlz/cdzl/cdzs/default) and synthetic GD-ROM GDI extraction compared + byte-for-byte with `chdman extractcd`. ## CHDSharp v1.6.1 Bug-fix and documentation release on top of v1.6.0. No public API changes. diff --git a/docs/building.md b/docs/building.md index f941217..a33c859 100644 --- a/docs/building.md +++ b/docs/building.md @@ -32,7 +32,7 @@ CSharp_CHDSharp.sln ├── VendoredLZMA/ LZMA SDK C# port ├── VendoredFlac/ Pure C# FLAC encoder/decoder ├── VendoredZSTD/ Pure C# zstd 1.5.5 encoder/decoder (MAME parity) -└── Directory.Build.props Centralized versioning (1.6.1) and analyzer setup +└── Directory.Build.props Centralized versioning (1.6.2) and analyzer setup ``` --- @@ -52,7 +52,7 @@ dotnet build CHDSharpLib/CHDSharpLib.csproj -c Release ### Centralized versioning -`Directory.Build.props` defines a single `` (currently `1.6.1`) that all projects inherit, so `AssemblyVersion`, `FileVersion`, and the NuGet package version stay in sync automatically. +`Directory.Build.props` defines a single `` (currently `1.6.2`) that all projects inherit, so `AssemblyVersion`, `FileVersion`, and the NuGet package version stay in sync automatically. ### Code style & analyzers @@ -185,7 +185,7 @@ For every runtime identifier the script publishes the CLI as a **framework-depen single-file** binary (`--self-contained false -p:PublishSingleFile=true` — the .NET runtime is *not* embedded), appends `LICENSE.txt`, `README.md`, `README.txt` and `WhatsNew.md`, and writes `CHDSharp__v.zip` (the exact asset name the CLI's -built-in update check looks up on GitHub releases, e.g. `CHDSharp_win-x64_v1.6.1.zip`). +built-in update check looks up on GitHub releases, e.g. `CHDSharp_win-x64_v1.6.2.zip`). Existing files in the output path are never deleted. The binary is named `CHDSharp` (`CHDSharp.exe` on Windows); bundles require the .NET 10 runtime.