conformance: pick the mem-write address per platform d69f9ef6bbac
The mem-write round-trip hard-coded $0400, which is fine on flat cores (X16/Neo/PC-FX) but is on-chip flash (MOS ROM) on the eZ80 Agon, where RAM only starts at $040000 — so the write was a silent no-op and the read-back returned ROM, failing the test against a fully-conformant server. Choose the scratch address from the platform reported by /status ($050000 on Agon, $0400 elsewhere). No behaviour change on the existing flat platforms. Git-Commit: 77648a4bb506fd7c5f8968da718322e29e8215df Git-Author: Andy McCall <[email protected]>
- Author
- Andy McCall @andymccall <[email protected]>
- When
- · 2026-07-22 00:01 UTC
- Signature
- ◈ sealed by Andy McCall
- Hash
d69f9ef6bbac3b168c188ce376da854b72d9244aea5acdfac486b67e6748d7ab- Depends on
- 674b8447022b 8ac19619e24b
- Depended on by
- nothing yet
- In bookmarks
- main perf-6
- Edits
- 4 atoms, 0 tree operations, 1 file
Browse the tree at this change
modified conformance/test_conformance.py +17 −4
| 1 | 1 | """Contract conformance tests (SPEC.md 0.3.x). Platform-agnostic: framebuffer |
|
| 2 | - | dimensions come from the PPM header, addresses use $0000, and `bank` is |
|
| 3 | - | exercised but banking is not required. Tests gated on the server's advertised |
|
| 4 | - | minor (input injection 0.2; memory write + audio 0.3) skip on older servers.""" |
|
| 2 | + | dimensions come from the PPM header, read addresses use $0000, and `bank` is |
|
| 3 | + | exercised but banking is not required. The one address that must be *writable* |
|
| 4 | + | (the mem-write round-trip) is chosen per-platform via `_scratch_ram`, because |
|
| 5 | + | low memory is not RAM everywhere — on the eZ80 Agon $0000-$03FFFF is on-chip |
|
| 6 | + | flash (MOS ROM) and RAM only begins at $040000. Tests gated on the server's |
|
| 7 | + | advertised minor (input injection 0.2; memory write + audio 0.3) skip on older |
|
| 8 | + | servers.""" |
|
| 5 | 9 | import urllib.error |
|
| 6 | 10 | import urllib.request |
|
| 7 | 11 | ||
| … | 109 unchanged lines |
||
| 117 | 121 | ||
| 118 | 122 | # -- contract 0.3: memory write + audio (skipped on < 0.3 servers) ----------- |
|
| 119 | 123 | ||
| 124 | + | def _scratch_ram(emu): |
|
| 125 | + | """A writable RAM address for the platform. Most cores are flat with RAM at |
|
| 126 | + | $0000, but the eZ80 Agon maps $0000-$03FFFF to flash (MOS ROM), so a write |
|
| 127 | + | there is a silent no-op and the read-back returns ROM. RAM starts at |
|
| 128 | + | $040000 there; $050000 is well clear of the MOS load area.""" |
|
| 129 | + | plat = (emu.status().get("platform") or "").lower() |
|
| 130 | + | return 0x050000 if "agon" in plat else 0x0400 |
|
| 131 | + | ||
| 132 | + | ||
| 120 | 133 | def test_mem_write_roundtrip(emu): |
|
| 121 | 134 | """POST /mem pokes bytes; GET /mem reads them back (contract 0.3).""" |
|
| 122 | 135 | if _contract_minor(emu) < 3: |
|
| 123 | 136 | pytest.skip("contract < 0.3 (no memory write)") |
|
| 124 | 137 | emu.pause() # freeze so the machine can't overwrite between write+read |
|
| 125 | 138 | try: |
|
| 126 | - | addr, payload = 0x0400, bytes([0xA5, 0x5A, 0x00, 0xFF]) |
|
| 139 | + | addr, payload = _scratch_ram(emu), bytes([0xA5, 0x5A, 0x00, 0xFF]) |
|
| 127 | 140 | assert emu.mem_write(addr, payload) == len(payload) |
|
| 128 | 141 | assert emu.mem(addr, len(payload)) == payload |
|
| 129 | 142 | finally: |
|
| … | 32 unchanged lines |