I. Un peu de théorie...

À l'allumage d'un Apple II+, IIe, IIe Enhanced, et même IIc, il se passe ceci (au niveau logiciel en ROM Autostart) :

  • récupération du contenu des adresses $FFFC ($62) et $FFFD ($FA).
  • saut à l'adresse obtenue : $FA62 (entry point de la ROM Autostart donc).
  • à partir de $FA62, diverses initialisations sont effectuées (notamment pour la page zéro et au niveau du mode d'affichage).
  • en $FA85, teste si le WARM START est possible (si $3F4 = $3F3 EOR $A5).
  • si oui, on saute à l'adresse contenue en $3F2/$3F3 (Reset Vector).
  • sinon on effectue un COLD START et on saute donc en $FAA6.

C'est cette routine en $FAA6 qui nous intéresse particulièrement. Ci-dessous le code issu d'un Enhanced IIe. On retrouve le même sur II+ et IIe (à une petite exception près, signalée dans le listing). Sur Apple IIc, il n'y a pas de test de slots (et pour cause...), la routine est donc totalement différente. Toute la suite ne le concerne donc plus :

// Début Routine
FAA6-   20 60 FB    JSR   $FB60   ; HOME + affichage du message "APPLE xx"
 
// INITIALISATION VECTORS
FAA9-   A2 05       LDX   #$05
FAAB-   BD FC FA    LDA   $FAFC,X
FAAE-   9D EF 03    STA   $03EF,X ; initialisation BRK Handler + RESET VECTOR
FAB1-   CA          DEX           ;                  ($FA59)       ($E000)
FAB2-   D0 F7       BNE   $FAAB
 
// TEST des SLOTS à partir du 7ème
FAB4-   A9 C8       LDA   #$C8	  ; $C7 + 1 !
FAB6-   86 00       STX   $00	  ; X=0
FAB8-   85 01       STA   $01	  ; $01 = $C8 
 
FABA-   A0 05       LDY   #$05    ; sur Enhanced IIe only ! LDY #$07 sur II+/IIe
FABC-   C6 01       DEC   $01     ; $01 = $C7, $C6, ... $C1
FABE-   A5 01       LDA   $01
FAC0-   C9 C0       CMP   #$C0    ; tous les slots ($C7-$C1) ont été checkés ?
FAC2-   F0 D7       BEQ   $FA9B   ; si oui, on saute vers le BASIC APPLESOFT
                                  ; car aucune ROM bootable n'a été trouvée !
FAC4-   8D F8 07    STA   $07F8   ; sauvegarde adresse SLOT
FAC7-   B1 00       LDA   ($00),Y ; test du contenu de la "ROM" du SLOT
FAC9-   D9 01 FB    CMP   $FB01,Y ; on compare avec une table
FACC-   D0 EC       BNE   $FABA   ; différent ? -> SLOT suivant
FACE-   88          DEY           ; octet à tester suivant
FACF-   88          DEY           ; pris un sur deux dans la table
FAD0-   10 F5       BPL   $FAC7   ; on boucle
 
// si le test a été concluant :
FAD2-   6C 00 00    JMP   ($0000) ; saut vers BOOT0 (ex : $C600)
 
// 2 octets inutilisés...
FAD5-   00          BRK		  ; EA (NOP) sur II+/IIe
FAD6-   00	    BRK           ; EA (NOP) sur II+/IIe
 
// table d'octets utilisés pour checker la présence d'une carte (bootable)
// dans un slot (les octets testés sont marqués d'un *)
FB01- 45 20 FF 00 FF 03 FF 3C
	 *     *     *     *
// correspondance avec par exemple une carte contrôleur DISK II en slot 6
// ou une carte HDD en slot 7 :
C600- A2 20 A0 00 A2 03 86 3C
         *     *     *     *
C700- A9 20 A9 00 A9 03 A9 3C

À la lecture de cette routine, on comprend maintenant pourquoi par exemple, un disque dur branché en SLOT 7 démarre avant une unité de disquette en SLOT 6. Dès qu'une carte bootable est identifiée, on saute au BOOT0 en exécutant la ROM de ladite carte. L'Autostart ne s'occupe absolument plus des slots restants. Comme le check se fait depuis $C700 vers $C100, le SLOT 7 est bien testé avant le 6.

On comprend aussi le code redondant que l'on peut trouver au début de la ROM d'une carte contrôleur :

C600- A2 20   LDX #$20 ;
C602- A0 00   LDY #$00
C604- A2 03   LDX #$03 ; encore un LDX ?!
C606- 86 3C   STX $3C

4 octets non consécutifs (3 seulement sur Enhanced IIe) sont donc checkés pour déterminer la présence d'une carte bootable ou non : $20, $00, $03 et $3C. Toutes les cartes bootables sont donc obligées de contenir ces 4 octets à leurs places respectives. Exemple récent avec la CFFA3000 où l'on trouve le code suivant :

C600- A9 20   LDA #$20
C602- A2 00   LDX #$00
C604- A9 03   LDA #$03
C606- A9 3C   LDA #$3C

Ces octets vérifiés proviennent très probablement de la première version du contrôleur DISK II avec la PROM P5 qui ne pouvait lire que 13 secteurs par piste (contrairement à la P5A dont est issu le code au-dessus). Sur la P5, on trouvait en début de code cette initialisation somme toute classique des registres :

C600- A2 20   LDX #$20
C602- A0 00   LDY #$00
C604- A9 03   LDA #$03
C606- 85 3C   STA $3C

II. Et maintenant la pratique !

L'objectif est de modifier la routine de détection de slots pour lui faire effectuer ce que l'on veut précisément, en l’occurrence nous permettre de choisir lors du boot le slot sur lequel doit se lancer la machine. Notre problème principal sera la place mémoire disponible. La routine originale fait 34 octets (en comptant les deux NOP/BRK de fin). Il va donc falloir faire tenir notre code dans cet espace réduit avec le cahier des charges suivant :

  • pouvoir choisir le slot de boot (de 7 à 1) par utilisation des touches numériques.
  • booter automatiquement sur un slot prédéterminé si aucune action n'est effectuée après un temps donné.
  • permettre de sauter directement au BASIC Applesoft sans booter sur un slot.

 

Pour intégrer tout ceci dans les 34 octets, il a fallu faire quelques concessions :

  • aucun test du slot en lui-même : la routine va jumper vers l'adresse mémoire ROM du slot quoiqu’il arrive. S'il n'y a rien au bout, plantage assuré !
  • pas de test non plus des touches utilisables : toutes les touches généreront une adresse de JMP. Plantage assuré de nouveau si on n'appuie pas sur la bonne !

 

Voici donc le résultat :

FAB4-   A9 C6       LDA   #$C6    ; slot 6 par défaut
FAB6-   85 01       STA   $01     ; on prépare le JMP indirect (adresse Hi)
FAB8-   86 00       STX   $00     ; x=0 (adresse Lo)
FABA-   A2 1E       LDX   #$1E    ; environ 3 secondes de tempo
FABC-   A9 C7       LDA   #$C7    ; attention, rien à voir avec le SLOT 7 !
FABE-   20 A8 FC    JSR   $FCA8   ; c'est la variable de la routine WAIT
FAC1-   CA          DEX           ;
FAC2-   D0 F8       BNE   $FABC   ; on boucle
FAC4-   AD 00 C0    LDA   $C000   ; test clavier
FAC7-   8D 10 C0    STA   $C010   ; réinitialisation clavier
FACA-   10 08       BPL   $FAD4   ; on a appuyé sur rien ? alors JMP $C600
FACC-   C9 B0       CMP   #$B0    ; était-ce la touche "0" ?
FACE-   F0 CB       BEQ   $FA9B   ; si oui, JMP APPLESOFT
FAD0-   49 70       EOR   #$70    ; on génère l'adresse à partir de la touche
FAD2-   85 01       STA   $01     ; appuyée. Espérons que ce soit un chiffre !
FAD4-   6C 00 00    JMP   ($0000) ; GO !

Ce code est configurable pour vos propres besoins essentiellement à 3 endroits :

  • FAB4- (LDA #$C6) : vous pouvez ici définir le slot par défaut sur lequel va booter la machine. Il suffit bien entendu de remplacer le $C6 par $C7 pour le SLOT 7, $C5 pour le 5, etc.
  • FABA- (LDX #$1E) : la temporisation. Vous pouvez augmenter ou réduire le $1E. La formule est (à peu près) : $0A x nb de secondes que vous voulez de tempo. $1E correspond donc à environ 3 secondes. Pour 2, ça sera $14.  L'astuce ici consiste à  utiliser la tempo pour laisser le temps d'appuyer sur une touche. Celle-ci ne sera testée qu'à la fin de la temporisation (et non pendant) mais le buffer, lui, s'en souviendra ! Si vous mettez une tempo trop courte, la touche ne sera pas prise en compte. Évitez donc de descendre en-dessous de la seconde.
  • FACC- (CMP #$B0) : vous pouvez ici définir une autre touche que 0 pour l'appel du BASIC APPLESOFT. Mettez un $A0 à la place du $B0 pour utiliser la barre d'espace par exemple. C'est la seule touche hard-codée, toutes les autres généreront une adresse par l’intermédiaire du EOR #$70. Exemple : touche 5, code ASCII $B5, donnera $B5 EOR $70 soit $C5 comme adresse Hi. D'où un JMP $C500 au final !

Mise à jour du 11 décembre 2011 :

  • si vous avez appliqué une des modifications "Reset", vous pouvez également, plutôt que de sauter au BASIC avec la touche 0, sauter vers le Monitor. Pour ce faire, remplacez en :
    FACE- F0 CB      BEQ  $FA9B par : F0 D3    (BEQ $FAA3)
  • sans avoir appliqué la modification "Reset", il faudra pour sauter au Monitor par la touche 0, remplacer également en :
    FAA3- 6C F2 03   JMP ($03F2)
    par : 4C 59 FF (JMP $FF59)

III. Utilisation

L'utilisation principale, c'est bien évidemment de programmer une EPROM 2764 avec le code Autostart ainsi modifié et de remplacer avec, la ROM "EF" dans un IIe. Mais vous pouvez aussi vous amuser avec des ROMS perso sous AppleWin (décidément cet émulateur est vraiment énorme).

Fichiers pour EPROM 2764 (Apple IIe) :

ROM ENHANCED "EF" modifiée (base : 342-0303-A) :  à n'utiliser qu'avec la ROM "CD" Enhanced et un 65C02 dans la machine !

ROM STANDARD "EF" modifiée (base : 342-0134-A) :  pour un IIe standard.

Vérifiez bien que le numéro de version correspond à la ROM présente dans votre Apple IIe avant d'effectuer tout changement (et de brûler une EPROM pour rien).

Personnalisation : utilisez un éditeur hexadécimal pour modifier directement le fichier .bin de l'EPROM.

Offset début du code modifié : $1AB4
Offset paramètre SLOT : $1AB5 (par défaut $C6)
Offset paramètre Temporisation : $1ABB  (par défaut $1E)
Offset Touche "Applesoft" : $1ACD (par défaut $B0)

Fichiers pour AppleWin :

F8.rom : Rom Autostart modifiée utilisable avec AppleWin comme "rom perso". Pour l'utiliser, il suffit de copier le fichier F8.rom dans le répertoire d'installation d'AppleWin et de lancer celui-ci avec comme paramètre en ligne de commande -f8rom F8.rom .
Attention de bien configurer AppleWin en mode "Enhanced Apple //e" pour l'émulation.

Personnalisation :

Offset début du code modifié : $2B4
Offset paramètre SLOT : $2B5 (par défaut $C6)
Offset paramètre Temporisation : $2BB  (par défaut $14)
Offset Touche "Applesoft" : $2CD (par défaut $B0)

Exemples d'utilisation : laissez la ROM modifiée par défaut, AppleWin bootera sur le SLOT 6. Vous pouvez ainsi définir un disque dur dans AppleWin et ne booter sur celui-ci que quand vous le voudrez, en appuyant sur 7.
Ou alors, éditez le $C6 (à l'offset $2B5) pour y mettre $C7 : le disque dur bootera alors systématiquement en premier (comme normalement), mais vous aurez la possibilité, en appuyant sur 6, de booter sur une image disque.

Notes : Il y a même possibilité d'effectuer ces modifications dans AppleWin directement (sans passer par une ROM perso chargée au lancement). Il faut alors remplacer (avec Resource Hacker par exemple) la ressource référencée ROM/129/1033 dans AppleWin.exe par celle-ci. Valable pour le mode "Enhanced Apple //e".

IV. Bonus

Pour les fans du tuning total, il est très facile de modifier le message de boot d'un Apple II. On l'a vu en début d'article, la routine d'affichage se trouve en $FB60 et la chaîne en elle-même commence en $FF0A (sur IIe Enhanced seulement) ou en $FB09 (II+ et IIe). Attention de bien respecter le nombre de caractères disponibles suivant les versions (ajoutez des espaces si besoin est). Si vous voulez faire plus long, il faudra à la fois modifier la routine d'affichage (pour prendre en compte les caractères supplémentaires) mais aussi trouver de la place pour votre texte. Car n'écrasez surtout pas ce qui suit la chaîne originelle avec votre prose, problèmes assurés sinon !

Pour les EPROMs :

Offset Texte Boot : $1F0A (ROM Enhanced) / $1B09 (ROM Unenhanced)

Pour AppleWin :

fichier F8.rom : Offset Texte Boot = $70A
fichier resource modified.129 : Offset Texte Boot = $3F0A