Obligement - L'Amiga au maximum

Mardi 17 octobre 2017 - 05:59  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

 · Accueil
 · A Propos
 · Articles
 · Galeries
 · Glossaire
 · Hit Parade
 · Liens
 · Liste jeux Amiga
 · Quizz
 · Téléchargements
 · Trucs et astuces


Articles

 · Actualité (récente)
 · Actualité (archive)
 · Comparatifs
 · Dossiers
 · Entrevues
 · Matériel (tests)
 · Matériel (bidouilles)
 · Points de vue
 · En pratique
 · Programmation
 · Reportages
 · Tests de jeux
 · Tests de logiciels
 · Tests de compilations
 · Articles divers

 · Articles in english
 · Articles in other languages


Twitter

Suivez-nous sur Twitter




Liens

 · Sites de téléchargements
 · Associations
 · Pages Personnelles
 · Moteurs de recherche
 · Pages de liens
 · Constructeurs matériels
 · Matériel
 · Autres sites de matériel
 · Réparateurs
 · Revendeurs
 · Presse et médias
 · Programmation
 · Développeurs logiciels
 · Logiciels
 · Développeurs de jeux
 · Jeux
 · Autres sites de jeux
 · Scène démo
 · Divers
 · Informatique générale


Jeux Amiga

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Trucs et astuces

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Glossaire

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Partenaires

Annuaire Amiga

Amedia Computer

Relec

Hit Parade


Contact

David Brunet

Courriel

 


En pratique : Déplombage de Turrican 2
(Article écrit par Alpha One et extrait de Flashtro.com - septembre 2004)


Note : traduction par David Brunet. Images par Christophe Escurat.

