Tachibana

Documentation › SEDORIC

Format disque SEDORIC & outillage

Référence primaire : manuel SEDORIC 3.0 (sedna3_0.pdf), recoupé avec A. Chéramy « SEDORIC 3.0 à NU » et l'outillage du projet SCUMM-Oric / scoop-oric. Rien n'est inventé : les offsets ci-dessous sont ceux du manuel, vérifiés byte-exact contre le dump de descripteur donné en exemple par le manuel lui-même.

1. Conteneur MFM_DISK

En-tête 256 o : "MFM_DISK" + sides (u32 LE) + tracks (u32 LE) + geometry (u32 LE). Puis un bloc de piste de 6400 o par (face, piste), dans l'ordre SIDE-MAJOR : toutes les pistes de la face 0, puis toutes celles de la face 1 (bloc = side * tracks + track).

Chaque bloc de piste : gap initial 60×$4E, puis par secteur 12×$00 | A1 A1 A1 FE [trk side sec size] CRC | 22×$4E | 12×$00 | A1 A1 A1 FB [256 data] CRC | 38×$4E, padding $4E jusqu'à 6400 o. CRC-16/CCITT (poly $1021, init $FFFF) sur les 4 octets de marque + les données.

Une image RAW (secteurs 256 o concaténés, même ordre side-major, sans cadrage) est acceptée par sedoric-info et produite par oric1-emu --disk-create / tools/sedoric_inject.py. tools/dsk_raw2mfm.py convertit RAW → MFM_DISK.

2. Secteurs système (piste 20)

