hg80 1.0.0

Z80 and Z80N CPU core, stepped one clock edge at a time
Documentation
# Contributing to hg80

## Submitting a change

Patches are welcome. Open a pull request at <https://codeberg.org/TwistedRaven/hg80>; development
itself happens in a private working repository, and an accepted patch is applied there.

Two consequences of that are worth knowing before you spend effort, because they are not what most
projects do:

- **Your change ships inside a release commit.** The public history carries one squashed commit per
  release, whose message is that release's `HISTORY.md` section. Your work is in the tree that
  commit publishes, alongside everything else in the release.
- **Your commit is preserved, but your branch is not merged into `main`.** The release commit names
  your commit as a parent, so it stays in the public history under your name and `git shortlog`
  counts it. What does not happen is a merge of your branch as its own commit on `main`.

A patch that arrives as a plain diff — on an issue, say — has no commit to preserve, so it is
credited with a `Co-authored-by:` trailer or a note in `HISTORY.md` instead.

## Building and testing

```
cargo test --all-features
cargo clippy --all-targets --all-features -- -D warnings
cargo fmt --check
```

Run the suite with default features as well as all features. The optional `serde` derives on the
state types are easy to break in only one configuration.

## The optional test vectors

`tests/vectors.rs` runs against a well-known set of Z80 test vectors: 1356 cases covering
documented and undocumented opcodes, the undocumented flag bits and the internal address latch. It
checks the ordered bus event log, the T-state total, every register and the changed memory.

**Those vectors are not distributed with this crate, and must not be added to it.**

It comes from [Fuse](https://sourceforge.net/projects/fuse-emulator/), which is under the GNU
General Public License version 2. The vector files carry no licence notice of their own, so the
project's licence applies to them. Shipping GPL-2 material inside an MIT OR Apache-2.0 crate would
put this crate's licensing in doubt, and being unambiguously permissive is the whole point of it.
So the files stay out and the test skips itself when they're absent.

Nothing here is derived from Fuse. The vectors are used as expected-output data, nothing more.

To run it, get `tests.in` and `tests.expected` from Fuse yourself and point the harness at them:

```
HG80_FUSE_DIR=/path/to/fuse/z80/tests cargo test --test vectors
```

Or put them in `tests/fuse/`, which is git-ignored and excluded from the published package so they
can't be committed or shipped by accident.

Without them:

```
$ cargo test --test vectors
skipped: no test vectors present
```

## The HDL comparison

Three tests compare this core against a simulation of the T80/T80N FPGA core it's derived from:
`tests/cycles.rs` for the bus, `tests/reference_state.rs` for the registers, and
`tests/z80n_tokens.rs` for the extended-instruction reports.

The reference VHDL isn't distributed here either. The measured results are committed, so all three
run without it.

To regenerate them you need GHDL and a copy of that VHDL:

```
HG80_VHDL_DIR=/path/to/vhdl sh sim/t80n/run.sh      # per-T-state traces
HG80_VHDL_DIR=/path/to/vhdl sh sim/t80n/state.sh    # final register state
```

Both skip with a message if GHDL or the VHDL is missing.

Where this core and the simulation disagree on purpose, the divergence is named in the test with
its reason — see `VECTORS_GOVERN` in `tests/reference_state.rs`. The design leaves some
undocumented flag bits alone where the published rule writes them, and the vectors win those.

## Code style

- Rustdoc on an item (`///`) goes on the public API and nothing else. An item no consumer can
  reach is documented for nobody. Note `pub` is not the test — `src/core` is a private module, so
  its `pub` items are public only where `lib.rs` re-exports them.
- Module headers (`//!`) are wanted on internal modules too. Rustdoc does not emit them for a
  private module, so they explain the file to whoever edits it rather than to a consumer, and what
  a file is for is exactly the kind of thing the code cannot state.
- Every other comment earns its place by explaining something the code does not state: a reason, a
  citation, a hazard. Where it sits is not the test — a comment inside a function body is judged on
  the same terms as one above it. Anything a better name would say is a rename instead, and
  anything a test would say is a test.
- Public documentation explains this crate on its own terms, never by reference to another project
  — not "like X", not "what Y needed". Naming a project that *uses* the crate is a fact about it
  and is fine; borrowing another project's design to explain this one is not.
- Write plainly, in en-GB. Short sentences, the fact before the reason, and no throat-clearing.
- Each file carrying derived work keeps its attribution header. See `NOTICE`.

## Licence

Contributions are dual licensed under MIT OR Apache-2.0, as described in `README.md`.