Prérequis
  • Un Amiga ou l'émulateur WinUAE.
  • Une cartouche Action Replay (ou l'image de sa ROM).
  • Le jeu original de Turrican 2 ou ses images CAPS.
  • Le logiciel PowerPacker ou XFD.
  • Un assembleur (ASM-One, Trash-M One, Seka ou similaire).
  • Les connaissances pour utiliser un de ces assembleurs.
Informations générales

Ce tutoriel est praticable uniquement par des personnes ayant déjà utilisé un assembleur et ayant programmé leur propre routine. Il est assez difficile d'écrire un tutoriel et, pour celui-ci, le rendre "tout public" est tout bonnement impossible. Par exemple, je ne vais pas expliquer ce que fait l'instruction "move" ou ce que veulent dire les mots "offset" ou "filelookuptable"...

De plus, cette méthode de déplombage n'est pas la seule. Comme je désire parler le moins possible sur la technique du "hardware-trackloading" (chargement matériel de piste), j'utiliserai une autre méthode dans ce déplombage, celle du "fileripping" (récupération de fichier).

Partie 1 : que se passe-t-il ?

Comme dans d'autres tutoriels, nous allons essayer dans un premier temps d'effectuer une copie de la disquette du jeu original de Turrican 2. Et devinez quoi ? Elle n'est pas vraiment copiable ! ;)

Déplombage de Turrican 2

Si on regarde de plus près l'écran de Trashcopy, nous pouvons voir que cette disquette est soit constituée d'un très grand nombre de "copylock" soit elle utilise simplement son propre format de piste. Pas besoin d'être clairvoyant pour deviner que la copie ne fonctionnera pas !

Commençons donc par charger la première piste (qui est la seule lisible) en mémoire pour voir ce qu'il se passe. Entrez dans votre Action Replay et tapez la commande suivante : "rt 0 1 50000".

Nous allons débuter par le désassemblage du code d'amorce. Tapons "d 5000c" et faisons défiler l'écran vers le bas, comme dans l'image ci-dessous.

Déplombage de Turrican 2

La première chose intéressante que nous pouvons voir ici est typique. A partir de l'adresse $50032-$50050, le trackdisk.device est utilisé pour lire $800 octets de la position de la disquette $400 vers la destination mémoire $60000.

Dans les deux dernières instructions à $50080/$50088, une exception est causée et notre petit programme se poursuit dans la mémoire à l'adresse $60000. Ceci sera donc probablement l'un des chargeurs ("loaders") du jeu !

Enregistrons dans un premier temps ces données sur une disquette. Insérons une disquette vierge dans df0: et sauvons tout ceci en tapant :

SM bootblock, 50000 50400
SM loader, 50400 50400+800

Poursuivons nos travaux avec le désassemblage du code de chargement ("loadercode"). Nous pourrions maintenant désassembler à partir de l'adresse $50400 mais, comme nous savons que le chargeur est situé à l'adresse mémoire $60000, nous allons, dans un premier temps, le charger à cette adresse avant de continuer. Tapons "LM loader, 60000" et commençons le désassemblage avec la commande "d 60000". Nous allons voir ceci :

Déplombage de Turrican 2

Le code commence avec quelques trucs standards comme l'arrêt de toutes les interruptions, le pointage de la pile de registres vers une zone quelconque de la mémoire, la définition d'une liste Copper et ainsi de suite...

Mais après ça, j'ai trouvé quelques lignes vraiment intéressantes. Jetons un coup d'oeil à l'instruction en $60030. La valeur du mot long $52412D49 est déplacée dans d0, la valeur $30000.l est déplacée en d1 (peut-être une adresse mémoire ?) et d'autres paramètres sont déplacés dans d2 ($1) avant d'appeler la routine située en $60164. Au retour de cette sous-routine, le programme saute en $3010A. Hummm... $3010A ?! Cela semble familier avec la valeur déplacée en d1 ($30000) avant le branchement en $60164. Allons jeter un coup d'oeil dans les quatre prochaines instructions : une valeur est encore déplacée dans d0 ($4D41494E.l), une autre dans d1 ($c0.l) même si d2 est encore définie à la valeur $1. Si nous continuons à dessassembler quelques lignes (pas de capture d'écran incluse), nous pouvons voir que le programme continue son exécution à l'adresse $c0 ! $c0 ? N'était-ce pas la valeur dans d1 avant que nous nous branchions en $60164 la seconde fois ?

Après avoir bu une autre bière, je me suis rendu compte que $60164 semble être une sorte de routine de chargement qui est appelée avec trois paramètres. d1 pourrait être l'adresse à laquelle le chargeur charge les pistes, mais que signifie la valeur dans d0 ?

Allons voir à l'adresse $60000 en ASCII (dans le chargeur donc). Tapons "n 60000" et regardons plus en détail :

Déplombage de Turrican 2

J'ai marqué en rouge les trucs intéressants. Nous pouvons voir les trois valeurs des mots longs "RA-I", "MAIN" et "PP20" (est-ce une entête PowerPacker ?), ce qui est vraiment intéressant. Il y a aussi quelques centaines d'octets dans le code qui sont complètement remplis de zéros ! Après avoir vérifié la manière dont les deux valeurs "RA-I" et "MAIN" sont incluses dans le code, je me suis aperçu que c'est le truc qui est déplacé vers d0 avant l'appel de notre chargeur. Le code de chargement se présente comme suit :

move.l #"RA-I",d0
move.l #$30000,d1
moveq #1,d2
bsr $60164
jsr $3010a
move.l #"MAIN",d0
move.l #$c0,d1
moveq #1,d2
bsr $60164

La valeur dans d0 semble contenir un nom de fichier. Si c'est le cas, le chargeur de jeu doit probablement disposer de quelque chose comme une table de correspondance qui dit au chargeur de piste où ces fichiers sont stockés sur la disquette. Mais impossible de trouver en mémoire, de $60000 à $60800, quelque chose de ce genre. Quoi qu'il en soit, essayons d'abord de récupérer ces deux fichiers, nous trouverons la signification du troisième paramètre dans d2. Peut-être allons-nous découvrir une table de correspondance dans la mémoire lorsque le chargeur sera appelé la première fois.

Insérons maintenant la disquette originale de Turrican 2 et allons faire quelques modifications dans le code de chargement.

Déplombage de Turrican 2

Nous allons insérer deux lignes de code à l'adresse $60042 juste après le retour de la probable routine de chargement de piste. Cela définira la couleur de l'écran en rouge dans une boucle infinie. Entrons le texte suivant :

a 60042
^60042 move.w #$f00,$dff180
^6004a bra $60042

Sautons ensuite dans le code de chargement en tapant "g 60000".

Après quelques chargements de piste, l'écran vire au rouge et plus rien ne se passe. Le chargeur de piste en a donc fini avec le fichier et le processeur semble avoir accroché notre boucle.

Déplombage de Turrican 2

Entrons donc dans notre Action Replay pour voir ce qu'il se passe : si le paramètre dans d1 ($30000) est vraiment une adresse mémoire, nous allons peut-être voir quelques bouts de code intéressants. Allons voir cela !

Tapons "n 30000".

Déplombage de Turrican 2

Voilà, vous êtes en mesure de voir que le chargeur a vraiment chargé des données non décompressées dans la mémoire. Au lieu de déplacer $1 dans d2, allons voir ce que le chargeur fait si nous l'effaçons. Désassemblons le code encore une fois pour trouver où l'instruction "moveq #1,d2" est exécutée et remplaçons-la par un "moveq #0,d2" comme ceci :

Déplombage de Turrican 2

a 6003c
^6003c moveq #0,d2
^6003e

Déplaçons-nous à nouveau vers le chargeur en tapant "g 60000".

Après quelques chargements de pistes, nous pouvons voir notre écran virer au rouge. Entrons avec l'Action Replay et jetons un coup d'oeil à l'adresse mémoire $30000. Tapons "n 30000" et regardons ce qu'il s'est passé.

Déplombage de Turrican 2

Oui, les données commencent par "PP20", ce qui signifie que le chargeur vient juste de lire les pistes du fichier sans le décompresser. Donc le paramètre d2 semble indiquer au chargeur si le fichier est compressé avec PowerPacker ou s'il est compressé par autre chose.

Maintenant, nous connaissons comment le chargeur fonctionne. Regardons ce qu'il se passe dans le code de chargement à l'adresse $60000. Nous avions parlé d'une certaine table de correspondance quelques lignes plus haut, regardons si quelque chose a changé. Tapons "n 60000".

Déplombage de Turrican 2

La région qui était précédemment remplie de zéros, et qui appelait le chargeur de piste, est maintenant remplie de données. Regardons d'un peu plus près ces octets. Tapons "m 60204" et descendons de quelques lignes.

Déplombage de Turrican 2

Oui ! Ça ressemble à une table de correspondance pour moi ça, hein ? Elle commence par le fichier "RA-I" et finit par le fichier "L4-1" et "MUS4" ! (souvenez-vous de la taille de table : 400 octets).

Faisons une petite pause et mettons à plat ce que nous connaissons maintenant. Nous sommes en état de pouvoir récupérer les fichiers présents dans la table de correspondance en appelant la routine de chargement et en passant le nom de fichier dans d0. Mais comment connaître la taille de chaque fichier ? Est-ce que cette valeur est aussi incluse dans la table de correspondance, et si oui, qu'elle valeur est-ce ? Il y a beaucoup de valeurs entre chaque nom de fichier. Essayons de trouver les bonnes valeurs grâce à quelques trucs simples. Nous allons appeler le chargeur une nouvelle fois pour qu'il charge les pistes du fichier "RA-I" dans la mémoire à l'adresse $30000. Mais cette fois, nous allons remplir cette partie de la mémoire avec des "A" : ainsi, quand le chargement sera fini, nous pourrons voir combien d'octets ont changé.

Tapons "o "A", 30000 50000". Cela remplie la mémoire de $30000 à $50000 avec la valeur donnée. Ensuite, faisons un autre saut vers notre routine de chargement avec la commande "g 60000".

Après l'écran rouge, nous entrons de nouveau dans l'Action Replay et descendons de quelques lignes depuis l'adresse $30000 jusqu'à voir les centaines d'octets "A". Après avoir vérifié où est-ce que les premiers "A" apparaissent, nous notons une longueur de $40f0 octets ! Rappelons-nous de cette valeur et regardons encore une fois dans la table des fichiers stockée en $60204. Strike ! Regardons la valeur du mot long à l'offset $8 depuis le début de la table. Cela doit être la taille. Essayons maintenant de charger le fichier "MAIN" dans la mémoire pour nous en assurer. Remplissons donc une nouvelle fois la mémoire à l'adresse $30000 avec des "A" comme précédemment, puis faisons ce qui suit :

Déplombage de Turrican 2

Changeons maintenant la valeur qui a été mise dans d0 de "RA-I" à "MAIN" à l'adresse $60030. Tapons "n 60032" (nous prenons l'adresse $60032 car les deux premiers octets sont l'instruction "move.l").

Remplaçons les quatre octets "RA-I" en "MAIN" et appuyons sur "Entrée" pour que l'Action Replay reconnaisse notre petit changement. Il faut bien écrire "MAIN" et non "main" ou "Main" car le chargeur ne trouvera pas le fichier dans la table de correspondance. Continuons et déplaçons-nous une nouvelle fois vers notre chargeur en tapant "g 60000". Après quelques chargements de pistes, l'écran vire de nouveau au rouge, nous savons donc que le chargement est fini. Descendons dans l'écran à l'adresse $30000 (en outre, "MAIN" semble aussi être compressé avec PowerPacker) jusqu'à atteindre notre zone remplie de "A". Rappelons-nous la longueur des données du fichier (qui devrait être de $e068 octets) et comparons-la avec la valeur dans la table de correspondance. Nous avions raison, c'est la même.

Bien, nous pouvons maintenant commencer par récupérer tous les fichiers de la disquette originale, mais attendons encore un peu ;). Maintenant que nous connaissons beaucoup de choses sur la façon dont le chargeur fonctionne, nous allons d'abord démarrer le jeu pour vérifier ce que fait le fichier "MAIN" après avoir été chargé en mémoire $c0. Comme nous devrons remettre ces fichiers sur une disquette plus tard et que nous devrons écrire notre propre chargeur de piste, il serait intéressant de savoir de combien de parties le chargeur du jeu est constituées, car nous allons devoir toutes les modifier.

Réinitialisons notre machine et insérons la disquette originale. Quand l'introduction de Rainbow Arts se termine et que le jeu charge quelques données depuis la disquette, entrons dans l'Action Replay et allons désassembler le code à l'adresse $c0, là où le fichier "MAIN" doit être situé. La première instruction est un branchement vers une autre adresse mémoire ($123e, capture d'écran non incluse), continuons donc de désassembler à l'adresse $123e. Tapons "d $123e"

