Tachibana

Dokumentation › SEDORIC

SEDORIC-Diskettenformat & Werkzeuge

Primäre Referenz: das SEDORIC 3.0-Handbuch (sedna3_0.pdf), abgeglichen mit „SEDORIC 3.0 à NU“ von A. Chéramy und den Werkzeugen des SCUMM-Oric- / scoop-oric-Projekts. Nichts ist erfunden: Die folgenden Offsets sind die des Handbuchs, byte-exakt gegen den Deskriptor-Dump verifiziert, den das Handbuch selbst als Beispiel angibt.

1. MFM_DISK-Container

256-Byte-Header: "MFM_DISK" + sides (u32 LE) + tracks (u32 LE) + geometry (u32 LE). Dann ein Track-Block von 6400 B pro (Seite, Track), in SIDE-MAJOR-Reihenfolge: alle Tracks von Seite 0, dann alle von Seite 1 (Block = side * tracks + track).

Jeder Track-Block: Anfangs-Gap 60×$4E, dann pro Sektor 12×$00 | A1 A1 A1 FE [trk side sec size] CRC | 22×$4E | 12×$00 | A1 A1 A1 FB [256 data] CRC | 38×$4E, $4E-Auffüllung bis 6400 B. CRC-16/CCITT (poly $1021, init $FFFF) über die 4 Markerbytes + die Daten.

Ein RAW-Image (256-Byte-Sektoren aneinandergereiht, dieselbe Side-Major-Reihenfolge, ohne Rahmung) wird von sedoric-info akzeptiert und von oric1-emu --disk-create / tools/sedoric_inject.py erzeugt. tools/dsk_raw2mfm.py konvertiert RAW → MFM_DISK.

2. Systemsektoren (Track 20)

