Skip to content

REST endpoint for REU memory read back #697

@JC-000

Description

@JC-000

Summary

The REST API exposes GET /v1/machine:readmem for reading C64 system memory ($0000–$FFFF), and SocketDMA opcode 0xFF07 REUWRITE lets external tools write into REU memory over the network. There is no symmetric network-reachable path for reading REU memory back out — neither a REST endpoint nor a SocketDMA opcode. This request proposes adding one.

Use Case — Snapshot interop between VICE and Ultimate hardware

I'm working on c64-test-harness, a Python test framework that drives both VICE emulator and Ultimate-64 hardware through a common protocol. One of the things it does is round-trip C64 snapshots between the two backends in VICE's native .vsf format. VICE's snapshot format has a REU module that carries the full REU bank contents, and being able to capture that from a running U64 / U2+ is what makes round-tripping between emulator and hardware possible.

Related prior work in this area:

  • additional Remote Interface Features #265 (mrdudz / Bob Andrews) — requesting additional remote-interface features specifically to run VICE tests automatically against U64 hardware. REU contents readback is the missing piece for full VICE↔U64 test automation.
  • REST API: add ramonly parameter to readmem/writemem for direct RAM access #674 (ZamBoyle / Johnny Piette) — REST API ramonly parameter for direct RAM access, closed COMPLETED. That work was driven by an Android Time Machine app ("READY.") doing save-state over REST. The same project would benefit from REU readback for the same save-state purpose.

Currently the only path I've found is to do REU→C64 DMA transfers through a staging window in C64 RAM:

  1. machine:pause
  2. Reserve a staging window in C64 RAM and stash whatever was there
  3. Loop: program $DF02–$DF09/$DF01 to DMA one REU chunk into the staging window, readmem it, advance
  4. Restore the staging window's original contents
  5. machine:resume

That works but it pauses the CPU, clobbers ~32 KB of C64 RAM, and orchestrates hundreds of $DF0x register-write rounds per 16 MB. The on-device "Save REU" menu action does the same thing in seconds via a direct memcpy from REU_MEMORY_BASE (c64_subsys.cc (https://github.com/GideonZ/1541ultimate/blob/master/software/io/c64/c64_subsys.cc), MENU_C64_SAVEREU). The asymmetry is purely in network reachability.

Proposed Solution

A new REST endpoint that mirrors the existing :readmem shape against REU address space:

GET /v1/machine:reumem?address=&length=

  • address — REU byte offset, 0 .. (REU_size_in_bytes - 1), 24-bit value
  • length — 1 .. 65536 (same cap as :readmem)
  • Response: Content-Type: application/octet-stream, raw bytes
  • Authentication: existing X-Password header
  • Errors:
    • 400 Bad Request on out-of-range / missing params
    • 409 Conflict (or 404) when REU is disabled in the device config

Implementation should be a thin parallel to the existing readmem handler in route_machine.cc (https://github.com/GideonZ/1541ultimate/blob/master/software/api/route_machine.cc). The REU DRAM is already FPGA-mapped from the firmware CPU's perspective (the menu save uses memcpy directly from REU_MEMORY_BASE), so the handler is essentially a streaming memcpy into the HTTP response buffer.

0xFF77 REUREAD
request: 3 bytes LE REU offset, 4 bytes LE length
response: raw bytes

Either alone solves the problem; the REST endpoint is the lower-friction option and likely sufficient.

Applies to both U64 and 1541 Ultimate II+

The REU is FPGA-DRAM on both product lines — built-in on the Ultimate-64 and on the Ultimate-II+ cartridge variants (when REU is enabled in the config). The same REU_MEMORY_BASE memcpy path applies on both, so this isn't a U64-only feature.

Current Workaround

c64-test-harness implements the staging-window approach above. With a 32 KB staging window at $0800–$87FF and the CPU paused, a 16 MB dump takes ~30 s at native 1 MHz or ~5–10 s in 48 MHz turbo. Works but intrusive — has to pause the CPU and briefly clobber 32 KB of C64 RAM. The presence of 0xFF07 REUWRITE in socket_dma.cc makes the read-side gap especially visible because the network-restore path is dramatically cleaner than the network-extract path.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions