RAM.DRV.SYSTEM


Dernière mise à jour le  jeudi 06/07/2006, 02:20 AM!!!


RAM.DRV.SYSTEM : le driver /RAM de Prosel-8 par Glen E. Bredon

Cet article est dédicacé à Mark Percival (Syndicomm) dont l'outil DiskMaker 8 a buté sur ce driver (dans sa phase beta).



01) Introduction


Dans le cadre d'un projet personnel sous ProDOS (un programme de création rapide de disks images en une passe), j'ai eu à m'intéresser de plus près à ma carte ram.
En effet, la capacité de stockage d'une disquette étant supérieure à celle de la mémoire principale d'une machine de base (64k), je souhaite lire toutes les données d'un seul coup et les stocker dans ma carte ram.

J'utilise comme extension une carte RamWorks III de la société Applied Engineering (AE).
Cette carte s'enfiche dans le slot 3 et donne les fonctionnalités d'une carte 80 colonnes étendue avec de la ram supplémentaire.
Je dispose pour ma part d'une carte faisant un méga (1024k).


02) Bank switching


La particularité de ce type de carte est de proposer une solution à la limite intrinsèque de la mémoire de l'Apple II (64k: de $0000 à $FFFF) en utilisant ce qu'on appelle le "bank switching". Comme on ne peut pas adresser plus de 64k, pour rajouter de la mémoire, il suffit de dire que l'on a à disposition plusieurs mémoires de 64k en parallèle et de préciser sur quelle mémoire on travaille. Chaque espace mémoire de 64k est appelée un bank.
Le nombre de banks de 64k dépend ensuite de la taille de votre carte mémoire qui peut être de 128k, 256k, 384k, etc...
Sur ma carte RamWorks III, je dispose de 16 banks de mémoire auxiliaire numérotés (en interne) de $00 à $0F.


Il y a 2 moyens d'utiliser ce type de carte: soit employer des programmes qui savent gérer seuls l'espace ram supplémentaire (exemple: les dernières versions d'Appleworks ou une version ancienne patchée, Locksmith Fast Copy, ...) soit transformer cette carte ram en un disque virtuel, c'est à dire un volume ProDOS sur lequel on peut sauvegarder des fichiers comme s'il s'agissait d'une disquette ou d'un disque dur volatile.
Il est possible de faire un mélange de ces 2 possibilités et c'était mon objectif quand j'ai commencé mes recherches dans ce domaine.
La documentation de la RamWorks III précise comment on peut utiliser les banks de mémoire additionnels mais en ce qui concerne l'aspect technique de la gestion de la carte ram comme disque virtuel, alors là, le moins que l'on puisse dire, c'est que c'est motus et bouche cousue. J'ai voulu ouvrir cette porte fermée et voir comment ça se passe.


03) ProDOS et la mémoire étendue


Il faut savoir que sans driver adéquate, ProDOS ne sait pas prendre en compte la ram supplémentaire de votre carte mémoire (la partie supérieure à 128k). Par défaut au démarrage, lorsque ProDOS détecte la présence d'une carte de type 80 colonnes étendue, il créé un disque virtuel /RAM générique que pour la taille de ce supplément immédiat de 64k.
Dans ses informations internes, il sait juste si vous avez 128k ou moins mais il n'y a rien de prévu en standard pour une taille supérieure à 128k.
Ce qui fait que même avec une carte d'un méga, vous n'avez qu'un volume /RAM d'un total de 120 blocks, c'est à dire 120 blocks*512 octets=61440 octets, soit 60k auquel il faut retrancher 7 blocks réservés pour le catalog et le volume bitmap (113 free blocks).
Toute le reste de votre mémoire est ignoré!

Pour gérer l'espace total des 1024k de ma carte, il faut avoir un driver compatible ProDOS.
Le driver de ce périphérique doit suivre les rêgles édictées par ce système d'exploitation.

Sur mon disque dur, juste après le programme ProDOS est lancé un driver pour ma carte ram. Mais il ne s'agit pas du driver proposé par AE.
Pourtant j'ai bien la disquette livrée avec une RamWorks III (idem pour mon autre carte RamWorks II) sur laquelle on trouve ProDrive (pour ProDOS) et RamDrive (fonctionnant sous DOS 3.3).
Mais je ne trouve pas la mise en oeuvre de la solution AE très pratique: ProDrive doit être lancé par BRUN ou en utilisant le menu d'installation accessible sur le Super Desktop Expander Disk.

Aussi, ce n'est pas ce driver que j'utilise au quotidien.
J'emploie le driver écrit par l'américain Glen E. Bredon (l'auteur de l'assembleur Merlin).
Il a proposé un driver personnel (tout au moins c'est présenté ainsi) dans son pack Prosel-8 et qui fonctionne sur les cartes AE et compatibles ainsi que pour les extensions de Checkmate Technology Inc.

Son driver est reconnu comme étant le meilleur ('preferred' d'après les newsgroups sur l'Apple II).
Il a aussi mis à disposition un programme qui permet de créer un SYS à partir de ProDrive d'AE et d'un supplément HEADER (personnel) mais je m'en suis tenu à son RAM.DRV.SYSTEM.

Tout comme ProDrive, il propose d'utiliser votre carte ram comme disque virtuel tout en offrant la possibilité de réserver des banks pour un autre usage. Ces banks réservés ne sont pas sélectionnables par le driver pour le disque virtuel. Il est donc possible de se les garder.

Un peu avant le décès de Glen Bredon (le 8 mai 2000), Prosel-8 est passé dans le domaine public avec l'accord de son auteur mais les sources de cette boite à outils ne sont pas disponibles sur internet.
Aussi ai-je décidé de créer un source de ce driver, de le commenter et de le mettre à disposition de ceux que cela pourrait aussi intéresser.


04) Utilisation et caractéristiques du driver RAM.DRV.SYSTEM


Le driver est un fichier .SYSTEM (type SYS) qui est exécuté au démarrage de ProDOS.
Il convient de le placer avant BASIC.SYSTEM ou le system final qui vous donnera la main.
Il faut par ailleurs aussi modifier quelques octets au début du driver pour pointer sur le prochain SYS à exécuter. (Ce type de manipulation est identique pour tous les .SYSTEM).
Vous pouvez faire ce changement facilement en utilisant un autre outil de Prosel, l'éditeur de blocks BLOCK.WARDEN.
Pour mettre à jour ce nom de prochain SYS avec BLOCK.WARDEN, il faut être sur le bon prefix, taper F)ollow, saisir RAM.DRV.SYSTEM, valider par enter puis faire E)dit. En avançant le curseur vers la droite, BLOCK.WARDEN reconnaitra automatiquement l'identifiant $EE $EE signalant un début de pathname et affichera une fenêtre pour saisir le nom du prochain SYS. Vous n'avez alors plus qu'à valider et sauvegarder la modification (ESC et Write block Yes).
Normalement, vous n'avez à faire cette modification qu'une seule fois...

Block.Warden
Block.Warden
Block.Warden
Block.Warden
Block.Warden


Vous pouvez aussi utiliser un programme BASIC (présent sur la disquette Prosel) écrit par Glen Bredon: CONFIG.RAMDRV.
Pour ce dernier, il faut en outre indiquer le drive et slot pour lequel on assigne le disk virtuel (slot 3 drive 1 par défaut) ainsi que le nombre de banks que l'on souhaite verrouiller (0 par défaut).

Le mapping drive/slot correspond à l'option SlotChanger d'Applied Engineering.
Les cartes RamWorks se mettent dans le connecteur auxiliaire (qui correspond en fait au drive 2 du slot 3). Mais il est préférable de forcer la reconnaissance du volume sur le slot 3 drive 1 (c'est ce paramétrage qui est mis par défaut et d'ailleurs toute device active en slot 3 drive 2 est automatiquement déconnectée s'il s'agit d'un driver stocké en $FFxx, adresse caractéristique pour un driver de ramdisk).

Concernant le verrouillage des banks, cette caractéristique est appelée dans le texte original de Prosel "bank lockout". A noter que le bank $00 auxiliaire (c'est à dire les 1er 64k additionnels de la carte d'extension) est toujours bloqué (comme pour ProDrive) et cela sans que l'on ait à spécifier quoi que ce soit. Il est bloqué même si vous indiquez que vous ne voulez pas réserver de banks particuliers.
Glen ne voulait pas toucher à ces 64k additionnels (qui peuvent servir aussi à d'autres fins comme le mode graphique DHGR...)

A noter que si vous n'avez pas lancé le driver, vous avez donc un volume /RAM créé par ProDOS qui lui au contraire utilise à fond le bank $00 aux.
Si vous ne le désactivez pas et si vous utilisez ce bank $00 aux par gestion directe dans votre programme, vous risquez d'avoir des plantages (en quittant par exemple) car le catalogue ou la volume bitmap peuvent avoir été altérés.
Pour plus de détail, voir l'excellent livre "Beneath Apple ProDOS" de Don Worth et Pieter Lechner et plus particulièrement le chapitre 7 : "Customizing ProDOS" (Disable /RAM volume for 128k machines).

Les blocks 0 et 1 du volume /RAM ne sont pas initialisés, ce qui veut dire que l'unité n'est pas bootable. Par contre, vous pouvez très bien mettre un fichier SYS sur le répertoire du ramdisk et le sélectionner après avoir fait un Quit.


05) Calcul de la taille de la mémoire


La carte RamWorks est assimilée par ProDOS a une carte 80 colonnes étendue.

Les cartes ne sont pas forcément vendues avec la même taille mémoire.
Une personne fauchée préférera acheter une carte avec 0k et récupérer des rams ailleurs (ou augmenter la capacité en fonction des rentrées d'argent).
D'autres voudront une carte "pleine" avec toute la ram possible que ce soit pour gérer de grosses applications ou tout simplement par goût du luxe.

En tout état de cause, la taille de la mémoire n'est pas inscrite en "dur" et c'est au driver de la déterminer pour savoir de combien de place il pourra disposer pour le volume /RAM.

Pour connaitre la taille exacte (qui sera un multiple de 64k - chaque bank faisant cette taille) le driver est obligé de tester les banks un par un en partant du principe qu'il peut y avoir jusqu'à $80 banks. Pour tester un bank, il doit tout d'abord le sélectionner puis écrire dedans à un endroit précis (en ayant pris la peine de sauvegarder le contenu au préalable au cas où).
Pour info, il écrit aux adresses $00 et $01 (page 0). Dans $00, il écrit le numéro du bank testé.
Puis il doit relire cet emplacement et vérifier que la valeur lue correspond bien à la valeur écrite précédemment. Si c'est le cas, alors le bank est valide. (Il remettra alors la valeur initiale trouvée à cet endroit avant d'avoir écrit dedans).
Si ce n'est pas le cas, c'est que soit le bank est HS (ram morte, ça arrive - il y a un outil de tests des rams pour cela) soit il n'y a pas de ram du tout correspondant à ce bank.
Par précaution, chaque bank est testé au moyen de 2 valeurs; la seconde étant un EOR #$FF de la première.

Pour sélectionner un bank (qu'il soit valable ou pas), RAM.DRV.SYSTEM écrit dans un softswitch spécial ($C073) le numéro de ce bank. Si ce bank n'est pas valable, cela n'a pas d'incidence et les écritures dans ce mauvais bank n'écraseront aucune donnée d'un autre bank. Ce qui est sur c'est que la relecture donnera une valeur différente de celle écrite dedans (on a écrit le numéro du bank).

A noter le mauvais gag: certaines autres cartes ram soit disant compatibles utilisent quant à elles un autre softswitch ($C071). Autant dire que le driver ram ne va rien trouver du tout.
Il faut alors modifier tous les tests $C073 par du $C071! Super pratique!!!
Du coup, certains programmes et des plus connus (ex: Publish It!, ProTerm, Apple II diagnostic, ...) ne reconnaissent pas ces cartes ram si un programme de patch spécial livré par le fabricant de la carte n'est pas appliqué sur ces applications pour les adapter à cet autre softswitch! Un bon moyen pour le frabricant de cartes de se faire du fric en facturant le soft en plus. A moins que ce soit la conséquence d'une "patent" destinée à empêcher un concurrent de sortir une carte directement concurrente à la sienne qui irait jusqu'à être compatible au niveau du driver... Allez savoir...

J'ai entendu parlé de MegaRAM/Microcom et de la Super Expander IIe. Mais il y en a probablement d'autres compte tenu du fort nombre de cartes proposées en leur temps sur le marché de l'Apple II.

La méthode de check des banks a permis de dresser une liste des banks valides et utilisables.
Il est important de noter que la numérotation des banks n'est pas nécessairement chronologique.
Pour ma carte, c'est le cas (banks $01 à $0F dispo pour /RAM) mais ce n'est pas la règle.
Ca dépend du fabricant, de l'agencement des rams sur la carte, la présence ou non d'une piggyback (ou piggy-back, c'est à dire une extension s'enfichant sur la RamWorks elle-même et donnant accès à encore plus de mémoire), etc...

Illustration:

Indice  Bank=(Contenu tableau),Indice
Liste   Ramworks III 1024k alone     Other card or configuration
  1     $01                              a
  2     $02                              b
  3     $03                              c
 ...
 15     $0F                              o


Aussi dans certains tableaux, je parlerais de banks a, b, c, ... plutôt que de mettre les banks $01, $02, ...


06) Comment ProDOS communique avec le volume /RAM


Ce volume /RAM correspond à une unité ProDOS au même titre qu'un volume de votre disque dur ou de votre disquette. Une unité est l'association d'un slot et d'un numéro de lecteur.
Sur un apple IIe classique, vous avez 7 slots physiques (de 1 à 7), chacun pouvant supporter 2 lecteurs.
Ce qui fait 14 unités. A cela il faut ajouter le pseudo slot 0 pour lequel on compte aussi 2 drives.
Soit un total de 16 unités gérables.

Quand ProDOS a besoin de dialoguer avec une unité, il se réfère à une table des "devices informations" contenue dans sa ProDOS System Global Page (main memory $BF00-$BFFF).
Concrêtement, le début de cette table (à partir de $BF10) contient 16 adresses que ProDOS appelle quand il veut dialoguer avec l'unité correspondante:

$BF10-$BF11 DEVADR01 -> adresse pointant le début du driver pour l'unité en slot 0, drive 1
$BF12-$BF13 DEVADR11 -> idem slot 1, drive 1 device driver address
$BF14-$BF15 DEVADR21 -> idem slot 2, drive 1
$BF16-$BF17 DEVADR31 -> idem slot 3, drive 1
$BF18-$BF19 DEVADR41 -> idem slot 4, drive 1
$BF1A-$BF1B DEVADR51 -> idem slot 5, drive 1
$BF1C-$BF1D DEVADR61 -> idem slot 6, drive 1
$BF1E-$BF1F DEVADR71 -> idem slot 7, drive 1
$BF20-$BF21 DEVADR02 -> idem slot 0, drive 2
$BF22-$BF23 DEVADR12 -> idem slot 1, drive 2
$BF24-$BF25 DEVADR22 -> idem slot 2, drive 2
$BF26-$BF27 DEVADR32 -> idem slot 3, drive 2
$BF28-$BF29 DEVADR42 -> idem slot 4, drive 2
$BF2A-$BF2B DEVADR52 -> idem slot 5, drive 2
$BF2C-$BF2D DEVADR62 -> idem slot 6, drive 2
$BF2E-$BF2F DEVADR72 -> idem slot 7, drive 2


Par défaut quand il n'y a pas de driver spécial et que ProDOS utilise le bank $00 aux comme volume /RAM, il fait un saut à l'adresse contenue dans DEVADR32 (slot 3, drive 2). Cette adresse est $FF00 en MEV (main mem).
Avec le driver RAM.DRV.SYSTEM, DEVADR32 est désactivée (même pointeur que pour le slot 0) et ProDOS saute à l'adresse contenue dans DEVADR31 (sauf si vous avez changé le mapping par défaut).
La routine principale du driver de RAM.DRV.SYSTEM se loge au même endroit (en $FF00 main mem) et détruit donc la routine native de ProDOS. (Certains fabricants préfèrent livrer une version de ProDOS modifiée plutôt que de faire un driver externe!)
A noter que c'est RAM.DRV.SYSTEM qui a mis à jour DEVADR32 et DEVADR31 lors de ses initialisations.
Pour d'autres cartes ram (type slinky comme la RamFactor d'AE ou l'Apple II Memory Expansion) dont le driver est en rom sur la carte, le procédé diffère (reconnaissance et formattage automatique du volume /RAMx où x est le slot logeant la carte ou /RAMxy avec x=slot et y=drive).

ProDOS gère aussi une autre liste importante: il s'agit de la liste des unités actives aux adresses:
$BF32-$BF3F DEVLST List of active devices (slot, drive and identification DSSSIIII).
Il y a aussi un pointeur sur cette liste contenu en:
$BF31 DEVCNT Count (minus 1) of active devices.
Si vous vous intéressez au source du driver, vous constaterez que ce pointeur et cette liste sont mis à jour dès que l'on ajoute ou supprime une unité.


07) Lien entre carte ram et volume /RAM


