ProDOS MLI Quit


Dernière mise à jour: mardi 19/09/2006 (correction KEY_ESC par KEY_TAB sur la page html et le .dsk).


Introduction

Dans le cadre de mon projet FASTDSK, je vais devoir écrire une routine permettant de sélectionner un répertoire sur une unité ProDOS disponible (pour la sauvegarde des disks images .dsk), sachant qu'il faut pouvoir naviguer d'un volume ProDOS à un autre facilement. Alors que je réfléchissais à la solution à mettre en oeuvre, je me suis tout naturellement demandé s'il n'existait pas déjà un programme répondant à ces caractéristiques et qui serait bien écrit.

J'ai alors tout de suite pensé à la routine qu'appelle ProDOS quand un appel est fait à MLI Quit.

Je ne parle bien sur pas de la vieille routine des premières versions de ProDOS où il fallait taper manuellement les noms de volume/chemin (prefix) et de programme (next application) qu'on l'on voulait lancer en sortant de MLI et qui balançait un message d'insulte (erreur) à la moindre faute de frappe quand on ne connaissait pas par coeur le nom correct à saisir:


Old MLI Quit
Old MLI Quit
Old MLI Quit

Il a existé et existe tout un tas de sélecteurs qui sont apparus à fur et à mesure soit pour combler les lacunes des 1ère versions de ProDOS (comme le très célèbre BBB, abrégé de Bird's Better Bye d'un des auteurs fétiches des Beagle Bros, à savoir Alan Bird ou encore BYE80, la version de BBB fonctionnant en 80 colonnes mise au point par Dave Ely) ou pour des améliorations de selecteur au goût de l'auteur (Super Selector, Squirt, ...)
La dernière en date est signée David Empson et s'intitule QUITTER.SYSTEM. Comme vous l'aurez deviné, il s'agit d'un SYS externe qui n'est pas directement intégré dans ProDOS. Quelques mots explicatifs de son auteur:

BBB runs in 40-column mode and the ProDOS-8 built-in
one looks quite different (from memory - I haven't seen it for ages).
I made a few improvements to Birds Better Bye (such as making it display
two columns of pathnames, and a "rescan" key). I distributed as part of
my freeware application Quitter.System, which gives additional features
such as booting directly from a specified slot and reconnecting GS/OS if
you have launched a P8 program selector.
Alan Bird's quit handler, which was included with AppleWorks 3.0, and which
I improved and used in the QUITTER.SYSTEM program which I co-wrote with a friend.


Tous ces sélecteurs sont sans aucun doute très biens, mais je préfère le standard et s'il y en a un qui me va bien c'est celui inclus dans la dernière release de ProDOS 8 (la 2.0.3) et qui permet de choisir facilement en mode 80 colonnes l'unité (avec la touche TAB), et naviguer dans les répertoires et sous répertoires à la recherche d'un SYS à lancer.

Exemple d'un 1er écran correspondant au volume d'un disque dur /HD1:

MLI Quit

Entrée dans un sous répertoire à la recherche d'un SYS (il y en a 2 sur le cliché -ED.IT et EXER- avec tout un tas de sous répertoires identifiés par l'icone de folder):

MLI Quit

Quand on va dans un répertoire sans sous répertoire ni SYS, on est bon pour appuyer sur ESC et revenir au niveau antérieur (ou changer de volume ProDOS):

MLI Quit

