Releases: Jondalar/TRX64
Release list
TRX64 0.12.4 — EasyFlash 3
Added
- EasyFlash 3. A full EasyFlash 3 image (CRT type 90, 8 MB, 8 slots) runs as the cartridge's CPLD does it:
- Slots and banking:
$DE01selects one of 8 slots.- Each slot uses EasyFlash banking (
$DE00/$DE02), including the no-VIC bit and the boot flag. - The IO2 RAM is shared by all slots.
$DE08reports the CPLD version.
- Mode register
$DE0F: EasyFlash with a reset (0), without a reset (1), and kill (7).- The KERNAL, freezer (AR/RR/NP, SS5) and C128 modes are not emulated. A program that selects one gets the cartridge switched off, and the status says "not emulated".
- Buttons: the cartridge's three buttons (Menu, Reset, Special) are new:
cart button <menu|reset|special>in the monitor;cart/buttonover the API;cart_buttonin the FFI.
- Flash: an MX29LV640EB with its 8 KB boot blocks, so the cartridge's own EasyAPI driver programs and erases unchanged.
- Writes survive checkpoints and are saved back as a type-90 CRT.
- Tested with skoe's EF3 boot image: it boots to its menu, starts a slot, and returns to the menu.
- Slots and banking:
Changed
- C64MegaCart is CRT type 88. It used to be 61, which mainline VICE assigns to MAX Basic. CRT files with type 61 are no longer read as C64MegaCart.
TRX64 0.12.3 — debug builds survive an interrupt
Fixed
-
Debug builds no longer panic on the first interrupt. 0.12.2 computed an addition on the IRQ/BRK path before checking whether an NMI was pending. With no NMI pending, the addition overflowed:
- Release builds wrapped silently, and the result was then ignored, so they behaved correctly.
- Debug builds stopped with "attempt to add with overflow" on every IRQ or BRK, so any application that embeds TRX64 and builds in debug failed.
The check now runs only when an NMI is pending. The pre-push gate also runs one booted IRQ in a debug build.
TRX64 0.12.2 — U64 turbo as measured
Fixed
-
U64 / C64 Ultimate turbo now behaves as measured on the device. The C64 Ultimate (firmware 3.15, core 1.50) was measured, and TRX64 now follows those measurements. Where the old model followed the menu labels or VICE's TurboMaster, it now follows the device:
$D031bit 7 means "no badline stalls". The old model had it inverted.$80is now 1 MHz without stalls.- The top speeds are 47 and 63 CPU cycles per PHI2, not the 48 and 64 on the menu labels. All other speeds are as labelled.
- Interrupts are taken at the turbo clock, within one PHI2 cycle, as on the device. The old model counted two PHI2 cycles.
- I/O costs as measured:
- CIA, IO1/IO2 and VIC/SID accesses wait for the PHI2 bus cycle with the measured lead.
- UCI at 16× now runs 1.0158×; the device runs 1.0157×.
- Program and menu share one turbo state. The last write wins, and a menu change applies even when the value is unchanged.
- In TurboEnable mode, a menu change also sets
$D030.
- In TurboEnable mode, a menu change also sets
- Reset readbacks follow the mode. In registers mode,
$D031reads$00after a reset. - The post-reset hold lasts 2^22 PHI2 cycles (4.26 s on PAL). The old value was 2.06 s.
$D07A/$D07B,$D0BC–$D0BFand their mirrors decode as on the device.- Colour stores (
$D020–$D02E) during turbo land at the pixel they were made in. - Snapshots and the checkpoint ring carry the turbo state on the U64 profile. Older U64 snapshots load with the reset defaults, and the restore says so.
At 1 MHz nothing changes.
-
A 1581 finds its DOS in any ROM directory (#4).
dos1581-318045-02.bin(or1581.bin/1581.rom) used to be looked up only in the directory that held the KERNAL. It is now found in any of the ROM directories.- Switching a drive to 1581, or powering one on, without a DOS is now refused. The error names the file and every directory searched. Before, the drive ran with no ROM, and the C64 reported
?DEVICE NOT PRESENT.
TRX64 0.12.1 — the C64's CIAs are VICE's
Fixed
-
A pending CIA interrupt stays until the ICR is read (#3).
- Writing the mask to
$DC0D/$DD0D(for example$7F) used to release a pending IRQ or NMI and clear the IR bit. - A 6526 and VICE keep both until
$DC0D/$DD0Dis read. - An IRQ handler that leaves through
$EA81without reading$DC0Dnow re-enters for ever, as on the real machine, instead of quietly working only in TRX64.
The C64's two CIAs now run on the same exact port of VICE's CIA core that the 1581 already used, with the C64 wiring ported from VICE:
- The keyboard matrix includes ghost keys.
- Joysticks, the paddle select, the VIC bank, the serial bus and the NMI are wired as in VICE.
- The CIA model follows the machine: a 6526 in the C64.
- IRQ timing is VICE's: a 6526 raises its IRQ one cycle late, and an ICR read acknowledges through the delay line.
- The time-of-day clock no longer loses about one cycle per tick.
- Writing the mask to
-
Snapshots carry the whole CIA state. Older
.c64reand.vsffiles still load. Their CIA record is converted, and the restore says so.
Programs whose timing hung on the old approximation can run a few cycles differently.
TRX64 0.12.0 — a daemon that ends when nobody uses it
New
- The daemon can end itself when nobody uses it.
--idle-exit <seconds>(off by default) ends the daemon with exit 0 and[trx64] idle for N s — exitingonce, for the whole window, no request arrived, no A/V viewer was connected and no trace was recording.- A viewer or a trace holds the clock; the window starts when the last of them ends.
- Before exiting it persists the cartridge and both drives' disks exactly as eject does.
daemon/keep_alive { seconds | null }holds the daemon at least that long;nullmeans never on idle. The reply is the idle status.idleExitinpingandsession/state:armedSeconds,deadlineMs(epoch ms, or null when it won't end),keptAliveUntilMs,keptForever,holding("subscriber"|"trace"| null).- RPC-only clients connect with
?av=0. A streaming daemon subscribes every connection to the video and audio push. A client that only speaks JSON-RPC now says so: it gets no binary frames, doesn't start the pacing loop on its own account, and doesn't count as a viewer.
Docs
- The play-API doc lists
daemon/keep_aliveand?av=0. It used to saypingreturns{}; it names the build, the project and the idle state.
TRX64 0.11.1 — clean port hand-off, traces that stream
Fixed
- A second daemon on a port another runtime owns leaves cleanly.
- When several clients warm-start a daemon on the same port at once, the losers used to boot a whole C64 and then panic on the bind (exit 101).
- The port is now taken before anything boots. A port somebody else owns prints one line,
port N already owned by another runtime — exiting cleanly, and exits 0. - Any other bind error exits non-zero with the OS error.
- A recording trace streams to its
.c64retrace.- The run used to sit in memory until
trace/run/stop: the file stayed at 0 bytes while recording, the daemon grew with every frame, and a crash lost everything. - Now the frames are appended once they pass 4 MiB, and the tail at stop. The finished file is byte-for-byte the same size with the same events.
trace/statusgainsbytesWritten(on disk) next tobytesBuffered(pending).
- The run used to sit in memory until
TRX64 0.11.0 — a loaded program hears the keyboard, writes land where they belong
New
- Start a loaded program where you say.
runonmedia/open,session/load_prgandruntime/run_prgstarts the program at that address after the load, without going through the keyboard. It takes a number or hex text:2112,$0840,0x0840or0840.runtime/run_prgused to accept only a number and ignored text. session/create {exerciser: true}declares a CPU/chip exerciser: bytes poked, PC set, run cycle-exact on the CPU-isolated core. It is the only thing that leaves the full machine.
Fixed
- A loaded PRG hears the keyboard. Opening a PRG,
run_prg, or any monitorwr/a/r a=…used to latch the machine onto the CPU-only core as soon as no disk and no cartridge were attached. There the CIAs don't run, so the KERNAL never scans the keyboard:READY.stayed on screen and typed text never arrived. Loading, typing and poking now keep the booted C64 whole. - Autostart really starts.
media/openon a$0801BASIC program queuedRUNin a buffer nothing read. It now typesRUN:+ RETURN through the keyboard, asrun_prgdoes. The colon turns text left on the screen line into a following statement instead of a?SYNTAX ERROR, as VICE does.media/openalso sets VARTAB after a$0801load. media/persistwrites the mounted cartridge. It wrote the cartridge's bare file name, so a new.crtappeared in the daemon's working directory and the mounted file stayed unchanged.- The cartridge now has one backing path.
media/persist,savecrt,swapcrt, eject and auto-persist all use it. - After
swapcrt, eject and persist write the new cartridge's file, not the old one's. - A clean cartridge is no longer rewritten.
- The reply is
{written, role, path: <absolute path written>, bytes}, or{written: false, role, reason}.
- The cartridge now has one backing path.
- No write lands in the daemon's working directory any more. A relative path given to
snapshot/dump,snapshot/undump,recorder/dump,vsf/save,audio/export, a trace output orringbuffer/dumpresolves against the bound project. With no project bound it is refused, instead of being written wherever the daemon was started.media/ingressresolves its path the waymedia/mountdoes.
TRX64 0.10.0 — a block assembler, sandboxes that keep to themselves, Intel Macs
New
- Block assembler. The monitor assembles whole blocks with labels (
loop:),name = value,*,</>,+/-,.byte,.wordand one*=/.org:asm <addr>collects lines untilend,asm-file <path> [addr]reads a source file, and RPCasm/blockreturns bytes, labels and per-line errors without writing anything. A block is written only if all of it assembled. - Sandbox runs keep their own media. A sandbox run that writes its disk or flashes its cartridge gets its own copy under
<project>/sandbox/<stamp>-<run-id>/, reported undermedia; the original image is never written. A run that only reads makes no folder. - Nearest mark.
transport/statuscarriesnearestMark { name, framesAway }, and the transport line ends in it (alpha +160). - Intel Macs. Release binaries for macOS x86_64, cross-built from Apple silicon.
Fixed
- Sandbox runs no longer touch the live machine.
sandbox/runandsandbox/runManyrestored into the shared session and paused it; each run now works on its own clone, on its own thread. - Sandbox
--zp $00/--zp $01seeds reach the CPU port and override--io. The seed used to land in RAM only, so a routine seeded at$35ran at$34and aDEC $01went to$33with the character ROM at$D000. iecshows every unit on the bus: both drives by unit and type (1541 or 1581) and every folder or host device, not only drive 8.- Monitor help:
devicenames drive8 … drive11 and the 1581,mount/identifylist.d81,reuandgeoramare listed,resetis warm unlesscold, and theturbonote only says "stored" on the 128 profile. - The cockpit colours
.d81as a disk image.
Docs
- New
docs/FEATURES.md, one line per feature. - README, CLI README,
MONITOR.mdand the SwiftAPI.mdbrought in line with the code: platforms, cartridge types,.d81and unit-awaremount/eject, 25 monitor verbs that were missing, measured ring sizes, the NTSC canvas,realtimepacing.
TRX64 0.9.2 — paddles and mice, disk swaps that behave, the Commodore key on Control
Paddles and mice, disk swaps that behave, and the Commodore key on Control
The POT lines
The SID's paddle registers $D419/$D41A now answer the control port CIA 1 selects
($DC00 bits 6/7), and take a new value every 512 cycles, as the chip does.
- A host sets what its device delivers per port — paddles, a 1351 mouse, the extra fire
buttons of a multi-button joystick:set_pot(port, x, y)/clear_pot(port)in the
library,session/pot_set/session/pot_clearon the daemon,potin the monitor. - With nothing set a POT line reads
$FF, as an open line does on a real C64 (it was a
constant$80). Both ports selected combine like two resistors in parallel. - The monitor shows the value the CPU reads at
$D419/$D41A, not the write shadow.
Disk swaps
- The 1541 now notices an eject. The write-protect sensor's reaction to a disk being
pulled was missing, so a drive never saw the old disk leave — only the new one arrive.
Every eject and every disk swap now goes through it, with the timing VICE uses. runtime/swap_disk_and_continuedoes what it says: eject, let the drive notice,
insert, let the drive notice, press the confirm key, run on — and report the screen
before and after and whether the prompt changed. It used to mount the new disk at once and
report steps it never ran. The confirm key is held 400 000 cycles by default
(confirm_hold_cycles): games that read the keyboard every few frames miss a short press.
Keyboard
Host Control is the Commodore key, as in VICE. The C64's CTRL stays on ^ below ESC,
RUN/STOP on Tab. Cmd is no longer mapped. The cockpit's README lists the whole left edge.
Swift API
The Swift library reaches both drive positions (power, unit, reset, stop, status), the
drive type (1541 or 1581), .d81 disks and the folder device. Existing calls are
unchanged and still address drive 8. The daemon gained session/drives,
session/drive_reset, session/drive_stop and device/folders for it.
Docs
The README now describes embedding trx64-core: the drive positions, the folder device,
IecDevice, FdcController and the POT lines.
TRX64 0.9.1 — a controller of your own in the 1581
A controller of your own in the 1581
A program that embeds TRX64 can now replace a 1581's WD1772 with its own disk controller
(FdcController). This is for hosts that keep the disk image themselves and serve it
sector by sector — the way the Ultimate's firmware serves a .d81 from an open file.
- The controller sees every access to the WD registers (
$6000-$7FFF) at the drive's
cycle, the side select and motor from the drive's CIA, and the drive's reset and power.
It drives the drive's ready, disk-change and write-protect lines. - Fitted only while the drive is switched off, like any change to the board. While a
controller is fitted the drive has no disk of TRX64's own: mounting and ejecting are
refused. - The 1581 DOS waits for BUSY without a timeout: a controller must raise BUSY within
6 drive cycles of a command, or the drive hangs. - A snapshot leaves out the controller's state if it opts out, and names it; restoring a
snapshot whose controller does not match the machine is refused. - Without a controller nothing changes: the built-in WD1772 is untouched and costs
nothing extra.
For programs that embed trx64-core
- New: the
FdcControllertrait,Machine::attach_fdc_controller/detach_fdc_controller.