Chaque block ProDOS de 512 octets est sauvegardé dans la carte ram sous forme de 2 pages de mémoire.
Mis bout à bout, l'espace disponible de chaque bank va former l'espace de stockage des blocks.

C'est le driver du ramdisk qui fait le lien entre le volume /RAM et la mémoire additionnelle.
Il doit permettre de faire comme n'importe quel driver d'unité de stockage au standard ProDOS.
A savoir gérer les 4 commandes suivantes:


Il doit être capable de faire l'équivalence entre un numéro de block ProDOS et l'emplacement des 512 octets de datas en mémoire, c'est à dire qu'il doit être capable de trouver le couple numéro de bank + l'adresse de début de stockage des bytes dans les 64k de ce bank. Nous verrons un peu plus loin qu'en fait il y a un troisième paramètre pour quelques blocks (c'est donc un triplet et non un couple).
Nous parlerons alors des switchs des bancs commutés de 4k à ce moment là.

Pour le reste, le driver fait du classique: il échange des informations entre les banks auxiliaires et la mémoire principale en faisant des "moves" dans un sens ou dans l'autre via un buffer qui lui se trouve toujours en main memory. Ce buffer contient les octets du block à écrire (pour la commande Write) ou contiendra les octets après la lecture (commande Read). Après c'est le programme appelant qui en dispose.


08) Volume directory et volume bitmap


Commençons à présent à décrire l'organisation de la mémoire auxiliaire pour le stockage des blocks.
Avec ProDOS, il y a quelques blocks qui sont réservés à son usage propre.
Il s'agit du volume directory, c'est à dire de la liste des objets contenu sur le volume (l'équivalent des secteurs $01 à $0F de la piste $11 d'une disquette sous DOS 3.3) et la volume bitmap qui indique la liste des blocks utilisés et ceux restants libres (l'équivalent de la VTOC sous DOS 3.3).

Autant dire que ces informations sont primordiales pour la gestion du volume /RAM par ProDOS.

Ces blocks se trouvent sur le 1er bank aux se trouvant après le bank $00 aux en tenant compte des éventuelles réservations de bank.
Par exemple avec ma RamWorks III, si je ne bloque pas de banks, le catalog et le volume bitmap se trouve sur le bank $01 aux. Si j'avais dit que je voulais réserver 2 banks, ces informations seraient sur le bank $03.


L'organisation des 1er blocks du disque ram est la même que pour une disquette 5,25".
Les blocks 2 à 5 correspondent au volume directory (on ne peut dont pas stocker davantage de noms que sur une disquette!)
A raison de 13 noms par block, pour les 4 blocks 2/3/4/5, on a au maximum 4*13=52 noms auquels il convient d'en retrancher un correspondant au nom du volume, ce qui fait un maximum de 51 objets en tout sur le volume.
Le block 6 joue le role de volume bitmap. Chaque block étant codé sur un bit, comme il y a 512 octets dans le block 6, on peut y représenter 512*8=4096 blocks, ce qui correspond à 4096*512=2097152 octets <=> 2048k, soit 2 megas octets.
Le stockage des datas commencent à partir du block 7 sur le même bank.
Un block est toujours sur le même bank (il n'y a pas 256 octets sur un bank et 256 sur un autre). Le stockage se fait par page entière : l'adresse mémoire pour chaque block stocké est toujours de la forme $xy00.
Pour le lien entre numéro de block et emplacement mémoire, référez-vous au tableau de l'organisation mémoire un peu plus bas.


09) Gestion de la mémoire et taille maximale


J'ai mentionné plus haut qu'en théorie le driver accepte jusqu'à $80 banks.
Il n'y en a que $18 (=24) effectifs géré par RAM.DRV.SYSTEM.
Ces numéros de banks valides trouvés et exploitables pour le volume /RAM sont aux adresses $FFBE-$FFD5 (MEV) lorsque la mise en place du driver est achevée et aux adresses $248C-$24A3 quand RAM.DRV.SYSTEM est en cours d'exécution avant de se reloger.

Le bank $00 aux n'est pas compris dedans puisqu'exclus du ramdisk.

Ce qui correspond à un max de 24*64k=1536k pour votre disque virtuel.
Vous pouvez par exemple utiliser une carte 1024k avec une piggy-back de 512k.
Avec cette configuration, votre disque virtuel sera de 15 banks de 64k pour la carte enfichée dans le slot 3 (15*64k=960k, les 64k manquant pour atteindre les 1024 correspondent au bank $00 aux intouchable) + 8 banks pour la piggyback, soit 23 banks.

Il existe des piggy-backs d'une taille supérieure à 512k mais elles sont très très rares!
En théorie, la RamWorks III + piggyback peut atteindre les 16 megs de ram!
J'ai déjà vu passer une piggyback de 2 mégas sur ebay mais le prix final était de la folie.
En toute honneteté, à moins de manipuler des fichiers appleworks monstrueux, un usage au delà de 1,5 meg n'est pas justifié.
Si vous avez une piggyback plus importante, le driver ne pourra pas exploiter tous les banks.


Avec une carte RamWorks III de 1024k, le catalog du volume /RAM indique que je dispose au total de 1904 blocks dont 7 sont réservés et 1897 libres.
Faisons un calcul simple: j'ai 15 banks valides de 64k pour mon ramdisk.
Donc normalement, je devrais avoir 15*64*1024=983040 octets, soit en divisant par 512 un total de 1920 blocs. Or j'en ai moins. Pourquoi?

En fait, ce n'est pas aussi simple. En effet dans chaque bank aux, il y a la page 0 et la pile (page 1) qui doivent être conservées intactes car un programme peut vouloir s'en servir pour son exécution. (L'avantage de ce type de carte par rapport aux extensions de type slinky, c'est qu'un programme peut s'exécuter dessus).
Il faut donc enlever ces 2 pages, soit 512 octets c'est à dire l'équivalent d'un block ProDOS par bank. Comme j'ai 15 banks, ça me fait 15 blocks à retrancher.
On recompte: 1920 - 15 = 1905 blocks! Ce n'est toujours pas ça...
Alors c'est quoi la ruse?

Il s'avère que le mécanisme adopté consiste à faire ce retranchement par multiple de 8 banks et ce dès le 1er bank rencontré.
Donc si je ne réserve pas de bank pour un autre usage, du moment que j'ai un bank sélectionnable, sont retranchés d'office 8 blocks. Dès que l'on atteint le 9ème bank, on refait -8 blocks, etc...
Bank $01 -> -8 blocks
Bank $02
...
Bank $08
Bank $09 -> -8 blocks
Bank $0A
...
Bank $0F

Dans mon cas, il y a retranchement de 16 blocks. 1920 - 16 = 1904 blocks au total. OK!


On a vu que l'on dispose de banks auxiliaires à l'image de la ram principale.
Et il faut tenir compte de ses particularités.
Notamment l'espace réservé pour les entrées/sorties.
L'espace $C000-$CFFF (correspondant aux I/O en main memory) ne peut pas être utilisé comme zone de stockage de blocks dans un bank auxiliaire.
Si on considère un bank de 64k, on ne peut accéder qu'à l'espace $0200-$BFFF et $D000-$FFFF.
Mais tout comme en ram princ, il y a aussi la subtilité de l'espace de 4k compris entre $D000-$DFFF.
Cet espace est alloué 2 fois et on dispose de 8k au lieu de 4. Il suffit pour cela d'indiquer si on travaille avec le banc commuté 1 ou le banc commuté 2. Cette sélection se fait comme d'habitude avec les softswitchs $C08x. A noter que sans ce jeu de commutateur, c'est carrément les derniers 16k de chaque bank qui ne seraient pas exploités car l'espace $E000-$FFFF est lui aussi en "concurrence" avec la zone de même adresse contenant la ROM de l'Apple II.
D'ailleurs, ça ne m'étonnerait pas qu'il y ait certains drivers qui occultent ces 16k dans chaque bank pour ne pas à avoir à gérer ces commutateurs logiques!! Avec Glen Bredon, c'est du solide et tout l'espace possible a été utilisé.

Récapitulons. Pour chaque bank, on a:

$0000-$00FF : page 0 (reserved)
$0100-$01FF : stack  (reserved)
$0200-$BFFF : free
$C000-$CFFF : I/O    (reserved)
$D000-$DFFF : bank 1 4k free
$D000-$DFFF : bank 2 4k free
$E000-$FFFF : free


On a donc au final $FE00 octets par bank de disponible, soit $FE00/512 = 127 blocks (=$7F).

 

10) Memory map après l'exécution de RAM.DRV.SYSTEM


