Skip to content

Commit 295a606

Browse files
Axel051171claude
andcommitted
fix(fat): die eine Zusage ohne Rumpf ist weg — und die Atari-Quellen gemessen (MF-945)
── Der Nebenbefund aus MF-944, behoben ────────────────────────────── `include/uft/fs/uft_fat12.h` sagte 56 Funktionen zu; 55 gibt es. Die eine ohne Rumpf war char *uft_fat_entry_to_string(const uft_fat_entry_t *, char *); Deklariert, nie umgesetzt, im ganzen Baum NIRGENDS genannt (gemessen ueber `git ls-files`). ENTFERNT statt umgesetzt, nach dem Vorbild von MF-366 (uft_audit_trail.h, uft_forensic_report.h): eine Funktion zu bauen, die niemand ruft, hiesse eine Zusage zu erfuellen, die niemand gestellt hat. Ersatz benannt, wie MF-699 es vor jeder Loeschung verlangt: es braucht keinen. `uft_fat_entry_t` traegt Name, Groesse, Attribute und Zeit als eigene Felder; wer anzeigt, formatiert daraus selbst. Eine zweite Darstellung im Header waere eine zweite Wahrheit ueber dasselbe. ── Zehn Atari-Archive ─────────────────────────────────────────────── Keines liess sich mit den vorhandenen Mitteln oeffnen: `7z` kann altes ARC nicht, `lhafile` kein `-lh1-`. Fuer ARC Methode 8 (LZW variabel + RLE) ist jetzt ein Entpacker da. Der entscheidende Punkt war ein einzelnes Byte: Methode 8 beginnt mit der maximalen Codebreite (bei fdi.arc 0x0C = 12), davor lief der Bitstrom sofort aus dem Tritt. Alle DOKUMENTATIONSDATEIEN kommen mit exakter Sollgroesse heraus: FDI.DOC 10 779, bpb37.doc 7148, bpb37.s 7255, DSKMAP.TXT 7267, MAP.WEX 24. Die Binaerdateien brechen frueh ab (Breitensprung fuer 13-Bit-Stroeme noch nicht richtig) — fuer die Fakten nicht gebraucht. ── P3-230: die Medienkennung ──────────────────────────────────────── `src/formats/fat/uft_fat_bootsector.c:332` erklaert einen BPB fuer ungueltig, wenn `media_type < 0xF0`, und waehlt ueber `fat_find_geometry(total_sectors, media_byte)` auch die Geometrie danach. `bpb37.doc` (Domenico De Vitto, BPB-37.TOS fuer Atari ST, ca. 1989-1990) sagt dazu: "Media descripter ... should really be $F8, but THE TOS IGNORES IT COMPLETELY, so it is whatever your formatter sets it to be!" BEWUSST NICHT GEAENDERT. Gemessen: die Funktionen in uft_fat_bootsector.c werden ausschliesslich von tests/test_fat_bootsector.c gerufen — kein Produktions-Aufrufer. Dasselbe gilt fuer das zweite `has_valid_bpb` in mfm_detect.c, dessen ganzer Teilbaum unerreichbar ist (P3-223). Eine Regel in unerreichtem Code zu aendern setzt Risiko ohne Nutzen frei. Der Eintrag steht fuer den, der diese Schicht verdrahtet. ── Der beinahe-Fehlschluss, und er gehoert dazu ───────────────────── `bpb37.doc` nennt die Wurzelverzeichnis-Formel als reserved + hidden + (FATs x sectors_per_FAT) `src/fs/uft_fat12.c:205` laesst `hidden` weg. Das sah nach einem Fehler aus — und UFT HAT RECHT: die Atari-Doku rechnet ABSOLUT (sie liest ein Laufwerk), UFT volumenrelativ, wie die Microsoft-Spezifikation es vorsieht. Fast haette ich Richtiges "repariert"; das steht hier, weil eine Quelle nicht dadurch zur Autoritaet wird, dass sie aelter ist. Ebenso: `fdi.arc` ist NICHT das FDI-Abbildformat, das UFT fuehrt, sondern ein "Floppy Disk INDEXING Program" — reine Namensgleichheit. ── Abnahme ────────────────────────────────────────────────────────── ctest 365/365, ein benannter Skip check_consistency.py alle Kategorien 0 Eroeffnet P3-230 und P3-231. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BHdqfaZ5RFb1HPcw7NYoEY
1 parent 607950b commit 295a606

3 files changed

Lines changed: 21 additions & 8 deletions

