Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 21 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,29 @@ jb inspectcode CSharp_CHDSharp.sln --severity=WARNING # ReSharper inspections
- Keep ReSharper inspections clean too: `jb inspectcode CSharp_CHDSharp.sln --severity=WARNING`
must report zero findings. The four vendored codec projects - `VendoredFlac`, `VendoredLZMA`,
`VendoredZLib` and `VendoredZSTD` - are excluded from InspectCode entirely
(`--exclude="Vendored*/**"`, projects and sources). They must stay verbatim for byte-for-byte
`chdman` parity: never edit them to satisfy an inspection, and never remove the exclusion. The
same rule lives in the root `.editorconfig` so IDE inspections stay quiet inside those folders.
(`--exclude="Vendored*/**"`, projects and sources); never remove the exclusion. The same rule
lives in the root `.editorconfig` so IDE inspections stay quiet inside those folders. See
[Vendored codecs (frozen)](#vendored-codecs-frozen) before touching anything in those folders.
InspectCode 2026.2 also logs a few internal `AssertionException`s while analyzing
`VendoredZSTD` (an analyzer bug, not a finding); the report is still empty.
- Always run `dotnet test` before committing. Run the battle harness for changes touching
encoding, decoding, CLI argument parsing, or anything chdman-visible.

## Vendored codecs (frozen)

`VendoredFlac`, `VendoredLZMA`, `VendoredZLib` and `VendoredZSTD` are kept byte-for-byte verbatim
from their upstream sources. They are **frozen by default**: editing them can break byte-for-byte
`chdman` parity, which is the project's most important invariant.

- Do not edit a vendored codec unless a change is **strictly necessary** (for example a correctness
or security fix with no viable alternative), and never merely to satisfy an analyzer, formatter
or InspectCode finding.
- Keep the existing exclusions in the InspectCode command and the root `.editorconfig`; do not
remove them to make an inspection "see" the vendored sources.
- If a vendored edit is truly required, explain why in the commit message and run the full battle
harness plus the relevant codec tests before committing.
- Preserve all upstream license headers and notices.

## Logging & bug reports (behavior to preserve)

- The CLI and Tester configure Serilog at startup (`MinimumLevel.Debug`) and bridge the library
Expand All @@ -68,7 +83,9 @@ jb inspectcode CSharp_CHDSharp.sln --severity=WARNING # ReSharper inspections
format overrides, ...) are diagnostics about the user's input, not defects. Log them with
`logger.UserError(...)` (`CHDSharpCli/UserErrorLogging.cs`), which keeps them at warning level in
the console/file logs but tags them so `BugReportSink` never reports them. Real runtime failures
(`Open failed`, `* failed: {Message}`, verify failures, ...) stay on `logger.Warning(...)`.
(`Open failed`, I/O failures in a `* failed: {Message}` event, verify failures, ...) stay on
`logger.Warning(...)`; malformed input images (`InvalidDataException`, missing referenced files)
are user errors instead.
- Every report must embed: `=== Environment Details ===` (Date, Application Name, Application
Version, OS Version, Architecture, Bitness, Windows, Linux or MacOsX Version, Processor Count,
Base Directory, Temp Path), `=== Error Details ===` (message), and `=== Exception Details ===`
Expand Down
17 changes: 10 additions & 7 deletions CHDSharpCli/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2275,14 +2275,17 @@ ref inputLengthFrames
log.Information(" Created ({File:N0} bytes)", new FileInfo(outputPath).Length);
VerifyResultChd(outputPath, parentPath);
}
// Malformed descriptors and unreadable source images (unrecognized ISO sector size,
// malformed CUE/GDI/TOC, truncated BIN/WAV, missing referenced file) are user-input
// errors: the same input fails the same way in chdman, so they must not be reported
// as application defects.
catch (Exception ex) when (ex is InvalidDataException or FileNotFoundException)
{
log.UserError("--createcd failed: {Message}", ex.Message);
return false;
}
catch (Exception ex)
when (ex
is ArgumentException
or InvalidDataException
or IOException
or UnauthorizedAccessException
or FileNotFoundException
)
when (ex is ArgumentException or IOException or UnauthorizedAccessException)
{
log.Warning("--createcd failed: {Message}", ex.Message);
return false;
Expand Down
2 changes: 1 addition & 1 deletion CHDSharpCli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.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_<os>-<arch>_v<version>.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.3** - expected `createcd` input failures no longer create bug reports: malformed ISO/CUE/GDI/TOC images, truncated BIN/WAV sources and missing referenced files keep their unchanged console text and exit code but are tagged as user errors. Other I/O and runtime failures are still reported. Six platform bundles are attached to every release (`CHDSharp_<os>-<arch>_v<version>.zip`). Release bundles are framework-dependent single-file binaries and require the .NET 10 runtime; the library targets `net8.0` / `net9.0` / `net10.0`.

---

Expand Down
2 changes: 1 addition & 1 deletion CHDSharpLib/CHDSharpLib.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<RepositoryType>git</RepositoryType>
<PackageLicenseFile>LICENSE.txt</PackageLicenseFile>
<PackageLicenseExpression></PackageLicenseExpression>
<PackageReleaseNotes>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.</PackageReleaseNotes>
<PackageReleaseNotes>v1.6.3: diagnostics and documentation release. The CLI's createcd command now tags malformed images (InvalidDataException) and missing referenced files (FileNotFoundException) as expected user errors, so they stay in the console/file logs but are no longer posted to the Bug Report API; console text and exit codes are unchanged and other runtime failures are still reported. AGENTS.md now documents the vendored codec projects as frozen for chdman byte parity. No public API or encoder output changes: 4,220 library tests + 455 encoder tests, jb inspectcode 0 findings, quick battle harness 905/905 checks. Pure C# - zero native dependencies. Targets net8.0/net9.0/net10.0.</PackageReleaseNotes>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<WarningsAsErrors>$(WarningsAsErrors);CS1591</WarningsAsErrors>
</PropertyGroup>
Expand Down
7 changes: 7 additions & 0 deletions CHDSharpLib/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,19 @@

---

## What's New in v1.6.3

- **CLI-side input errors no longer become bug reports** - `--createcd` now tags malformed images (`InvalidDataException`) and missing referenced files (`FileNotFoundException`) as expected user errors. Console output and exit codes are unchanged; other runtime failures are still reported. No library API or encoder behavior changed.
- **Vendored codecs are frozen** - `AGENTS.md` documents that `VendoredFlac`, `VendoredLZMA`, `VendoredZLib` and `VendoredZSTD` stay verbatim for byte-for-byte `chdman` parity and are only to be edited when strictly necessary.
- **No public API changes** - 4,220 library tests + 455 encoder tests on each of `net8.0`/`net9.0`/`net10.0`, `jb inspectcode` 0 findings, quick battle harness 905/905 checks.

## 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.
Expand Down
27 changes: 26 additions & 1 deletion CHDSharpTest/CliIntegrationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -196,4 +196,29 @@ public void Createdvd_reports_usage_error_when_arguments_are_missing()
StringComparison.Ordinal
);
}
}