**********************************************************************************************************************
* Mémoire principale (aussi appelée mémoire vive ou MEV par opposition        * Mémoire auxiliaire : bank $00        *
* ==================  à la mémoire morte MEM ou ROM)                          * ==================                   *
*                                                                             *                                      *
* $0000       Début espace mémoire 64k.                                       * $0000 :0    Début espace mémoire 64k *
*                                                                             *                                      *
*                                                                             *                                      *
*                                                                             *               N                      *
*                                                                             *                                      *
* $02D0-$02E4 Espace buffer clavier ou copie de CALL_RWRDB mis en place       *               O                      *
*             à chaque appel du driver RAMDISK_DRV pour appeler la routine    *                                      *
*             RWRDB présente sur le bank choisi.                              *               T                      *
*                                                                             *                                      *
*                                                                             *                                      *
*                                                                             *                                      *
*                                                                             *               U                      *
*                                                                             *                                      *
* $8000-$81FF 512 bytes buffer for RAMDISK_DRV if the provided buffer is too  *               S                      *
*             high.                                                           *                                      *
*                                                                             *               E                      *
* ProDOS System Global Page / MLI Global Page                                 *                                      *
*                                                                             *               D                      *
* $BF16-$BF17 DEVADR31 (slot 3, drive 1 device driver address = $FF00 defaut) *                                      *
* $BF26-$BF27 DEVADR32 (slot 3, drive 2 device driver address = idem slot 0)  *               !                      *
* $BF98       MACHID (Machid ID byte) : ..11.... 128K                         *                                      *
*                                                                             *                                      *
* Banc commuté 1 MEV                                                          *                                      *
* ==================                                                          *                                      *
*                                                                             *                                      *
* $FF00-$FFBD RAMDISK_DRV (point d'entrée de la gestion de la device)         *                                      *
*             Comme tous les "storage Devices drivers" par blocks de ProDOS,  *                                      *
*             ce driver doit gérer les 4 commandes classiques: Status, Read,  *                                      *
*             Write et Format. A chaque appel R/W, swap le module CALL_RWRDB  *                                      *
*             et l'espace du buffer clavier, calcule le bank et l'adresse     *                                      *
*             mémoire, appel de CALL_RWRDB puis reswap le module CALL_RWRDB   *                                      *
*             et l'espace du buffer clavier.                                  *                                      *
* $FFBE-$FFD5 Liste des 24 banks utilisables (a, b, ...)                      *                                      *
* $FFD6-$FFEA Original du module CALL_RWRDB ou zone de swap                   *                                      *
*             avec le contenu de la partie du buffer clavier $02D0-$02E4      *                                      *
*             avant l'appel du driver.                                        *                                      *
*                                                                             *                                      *
* $FFFF       Fin espace mémoire 64k                                          * $FFFF       Fin espace mémoire 64k   *
**********************************************************************************************************************


Cartographie de la mémoire auxiliaire utilisée par /RAM avec le découpage en blocks ProDOS:

Exemple pour 3 premiers banks: a, b et c.

***************************************************************************************************************************
* Block Bank Adresse 64k   Banc           * Block Bank Adresse 64k   Banc         * Block Bank Adresse 64k   Banc         *
*       Aux                commuté        *       Aux                commuté      *       Aux                commuté      *
*                          MEV 4k         *                          MEV 4k       *                          MEV 4k       *
* -----  a   $0000-$0005     (P0)         * -----  b   $0000-$00BD     (P0)       * -----  c   $0000-$00BD     (P0)       *
* -----  a   $0006-$0008     (signat GEB) *                                       *                                       *
* -----  a   $00BE-$00F4     (RWRDB)      * -----  b   $00BE-$00F4     (RWRDB)    * -----  c   $00BE-$00F4     (RWRDB)    *
* -----  a   $00F5-$01FF     (P0/stack)   * -----  b   $00F5-$01FF     (P0/stack) * -----  c   $00F5-$01FF     (P0/stack) *
*                                         *                                       *                                       *
*                                         * + block offset $007F:                 * + block offset $007F:                 *
* $0000  a   $0200-$03FF                  * $007F  b   $0200-$03FF                * $00FE  c   $0200-$03FF                *
* $0001  a   $0400-$05FF                  * $0080  b   $0400-$05FF                * $00FF  c   $0400-$05FF                *
* $0002  a   $0600-$07FF     (volume dir) * $0081  b   $0600-$7FFF                * $0100  c   $0600-$07FF                *
* $0003  a   $0800-$09FF     (volume dir) * ...                                   * ...                                   *
* $0004  a   $0A00-$0BFF     (volume dir) *                                       *                                       *
* $0005  a   $0C00-$0DFF     (volume dir) *                                       *                                       *
* $0006  a   $0E00-$0FFF     (vol bitmap) *                                       *                                       *
* $0007  a   $1000-$11FF                  *                                       *                                       *
* $0008  a   $1200-$13FF                  *                                       *                                       *
* ...                                     *                                       *                                       *
* $000F  a   $2000-$21FF                  *                                       *                                       *
* $0017  a   $3000-$31FF                  *                                       *                                       *
* $001F  a   $4000-$41FF                  *                                       *                                       *
* $0027  a   $5000-$51FF                  *                                       *                                       *
* $002F  a   $6000-$61FF                  *                                       *                                       *
* $0037  a   $7000-$71FF                  *                                       *                                       *
* $003F  a   $8000-$81FF                  *                                       *                                       *
* $0047  a   $9000-$91FF                  *                                       *                                       *
* $004F  a   $A000-$A1FF                  *                                       *                                       *
* $0057  a   $B000-$B1FF                  *                                       *                                       *
* ...                                     *                                       *                                       *
* $005E  a   $BE00-$BFFF                  *                                       *                                       *
* $005F  a   $D000-$D1FF   2              *                                       *                                       *
* $0060  a   $D200-$D3FF   2              *                                       *                                       *
* ...                                     *                                       *                                       *
* $0066  a   $DE00-$DFFF   2              *                                       *                                       *
* $0067  a   $D000-$D1FF   1              *                                       *                                       *
* ...                                     *                                       *                                       *
* $006E  a   $DE00-$DFFF   1              *                                       *                                       *
* $006F  a   $E000-$E1FF   1 MEV          *                                       *                                       *
* ...                                     *                                       *                                       *
* $007E  a   $FE00-$FFFF   1 MEV          * $00FD  b   $FE00-$FFFF   1 MEV        * $017C  c   $FE00-$FFFF   1  MEV       *
***************************************************************************************************************************


11) Les routines du driver


Généralement quand on veut faire des échanges de données entre la ram princ et la ram auxiliaire, on utilise des sous programmes spéciaux dédiés. Je pense ici à la routine AUXMOVE en $C311.

Le problème avec cette routine, c'est qu'elle ne permet pas de copier des données dans la mémoire à banc commuté ($D000-$FFFF). Or pour RAM.DRV.SYSTEM cette zone est utilisée dans le cadre de la sauvegarde des blocks dans chaque bank aux. Il n'a donc pas été possible d'utiliser ces programmes tout fait.

Pour traiter la commande Read block (au niveau device storage driver), le programme qui fait ça doit pouvoir lire des données dans un bank auxiliaire. Et il faut obligatoirement qu'il le trouve lui même dans ce bank car un programme s'exécutant dans un bank aux ou en ram princ ne peut pas lire les infos d'un autre bank (qui peuvent se trouver n'importe où dans les 64k). Ceci explique pourquoi il a été nécessaire d'avoir dans chaque bank aux valide un bout de code pour faire ces opérations d'échange d'espaces mémoires.
Pour prendre le moins de place possible, comme on a déjà la restriction de la page 0 et de la pile, le plus économique a été de mettre cette routine en page 0 aux du bank dans un endroit qui ne dérange pas. On la trouve donc de $BE à $F4.
C'est lors de l'exécution de RAM.DRV.SYSTEM que ce code est placé dans chacun des banks valides.
J'ai donné à ce code exécuté en ram aux le nom RWRDB, ce qui est l'abrégé pour Read/Write RamDisk blocks.