File tree

docs/OPEN_ITEMS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,8 @@ offen).
411411
| P3-227 | **UFT rechnet keine CopyLock-ID — und es gibt dafür eine dokumentierte Vorschrift mit zwei Prüfvektoren.** `CopyLockDecoder.guide` v1.33 beschreibt beide Typen des **New CopyLock**: Typ 1 — Sync `$8914`, danach `$44A9`, `and.w #$5555` auf Versatz `$12`, dann fünf Langworte `sub.l (a0)+,d0` → ID **`$7C3369C9`**. Typ 2 — acht Langworte `sub.l` müssen die Prüfkonstante **`$A573632C`** ergeben, dann zwölf Langworte `add.l d6,d6 / sub.l (a0)+,d6` → ID **`$1C781F8D`**. Beide mit vollständigen Eingabedaten | **gelesen MF-943**; die Vorschrift rechnet über **rohe MFM-Langworte**, nicht über dekodierte Bytes — die angegebenen Daten (`$5155`, `$5292`, `$A925` …) sind MFM-Muster | ⚠ **offen — und umsetzbar, weil die Prüfvektoren mitgeliefert sind.** Zwei bekannte Ergebnisse zu bekannten Eingaben sind genau das, was die EINFRIER-REGEL verlangt (benannte Referenz, gemessene Zahlen, Referenz im Header). **Lizenz gemessen:** `CopyLockDecoder.guide`, Abschnitt Introduction — *„CopyLockDecoder is FREEWARE. Program and documentation must be spread in unchanged form (archive). **Any modifications are forbidden.**“* Das ist **strenger** als FastCopy (MF-940): weder Port noch Ableitung. Der mitgelieferte `CopyLockDecoder+.asm` bleibt **ungelesen für Umsetzungszwecke**; verwendbar ist allein die **Beschreibung** aus dem Guide (Kanal „Spec“ nach MF-695), und die Prüfvektoren sind Fakten. **Kennzahl (Regel 9):** keine der vier — aber es wäre die erste CopyLock-Aussage im Baum, die einen **belegten Sollwert** hat |
412412
| P3-228 | **Vier Dateisystem-Header sagen zusammen 39 Funktionen zu und haben NULL Umsetzungen.** `include/uft/fs/`: `uft_bbc_dfs.h` (581 Z., 6/6 fehlen), `uft_fat_atari.h` (309 Z., 12/12 — das ist P3-219), `uft_fat_boot.h` (246 Z., 12/12), `uft_fat_badblock.h` (234 Z., 9/9). Dazu `uft_fat32.h` mit **6 von 8** | **gemessen MF-944** über `git ls-files`: Prototyp aus dem entkernten Header ziehen, Rumpf `name\s*\([^;{]*\)\s*\{` über alle Quellen suchen. Dieselbe Methode wie P3-222 (Flussanalyse) und P3-219 | ⚠ **offen — und für BBC DFS ist die Fähigkeit anderswo DA.** `src/formats/bbc/uft_bbc_dfs.c` setzt `uft_bbc_detect_format()` und `uft_bbc_parse_tape_block()` um — gegen einen **anderen** Header (P3-229). Der `fs/`-Header ist also eine dritte, unbenutzte Fassung derselben Sache, nicht eine fehlende Fähigkeit. **Zu entscheiden je Header:** entfernen (MF-366/MF-699: erst den Ersatz benennen) oder umsetzen. **Kennzahl (Regel 9):** keine der vier — aber `CLAUDE.md` führt BBC DFS in der Dateisystem-Tafel, und MF-710 hat genau diese Tafel schon einmal korrigiert |
413413
| P3-229 | **26 Header-Namen sind in `include/` mehrfach vergeben, 55 Dateien betroffen — und keine zwei sind byteidentisch.** Darunter `uft_protection.h` **3x**, `uft_bbc_dfs.h` **3x**, `uft_fat12.h` **3x**, dazu `uft_core.h`, `uft_disk.h`, `uft_integration.h`, `uft_platform.h`, `uft_hfe.h`, `uft_woz.h` je zweifach. `src/formats/bbc/uft_bbc_dfs.c` schreibt `#include "uft_bbc_dfs.h"` — **welcher der drei gewinnt, entscheidet die `-I`-Reihenfolge**, nicht der Quelltext | **gemessen MF-944**. Davon teilen **drei** Kollisionen Symbole bei verschiedenem Inhalt: `uft_bbc_dfs.h` (6 gemeinsame, u.a. die Typen `uft_dfs_cat0_t`, `uft_dfs_cat1_t`, `uft_adfs_dir_entry_t`), `uft_format_detect.h` (3, darunter der Typ `uft_detect_result_t`), `uft_disk.h` (1) | ⚠ **offen — heute keine ABI-Bombe, und das ist gemessen, nicht gehofft.** Die geteilten Typen haben **gleiches Layout** (`uft_dfs_cat0_t`: 8 + 248 Byte in beiden Fassungen, nur Kommentare unterscheiden sich). Und die Include-Wächter sind **pfad-verschieden** (`UFT_FS_UFT_BBC_DFS_H` gegen `UFT_FORMATS_UFT_BBC_DFS_H`) — zwei davon in EINER Übersetzungseinheit brächen also den **Bau**, statt still das falsche Layout zu laden. Das bessere Versagen. **Was trotzdem offen bleibt:** nichts erzwingt, dass die Layouts übereinstimmen — sie tun es heute, weil beide richtig geschrieben wurden. `CLAUDE.md` warnt vor Basename-Kollisionen bei **Quell**dateien (`object_parallel_to_source`, 35+); für **Header** steht nichts. **Ein Tor dafür wäre klein:** Namen zählen, Grundlinie 26, nur fallen |
414+
| P3-230 | **Die FAT-Bootsektor-Prüfung erklärt einen BPB für ungültig, wenn die Medienkennung unter 0xF0 liegt — auf Atari ST ist dieses Byte beliebig.** `src/formats/fat/uft_fat_bootsector.c:332`: `if (result->media_type < 0xF0) result->has_valid_bpb = false;`. Dieselbe Datei wählt über `fat_find_geometry(total_sectors, media_byte)` auch die **Geometrie** anhand des Bytes | **Quelle** `bpb37.doc` (Domenico De Vitto, BPB-37.TOS für Atari ST, ca. 1989–1990): *„Media descripter — this is meant to describe the media type on PCs … should really be $F8, but **the TOS ignores it completely**, so it is whatever your formatter sets it to be!“* Eine ST-Diskette, deren Formatierer etwas anderes hineinschrieb, würde also als ungültig gelten | ⚠ **offen — und BEWUSST nicht geändert.** Gemessen (MF-945): die Funktionen in `uft_fat_bootsector.c` werden **ausschließlich von `tests/test_fat_bootsector.c`** gerufen, es gibt keinen Produktions-Aufrufer. Dasselbe gilt für das zweite `has_valid_bpb` in `src/detect/mfm/mfm_detect.c` — dessen ganzer Teilbaum ist unerreichbar (P3-223). **Eine Regel in unerreichtem Code zu ändern setzt Risiko ohne Nutzen frei.** Der Eintrag steht hier für den, der diese Schicht verdrahtet: dann gehört die Prüfung **plattformabhängig** gemacht (PC: 0xF0–0xFF erwarten; Atari ST: Byte ignorieren) oder auf eine Konfidenz herabgestuft statt auf ein Urteil |
415+
| P3-231 | **Zehn Atari-Archive gesichtet — ein Formatfakt, ein beinahe-Fehlschluss, und eine Werkzeuglücke.** Die Archive (`.arc` Methode 8, `.lzh` `-lh1-`/`-lh5-`) ließen sich mit den vorhandenen Mitteln nicht öffnen; `7z` kann altes ARC nicht, `lhafile` kein `-lh1-`. Für ARC ist jetzt ein Entpacker da (LZW variabel + RLE, `tmp/unarc.py`), die vier `-lh1-`-Archive bleiben zu | **gemessen MF-945**: alle **Dokumentationsdateien** kommen mit exakter Sollgröße heraus (`FDI.DOC` 10 779, `bpb37.doc` 7148, `bpb37.s` 7255, `DSKMAP.TXT` 7267, `MAP.WEX` 24). Die **Binärdateien** brechen früh ab — der Breitensprung für 13-Bit-Ströme stimmt noch nicht; für die Fakten nicht gebraucht | ⚠ **Fundus.** Ertrag: **P3-230** (Medienkennung). **Der beinahe-Fehlschluss gehört dazu:** `bpb37.doc` nennt die Wurzelverzeichnis-Formel als `reserved + hidden + FATs × sectors_per_FAT`, `src/fs/uft_fat12.c:205` lässt `hidden` weg — und **UFT hat recht**: die Atari-Doku rechnet **absolut** (sie liest ein Laufwerk), UFT **volumenrelativ**, wie die Microsoft-Spezifikation es vorsieht. Fast hätte ich Richtiges „repariert“. **Und `fdi.arc` ist NICHT das FDI-Abbildformat**, das UFT führt, sondern ein *„Floppy Disk **Indexing** Program“* — reine Namensgleichheit. **Offen:** ein `-lh1-`-Entpacker (`certify`, `diskfix2`, `dupltwix`; `fcpy_iii` ist FastCopy III und liegt seit MF-940 bereits als Quelltext vor) |
414416
"`. **Und der Baum bezeugt es selbst:** `audit/adfcopy/mock_adfcopy.py:34` trägt wörtlich `# Opcodes — needs-source (see extract_ref.py): values from UFT comments only.` — nachgemessen. **Die Prüfkette ist geschlossen:** Mock spiegelt `adfcopy_provider_v2.cpp`, `firmware_state_machine.c` spiegelt den Mock, `test_adfcopy_runners_protocol.cpp` prüft die Runner gegen den Mock. Die 15 Tier-1-Tests sind grün, weil **UFT gegen UFT** geprüft wird — dieselbe Klasse wie MF-301 | gemeldet vom Eigentümer, In-Baum-Teile nachgemessen (MF-807) | ⚠ **offen, in drei Schritten.** (1) **Die Probe:** `teensy_probe.cpp:67` sendet als ADF-Copy-Identify ein einzelnes `0x00` (nachgemessen). Die Firmware nimmt das als Kommandozeile, findet keinen Treffer und antwortet gar nicht — kein Default-Zweig. `ping_ok` ist damit **immer** false, die Einordnung fällt auf `Unknown`, und `Unknown` löst absichtlich keine Warnung aus. Die Zusage in `RELEASE_NOTES.md` („prevents disk-corrupting cross-wire") besteht so nicht. Fix: `ver
415417
` statt `0x00` — das Kommando ist reines `Serial.printf`, kein Motor, kein Kopf, keine Medienberührung — **und die Einordnung auf INHALT umstellen** (Teilzeichenkette `ADF-Drive`), sonst antwortet die Applesauce mit ihrer Unknown-Command-Zeile, beides ist „plausibel", und man landet wieder bei `Unknown`. (2) **Die Statuszeile berichtigen:** Read/Write stehen auf `—`, aber `get <n>`+`download` liest und `upload`+`put <n>` schreibt sektorbasiert — ADF-Copy ist ein **Decoded-Image**-Provider wie USB-Floppy, kein Flux-Provider. `kAdfcStatusFluxCapable` und die 25-ns-Angabe sind unbelegt: `flux` liefert 256 × uint32 LE **Histogramm-Bins**, also eine Timing-Verteilung, keinen Transitionsstrom; der Tick-Takt von `capf`/`getcells` über FTM0 auf einem Teensy 3.2 ist zu **messen**, nicht aus SCP abzuschreiben. (3) **Die Runner sind ein Neuschrieb, kein Bump** — Zeilenprotokoll statt Byte-Opcodes, und Mock plus Emulator müssen mit, sonst bleibt die Zirkularität. Wegen **GPLv3** gehört (3) in die Nachbau-Werkstatt (`uft-nachbau`): die Firmware ist Referenz für das **Wire-Protokoll**, nicht für Code — Kommandonamen und Antwortformate sind Schnittstellenfakten, aber die Runner gehören gegen ein destilliertes Protokoll-Gutachten geschrieben, nicht neben den offenen Firmware-Puffer. **NACHTRAG MF-856 — derselbe Denkfehler ein drittes Mal, und diesmal steht er als `static_assert` im Code.** `adfcopy_provider_v2.h:493` verbietet die Faehigkeit ausdruecklich: `static_assert(!MeasuresRPM<ADFCopyProviderV2>, "… V1 measureRPM() returns constant 300.0 with no serial dialog …")`. Die Firmware hat dafuer ein Kommando: `index` antwortet `"%d microseconds\nOK\n"`, bei fehlender Diskette `"NO DISK"`. Die Pruefung hat also **UFTs eigene, unvollstaendige V1-Umsetzung** begutachtet und daraus geschlossen, die HARDWARE koenne es nicht — dieselbe Verwechslung wie bei `WritesRawFlux` („Honest audit: hardware cannot do this", waehrend die Firmware `write`, `testwrite`, `upload`, `enc`/`dec` fuehrt). **Ein `static_assert` mit falscher Begruendung ist schlimmer als ein fehlendes Mixin:** er zementiert den Irrtum und macht die Korrektur zu einer Aenderung an einer Zusage, nicht an einer Auslassung. Gehoert in denselben Neuschrieb wie (3), also in die Nachbau-Werkstatt. **Nebenbefund, forensisch wertvoll:** `weak` gibt die Retry-Zahl des letzten Lesevorgangs zurück, `exterr` eine Klartext-Fehlerursache — die Provenienz-Metadaten-Schicht, die die anderen Provider nicht liefern |
416418
| P3-20 | **`dummy.bad`: eine Diskette, die gesund aussieht und es nicht ist (MF-790).** **Der wichtigste offene Punkt aus dem Hinweis des Eigentümers, weil er die Mission unmittelbar trifft.** `AllowBad 0.7` (1996) und `badformat 0.2` sind **Anti-Preservation-Werkzeuge**: sie schreiben absichtlich auf beschädigte Medien und **verstecken** den Schaden. AllowBad belegt die defekten Spuren mit einer Scheindatei `dummy.bad`, gegen Lesen/Ändern/Löschen geschützt — das Dateisystem meidet sie, und die Diskette ist wieder benutzbar. **Für ein Werkzeug, das den Marker nicht kennt, liest sich so eine Diskette als gesund:** 880 K, eine Datei, Bitmap stimmig. Der Befund wäre falsch, und zwar in genau der Richtung, die dieses Projekt ausschließt — „keine stille Veränderung" gilt auch für den *Bericht*. Im Baum findet sich dazu **nichts** (gemessen). **Klar umrissener Prüfauftrag:** `dummy.bad` erkennen, benennen, und die belegten Bereiche als **schadensverdächtig** statt als belegt führen. Der Marker ist dafür gut geeignet — benannt, geschützt, an Spurgrenzen ausgerichtet. Kennzahl: keine der vier direkt, aber es ist ein **Falschbefund**, und die stehen in diesem Baum über Kennzahlen |