SektorRolleSchlüsselfelder
s1 SystemDiskettenname + Autoexec+9..+29 Diskettenname (21 B) · +0x1E..+0x59 INIST (60 B: ASCII-Boot-Befehle, getrennt durch :, abgeschlossen mit #00)
s2 VTOC/BitmapZähler+2,+3 freie Sektoren (LE) · +4,+5 Dateizahl (LE)
s4 DirectoryKatalog+0,+1 Link zum nächsten Dir-Sektor (0=Ende) · +2 High-Water-Mark · 16-Byte-Einträge ab +16

Directory-Eintrag (16 B): name[9] ext[3] track sector nsec status (V4 gültige Datei = $40; Bit 7 = gelöscht).

Hinweis (auf Master-Disketten beobachtet): Der VTOC-free/files-Zähler kann eine 80-Track-Vorlage sein, die auf ein kleineres physisches Image gestempelt wurde — eine Vorlage, kein neu berechneter Zustand. sedoric-info meldet daher sowohl den VTOC-Zähler als auch die Zahl der tatsächlich im Katalog durchlaufenen Dateien.

3. Dateideskriptor-Sektor

Vom Directory-Eintrag angezeigt (track,sector). Echter Dump aus dem Handbuch (Deskriptor der BANQUE-#7-Systemdatei, S.16):

 0 1 2 3 4 5 6 7 8 9 A B C D E F
00 00 FF 40 00 C4 FF C7 00 00 04 00 05 0B 05 0C 05 0D 05 0E 00 00
OffsetFeldBeispiel
+0,+1Link zum nächsten Deskriptor (00 00 = keiner)00 00
+2Erst-Deskriptor-MarkerFF
+3Typ: b0=AUTO, b6=Datenblock, b7=BASIC → $40=ML, $41=AUTO ML40
+4,+5Ladeadresse (LE)00 C4 = $C400
+6,+7Endadresse (LE)FF C7 = $C7FF
+8,+9Ausführungsadresse, falls AUTO (LE)00 00
+0xA,+0xBAnzahl der Datensektoren (LE)04 00 = 4
+0xC..Datensektorkarte (track,sector)×n, abgeschlossen 00 0005 0B 05 0C 05 0D 05 0E 00 00

Dieser Dump korrigiert die alte tap2sedoric-Implementierung, die +3=0 ließ (kein Typ) und die Sektorzahl bei +9,+10 in Big-Endian schrieb (überlappend mit der Ausführungsadresse). Korrigiert seit v1.64.0.

Verkettete Deskriptoren (Dateien > 122 Sektoren) — validiert

Ein Deskriptor-Sektor enthält nur einen Teil der Karte: Der 1. Deskriptor trägt den Header (12 B) und dann die Karte ab +0x0C (122 Paare max, 0x0C..0xFE); jeder folgende Deskriptor trägt nur den Link +0,+1 und dann die Karte ab +0x02 (127 Paare max). Der Link +0,+1 zeigt auf den nächsten Deskriptor (00 00 = letzter). +0xA,+0xB (1. Deskriptor) = Gesamtzahl der Datensektoren. In situ validiert: eine Datei mit 150 Sektoren (2 Deskriptoren) vollständig von LOAD geladen. tap2sedoric und sedoric_inject.py verketten seit v1.65.0.

4. Werkzeuge

WerkzeugRolle
tap2sedoric <in.tap> -o out.dsk -b base.dsk [-n NAME.EXT] [-a] [-e EXEC] [-i "INIST"]injiziert eine CSAVE-.tap in eine MFM-Sedoric-Diskette (Datei + konformer Deskriptor + Dir-Eintrag + VTOC; -a/-e AUTO, -i Boot-Autoexec)
sedoric-info <disk.dsk> [--check FREE:FILES]inspiziert VTOC, Diskettenname, INIST, Katalog und decodierte Deskriptoren; --check = Regressionswächter für die Zähler
tools/sedoric_inject.py …RAW-Injektion (direkte Offsets)
tools/dsk_raw2mfm.py <raw> <out.dsk> …RAW → MFM_DISK (Side-Major-Blöcke)

Typische RAW-Kette: oric1-emu --disk-create base.raw (dann INIT beim Booten für eine echte VTOC) → sedoric_inject.pydsk_raw2mfm.pyoric1-emu --disk-rom microdis.rom -d.

5. Multi-Datei-Injektion (Grenze aufgehoben)

Historisch allozierten sowohl tap2sedoric als auch sedoric_inject.py stets ab Track 21 Sektor 1, ohne die bereits belegten Sektoren zu berücksichtigen: Eine zweite Injektion auf dieselbe Diskette überschrieb die erste.

Seit v1.64.0 durchlaufen beide Werkzeuge den Katalog (vollständige Kette) und die Sektorkarten der vorhandenen Deskriptoren — einschließlich der verketteten Katalogsektoren selbst — um belegte Sektoren vor dem Allozieren zu markieren. Verifiziert durch make test-sedoric-tools.

Directory-Sektor-Verkettung (implementiert)

Wenn der aktuelle Katalogsektor voll ist (15 Einträge), durchlaufen die Werkzeuge die Kette über den Link +0,+1; ist die gesamte Kette voll, allozieren sie einen freien Sektor, initialisieren ihn als leeren Katalog und verketten ihn. Da Katalogsektoren per Track/Sektor-Link lokalisiert werden, kann ein verketteter Katalog auf jedem freien Sektor liegen. In situ validiert.

6. Eine Maschinencode-Datei unter Sedoric ausführen (in situ validiertes Rezept)

Laden/Ausführen im Emulator verifiziert (Bare-Boot + LOAD). Angetroffene Fallstricke und gelöst:

Befehl / FallErgebnis
PROBE tippen (nackter Name) bei Ready?SYNTAX ERROR — ein nackter Name startet nur ein AUTO-BASIC
LOADM"PROBE"?TYPE MISMATCHLOADM ist der Kassetten-ROM-Befehl
CLOAD"PROBE"kein Fehler, aber lädt nichts (BASIC-Dateien)
LOAD"PROBE" bei .BIN?FILE NOT FOUND.COM ist die Standarderweiterung
LOAD"PROBE",J bei AUTOBREAK ON BYTE #5000,J kollidiert mit der AUTO-Flag
LOAD"PROBE" bei .COM AUTO (Typ $41)lädt UND führt aus

Rezept: als .COM AUTO injizieren (tap2sedoric … -n NAME.COM -a -e EXEC), dann bei Ready: LOAD"NAME". Der Sedoric-Befehl ist LOAD (erkennt BASIC vs. binär automatisch über das Typbyte +3), mit Optionen ,A (Adresse) und ,J (Sprung).

Nackter bootfähiger Sedoric-Master (deterministisch)

Um eine selbstgemachte .COM zu validieren, braucht man eine Diskette, die ohne konkurrierende Anwendung nach Ready bootet. Robuste, timing-freie Methode:

tools/sedoric_mkbare.py disks/SEDO40u.DSK bare.dsk        # neutralisiert die INIST
tools/sedoric_mkbare.py disks/SEDO40u.DSK auto.dsk 'LOAD"PROBE"'   # oder Auto-Start

Es neutralisiert (oder ersetzt) die INIST (Track 20 Sektor 1, +0x1E..+0x59, MFM-Sektor-CRC neu berechnet; RAW ebenfalls behandelt) → die Diskette fällt auf ein nacktes SEDORIC V4.0 / Ready zurück, bleibt aber bootfähig.

Eine Datei aus Maschinencode laden (in situ validiertes Rezept)

Aus einem laufenden ML-Programm (von LOAD gestartet) ist das Sedoric-RAM-Overlay nicht gemappt: die DOS-Routinen direkt aufzurufen ($DB2D Suche, $E0EA Lesen) stürzt ab. Der robuste Weg führt über den „!“-Vektor $0467 (im niedrigen RAM, immer gemappt), der zum Overlay umschaltet, den SEDORIC-Interpreter ($D3AE) auf der von TXTPTR ($00E9/$00EA) angezeigten Zeile ausführt und dann zurückschaltet und RTS macht.

        LDA #<CMD : STA $E9        ; TXTPTR = Adresse der Befehlszeile
        LDA #>CMD : STA $EA
        JSR $0467                  ; "!"-Vektor: fuehrt den Befehl aus (Overlay geregelt)
        ; ... Datei geladen; normale Fortsetzung ...
        RTS
CMD:    .byte "LOAD\"SCDATA\"", 0  ; SEDORIC-Zeile mit $00 abgeschlossen

Fallstrick: Die Zeile muss mit $00 abgeschlossen werden, niemals mit CR ($0D). Mit CR schließt der $D3AE-Interpreter nicht ab und macht kein RTS. TXTPTR zeigt auf das erste Zeichen (das L).

Sedoric-RAM-Overlay ↔ BASIC-ROM-Umschaltung (validiert)

Aus einem von LOAD gestarteten ML-Programm ist das BASIC-ROM bei $C000-$FFFF gemappt: Systemvariablen und Routinen liegen im Overlayvor jedem $C000+-Zugriff umschalten. Am einfachsten: JSR $0477 (Sedoric-Stub im niedrigen RAM) — ein ROM↔Overlay-Toggle, der Laufwerk/Seite/IRQ über den $04FB-Shadow bewahrt:

PHP:PHA:SEI : LDA $04FB : EOR #$02 : STA $04FB : STA $0314 : PLA:PLP:RTS

$0314-Werte: Bit 1 (ROMDIS, $02) = 0 → RAM-Overlay $C000-$DFFF, = 1 → BASIC-ROM; Bit 7 (EPROM, $80) = 1 → RAM-Overlay $E000-$FFFF. Da $0314 nur schreibbar ist, über den $04FB-Shadow oder $0477 gehen.

Eine Datei sektorweise an einem Offset lesen (wahlfreier Zugriff) — validiert

Um N Bytes an einem Offset zu lesen, ohne die ganze Datei zu laden. Overlay ON ($0477) erforderlich.

  1. BUFNOM gefüllt + JSR $DB2D (SEARCH) → X = POSNMX, Katalogsektor in BUF3.
  2. LDA $C30C,X : LDY $C30D,X : JSR $DA5DDeskriptor in BUF1 ($C100) geladen.
  3. BUF1-Layout: $C100/01 Nächst-Deskriptor-Link · $C102=FF · $C103 Typ · $C104-05 load · $C106-07 end · $C108-09 exec · $C10A-0B Sektorzahl · Karte ab $C10C.
  4. sect_index = off/256, byte_in_sect = off & 255. DRIVE $C000, TRACK $C001, SECTOR $C002, RWBUF $C003/$C004 setzen.
  5. JSR $DA73 (XPRSEC). N Bytes ab Puffer + byte_in_sect kopieren.

XRWTS/XPRSEC-Schnittstelle (Handbuch, byte-exakt): DRIVE $C000, TRACK $C001 (b7=Seite B), SECTOR $C002, RWBUF $C003/$C004. $C009 = DRVDEF, $C00A = DRVSYS.

Reproduziert aus docs/SEDORIC.md (maßgebliche, aktuelle Version auf GitHub, mit den vollständigen Rezepten).

← Dokumentation · LOCI →