In meinem Keller stehen Kisten voller alter 5,25-Zoll-Disketten. Commodore-Software aus den späten 80ern, Spiele, Tools, selbstgeschriebener Kram. Das Problem mit Floppy-Disks: die Magnetisierung lässt mit der Zeit nach. Alle paar Jahre sollte man die Daten einmal komplett lesen und zurückschreiben, sonst wird das Medium irgendwann unlesbar. Mein letztes Auffrischen ist eine Weile her, also war es mal wieder Zeit. Zugegeben, ich arbeite nur noch extrem selten mit meinem Commodore; aber wenn ich es mache, ist es immer eine kleine Zeitreise voller Nostalgie für mich. Die Geräusche, der Geruch, die Wartezeit. Hin und wieder tut es mir einfach gut, noch mal die alten Spiele zu spielen, mit den Tools zu arbeiten oder auch meine ersten eigenen Programme noch mal zu starten, in den Code zu schauen *kopfschütteln*…. Ich habe sogar noch alte Hausaufgaben auf Disketten 😀
Was als routinemäßige Sicherungsaktion geplant war, wurde dann allerdings eine mehrtägige Debugging-Session. Inklusive eines Firmware-Bugs, der seit sechs Jahren im Code schlummerte.
Die Ausgangslage
Mein Setup: Zwei Commodore 1571 Laufwerke, angeschlossen über einen xum1541 USB-Adapter an einem Linux-Rechner. Der xum1541 sitzt auf einem TEENSY2-Board (ATmega32U4) und spricht über USB mit OpenCBM, einer Open-Source-Treibersammlung für Commodore-Laufwerke. Die Software-Seite hatte ich in einer vorherigen Session bereits verifiziert. Beide Laufwerke laufen bei fast perfekten 300,5 RPM, lesen und schreiben fehlerfrei auf beiden Seiten und liefern sogar bit-identische Images im Crosscheck.
Der Plan war simpel: Alle Disketten systematisch als 1:1-Image sichern, die physischen Medien durch Zurückschreiben auffrischen und nebenbei prüfen, ob die Inhalte bereits in Online-Archiven wie CSDB, Gamebase64 oder dem Internet Archive vorhanden sind.
Der xum1541 im gelben Gehäuse. Links das USB-Kabel zum Linux-Rechner, rechts das IEC-Kabel zur 1571:

Und ein Blick auf die Platine mit dem Teensy2-Board (ATmega32U4), in dem der Firmware-Bug steckte:

Disk 001: Pirates! und das Kopierschutz-Problem
Die erste Disk war eine Pirates!-Kopie (Microprose, 1987), „imported by The Critters Inc 1221“. Mit d64copy ausgelesen, 683 Blocks, keine Fehler. Dann zurückgeschrieben und zur Verifikation nochmal gelesen. Checksummen stimmten nicht überein.
Die Analyse ergab: Das Original-D64 enthält drei Sektoren mit Error Code 5 (Data Block Checksum Error) auf Track 23 und 24. Das ist klassischer C64-Kopierschutz. Microprose nutzte absichtliche Lesefehler, um Raubkopien zu erkennen. Das Spiel prüft beim Start ob diese Fehler vorhanden sind, fehlen sie, verweigert es den Dienst.
d64copy arbeitet auf Sektor-Ebene und kann solche GCR-Level-Fehler nicht reproduzieren. Die Error-Info wird zwar im D64 gespeichert (Emulatoren wie VICE werten sie aus), aber auf der physischen Disk gehen die absichtlichen Fehler beim Zurückschreiben verloren. Für eine echte 1:1-Kopie inklusive Kopierschutz braucht man nibtools. Das arbeitet direkt auf GCR/Nibble-Ebene und liest die Rohdaten vom Laufwerk, inklusive aller Timing-Patterns und absichtlichen Fehler.
nibtools bauen und der erste Crash
nibtools liegt als Quellcode im OpenCBM-Quellbaum, muss aber separat gebaut werden. Ich habe den markusC64-v637 Branch von GitHub genommen. Build mit dem cc65 Cross-Compiler für den 6502-Floppy-Code und gcc für die Host-Tools ging glatt. Erster Versuch:
nibread -D8 image.nib
Ergebnis: LIBUSB_ERROR_PIPE. Der USB-Transfer bricht sofort ab, nachdem der Drive-Code hochgeladen ist. nibtools erkennt die 1571 korrekt und versucht SRQ-Burst-Transfers zu nutzen, ein schnelles serielles Protokoll das die CIA-UART der 1571 verwendet. Aber der Transfer scheitert schon beim Communication-Test.
Drei Schichten tief: der Firmware-Bug
Schicht 1: Bekannter SRQ-Bug in Firmware v7. Die xum1541-Firmware v7 hatte einen dokumentierten Bug: IEC_SRQ war als 0x80 definiert (Bit 7), aber die Lookup-Tabelle iec2hw_table hatte nur 16 Einträge (4 Bits). SRQ-Operationen griffen ins Leere. In v8 gefixt: IEC_SRQ auf 0x10 geändert, Tabelle auf 32 Einträge erweitert. Commit 3ef4fc0d von Spiro Trikaliotis, 2021.
Problem: Es gab kein fertiges v8-Hex für das TEENSY2-Board. Nur für ZOOMFLOPPY und PROMICRO. Die Boards haben unterschiedliche Mikrocontroller-Pin-Belegungen, also kann man die Firmware nicht einfach zwischen Boards tauschen. Lösung: AVR-Toolchain installiert (gcc-avr, avr-libc), v8 für TEENSY2 selbst gebaut und über den HalfKay-Bootloader geflasht.
teensy_loader_cli --mcu=atmega32u4 -w -v firmware.hex
Risikofrei, da der Bootloader in einem geschützten Flash-Bereich sitzt. Knopf am Teensy drücken, flashen, fertig.
Schicht 2: v8 geflasht, gleiches Problem. Auch mit v8 kommt LIBUSB_ERROR_PIPE. Die OpenCBM-Library musste ebenfalls neu gebaut werden, sie prüft die Firmware-Version und war noch auf v7 kompiliert. Neu gebaut, installiert. Immer noch Crash.
Schicht 3: Der eigentliche Bug. Also tiefer in den Quellcode. In board-teensy2.h, Funktion iec_srq_write():
// BUGGY — seit Commit 57bb6726 (April 2020) PORTD = (((data >> 4) & IO_DATA) ^ IO_DATA) | IO_SRQ;
Das wurde 1:1 von der ZoomFloppy-Implementierung kopiert. Aber die Pin-Belegung ist bei den Boards unterschiedlich:
- ZoomFloppy hat
IO_DATAauf Port D, Bit 4 (PD4) - TEENSY2 hat
IO_DATAauf Port F, Bit 0 (PF0)
Der Code schrieb auf den komplett falschen Port mit dem falschen Bit-Shift. Das erklärt warum der Communication-Test sofort fehlschlug. Die SRQ-Daten kamen nie auf den richtigen Pins an.
Der Fix, analog zur korrekten PROMICRO-Implementierung:
// FIXED uint8_t port_base_data = (DDRF & IO_ATN) | IO_SRQ; // ... DDRF = (((data >> 7) & IO_DATA) ^ IO_DATA) | port_base_data;
Die Änderungen im Detail: PORTD wird zu DDRF (richtiger Port für die IEC-Leitungen beim TEENSY2), der Shift von data >> 4 auf data >> 7 (Bit 7 des Datenbytes auf Bit 0 des Ports, wo IO_DATA liegt), und der ATN-Zustand wird über port_base_data erhalten, was vorher nicht berücksichtigt war. Timing von 0,935 µs auf 0,80 µs angepasst, passend zur PROMICRO-Implementierung.
Firmware neu gebaut (8260 Bytes, 32 mehr als vorher), geflasht. nibread läuft sofort fehlerfrei durch alle 41 Tracks. Der Bug steckte seit April 2020 im Code. Jeder mit einem TEENSY2-basierten xum1541 hatte dieses Problem bei SRQ-Transfers.
Den Fix habe ich als Pull Request eingereicht, der am 26. März vom OpenCBM-Maintainer Spiro Trikaliotis gemerged wurde. Damit ist auch ein seit 2021 offenes Issue im nibtools-Repository endlich geschlossen. Dort hatten andere User auf macOS und Fedora mit Teensy-basierten Adaptern exakt die gleichen LIBUSB-Fehler gemeldet, ohne dass die Ursache gefunden wurde.
Die bittere Lektion mit Disk 001
Die erste Pirates!-Disk, der Import von The Critters Inc, war zu diesem Zeitpunkt bereits zerstört. Ich hatte sie vor dem Fix mit d64copy zurückgeschrieben. Das hat die GCR-Level-Kopierschutzmuster überschrieben. Das anschließend mit nibread erstellte NIB-Image zeigt nur noch die „reparierten“ Sektoren, nicht den originalen Kopierschutz. Disk und Images entsorgt.
Die Lektion ist simpel und ärgerlich zugleich: Nie zurückschreiben, bevor das NIB-Image existiert.
Der Workflow ab Disk 002
Ab der zweiten Disk lief der Prozess dann sauber:
nibread -D8— GCR-Rohdaten lesen, inklusive Kopierschutzd64copy— Sektor-Level-Image für Emulatorennibwrite— 1:1 zurückschreiben aus dem NIB (erhält Kopierschutz)d64copynochmal lesen + MD5-Vergleich zur Verifikation
Ergebnisse
| Disk | Inhalt | Status |
|---|---|---|
| 001 | Pirates! (The Critters Inc) | Verloren — Kopierschutz vor dem Fix zerstört |
| 002 | Ace of Aces, Light Force, Hacker + Trainers | Gesichert + aufgefrischt, Killer Track auf Track 1 erhalten |
| 003 | Commando, The Last V8, Robin of the Wood | Verloren — Medium physisch zu schwer beschädigt |
| 004 | Warplay, Worldcup 86, Hyper Olympics | Gesichert, Original-Disk defekt (T18/S15) |
| 005 | Pirates! (The Red Lions Import, 2-Disk) | Gesichert + aufgefrischt + verifiziert |
Technische Eckdaten
Für die Leute die es genau wissen wollen:
- Hardware: 2× Commodore 1571, xum1541 (TEENSY2, ATmega32U4), Linux-Host
- Software: OpenCBM (from source), nibtools (markusC64-v637), VICE 3.7.1
- RPM: Konstant 300,5 RPM (Nominal: 300). Die 1571 ist elektronisch geregelt, kein Trimmpoti
- Kopierschutz-Typen: Error Code 5 (Checksum Errors) auf Pirates!, Killer Track (Track komplett mit Sync-Bytes) auf der Crocodile Soft Compilation
- NIB-Format: ~336 KB pro Disk (41 Tracks × 8192 Bytes GCR-Rohdaten)
- D64-Format: ~175 KB pro Disk (683 Sektoren × 256 Bytes + optional 683 Bytes Error-Info)
Fazit
Was als „schnell mal Disketten auffrischen“ geplant war, endete in einer Reise durch sechs Jahre alten Firmware-Code. Der Bug in iec_srq_write() war ein klassischer Copy-Paste-Fehler, der nie aufgefallen ist, weil kaum jemand nibtools mit einem TEENSY2-Board benutzt. SRQ-Burst-Transfers braucht man nur für nibtools, und die meisten Leute nutzen ohnehin einen ZoomFloppy-Adapter, wo der Code korrekt ist.
Der Verlust von Disk 001 ärgert mich immer noch. Aber die Lektion sitzt: Erst NIB, dann zurückschreiben. Und wenn ein Tool beim ersten Mal nicht funktioniert, lohnt es sich manchmal die Firmware aufzuschrauben, statt das Tool wegzulegen.
Der Blick ins Regal, wo das alles steht. Ja, es ist voll da unten:


Siehe auch: Commodore – PC Projekt (mein erster Versuch mit cbm4linux und einem XM1541-Kabel, anno 2009) und VC-64 Turbo Tape (1986).
Fragen? Einfach melden.





Einige Male habe ich mir schon vorgenommen die ganzen Schlabberdisketten irgendwie ordentlich zu archivieren. Tja, aber wie? Von Schlabberdiskette auf Schlabberdiskette kopieren ist nicht das Gelbe vom Ei. Zum Einen sind die Dinger einfach zu empfindlich und zum Anderen gibt es auch Disketten die sich nicht so einfach kopieren lassen. Ich denke da z.B. an GEOS usw…
Also, was machen? Ein PC-Laufwerk für die Schlabberdisketten kann die Commodore beschriebenen leider nicht lesen. Das liegt jetzt nicht am genutzten Dateisystem auf den Datenträgern, sondern an der Art wie der Kontroller die Daten auf die Diskette packen lässt. Daher fällt es schon einmal flach diese einfach mit einem einfachen PC-Laufwerk kopieren bzw. archivieren zu wollen. Vielleicht kann man das Commodore Laufwerk ja einfach in den PC einbauen? Hm, so einfach geht das nicht aber man könnte über ein Kabel die komplette Floppy an seinen Computer anschließen. Zumindest hat mir google so etwas erzählt. Dann könnte ich auch Disketten 1A kopieren und öhm Images von Disketten machen und diese archivieren. Wie viele C64 Diskette (jede Seite hat ~170,8KB) bekomme ich wohl auf eine CD-ROM oder gar DVD *denk*? Diese Idee mit dem Kabel und der ganzen Floppy am PC hat mir gefallen, daher habe ich google mal nach dem Kabel gefragt.
Die Antwort war dieser Schaltplan zu einem XM1541 Kabel:
Gut, schaut ja nicht sonderlich schwer aus. Ich brauche quasi nur:
– 1 x 25 Pol. LPT Stecker
– 1 x 6 Pol. DIN Stecker
– 4 x Diode BAT85 (sind diese Schottky Dioden), die 1N5819 sollten also auch klappen.
– 1 x 5 Pol. geschirmte Leitung (ungeschirmt geht sicher auch. Nur halt nicht bei Leuten mit Hirn)

Jetzt kann ich auch schon meine 1541 Floppy an meinen Laptop anstöpseln:
Ja, so gefällt mir das schon. Schaut doch ganz nett aus, oder?
Den Hardwareteil hätten wir damit. Jetzt müssen wir es nur noch schaffen, der Hardware zu sagen was sie machen soll. Also mal wieder google nach Hilfe gefragt. Cbm4linux soll da wohl die Lösung meiner Probleme sein. Auf der Homepage zu 

Richtig geil wird es aber erste wenn man einen C64 / C128 oder ähnlich Emulator benutzt. Ich nutze hier VICE. 1A Teil. Dieser unterstützt nämlich die Anbindung von einer echten Commodore Floppy an einen PC. Weil der PC „etwas“ schneller ist als der Commodore 64 mit seiner 1MHz CPU rennt alles (je nach Einstellung) natürlich auch wie Sau. Schaut selbst:


