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...
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:
- Status : donne des informations sur le volume à partir de
son
numéro d'unité (le minimum à fournir: la taille du
volume en nbr de blocks et si
l'unité n'est pas en erreur).
- Read : lecture d'un block à partir d'un
numéro de block.
- Write : écriture d'un block dont le numéro
est
communiqué.
- Format : formattage du volume. Cette commande n'est pas
systématiquement gérée par les unités de
stockage car les fabricants peuvent livrer un outil en plus
dédié à cette tâche ou alors le process est
automatique. RAM.DRV.SYSTEM ne fera
rien
si on utilise cette commande. Le seul moyen de formatter le volume
c'est lors d'un premier
lancement ou en appuyant sur la touche pomme-fermée
(closed-apple) pendant le démarrage de ProDOS
quand le driver s'exécute.
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):
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!)

|
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
------------------------------------------------------------------------------
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