Suivez-nous sur X
|
|
|
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,
ALL
|
|
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
|
|
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
|
|
A propos d'Obligement
|
|
David Brunet
|
|
|
|
En pratique : Déplombage de Turrican 3
(Article écrit par Matthias Heydorn et extrait de Flashtro.com - novembre 2004)
|
|
Note : traduction par Denis Lechevalier.
Prérequis
- Un Amiga ou l'émulateur WinUAE (configuration : 2 Mo de mémoire Chip, 2 Mo de mémoire Fast).
- Une cartouche Action Replay III (ou l'image de sa ROM).
- Le jeu original Turrican 3 ou l'image IPF du jeu.
- Un logiciel Assembler (ASM-One, Trash-M One, Seka ou similaire).
Déplombage de Turrican 3
Devinez quoi, c'est la vérification de la protection...
Commençons avec quelque chose de familier... Activez l'Action Replay et lisez la seule piste DOS
lisible 0 pour vérifier ce qui se passe dans le code de l'amorce ("bootcode").
Tapez "rt 0 1 $50000" et désassemblez quelques lignes en utilisant la commande "d $5000c".
Les premières choses intéressantes apparaissent ici : $1200 octets de données sont chargées en utilisant le
trackdisk.device positionné à l'adresse $58000. C'est la partie où le logo "Rainbow Arts" disparait alors
rappelons-nous de "ripper" cet endroit de la mémoire durant les prochaines étapes du déplombage.
Désassemblons encore quelques lignes...
Eh bien, on dirait qu'il y a un petit chargeur de piste ("trackloader") planqué dans le code de démarrage
qui charge $1800 octets de données à l'adresse $7E800, suivi par un saut (jmp) en $7E800.
C'est le chargeur principal ("mainloader") du jeu. Donc, comme toujours, on va remplacer le "jmp"
avec une boucle de branchement ("branch-loop") de suite pour aller au contact avec le truc
qui est chargé en $58000 et $7E800. :-)
Ça ne devrait rien représenter de nouveau pour vous alors faites comme indiqué dans l'image ci-dessous,
réinitialisez votre machine et démarrez le jeu.
Ainsi, quand l'écran noir apparaît, le processeur se fait une soirée "branchée" et on peut activer l'Action Replay
pour sauver certains trucs importants.
Jetons un coup d'oeil de près aux adresses $58000 et $7E800.
Les choses semblent être chargées, alors sauvons-les sur notre disquette de sauvegarde.
Les données en $58000 ont une longueur de $1200 octets et le truc en $7E800 fait $1800
octets (on le sait grâce au code de l'amorce), alors insérez une disquette vierge formatée
et suivez les instructions montrés dans l'image ci-dessus.
Maintenant, c'est le moment de vous dire certains faits à propos de la routine principale de chargement de piste :
le chargeur de piste ("trackloader") est stocké en $7F020, il fonctionne avec une table de fichiers qui est
située en $7FCBA et elle est appelée avec une table d'entrée de fichier en D0.
Cette valeur est alors multipliée par !16 avec une instruction "asl.l #4,d0", ainsi chaque entrée de la
table de fichiers a une taille de !16 octets. Peut-être devrais-je vous dire quelque chose à
propos des valeurs dans cette table, jetons donc un rapide coup d'oeil dessus.
Position (offset) :
- $0.b = inutile.
- $1.b = numéro de cylindre (et non de piste).
- $2.b = piste 0 ou 1 sur le cylindre.
- $3.b = Je ne sais pas, peut-être la position du secteur sur la piste ("sectoroffset on track") ou quelque chose comme ça.
- $4.l = l'adresse de chargement du fichier.
- $8.l = octets à lire.
- $C.l = chose intéressante, si vous avez une extension de mémoire, le jeu alloue la mémoire haute et charge les
données à cette adresse au lieu d'utiliser celle à la position $4.l dans la table. Cette nouvelle adresse de
chargement est stockée ici, suivie par la copie des octets à la bonne adresse à la position $4.l !
Comme ça, le jeu vérifie cette valeur plus tard, si ce n'est pas zéro, il copie juste les octets de la mémoire au
lieu de charger les pistes à nouveau depuis la disquette. Super idée ! :-)
Bon... utilisons notre savoir pour "ripper" toute la disquette ! Mettons un point d'arrêt ("breakpoint")
à l'adresse du chargeur de piste en $7F020 et changeons certains paramètres de chargement. Continuez le jeu
avec un saut en $7E800 comme montré sur l'image suivante (n'oubliez pas d'insérer de nouveau la disquette de jeu).
Important : si vous utilisez une autre configuration mémoire que moi (2 Mo de mémoire Chip, 2 Mo de mémoire Fast),
les adresses peuvent différer de celles utilisées dans ce tutoriel. Ainsi, si vous utilisez une autre configuration,
vous devrez sauver les pistes chargées depuis un autre endroit de la mémoire. Dans ce cas, il stocke toutes les pistes
à partir de l'adresse $80000 (A3 = pointeur mémoire) et comme dit précédemment, copiez-le à la bonne adresse qui
est stockée dans la table de fichiers.
Maintenant que l'Action Replay apparaît de nouveau, voyons les registres pour voir quelle entrée dans la table
de fichiers le jeu veut charger. Comme vous le voyez en D0, ça doit être l'entrée #6, donc regardons la position de
la table de fichiers 6*!16=$60. Il veut charger $3400 octets à l'adresse $43000, commençant au cylindre 1, piste 0.
C'est une super position de départ donc pas besoin de changer cela. Mais comme vous l'avez deviné, on ne veut pas
"ripper" seulement $3400 octets alors changeons ce paramètre, par exemple en $F0000 (!983040) octets.
Faites-le pas à pas comme montré sur l'image ci-dessus et continuez le jeu en quittant l'Action Replay.
Ainsi, après avoir lu quelques pistes, le jeu se bloque au cylindre 21. Pas besoin de s'inquiéter de cela,
c'est la piste des meilleurs scores qui a un autre format. Entrons à nouveau dans l'Action Replay
pour sauver les cylindres 1-20 sur notre disquette de sauvegarde.
Comme le registre d'adresse A3 est utilisé en tant que pointeur mémoire ($80000 en premier),
on n'aura pas besoin de chercher la fin des données chargées à la main parce qu'il pointe directement dessus. :-)
Sauvez le tout comme dans l'image ci-dessus, réinitialisez votre machine et faites la même chose pour les cylindres allant de 21-79.
Si le jeu se bloque dans la boucle de branchement, entrez à nouveau dans l'Action Replay, collez un
point d'arrêt à l'adresse $7F020 et sautez dans le code principal avec "g $7E800". Attendez jusqu'à
ce que l'Action Replay s'active, nous disant quelle instruction en $7F020 est la prochaine à être exécutée.
Maintenant, changeons l'entrée dans la table de fichier #6 comme ceci :
Donc maintenant, on change les paramètres pour charger $F0000 octets du cylindre $15 (!21), piste 1 (rappelez-vous,
la piste 0 est la piste des meilleurs scores).
Après avoir fait les changements, sortez de l'Action Replay et laissez le jeu se charger dans le reste de la
disquette. Si le chargement de piste a atteint le cylindre 80, entrez à nouveau dans l'Action Replay et sauvez-les
sur une nouvelle disquette formatée (ça ne rentrera pas du tout sur notre première disquette de sauvegarde).
Comme vous le savez, A3 pointe vers la fin des données, dans ce cas-ci $13E200. Alors, sauvez-moi cela en faisant :
"sm cyl21-79, $80000 $13E200", exactement $BE200 (!778752) octets !
Eh bien, félicitations, c'était la dernière chose à traiter avec la disquette de jeu originale.
Au fait, on ne modifiera pas le chargeur de jeu original directement en $7F020 mais en $7F2AC. C'est la partie
du chargeur où les pistes sont chargées à la bonne position (ou dans la mémoire haute allouée). Si le chargeur
de piste atteint cette adresse, le truc qui suit est important pour nous.
- $7FDFE.L = lecture de l'adresse.
- $7FE02.L = octets à lire.
- $7FE20.B = numéro de cylindre.
- $7FE1C.B = numéro de piste.
- $7FE0A.L = chargement d'adresse MFM.
Maintenant, avec ces informations, cela devrait être facile de modifier le chargeur pour gérer nos pistes.
Chargez votre Assembleur préféré, ASM-One dans ce cas précis, et commençons par écrire les images-disques.
On mettra toutes les données sur deux disquettes parce qu'elles ne tiendront pas sur une disquette formatée au
standard AmigaDOS. Réservez 1200 ko de mémoire Chip et tapez le code de l'image disque qui cache"
"copier et coller" sous l'image.
MOVE.W #$4E75,chargeur+$806 ; mets un -rts- sur le branchement "Load Highscore".
MOVE.L #$4E714E71,chargeur+$1132 ; "Nope" une routine qui demande la disquette originale.
MOVE.W #$4E71,chargeur+$1136
MOVE.L #$11805000,chargeur+$D4C ; Désactive le "diskstepper" de Turrican 3 !
MOVE.W #$600E,chargeur+$D50
LEA NouveauLOADER(PC),A0 ; écrase simplement une partie du chargeur original avec le nôtre.
LEA chargeur+$AAC(PC),A1 ; chargeur+$AAC est $7F2AC plus tard en mémoire.
MOVE.L #(finNouveauLOADER-NouveauLOADER)-1,D0
RemplaceLOADER:
MOVE.B (A0)+,(A1)+
DBF D0,REmPLACELOADER
RTS
|
NouveauLOADER :
MOVE.L $7FDFE,A0 ; lire l'adresse.
MOVE.L $7FE02,D0 ; octets à lire.
MOVEQ #0,D1 ; vider les registres voulus.
MOVEQ #0,D2
MOVE.B $7FE20,D1 ; obtenir le numéro de cylindre.
LEA DISKSTATUS(PC),A2 ; adresse du mot de statut "quelle disquette est insérée ?", 0=Disk1, 1=Disk2.
CMP.B #21,D1 ; doit être lu au-delà du cylindre 21 ?
BGE.B SECONDDISque ; oui... c'est sur la disquette 2.
TST.W (A2) ; première disquette dans le lecteur ?
BEQ.B CORRECTDISque ; oui, tout est OK alors.
BSR.W couleursFLASH ; autrement flash de couleurs !
CLR.W (A2) ; changer le statut de la disquette en "Disque 1 inséré".
BRA.B CORRECTDISque
|
SECONDDISque :
SUB.B #21,D1 ; tout ce qui commence depuis le cylindre 21 sur la disquette originale
; commence maintenant de zéro à nouveau sur la disquette 2.
TST.W (A2) ; seconde disquette dans le lecteur ?
BNE.B CORRECTDISque ; oui, continuer le chargement de pistes.
BSR.W couleursflash ; autrement couleurs qui flashent...
MOVE.W #1,(A2) ; ...et changez le statut de la disquette en "Disque 2 inséré".
|
CORRECTDISque :
LSL.L #1,D1 ; numéro de cylindre * 2 = numéro de piste...
ADD.B $7FE1C,D1 ; ... + numéro de piste sur le cylindre = piste correcte !
MULS #$1A00,D1 ; multiplier avec la taille de piste du jeu = position d'octet correcte sur la disquette.
DIVS.W #$1600,D1 ; divisez par une taille de piste DOS normale,
; d1 = numéro de piste correcte sur le disque déplombé.
SWAP D1 ; reste de la division = position d'octet sur la piste.
MOVE.W D1,D2 ; déplace la position de l'octet en d2.
CLR.W D1 ; vide la position de l'octet en d1 et...
SWAP D1 ; le permute de nouveau donc d1 = numéro de piste.l de nouveau.
MOVE.L $7FE0A,A2 ; adresse de chargement MFM.
LEA $DFF000,A6 ; adresse de base des puces propriétaires en a6, nécessaire pour le chargeur de piste.
BSR.B TRACKLOADER ; charger le truc !
LEA $DFF000,A5 ; adresse de base des puces propriétaires en a5, nécessaire pour le jeu. :-)
RTS
|
couleursflash :
MOVE.W D7,$DFF180
SUBQ.W #1,D7
BTST #6,$BFE001
BNE.B couleursFLASH
MOVE.W #$0,$DFF180
RTS
|
statusdudisque :
TRACKLOADER :
INCBIN "ALPHA:TRACKLOADERS/TRACKLOADER.BIN"
|
finnouveauLOADER :
; image disque.
DISque :
DC.B "DOS",0 ; disque 1 = !50 pistes !
DC.L 0
DC.L 0
MOVE.W #$02,$1C(A1) ; Utilise le trackdisk.device pour charger les trucs en $7E800 and $58000.
MOVE.L #$7E800,$28(A1)
MOVE.L #$400,$2C(A1)
MOVE.L #$1800,$24(A1)
JSR -$1C8(A6)
MOVE.W #$02,$1C(A1)
MOVE.L #$58000,$28(A1)
MOVE.L #$1C00,$2C(A1)
MOVE.L #$1200,$24(A1)
JSR -$1C8(A6)
MOVE.W #$7FFF,$DFF09A ; flingue les Interruptions & les DMA et saute dans le chargeur du jeu.
MOVE.W #$7FFF,$DFF096
MOVE.B #$1,$7FE14
JMP $7E800
|
finduBOOT :
BLK.B $400-(finduBOOT-DISque),0 ; remplit le reste du code d'amorce avec des zéros, comme ça le
; chargeur du jeu commence en position impair en !1024 ($400).
|
chargeur :
INCBIN "ALPHA:T3/7E800" ; position sur disque = $400.
INCBIN "ALPHA:T3/58000" ; position sur disque = $1C00.
BLK.B $600,0
|
donneesdejeu :
INCBIN "ALPHA:T3/CYL1-20" ; position sur disque = $3400 (cylindre 1, piste 0 sur la
; disquette de jeu originale).
BLK.B $A00,0 ; juste pour faire les !50 pistes entières. :-)
|
DISque2 :
; Disque 2 = !140 pistes !
BLK.B $1A00,0 ; données de jeu sur le disque 2 commence sur le cylindre 0, piste 1
; (calculé avec une taille de piste de $1A00 bien sûr).
INCBIN "ALPHA:T3/CYL21-79"
BLK.B $C00,0 ; juste pour faire les !140 pistes entières.
|
Le binaire et le code source du chargeur de piste et du déplombage peut être téléchargé depuis
ce lien (NDLR : vous devez être enregistré
à Flashtro pour pouvoir le télécharger).
Et maintenant, il est temps d'assembler tout ça en utilisant la commande "A" et exécuter le (code) avec
"J". Maintenant que le chargeur est modifié en mémoire, il est temps de sauver les pistes sur nos disquettes.
Tapez "WT" et sauvez les pistes commençant en mémoire depuis la disquette étiquetée "DISque1", en écrivant
les pistes 0 à !50. Finalement, calculez la somme de contrôle du nouveau bloc d'amorce pour notre disquette 1
avec "CC". Insérez la seconde disquette et continuez en écrivant les pistes depuis la disquette avec l'étiquette
"DISK2" comme montré ci-dessous sur l'image (pistes 0 - !150).
Redémarrez votre Amiga, insérez la disquette 1 et appréciez ce super jeu.
|