# MZ-800 Emulator (experimental version)

The project moved from SourceForge to GitHub. The latest source code and
releases are now available at <https://github.com/michalhucik/mz800emu>.

Older stable 1.0.x releases remain archived on the original SourceForge
page: <https://sourceforge.net/projects/mz800emu/>


## Windows

If you want to always have the console displayed on the Windows platform, you have three options:

- Run program from MSYS2 console
- Create shortcut for `mz800emu.exe` and add exec parameter `--console`
- Compile program with parameter `FORCE_CONSOLE=1`


## Keyboard mapping

Most keys are located in the same positions as the MZ-800 — like in the emulator from Zdenek Adler.

### Specialities & Differences

| Sharp key    | PC key                  |
|--------------|-------------------------|
| `GRAPH`      | CapsLock                |
| `ALPHA`      | `\`                     |
| `BLANK_KEY`  | `~`                     |
| `ESC`        | Esc, or End             |
| `INST`       | Insert                  |
| `DEL`        | Backspace, or Delete    |
| `@`          | F6                      |
| `\`          | F7                      |
| `?`          | F8                      |
| `LIBRA`      | F9                      |


## Command-line options

The emulator supports a small set of long options. Options not listed below
are rejected with an error - use `--help` for a generated listing.

| Option | Argument | Description |
|--------|----------|-------------|
| `--help` | - | Print the option list and exit. |
| `--console` | - | Windows only: allocate a console window for stdout/stderr. |
| `--run-mzf` | `<filepath>` | Automatically load and run the given MZF file after the emulator boots. |
| `--cdl-mode` | `<off\|window\|always>` | Set the CDL (Memory Heatmap) recording mode. |
| `--cdl-dir` | `<dirpath>` | Set the target directory for CDL export. The directory is created on export if it does not exist. |
| `--cdl-name` | `<basename>` | Set the CDL export basename (without `.json`). The full meta path is `<dir>/<name>.json`; per-region binary files are saved as `<dir>/<name>_<region>.cdl`. |
| `--cdl-save-on-exit` | `<on\|off>` | Enable/disable automatic CDL export when the emulator exits. |
| `--cputrack-mode` | `<off\|window\|always>` | Set the CPU Tracking Log recording mode (one of four trace-suite subsystems). |
| `--cputrack-dir` | `<dirpath>` | Target directory for cputrack export. |
| `--cputrack-name` | `<basename>` | Basename for cputrack export files. |
| `--cputrack-chunk-mb` | `<N>` | RAM chunk size before disk swap (default 64). |
| `--cputrack-max-total-mb` | `<N>` | Max total recording size, 0 = unlimited (default 0). |
| `--cputrack-save-on-exit` | `<on\|off>` | Auto-finalize cputrack export when the emulator exits. |
| `--iorqlog-mode` | `<off\|window\|always>` | Set the IORQ Log recording mode. |
| `--iorqlog-dir` | `<dirpath>` | Target directory for iorqlog export. |
| `--iorqlog-name` | `<basename>` | Basename for iorqlog export files. |
| `--iorqlog-chunk-mb` | `<N>` | RAM chunk size before disk swap (default 64). |
| `--iorqlog-max-total-mb` | `<N>` | Max total recording size, 0 = unlimited (default 0). |
| `--iorqlog-save-on-exit` | `<on\|off>` | Auto-finalize iorqlog export when the emulator exits. |
| `--intlog-mode` | `<off\|window\|always>` | Set the Interrupt Log recording mode. |
| `--intlog-dir` | `<dirpath>` | Target directory for intlog export. |
| `--intlog-name` | `<basename>` | Basename for intlog export files. |
| `--intlog-chunk-mb` | `<N>` | RAM chunk size before disk swap (default 64). |
| `--intlog-max-total-mb` | `<N>` | Max total recording size, 0 = unlimited (default 0). |
| `--intlog-save-on-exit` | `<on\|off>` | Auto-finalize intlog export when the emulator exits. |
| `--hwlog-mode` | `<off\|window\|always>` | Set the HW Log recording mode. |
| `--hwlog-dir` | `<dirpath>` | Target directory for hwlog export. |
| `--hwlog-name` | `<basename>` | Basename for hwlog export files. |
| `--hwlog-chunk-mb` | `<N>` | RAM chunk size before disk swap (default 64). |
| `--hwlog-max-total-mb` | `<N>` | Max total recording size, 0 = unlimited (default 0). |
| `--hwlog-save-on-exit` | `<on\|off>` | Auto-finalize hwlog export when the emulator exits. |
| `--hwlog-hs-decimation` | `<N>` | Decimate hwlog `GDG_VIDEO` HS/HBLN edges: emit every N-th edge. `0` = OFF (default; full rate is ~31000 events/sec). |
| `--all-traces-mode` | `<off\|window\|always>` | Shorthand: set the recording mode for ALL four trace-suite subsystems (cputrack, iorqlog, intlog, hwlog) at once. Per-subsystem `--<sys>-mode` takes precedence. |
| `--all-traces-dir` | `<dirpath>` | Shorthand: set the target directory for ALL four trace-suite subsystems. Per-subsystem `--<sys>-dir` takes precedence. |
| `--no-save-ini` | - | Do not write the `.ini` file at exit. CLI overrides become session-only. |
| `--no-first-run-windows` | - | Suppress automatic opening of About + Version Check Setup windows on first run (when no `.ini` file exists). Useful for headless / scripted launches. |

### CDL export layout

A CDL export consists of one `meta.json` file plus one binary file per
memory region. With `--cdl-dir ./my-runs/` and `--cdl-name session1`
the produced layout is:

```
./my-runs/
    session1.json                # meta + region table (text)
    session1_bus.cdl             # 64K cells × 12 bytes (R, W, X uint32 LE)
    session1_ram.cdl
    session1_rom-lower.cdl
    ...
    session1_iorq-8bit.cdl