SecteurRôleChamps clés
s1 Systèmenom disque + autoexec+9..+29 nom disque (21 o) · +0x1E..+0x59 INIST (60 o : commandes ASCII de boot, séparées par :, terminées par #00)
s2 VTOC/bitmapcompteurs+2,+3 secteurs libres (LE) · +4,+5 nb de fichiers (LE)
s4 Directorycatalogue+0,+1 lien vers secteur dir suivant (0=fin) · +2 high-water mark · entrées de 16 o à partir de +16

Entrée directory (16 o) : name[9] ext[3] track sector nsec status (V4 fichier valide = $40 ; bit 7 = supprimé).

Note (constatée sur disques Master) : le compteur free/files de la VTOC peut être un template 80 pistes plaqué sur une image physique plus petite — c'est un modèle, pas un état recalculé. sedoric-info rapporte donc à la fois le compteur VTOC et le nombre de fichiers réellement parcourus dans le catalogue.

3. Secteur descripteur de fichier

Pointé par l'entrée directory (track,sector). Dump réel du manuel (descripteur du fichier système BANQUE n°7, p.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
OffsetChampExemple
+0,+1lien vers descripteur suivant (00 00 = aucun)00 00
+2marqueur premier descripteurFF
+3type : b0=AUTO, b6=bloc data, b7=BASIC → $40=ML, $41=AUTO ML40
+4,+5adresse de chargement (LE)00 C4 = $C400
+6,+7adresse de fin (LE)FF C7 = $C7FF
+8,+9adresse d'exécution si AUTO (LE)00 00
+0xA,+0xBnombre de secteurs data (LE)04 00 = 4
+0xC..carte des secteurs data (track,sector)×n, terminée 00 0005 0B 05 0C 05 0D 05 0E 00 00

Ce dump corrige l'ancienne implémentation de tap2sedoric qui laissait +3=0 (type absent) et écrivait le nombre de secteurs en +9,+10 big-endian (chevauchant l'adresse d'exécution). Corrigé depuis v1.64.0.

Descripteurs chaînés (fichiers > 122 secteurs) — validé

Un secteur descripteur ne contient qu'une partie de la carte : le 1ᵉʳ descripteur porte l'en-tête (12 o) puis la carte dès +0x0C (122 paires max, 0x0C..0xFE) ; chaque descripteur suivant ne porte que le lien +0,+1 puis la carte dès +0x02 (127 paires max). Le lien +0,+1 pointe le descripteur suivant (00 00 = dernier). +0xA,+0xB (1ᵉʳ descripteur) = nombre total de secteurs data. Validé in-situ : fichier de 150 secteurs (2 descripteurs) chargé intégralement par LOAD. tap2sedoric et sedoric_inject.py chaînent depuis v1.65.0.

4. Outils

OutilRôle
tap2sedoric <in.tap> -o out.dsk -b base.dsk [-n NAME.EXT] [-a] [-e EXEC] [-i "INIST"]injecte un .tap CSAVE dans un disque MFM Sedoric (fichier + descripteur conforme + entrée dir + VTOC ; -a/-e AUTO, -i autoexec de boot)
sedoric-info <disk.dsk> [--check FREE:FILES]inspecte VTOC, nom disque, INIST, catalogue et descripteurs décodés ; --check = garde de régression sur les compteurs
tools/sedoric_inject.py …injection en RAW (offsets directs)
tools/dsk_raw2mfm.py <raw> <out.dsk> …RAW → MFM_DISK (blocs side-major)

Chaîne RAW type : oric1-emu --disk-create base.raw (puis INIT au boot pour une vraie VTOC) → sedoric_inject.pydsk_raw2mfm.pyoric1-emu --disk-rom microdis.rom -d.

5. Injection multi-fichiers (limite levée)

Historiquement, tap2sedoric et sedoric_inject.py allouaient toujours à partir de la piste 21 secteur 1 sans consulter les secteurs déjà occupés : une deuxième injection sur le même disque écrasait la première.

Depuis v1.64.0, les deux outils parcourent le catalogue (chaîne complète) et les cartes de secteurs des descripteurs existants — y compris les secteurs catalogue chaînés eux-mêmes — pour marquer les secteurs occupés avant d'allouer. Vérifié par make test-sedoric-tools.

Chaînage de secteurs directory (implémenté)

Quand le secteur de catalogue courant est plein (15 entrées), les outils parcourent la chaîne via le lien +0,+1 ; si toute la chaîne est pleine, ils allouent un secteur libre, l'initialisent en catalogue vierge et l'y chaînent. Les secteurs catalogue étant localisés par lien piste/secteur, un catalogue chaîné peut résider sur n'importe quel secteur libre. Validé in-situ.

6. Exécuter un fichier ML sous Sedoric (recette validée in-situ)

Chargement/exécution vérifiés dans l'émulateur (boot bare + LOAD). Pièges rencontrés et tranchés :

Commande / casRésultat
taper PROBE (nom nu) au Ready?SYNTAX ERROR — le nom nu ne lance qu'un BASIC AUTO
LOADM"PROBE"?TYPE MISMATCHLOADM est la commande ROM cassette
CLOAD"PROBE"pas d'erreur mais ne charge rien (fichiers BASIC)
LOAD"PROBE" sur .BIN?FILE NOT FOUND.COM est l'extension par défaut
LOAD"PROBE",J sur AUTOBREAK ON BYTE #5000,J entre en conflit avec le flag AUTO
LOAD"PROBE" sur .COM AUTO (type $41)charge ET exécute

Recette : injecter en .COM AUTO (tap2sedoric … -n NAME.COM -a -e EXEC), puis au Ready : LOAD"NAME". La commande Sedoric est LOAD (auto-détecte BASIC vs binaire via l'octet de type +3), avec options ,A (adresse) et ,J (jump).

Master Sedoric « nu » bootable (déterministe)

Pour valider un .COM maison, il faut un disque qui boote au Ready sans application concurrente. Méthode robuste, sans timing :

tools/sedoric_mkbare.py disks/SEDO40u.DSK bare.dsk        # neutralise l'INIST
tools/sedoric_mkbare.py disks/SEDO40u.DSK auto.dsk 'LOAD"PROBE"'   # ou autolance

Il neutralise (ou remplace) l'INIST (piste 20 secteur 1, +0x1E..+0x59, CRC du secteur MFM refait ; RAW aussi géré) → le disque tombe en SEDORIC V4.0 / Ready nu tout en restant bootable.

Charger un fichier depuis du code machine (recette validée in-situ)

Depuis un programme ML en cours d'exécution (lancé par LOAD), l'overlay RAM Sedoric n'est pas mappé : appeler directement les routines DOS ($DB2D recherche, $E0EA lecture) plante. La voie robuste passe par le vecteur « ! » $0467 (en RAM basse, toujours mappé), qui bascule sur l'overlay, exécute l'interpréteur SEDORIC ($D3AE) sur la ligne pointée par TXTPTR ($00E9/$00EA), puis rebascule et fait RTS.

        LDA #<CMD : STA $E9        ; TXTPTR = adresse de la ligne de commande
        LDA #>CMD : STA $EA
        JSR $0467                  ; vecteur "!" : execute la commande (overlay gere)
        ; ... fichier charge ; poursuite normale ...
        RTS
CMD:    .byte "LOAD\"SCDATA\"", 0  ; ligne SEDORIC terminee par $00

Piège : la ligne doit être terminée par $00, jamais par CR ($0D). Avec CR l'interpréteur $D3AE n'aboutit pas et ne fait pas RTS. TXTPTR pointe sur le premier caractère (le L).

Bascule overlay RAM Sedoric ↔ ROM BASIC (validé)

Depuis un ML lancé par LOAD, la ROM BASIC est mappée en $C000-$FFFF : variables système et routines sont dans l'overlay → basculer avant tout accès $C000+. Le plus simple : JSR $0477 (stub Sedoric en RAM basse) — un toggle ROM↔overlay qui préserve lecteur/face/IRQ via le shadow $04FB :

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

Valeurs $0314 : bit 1 (ROMDIS, $02) = 0 → overlay RAM $C000-$DFFF, = 1 → ROM BASIC ; bit 7 (EPROM, $80) = 1 → overlay RAM $E000-$FFFF. $0314 étant en écriture seule, passer par le shadow $04FB ou $0477.

Lire un fichier par secteur à un offset (accès aléatoire) — validé

Pour lire N octets à un offset sans charger tout le fichier. Overlay ON ($0477) obligatoire.

  1. BUFNOM rempli + JSR $DB2D (SEARCH) → X = POSNMX, secteur catalogue en BUF3.
  2. LDA $C30C,X : LDY $C30D,X : JSR $DA5Ddescripteur chargé dans BUF1 ($C100).
  3. Format BUF1 : $C100/01 lien descr. suivant · $C102=FF · $C103 type · $C104-05 load · $C106-07 end · $C108-09 exec · $C10A-0B nb secteurs · carte dès $C10C.
  4. sect_index = off/256, byte_in_sect = off & 255. Poser DRIVE $C000, PISTE $C001, SECTEUR $C002, RWBUF $C003/$C004.
  5. JSR $DA73 (XPRSEC). Copier N octets depuis tampon + byte_in_sect.

Interface XRWTS/XPRSEC (manuel, byte-exact) : DRIVE $C000, PISTE $C001 (b7=face B), SECTEUR $C002, RWBUF $C003/$C004. $C009 = DRVDEF, $C00A = DRVSYS.

Reproduit depuis docs/SEDORIC.md (version de référence à jour sur GitHub, avec les recettes complètes).

← Documentation · LOCI →