A port of the Amstrad CPC 6128 to the MEGA65, built on top of the
MiSTer2MEGA65 (M2M) framework and
based on the
MiSTer-devel/Amstrad_MiSTer
core (T80pa Z80 CPU, ga40010 gate array, UM6845R CRTC, YM2149 PSG,
i8255 PPI, u765 uPD765 floppy controller).
Current status: version 1.0, for MEGA65 R3 and R6.
The CPC 6128 boots end-to-end on real MEGA65 hardware with working keyboard,
video, sound, joystick, and two .DSK disk drives. What makes this port
unusual is that the MEGA65's internal 3.5" floppy drive works as a real CPC
drive - it reads genuine CPC disks, formats them, writes .DSK images onto
physical disks, and writes changed tracks back. This has been confirmed on real
hardware against a real CPC 6128: a disk formatted on the MEGA65 is read by the
CPC, and a game copied on the MEGA65 boots on the CPC.
See .research/PORTING-PLAN.md for the technical plan the port was built
against, and doc/m2m/exceptions.md for every change made to the framework and
to the MiSTer core, each with the reasoning behind it.
Green Beret (Konami, 1986) on real MEGA65 hardware:
![]() |
![]() |
On the left, the headline feature: a genuine CPC disk sitting in the MEGA65's
own 3.5" drive, catalogued from BASIC - Drive A: user 0, two files, 161K free. No .DSK file is involved. (The Syntax error lines above it are the
| character being typed wrong; on a CPC it is SHIFT + @, which is exactly the
sort of thing GETTING-STARTED.md exists to tell you.) On the right, CP/M Plus
booting off a real disk - 61K TPA, 2 disc drives.
Two guides come with the core. They live in doc/ here, and are attached to
the release as well so you can keep them next to the core on the SD card:
doc/GETTING-STARTED.md- read this one first if you have never used an Amstrad CPC. It assumes you are arriving from a Commodore machine and says so out loud: howCATis notLOAD"$",8, why the closing quote nobody types is optional, and where the|character lives on the MEGA65 keyboard (SHIFT + @) - which you need for every single disk command. It is also where the download links are: the three ROM files the core will not boot without, and where to find.DSKimages and the CP/M disks.doc/MANUAL-floppy.md- the technical manual for the real floppy drive: which disks it will accept (720K DD), what format gets written, what each menu action does, and what to do when the drive refuses and flashes red.
- Machine: Amstrad CPC 6128 (128 KB RAM), PAL video, Locomotive-compatible keyboard mapping on the MEGA65 keyboard, and joystick support with swappable ports.
- ROMs (not included): the core loads three mandatory 16 KB files from
/cpc4mega65/on the SD card -os6128.rom,basic6128.romandamsdos.rom- and does not boot without them. They are Amstrad firmware and are not mine to distribute. If one is missing, the core names the file it could not find rather than failing silently. - Disk drives: two virtual drives,
Drive A:andDrive B:, each able to mount a.DSKor.EDSKimage from the SD card, exactly like any other MiSTer2MEGA65 core. - Real floppy drive: either virtual drive can be replaced by the MEGA65's own internal 3.5" drive. See the next section; this is the headline feature.
- Video: CRT emulation, 4:3 / 5:4 / 16:9 HDMI aspect ratios, HDMI zoom.
- Audio: audio improvement filter.
- Settings: remembered across power cycles, with one deliberate exception (see "Actions are never remembered" below).
Set Internal floppy to Drive A: or Drive B: in the Options menu and that
drive stops being an image and becomes the physical 3.5" drive in your MEGA65.
Everything below happens on genuine CPC DATA-format disks (40 tracks, single
sided, 9 x 512-byte sectors, IDs &C1-&C9).
| Menu item | What it does |
|---|---|
Read disk now |
Reads the whole disk and builds a .DSK image in memory that the CPC then sees as a normal drive. Takes about 26 seconds. |
FORMAT WHOLE DISK !! |
Formats all 40 tracks in CPC DATA format. Destroys the disk data. |
COPY IMAGE TO DISK !! |
Writes the .DSK mounted in the other drive onto the physical disk. Destroys the disk data. |
WRITE BACK TO DISK !! |
Writes back only the tracks the CPC has modified since the last read. |
Auto write-back |
Does the same automatically, one second after the CPC stops writing. |
The MEGA65's drive LED is the main feedback channel, and it is deliberately blunt - it answers "did it work?", not "what happened":
- Blinking: while an operation is running.
- Green (0.5s): when an operation finished correctly.
- Amber (0.5s): when it finished badly (unreadable tracks, nothing written, or no disk in the drive).
- Red (0.5s): when the drive refused (the disk is write-protected, or the image cannot be copied).
- Amber (steady): while there are still modified tracks that have not been written back yet. Do not eject the disk while the LED is amber. No timer can promise you a safe moment; a "not yet" signal can.
Read disk now, FORMAT, COPY and WRITE BACK are actions, not settings.
They are cleared every time the core starts on purpose: the framework's
settings file stores every menu bit alike, so without this, a core that was
switched off with FORMAT ticked would format whatever disk was in the drive
at power-on. Internal floppy and Auto write-back are remembered because
those are states.
Actions also untick themselves as soon as the operation ends, so you never have to remember to clear them before running the same one again.
COPY IMAGE TO DISK !! reproduces what it can reproduce exactly, and refuses
the rest rather than writing a disk that looks finished and is not.
It handles sector sizes from 128 to 8192 bytes, tracks of up to ten sectors, tracks written without an index mark, and the anomalies copy-protected originals use to tell an original from a copy: deleted data marks, sectors with no data field at all, and data CRCs that are deliberately wrong. Reproducing those faults is copying faithfully - correcting them would break the disk, which is why the telemetry counts them separately from real errors. Tracks marked unformatted are skipped, which is what "unformatted" means.
Two things it cannot do, and both are properties of the file rather than of the format:
- An image whose own signature has bit flips is not recognised as a
.DSK. - A track whose sector headers share one physical data area, each declaring a
different length, cannot be rebuilt from an
.EDSKat all: the file records what the controller returned, not what is on the disk. Copying the original disk itself would need a flux-level controller, which is on the roadmap.
When the copier refuses, the LED goes red and the telemetry dump records exactly which rule was broken.
- The CPC runs at its authentic 50.08 Hz while HDMI outputs exactly 50.000 Hz, so one frame is dropped every 12.5 seconds. Fixing this is the first item in version 1.1.
- Switching the drive off mid-write leaves a half-written track. Closing the write gate immediately is the correct thing to do, but the track that was being written is lost. Let the operation finish.
Audio improvementsapplies a filter that was tuned for a C64, not for a CPC. The MiSTer Amstrad core defines no audio filter at all, so there were no correct values to copy from it and the framework's C64 defaults are still in place. It is a low-pass, so it does not damage the sound - but it does not model the 6128's output stage either. Doing it properly means deriving the coefficients from the real hardware, which is on the roadmap.- Only the CPC 6128 is implemented. The 464 and 664 are on the roadmap.
- No tape support yet; see
ROADMAP.md. - Comments in the source refer to
DECISIONES.md, which is not here. It is a day-by-day development log kept outside this repository and deliberately not published. Where a decision matters to someone reading the code, the reasoning is in the comment itself, so nothing is hidden behind that name - but the dangling reference is real and you will run into it.
Read disk now builds the image in memory from nothing. COPY IMAGE TO DISK !! is the opposite direction and needs a source, so the other drive has
to have a real .DSK mounted - if Internal floppy is Drive A:, the copier
reads from Drive B:.
The copier checks every track and every sector header of the source image before it opens the write gate once. A disk is either copied or left untouched; it is never left half-overwritten because the copier discovered a problem on track 30.
Only the tracks the CPC actually modified are written back, and a track that could not be read completely is never written back at all. The in-memory image does not hold its true contents, so writing it would punch holes in a disk that was fine.
The project targets Vivado 2022.2. There is one build script per board:
vivado -mode batch -source CORE/build_core.tclvivado -mode batch -source CORE/build_core_r3.tclThe first builds for R6, the second for R3. They differ in exactly one line -
which .xpr they open - because the R3 and R6 projects are otherwise the same
sources with different top-level entities and constraints.
Both scripts currently contain absolute paths to the machine they were
written on, so you will have to edit the E:/CPC4MEGA65/ prefixes before
either one will run anywhere else. That is a real defect and it is on the list
for 1.1; it is mentioned here rather than left for you to discover on the first
line of output.
The build script checks timing after implementation and fails the build on negative slack. Vivado will happily write a bitstream that does not meet timing, but the resulting core fails erratically on real hardware.
The QNICE Shell firmware is reassembled automatically at the start of synthesis
(CORE/m2m-rom/synth_pre.tcl), which also regenerates the menu index constants
from CORE/vhdl/mega65.vhd, so a menu change can never leave a stale index
behind in the firmware. The build stops if that reassembly did not actually
happen - it checks that the firmware image is newer than its sources, rather
than trusting the exit code of the script that builds it. That matters more
than it sounds: a stale firmware passes timing cleanly, because the contents of
an initialised BRAM never touch the critical path, and the only symptom is menu
lines that do somebody else's job.
See AUTHORS. In short: the Amstrad CPC hardware is Amstrad plc's, the MiSTer
core is the MiSTer Development Team's, the framework is MiSTer2MEGA65's, and
the MEGA65 port is mine. No Amstrad ROMs are included.
Particular thanks to sy2002 for MiSTer2MEGA65 and for his help along the way. The framework is what makes a port like this the work of weeks rather than months - the QNICE Shell, the on-screen menu, the HDMI pipeline and the SD card handling are all his and his team's, and none of it had to be invented here. He also took the time to answer the questions raised upstream during this port, both on how a menu item that performs an action should behave and on where physical floppy drive work had already been done in the C64 core. That guidance is shaping where this port goes next.