```

The `meta.json` contains the absolute filenames of the per-region files,
so the GUI Import action only needs the meta file - it parses the region
table and loads the referenced files from the same directory.

### Persistence

CLI options for the CDL settings (`--cdl-mode`, `--cdl-dir`, `--cdl-name`,
`--cdl-save-on-exit`) override the values loaded from the `.ini` file.
On exit the `.ini` is rewritten with the current (overridden) values, so
the override becomes the new default for next runs.

To test a setting without making it permanent, combine the override with
`--no-save-ini`:

```
mz800emu --cdl-mode always --no-save-ini
```

### Examples

```
mz800emu --help

# Boot with a specific MZF, record CDL while debug window is open,
# export CDL on exit (settings persisted to .ini):
mz800emu --run-mzf "Batman Demo.mzf" --cdl-mode window --cdl-save-on-exit on

# One-shot session: record CDL always, export on exit, do not change .ini:
mz800emu --cdl-mode always --cdl-save-on-exit on --no-save-ini

# Custom export directory + custom basename:
mz800emu --cdl-mode always \
         --cdl-dir ./my-cdl-runs/sapo-p/ \
         --cdl-name run-2026-05-01 \
         --cdl-save-on-exit on
```

For details about the CDL file format and per-file semantics see
[`../cz/debugger/formats/cdl_format.md`](../cz/debugger/formats/cdl_format.md) (Czech).


## trace-suite (CPU Tracking, IORQ, Interrupt, HW Logs)

Four independent sequential logging subsystems for deep analysis of
executed code, I/O traffic, interrupts and HW state changes. Each
subsystem can be activated independently via `--<sys>-mode=<off|window|always>`
where `<sys>` = `cputrack` / `iorqlog` / `intlog` / `hwlog`. Per-subsystem
options follow the same pattern as CDL (`-dir`, `-name`, `-save-on-exit`)
plus chunk/total limits for streaming recording.

Output structure (per recording directory):

```
./trace-suite/
    cputrack.json                    # meta + chunks anchor + initial regs/RAM dump
    cputrack_initial_ram.bin         # 64 KB CPU RAM snapshot
    cputrack_initial_vram.bin        # 32 KB VRAM (MZ-800)
    cputrack_initial_memext.bin      # 512 KB Memext (if attached)
    cputrack.000.bin                 # chunk 0 - 12 B per CPU instruction
    cputrack.001.bin                 # chunk 1
    ...
    iorqlog.json                     # meta + chunks anchor
    iorqlog.000.bin                  # 24 B per I/O event
    intlog.json
    intlog.000.bin                   # 24 B per interrupt event
    hwlog.json
    hwlog.000.bin                    # 24 B per HW state change event
```

Per-subsystem format details:

- [`../cz/debugger/formats/CPU-track_format.md`](../cz/debugger/formats/CPU-track_format.md) - CPU Tracking Log (Czech)
- [`../cz/debugger/formats/IORQ-log_format.md`](../cz/debugger/formats/IORQ-log_format.md) - IORQ Log (Czech)
- [`../cz/debugger/formats/INT-log_format.md`](../cz/debugger/formats/INT-log_format.md) - Interrupt Log (Czech)
- [`../cz/debugger/formats/HW-log_format.md`](../cz/debugger/formats/HW-log_format.md) - HW Log (Czech)
- [`../cz/debugger/Trace_Suite.md`](../cz/debugger/Trace_Suite.md) - User overview, GUI menu, INI persistence (Czech)

Other debugger documents:

- [`debugger/disassembler-window.md`](debugger/disassembler-window.md) -
  standalone Disassembler window V1 (range disasm, S/L/D/W auto-labels,
  sym_db/CDL gating, export .asm/.s for pasmo/sjasmplus/sdcc-asz80)

### Examples

```
# Record CPU instructions during a session, into custom directory:
mz800emu --run-mzf program.mzf --cputrack-mode always \
         --cputrack-dir ./traces/batman/ --cputrack-name run-001 \
         --cputrack-save-on-exit on

# All four subsystems at once:
mz800emu --cputrack-mode always --iorqlog-mode always \
         --intlog-mode always --hwlog-mode always

# Same effect using the shorthand (active + shared directory):
mz800emu --all-traces-mode always --all-traces-dir ./logs/run-1/

# Mix shorthand with one per-subsystem override (everything always
# except hwlog, which stays off):
mz800emu --all-traces-mode always --hwlog-mode off

# Constrain disk usage with chunk size + total cap:
mz800emu --cputrack-mode always \
         --cputrack-chunk-mb 32 --cputrack-max-total-mb 512
```


## Known issues

### ImGui

If you run into problems with the application remembering the wrong size or position of windows, you can edit or delete the `mz800emu-imgui.ini` file.