La question qui se pose à présent est comment appeler cette routine RWRDB?
On pourrait se dire qu'il suffit de l'appeler depuis le point d'entrée du driver.
Or ce dernier (que j'ai appellé RAMDISK_DRV) se trouve dans la carte langage (main memory) à partir de l'adresse $FF00.
Ce n'est donc pas possible et je vous explique pourquoi.
RWRDB se trouve en page zero dans les banks aux, on l'a vu.
Pour que ce code soit exécutable, il faut que ce soit la page 0 de ce bank qui soit active.
Ceci se fait en utilisant un softswitch ALTZP (alternate zero page) et plus précisement en enclenchant le commutateur AUXZP ($C009) = auxiliary zero page. Or ce softswitch active aussi en même temps la carte langage du bank! Ce qui veut dire que le programme RAMDISK_DRV ne doit absolument pas enclencher lui-même le commutateur $C009 (AUXZP) sinon le RAMDISK_DRV en cours d'exécution est mis hors circuit: on désactive l'espace mémoire alors qu'un programme est en cours d'exécution dedans! (-> crash assuré car la prochaine instruction à exécuter se trouve dans l'espace $FFxx du bank aux qui ne contient bien sur que les données des blocks). Seul un programme en mémoire principal contenu dans l'espace $0200-$BFFF peut faire cette commutation.

C'est alors que rentre en jeu un troisième programme: CALL_RWRDB.
La seule fonction de ce programme est de faire le relai entre RAMDISK_DRV et le RWRDB du bank aux contenant les datas.
Or en ram princ la place est "cher" (surtout elle est réservée pour les programmes utilisateurs) et il est hors de question d'avoir un programme système en permanence dans cet espace.
D'où la solution utilisée par Glen Bredon qui consiste à n'avoir cette routine CALL_RWRDB en ram princ qu'au moment où on en a besoin. Quand RAMDISK_DRV veut appeler RWRDB, il fait un swap entre une partie du buffer clavier ($02D0-$02E4) et la routine d'origine CALL_RWRDB stockée avec RAMDISK_DRV à partir de $FFD6. Ceci permet de ne pas écraser ce qui pouvait se trouver dans cette partie du buffer clavier.
Ca veut aussi dire que si un programme a besoin de lire 15 blocks de datas à la suite les uns des autres, alors RAMDISK_DRV est sollicité 15 fois et ce swap aura lieu 2*15 fois de suite. En effet quand la routine CALL_RWRDB a été exécutée et que RAMDISK_DRV n'en a plus besoin, il remet en place le contenu du buffer clavier d'origine et reloge sa routine CALL_RWRDB en lieu sur.
Ca fait beaucoup de va et vient de mémoire, mais c'est le prix à payer pour avoir la compatibilité avec les anciennes versions Apple II et Apple II+ avec leur gestion de carte langage.

Pour vous aidez à vous y retrouver, voici un schéma de la mémoire avec 3 banks de la RamWorks ($00, a et b) et les bancs commutés en MEV (carte langage dans chaque bank ainsi qu'en main memory):

Memory map


Les routines RWRDB et CALL_RWRDB répondent à l'image "short is beautiful".
Elles ne font que le strict minimum qui leur est demandé.
C'est le programme RAMDISK_DRV qui fait le reste comme la partie très importante du lien entre block ProDOS et le triplet (numéro bank aux/adresse début stockage du block dans les 64k du bank/éventuel numéro de banc commuté si le block ProDOS est dans l'espace de banc commuté de 4k de la carte langage auxiliaire $D000-$DFFF).
Pour le mapping blocks/adresses en bank aux, il est à noter que le banc commuté de 4k numéro 2 se substitue à l'espace $C000-$CFFF et que par défaut l'emplace $D000-$DFFF correspond au banc commuté de 4k numéro 1.

Chronologie d'un exec du driver de la device (dans la plupart des cas):

- Appel du driver RAMDISK_DRV.
- Inits et calculs.
- Swap partie buffer clavier et CALL_RWRDB pour avoir cette dernière routine en page 2 de la ram princ.
- RAMDISK_DRV fait un call de la routine CALL_RWRDB.
- CALL_RWRDB commute la page 0 aux du bank sélectionné (et met RAMDISK_DRV hors fonction, status language card = disable).
- CALL_RWRDB appelle RWRDB.
- RWRDB fait l'opération read ou write.
- Retour à CALL_RWRDB.
- CALL_RWRDB reconnecte RAMDISK_DRV et active la page 0 en ram princ.
- Retour à RAMDISK_DRV.
- RAMDISK_DRV refait le swap buffer clavier/routine CALL_RWRDB pour remettre la configuration initiale.

12) Driver /RAM et émulateurs


Le seul émulateur que j'utilise qui autorise plus de 128k, c'est Apple Oasis.
On peut s'octroyer jusqu'à 1 meg.
(Ne pas oublier de faire un save après la modif, de quitter l'émulo puis de le relancer!)
RAM.DRV.SYSTEM permet donc d'avoir en ligne un volume /RAM comme avec ma RamWorks III.
Sauf que lui émule avec 1024k une RamWorks originale doté de 512k et son piggy-back de 512k.

On obtient les mêmes numéros de banks pour l'utilisation du ramdisk, à savoir de $01 à $0F.

Voila à quoi ressemble cette carte et son add-on (il s'agit ici de contrefaçon taïwanaise, mais ça vous donne une idée -il ne manque que la signature du constructeur!)

RamWorks originale & piggy-back
RamWorks originale & piggy-back
RamWorks originale & piggy-back
RamWorks originale & piggy-back
RamWorks originale & piggy-back
RamWorks originale & piggy-back



hr Ramworks


AppleWorks 3 Expander
Ramcards Tests


Floppy
ProDOS
Download RAM.DRV.SYSTEM source code (gzipped)

File: Ram_Drv_System.dsk
Disk: ProDOS /ABOUT.RAM (140KB)
 Name                             Type Auxtyp Modified         Format   Length
------------------------------------------------------------------------------
 PRODOS                           SYS  $0000  04-Mar-92 23:00  ProDOS    17128
 RAM.DRV.SYSTEM                   SYS  $2000  26-May-92 21:27  ProDOS     1209
 BASIC.SYSTEM                     SYS  $2000  13-Feb-92 01:00  ProDOS    10240
 RAM.DRV.SYST.S                   TXT  $0000  06-Jul-06 00:27  ProDOS    26023
------------------------------------------------------------------------------


Ram testing...


13) Source assemblé




:asm
                1   
                2             ORG   $2000     
                3             TYP   $FF       
                4   
                5    ********************************
                6    *                              *
                7    *  RAM.DRV.SYSTEM (type SYS)   *
                8    *    Driver ProDOS carte Ram   *
                9    *  RamWorks & Checkmate Tech   *
                10   *  (c) Glen Bredon (Prosel-8)  *
                11   *     Source by Deckard        *
                12   * http://underground2e.free.fr *
                13   *                              *
                14   ********************************
                15  
                16   * Assembleur: Merlin-8 2.58 (ProDOS)
                17   * Last update: 06 jul 2006
                18  
                19   ********************************
                20  
                21   * Commandes MLI
                22  
                23   QUIT     =     $65       
                24   GET_FILE_INFO = $C4      
                25   ONLINE   =     $C5       
                26   OPEN     =     $C8       
                27   READ     =     $CA       
                28   CLOSE    =     $CC       
                29   GET_EOF  =     $D1       
                30  
                31   * Page 0 main memory
                32   * Parameters device driver
                33  
                34   DRV_COMMAND EQU $42       ; command
                35   DRV_BUFFL EQU  $44        ; buffer low main mem pour read/write
                36   DRV_BUFFH EQU  $45        ; buffer high main mem pour read/write
                37   DRV_BLKL EQU   $46        ; block low à lire ou écrire
                38   DRV_BLKH EQU   $47        ; block high à lire ou écrire
                39  
                40   * Ram princ
                41  
                42   ONLINE_BUF EQU $0220      ; $0220-$022F Buffer MLI Online
                43   BANK_OK  EQU   $248C      ; $18 octets ($248C-$24A3) Liste des banks retenus
                44                             ; pour le disk virtuel de ram. Cette liste est movée
                45                             ; dans l'espace $FFBE-$FFD5 du driver ramdisk. Les
                46                             ; numéros des banks ne sont pas forcément
                47                             ; chronologiques.
                48   WRK_NB_LCK_BK EQU $24B9   ; zone de travail nombre de banks bloqués
                49   LAST_BLK_LCK EQU $24BA    ; borne dernier bank bloqué
                50   BANK_LST EQU   $24BB      ; $80 octets stockage des banks ($FF=bad bank)
                51                             ; No locked banks in this buffer (excluded)
                52   BANK_LST_ALL EQU $253B    ; $80 octets stockage des banks ($FF=bad bank)
                53                             ; all banks in this buffer (incl. locked banks)
                54   SAV_BYTE_00 EQU $25BB     ; sauvegarde des octets $00 des $80 banks
                55   SAV_BYTE_01 EQU $263B     ; sauvegarde des octets $01 des $80 banks
                56  
                57   * Ram aux (1er bank aux valide différent de bank $00)
                58  
                59   RAM_BLK0002L EQU $0600    ; block 2 : volume dir
                60   RAM_BLK0002H EQU $0700   
                61   RAM_BLK0003L EQU $0800    ; block 3 : volume dir
                62   RAM_BLK0003H EQU $0900   
                63   RAM_BLK0004L EQU $0A00    ; block 4 : volume dir
                64   RAM_BLK0004H EQU $0B00   
                65   RAM_BLK0005L EQU $0C00    ; block 5 : volume dir
                66   RAM_BLK0005H EQU $0D00   
                67   RAM_BLK0006L EQU $0E00    ; block 6 : volume bitmap
                68   RAM_BLK0006H EQU $0F00   
                69   RAM_BLK0007L EQU $1000    ; block 7 : adresse début des datas
                70  
                71   * Adresses ProDOS
                72  
                73   MLI      EQU   $BF00      ; appel MLI ProDOS
                74   DEVADR01 EQU   $BF10      ; début des devices addresses (slot 0, drive 1)
                75   DEVADR32 EQU   $BF26      ; addr device driver slot 3, drive 2 (/RAM)
                76   DEVCNT   EQU   $BF31      ; Count (minus 1) of active devices
                77   DEVLST   EQU   $BF32      ; List if active devices (Slot, drive, id =DSSSIIII)
                78   DATE     EQU   $BF90      ; date/time sur 4 octets
                79  
                80   * Softswitchs
                81  
                82   _80STORE0 EQU  $C000      ; utilise main/aux read/wrt
                83   _80STORE1 EQU  $C001      ; accès page affich
                84   MAINREAD EQU   $C002      ; lecture en mémoire principale
                85   AUXREAD  EQU   $C003      ; lecture en ram aux
                86   MAINWRT  EQU   $C004      ; écriture en main memory
                87   AUXWRT   EQU   $C005      ; écriture en ram aux
                88   MAINZP   EQU   $C008      ; page 0 main memory (ALTZP) + RAMDISK_DRV on
                89   AUXZP    EQU   $C009      ; page 0 ram aux (ALTZP) + RAMDISK_DRV off
                90   RZPSW    EQU   $C016      ; lecture état ALTZP - read zero page switch
                91   R80ST    EQU   $C018      ; read 80STORE
                92   BUTTN1   EQU   $C062      ; touche pomme-fermée=closed-apple (option)
                93   BANKSEL  EQU   $C073      ; bank switching selector (ramworks et compatibles)
                94                             ; ou aussi appelé bank select register.
                95  
                96   ********************************
                97  
2000: 4C E1 20  98   H2000    JMP   H20E1      ; jump start
                99  
                100  *-------------------------------
                101  * Ram driver parameters
                102  *-------------------------------
                103 
2003: EE EE     104           HEX   EEEE       ; header id for launcher (used by Block.Warden)
2005: 40        105           DFB   64         ; length of pathname buffer
                106 
                107                            ; you have to change the following label to use it
                108                            ; with your own disk!
2006: 17 2F 41  109  NEXT_SYS STR   '/ABOUT.RAM/BASIC.SYSTEM'
2009: 42 4F 55 54
200D: 2E 52 41 4D
2011: 2F 42 41 53
2015: 49 43 2E 53
2019: 59 53 54 45
201D: 4D
201E: 00 00 00  110           DS    40,0      
2021: 00 00 00 00
2025: 00 00 00 00
2029: 00 00 00 00
202D: 00 00 00 00
2031: 00 00 00 00
2035: 00 00 00 00
2039: 00 00 00 00
203D: 00 00 00 00
2041: 00 00 00 00
2045: 00
                111 
2046: FF FF     112           HEX   FFFF       ; borne butoire pathname buffer
                113                            ; not used (because len=64 here)
                114 
2048: 00        115  NB_LOCKED_BK DFB 0        ; nbr de banks bloqués (préservation usage user)
                116                            ; lock out how many 64k banks of ramcard memory
                117                            ; YOU CAN CHANGE IT!!
                118 
2049: 03        119  MAP_SLOT_DRV DFB %00000011 ; (drive*8)-8 + slot -> drive 1, slot 3 (default)
                120                            ; mapping slot and drive 0000DSSS
                121                            ; D : 0=drive 1, 1=drive 2 / SSS=slot number
                122                            ; YOU CAN CHANGE IT!!
                123 
                124  ********************************
                125  *                              *
                126  * Prise en compte du prochain  *
                127  *    .SYS mentionné en dur     *
                128  *                              *
                129  ********************************
                130 
                131  * Run next SYS program
                132 
                133  HBD00                    
                134 
                135           ORG   $BD00     
                136 
BD00: AE 06 20  137           LDX   NEXT_SYS   ; longueur next SYSTEM
BD03: F0 5E     138           BEQ   :2         ; pas de nom mentionné
                139 
BD05: BD 06 20  140  :1       LDA   NEXT_SYS,X ; recopie du nom en page 2 (buffer clavier)
BD08: 9D 80 02  141           STA   $0280,X   
BD0B: CA        142           DEX             
BD0C: 10 F7     143           BPL   :1        
                144 
BD0E: 20 00 BF  145           JSR   MLI        ; récupère les infos de cet objet
BD11: C4        146           DFB   GET_FILE_INFO
BD12: 70 BD     147           DA    TBL_GET_F_I
BD14: B0 4D     148           BCS   :2         ; err->quit
                149 
BD16: AE 74 BD  150           LDX   FILE_TYPE  ; $FF (=system)+1
BD19: E8        151           INX             
BD1A: D0 47     152           BNE   :2         ; pas un type SYS
                153 
BD1C: 20 00 BF  154           JSR   MLI        ; ouverture du SYS
BD1F: C8        155           DFB   OPEN      
BD20: 82 BD     156           DA    TBL_OPEN  
BD22: B0 39     157           BCS   :3         ; err->quit
                158 
BD24: AD 87 BD  159           LDA   OPEN_NUM   ; dispatch le numéro du fichier
BD27: 8D 8B BD  160           STA   READ_NUM  
BD2A: 8D 93 BD  161           STA   GET_EOF_NUM
                162 
BD2D: 20 00 BF  163           JSR   MLI        ; recherche fin du fichier SYS
BD30: D1        164           DFB   GET_EOF   
BD31: 92 BD     165           DA    TBL_GET_EOF
BD33: B0 28     166           BCS   :3        
                167 
BD35: AD 96 BD  168           LDA   EOF_POS+2  ; 3 octets de taille?
BD38: D0 23     169           BNE   :3         ; si oui, trop gros ->err
                170 
BD3A: AD 95 BD  171           LDA   EOF_POS+1  ; check taille high
BD3D: C9 98     172           CMP   #>$9800    ; $2000+9800
BD3F: B0 1C     173           BCS   :3         ; encore trop long
                174 
BD41: 8D 8F BD  175           STA   READ_REQ_LEN+1 ; parm read
BD44: AD 94 BD  176           LDA   EOF_POS   
BD47: 8D 8E BD  177           STA   READ_REQ_LEN
                178 
BD4A: 20 00 BF  179           JSR   MLI        ; charge le SYS en $2000
BD4D: CA        180           DFB   READ      
BD4E: 8A BD     181           DA    TBL_READ  
BD50: B0 0B     182           BCS   :3         ; err->quit
                183 
BD52: 20 00 BF  184           JSR   MLI       
BD55: CC        185           DFB   CLOSE     
BD56: 88 BD     186           DA    TBL_CLOSE 
BD58: B0 03     187           BCS   :3         ; err->re-try close+quit
                188 
BD5A: 4C 00 20  189           JMP   $2000      ; lance du .SYSTEM
                190 
BD5D: 20 00 BF  191  :3       JSR   MLI        ; passe la main
BD60: CC        192           DFB   CLOSE     
BD61: 88 BD     193           DA    TBL_CLOSE 
                194 
BD63: 20 00 BF  195  :2       JSR   MLI        ; passe la main
BD66: 65        196           DFB   QUIT      
BD67: 69 BD     197           DA    TBL_QUIT  
                198 
                199  *-------------------------------
                200 
                201  * Parameters Quit
                202 
BD69: 04        203  TBL_QUIT DFB   4         
BD6A: 00 00 00  204           DS    6,0       
BD6D: 00 00 00
                205 
                206  * Parameters Get File Info
                207 
BD70: 0A        208  TBL_GET_F_I DFB $0A      
BD71: 80 02     209           DA    $0280     
BD73: 00        210           DFB   0         
BD74: 00        211  FILE_TYPE DFB  0          ; file type
BD75: 00 00 00  212           DS    13,0      
BD78: 00 00 00 00
BD7C: 00 00 00 00
BD80: 00 00
                213 
                214  * Parameters Open
                215 
BD82: 03        216  TBL_OPEN DFB   $03       
BD83: 80 02     217           DA    $0280     
BD85: 00 1C     218           DA    $1C00     
BD87: 00        219  OPEN_NUM DFB   0         
                220 
                221  * Parameters Close
                222 
BD88: 01        223  TBL_CLOSE DFB  1         
BD89: 00        224  CLOSE_NUM DFB  0         
                225 
                226  * Parameters Read
                227 
BD8A: 04        228  TBL_READ DFB   4         
BD8B: 00        229  READ_NUM DFB   0         
BD8C: 00 20     230           DA    $2000      ; adresse implantation
BD8E: 00 00     231  READ_REQ_LEN DS 2,0      
BD90: 00 00     232           DS    2,0       
                233 
                234  * Parameters Get Eof
                235 
BD92: 02        236  TBL_GET_EOF DFB 2        
BD93: 00        237  GET_EOF_NUM DFB 0        
BD94: 00 00 00  238  EOF_POS  DS    3,0       
                239 
                240  ********************************
                241  *                              *
                242  *  Point d'entrée de RAM.DRV   *
                243  *                              *
                244  ********************************
                245 
                246           ORG             
                247                            ; $20E1
                248  *-------------------------------
                249  * Reloge le code de chargement
                250  * du prochain SYS en $BD00
                251  *-------------------------------
                252 
20E1: A0 00     253  H20E1    LDY   #0        
20E3: B9 4A 20  254  :1       LDA   HBD00,Y   
20E6: 99 00 BD  255           STA   $BD00,Y   
20E9: C8        256           INY             
20EA: D0 F7     257           BNE   :1        
                258 
                259  *-------------------------------
                260  * Get ram size
                261  *-------------------------------
                262 
20EC: 8D 00 C0  263  H20EC    STA   _80STORE0  ; utilise ramread/ramwrite
20EF: A0 00     264           LDY   #0        
20F1: 8C 73 C0  265           STY   BANKSEL    ; bank 0
20F4: 8D 09 C0  266           STA   AUXZP      ; utilise page 0 aux
                267 
20F7: A9 FF     268           LDA   #$FF       ; init les 2 buffers de $80 octets avec les listes
20F9: 99 BB 24  269  H20F9    STA   BANK_LST,Y ; des banks ($FF=bad bank) locked et all.
20FC: C8        270           INY              ; 2*$80 = $100
20FD: D0 FA     271           BNE   H20F9     
                272                            ; Y=0
                273  * Backup adresses $00/$01 de chaque bank
                274  * car ces adresses sont écrasées pour le test
                275 
                276                            ; start: bank 0 aux ($00/$01 page 0 princ not saved)
20FF: 8C 73 C0  277  H20FF    STY   BANKSEL    ; enclenche bank Y
2102: A5 00     278           LDA   $00        ; backup $00 addr in buffer
2104: 99 BB 25  279           STA   SAV_BYTE_00,Y
2107: A5 01     280           LDA   $01        ; backup $01 addr in buffer
2109: 99 3B 26  281           STA   SAV_BYTE_01,Y
210C: C8        282           INY              ; for $80 banks ($00-$7F)
210D: 10 F0     283           BPL   H20FF     
                284 
                285  * Pour tester si un bank est valide, on l'enclenche
                286  * en écrivant son numéro à l'adresse spéciale $c073
                287  * puis on écrit dedans à un endroit particulier. Si la
                288  * relecture au meme endroit donne le meme résultat,
                289  * cela veut dire que le bank est ok. Ici le test est
                290  * réalisé en page 0 sur les octets $00 et $01.
                291 
                292  * Phase d'écriture
                293 
210F: 88        294           DEY              ; Y=$7F
2110: 8C 73 C0  295  H2110    STY   BANKSEL   
2113: 84 00     296           STY   $00        ; écrit le numéro du bank dans $00 (page 0 aux)
2115: 98        297           TYA             
2116: 49 FF     298           EOR   #$FF      
2118: 85 01     299           STA   $01        ; écrit le checksum (=num bank eor #$FF) dans $01
211A: 88        300           DEY              ; pour $80-1 banks
211B: D0 F3     301           BNE   H2110      ; ne fait pas le bank 0 aux ici
                302 
                303                            ; Y=0 : fait le bank 0 ici car il faut faire
                304                            ; aux et princ
                305 
211D: 8C 73 C0  306           STY   BANKSEL    ; fait le bank 0 aux
2120: 84 00     307           STY   $00       
2122: 84 01     308           STY   $01        ; no eor
2124: 8D 08 C0  309           STA   MAINZP     ; puis la page 0 princ
2127: 84 00     310           STY   $00       
2129: 84 01     311           STY   $01        ; no eor
                312 
212B: 8D 09 C0  313           STA   AUXZP      ; repasse en page 0 aux
                314 
212E: AD 48 20  315           LDA   NB_LOCKED_BK ; place le nb de banks bloqués dans la zone
2131: 8D B9 24  316           STA   WRK_NB_LCK_BK ; de travail qu'on décrémentera à fur et à mesure
                317 
                318  * Phase de lecture et controle résultat
                319 
2134: A0 01     320           LDY   #1         ; skip bank 0 aux (préservé)
2136: 8C 73 C0  321  H2136    STY   BANKSEL    ; enclenche bank Y
2139: C4 00     322           CPY   $00        ; compare avec valeur stockée précedemment
213B: D0 29     323           BNE   H2166      ; pas pareil -> bad bank
                324 
213D: 98        325           TYA             
213E: 49 FF     326           EOR   #$FF      
2140: 45 01     327           EOR   $01        ; compare checksum avec valeur sauvée
2142: D0 22     328           BNE   H2166      ; pas pareil -> bad bank
                329 
2144: C4 00     330           CPY   $00        ; check $00/$01
2146: D0 1E     331           BNE   H2166      ; toujours pas bon -> écarte ce bank aux
                332 
2148: 98        333           TYA              ; signale que le bank est valide dans la liste ALL
2149: 99 3B 25  334           STA   BANK_LST_ALL,Y ; stockage numéro
                335 
214C: AE B9 24  336           LDX   WRK_NB_LCK_BK ; reste-il des banks bloqués?
214F: D0 03     337           BNE   H2154      ; oui
                338 
2151: 8D BA 24  339           STA   LAST_BLK_LCK ; non -> set borne dernier bank bloqué
                340 
2154: CE B9 24  341  H2154    DEC   WRK_NB_LCK_BK ; un bank bloqué en moins
2157: 10 0D     342           BPL   H2166      ; il y en a encore
                343 
2159: 99 BB 24  344           STA   BANK_LST,Y ; sauve le bank dans la liste restreinte
                345 
                346  * Recopie à partir de $00B0 la routine RWRDB
                347  * dans ce bank aux valide
                348 
215C: A2 45     349           LDX   #$45      
215E: BD 54 23  350  H215E    LDA   H2355-1,X 
2161: 95 AF     351           STA   $B0-1,X   
2163: CA        352           DEX             
2164: D0 F8     353           BNE   H215E     
                354 
2166: C8        355  H2166    INY              ; passe au bank suivant
2167: 10 CD     356           BPL   H2136      ; fait banks aux $01 à $7F
                357 
                358  * Restauration des données altérées dans chaque bank
                359  * aux valide aux addr $00 et $01
                360 
                361                            ; Y=$80
2169: B9 3A 25  362  H2169    LDA   BANK_LST_ALL-1,Y ; bank valide (<$80)?
216C: 30 12     363           BMI   H2180      ; non: bad bank ($FF)
                364 
216E: CD BA 24  365           CMP   LAST_BLK_LCK ; est-ce la borne bank bloqué?
2171: F0 0D     366           BEQ   H2180      ; oui, ne fait pas les restaurations
                367 
2173: 8D 73 C0  368           STA   BANKSEL    ; enclenche bank acc
2176: B9 BA 25  369           LDA   SAV_BYTE_00-1,Y ; restore addr $00 previously saved
2179: 85 00     370           STA   $00       
217B: B9 3A 26  371           LDA   SAV_BYTE_01-1,Y ; idem adr $01
217E: 85 01     372           STA   $01       
                373 
2180: 88        374  H2180    DEY              ; bank précédant
2181: D0 E6     375           BNE   H2169      ; ne fait pas le bank 0 aux
                376                            ; Y=0
2183: 8C 73 C0  377           STY   BANKSEL    ; enclenche bank 0
2186: 84 00     378           STY   $00        ; marque le bank 0 aux
                379 
                380  * Récupère la liste finale des banks valides
                381  * pour avoir les numéros regroupés. On se restreint
                382  * à la liste des banks aux valides éligibles.
                383 
2188: A2 FF     384           LDX   #$FF       ; X -> $FF+1=0
218A: E8        385  H218A    INX              ; indice sur BANK_OK
218B: E0 18     386           CPX   #$18       ; dernier bank accepté?
218D: B0 0D     387           BCS   H219C      ; oui, on arrete là (>=)
                388 
                389                            ; skip bank 0 aux
218F: C8        390  H218F    INY              ; bank suivant
2190: 30 0A     391           BMI   H219C      ; fin car on vient de parcourir $80 banks
                392 
2192: B9 BB 24  393           LDA   BANK_LST,Y ; bank valide?
2195: 30 F8     394           BMI   H218F      ; non ($FF)
                395 
2197: 9D 8C 24  396           STA   BANK_OK,X  ; ajoute à la liste finale
219A: 10 EE     397           BPL   H218A      ; toujours
                398 
                399  * Calcul du nbr de blocks
                400  * Nbr de bank * 128 (- 8 blocks tous les 8 banks en
                401  * commançant dès le 1er bank).
                402  * Si 01 bank  ->  1*128 - 8 blocks  = 120 blocks total
                403  * Si 02 banks ->  2*128 - 8 blocks  = 248
                404  * etc...
                405  * Si 08 banks ->  8*128 - 8 blocks  = 1016
                406  * Si 09 banks ->  9*128 - 16 blocks = 1136
                407  * etc...
                408  * Si 24 banks -> 24*128 - 24 blocks = 3048
                409  *
                410  * Les blocks réservés (par lot de 8) correspondent aux pages
                411  * 0 et 1 (pile=stack) de chaque bank.
                412 
                413                            ; X=nbr de banks dans la liste
219C: 8A        414  H219C    TXA              ; nbr de blocks * 128
219D: 4A        415           LSR             
219E: 8D CD 23  416           STA   VOL_TOT_BLK+1 ; high
21A1: 6E CC 23  417           ROR   VOL_TOT_BLK
21A4: 8E 24 24  418           STX   HFF55+1    ; sauve nbr de banks valides
21A7: CA        419           DEX             
21A8: 8E 9E 23  420           STX   H239E      ; sauve nbr de banks-1
21AB: 30 38     421           BMI   GO_QUIT    ; aucun bank valide réservable pour le ramdisk
                422 
21AD: AD CC 23  423           LDA   VOL_TOT_BLK ; -nb de bank
21B0: 38        424           SEC             
21B1: ED 24 24  425           SBC   HFF55+1   
21B4: 29 F8     426           AND   #%11111000
21B6: 8D CC 23  427           STA   VOL_TOT_BLK ; low
21B9: 8D D4 23  428           STA   RWB_ST_BLKL+1
21BC: B0 03     429           BCS   H21C1     
                430 
21BE: CE CD 23  431           DEC   VOL_TOT_BLK+1 ; high
                432 
21C1: AD CD 23  433  H21C1    LDA   VOL_TOT_BLK+1
21C4: 8D D6 23  434           STA   RWB_ST_BLKH+1
                435 
21C7: AD 8C 24  436           LDA   BANK_OK    ; positionne sur le 1er bank aux valide qui est
21CA: 8D 73 C0  437           STA   BANKSEL    ; différent du bank 0 aux.
21CD: A5 00     438           LDA   $00        ; check si un moins un bank. Bank 0 aux interdit.
21CF: F0 14     439           BEQ   GO_QUIT    ; aucun bank! On s'arrete ici.
                440 
                441 
                442  *-------------------------------
                443  * Préparation volume /RAM
                444  *-------------------------------
                445 
                446  * Laisse une trace dans le 1er bank aux valide pour identifier
                447  * le driver en place (signature avec nom de l'auteur!)
                448 
21D1: A2 02     449           LDX   #2         ; check signature bank aux
21D3: BD A0 23  450  H21D3    LDA   H23A0,X    ; trigramme nom de l'auteur
21D6: D5 06     451           CMP   $06,X      ; existe déja?
21D8: D0 11     452           BNE   H21EB      ; pas encore signé. Préparation du volume à faire.
                453 
21DA: CA        454           DEX              ; caractère suivant
21DB: 10 F6     455           BPL   H21D3     
                456                            ; la signature est présente. Donc normalement
                457                            ; ce volume a déja été formatté logiquement.
                458                            ; Néanmoins, l'utilisateur peut demander à forcer
                459                            ; un reformattage. Teste la touche spéciale.
                460                            ; X=$FF
21DD: 2C 62 C0  461           BIT   BUTTN1     ; test touche pomme-fermée=closed-apple (option)
21E0: 30 0E     462           BMI   RAM_FORMAT ; oui, touche enfoncée -> formattage demandé
                463 
21E2: 4C 76 22  464           JMP   H2276      ; laisse en état et passe à la suite.
                465 
21E5: 4C 4F 23  466  GO_QUIT  JMP   RAMDISK_QUIT
                467 
21E8: BD A0 23  468  H21E8    LDA   H23A0,X    ; set signature
21EB: 95 06     469  H21EB    STA   $06,X      ; page 0 1er bank aux valide de la liste
21ED: CA        470           DEX             
21EE: 10 F8     471           BPL   H21E8     
                472 
                473  * Formattage du ram disk
                474 
21F0: 8D 08 C0  475  RAM_FORMAT STA MAINZP    
21F3: A0 03     476           LDY   #3         ; date/time volume
21F5: B9 90 BF  477  H21F5    LDA   DATE,Y     ; donnée par la prodos system global page
21F8: 99 BF 23  478           STA   VOL_DATETIME,Y
21FB: 88        479           DEY             
21FC: 10 F7     480           BPL   H21F5      ; >=0
                481 
21FE: 8D 05 C0  482           STA   AUXWRT     ; écriture bank aux
2201: C8        483           INY              ; Y=0
2202: 98        484           TYA              ; acc=0. Ecrase blocks 2 à 6.
2203: 99 00 06  485  H2203    STA   RAM_BLK0002L,Y
2206: 99 00 07  486           STA   RAM_BLK0002H,Y
2209: 99 00 08  487           STA   RAM_BLK0003L,Y
220C: 99 00 09  488           STA   RAM_BLK0003H,Y
220F: 99 00 0A  489           STA   RAM_BLK0004L,Y
2212: 99 00 0B  490           STA   RAM_BLK0004H,Y
2215: 99 00 0C  491           STA   RAM_BLK0005L,Y
2218: 99 00 0D  492           STA   RAM_BLK0005H,Y
221B: 99 00 0E  493           STA   RAM_BLK0006L,Y
221E: 99 00 0F  494           STA   RAM_BLK0006H,Y
2221: C8        495           INY             
2222: D0 DF     496           BNE   H2203     
                497 
2224: A0 2A     498           LDY   #$2A       ; copie infos volume sur block 2
2226: B9 A3 23  499  H2226    LDA   VOL_DIR_HEAD,Y
2229: 99 00 06  500           STA   RAM_BLK0002L,Y
222C: 88        501           DEY             
222D: 10 F7     502           BPL   H2226     
                503 
                504  * Effectue le chainage des blocks du volume dir
                505 
222F: A0 02     506           LDY   #<$0002    ; previous block=2 on block 3
2231: 8C 00 08  507           STY   RAM_BLK0003L
2234: C8        508           INY             
2235: 8C 00 0A  509           STY   RAM_BLK0004L ; previous block=3 on block 4
2238: C8        510           INY             
2239: 8C 00 0C  511           STY   RAM_BLK0005L ; previous block=4 on block 5
223C: 8C 02 08  512           STY   RAM_BLK0003L+2 ; next block=4 on block 3
223F: C8        513           INY             
2240: 8C 02 0A  514           STY   RAM_BLK0004L+2 ; next block=5 on block 4
                515 
                516  * Alimente la volume bitmap (block 6)
                517 
2243: AD CC 23  518           LDA   VOL_TOT_BLK ; nbr de blocs * 8
2246: 85 3C     519           STA   $3C       
2248: AD CD 23  520           LDA   VOL_TOT_BLK+1
224B: 4A        521           LSR             
224C: 66 3C     522           ROR   $3C       
224E: 4A        523           LSR             
224F: 66 3C     524           ROR   $3C       
2251: 4A        525           LSR             
2252: 66 3C     526           ROR   $3C       
2254: 18        527           CLC             
2255: 69 0E     528           ADC   #>RAM_BLK0006L ; + adr début volume bitmap
2257: 85 3D     529           STA   $3D       
                530 
2259: A0 00     531           LDY   #0         ; au dela de l'espace des blocks du volume
225B: 98        532           TYA              ; force les 8 blocks suivant à l'état occupé
225C: 91 3C     533  H225C    STA   ($3C),Y    ; acc=0 (used) ou $FF (free)
225E: A5 3C     534           LDA   $3C        ; octet de la volume bitmap précédant
2260: 38        535           SEC             
2261: E9 01     536           SBC   #$01      
2263: 85 3C     537           STA   $3C       
2265: A9 FF     538           LDA   #$FF       ; 8 blocks libres
2267: B0 F3     539           BCS   H225C      ; tout le reste est free
                540 
2269: C6 3D     541           DEC   $3D       
226B: A6 3D     542           LDX   $3D       
226D: E0 0E     543           CPX   #>RAM_BLK0006L
226F: B0 EB     544           BCS   H225C      ; fait toute la volume bitmap en "free"
                545                            ; pour finir:
2271: A9 01     546           LDA   #%00000001 ; signale que les blocks 0 à 6 sont bloqués dans
2273: 8D 00 0E  547           STA   RAM_BLK0006L ; la volume bitmap.
                548                            ; Vous noterez que rien n'a été fait sur les blocks
                549                            ; 0 et 1 de l'unité ramdisk
                550 
                551  *-------------------------------
                552  * Mise en place du driver
                553  *-------------------------------
                554 
2276: A9 00     555  H2276    LDA   #0        
2278: 8D 04 C0  556           STA   MAINWRT   
227B: 8D 08 C0  557           STA   MAINZP    
227E: 8D 73 C0  558           STA   BANKSEL    ; bank 0 carte ram
2281: 2C 8B C0  559           BIT   $C08B      ; bank 1 -> utilise MEV (RAMDISK_DRV on)
2284: 2C 8B C0  560           BIT   $C08B      ; first bit: read allowed. Second bit: write allowed.
                561 
2287: A9 D8     562           LDA   #$D8       ; check 'CLD' (ID début driver)
2289: CD 00 FF  563           CMP   RAMDISK_DRV ; un driver déja en place? En MEV princ par défaut
228C: F0 10     564           BEQ   H229E      ; oui
                565 
228E: 8D 09 C0  566           STA   AUXZP      ; MEV bank aux 0. Au cas où le driver a été mis
2291: CD 00 FF  567           CMP   RAMDISK_DRV ; en ram aux bank 0 pour une raison quelconque...
2294: F0 08     568           BEQ   H229E      ; oui. On garde page 0 aux et carte langage aux.
                569 
2296: CD 00 DE  570           CMP   $DE00      ; routine MLI main entry point en place en ram aux?
2299: F0 03     571           BEQ   H229E      ; oui
                572 
229B: 8D 08 C0  573           STA   MAINZP     ; recopie le driver en MEV princ
                574 
229E: A0 00     575  H229E    LDY   #0        
22A0: B9 CE 23  576  H22A0    LDA   H23CE,Y   
22A3: 99 00 FF  577           STA   RAMDISK_DRV,Y ; RAMDISK_DRV en carte langage
22A6: C8        578           INY             
22A7: C0 EB     579           CPY   #$EB      
22A9: 90 F5     580           BCC   H22A0      ; si Y < #$EB
                581 
22AB: AC 31 BF  582           LDY   DEVCNT     ; recherche dans les devices actives le slot/drive
22AE: B9 32 BF  583  H22AE    LDA   DEVLST,Y   ; défini pour le mapping du disk virtuel
22B1: 4A        584           LSR              ; format device=DSSSIIII
22B2: 4A        585           LSR              ; -> 0000DSSS
22B3: 4A        586           LSR             
22B4: 4A        587           LSR             
22B5: CD 49 20  588           CMP   MAP_SLOT_DRV ; est-ce cette device?
22B8: F0 12     589           BEQ   H22CC      ; oui
                590 
22BA: 88        591           DEY              ; passe à la device précédante
22BB: 10 F1     592           BPL   H22AE     
                593                            ; la device n'est pas active
22BD: EE 31 BF  594           INC   DEVCNT     ; on l'ajoute à la liste
                595 
22C0: AC 31 BF  596           LDY   DEVCNT     ; décalage des devices pour inclure la nouvelle
22C3: B9 31 BF  597  H22C3    LDA   DEVLST-1,Y
22C6: 99 32 BF  598           STA   DEVLST,Y  
22C9: 88        599           DEY             
22CA: D0 F7     600           BNE   H22C3     
                601                            ; Y=0
22CC: AD 49 20  602  H22CC    LDA   MAP_SLOT_DRV ; transforme 0000DSSS en DSSS0000
22CF: 0A        603           ASL              ; D=0 -> drive 1, D=1 -> drive2
22D0: AA        604           TAX              ; x=device*2 (si S3 D1, X=6 -> DEVADR31)
22D1: 0A        605           ASL             
22D2: 0A        606           ASL             
22D3: 0A        607           ASL             
22D4: 8D 9B 23  608           STA   ONLINE_NUM
22D7: 09 0E     609           ORA   #%00001110 ; DSSS1110 -> 1110=no err sur la device
22D9: 99 32 BF  610           STA   DEVLST,Y   ; ajoute/modifie à la liste des devices actives
22DC: A9 01     611           LDA   #<RAMDISK_DRV+1 ; pointeur driver pour cette device (skip CLD)
22DE: 9D 10 BF  612           STA   DEVADR01,X ; adr low driver
22E1: A9 FF     613           LDA   #>RAMDISK_DRV+1
22E3: 9D 11 BF  614           STA   DEVADR01+1,X ; adr high driver
22E6: AD 49 20  615           LDA   MAP_SLOT_DRV
22E9: C9 0B     616           CMP   #%00001011 ; slot 3, drive 2?
22EB: F0 34     617           BEQ   H2321      ; skip traitement slot 3 drive 2
                618 
                619  * Traitement du slot 3, drive 2 : déconnection
                620  * d'un driver RAM à cet endroit
                621 
22ED: AC 31 BF  622           LDY   DEVCNT     ; recherche si cette device est active
22F0: B9 32 BF  623  H22F0    LDA   DEVLST,Y  
22F3: 29 F0     624           AND   #%11110000 ; vire statut device
22F5: C9 B0     625           CMP   #%10110000 ; slot 3, drive 2?
22F7: F0 05     626           BEQ   H22FE      ; ok, found
                627 
22F9: 88        628           DEY              ; device précédante
22FA: 10 F4     629           BPL   H22F0      ; pas fini
                630 
22FC: 30 23     631           BMI   H2321      ; branche toujours si not found
                632 
22FE: AE 27 BF  633  H22FE    LDX   DEVADR32+1 ; check driver ram en $FFxx
2301: E8        634           INX              ; $FF+1=0
2302: D0 1D     635           BNE   H2321      ; pas un driver ram classique!
                636 
2304: B9 33 BF  637  H2304    LDA   DEVLST+1,Y ; supprime la device de la liste des actives
2307: 99 32 BF  638           STA   DEVLST,Y  
230A: C8        639           INY             
230B: CC 31 BF  640           CPY   DEVCNT    
230E: 90 F4     641           BCC   H2304     
                642 
2310: F0 F2     643           BEQ   H2304     
                644 
2312: CE 31 BF  645           DEC   DEVCNT     ; une device de moins
2315: AD 10 BF  646           LDA   DEVADR01   ; met la gestion de la device 0 à la place
2318: 8D 26 BF  647           STA   DEVADR32   ; low
231B: AD 11 BF  648           LDA   DEVADR01+1
231E: 8D 27 BF  649           STA   DEVADR32+1 ; high
                650 
                651  *-------------------------------
                652 
2321: 2C 82 C0  653  H2321    BIT   $C082      ; lecture rom
                654 
2324: 20 00 BF  655           JSR   MLI        ; recherche nom de ce volume à partir de l'unité
2327: C5        656           DFB   ONLINE    
2328: 9A 23     657           DA    TBL_ONLINE
                658 
232A: A2 00     659           LDX   #0         ; check result
232C: AD 20 02  660           LDA   ONLINE_BUF ; 1er octet buffer
232F: 0D 9F 23  661           ORA   H239F     
2332: D0 1B     662           BNE   RAMDISK_QUIT ; un caractère trouvé -> ok
                663 
2334: 90 19     664           BCC   RAMDISK_QUIT ;
                665 
2336: A9 FF     666           LDA   #$FF       ; anomalie ONLINE sur volume
2338: 8D 9F 23  667           STA   H239F     
233B: 8D 09 C0  668           STA   AUXZP     
233E: AD 8C 24  669           LDA   BANK_OK    ; sur 1er bank valide
2341: 8D 73 C0  670           STA   BANKSEL   
2344: 86 06     671           STX   $06        ; kill signature 1er bank aux valide
2346: 8E 73 C0  672           STX   BANKSEL    ; repasse sur bank 0 aux
2349: 8E CC 23  673           STX   VOL_TOT_BLK ; et nbr de blocks low
234C: 4C EC 20  674           JMP   H20EC      ; remet le couvert...
                675 
                676  *-------------------------------
                677  * Lance le prochain SYS
                678  *-------------------------------
                679 
234F: 8D 08 C0  680  RAMDISK_QUIT STA MAINZP  
2352: 4C 00 BD  681           JMP   $BD00      ; charge le prochain SYS
                682 
                683 
                684 
                685  ********************************
                686  *                              *
                687  *           RWRDB              *
                688  * Read/Write RamDisk Block     *
                689  * Routine recopiée dans chaque *
                690  * bank aux valide en page 0    *
                691  * (de $00B0 à $00F4)           *
                692  *                              *
                693  ********************************
                694 
                695  * Cette routine est exclusivement appelée par
                696  * CALL_RWRDB quand ce dernier est dans le buffer clavier
                697  * en ram princ.
                698 
                699  * In : carry = 1 : read
                700  *      carry = 0 : write
                701  *      Acc       : high buffer ram princ
                702  *      X         : low  buffer ram princ
                703  *      Y         : adr high ram aux début datas
                704  *
                705  * Out: Y     = 0 : always
                706  *      carry = 0 : always
                707  *      N     = 0 : req. ZP princ
                708  *      N     = 1 : req. ZP aux
                709 
                710  H2355                    
                711           ORG   $00B0     
                712 
                713  RWRDB                    
00B0: 85 E0     714           STA   H00DE+2    ; sta high début adr ram princ
00B2: B0 03     715           BCS   H00B7      ; si read
                716 
00B4: 84 E0     717           STY   H00DE+2    ; sta high début adr ram aux si write
00B6: A8        718           TAY              ; inverse de read
                719 
00B7: A9 00     720  H00B7    LDA   #0        
00B9: 8D 05 C0  721           STA   AUXWRT    
00BC: 90 09     722           BCC   H00C7      ; write -> écriture bank aux
                723 
00BE: 8A        724           TXA              ; read -> lecture bank aux, écriture main mem
00BF: A2 00     725           LDX   #0        
00C1: 8D 04 C0  726           STA   MAINWRT    ; read: les données vont de /ram vers la main mem
00C4: 8D 03 C0  727           STA   AUXREAD   
                728 
00C7: 84 DD     729  H00C7    STY   H00DB+2    ; lda high début block
00C9: C8        730           INY             
00CA: 84 E3     731           STY   H00E1+2    ; lda high fin block
00CC: 85 DF     732           STA   H00DE+1    ; sta low début block
00CE: 85 E5     733           STA   H00E4+1    ; sta low fin block
00D0: 86 DC     734           STX   H00DB+1    ; lda low début block
00D2: 86 E2     735           STX   H00E1+1    ; lda low fin block
00D4: A4 E0     736           LDY   H00DE+2    ; sta high
00D6: C8        737           INY             
00D7: 84 E6     738           STY   H00E4+2    ; sta
                739 
                740  * Effectue le read ou le write
                741 
00D9: A0 00     742           LDY   #0        
00DB: B9 00 10  743  H00DB    LDA   RAM_BLK0007L,Y ; LDA $??00,Y début block
00DE: 99 00 10  744  H00DE    STA   RAM_BLK0007L,Y ; STA $????,Y
00E1: B9 00 10  745  H00E1    LDA   RAM_BLK0007L,Y ; LDA $??00,Y fin block
00E4: 99 00 10  746  H00E4    STA   RAM_BLK0007L,Y ; STA $????,Y
00E7: C8        747           INY             
00E8: D0 F1     748           BNE   H00DB     
                749                            ; Y=0
00EA: 8D 04 C0  750           STA   MAINWRT    ; écriture en princ
00ED: 8D 02 C0  751           STA   MAINREAD   ; lecture en princ
00F0: 18        752           CLC             
00F1: 2C E4 02  753           BIT   SAVE_ALTZP ; N=1 si ZP aux, N=0 si ZP princ
00F4: 60        754           RTS             
                755 
                756           ORG   $239A      ; ORG alone -> BUG in generated code (bad ref addrs!)
                757 
                758  *-------------------------------
                759 
                760  * Parameters Online
                761 
239A: 02        762  TBL_ONLINE DFB 2         
239B: 30        763  ONLINE_NUM DFB %00110000  ; unit %DSSS0000
239C: 20 02     764           DA    ONLINE_BUF ; 16 octets $0220-022F
                765 
                766  *-------------------------------
                767 
239E: 00        768  H239E    DFB   0          ; nbr de banks valides-1
239F: 00        769  H239F    DFB   0          ; pour ORA sur 1er caractère buff résultat Online
                770 
                771  * Signature en page 0 1er bank aux valide ($06/$07/$08)
                772 
23A0: C7        773  H23A0    ASC   "G" ; Glen
23A1: C5        774           ASC   "E" ; E.
23A2: C2        775           ASC   "B" ; Bredon
                776 
                777  *-------------------------------
                778 
                779  * Volume directory header
                780 
23A3: 00 00     781  VOL_DIR_HEAD DA $0000     ; no previous dir block
23A5: 03 00     782           DA    $0003      ; next dir bloc
                783 
23A7: F3        784           DFB   %11110011  ; 4 first bits = $F = vol dir header id
                785                            ; 4 last  bits = $3 = volume name length
23A8: 52 41 4D  786           ASC   'RAM' ; volume name
23AB: 00 00 00  787           DS    12,0       ; complément nom pour 15 caractères
23AE: 00 00 00 00
23B2: 00 00 00 00
23B6: 00
                788 
23B7: 00 00 00  789           DS    8,0        ; not used
23BA: 00 00 00 00
23BE: 00
                790 
23BF: 00 00 00  791  VOL_DATETIME DS 4,0       ; creation date/time
23C2: 00
23C3: 01        792           DFB   1          ; version
23C4: 00        793           DFB   0          ; min version
23C5: C3        794           DFB   %11000011  ; access: destroy/rename/write/read
23C6: 27        795           HEX   27         ; lenght of each entry in bytes ($27 = standard)
23C7: 0D        796           HEX   0D         ; entries per block ($0D = standard)
23C8: 00 00     797           DA    $0000      ; file count
23CA: 06 00     798           DA    $0006      ; bit map pointer (block 6)
23CC: 00 00     799  VOL_TOT_BLK DFB 0,0       ; total block low/high
                800 
                801 
                802  ********************************
                803  *                              *
                804  *       Driver RamDisk         *
                805  * recopié en MEV princ dans le *
                806  * banc commuté en $FF00-$FFEA  *
                807  *                              *
                808  ********************************
                809 
                810  * Commande STATUS
                811  * ---------------
                812  * In : DRV_COMMAND : 00 (commande)
                813  *
                814  * Out: X           : blocks dispos low
                815  *      Y           : blocks dispos high
                816  *      carry       : 0 (always) -> no err
                817  *      acc         : 0 (always) -> no err
                818  *
                819  * Commande FORMAT
                820  * ---------------
                821  * In : DRV_COMMAND : 03 (commande)
                822  *
                823  * Out: carry       : 0 (always) -> no err
                824  *      acc         : 0 (always) -> no err
                825  *
                826  * Commandes READ/WRITE
                827  * --------------------
                828  * In : DRV_COMMAND : 01 (read) or 02 (write)
                829  *      DRV_BUFFL   : low buffer implantation block
                830  *      DRV_BUFFH   : high buffer
                831  *      DRV_BLKL    : low block ProDOS 512 octets
                832  *      DRV_BLKH    : high block ProDOS 512 octets
                833  *
                834  * Out: carry       : 0 (no err) or 1 (err -> see acc)
                835  *      acc         : 0 (no err) or $27 (I/O err)
                836 
                837  H23CE                    
                838 
                839           ORG   $FF00     
                840 
                841  RAMDISK_DRV              
FF00: D8        842           CLD              ; valid driver for BI
FF01: A5 42     843           LDA   DRV_COMMAND ; commande status?
FF03: D0 07     844           BNE   HFF0C      ; non
                845 
                846           ORG             
                847 
                848  *-------------------------------
                849  * Commande : Status
                850  *-------------------------------
                851 
                852  * Retourne la taille calculée lors du formattage
                853 
                854                            ; acc=0=no err
23D3: A2 00     855  RWB_ST_BLKL LDX #$00      ; blocks dispos low
23D5: A0 00     856  RWB_ST_BLKH LDY #$00      ; blocks dispos high
                857 
                858           ORG   $FF09     
                859 
FF09: 18        860  HFF09    CLC              ; no err
FF0A: 90 77     861           BCC   HFF83      ; toujours ->fin
                862 
                863  *-------------------------------
                864  * Commande : Format (NO EFFECT)
                865  *-------------------------------
                866 
FF0C: C9 03     867  HFF0C    CMP   #$03       ; commande format?
FF0E: F0 F9     868           BEQ   HFF09      ; oui. Mais pas autorisée sur le ramdisk
                869                            ; carry=0 si commande 1 (read) ou 2 (write)
                870                            ; carry=1 pour autres valeurs
                871 
                872  *-------------------------------
                873 
FF10: A9 27     874  HFF10    LDA   #$27       ; I/O err
FF12: B0 73     875           BCS   HFF87      ; si commande > 3
                876 
                877  *-------------------------------
                878  * Commandes : Read / Write
                879  *-------------------------------
                880 
                881  * Sauvegarde avant utilisation
                882 
FF14: AD 18 C0  883           LDA   R80ST      ; mémorise état 80STORE
FF17: 48        884           PHA             
FF18: 8D 00 C0  885           STA   _80STORE0  ; utilise ramread/ramwrite
FF1B: A5 40     886           LDA   $40        ; sauvegarde octets utilisés page
FF1D: 48        887           PHA             
FF1E: A5 41     888           LDA   $41       
FF20: 48        889           PHA             
                890 
FF21: A5 44     891           LDA   DRV_BUFFL  ; ($40) pointe sur dernier 256 octets buffer ram
FF23: 85 40     892           STA   $40        ; princ pour la phase de swap buffer s'il n'est
FF25: A6 45     893           LDX   DRV_BUFFH  ; pas bon
FF27: E8        894           INX             
FF28: 86 41     895           STX   $41       
                896 
FF2A: 20 88 FF  897           JSR   CHECK_BUFFH ; routine copie CALL_RWRDB dans buffer clavier et
                898                            ; check buffer high block
FF2D: 8E D4 02  899           STX   H02D3+1    ; met en place LDA#>buffer dans CALL_RWRDB
FF30: AD 16 C0  900           LDA   RZPSW      ; store état ALTZP (page 0 princ ou aux)
FF33: 8D E4 02  901           STA   SAVE_ALTZP
                902 
FF36: A5 47     903           LDA   DRV_BLKH   ; sauve block high
FF38: 48        904           PHA             
FF39: AA        905           TAX              ; X=block high
                906 
                907  * Routine très importante!!!!
                908  * A partir d'un numéro de block, calcule l'adresse en ram
                909  * où se trouvent les datas et le bank à sélectionner.
                910  * Commute aussi la MEV et le bank de 4k si c'est cette
                911  * partie qui est concernée.
                912 
                913                            ; Y=0
FF3A: A5 46     914           LDA   DRV_BLKL   ; enlève $7F blocks, c'est à dire le nbr de blocks
FF3C: 38        915  HFF3C    SEC              ; contenus dans un bank
FF3D: C8        916  HFF3D    INY              ; on n'oublie pas qu'il faut prendre en compte le
FF3E: E9 7F     917           SBC   #$7F       ; fait que le block 0 commence à $0200
                918 
FF40: B0 FB     919           BCS   HFF3D     
                920 
FF42: CA        921           DEX              ; block high-1
FF43: 10 F7     922           BPL   HFF3C     
                923                            ; carry=0
FF45: 98        924           TYA              ; ajout pour calc adresse
FF46: 65 46     925           ADC   DRV_BLKL  
FF48: 90 02     926           BCC   HFF4C     
                927 
FF4A: E6 47     928           INC   DRV_BLKH  
                929 
FF4C: 0A        930  HFF4C    ASL              ; block restant * 2 = adresse
FF4D: A8        931           TAY              ; dans Y
FF4E: A5 47     932           LDA   DRV_BLKH  
FF50: 2A        933           ROL             
FF51: AA        934           TAX              ; numéro bank
                935 
FF52: 68        936           PLA              ; restaure block high
FF53: 85 47     937           STA   DRV_BLKH  
                938 
                939           ORG             
                940 
2423: E0 00     941  HFF55    CPX   #$00       ; compare avec nbr de banks valides
                942 
                943           ORG   $FF57     
                944 
FF57: B0 1B     945           BCS   HFF74      ; trop grand -> reswap et I/O err
                946 
FF59: 98        947           TYA              ; examine adresse high
FF5A: E9 BF     948           SBC   #>$BF00   
FF5C: C9 10     949           CMP   #>$1000    ; banc commuté 2 4k?
FF5E: B0 06     950           BCS   HFF66      ; non
                951 
FF60: 69 D0     952           ADC   #>$D000    ; skip $C000-$CFFF
FF62: A8        953           TAY             
FF63: 2C 83 C0  954           BIT   $C083      ; bank 2 4k MEV (read)
                955 
                956                            ; Y=adr mem high
                957                            ; X=bank à prendre
                958 
FF66: A5 42     959  HFF66    LDA   DRV_COMMAND
FF68: 4A        960           LSR              ; carry=cmd (=1 pour read, =0 pour write)
FF69: BD BE FF  961           LDA   RWB_RAM_BK,X
FF6C: A6 44     962           LDX   DRV_BUFFL 
FF6E: 20 D0 02  963           JSR   CALL_RWRDB ; lance les opérations d'E/S
FF71: 2C 8B C0  964           BIT   $C08B      ; bank 1 4k MEV (read)
                965 
FF74: 20 88 FF  966  HFF74    JSR   CHECK_BUFFH ; remet la situation initiale en place dans le
                967                            ; buffer clavier
                968 
                969  * Restaure les valeurs altérées
                970 
FF77: 68        971           PLA              ; octets page 0
FF78: 85 41     972           STA   $41       
FF7A: 68        973           PLA             
FF7B: 85 40     974           STA   $40       
FF7D: 68        975           PLA              ; restaure état 80STORE
FF7E: 10 03     976           BPL   HFF83      ; ok déja usage ramread/ramwrite
                977 
FF80: 8D 01 C0  978           STA   _80STORE1  ; accès page affichage
                979 
                980 
                981  *-------------------------------
                982 
FF83: A9 00     983  HFF83    LDA   #0         ; no err
FF85: B0 89     984           BCS   HFF10      ; I/O err
                985                            ; carry=0
FF87: 60        986  HFF87    RTS              ; end no err
                987 
                988  *-------------------------------
                989  * Swap routine appel RWRDB et
                990  * contenu espace buffer clavier
                991  * et check adr high buffer
                992  *-------------------------------
                993 
                994  * Il faudra 2 appels de cette routine:
                995  * 1 pour mettre en place la routine en $02D0
                996  *          + backup buffer clavier
                997  * 1 pour remettre la situation initiale
                998 
                999  * In : DRV_BUFFH = buffer high main memory
                1000 *      DRV_BUFFL = buffer low
                1001 *      ($40)     = pointe sur les 256 derniers octets buffer
                1002 *
                1003 * Out: X         = buffer high ram princ validé
                1004 *      Y         = 0 (always)
                1005 *
                1006 * carry n'est pas altérée
                1007
                1008 CHECK_BUFFH              
FF88: A0 15     1009          LDY   #$15       ; met en place $02D0-$02E4 en ram princ dans le
FF8A: BE D5 FF  1010 HFF8A    LDX   HFFD6-1,Y  ; buffer clavier et en meme temps sauve le contenu
FF8D: B9 CF 02  1011          LDA   CALL_RWRDB-1,Y ; de ce dernier à la place du code déplacé.
FF90: 99 D5 FF  1012          STA   HFFD6-1,Y 
FF93: 8A        1013          TXA             
FF94: 99 CF 02  1014          STA   CALL_RWRDB-1,Y
FF97: 88        1015          DEY             
FF98: D0 F0     1016          BNE   HFF8A     
                1017
                1018 * Il est interdit d'utiliser l'espace >= $BC00
                1019 * comme buffer. Si dans l'espace interdit, alors force
                1020 * le buffer sur $8000-$81FF.
                1021
                1022                           ; Y=0. Default X=buffer high demandé
FF9A: A6 45     1023          LDX   DRV_BUFFH  ; si buffer < $80xx
FF9C: 10 1F     1024          BPL   HFFBD      ; buffer high ok
                1025                           ; >=$8000
FF9E: 24 45     1026          BIT   DRV_BUFFH  ; si buffer < $BCxx
FFA0: 50 1B     1027          BVC   HFFBD      ; V=0 : buffer ok
                1028
FFA2: BE 00 80  1029 HFFA2    LDX   $8000,Y    ; swap contenu buffer demandé avec buffer
FFA5: B1 44     1030          LDA   (DRV_BUFFL),Y ; autorisé
FFA7: 99 00 80  1031          STA   $8000,Y    ; buffer début block
FFAA: 8A        1032          TXA             
FFAB: 91 44     1033          STA   (DRV_BUFFL),Y
FFAD: BE 00 81  1034          LDX   $8100,Y    ; buffer fin block
FFB0: B1 40     1035          LDA   ($40),Y   
FFB2: 99 00 81  1036          STA   $8100,Y   
FFB5: 8A        1037          TXA             
FFB6: 91 40     1038          STA   ($40),Y   
FFB8: C8        1039          INY             
FFB9: D0 E7     1040          BNE   HFFA2     
                1041                           ; Y=0
FFBB: A2 80     1042          LDX   #>$8000    ; force buffer $8000
FFBD: 60        1043 HFFBD    RTS             
                1044
                1045 *-------------------------------
                1046
FFBE: 00 00 00  1047 RWB_RAM_BK DS  $18,0      ; $FFBE-$FFD5 (et $248C-$24A3) : liste des banks
FFC1: 00 00 00 00
FFC5: 00 00 00 00
FFC9: 00 00 00 00
FFCD: 00 00 00 00
FFD1: 00 00 00 00
FFD5: 00
                1048                           ; valides sélectionnés.
                1049
                1050 ********************************
                1051 *                              *
                1052 * Routine d'appel de RWRDB     *
                1053 * stockée dans buffer clavier  *
                1054 * de la ram princ              *
                1055 *                              *
                1056 ********************************
                1057
                1058 * In : carry   = 1 read
                1059 *      carry   = 0 write
                1060 *      acc     = bank aux à commuter
                1061 *      Y       = adr high ram aux début datas
                1062 *      X       = adr low  buffer valide ram princ
                1063 *      $02D3+1 = adr high buffer valide ram princ
                1064
                1065 HFFD6                    
                1066          ORG   $02D0     
                1067
                1068 CALL_RWRDB               
02D0: 8D 73 C0  1069          STA   BANKSEL    ; enclenche bank = acc
02D3: A9 00     1070 H02D3    LDA   #0         ; LDA#>buffer ram princ
02D5: 8D 09 C0  1071          STA   AUXZP      ; carte langage main mem off (RAMDISK_DRV off)
                1072                           ; et RWRDB bank aux on (page 0 bank aux on)
02D8: 20 B0 00  1073          JSR   RWRDB      ; passe par la routine en page 0 aux
                1074                           ; Y=0
02DB: 8C 73 C0  1075          STY   BANKSEL    ; bank 0
02DE: 30 03     1076          BMI   :1         ; N=1 -> keep ZP aux (cas spécial driver en bank 0
                1077                           ;                     aux)
02E0: 8D 08 C0  1078          STA   MAINZP     ; RAMDISK_DRV on et page 0 ram princ
02E3: 60        1079 :1       RTS             
                1080
02E4: 00        1081 SAVE_ALTZP DFB 0          ; sauvegarde switch page 0 (princ ou aux)
                1082                           ; $02E4
                1083

Object saved as RAM.DRV.SYSTEM,A$2000,L$04B9,SYS

 
 
--End assembly, 1209 bytes, Errors: 0


Symbol table - alphabetical order:

?  AUXREAD =$C003      AUXWRT  =$C005      AUXZP   =$C009      BANKSEL =$C073
   BANK_LST=$24BB      BANK_LST_ALL=$253B      BANK_OK =$248C      BUTTN1  =$C062
   CALL_RWRDB=$02D0      CHECK_BUFFH=$FF88      CLOSE   =$CC     ?  CLOSE_NUM=$BD89
   DATE    =$BF90      DEVADR01=$BF10      DEVADR32=$BF26      DEVCNT  =$BF31
   DEVLST  =$BF32      DRV_BLKH=$47        DRV_BLKL=$46        DRV_BUFFH=$45
   DRV_BUFFL=$44        DRV_COMMAND=$42        EOF_POS =$BD94      FILE_TYPE=$BD74
   GET_EOF =$D1        GET_EOF_NUM=$BD93      GET_FILE_INFO=$C4        GO_QUIT =$21E5
?  H00B7   =$B7     ?  H00C7   =$C7     ?  H00DB   =$DB     ?  H00DE   =$DE
?  H00E1   =$E1     ?  H00E4   =$E4        H02D3   =$02D3   ?  H2000   =$2000
   H20E1   =$20E1      H20EC   =$20EC      H20F9   =$20F9      H20FF   =$20FF
   H2110   =$2110      H2136   =$2136      H2154   =$2154      H215E   =$215E
   H2166   =$2166      H2169   =$2169      H2180   =$2180      H218A   =$218A
   H218F   =$218F      H219C   =$219C      H21C1   =$21C1      H21D3   =$21D3
   H21E8   =$21E8      H21EB   =$21EB      H21F5   =$21F5      H2203   =$2203
   H2226   =$2226      H225C   =$225C      H2276   =$2276      H229E   =$229E
   H22A0   =$22A0      H22AE   =$22AE      H22C3   =$22C3      H22CC   =$22CC
   H22F0   =$22F0      H22FE   =$22FE      H2304   =$2304      H2321   =$2321
   H2355   =$2355      H239E   =$239E      H239F   =$239F      H23A0   =$23A0
   H23CE   =$23CE      HBD00   =$204A      HFF09   =$FF09      HFF0C   =$FF0C
   HFF10   =$FF10      HFF3C   =$FF3C      HFF3D   =$FF3D      HFF4C   =$FF4C
   HFF55   =$2423      HFF66   =$FF66      HFF74   =$FF74      HFF83   =$FF83
   HFF87   =$FF87      HFF8A   =$FF8A      HFFA2   =$FFA2      HFFBD   =$FFBD
   HFFD6   =$FFD6      LAST_BLK_LCK=$24BA   ?  MAINREAD=$C002      MAINWRT =$C004
   MAINZP  =$C008      MAP_SLOT_DRV=$2049      MLI     =$BF00      NB_LOCKED_BK=$2048
   NEXT_SYS=$2006      ONLINE  =$C5        ONLINE_BUF=$0220      ONLINE_NUM=$239B
   OPEN    =$C8        OPEN_NUM=$BD87      QUIT    =$65        R80ST   =$C018
   RAMDISK_DRV=$FF00      RAMDISK_QUIT=$234F      RAM_BLK0002H=$0700      RAM_BLK0002L=$0600
   RAM_BLK0003H=$0900      RAM_BLK0003L=$0800      RAM_BLK0004H=$0B00      RAM_BLK0004L=$0A00
   RAM_BLK0005H=$0D00      RAM_BLK0005L=$0C00      RAM_BLK0006H=$0F00      RAM_BLK0006L=$0E00
?  RAM_BLK0007L=$1000      RAM_FORMAT=$21F0      READ    =$CA        READ_NUM=$BD8B
   READ_REQ_LEN=$BD8E      RWB_RAM_BK=$FFBE      RWB_ST_BLKH=$23D5      RWB_ST_BLKL=$23D3
   RWRDB   =$B0        RZPSW   =$C016      SAVE_ALTZP=$02E4      SAV_BYTE_00=$25BB
   SAV_BYTE_01=$263B      TBL_CLOSE=$BD88      TBL_GET_EOF=$BD92      TBL_GET_F_I=$BD70
   TBL_ONLINE=$239A      TBL_OPEN=$BD82      TBL_QUIT=$BD69      TBL_READ=$BD8A
   VOL_DATETIME=$23BF      VOL_DIR_HEAD=$23A3      VOL_TOT_BLK=$23CC      WRK_NB_LCK_BK=$24B9
   _80STORE0=$C000      _80STORE1=$C001  


Symbol table - numerical order:

   DRV_COMMAND=$42        DRV_BUFFL=$44        DRV_BUFFH=$45        DRV_BLKL=$46
   DRV_BLKH=$47        QUIT    =$65        RWRDB   =$B0     ?  H00B7   =$B7
   GET_FILE_INFO=$C4        ONLINE  =$C5     ?  H00C7   =$C7        OPEN    =$C8
   READ    =$CA        CLOSE   =$CC        GET_EOF =$D1     ?  H00DB   =$DB
?  H00DE   =$DE     ?  H00E1   =$E1     ?  H00E4   =$E4        ONLINE_BUF=$0220
   CALL_RWRDB=$02D0      H02D3   =$02D3      SAVE_ALTZP=$02E4      RAM_BLK0002L=$0600
   RAM_BLK0002H=$0700      RAM_BLK0003L=$0800      RAM_BLK0003H=$0900      RAM_BLK0004L=$0A00
   RAM_BLK0004H=$0B00      RAM_BLK0005L=$0C00      RAM_BLK0005H=$0D00      RAM_BLK0006L=$0E00
   RAM_BLK0006H=$0F00   ?  RAM_BLK0007L=$1000   ?  H2000   =$2000      NEXT_SYS=$2006
   NB_LOCKED_BK=$2048      MAP_SLOT_DRV=$2049      HBD00   =$204A      H20E1   =$20E1
   H20EC   =$20EC      H20F9   =$20F9      H20FF   =$20FF      H2110   =$2110
   H2136   =$2136      H2154   =$2154      H215E   =$215E      H2166   =$2166
   H2169   =$2169      H2180   =$2180      H218A   =$218A      H218F   =$218F
   H219C   =$219C      H21C1   =$21C1      H21D3   =$21D3      GO_QUIT =$21E5
   H21E8   =$21E8      H21EB   =$21EB      RAM_FORMAT=$21F0      H21F5   =$21F5
   H2203   =$2203      H2226   =$2226      H225C   =$225C      H2276   =$2276
   H229E   =$229E      H22A0   =$22A0      H22AE   =$22AE      H22C3   =$22C3
   H22CC   =$22CC      H22F0   =$22F0      H22FE   =$22FE      H2304   =$2304
   H2321   =$2321      RAMDISK_QUIT=$234F      H2355   =$2355      TBL_ONLINE=$239A
   ONLINE_NUM=$239B      H239E   =$239E      H239F   =$239F      H23A0   =$23A0
   VOL_DIR_HEAD=$23A3      VOL_DATETIME=$23BF      VOL_TOT_BLK=$23CC      H23CE   =$23CE
   RWB_ST_BLKL=$23D3      RWB_ST_BLKH=$23D5      HFF55   =$2423      BANK_OK =$248C
   WRK_NB_LCK_BK=$24B9      LAST_BLK_LCK=$24BA      BANK_LST=$24BB      BANK_LST_ALL=$253B
   SAV_BYTE_00=$25BB      SAV_BYTE_01=$263B      TBL_QUIT=$BD69      TBL_GET_F_I=$BD70
   FILE_TYPE=$BD74      TBL_OPEN=$BD82      OPEN_NUM=$BD87      TBL_CLOSE=$BD88
?  CLOSE_NUM=$BD89      TBL_READ=$BD8A      READ_NUM=$BD8B      READ_REQ_LEN=$BD8E
   TBL_GET_EOF=$BD92      GET_EOF_NUM=$BD93      EOF_POS =$BD94      MLI     =$BF00
   DEVADR01=$BF10      DEVADR32=$BF26      DEVCNT  =$BF31      DEVLST  =$BF32
   DATE    =$BF90      _80STORE0=$C000      _80STORE1=$C001   ?  MAINREAD=$C002
?  AUXREAD =$C003      MAINWRT =$C004      AUXWRT  =$C005      MAINZP  =$C008
   AUXZP   =$C009      RZPSW   =$C016      R80ST   =$C018      BUTTN1  =$C062
   BANKSEL =$C073      RAMDISK_DRV=$FF00      HFF09   =$FF09      HFF0C   =$FF0C
   HFF10   =$FF10      HFF3C   =$FF3C      HFF3D   =$FF3D      HFF4C   =$FF4C
   HFF66   =$FF66      HFF74   =$FF74      HFF83   =$FF83      HFF87   =$FF87
   CHECK_BUFFH=$FF88      HFF8A   =$FF8A      HFFA2   =$FFA2      HFFBD   =$FFBD
   RWB_RAM_BK=$FFBE      HFFD6   =$FFD6