[Fact]
public void Createcd_rejects_iso_size_that_is_not_sector_aligned()
{
// cdrom.cpp:2078 - parse_iso only accepts sizes that are a multiple of 2048,
// 2336 or 2352. This is an expected input error, not a defect.
var dir = Path.Combine(Path.GetTempPath(), "chdsharp-createcd-" + Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(dir);
try
{
var input = Path.Combine(dir, "odd.iso");
File.WriteAllBytes(input, new byte[1000]);
var output = Path.Combine(dir, "out.chd");

var (exitCode, log) = RunCli("createcd", "--input", input, "--output", output);

Assert.Equal(1, exitCode);
Assert.Contains("Unrecognized ISO sector size", log, StringComparison.Ordinal);
Assert.False(File.Exists(output));
}
finally
{
Directory.Delete(dir, recursive: true);
}
}
}
2 changes: 1 addition & 1 deletion CHDSharpTest/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.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.
> **v1.6.3** - targets `net8.0` / `net9.0` / `net10.0`. 4,220 tests per target framework; encoder suite 455 tests; quick battle harness 905/905 checks vs `chdman` 0.289; solution clean under `jb inspectcode`. v1.6.3 adds the `createcd` non-sector-aligned ISO regression test and classifies malformed input images as user errors.

---

Expand Down
2 changes: 1 addition & 1 deletion CHDSharpTestDataGeneration/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

**Deterministic CHD test corpus generator for the CHDSharp xUnit test suite.**

> **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.
> **v1.6.3** - 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.3 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.

Expand Down
6 changes: 3 additions & 3 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<Project>
<PropertyGroup>
<Version>1.6.2</Version>
<AssemblyVersion>1.6.2</AssemblyVersion>
<FileVersion>1.6.2</FileVersion>
<Version>1.6.3</Version>
<AssemblyVersion>1.6.3</AssemblyVersion>
<FileVersion>1.6.3</FileVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<DebugType>embedded</DebugType>
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,20 @@ Supports every CHD format version (V1–V5), all 10 compression codecs, parent/c

---

## What's New in v1.6.3

- **Expected `createcd` input errors stay out of the Bug Report API** - malformed ISO/CUE/GDI/TOC files, truncated BIN/WAV sources and missing referenced files are now logged through `logger.UserError(...)`. The console text and exit code are unchanged (the same input is rejected by `chdman` too), but these diagnostics are no longer POSTed as application defects. Other I/O and runtime failures are still reported.
- **Vendored codecs are explicitly frozen** - `AGENTS.md` now states that `VendoredFlac`, `VendoredLZMA`, `VendoredZLib` and `VendoredZSTD` stay byte-for-byte verbatim for `chdman` parity and may only be edited when strictly necessary, never to satisfy an analyzer or InspectCode finding.
- **Verification** - 4,220 library tests + 455 encoder tests on each of `net8.0`/`net9.0`/`net10.0`, `jb inspectcode` 0 findings, quick battle harness 905/905 checks. No public API or encoder-output changes.

## 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.
Expand Down
Loading
Loading