Déplombage de Turrican 2

Nous pouvons voir dans ces lignes de code quelque chose de familier. A l'adresse $1294, une autre routine est appelée deux fois avec un branchement en $6f8 qui semble prendre les mêmes paramètres que dans notre premier chargeur ! C'est bien car nous avons besoin de programmer un seul chargeur de piste, un pour le chargeur en $60000 et un pour celui situé quelque part dans le fichier "MAIN". Avant d'aller plus loin dans le chargeur de piste, jetons un oeil dans la mémoire à l'adresse $c0 en ASCII pour voir s'il y a une autre table de correspondance, ou si l'ancienne en $60204 est utilisée. Tapons "n c0" et descendons quelques lignes plus bas.

Déplombage de Turrican 2

Comme nous pouvons le voir, il y a quelque chose d'intéressant qui commence à l'adresse $802. C'est notre table de correspondance que nous avons vue précédemment. Mais si nous descendons de quelques lignes, nous pouvons voir que cette nouvelle table semble complète car elle ne finit pas par "L4-1" et "MUS4" mais par "L5-2" et "EDAT", qui sont probablement le "END-DATA", soit la fin des données ! Sauvons donc sur disquette cette nouvelle table de correspondance pour une utilisation ultérieure. Tapons "SM filelist, 802 9e2".

Souvenons-nous que la taille de cette nouvelle table complète est de !480 octets.

Après avoir réalisé quelques tests, je suis arrivé à la conclusion qu'il n'y a qu'un seul chargeur, situé en $6f8, que le jeu utilise jusqu'à la fin.

Passons à quelque chose de plus facile. Comme nous connaissons tous les noms des fichiers, nous pouvons donc continuer notre petit déplombage en récupérant ces fichiers sur notre disquette. Nous allons utiliser le premier chargeur pour cela. Redémarrons notre machine, insérons notre disquette de sauvegarde et chargeons notre fichier nommé "loader" (chargeur) que nous avons préalablement sauvé au début de notre tutoriel à l'adresse $60000. Tapons donc "LM loader, 60000".

Maintenant, nous avons de quoi faire pour la prochaine heure en récupérant tous les fichiers. Si vous êtes un programmeur, vous pourriez programmer quelques lignes afin de récupérer tous les fichiers automatiquement.

Partie 2 : récupération des fichiers

Maintenant que nous avons le chargeur original à l'adresse $60000, les choses deviennent de nouveau intéressantes !

Comme nous le savons, le premier chargeur a une table de correspondance incomplète, donc après avoir récupéré tous les fichiers de "L4-1" et "MUS4", nous devrons écraser certains noms de fichiers avec ceux restants, en incluant toutes les données comme la taille, etc. Commençons par modifier le chargeur de fichier ("loaderfile") comme indiqué au début de ce tutoriel.

Important : les fichiers sur la disquette sont stockés dans l'ordre qu'ils apparaissent dans la table de correspondance. J'ai eu quelques problèmes en essayant de récupérer les fichiers dans un ordre aléatoire. Il n'est pas possible de récupérer les données de "L4-1" puis celles de "RA-I" qui, lui, se trouve au début de la table de correspondance. Il nous sera plus facile de noter sur un morceau de papier chaque nom de fichier à récupérer, avec sa longueur, et le tout dans le bon ordre. Ce chargeur n'aime pas revenir sur le fichier précédent ! Commençons donc par modifier notre chargeur une seconde fois :

a 60042
^60042 move.w #$f00,$dff180
^6004a bra $60042

Cela arrêtera de nouveau le processeur, au niveau de notre routine de l'écran en rouge, après chaque chargement des pistes de données de nos fichiers. Continuons donc en récupérant les fichiers de "RA-I" à "MUS4" qui sont les dernières entrées dans notre table (incomplète) de correspondance. Assurons-nous d'avoir une seconde disquette formatée car une seule ne suffira pas.

En premier lieu, écrasons le "moveq #1,d2" avant que le chargeur ne soit appelé dans "moveq #0,d2" car nous voulons disposer des données dans l'état où elles sont stockées sur le disque, et non pas dans un état décompressé.

a 6003c
^6003c moveq #0,d2
^6003e

Si l'ordinateur plante durant l'action de récupération et que nous ne voulons pas refaire ces correctifs à chaque fois, nous pouvons sauver ce chargeur modifié sous le nom de "loaderp" sur notre disquette et le recharger à la place de notre chargeur ("loader") non modifié. Comme le fichier "RA-I" est le premier à être chargé, nous n'avons pas besoin d'en faire plus que de nous déplacer dans notre code de chargement à l'adresse $60000, en tapant "g 60000" et d'attendre que l'écran rouge apparaisse. Entrons dans notre Action Replay et sauvons le tout avec la commande "SM ra-i, 30000 340f0" car nous connaissons maintenant la longueur de chaque fichier (offset +$8 dans la table de correspondance pour chaque entrée). Évidemment, il faut penser à changer de disquette avant de sauver le fichier et avant de charger les pistes du prochain fichier de la disquette originale.

Il est temps maintenant de changer le nom qui a été déplacé dans d0 à l'adresse $60030 avant que le chargeur ne soit appelé. Tapons "n $60032" (les deux octets en $60030 sont notre instruction "move.l") et écrasons le mot long "RA-I" avec le nom de fichier suivant de notre table de correspondance, en l'occurrence "MAIN", puis appuyons sur la touche "Entrée". Voilà maintenant ce que nous devons faire :
  1. Insérons notre disquette originale.
  2. Déplaçons-nous dans le code de chargement avec la commande "g 60000".
  3. Insérons notre disquette de sauvegarde.
  4. Sauvons le fichier avec la commande "SM filename, $30000 $30000+filesize".
  5. Changeons le nom du fichier qui a été déplacé dans d0 avec la commande "n 60032", puis entrons le nouveau nom du fichier et appuyons sur "Entrée".
  6. Retournons au point 1.
Note : Si notre ordinateur plante, par exemple sur le fichier "L1-1", nous n'aurons pas à recommencer depuis le début (fichier "RA-I") après le redémarrage de notre machine. Donc chargeons simplement le chargeur modifié, poursuivons avec le dernier fichier que nous étions en train de récupérer, puis continuons avec le prochain fichier dans la table et ainsi de suite.

Poursuivons cette procédure jusqu'à ce que nous ayons récupéré le fichier nommé "MUS4" qui est la dernière entrée de notre table de fichiers à l'adresse $60204. Pour finir avec les derniers fichiers (L4-2, L5-1, MUS5, L5-2 et EADT), nous allons copier ces cinq fichiers depuis la table complète de la disquette vers la table que nous utilisons pour le moment à l'adresse $60204. Nous pouvons écraser les cinq premières données sans problèmes car nous les avons déjà récupérées ces fichiers. Insérons donc notre disquette de sauvegarde et tapons "LM filelist, 5f000". Descendons tout à la fin en utilisant la commande "m 5f000".

Déplombage de Turrican 2

Copions le bloc mémoire avec les cinq derniers fichiers dans notre table de correspondance à l'adresse $60204. Tapons : "trans 5f190 5f1e0 60204".

Maintenant, nous pouvons continuer de récupérer les derniers fichiers "L4-2" à "EDAT" comme nous l'avons fait précédemment.

Félicitation ! Nous pouvons ranger notre disquette originale dans sa boîte, nous n'en aurons plus besoin.

Note : afin de rendre les choses plus faciles, cela serait une bonne idée que de créer un répertoire sur notre disque dur et de copier tous les fichiers dedans.

Partie 3 : comprendre la routine "trackloading" (chargeur de piste)