docs/STAND.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Stand: 2026-09-06
4141

4242
## Was offen ist
4343

44-
`docs/OPEN_ITEMS.md` führt **7564** Zeilen in **82** Abschnitten.
44+
`docs/OPEN_ITEMS.md` führt **7566** Zeilen in **82** Abschnitten.
4545

4646
**erledigt** (1):
4747
- GCR-1 — der 6-and-2-Dekoder steht, 560 von 560 Sektoren belegt (MF-715)

include/uft/fs/uft_fat12.h

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -995,13 +995,24 @@ time_t uft_fat_to_unix_time(uint16_t fat_time, uint16_t fat_date);
995995
*/
996996
void uft_fat_from_unix_time(time_t unix_time, uint16_t *fat_time, uint16_t *fat_date);
997997

998-
/**
999-
* @brief Format entry as string
1000-
* @param entry Directory entry
1001-
* @param buffer Output buffer (at least 80 bytes)
1002-
* @return buffer
1003-
*/
1004-
char *uft_fat_entry_to_string(const uft_fat_entry_t *entry, char *buffer);
998+
/* MF-945: hier stand
999+
*
1000+
* char *uft_fat_entry_to_string(const uft_fat_entry_t *entry,
1001+
* char *buffer);
1002+
*
1003+
* Deklariert, NIE umgesetzt, und im ganzen Baum nirgends genannt —
1004+
* gemessen ueber `git ls-files`. Sie war die EINZIGE der 56 Zusagen
1005+
* dieses Headers ohne Rumpf; die uebrigen 55 gibt es.
1006+
*
1007+
* Entfernt statt umgesetzt, nach dem Vorbild von MF-366
1008+
* (`uft_audit_trail.h`, `uft_forensic_report.h`): eine Funktion, die
1009+
* niemand ruft, zu bauen hiesse, eine Zusage zu erfuellen, die niemand
1010+
* gestellt hat.
1011+
*
1012+
* Ersatz benannt (MF-699 verlangt das vor jeder Loeschung): es braucht
1013+
* keinen. `uft_fat_entry_t` traegt Name, Groesse, Attribute und Zeit als
1014+
* eigene Felder; wer anzeigt, formatiert daraus selbst. Eine zweite
1015+
* Darstellung im Header waere eine zweite Wahrheit ueber dasselbe. */
10051016

10061017
/**
10071018
* @brief Format attributes as string

0 commit comments

Comments
 (0)