À l'image des modifications de ROM proposées par Krakowicz (grand cracker US) ou Lot (pour sa Kracrom spéciale Godfather), incorporer une option de sauvegarde de certaines pages mémoire lors d'un RESET Custom, est une évidence pour tout bidouilleur un peu curieux de nature. Sauvegarder, par exemple, les pages 0 à 8 pour examen ultérieur, serait une bonne idée...
Pourquoi cette partie en particulier ? Tout simplement parce que ces pages mémoire sont des zones clés de l'Apple II. Pour rappel :
- La page 0, utilisée par de nombreuses routines en ROM, est modifiée en permanence. Et de par les spécificités du 6502 (avec ses instructions dédiées), c'est une page particulièrement utilisée par les programmes.
- La page 1 contient la pile. Elle aussi change constamment au gré de l'exécution d'un programme.
- La page 2 correspond au buffer d'entrée. Le moindre appui sur une touche altère son contenu.
- La page 3, outre le fait de contenir plusieurs vecteurs intéressants, se trouve surtout au mauvais endroit : elle sera donc sauvée avec le reste (oui c'est super technique...).
- Les pages 4 à 7 correspondent aux adresses de l'écran TEXT, Page 1. Là par contre le moindre défilement vertical d'une ligne suffira à totalement modifier le contenu des 4 pages. À préserver donc !
- La page 8, elle, sera écrasée par le simple boot d'une disquette Dos. Autant en profiter pour la déplacer elle aussi.
Rien que l'appel au Monitor modifiera, au moins en partie, chacune de ces pages. On comprendra aisément que ce sont des endroits privilégiés pour y cacher des routines que l'on veut garder secrètes. D'où l’intérêt de pouvoir examiner ces pages et donc de les sauvegarder avant le saut au Monitor.
Le meilleur endroit pour déplacer ces zones mémoire, se situe au niveau de la page Hires 1. Essentiellement utilisée pour des images, on peut donc y loger provisoirement nos pages. L'essentiel étant de pouvoir les examiner à loisir sans perte de données après avoir récupéré la main.
Seul problème : une routine de déplacement, même très simple, prend de la place, il va donc falloir la loger quelque part. Sur IIe (et II+), la solution la plus évidente est de remplacer les routines Monitor WRITE et READ, utilisées par les commandes basic LOAD et SAVE. Attention, ne pas confondre avec les commandes DOS. Ici, on parle bien des deux commandes permettant de sauver vers, et de relire depuis, un magnétophone à cassette. Avec l'utilisation du DISK II, ces deux routines ne sont plus utilisées et laissent donc de la place pour y loger notre propre routine.
Sur IIe Enhanced, ces deux routines existent toujours. Toutefois, ce ne sont plus du tout les mêmes et il y a beaucoup moins de place disponible. Voilà pourquoi cette routine ne s'adresse qu'au IIe UnEnhanced (ou II+). Sur IIe Enhanced, il faudra trouver une autre place...
FA85- AD F2 03 LDA $03F2 ; test vecteur reset FA88- D0 0C BNE $FA96 ; non nul ? FA8A- AD F3 03 LDA $03F3 ; idem FA8D- D0 07 BNE $FA96 ; FA8F- AD F4 03 LDA $03F4 ; test octet contrôle FA92- C9 FF CMP #$FF ; égal à #$FF ? FA94- F0 10 BEQ $FAA6 ; oui ? alors go COLDSTART ! FA96- 4C 1D FD JMP $FF1D ; saut vers routine évoluée ! FA99- 00 00 ; octets inutilisés (mis à 00) FA9B- A0 03 LDY #$03 ; routine originale FA9D- 8C F2 03 STY $03F2 ; que l'on conserve car FAA0- 4C 00 E0 JMP $E000 ; utilisée par la modif Autostart FAA3- 4C 59 FF JMP $FF59 ; saut monitor ! |
La première partie de la routine est la même que pour le RESET simple. Seul le saut en $FA96 ne s'effectue plus vers $FAA3 mais vers $FF1D. Tout le reste est identique. On conserve donc l'Autostart (modifié ou pas) en cas de COLDSTART. Et on s'oriente vers notre routine perso en cas de RESET/WARMSTART.
FECD- 60 RTS ; neutralisation SAVE FECE- AD 00 C0 LDA $C000 ; attente FED1- 10 FB BPL $FECE ; de l'appui d'une touche FED3- 8D 10 C0 STA $C010 ; réinitialise clavier FED6- C9 C4 CMP #$C4 ; touche "D" (Dump) ? FED8- D0 38 BNE $FF12 ; non ? FEDA- A0 00 LDY #$00 ; oui FEDC- B9 00 00 LDA $0000,Y ; on commence FEDF- 99 00 20 STA $2000,Y ; par mover toute la page 0 FEE2- C8 INY FEE3- D0 F7 BNE $FEDC FEE5- 84 00 STY $00 ; afin d'utiliser FEE7- 84 02 STY $02 ; ensuite les octets FEE9- A9 01 LDA #$01 ; page 0 FEEB- 85 03 STA $03 ; pour un déplacement FEED- A9 21 LDA #$21 ; indexé FEEF- 85 01 STA $01 ; $0100 -> $2100 FEF1- D0 0B BNE $FEFE ; saut inconditionnel ici FEF3- 4C A6 FA JMP $FAA6 ; COLDSTART FEF6- 20 00 FE JSR $FE00 ; ne pas toucher FEF9- 68 PLA ; à cette partie FEFA- 68 PLA ; sous peine FEFB- D0 6C BNE $FF69 ; de gros problèmes FEFD- 60 RTS ; neutralisation LOAD FEFE- B1 02 LDA ($02),Y ; on déplace de $0100+ FF00- 91 00 STA ($00),Y ; vers $2100+ FF02- C8 INY FF03- D0 F9 BNE $FEFE FF05- E6 01 INC $01 FF07- E6 03 INC $03 FF09- A5 03 LDA $03 FF0B- C9 09 CMP #$09 ; est-ce la page 9 FF0D- D0 EF BNE $FEFE ; non ? on boucle FF0F- 4C 59 FF JMP $FF59 ; saut monitor ! FF12- C9 CD CMP #$CD ; est-ce la touche "M" (move) ? FF14- F0 F9 BEQ $FF0F ; si oui saut direct au monitor FF16- C9 D2 CMP #$D2 ; est-ce la touche "R" (reboot) ? FF18- F0 D9 BEQ $FEF3 ; si oui saut vers le COLDSTART FF1A- 6C F2 03 JMP ($03F2) ; toutes les autres touches envoient ; vers le vector Reset par défaut FF1D- A0 30 LDY #$30 ; petit son FF1F- A9 20 LDA #$20 ; pour le fun et FF21- 20 A8 FC JSR $FCA8 ; surtout pour avertir FF24- AD 30 C0 LDA $C030 ; l'utilisateur qu'il FF27- 88 DEY ; va falloir appuyer FF28- D0 F5 BNE ; sur une touche ! FF2A- 4C CE FE JMP $FECE ; saut au début de la routine |
La seconde partie de la routine demande quelques éclaircissements :
- $FECD et $FEFD sont les deux points d'entrées des routines WRITE et READ que l'on écrase. Pour éviter que les commandes LOAD et SAVE qui les utilisent ne plantent lamentablement, j'ai donc mis deux RTS pour les neutraliser.
- entre les routines WRITE ($FECD-$FEF5) et READ ($FEFD-$FF2C), il y a une zone à ne surtout pas écraser par notre code : $FEF6-FEFC (sous peine de gros problèmes). On passe donc par-dessus à l'aide d'un saut.
- en $FEDC, j'utilise un LDA $0000,Y (absolu, Y) et non pas un LDA $00,X (page 0, x).Les deux instructions utilisent le même nombre de cycles. Le LDA absolu est certes plus long d'un octet mais cet octet me sert justement à retomber sur mes pieds quand il faudra passer par-dessus la zone intouchable dont je parle juste au-dessus.
- pour atteindre le COLDSTART, on passe par un saut intermédiaire. Je ne pouvais faire un branchement direct par BEQ depuis $FF14 vers $FAA6 (déplacement trop important). Comme j'avais de la place avant la zone intouchable, j'ai déporté le JMP à cet endroit.
- la routine READ se termine officiellement en $FF3A. Toutefois la partie en $FF2D (qui affiche le message "ERR" suivi d'un joli BiP) est utilisée régulièrement pour signaler une erreur par des programmes tiers. Ne pas y toucher donc !
Sinon, au fait, elle fait quoi exactement cette routine ?
Et bien, suite à un Reset donc, après un petit "bip" (custom lui aussi), elle attend que l'on appuie sur une touche. Plusieurs choix possibles :
- touche "M" (pour Monitor) : nous envoie directement sous Monitor.
- touche "R" (pour Reboot) : nous envoie directement vers le COLDSTART et force donc un recheck des Slots par l'Autostart pour un reboot en bonne et due forme.
- touche "D" (pour Dump) : copie les pages 0 à 8 (inclues) vers l'espace $2000-$28FF et saute ensuite au Monitor.
- toute autre touche effectuera un saut vers le contenu du vecteur Reset. L'idée ici est d’effectuer ce que le programme avait prévu à la base en cas de RESET, comme par exemple revenir à un menu ou autre. J'attire toutefois votre attention sur les programmes qui s'amusent à corrompre uniquement l'octet de contrôle du vecteur Reset ($3F4) pour forcer un COLDSTART. Ils risquent ici de poser problème. En effet, vu qu'il n'y aura pas de COLDSTART effectué (ce qui est le but premier de la modification...) mais un saut vers le contenu du vecteur Reset, si celui-ci ne contient pas une adresse valide, plantage assuré. Forcez dans ce cas manuellement le saut au Monitor par "M" ou le reboot par "R".
Où effectuer les modifications ?
- à partir des offsets $1A85 pour la première partie et $1ECD pour la seconde dans une ROM de IIe UnEnhanced. Je rappelle que cette modification est non compatible avec la ROM IIe Enhanced !
- à partir des offsets $285 et $6CD pour un fichier F8.rom type AppleWin.