Nous devons à présent programmer... puisque nous devrons remettre ces fichiers sur disquette. Nous devons donc programmer notre propre chargeur de piste, et donc savoir comment ce chargeur de piste de Turrican 2 fonctionne. Comme nous l'avons vu au début de ce tutoriel, il y a trois paramètres à définir (d0, d1 et d2) avant d'appeler le chargeur. Comme nous le savons, le troisième paramètre contenu dans d2 sert à la décompression ou une chose comme ça. Donc la routine à l'adresse $60164 n'est pas uniquement le pur chargeur de piste... il semble également être composé d'une autre routine qui permet de décompresser les pistes de données. Nous avons récupéré les fichiers dans leur format compressé, donc nous avons encore besoin de cette routine de décompression. Essayons donc de trouver où le "vrai" chargeur de piste débute, et de quels types de paramètres a-t-il besoin pour fonctionner. Désassemblons notre chargeur à partir de l'adresse $60164. Tapons "d 60164" et faisons défiler quelques lignes...

Déplombage de Turrican 2

$60164 TST.L $60204  ; Est-ce que la table de correspondance est déjà chargée ?
$6016A BNE $60186    ; Oui... on continue. 
$6016C ... 
$60170 ... 
$60176               ; Pas nécessaire pour nous. Un branchement vers une
$60178               ; routine qui semble définir la table de correspondance à l'adresse $60204
$6017A ... 
$6017E ... 
$60182 ...
$60186 LEA $60204(PC), A1 ; Stocke l'adresse dans notre table de fichiers en A1.
$6018A MOVEQ #$18, D3     ; Combien de fichiers sont stockés dans la table de correspondance. 
$6018C CMP.L (A1), D0     ; Compare le nom de fichier donné en D0 avec l'entrée de la table de correspondance. 
$6018E BEQ $6019C         ; Trouve le fichier... Continue le code en $6019C
                          ; (A1 pointe maintenant vers l'entrée correcte dans la table des fichiers) 
$60190 LEA $10(A1), A1    ; Laisse la table des fichiers sur la prochaine entrée.
$60194 DBF D3, $6018C     ; Continue à chercher tant que d3 ne donne pas "-1".
$60198 MOVEQ #$-1, D0     ; Code d'erreur dans D0 -> fichier non trouvé ! ;) 
$6019A RTS                ; Retourne là d'où l'on vient.
-----------------------------------------------------------------------------------------------
$6019C MOVE.L 8(A1), D0   ; Vous rappelez-vous de l'offset $8 ? -> Déplacement de la longueur du fichier dans D0.
$601A0 MOVE.L D1, A0      ; Vous rappelez-vous de D1 ? -> Mettre notre adresse "où chargé ?" dans A0.
$601A2 BTST #$0, D2       ; Vous rappelez-vous de notre paramètre de compression D2 ? -> Teste l'octet 0 ?
$601A6 BEQ.B $601B8       ; Zéro... pas besoin de décompresser... continue en $601B8.
$601A8 SUBQ.L #$8, A0     ; Eh bien... notre adresse "où chargé ?" est soustraite de 8.
$601AA MOVE.L (A0), $601FC ; Sauve les 8 octets avant de charger la vraie adresse de chargement.
                           ; Cela semble définir 8 octets.
$601B0 MOVE.L 4(a0), $60200 ; Pour l'entête "PP20" (4 octets) qui inclus la taille
                            ; du fichier décompressé (4 octets). 
$601B8 MOVEM.L D1-D2/A0-A1, -(A7) ; Sauve les éléments nécessaires dans la pile.

Maintenant, ouvrons nos yeux, les quatre instructions importantes arrivent :

$601BC MOVE.W 4(A1), D1   ; La valeur du mot située à l'offset+4 de la table des fichiers en d1.
$601C0 MOVE.W 6(A1), D2   ; La valeur du mot située à l'offset+6 de la table des fichiers en d2.
$601C4 EXT.L D2           ; Élargie D2 en un mot long.
$601C6 BSR.W $60394       ; Devinez quoi ? C'est notre chargeur de piste !
$601CA ...

A présent, il n'y a plus rien d'autre à savoir concernant notre chargeur de piste. Il est situé à l'adresse $60394 et il prend les paramètres suivants :
  • D0.L : longueur du fichier.
  • D1.W : valeur du mot stocké dans la table des fichiers à l'offset +$4.
  • D2.W : valeur du mot stocké dans la table des fichiers à l'offset +$6 (élargie en mot long).
  • A0.l : adresse mémoire.
Les registres dans d1 et d2 sont sûrement utilisés pour dire au chargeur où est-ce que le fichier est situé sur la disquette. Quelque chose comme D1=numéro de la piste, et D2=offset depuis le début de la piste. Le même code que ci-dessus est utilisé dans le fichier "MAIN". Le chargeur de piste commence en mémoire à l'adresse $9e2 et, bien sûr, il prend les mêmes paramètres. Je pense qu'il n'est pas nécessaire d'ajouter une capture d'écran pour cela.

Mais ne nous préoccupons pas davantage de cela. La prochaine partie permettra de sauver les fichiers enregistrés sur une disquette DOS standard en utilisant le trackdisk.device et en faisant quelques modifications dans la table de correspondance. Nous ne pouvons pas placer les fichiers au même endroit que sur la disquette originale car il n'y a pas la même quantité de données sur une piste DOS que sur la disquette de jeu de Turrican 2.

Partie 4 : créer l'image-disque

Toute cette partie a été faite en utilisant (dans mon cas) l'assembleur ASM-One.

Si nous additionnons toutes les tailles de nos fichiers, cela ne rentre pas sur une seule disquette. Donc sur la première disquette, nous allons placer les fichiers de "A-I" à "L3-3" et sur la seconde disquette, nous mettrons le reste des fichiers. Nous aurons donc à changer de disquette avant le niveau 4 ! Pour indiquer au chargeur à quelle disquette le fichier en question appartient, nous utiliserons, dans la table des fichiers, le numéro des pistes de 0 à 159 pour la disquette 1 et de 160 à xxx pour la seconde disquette (une disquette est composée de 160 pistes, numérotées de 0 à 159).

Avant de réaliser cette image-disque, nous devons encore faire une chose. Nous savons qu'il y a un chargeur distinct dans le fichier "MAIN" que nous devons aussi modifier. Comme nous avons sauvé le fichier "MAIN" dans un format PowerPacker, nous devons, dans un premier temps, le décompresser et l'enregistrer sous forme décompressé sur notre disquette, cela facilitera notre prochain correctif (et facilitera le travail des gens qui voudront réaliser un mode de triche pour le jeu, hé hé).

Commençons donc par décompresser le fichier en utilisant PowerPacker ou XFD et sauvons notre fichier décompressé (!132568 octets) sur une de nos disquettes de sauvegarde. Écrasons le vieux fichier "MAIN" dont nous n'avons plus besoin dans sa forme compressée. Il est maintenant temps de lancer notre assembleur, dans mon cas, c'est ASM-One, et commençons par écrire l'image-disque. Réservons un peu de mémoire, passons en mode "édition" en appuyant sur "ESC" et tapons le code suivant (bien sûr, vous devez changer le chemin où vous allez sauver vos fichiers) :

Déplombage de Turrican 2

Si vous n'avez pas assez de mémoire de libre dans votre machine, vous devez écrire l'image-disque en deux étapes (voir partie 6). De plus, si vous ne disposez pas d'un disque dur et que vous avez les fichiers stockés sur deux disquettes, vous devez aussi utiliser cette méthode.

Nous intégrons d'abord le bloc d'amorce (!1024 octets) suivi par le premier chargeur (!2048 octets). Puis, nous remplissons les !2560 octets restants de la piste 0 (une piste dispose d'une taille de !5632 -$1600- octets) avec des zéros ! Nous insérons ensuite trois pistes vides pour une jolie "cracktro", suivi par les fichiers du jeu qui apparaissent dans la table de correspondance. Nous sauverons toutes les données sur disquette plus tard, en utilisant la commande "wt" (Write Track) d'ASM-One.

Si vous avez fini avec l'image-disque, nous pouvons commencer à écraser les valeurs originales dans la table des fichiers avec nos propres positions de pistes de notre disquette de déplombage. Quittons le mode "édition" en appuyant sur "ESC" et sauvons le code source de l'image-disque sur notre disquette en utilisant la commande "w", en le nommant par exemple "image".

A présent, effaçons le code source en utilisant la commande "ZS" (Zap Source) pour commencer notre petit code correctif de la table des fichiers. Nous allons programmer quelques instructions qui vont remplir la table de correspondance automatiquement avec les valeurs correctes. Repassons de nouveau en mode "édition" (j'espère que vous connaissez maintenant la touche à presser) et tapons (encore une fois, n'oubliez pas de changer le chemin de la table des fichiers, les explications suivent) :

Déplombage de Turrican 2

La seconde instruction est vraiment importante, c'est dû au fait que nous avons décompressé le fichier "MAIN", nous devons écrire une nouvelle taille de fichier, qui est de !132568 ($205d8) octets, dans la table des fichiers (chaque entrée est de $16 octets, donc l'offset de la taille du fichier "MAIN", qui est le deuxième fichier de la table, est à l'offset !16 + !8).

Dans le code source, un compteur d'octets dans d1 est utilisé pour stocker la position actuelle du fichier de jeu sur la disquette, en tant que valeur d'octets (bytevalue). Nous commençons donc avec "RA-I" sur la piste 4 qui semble être à la position disquette 4*$1600 (rappelez-vous, une piste a une taille de $1600 octets). Ensuite, le compteur d'octets est divisé par $1600 pour avoir le numéro de piste courant du fichier ("4" dans la première boucle) et le stocke dans la table des fichiers. Nous permutons ensuite la valeur pour avoir le reste de notre division qui est en fait l'octet d'offset du fichier sur la piste ("0" dans la première boucle).

Maintenant, la taille de fichier de l'actuel fichier ($40f0 dans la première boucle) est ajoutée à la valeur de notre compteur d'octets dans d1, le changeant alors en 4*$1600+$40f0. Enfin, nous pointons a0 sur la prochaine entrée dans notre table des fichiers et recommençons la même manipulation jusqu'à la fin de la table des fichiers. Si le fichier "L4-1" est atteint, le compteur d'octets est positionné à 160*$1600 car, à partir de maintenant, les fichiers appartiennent à la deuxième disquette et recommencent en piste 0 ! Notre propre chargeur va vérifier la position de la piste et, si elle est plus large que 159, il affichera un flash d'écran pour que l'utilisateur sache que la disquette doit être changée (évidemment, cela fonctionne aussi dans l'autre sens : si la disquette 2 est dans le lecteur et que la disquette 1 est demandée).

Bien, quittons le mode "édition" en appuyant sur la touche "ESC" et commençons par assembler le tout. Tapons "A" et appuyons sur la touche "Entrée". Si nous avons tout bien tapé et que nous ne voyons pas de message d'erreurs, lançons le code avec la commande "J" et appuyons sur "Entrée". Maintenant, notre table de fichiers devrait être modifiée. Vérifions cela en utilisant la commande "H filetable" et appuyons sur "Entrée". Nos valeurs dans la table des fichiers doivent ressembler à cela :

Déplombage de Turrican 2

Si vous voyez la même chose sur votre écran, alors sauvez la table des fichiers modifiés sur la disquette. Nommez-la par exemple "filetablepatched".

Partie 5 : modifier le chargeur et le fichier "MAIN"

Dans ce tutoriel, je ne vais pas vous expliquer comment le chargement matériel de piste a été programmé ou comment les données sont stockées sur disquette au format MFM, car ce tutoriel ne se concentre que sur le déplombage de Turrican 2. Notre chargeur devra fonctionner avec les mêmes paramètres donnés dans les mêmes registres que le chargeur original, donc notre routine de chargement de piste fonctionnera aussi avec les paramètres suivants :
  • D0.l = octets à lire.$
  • D1.w = numéro de la piste (là où se situe le début des données).
  • D2.l = octets de l'offset (là où notre fichier commence sur la piste).
  • A0.l = adresse mémoire de chargement.
Vous ne pourrez pas comprendre les prochaines lignes si vous n'avez jamais programmé un chargement matériel de piste. Mais je vais tout de même le poster ici, vous pourrez donc le copier-coller dans votre code source. Je ne vais pas non plus vous montrer ici toutes les captures d'écran car, devinez quoi, vous ne pourrez pas faire de copier-coller depuis des images :-). Ce chargeur est un broyeur de piste ("trackgrinding") car il est toujours un pas derrière la piste 0, puis va ensuite jusqu'à la piste où le fichier courant est situé. Appréciez le son du lecteur de disquette ! ;)

; =================================
; Trackloader for Turrican 2.
; D0.l = Bytes to read
; D1.w = Tracknumber
; D2.l = Trackoffset
; A0.l = Buffer to read
; A6.l = $dff000
;==================================

trload:
lea diskstatus(pc),a4
cmp.w #160,d1
blt.b disk1
disk2:
sub.w #160,d1
tst.b (a4)
bne.b crdisk
move.b #1,(a4)
bra.b flash
disk1:
tst.b (a4)
beq.b crdisk
move.b #0,(a4)
flash:
move.w d5,$180(a6)
subq.w #1,d5
btst #6,$bfe001
bne.b flash
crdisk:
lea $bfd100,a4
lea bytecounter(pc),a2
lea kopfstatus(pc),a3
move.l #0,(a2)
move.b #0,(a3)
move.b #%01111101,(a4)
nop
nop
move.b #%01110101,(a4)
bsr.w diskok
add.l d2,d0
mvzero:
btst #4,$bfe001
beq.b trzero
bset #1,(a4)
bsr.w movehd
bsr.w delay
bra.w mvzero
trzero:
bsr.w diskok
moveq #0,d3
move.b d1,d3
divs.w #2,d3
move.l d3,d1
swap d1
cmp.w #0,d1
beq.b headd
bclr #2,(a4)
bsr.w delay
move.b #1,(a3)
bra.b mvzyl
headd:
bset #2,(a4)
bsr.w delay
move.b #0,(a3)
mvzyl: 
cmp.b #0,d3
beq.b zylok
moveit:
bsr.w delay
bclr #1,(a4)
bsr.w movehd
dbf d3,mvzyl

zylok:
bsr.w diskok
bsr.w readtr
bra.w decode

trdone:
cmp.b #1,(a3)
bne.b headup
bset #2,(a4)
move.b #0,(a3)
moveq #1,d3
bra.b moveit
bclr #1,(a4)
bsr.w movehd
bsr.w delay
bra.b zylok

headup: 
bclr #2,(a4)
move.b #1,(a3)
bra.w zylok

ready:
bsr.w delay
move.b #%11111101,(a4)
nop
nop
move.b #%11100111,(a4)
rts

diskok: 
btst #5,$bfe001
bne.b diskok
rts

readtr: 
move.w #$2,$9c(a6)
move.w #$8210,$96(a6)
clr.w $24(a6)
move.l #$74000,$20(a6)
move.w #$4489,$7e(a6)
move.w #%0111111100000000,$9e(a6)
move.w #%1001010100000000,$9e(a6)
move.w #$9900,$24(a6)
move.w #$9900,$24(a6)
dwait: 
btst #1,$1f(a6)
beq.b dwait
clr.w $24(a6)
rts

movehd: 
bclr #0,(a4)
nop
nop
nop
bset #0,(a4)
rts

delay: 
move.w #$4000,d4
wait:
dbra d4,wait
rts

decode: 
move.l #$55555555,d4 
moveq #0,d5
dec: 
lea $74000,a1
ssync: 
cmp.w #$4489,(a1)+
bne.b ssync
cmp.w #$4489,(a1)
beq.b ssync
move.l (a1),d3
move.l 4(a1),d1
and.l d4,d3
and.l d4,d1
asl.l #1,d3
or.l d1,d3
ror.l #8,d3
cmp.b d5,d3
beq.b bfound
add.l #1086,a1
bra.b ssync
bfound: 
add.l #56,a1
move.l #(512/4)-1,d6
decbl: 
move.l 512(a1),d1
move.l (a1)+,d3
and.l d4,d3
and.l d4,d1
asl.l #1,d3
or.l d1,d3
cmp.l (a2),d2
bgt.b ofschk 
move.l d3,(a0)+
ofschk: 
addq.l #4,(a2)
cmp.l (a2),d0
ble.w ready
dbra d6,decbl
cmp.b #10,d5
beq.w trdone
addq.b #1,d5
bra.w dec

bytecounter: dc.l 0
kopfstatus: dc.b 0
diskstatus: dc.b 0
trloadend:

Maintenant, si vous êtes prêt à taper (ou coller) le code source, il faut faire ceci :
  • Assemblons le tout en utilisant la commande "a" puis appuyons sur "Entrée".
  • Sauvons le chargeur de piste sur la disquette en tant que binaire en utilisant la commande "wb".
  • Nommons-le par exemple "trloader", et le label "trload" - "trloadend", qui fait exactement 484 ($1e4) octets au total.
N'oublions pas de sauver le code source. Il est temps maintenant de modifier nos deux fichiers, "loader" et "MAIN" avec la nouvelle table des fichiers et la nouvelle routine de chargement de piste.

Retournons à notre Action Replay. Commençons par le chargeur ("loader"). Tapons "LM loader, $50000" et appuyons sur "Entrée". Nous savons que la table de correspondance est stockée à l'adresse $60204 dans la mémoire, donc l'offset du début de notre routine "loader" est $204. Chargeons donc notre table de fichiers modifiée vers l'adresse $45000 et copions-la dans notre code de chargement. Tapons "LM filetablepatched, $45000".

Transférons maintenant ses 400 premiers octets à la position correcte (nous ne prenons que les 400 premiers octets car, comme nous le savons, la table de correspondance dans le chargeur n'est pas complète : copier la totalité de nos 480 octets pourrait écraser un peu notre chargeur de piste qui est situé à la fin de la table des fichiers). Tapons "trans $45000 $45000+!400 $50204".

Nous devons maintenant faire la même chose avec la routine de chargement de piste. Comme nous l'avons vu dans la partie précédente, le chargeur de piste commence en $60394, ce qui veut dire que l'offset de notre chargeur commence en $394. Chargeons donc également le chargeur de piste, nous prendrons l'adresse $46000 pour lui. Tapons "LM trackloader, $46000" et copions-le dans le chargeur en utilisant la commande "trans $46000 $46000+!484 $50394".

Avant d'écrire le chargeur modifié, revenons sur la disquette : nous ne devons pas oublier de changer le paramètre dans d2 avant que le chargeur essaye d'attraper le fichier "MAIN" dans #0. Ceci car nous allons sauver le fichier "MAIN" sous forme non compressé sur la disquette. Si nous laissons le "moveq #1,d2" dans le code, le chargeur essayera de décompresser le fichier, ce qui causera un plantage du jeu ! Changeons donc cette instruction maintenant. Tapons "a 50054", insérons un "moveq #0,d2" et appuyons sur "Entrée". Maintenant, nous sommes prêts à écrire le chargeur modifié sur notre disquette. Tapons "SM loader, $50000 $50000+!2048".

Bien. Il faut maintenant procéder à la même action de modification avec le fichier "MAIN". Chargeons ce fichier avec la commande "LM main, $50000". Nous savons que la table de correspondance est stockée à l'adresse mémoire $802, donc l'offset du début du fichier "MAIN" est $742 ($802-$c0). Copions donc la table de correspondance complète avec la commande "trans $45000 $4500+!480 $50742". Maintenant, effectuons la même chose pour le chargeur de piste qui est en mémoire à l'adresse $9e2, l'offset de l'adresse de départ est donc : $922 ($9e2-$c0). Tapons "trans $46000 $46000+!484 $50922".

Notre fichier "MAIN" est à présent également modifié. Mais avant de le sauver, nous devons modifier encore deux choses que je vais d'abord expliquer : le jeu charge et sauve les meilleurs scores, ce qui provoquera un plantage du jeu s'il ne trouve pas le format original de piste sur notre version déplombée. Il y a deux "branchements" simples que nous devons enlever pour que cela ne se produise pas. Comment ai-je trouvé ces branchements ? Je n'ai pas d'explication car il n'y a pas de technique spéciale pour les trouver. Parfois, vous pouvez passer des heures à chercher des satanés sauts !

Bref, nous trouverons ces deux satanés branchements ici :

Déplombage de Turrican 2

Remplaçons donc le premier par un "nop" et le second par un "rts" comme ceci :

A $511D0
^511d0 nop
^511d2 nop
^511d4

...et finalement :

A $5032e
^5032e rts
^50330

Sauvons ce fichier sur la disquette en utilisant la commande "SM main, $50000 $50000+!132568".

Partie 6 : écriture des images-disques

Réinitialisons notre machine et chargeons l'assembleur. Réservons environ 1,2 Mo de mémoire (car nous allons charger l'ensemble des fichiers en mémoire d'un seul coup) et préparons-nous à sauver notre déplombage sur disquette !

Chargeons le code source de notre image dans l'éditeur en utilisant la commande "R" et assemblons-le, toujours en utilisant la commande "A". Après un assemblage sans erreur, insérons une nouvelle disquette vierge dans le lecteur DF0: grâce à la commande "WT". Indiquons à l'éditeur d'écrire depuis l'adresse mémoire "BOOT:", ce qui correspond aux pistes 0 à 144. (nous écrivons sur moins de 160 pistes car la disquette n'est pas pleine). Une fois cette étape terminée et que la disquette a fini de travailler, insérons une seconde disquette vierge et tapons "WT". Indiquons à l'éditeur d'écrire depuis l'adresse mémoire "L4_1:", ce qui correspond aux pistes 0 à 67.

Une fois que la seconde disquette a fini de travailler, insérons de nouveau la première disquette, redémarrons notre Amiga : notre version déplombée de Turrican 2 se chargera !

Déplombage de Turrican 2



[Retour en haut] / [Retour aux articles]