Ok j'ai une routine sympa à portée de main.
Malheureusement après un tour d'horizon sur le net, il n'existe pas à ma connaissance un source complet de cette version en libre accès. Grrrr! Pas de chance. Surtout qu'il me faudrait la modifier pour l'adapter à mes besoins (pas besoin de SYS, afficher <select this directory> quand il n'y a aucun sous répertoire, etc...)


Récupération

Il a donc fallu que je mette les mains dans le camboui pour extraire la chose.
Comment s'y prendre?
Voilà comment j'ai fait...

Je sais déjà que la routine est incluse dans le fichier ProDOS mais j'ignore où.
En effet l'adresse d'implantation dans ce fichier varie presque à chaque version de ProDOS.
Je sais également que quelque soit la version, le code est exécuté à partir de l'adresse $1000 quand un MLI Quit est rencontré.

Je vais donc mettre un point d'arrêt sous AppleWin pour voir un peu la tête du code.
Je lance une disquette avec le bon ProDOS et un BASIC.SYSTEM.
Quand il me rend la main sous BASIC.SYSTEM, je passe en mode débugger et saisis "BP 1000" suivi d'un "G".
Dès qu'il revient sur l'écran normal, je tape BYE et attend de voir ce qu'il me présente comme résultat.
Il s'arrête tout d'abord sur le code qui recopie la routine en $1000:

Search with Debug

Je pourrais en savoir plus dès ce moment là, mais à quoi bon analyser la routine quand un second "G" m'amène directement sur le début du code:

Search with Debug


Je note les 1er octets de la routine:  D8AD82C09CF203.

Pour savoir où se trouve ce code dans le fichier ProDOS, je vais à présent utiliser un programme utilitaire sympa appelé LIST version 2.5.
Il permet non seulement de visualiser le contenu de plein de fichiers aux formats différents mais aussi de faire des recherches sur des caractères ou des séquences hexa.
Je l'ai mis sur la disquette jointe. Son auteur est Stowe Keller et à l'époque c'était un shareware.

Using List

Je sélectionne le volume /MLIQUIT, puis le fichier ProDOS dont il m'affiche le contenu:

Using List

Je tape open-apple F et sélectionne Hex quand il me demande le type de "Find" que je veux.
Je tape alors la séquence d'octets de tout à l'heure et lance la recherche en validant par return:

Using List

Et hop, il m'affiche alors l'offset où se trouve ce code, à savoir $3D00.

Using List

Comme le fichier ProDOS commence en $2000, ma routine convoitée se trouve donc en $2000+$3D00=$5D00.
Il n'y a plus qu'à sauvegarder la routine d'origine en tapant:
BLOAD PRODOS,TSYS,A$2000
BSAVE MLIQUIT.ORIG,A$5D00,L$0300


Reconstruction

Maintenant, on passe au classique boot de Merlin 8, à l'exécution de Sourceror et au désassemblage de la routine.
Une fois que c'est ok, le plus dur reste à faire: comprendre le code et en faire un source commenté intelligible.
Le résultat de mon travail de retro-engineering se trouve sur le disk image suivant. L'assemblage du source donne un autre BIN appelé MLIQUIT que j'ai comparé avec MLIQUIT.ORIG grâce à l'outil COPY 2+ 9.1 (option Kompare files).
Le résultat est identique.


Floppy
ProDOS
Download MLI Quit Source code from ProDOS 8 2.0.3 (gzipped)

Contenu de la disquette MLI_Quit.dsk:
PRODOS --> /MLIQUITT
 PRODOS          | SYS | A$0000 | L$42E8 | B$0023
 RAM.DRV.SYSTEM  | SYS | A$2000 | L$04B9 | B$0004
 BASIC.SYSTEM    | SYS | A$2000 | L$2800 | B$0015
 MLIQUIT.ORIG    | BIN | A$5D00 | L$0300 | B$0003
 MLIQUIT.S       | TXT | A$0000 | L$4F9C | B$0029
 MLIQUIT         | BIN | A$1000 | L$0303 | B$0003
 LIST            (DIR)
     LIST.LAUNCH     | SYS | A$2000 | L$02DF | B$0003
     LIST.SYSTEM     | SYS | A$2000 | L$9135 | B$004A
     LIST.DESCR      | AWP | A$C003 | L$A713 | B$0055
     LIST.CONFIG     | BIN | A$0000 | L$00F2 | B$0001.



Quelques explications


Organisation de la mémoire:

$0074-$00F2 : type des 127 objets possible
$0280-$02C0 : len+/pathname complet/00
$1000-$1302 : mli quit (cf source plus bas)
$1400-$1BF0 : buffer stockage des 127 noms d'objets possible (127 * 16 <-len+nom objet)
$1C00-$1FFF : buffer $400 octets pour open
$2000-$xxxx : buffer read (volume ou dir ou sys)


Fonctionnement simplifié:

Le programme se base sur la liste des unités actives.
Il commence soit par la dernière unité utilisée (s'il y en a une) soit
par la dernière de la liste.
A partir de cette référence d'unité, il fait un MLI Online pour obtenir
le nom de ce volume et ensuite il ne travaille plus que sur des noms.
S'en suit un MLI open et un MLI read pour accéder au catalog du volume ou du dir.
Puis il lit le catalog objet par objet (descriptif), vérifie que cet objet est ok et
l'ajoute le cas échéant dans la liste des noms.
En faisant un ESC ou un RETURN sur un répertoire, le programme repart sur le MLI open
après avoir allonger ou raccourci le nom selon la touche employée.


Explication rapide des variables utilisées pour l'affichage:

Quand une unité a été sélectionnée par le programme, on se retrouve au niveau de la racine
(root) du volume. La variable DIR_LEVEL indique le niveau de profondeur, c'est à dire
le nombre de répertoires valides à partir de cette racine au fur et à mesure de la navigation
par l'utilisateur dans ce volume.
Quand l'unité n'est pas encore validée, on a DIR_LEVEL = 0.
Au niveau de la racine, on a DIR_LEVEL = 1.
Si l'utilisateur tape RETURN sur un nom de DIR, alors on augmente d'un niveau.
S'il fait ESC, on diminue d'un niveau hiérarchique (sauf si on est déja à la racine).
Exemple pour un volume /VOLUME/ avec 2 niveaux de répertoires imbriqués DIR1 et DIR2,
on aura DIR_LEVEL=3 si l'utilisateur a fait 2 fois RETURN (sur DIR1 d'abord puis
DIR2).
/VOLUME/DIR1/DIR2/
   1     2    3    <- DIR_LEVEL
Définition: DIR_LEVEL[0,1=root,nombre de sous-répertoires sélectionnés par le user]


Exemple de contenu d'un répertoire après filtrage par le programme qui ne garde
que les répertoires (DIR) et les fichiers système (SYS):

RANK   FILENAME FILETYPE

01     NAME01   DIR
02     NAME02   DIR
03     NAME03   SYS
04     NAME04   DIR
05     NAME05   SYS
06     NAME06   SYS
07     NAME07   DIR
08     NAME08   DIR
09     NAME09   DIR
10     NAME10   DIR
11     NAME11   DIR
12     NAME12   DIR
13     NAME13   DIR
14     NAME14   DIR
15     NAME15   DIR
16     NAME16   SYS
17     NAME17   SYS
18     NAME18   SYS
19     NAME19   SYS
20     NAME20   DIR
21     NAME21   DIR
22     NAME22   SYS

Il y a 22 noms sélectionnables.
La variable CPT_NAME est un compteur sur le nombre d'objets (=noms).
Ici CPT_NAME = 22.
S'il n'y avait eu aucun DIR et SYS dans le répertoire courant, on aurait eu CPT_NAME = 0
et il n'y aurait pas d'affichage.
Il ne faut pas confondre le nombre total d'objets d'un répertoire et cette
liste de noms qui a été filtrée. Dans la suite de l'explication, quand je parle de liste
de noms, je me réfère uniquement à la liste filtrée (donc des noms que l'on veut
afficher).
Définition: CPT_NAME [0,nombre de noms avec max=127]


L'écran texte normal de l'Apple II permet d'avoir jusqu'à 24 lignes.
Ces lignes sont numérotées de 00 à 23.
La variable CV indique la valeur de l'ordonnée.
On réserve 2 lignes en haut et 2 en bas pour des affichages différents.
Donc on ne peut afficher que 20 noms à la fois sur l'écran de CV = 2 à CV = 21.
CV correspond à l'endroit où se trouve le nom en video-inversé en cours de
sélection.
Définition: CV [2,21] pour l'affichage de la liste uniquement!!


L'utilisateur peut choisir d'aller dans un sous répertoire ou sélectionner un SYS
pour le lancer. Il va donc faire défiler la liste des noms de 1 en 1 en utilisant les
touches HAUT et BAS.
Pour que l'on sache toujours sur quel nom il se trouve, on introduit la notion
de pointeur sur la liste des noms. Ce pointeur correspond au nom courant sur lequel
se trouve l'utilisateur. La variable utilisée est PTR_LIST.
Le 1er indice de cette variable est 0.
Quand PTR_LIST pointe sur NAME01, on a PTR_LIST = 0.
Pour NAME02, PTR_LIST = 1, etc...
Le nom correspondant à PTR_LIST apparait en video-inversée sur l'écran.
Définition: PTR_LIST [0,CPT_NAME-1 avec max=126]


Dans la mesure où la liste peut compter jusqu'à 127 noms et que l'on ne peut
en avoir que 20 à l'écran, il faut bien à un moment où un autre que l'on
sache à partir du combien t-ième l'affichage écran doit commencer.
C'est le rôle d'un autre pointeur: PTR_SCRN. (SCRN pour screen=écran en anglais).
Il se réfère toujours à la liste de noms et pointe sur le 1er nom
que l'on trouve en tête d'affichage sur l'écran.
Avec notre exemple, PTR_SCRN vaudra 0 tant que l'utilisateur
ne descendra pas avec la touche BAS au delà de NAME20.
S'il descend encore (PTR_LIST = 20 pointant sur NAME21),
alors l'affichage écran devra se faire à partir de NAME02 et dans ce
cas on a PTR_SCRN = 1.
Ce pointeur est réajusté en fait quand le nom en video-inversée est soit
sur la 1ère ligne de l'écran soit sur la dernière et que l'action
utilisateur le fait sortir de l'écran.
Définition: PTR_SCRN [0,max=max(PTR_LIST)-19=107]


Illustration:

Au début, l'utilisateur est sur le 1er nom.
NAME01 est en video-inversée.
PTR_LIST = 0.
PTR_SCRN = 0.

CV
   ***********************<SCREEN>**************************
00 */VOLUME/DIR1/DIR2/                                     *
01 *                                                       *
02 *  [] NAME01  <- PTR_LIST (0) = PTR_SCRN (0)            *
03 *  [] NAME02                                            *
04 *     NAME03                                            *
05 *  [] NAME04                                            *
06 *     NAME05                                            *
07 *     NAME06                                            *
08 *  [] NAME07                                            *
09 *  [] NAME08                                            *
10 *  [] NAME09                                            *
11 *  [] NAME10                                            *
12 *  [] NAME11                                            *
13 *  [] NAME12                                            *
14 *  [] NAME13                                            *
15 *  [] NAME14                                            *
16 *  [] NAME15                                            *
17 *     NAME16                                            *
18 *     NAME17                                            *
19 *     NAME18                                            *
20 *     NAME19                                            *
21 *  [] NAME20                                            *
22 *                                                       *
23 *       RETURN: Select | TAB: Chg Vol | ESC: Back       *
   *********************************************************
      [] NAME21
         NAME22  <- CPT_NAME (22)

Il tape sur la touche flèche BAS une fois.
NAME02 est en vidéo-inversée.
PTR_LIST = 1.
PTR_SCRN = 0.

CV
   ***********************<SCREEN>**************************
00 */VOLUME/DIR1/DIR2/                                     *
01 *                                                       *
02 *  [] NAME01  <- PTR_SCRN (0)                           *
03 *  [] NAME02  <- PTR_LIST (1)                           *
04 *     NAME03                                            *
05 *  [] NAME04                                            *
06 *     NAME05                                            *
07 *     NAME06                                            *
08 *  [] NAME07                                            *
09 *  [] NAME08                                            *
10 *  [] NAME09                                            *
11 *  [] NAME10                                            *
12 *  [] NAME11                                            *
13 *  [] NAME12                                            *
14 *  [] NAME13                                            *
15 *  [] NAME14                                            *
16 *  [] NAME15                                            *
17 *     NAME16                                            *
18 *     NAME17                                            *
19 *     NAME18                                            *
20 *     NAME19                                            *
21 *  [] NAME20                                            *
22 *                                                       *
23 *       RETURN: Select | TAB: Chg Vol | ESC: Back       *
   *********************************************************
      [] NAME21
         NAME22  <- CPT_NAME (22)

Il continue de descendre jusqu'à la dernière ligne de l'écran.
NAME20 est en video-inversée.
PTR_LIST = 19.
PTR_SCRN = 0.

CV
   ***********************<SCREEN>**************************
00 */VOLUME/DIR1/DIR2/                                     *
01 *                                                       *
02 *  [] NAME01  <- PTR_SCRN (0)                           *
03 *  [] NAME02                                            *
04 *     NAME03                                            *
05 *  [] NAME04                                            *
06 *     NAME05                                            *
07 *     NAME06                                            *
08 *  [] NAME07                                            *
09 *  [] NAME08                                            *
10 *  [] NAME09                                            *
11 *  [] NAME10                                            *
12 *  [] NAME11                                            *
13 *  [] NAME12                                            *
14 *  [] NAME13                                            *
15 *  [] NAME14                                            *
16 *  [] NAME15                                            *
17 *     NAME16                                            *
18 *     NAME17                                            *
19 *     NAME18                                            *
20 *     NAME19                                            *
21 *  [] NAME20  <- PTR_LIST (19)                          *
22 *                                                       *
23 *       RETURN: Select | TAB: Chg Vol | ESC: Back       *
   *********************************************************
      [] NAME21
         NAME22  <- CPT_NAME (22)

Il descend encore une fois.
NAME21 est en video-inversée.
PTR_LIST = 20.
PTR_SCRN = 1.

CV
      [] NAME01
   ***********************<SCREEN>**************************
00 */VOLUME/DIR1/DIR2/                                     *
01 *                                                       *
02 *  [] NAME02  <- PTR_SCRN (1)                           *
03 *     NAME03                                            *
04 *  [] NAME04                                            *
05 *     NAME05                                            *
06 *     NAME06                                            *
07 *  [] NAME07                                            *
08 *  [] NAME08                                            *
09 *  [] NAME09                                            *
10 *  [] NAME10                                            *
11 *  [] NAME11                                            *
12 *  [] NAME12                                            *
13 *  [] NAME13                                            *
14 *  [] NAME14                                            *
15 *  [] NAME15                                            *
16 *     NAME16                                            *
17 *     NAME17                                            *
18 *     NAME18                                            *
19 *     NAME19                                            *
20 *  [] NAME20                                            *
21 *  [] NAME21  <- PTR_LIST (20)                          *
22 *                                                       *
23 *       RETURN: Select | TAB: Chg Vol | ESC: Back       *
   *********************************************************
         NAME22  <- CPT_NAME (22)



Source assemblé



                1   
                2             LST   OFF
                3             ORG   $1000     
                4             XC               ; assemblage proc 65C02
                5   
                6    ********************************
                7    *                              *
                8    *  ProDOS 8 V2.0.3 : MLI QUIT  *
                9    *  (c)1983-1993 Apple Computer *
                10   *                              *
                11   *      Source by Deckard       *
                12   *                              *
                13   ********************************
                14  
                15   * Pour récupérer la routine MLI Quit originale, faire:
                16   * BLOAD PRODOS,A$2000,TSYS
                17   * BSAVE MLIQUIT.ORIG,A$5D00,L$300
                18  
                19   * Page 0 (usage standard)
                20  
                21   WNDLFT   EQU   $20        ; marge gauche
                22   WNDWDTH  EQU   $21        ; largeur
                23   WNDTOP   EQU   $22        ; marge haute [00,..]
                24   WNDBTM   EQU   $23        ; marge basse [..,23]
                25  
                26   CH       EQU   $24        ; screen x coord [0,79]
                27   CV       EQU   $25        ; screen y coord [0,23]
                28   INVFLG   EQU   $32        ; flag affichage normal/inverse (ou flash)
                29  
                30   * Page 0 (par MLI Quit)
                31  
                32   TBL_SET_MARK EQU $60      ; parms for MLI set mark
                33   FIL_SET_MARK EQU $61      ; file #
                34   NEW_FILE_POS EQU $62      ; $62/$63/$64 new file position
                35  
                36   ZDEVCNT  EQU   $65        ; copie de DEVCNT for work
                37   PTR_LIST EQU   $67        ; pointeur sur liste des noms [0,CPT_NAME-1]
                38   CPT_NAME EQU   $68        ; nbr de noms ok dans le répertoire [0,127]
                39   LEN_NAME EQU   $69        ; name length
                40   CPT_PRT_PAGE EQU $6A      ; compteur affichage noms sur l'écran
                41   DIR_LEVEL EQU  $6B        ; nbr de niveaux de répertoire [0=unité non
                42                             ; selectionnée, 1=root, ...]
                43   PTR_NAME EQU   $6C        ; et $6D. Pointeur sur nom objet [0,126]
                44   DIR_ELENGTH EQU $6E       ; length (bytes) of each entry in the vol dir
                45                             ; -> usually = $27
                46   DIR_EP_BLK EQU $6F        ; entries per block (usually = $0D)
                47   FILE_COUNT EQU $70        ; et $71 : nbr of active entries in dir
                48   CPT_SKIP_NAME EQU $72     ; nbr de noms à sauter dans le block
                49   PTR_SCRN EQU   $73        ; pointeur écran [0,107]
                50   FILE_TYPEL EQU $74        ; liste des "file type" des noms sélectionnables
                51                             ; [$74,$F2]
                52  
                53   * Ram
                54  
                55   KEYBUFF  EQU   $0280      ; keyboard buffer
                56   SOFTEV   EQU   $03F2      ; vector for warm start
                57   OURCH    EQU   $057B      ; 80c CH
                58   BUF_NAMES EQU  $1400      ; buffer des 127 noms possible
                59   BUF_OPEN EQU   $1C00      ; $400 bytes buffer for mli open
                60  
                61   * Ram spécifique programme
                62  
                63   H2000    EQU   $2000      ; buffer read / adresse SYS loaded
                64   VOL_HEADER EQU $2000      ; début buffer (en-tete vol/dir)
                65   ENTRY_LENGTH EQU VOL_HEADER+$23 ; positionnement pour : taille d'une
                66                             ; description d'objet (SYS/DIR) dans le répertoire
                67                             ; (usually $27)
                68  
                69   OBJ_HEADER EQU $2000      ; début buffer (descriptif objet)
                70   FILE_TYPE EQU  OBJ_HEADER+$10 ; positionnement pour : type objet
                71   ACCESS   EQU   OBJ_HEADER+$1E ; positionnement pour : détail accès objet
                72  
                73   * Prodos global page
                74  
                75   MLI      EQU   $BF00      ; MLI entry addr
                76   DEVNUM   EQU   $BF30      ; last used drive+slot DSSS0000
                77   DEVCNT   EQU   $BF31      ; count of active devices
                78   DEVLST   EQU   $BF32      ; list of active devices
                79   BITMAP   EQU   $BF58      ; bitmap of low 48k of memory
                80  
                81   * I/O
                82  
                83   KEY      EQU   $C000      ; key pressed
                84   STROBE   EQU   $C010      ; keyboard
                85  
                86   * Rom
                87  
                88   SETTXT   EQU   $FB39      ; set for text mode
                89   TABV     EQU   $FB5B      ; vtab to row in acc
                90   SETPWRC  EQU   $FB6F      ; routine to calculate the 'funny complement' for
                91                             ; reset vector
                92   BELL1    EQU   $FBD9      ; direct call to bell routine
                93   HOME     EQU   $FC58      ; clear screen
                94   COUT     EQU   $FDED      ; user output routine
                95   SETINV   EQU   $FE80      ; set inverse video
                96   SETNORM  EQU   $FE84      ; set normal video
                97  
                98   * Commandes prodos
                99  
                100  ONLINE   =     $C5       
                101  SET_PREFIX =   $C6       
                102  OPEN     =     $C8       
                103  READ     =     $CA       
                104  CLOSE    =     $CC       
                105  SET_MARK =     $CE       
                106 
                107  ********************************
                108 
1000: D8        109  H1000    CLD             
                110 
1001: AD 82 C0  111           LDA   $C082      ; enables rom
                112                            ; fait pointer reset sur le début de cette routine
1004: 9C F2 03  113           STZ   SOFTEV     ; low vector = 0
1007: A9 10     114           LDA   #>H1000   
1009: 8D F3 03  115           STA   SOFTEV+1   ; high vector
100C: 20 6F FB  116           JSR   SETPWRC    ; calcule $03F4 (funny complement)
100F: A9 A0     117           LDA   #" "       ; turn on the video firmware
1011: 20 00 C3  118           JSR   $C300      ; 80c firmware
                119 
1014: A2 17     120           LDX   #23        ; declare free l'espace ram 48k
1016: 9E 58 BF  121  :1       STZ   BITMAP,X   ; 0=free
1019: CA        122           DEX             
101A: 10 FA     123           BPL   :1        
                124 
101C: EE 6F BF  125           INC   BITMAP+23  ; sauf bit 0 -> $BF00-$BFFF (ProDOS global page)
101F: A9 CF     126           LDA   #%11001111 ; pages 2/3 free. 0/1 & 4 to 7 not free
1021: 8D 58 BF  127           STA   BITMAP    
                128 
1024: A9 02     129           LDA   #2         ; nbr de parms
1026: 85 60     130           STA   TBL_SET_MARK ; pour MLI set mark
1028: AE 31 BF  131           LDX   DEVCNT     ; zone de travail du nbr d'unités actives
102B: 86 65     132           STX   ZDEVCNT    ; pour passer de l'une à l'autre
102D: AD 30 BF  133           LDA   DEVNUM     ; déja une unité utilisée? (la dernière)
1030: D0 10     134           BNE   PREPARE_UNIT ; oui, commence par celle-ci
                135 
                136 
                137  *==============================*
                138  *                              *
                139  *    Sélectionne une unité     *
                140  *                              *
                141  *==============================*
                142 
                143  SELECT_UNIT              
1032: A6 65     144           LDX   ZDEVCNT    ; nbr d'unité
1034: BD 32 BF  145           LDA   DEVLST,X   ; prend la dernière DSSS000 unité active pointée
1037: E0 01     146           CPX   #1         ; est-ce qu'on les a toutes faites?
1039: B0 04     147           BCS   :1         ; >=1 -> non
                148 
103B: AE 31 BF  149           LDX   DEVCNT     ; repart sur la dernière (boucle)
103E: E8        150           INX             
103F: CA        151  :1       DEX             
1040: 86 65     152           STX   ZDEVCNT    ; nbr d'unité-1 [0,x] pour préparer la prochaine
                153 
                154 
                155  *==============================*
                156  *                              *
                157  *    Pré-traitement unité      *
                158  *                              *
                159  *==============================*
                160 
                161  PREPARE_UNIT             
1042: 8D F5 12  162           STA   UNIT       ; unité selectionnée
1045: 20 00 BF  163           JSR   MLI        ; récupère le nom du volume sans / devant
1048: C5        164           DFB   ONLINE    
1049: F4 12     165           DA    TBL_ONLINE
104B: B0 E5     166           BCS   SELECT_UNIT ; unit error. Passe à la suivante.
                167 
104D: 64 6B     168           STZ   DIR_LEVEL  ; default: unit non encore sélectionnée
104F: AD 81 02  169           LDA   KEYBUFF+1  ; 1er caractère récupéré DSSSLLLL
1052: 29 0F     170           AND   #$0F       ; garde que la longueur
1054: F0 DC     171           BEQ   SELECT_UNIT ; len=0 -> error. Try next unit
                172 
1056: 69 02     173           ADC   #2         ; len+2 (pour les 2 '/' rajoutés ci-dessous)
1058: AA        174           TAX             
                175 
                176  PREPARE_NAME              ; point d'entrée lors d'un changement de DIR
1059: 8E 80 02  177           STX   KEYBUFF    ; sauve longueur
105C: A9 2F     178           LDA   #'/'      
105E: 8D 81 02  179           STA   KEYBUFF+1   ; replace DSSSLLLL with first / (volume name)
1061: 9D 80 02  180           STA   KEYBUFF,X  ; met aussi un / en fin de nom: /name/
1064: 9E 81 02  181           STZ   KEYBUFF+1,X ; et un terminateur $00
                182 
1067: 20 00 BF  183           JSR   MLI        ; ouverture unité ou répertoire
106A: C8        184           DFB   OPEN      
106B: EC 12     185           DA    TBL_OPEN  
106D: 90 10     186           BCC   DO_VOL_DIR ; ok
                187 
                188                            ; error
106F: A5 6B     189           LDA   DIR_LEVEL  ; l'unité était sélectionnée?
1071: F0 BF     190           BEQ   SELECT_UNIT ; non, va sur la prochaine unité ou reste sur la
                191                            ; meme en fonction de ZDEVCNT
                192 
                193                            ; erreur lors de l'acces d'un sous-répertoire!
                194                            ; l'unité est soit endommagée soit bad dir name
1073: 20 DD FB  195           JSR   BELL1+4    ; signale erreur avec son
1076: 20 DA 11  196           JSR   PREVIOUS_DIR ; essaie de remonter d'un niveau
1079: 8E 80 02  197           STX   KEYBUFF    ; stocke nouvelle longueur
107C: 4C B0 11  198           JMP   KEY_USER   ; attente touche & action
                199 
                200 
                201  *==============================*
                202  *                              *
                203  *   Traitement du volume ou    *
                204  *       d'un répertoire        *
                205  *                              *
                206  *==============================*
                207 
                208  DO_VOL_DIR               
107F: E6 6B     209           INC   DIR_LEVEL  ; validation volume ou niveau de DIR
1081: 64 68     210           STZ   CPT_NAME   ; init nbr de noms
                211 
1083: AD F1 12  212           LDA   FIL_OPEN   ; fixe file number pour read & set mark
1086: 8D FC 12  213           STA   FIL_READ  
1089: 85 61     214           STA   FIL_SET_MARK
108B: A9 2B     215           LDA   #$2B       ; fixe len read = taille volume/dir header
108D: 8D FF 12  216           STA   RQL_READ  
1090: 9C 00 13  217           STZ   RQL_READ+1 ; high=0
1093: 20 B4 12  218           JSR   DO_READ    ; lecture descriptif (header)
1096: B0 1B     219           BCS   GO_PRINT_LIST ; error
                220 
1098: A2 03     221           LDX   #3         ; sauvegarde en page 0 de "entry length",
109A: BD 23 20  222  :1       LDA   ENTRY_LENGTH,X ; "entries per block" et "file count"
109D: 95 6E     223           STA   DIR_ELENGTH,X
109F: CA        224           DEX             
10A0: 10 F8     225           BPL   :1        
                226                            ; positionne pour lecture prochain nom du catalog
10A2: 8D FF 12  227           STA   RQL_READ   ; length of 1 entry in vol dir
10A5: A9 01     228           LDA   #1         ; init compteur de noms à sauter dans le block.
10A7: 85 72     229           STA   CPT_SKIP_NAME ; skip nom vol ou nom dir
10A9: 64 63     230           STZ   NEW_FILE_POS+1 ; init positionnement high
10AB: 64 64     231           STZ   NEW_FILE_POS+2
                232 
                233  *==============================*
                234  *                              *
                235  *   Controles sur le nombre    *
                236  *          d'objets            *
                237  *                              *
                238  *==============================*
                239 
10AD: A5 70     240           LDA   FILE_COUNT ; est-ce qu'il y a au moins un objet valide?
10AF: 05 71     241           ORA   FILE_COUNT+1
10B1: D0 02     242           BNE   CHECK_NBR_NAM ; oui
                243                            ; non -> affiche liste vide quand meme
                244 
                245  GO_PRINT_LIST            
10B3: 80 74     246           BRA   PRINT_LIST ; toujours
                247 
                248  CHECK_NBR_NAM            
10B5: 24 71     249           BIT   FILE_COUNT+1 ; + de 127 noms?
10B7: 30 FA     250           BMI   GO_PRINT_LIST ; oui, arrete là
                251 
                252 
                253  *==============================*
                254  *                              *
                255  *  Calcule le positionnement   *
                256  * à faire pour pointer sur le  *
                257  *    prochain nom à lire       *
                258  *                              *
                259  *==============================*
                260 
                261  POSITION_NAME            
                262                            ; position dans le block [$0000-$01FF]
10B9: A5 63     263           LDA   NEW_FILE_POS+1 ; init high position sans toucher au résultat
10BB: 29 FE     264           AND   #%11111110 ; des précédants positionnements
10BD: 85 63     265           STA   NEW_FILE_POS+1
10BF: A4 72     266           LDY   CPT_SKIP_NAME ; nbr noms à sauter < ...
10C1: A9 00     267           LDA   #0        
10C3: C4 6F     268           CPY   DIR_EP_BLK ; ... au nbr de noms par block?
10C5: 90 07     269           BCC   :1         ; oui (< $0D)
                270 
10C7: A8        271           TAY              ; on saut un bloc entier
10C8: 84 72     272           STY   CPT_SKIP_NAME ; repart sur le 1er nom du block suivant
                273                            ; Y=0
10CA: E6 63     274           INC   NEW_FILE_POS+1 ; skip 1 block (=512 octets)
10CC: E6 63     275  :2       INC   NEW_FILE_POS+1
10CE: 88        276  :1       DEY              ; -1 nom à sauter
10CF: 18        277           CLC              ; prépare pour l'ADC qui suit
10D0: 30 06     278           BMI   :3         ; ok on a fini de comptabiliser le positionnement
                279                            ; pour les noms à sauter
                280 
10D2: 65 6E     281           ADC   DIR_ELENGTH ; ajoute la taille d'un descriptif d'objet
10D4: 90 F8     282           BCC   :1        
                283 
10D6: B0 F4     284           BCS   :2         ; dépassement (incrémente high pour accès 256 bytes
                285                            ; suivants)
                286 
10D8: 69 04     287  :3       ADC   #$04       ; skip pointer fields en début de block
10DA: 85 62     288           STA   NEW_FILE_POS
                289 
10DC: 20 00 BF  290           JSR   MLI        ; ok positionne sur début du prochain descriptif
10DF: CE        291           DFB   SET_MARK   ; du nom à traiter
10E0: 60 00     292           DA    TBL_SET_MARK
10E2: B0 CF     293           BCS   GO_PRINT_LIST ; err. Affiche déja ce qui a été fait
                294 
10E4: 20 B4 12  295           JSR   DO_READ    ; lecture descriptif d'un nom
10E7: B0 CA     296           BCS   GO_PRINT_LIST ; err. Affiche déja ce qui a été fait
                297 
10E9: E6 72     298           INC   CPT_SKIP_NAME ; saute ce nom pour accéder au prochain
                299 
                300 
                301  *==============================*
                302  *                              *
                303  *   Controle prise en compte   *
                304  *      d'un nom du catalog     *
                305  *                              *
                306  *==============================*
                307 
10EB: AD 00 20  308           LDA   OBJ_HEADER ; controle objet supprimé
10EE: 29 F0     309           AND   #$F0       ; vire len
10F0: F0 C7     310           BEQ   POSITION_NAME ; deleted entry!
                311 
                312                            ; ok il était défini comme nom actif. Signale
                313                            ; que ca en fait un de moins dans le compteur
                314                            ; fourni par l'en-tete
10F2: C6 70     315           DEC   FILE_COUNT ; -1 nom dans la liste des actifs (low)
10F4: D0 02     316           BNE   :4        
                317 
10F6: C6 71     318           DEC   FILE_COUNT+1 ; high
                319 
10F8: 6E 1E 20  320  :4       ROR   ACCESS     ; autorisé à lire cet objet?
10FB: 90 B8     321           BCC   CHECK_NBR_NAM ; non!
                322 
                323                            ; ok traitable, vérifie à présent les types objet
10FD: AD 10 20  324           LDA   FILE_TYPE 
1100: C9 0F     325           CMP   #$0F       ; = DIR?
1102: F0 04     326           BEQ   :5         ; oui
                327 
1104: C9 FF     328           CMP   #$FF       ; = SYS.
1106: D0 AD     329           BNE   CHECK_NBR_NAM ; non -> suivant
                330 
1108: A6 68     331  :5       LDX   CPT_NAME   ; nbr max de noms gérés dans le répertoire?
110A: E0 80     332           CPX   #128      
110C: B0 1B     333           BCS   PRINT_LIST ; oui (>=128). Arrete prise en compte
                334 
                335 
                336  *==============================*
                337  *                              *
                338  *   Prise en compte d'un nom   *
                339  *                              *
                340  *==============================*
                341 
                342                            ; acc=file type,X=position dans liste
110E: 95 74     343           STA   FILE_TYPEL,X ; sauve le type de l'objet à son indice
1110: 20 58 12  344           JSR   CALC_PTR_NAME ; pointe sur position courante
                345 
1113: A0 0F     346           LDY   #$0F       ; dernier caractère du nom
1115: B9 00 20  347  :6       LDA   OBJ_HEADER,Y
1118: 91 6C     348           STA   (PTR_NAME),Y
111A: 88        349           DEY             
111B: 10 F8     350           BPL   :6         ; recopie tout le nom & storage type+len
                351 
111D: C8        352           INY              ; Y=0
111E: 29 0F     353           AND   #$0F       ; garde que la longueur (kill storage type)
1120: 91 6C     354           STA   (PTR_NAME),Y ; save len
1122: E6 68     355           INC   CPT_NAME   ; un nom de plus
1124: D0 8F     356           BNE   CHECK_NBR_NAM ; passe au suivant
                357 
                358  *-------------------------------
                359 
                360  GO_SEL_UNIT              
1126: 4C 32 10  361           JMP   SELECT_UNIT
                362 
                363 
                364  *==============================*
                365  *                              *
                366  * Affichage de la liste des    *
                367  *            noms              *
                368  *                              *
                369  *==============================*
                370 
                371  PRINT_LIST               
1129: 20 00 BF  372           JSR   MLI        ; ferme le volume/dir
112C: CC        373           DFB   CLOSE     
112D: F2 12     374           DA    TBL_CLOSE 
112F: B0 F5     375           BCS   GO_SEL_UNIT ; err: passe à une autre unité
                376 
1131: 20 39 FB  377           JSR   SETTXT     ; mode text
1134: 20 58 FC  378           JSR   HOME       ; efface écran
1137: A9 17     379           LDA   #23        ; positionne en bas écran
1139: 20 5B FB  380           JSR   TABV      
                381 
113C: A0 00     382           LDY   #0         ; affiche l'aide en ligne
113E: A9 14     383           LDA   #20        ; à partir de l'abscisse dans acc
1140: 20 4A 12  384           JSR   PRINT_MSGX
                385 
1143: 20 AD 12  386           JSR   CURSOR_UP_LFT ; curseur en haut à gauche
1146: A2 00     387           LDX   #0         ; affichage en haut de l'écran du pathname
1148: BD 81 02  388  :1       LDA   KEYBUFF+1,X
114B: F0 06     389           BEQ   :2         ; arret quand rencontre du terminateur
                390 
114D: 20 AF 12  391           JSR   PRINT_CHAR ; affichage caractère par caractère
1150: E8        392           INX             
1151: D0 F5     393           BNE   :1        
                394 
1153: 64 67     395  :2       STZ   PTR_LIST   ; init pointeur liste des noms
1155: 64 73     396           STZ   PTR_SCRN   ; init pointeur écran
1157: A5 68     397           LDA   CPT_NAME   ; aucun nom?
1159: F0 55     398           BEQ   KEY_USER   ; oui. Attente autre touche.
                399 
115B: C9 15     400           CMP   #21        ; plus d'une page de noms?
115D: 90 02     401           BCC   :3         ; non. Fait ce nombre de noms et pas plus.
                402 
115F: A9 14     403           LDA   #20        ; on fait une page pleine
1161: 85 6A     404  :3       STA   CPT_PRT_PAGE
                405 
1163: A9 02     406           LDA   #2         ; définition fenetre écran pour protéger
1165: 85 22     407           STA   WNDTOP     ; l'affichage du pathname et de l'aide des touches
1167: 85 20     408           STA   WNDLFT    
1169: A9 16     409           LDA   #22       
116B: 85 21     410           STA   WNDWDTH   
116D: 85 23     411           STA   WNDBTM    
                412 
116F: 20 77 12  413  :4       JSR   PRINT_NAME ; affiche le nom en normal
1172: E6 67     414           INC   PTR_LIST   ; un nom de plus dans la liste
1174: C6 6A     415           DEC   CPT_PRT_PAGE ; un nom en moins à afficher sur cet écran
1176: D0 F7     416           BNE   :4         ; pas fini
                417 
1178: 64 67     418           STZ   PTR_LIST   ; repositionne en haut de liste
117A: F0 2E     419           BEQ   PRT_INV_NAME ; toujours (affiche nom inverse)
                420 
                421 
                422  *==============================*
                423  *                              *
                424  *    Traitement flèche HAUT    *
                425  *                              *
                426  *==============================*
                427 
117C: 20 77 12  428  KEY_UP   JSR   PRINT_NAME ; affiche le nom pointé en normal
117F: A6 67     429           LDX   PTR_LIST   ; est-on au tout début de la liste?
1181: F0 27     430           BEQ   PRT_INV_NAME ; oui. Ne bouge pas (affiche nom pointé en inverse)
                431 
1183: C6 67     432           DEC   PTR_LIST   ; pointeur liste-1
1185: A5 25     433           LDA   CV         ; position écran
1187: C9 02     434           CMP   #$02       ; est-on en haut?
1189: D0 1F     435           BNE   PRT_INV_NAME ; non. Affiche nom pointé en inverse
                436 
                437                            ; comme on était en haut de l'écran et que le
                438                            ; pointeur de noms sur la liste a fait -1, il faut
                439                            ; repositionner le début de l'affichage sur ce nom,
                440                            ; décaler la liste vers le bas et afficher ce
                441                            ; ce précédant nom sur la 1ère ligne.
118B: C6 73     442           DEC   PTR_SCRN   ; pointeur écran-1
118D: A9 16     443           LDA   #$16       ; ctrl-V -> décalage écran vers le bas (SCROLLDOWN)
118F: D0 16     444           BNE   GO_PRT     ; toujours
                445 
                446 
                447  *==============================*
                448  *                              *
                449  *     Traitement flèche BAS    *
                450  *                              *
                451  *==============================*
                452 
1191: 20 77 12  453  KEY_DOWN JSR   PRINT_NAME ; affiche le nom pointé en normal
1194: A6 67     454           LDX   PTR_LIST   ; position actuelle pointeur déja sur dernier
1196: E8        455           INX              ; nom?
1197: E4 68     456           CPX   CPT_NAME  
1199: B0 0F     457           BCS   PRT_INV_NAME ; oui. Reste sur place et affiche nom pointé en
                458                            ; inverse
119B: 86 67     459           STX   PTR_LIST   ; pointeur liste+1
119D: A5 25     460           LDA   CV         ; est-on en bas de l'écran?
119F: C9 15     461           CMP   #21       
11A1: D0 07     462           BNE   PRT_INV_NAME ; non pas encore
                463 
                464                            ; on était en bas. Il faut descendre hors écran.
11A3: E6 73     465           INC   PTR_SCRN   ; positionne le pointeur écran sur le nom suivant
11A5: A9 17     466           LDA   #$17       ; ctrl-W -> décalage écran vers le haut (SCROLLUP)
11A7: 20 ED FD  467  GO_PRT   JSR   COUT      
                468 
                469  PRT_INV_NAME             
11AA: 20 80 FE  470           JSR   SETINV     ; affichage du nom pointé en inverse
11AD: 20 77 12  471           JSR   PRINT_NAME
                472 
                473 
                474  *==============================*
                475  *                              *
                476  * Attente d'une touche et exec *
                477  * action correspondante        *
                478  *                              *
                479  *==============================*
                480 
11B0: AD 00 C0  481  KEY_USER LDA   KEY        ; key pressed?
11B3: 10 FB     482           BPL   KEY_USER   ; non
                483 
11B5: 8D 10 C0  484           STA   STROBE     ; init keyboard
11B8: 20 84 FE  485           JSR   SETNORM    ; mode normal
                486 
11BB: A6 68     487           LDX   CPT_NAME   ; si aucun objet sélectionnable
11BD: F0 0C     488           BEQ   :1         ; saute les touches correspondantes
                489 
11BF: C9 8D     490           CMP   #$8D       ; return?
11C1: F0 31     491           BEQ   KEY_RETURN ; oui
                492 
11C3: C9 8A     493           CMP   #$8A       ; down?
11C5: F0 CA     494           BEQ   KEY_DOWN   ; oui
                495 
11C7: C9 8B     496           CMP   #$8B       ; up?
11C9: F0 B1     497           BEQ   KEY_UP     ; oui
                498 
11CB: C9 89     499  :1       CMP   #$89       ; tab?
11CD: F0 1E     500           BEQ   KEY_TAB    ; oui
                501 
11CF: C9 9B     502           CMP   #$9B       ; esc?
11D1: D0 DD     503           BNE   KEY_USER   ; non -> touche incorrecte. Wait for next.
                504 
                505 
                506  *==============================*
                507  *                              *
                508  *       Traitement ESC         *
                509  *                              *
                510  *==============================*
                511 
11D3: 20 DA 11  512           JSR   PREVIOUS_DIR ; essaie de remonter d'un niveau
11D6: C6 6B     513           DEC   DIR_LEVEL  ; level-1
11D8: 80 17     514           BRA   NEW_DIR    ; toujours
                515 
                516 
                517  *==============================*
                518  *                              *
                519  *  Remonte d'un répertoire     *
                520  *                              *
                521  *==============================*
                522 
                523  * In : KEYBUFF = len+pathname
                524  *
                525  * Out: X       = new length
                526 
                527  PREVIOUS_DIR             
                528 
11DA: AE 80 02  529           LDX   KEYBUFF    ; longueur pathname
11DD: CA        530  :1       DEX              ; -1
11DE: BD 80 02  531           LDA   KEYBUFF,X  ; caractère pointé
11E1: C9 2F     532           CMP   #'/'       ; = séparateur de répertoire?
11E3: D0 F8     533           BNE   :1         ; non, remonte encore jusqu'à en trouver un
                534 
11E5: E0 01     535           CPX   #1         ; est-ce la racine du volume?
11E7: D0 03     536           BNE   :2         ; non
                537 
11E9: AE 80 02  538           LDX   KEYBUFF    ; ne bouge pas (on est sur root)
11EC: 60        539  :2       RTS             
                540 
                541 
                542  *==============================*
                543  *                              *
                544  *    Traitement touche TAB     *
                545  *                              *
                546  *==============================*
                547 
11ED: 4C 32 10  548  KEY_TAB  JMP   SELECT_UNIT ; passe à la next unit
                549 
                550 
                551  *==============================*
                552  *                              *
                553  *  Traite un autre répertoire  *
                554  *                              *
                555  *==============================*
                556 
11F0: E8        557  NEW_DIR2 INX              ; positionne sur dernier caractère+1
11F1: 4C 59 10  558  NEW_DIR  JMP   PREPARE_NAME ; met '/' et traite ce dir
                559 
                560 
                561  *==============================*
                562  *                              *
                563  *   Traitement touche RETURN   *
                564  *                              *
                565  *==============================*
                566 
                567  KEY_RETURN               
11F4: 20 00 BF  568           JSR   MLI        ; fait un set prefix sur le directory
11F7: C6        569           DFB   SET_PREFIX
11F8: F8 12     570           DA    TBL_SET_PFX
11FA: B0 F1     571           BCS   KEY_TAB    ; marche pas -> passe à l'unit suivante
                572 
11FC: A6 67     573           LDX   PTR_LIST   ; recherche adr nom sur objet pointé
11FE: 20 58 12  574           JSR   CALC_PTR_NAME
                575                            ; Y=0
1201: AE 80 02  576           LDX   KEYBUFF    ; ajoute le nom à la suite du pathname courant
1204: C8        577  :1       INY             
1205: B1 6C     578           LDA   (PTR_NAME),Y ; recopie le nom dans buffer clavier
1207: E8        579           INX             
1208: 9D 80 02  580           STA   KEYBUFF,X 
120B: C4 69     581           CPY   LEN_NAME   ; dernier caractère?
120D: 90 F5     582           BCC   :1         ; non
                583 
120F: 8E 80 02  584           STX   KEYBUFF    ; sauve nouvelle longueur
1212: A4 67     585           LDY   PTR_LIST   ; récupère le type de l'objet pointé
1214: B9 74 00  586           LDA   FILE_TYPEL,Y
1217: 10 D7     587           BPL   NEW_DIR2   ; traite un autre DIR
                588 
                589  * Lancement final du SYS sélectionné
                590 
1219: 20 39 FB  591           JSR   SETTXT     ; petit ménage avant de partir
121C: 20 58 FC  592           JSR   HOME      
                593 
121F: A9 95     594           LDA   #$95       ; ctrl-U -> desactive sous prog 80c
1221: 20 ED FD  595           JSR   COUT      
                596 
1224: 20 00 BF  597           JSR   MLI        ; ouverture du SYS
1227: C8        598           DFB   OPEN      
1228: EC 12     599           DA    TBL_OPEN  
122A: B0 C1     600           BCS   KEY_TAB  
                601 
122C: AD F1 12  602           LDA   FIL_OPEN   ; met file number pour read
122F: 8D FC 12  603           STA   FIL_READ  
1232: A9 FF     604           LDA   #$FF       ; pas de limite de lecture (load all the file)
1234: 8D FF 12  605           STA   RQL_READ  
1237: 8D 00 13  606           STA   RQL_READ+1
123A: 20 B4 12  607           JSR   DO_READ    ; chargement du SYS
123D: 08        608           PHP             
123E: 20 00 BF  609           JSR   MLI         ; ferme tous les fichers ouverts
1241: CC        610           DFB   CLOSE     
1242: F2 12     611           DA    TBL_CLOSE 
1244: 28        612           PLP             
1245: B0 A6     613           BCS   KEY_TAB    ; error, retour à la case départ. Je suis
                614                            ; sceptique sur le bon fonctionnement (impact du
                615                            ; ctrl-U???)
                616 
1247: 4C 00 20  617           JMP   H2000      ; lancement final du SYS. Tchao bambino...
                618 
                619 
                620  *==============================*
                621  *                              *
                622  * Affiche une chaine (message) *
                623  *                              *
                624  *==============================*
                625 
                626  PRINT_MSGX               
124A: 85 24     627           STA   CH         ; positionne curseur
                628  PRINT_MSG                
124C: B9 BB 12  629           LDA   STRINGS,Y 
124F: F0 06     630           BEQ   :1         ; terminateur
                631 
1251: 20 ED FD  632           JSR   COUT       ; affiche le caractère
1254: C8        633           INY              ; next char
1255: D0 F5     634           BNE   PRINT_MSG  ; always
1257: 60        635  :1       RTS             
                636 
                637 
                638  *==============================*
                639  *                              *
                640  *    Calcule adresse début     *
                641  *   informations d'un objet    *
                642  *                              *
                643  *==============================*
                644 
                645  * In : X        =  numéro objet (=nom)
                646  *
                647  * Out: Y        =  0
                648  *      LEN_NAME = longueur du nom
                649  *      PTR_NAME = pointeur sur buffer
                650 
                651  CALC_PTR_NAME            
1258: 64 6D     652           STZ   PTR_NAME+1 ; low=0
125A: 8A        653           TXA              ; object number *16
125B: 0A        654           ASL             
125C: 26 6D     655           ROL   PTR_NAME+1
125E: 0A        656           ASL             
125F: 26 6D     657           ROL   PTR_NAME+1
1261: 0A        658           ASL             
1262: 26 6D     659           ROL   PTR_NAME+1
1264: 0A        660           ASL             
1265: 26 6D     661           ROL   PTR_NAME+1
1267: 85 6C     662           STA   PTR_NAME  
1269: A9 14     663           LDA   #>BUF_NAMES ; + high début stockage
126B: 18        664           CLC             
126C: 65 6D     665           ADC   PTR_NAME+1
126E: 85 6D     666           STA   PTR_NAME+1
1270: A0 00     667           LDY   #0         ; save name length
1272: B1 6C     668           LDA   (PTR_NAME),Y
1274: 85 69     669           STA   LEN_NAME  
1276: 60        670           RTS             
                671 
                672 
                673  *==============================*
                674  *                              *
                675  * Affichage d'un nom à l'écran *
                676  *                              *
                677  *==============================*
                678 
                679  * In : PTR_LIST    indice nom à écrire
                680  *      FILE_TYPEL  tableau des types des objets
                681  *      INVFLG      type d'affichage (normal/inverse)
                682 
                683  * A noter que comme on affiche un espace avant et un espace
                684  * après le nom, si on est en mode inverse, on les voit.
                685 
                686  PRINT_NAME               
1277: A9 02     687           LDA   #2         ; saute 2 positions horizontales
1279: 8D 7B 05  688           STA   OURCH     
127C: A6 67     689           LDX   PTR_LIST   ; pointeur nom dans liste - ptr nom écran
127E: 8A        690           TXA             
127F: 38        691           SEC             
1280: E5 73     692           SBC   PTR_SCRN   ; résultat toujours [0,19]
1282: 1A        693           INC   A          ; saute les 2 1ère lignes figées
1283: 1A        694           INC   A         
1284: 20 5B FB  695           JSR   TABV       ; positionnement vertical [2,21]
                696 
1287: B5 74     697           LDA   FILE_TYPEL,X ; type objet
1289: 30 0E     698           BMI   :1         ; = SYS
                699 
                700                            ; pour un DIR on ajoute l'icone dossier
128B: 9C 7B 05  701           STZ   OURCH     
128E: A5 32     702           LDA   INVFLG     ; sauve le mode affichage actuel
1290: 48        703           PHA             
1291: A0 2A     704           LDY   #$2A       ; affichage icone folder
1293: 20 4C 12  705           JSR   PRINT_MSG 
1296: 68        706           PLA              ; restaure le mode affichage actuel
1297: 85 32     707           STA   INVFLG    
                708 
1299: 20 A9 12  709  :1       JSR   PRINT_SPACE ; affiche espace
129C: 20 58 12  710           JSR   CALC_PTR_NAME ; calcule adr début nom
                711                            ; Y=0
129F: C8        712  :2       INY              ; first=1->skip len
12A0: B1 6C     713           LDA   (PTR_NAME),Y ; affiche un caractère du nom
12A2: 20 AF 12  714           JSR   PRINT_CHAR
12A5: C4 69     715           CPY   LEN_NAME   ; dernier caractère?
12A7: 90 F6     716           BCC   :2         ; non
                717 
                718  PRINT_SPACE              
12A9: A9 A0     719           LDA   #" "       ; affiche espace
12AB: D0 04     720           BNE   DO_COUT    ; always
                721 
                722  CURSOR_UP_LFT            
12AD: A9 99     723           LDA   #$99       ; ctrl-Y -> curseur en haut à gauche (top&left)
                724 
                725  PRINT_CHAR               
12AF: 09 80     726           ORA   #%10000000 ; "caractère"
12B1: 4C ED FD  727  DO_COUT  JMP   COUT       ; affiche
                728 
                729 
                730  *==============================*
                731  *                              *
                732  * Effectue 1 lecture MLI read  *
                733  *                              *
                734  *==============================*
                735 
12B4: 20 00 BF  736  DO_READ  JSR   MLI       
12B7: CA        737           DFB   READ      
12B8: FB 12     738           DA    TBL_READ  
12BA: 60        739           RTS             
                740 
                741  *==============================*
                742  *                              *
                743  *    Chaines pour PRINT_MSG    *
                744  *                              *
                745  *==============================*
                746 
                747  STRINGS                  
                748 
                749  * Aide en ligne
                750 
12BB: D2 C5 D4  751           ASC   "RETURN: Select | TAB: Chg Vol | ESC: Back"00
12BE: D5 D2 CE BA
12C2: A0 D3 E5 EC
12C6: E5 E3 F4 A0
12CA: FC A0 D4 C1
12CE: C2 BA A0 C3
12D2: E8 E7 A0 D6
12D6: EF EC A0 FC
12DA: A0 C5 D3 C3
12DE: BA A0 C2 E1
12E2: E3 EB 00
                752 
                753  * Icone dossier
                754 
12E5: 0F        755           DFB   $0F        ; ctrl-O -> mode inverse
12E6: 1B        756           DFB   $1B        ; esc -> activation icones souris (MOUSON)
12E7: D8 D9     757           ASC   "XY" ; icone folder
12E9: 18        758           DFB   $18        ; ctrl-X -> desactivation icones souris (MOUSOFF)
12EA: 0E        759           DFB   $0E        ; ctrl-N -> mode normal
12EB: 00        760           DFB   0          ; terminateur
                761 
                762 
                763  *==============================*
                764  *                              *
                765  *      Tables pour MLI         *
                766  *                              *
                767  *==============================*
                768 
                769  * Open
                770 
12EC: 03        771  TBL_OPEN DFB   3         
12ED: 80 02     772           DA    KEYBUFF    ; addr of pathname
12EF: 00 1C     773           DA    BUF_OPEN   ; buffer
12F1: 00        774  FIL_OPEN DFB   0          ; file #
                775 
                776  * Close
                777 
                778  TBL_CLOSE                
12F2: 01        779           DFB   1         
12F3: 00        780           DFB   0          ; close all opened files
                781 
                782  * Online
                783 
                784  TBL_ONLINE               
12F4: 02        785           DFB   2         
12F5: 60        786  UNIT     DFB   %01100000  ; value not used (slot 6, drive 1)
12F6: 81 02     787           DA    KEYBUFF+1  ; 16 bytes buffer for a specific unit
                788 
                789  * Set Prefix
                790 
                791  TBL_SET_PFX              
12F8: 01        792           DFB   1         
12F9: 80 02     793           DA    KEYBUFF    ; addr of pathname
                794 
                795  * Read
                796 
12FB: 04        797  TBL_READ DFB   4         
12FC: 01        798  FIL_READ DFB   1          ; file #
12FD: 00 20     799           DA    H2000      ; addr data buffer
12FF: 00 00     800  RQL_READ DA    $0000      ; requested length
1301: 00 00     801           DA    $0000      ; actual length
                802 
                803  * Note: Une partie de la table n'apparait pas quand la routine
                804  *       est incluse dans ProDOS en $5D00-$5FFF. Quand elle est
                805  *       recopiée en $1000, elle fait plus de $300 de long.
                806  *       Comme ces derniers octets de la table READ sont à
                807  *       zero en temps normal, ce n'est en rien génant.
                808 
                809           SAV   MLIQUIT   

Object saved as MLIQUIT,A$1000,L$0303,BIN

 
 
--End assembly, 771 bytes, Errors: 0


Symbol table - alphabetical order:

   ACCESS  =$201E      BELL1   =$FBD9      BITMAP  =$BF58      BUF_NAMES=$1400
   BUF_OPEN=$1C00      CALC_PTR_NAME=$1258      CH      =$24        CHECK_NBR_NAM=$10B5
   CLOSE   =$CC        COUT    =$FDED      CPT_NAME=$68        CPT_PRT_PAGE=$6A
   CPT_SKIP_NAME=$72        CURSOR_UP_LFT=$12AD      CV      =$25        DEVCNT  =$BF31
   DEVLST  =$BF32      DEVNUM  =$BF30      DIR_ELENGTH=$6E        DIR_EP_BLK=$6F
   DIR_LEVEL=$6B        DO_COUT =$12B1      DO_READ =$12B4      DO_VOL_DIR=$107F
   ENTRY_LENGTH=$2023      FILE_COUNT=$70        FILE_TYPE=$2010      FILE_TYPEL=$74
   FIL_OPEN=$12F1      FIL_READ=$12FC      FIL_SET_MARK=$61        GO_PRINT_LIST=$10B3
   GO_PRT  =$11A7      GO_SEL_UNIT=$1126      H1000   =$1000      H2000   =$2000
   HOME    =$FC58      INVFLG  =$32        KEY     =$C000      KEYBUFF =$0280
   KEY_DOWN=$1191      KEY_TAB =$11ED      KEY_RETURN=$11F4      KEY_UP  =$117C
   KEY_USER=$11B0      LEN_NAME=$69        MLI     =$BF00      NEW_DIR =$11F1
   NEW_DIR2=$11F0      NEW_FILE_POS=$62        OBJ_HEADER=$2000      ONLINE  =$C5
   OPEN    =$C8        OURCH   =$057B      POSITION_NAME=$10B9      PREPARE_NAME=$1059
   PREPARE_UNIT=$1042      PREVIOUS_DIR=$11DA      PRINT_CHAR=$12AF      PRINT_LIST=$1129
   PRINT_MSG=$124C      PRINT_MSGX=$124A      PRINT_NAME=$1277      PRINT_SPACE=$12A9
   PRT_INV_NAME=$11AA      PTR_LIST=$67        PTR_NAME=$6C        PTR_SCRN=$73
   READ    =$CA        RQL_READ=$12FF      SELECT_UNIT=$1032      SETINV  =$FE80
   SETNORM =$FE84      SETPWRC =$FB6F      SETTXT  =$FB39      SET_MARK=$CE
   SET_PREFIX=$C6        SOFTEV  =$03F2      STRINGS =$12BB      STROBE  =$C010
   TABV    =$FB5B      TBL_CLOSE=$12F2      TBL_ONLINE=$12F4      TBL_OPEN=$12EC
   TBL_READ=$12FB      TBL_SET_MARK=$60        TBL_SET_PFX=$12F8      UNIT    =$12F5
   VOL_HEADER=$2000      WNDBTM  =$23        WNDLFT  =$20        WNDTOP  =$22
   WNDWDTH =$21        ZDEVCNT =$65    


Symbol table - numerical order:

   WNDLFT  =$20        WNDWDTH =$21        WNDTOP  =$22        WNDBTM  =$23
   CH      =$24        CV      =$25        INVFLG  =$32        TBL_SET_MARK=$60
   FIL_SET_MARK=$61        NEW_FILE_POS=$62        ZDEVCNT =$65        PTR_LIST=$67
   CPT_NAME=$68        LEN_NAME=$69        CPT_PRT_PAGE=$6A        DIR_LEVEL=$6B
   PTR_NAME=$6C        DIR_ELENGTH=$6E        DIR_EP_BLK=$6F        FILE_COUNT=$70
   CPT_SKIP_NAME=$72        PTR_SCRN=$73        FILE_TYPEL=$74        ONLINE  =$C5
   SET_PREFIX=$C6        OPEN    =$C8        READ    =$CA        CLOSE   =$CC
   SET_MARK=$CE        KEYBUFF =$0280      SOFTEV  =$03F2      OURCH   =$057B
   H1000   =$1000      SELECT_UNIT=$1032      PREPARE_UNIT=$1042      PREPARE_NAME=$1059
   DO_VOL_DIR=$107F      GO_PRINT_LIST=$10B3      CHECK_NBR_NAM=$10B5      POSITION_NAME=$10B9
   GO_SEL_UNIT=$1126      PRINT_LIST=$1129      KEY_UP  =$117C      KEY_DOWN=$1191
   GO_PRT  =$11A7      PRT_INV_NAME=$11AA      KEY_USER=$11B0      PREVIOUS_DIR=$11DA
   KEY_TAB =$11ED      NEW_DIR2=$11F0      NEW_DIR =$11F1      KEY_RETURN=$11F4
   PRINT_MSGX=$124A      PRINT_MSG=$124C      CALC_PTR_NAME=$1258      PRINT_NAME=$1277
   PRINT_SPACE=$12A9      CURSOR_UP_LFT=$12AD      PRINT_CHAR=$12AF      DO_COUT =$12B1
   DO_READ =$12B4      STRINGS =$12BB      TBL_OPEN=$12EC      FIL_OPEN=$12F1
   TBL_CLOSE=$12F2      TBL_ONLINE=$12F4      UNIT    =$12F5      TBL_SET_PFX=$12F8
   TBL_READ=$12FB      FIL_READ=$12FC      RQL_READ=$12FF      BUF_NAMES=$1400
   BUF_OPEN=$1C00      H2000   =$2000      VOL_HEADER=$2000      OBJ_HEADER=$2000
   FILE_TYPE=$2010      ACCESS  =$201E      ENTRY_LENGTH=$2023      MLI     =$BF00
   DEVNUM  =$BF30      DEVCNT  =$BF31      DEVLST  =$BF32      BITMAP  =$BF58
   KEY     =$C000      STROBE  =$C010      SETTXT  =$FB39      TABV    =$FB5B
   SETPWRC =$FB6F      BELL1   =$FBD9      HOME    =$FC58      COUT    =$FDED
   SETINV  =$FE80      SETNORM =$FE84