Index du Forum
IDENTIFICATION SERVEUR : 10.14.20.84 - CLIENT : 3.235.108.188

 FAQFAQ   RechercherRechercher   Liste des MembresListe des Membres   Groupes d'utilisateursGroupes d'utilisateurs   S'enregistrerS'enregistrer 
 ProfilProfil   Se connecter pour vérifier ses messages privésSe connecter pour vérifier ses messages privés   ConnexionConnexion 

Drol (Broderbund - 1983)

 
Poster un nouveau sujet   Répondre au sujet     Index du Forum -> PROTECTION MALEFIQUE
Voir le sujet précédent :: Voir le sujet suivant  
Auteur Message
aloysiuscoincoin



Inscrit le: 17 Mar 2018
Messages: 21

MessagePosté le: Jeu 18 Fév 2021, 20:17    Sujet du message: Drol (Broderbund - 1983) Répondre en citant

Salut à tous !
Tout le monde connaît Drol, ce jeu super mignon avec son poulet cuit qui tressaute frénétiquement dans son plat. Je suis en train de tenter de le déplomber et je me propose de partager le processus ici si tant est que ça intéresse quelqu'un, dans ce qui va probablement ressembler à une sorte de feuilleton compte tenu de la protection que j'apprécie autant que le jeu lui-même.
Je déplombe à l'ancienne sur un vrai apple II avec le secours d'un wDrive connecté en tant que drive 2 pour cracker les images .woz puisque je n'ai pas de 'vrais' originaux à me mettre sous la dent.
Je commence toujours par tenter de faire une copie 'fonctionnelle' de l'image .woz vers une vraie disquette pour déplomber ensuite cette disquette, mais dans le cas de Drol, je n'ai pas réussi à faire une copie fonctionnelle, je tente donc de cracker l'image du soft insérée dans le drive 2. C'est pourquoi le boot-tracing passe sur le drive 2.
On peut toujours faire la copie du secteur 0 track 0 de n'importe quelle disquette c'est donc comme ça que je 'boote' le premier secteur de Drol sur le drive 1 pour basculer ensuite vers l'image sur le drive 2.

Comme dirait Dora l'exploratrice : "Allons-y let's go c'est parti les amis..."

Disque 1 : vraie disquette avec le secteur de boot de Drol
Disque 2 : wDrive avec l'image de Drol Piste 0

sur l'apple II, traditionnel début de boot tracing :
*9600<c600.c6ffM
*96f8:00
*9600G

Code:

; code chargé en $0800 mais relogé en $0200

0200: 01 a2      ORA ($A2,X)         
0202: 00         BRK                 
0203: bd 00 08   LDA $0800,X         ; reloge le code dans le buffer clavier
0206: 9d 00 02   STA $0200,X         
0209: e8         INX                 
020a: d0 f7      BNE $203           
020c: 4c 0f 02   JMP $020F           : << entrypoint réel


; ********************************
; entrypoint
; ********************************

020f: a0 ab      LDY #$AB           
0211: 98         TYA                 
0212: 85 3c      STA $3C             
0214: 4a         LSR A               
0215: 05 3c      ORA $3C             
0217: c9 ff      CMP #$FF           
0219: d0 09      BNE $224           
021b: c0 d5      CPY #$D5           
021d: f0 05      BEQ $224           
021f: 8a         TXA                 
0220: 99 00 08   STA $0800,Y         
0223: e8         INX                 
0224: c8         INY                 
0225: d0 ea      BNE $211         
 
0227: 84 3d      STY $3D             
0229: 84 26      STY $26             ; adresse de chargement pour le prochain secteur
022b: a9 03      LDA #$03            ; == $0300
022d: 85 27      STA $27             
022f: a6 2b      LDX $2B             

0231: 20 5d 02   JSR $025D           ; saut à chargement secteur suivant

0234: 20 d1 02   JSR $02D1           ; dénibbilisation en $0300
 
0237: 4c 01 03   JMP $0301           ; saut en $0301


Le secteur de boot charge un autre secteur en $0300, on peut le récupérer en modifiant le boot tracing du début comme ceci :

Code:
*9600<c600.c6ffM
96f8:   sta $c0eb   ; passe sur le drive 2
      lda #$13
      sta $082c
      lda #$00
       sta $0837
      jmp $0801


On obtient donc un code en $0300 :

Code:

0300: 99         ???                 ; code pour le décodage en EOR

;*************************************************
; Entrypoint phase 1
;*************************************************
0301: 84 48      STY $48
0303: a0 00      LDY #$00           
0305: 98         TYA                 
0306: a2 20      LDX #$20           
0308: 99 00 45   STA $4500,Y         
030b: c8         INY                 
030c: d0 fa      BNE $308           
030e: ee 0a 03   INC $030A           
0311: ca         DEX                 
0312: d0 f4      BNE $308            ; nettoyage page HGR2

0314: ad 57 c0   LDA $C057           
0317: ad 52 c0   LDA $C052           
031a: ad 55 c0   LDA $C055           
031d: ad 50 c0   LDA $C050           ; passage en HGR2

0320: b9 00 03   LDA $0300,Y         ; on prend le premier octet juste avant le code (octet == #$99)
0323: 45 48      EOR $48             ; EOR #$99
0325: 99 00 01   STA $0100,Y         ; on reloge le code en le décryptant vers $0100 (pile)
0328: c8         INY                 
0329: d0 f5      BNE $320           
032b: a2 cf      LDX #$CF            ; pointeur de pile modifié
032d: 9a         TXS                 
032e: 60         RTS                 ; saute à pointeur de pile+1 ($0130)

 
032f: 9b         ???                 ; inutile d'afficher le reste, c'est codé à coup de EOR #$99...
0330: 3b 9d 1f   rla $1F9D,Y         
0333: 1f 39 99   BBR1 $9939         
0336: 1d 1a 1f   ORA $1F1A,X         
0339: 1d 3f b2   ORA $B23F,X         


Jusque là c'est gentil mais il s'est quand même fait un petit plaisir en planquant l'adresse de saut finale via un RTS et une modification préalable du pointeur de pile...

On peut reconstituer l'état de la pile en exécutant le code ci-dessus.
La pile une fois décryptée montre ceci :
Code:

; bouillie d'octets provenant de la partie en clair encodée lors du 'décodage'
0100: 00         BRK                 
0101: 1d d1 39   ORA $39D1,X         
0104: 99 01 3b   STA $3B01,Y         
0107: b9 00 99   LDA $9900,Y         
010a: f9 51 49   SBC $4951,Y         
010d: 63 77      rra ($77,X)         
010f: 93 9a      sxa ($9A),Y         
0111: 53 49      sre ($49),Y         
0113: 6d 34 ce   ADC $CE34           
0116: 59 34 cb   EOR $CB34,Y         
0119: 59 34 cc   EOR $CC34,Y         
011c: 59 34 c9   EOR $C934,Y         
011f: 59 20 99   EOR $9920,Y         
0122: 9a         TXS                 
0123: dc d1 00   nop $00D1           
0126: 99 98 51   STA $5198,Y         
0129: 49 6c      EOR #$6C           
012b: 3b 56 03   rla $0356,Y         
012e: f9 02      ???

;*****************************************************
; entrypoint boot 2
;*****************************************************

0130: a2 04      LDX #$04            ; 4 secteurs à charger
0132: 86 86      STX $86
0134: A0 00      LDY #$00                         
0136: 84 83      STY $83             
0138: 86 84      STX $84             ; adresse de chgt == $0400 == page text
013a: a6 2b      LDX $2B             
013c: bd 8c c0   LDA $C08C,X         
013f: 10 fb      BPL $13C           
0141: c9 bf      CMP #$BF            ; bf ... trois marqueurs comme prologue
0143: d0 f7      BNE $13C           
0145: bd 8c c0   LDA $C08C,X         
0148: 10 fb      BPL $145           
014a: c9 d7      CMP #$D7            ; d7
014c: d0 f3      BNE $141           
014e: bd 8c c0   LDA $C08C,X         
0151: 10 fb      BPL $14E           
0153: c9 d5      CMP #$D5            ; d5
0155: d0 f3      BNE $14A           
0157: bd 8c c0   LDA $C08C,X         
015a: 10 fb      BPL $157           
015c: 2a         ROL A               
015d: 85 85      STA $85             
015f: bd 8c c0   LDA $C08C,X         
0162: 10 fb      BPL $15F           
0164: 25 85      AND $85             
0166: 91 83      STA ($83),Y         ; décodage en 4&4, ce n'est pas du 6&2
0168: c8         INY                 
0169: d0 ec      BNE $157           
016b: 0e 00 c0   ASL $C000           
016e: bd 8c c0   LDA $C08C,X         
0171: 10 fb      BPL $16E           
0173: c9 d4      CMP #$D4            ; marqueur de fin de secteur == $d4
0175: d0 b9      BNE $130           
0177: e6 84      INC $84             
0179: c6 86      DEC $86             ; un secteur en moins
017b: d0 da      BNE $157           
017d: 60         RTS                 ; saute à l'adresse suivante dans la pile ($0400) <<< bloquer ce saut dans le boot-tracing suivant


017e: e3 b1      ins ($B1,X)   

; ******************************************************
; retour après le RTS suite au chargement de la nouvelle pile (on verra ça plus tard)
; ******************************************************
; évidemment les données ci-dessous sont remplacées par celles qui seront chargées plus tard.     
0180: e6 91      INC $91             
0182: e4 e6      CPX $E6             
0184: e4 d0      CPX $D0             
0186: 02 e6      hlt                 
0188: e5 e6      SBC $E6             
018a: e6 d0      INC $D0             
018c: 02 e6      hlt                 
018e: e7 a5      SMB6 $A5           
0190: e6 c5      INC $C5             
0192: 4c a5 e7   JMP $E7A5           
0195: e5 4d      SBC $4D             
0197: 90 e6      BCC $17F           
0199: a2 fe      LDX #$FE           
019b: b5 e6      LDA $E6,X           
019d: 95 4e      STA $4E,X           
019f: b5 cc      LDA $CC,X           
01a1: f5 dc      SBC $DC,X           
01a3: 95 cc      STA $CC,X           
01a5: e8         INX                 
01a6: d0 f3      BNE $19B           
01a8: a6 d8      LDX $D8             
01aa: 60         RTS                 
01ab: b1 4c      LDA ($4C),Y         
01ad: 91 ce      STA ($CE),Y         
01af: a5 ce      LDA $CE             
01b1: d0 02      BNE $1B5           
01b3: c6 cf      DEC $CF             
01b5: c6 ce      DEC $CE             
01b7: a5 4c      LDA $4C             
01b9: d0 02      BNE $1BD           
01bb: c6 4d      DEC $4D             
01bd: c6 4c      DEC $4C             
01bf: c5 ca      CMP $CA             
01c1: a5 4d      LDA $4D             
01c3: e5 cb      SBC $CB             
01c5: 90 e4      BCC $1AB           
01c7: b0 d0      BCS $199           
01c9: 20 15 e7   JSR $E715           
01cc: a4 ce      LDY $CE             
01ce: c0 ca      CPY #$CA   
       
01d0: 2f 01 ff   BBR2 $FF01          ; << vecteur du RTS précédent (2f  01) + 1 == $130 == adresse de retour lors du premier RTS

01d3: 03 ff      slo ($FF,X)         ; l'adresse suivante est celle à laquelle saute le soft lors du RTS après le chgt des 4 secteurs en $0400 ($3ff +1 == $400)
01d5: 04 4f      TSB $4F             ; ensuite, retour en $0500 au prochain RTS (on verra ça dans la phase de chargement suivante)
01d7: 04 ff      TSB $FF             ; puis en $450
01d9: 1f 85 4b   BBR1 $4B85         
01dc: 4c b7 e5   JMP $E5B7           
01df: 86 d8      STX $D8             
01e1: 20 1e f1   JSR $F11E           
01e4: 20 fd fe   JSR $FEFD           
01e7: a2 ff      LDX #$FF           
01e9: 38         SEC                 
01ea: b5 4d      LDA $4D,X           
01ec: f5 cf      SBC $CF,X           
01ee: 95 db      STA $DB,X           
01f0: e8         INX                 
01f1: f0 f7      BEQ $1EA           
01f3: 90 87      BCC $17C           
01f5: a5 cc      LDA $CC             
01f7: c5 da      CMP $DA             
01f9: a5 cd      LDA $CD             
01fb: e5 db      SBC $DB             
01fd: b0 d5      BCS $1D4   


Il va falloir s'arrêter à l'adresse $017D au prochain boot-tracing, mais on voit déjà que cette protection aime bien la pile, le buffer clavier, la page TXT pour y mettre du code et sautiller comme un poulet cuit via des RTS plutôt que des appels normaux, histoire de simplifier la tâche certainement Wink. On peut voir également que c'est un format de 'secteurs' maison avec un encodage 4&4 et des marqueurs minimalistes : une séquence prologue + 512 nibbles + un nibble de fin + 512 nibbles + un nibble de fin + etc...
Plutôt sympa.
Smile

Pour charger la phase suivante, on va modifier l'ancien boot tracer avec ceci :

Code:
; Bidouillage de la recopie de la routine contrôleur disquette vers $8600
; 8600 < c600.c6ffM puis on ajoute cette partie pour tracer jusqu'à la phase suivante de boot

      .cr 6502 ; = choix du microprocesseur à assembler

      .or $86f8 ; = ORG
      .tf Drol_boot1.bin ,bin    ; target file (fichier assemblé)

; constantes
DRIVE2      .eq $c0eb   
MONITOR      .eq $ff59

prog_begin               ; début du prog

;   début de la routine   
      sta DRIVE2
      lda #boot0  ; adresse basse du label en $0838
      sta $0838   ; renvoie vers ici pour bidouiller le boot suivant
      lda /boot0  ; adresse haute du label en $0839
      sta $0839
      jmp $0801
boot0   lda #$8d   ; modifie l'adresse de retour dans la pile pour l'envoyer vers un peu plus bas et recopier le contenu
            ; de la page TEXT vers $1400 à $1800 (les valeurs remplacées tiennent compte du EOR #$99)
      sta $03d2
      lda #$1e
      sta $03d3
      jmp $0301 ; saute à l'exécution de la phase 1
retour   ldx #$00    ; la phase 1 revient ici après le chargement des 4 secteurs en $0400

read           lda $0400,x   ; recopie des 4 secteurs vers la zone $1400-$1800 avant le retour au moniteur
store   sta $1400,x       ; indispensable sinon on bousille la page TEXT en revenant au moniteur, bien entendu
      inx
      bne read
      inc read+2
      inc store+2
      lda store+2
      cmp #$18   ; on est à $1800 ?
      bne read
      jmp MONITOR

prog_end               ; fin du programme


Désolé, c'est assez moche à lire, mais on comprend le principe j'espère :/

Une fois qu'on a récupéré le code chargé en page TEXT, on peut y jeter un oeil :

Code:

Boot 3 - DROL
cette partie se charge normalement en $0400
-------------------------------
$4400 : A0 00      LDY #$00
$4402 : B9 00 06   LDA $0600,Y
$4405 : 99 00 BE   STA $BE00,Y
$4408 : B9 00 07   LDA $0700,Y
$440B : 99 00 BF   STA $BF00,Y
$440E : C8         INY
$440F : D0 F1      BNE $4402
$4411 : A6 2B      LDX $2B
$4413 : 8E 49 BF   STX $BF49
$4416 : 20 E0 BE   JSR $BEE0        ; recopie de la carte langage sur elle-même

$4419 : AD 83 C0   LDA $C083
$441C : AD 83 C0   LDA $C083
$441F : A0 00      LDY #$00
$4421 : A9 BF      LDA #$BF
$4423 : 8C FC FF   STY $FFFC
$4426 : 8D FD FF   STA $FFFD
$4429 : 8C F2 03   STY $03F2         ; revectorise le reset vers $BF00 dans la rom et en $3f2 et $3f3
$442C : 8D F3 03   STA $03F3         ; pour faciliter le boulot du déplombeur :D
$442F : A0 03      LDY #$03
$4431 : 8C F0 03   STY $03F0
$4434 : 8D F1 03   STA $03F1
$4437 : 84 36      STY $36
$4439 : 85 37      STA $37
$443B : 84 38      STY $38
$443D : 85 39      STA $39
$443F : 49 A5      EOR #$A5
$4441 : 8D F4 03   STA $03F4
$4444 : BA         TSX
$4445 : 9A         TXS ; ne fait rien
$4446 : E8         INX ; ne sert à rien
$4447 : BA         TSX ; car TSX lui redonne une valeur
$4448 : 9A         TXS ; ne sert à rien
$4449 : E8         INX
$444A : BA         TSX
$444B : 9A         TXS ; ne fait rien
$444C : E8         INX
$444D : BA         TSX ; met le stack pointer dans X
$444E : 60         RTS               ; saute en $0500 si l'on en croit la pile (celle plus haut dans le post) pour déplacer la le bras

en $0500 on trouve :
; ******************************************************
; adresse de retour après le RTS
; si l'on en croit la pile
; ******************************************************
$4500 : A0 00      LDY #$00
$4502 : A2 20      LDX #$20
$4504 : 98         TYA
$4505 : 99 00 20   STA $2000,Y
$4508 : C8         INY
$4509 : D0 FA      BNE $4505
$450B : EE 07 05   INC $0507
$450E : CA         DEX
$450F : D0 F4      BNE $4505            ; nettoie la page HGR1

$4511 : 2C 54 C0   BIT $C054
$4514 : A9 02      LDA #$02            ; 2 phases
$4516 : 4C 40 05   JMP $0540            ; déplacement piste 01


en $0540 :

$4540 : A2 13      LDX #$13
$4542 : 2C A2 0A   BIT $0AA2            ; cette instruction BIT est une astuce pour planquer le LDX #$0A à l'octet qui suit...
$4545 : 8E AE 05   STX $05AE
$4548 : 8D D0 05   STA $05D0            ; $05d0 == #$02 == piste 1 désirée (puis #$08 pour piste 4)
$454B : CD 48 BF   CMP $BF48            ; #$00 == piste actuelle
$454E : F0 59      BEQ $45A9            ; on y est déjà ? OK alors on sort...
.
.
.
.

$45A9 : AE 49 BF   LDX $BF49            ; LDX slot 6
$45AC : 60         RTS                  ; saute à la nouvelle adresse dans la pile ($0450)

Ce soft adore sautiller via la pile, c'est rigolo !

en $0450 :

$4450 : BA         TSX            ; pointeur de pile vers x
$4451 : 8A         TXA            ; vers accumulateur
$4452 : 18         CLC
$4453 : 69 28      ADC #$28      ; bidouillage pointeur de pile ... une manie...
$4455 : AA         TAX
$4456 : 9A         TXS            ; hop !

$4457 : A2 00      LDX #$00
$4459 : AC 49 BF   LDY $BF49      ; slot
$445C : B9 8C C0   LDA $C08C,Y
$445F : 10 FB      BPL $445C
$4461 : C9 DF      CMP #$DF      ; df      << Bien sûr, les marqueurs sont différents de ceux précédemment utilisés
$4463 : D0 F7      BNE $445C
$4465 : EA         NOP
$4466 : B9 8C C0   LDA $C08C,Y
$4469 : 10 FB      BPL $4466
$446B : C9 DE      CMP #$DE      ; de
$446D : D0 ED      BNE $445C
$446F : EA         NOP
$4470 : B9 8C C0   LDA $C08C,Y
$4473 : 10 FB      BPL $4470
$4475 : C9 DD      CMP #$DD      ; dd
$4477 : D0 E3      BNE $445C
$4479 : EA         NOP
$447A : B9 8C C0   LDA $C08C,Y
$447D : 10 FB      BPL $447A
$447F : 38         SEC
$4480 : 2A         ROL
$4481 : 85 00      STA $00
$4483 : B9 8C C0   LDA $C08C,Y
$4486 : 10 FB      BPL $4483
$4488 : 25 00      AND $00         ; encodage 4&4
$448A : 48         PHA            ; on remplace intégralement la pile avec les datas chargés directement (256 octets poussés)
$448B : CA         DEX            
$448C : D0 EC      BNE $447A      ; boucle sur les 256 octets à décoder en 4&4

$448E : B9 8C C0   LDA $C08C,Y
$4491 : 10 FB      BPL $448E
$4493 : C9 D5      CMP #$D5      ; marqueur de fin = D5 ? (différent de celui précédemment utilisé :D )
$4495 : D0 C5      BNE $445C      ; non ? on recommence
$4497 : 60         RTS            ; sinon saute à une adresse en fonction du pointeur de pile + #$28 et de la nouvelle pile
                           ; comme le pointeur de pile pointe vers l'adresse contenue en $0100 de la [color=orange]nouvelle[/color] pile, on ne sait pas où
                           ; il saute... trop malin... (il saute en fait à l'adresse $0180 mais bon, c'est quand même malin).



Donc, ce petit malin nous oblige à refaire un nouveau boot-tracer pour récupérer l'intégralité de la pile nouvellement chargée par cette routine et trouver l'adresse de saut $0180 appelée pour la poursuite du chargement du programme.
Very Happy
Code:

      .cr 6502 ; = choix du microprocesseur à assembler

      .or $86f8 ; = ORG
      .tf Drol_pileboot2.bin ,bin    ; target file (fichier assemblé)
*      .da prog_begin      ; insère l'adresse de début dans le fichier bin
*      .da prog_end - prog_begin    ; insère la taille en octets dans le fichier bin

; constantes
DRIVE2      .eq $c0eb   ; EQU
MONITOR      .eq $ff59

prog_begin               ; début du prog

;   début de la routine   
      sta DRIVE2
      lda #boot0  ; adresse basse du label en $0838
      sta $0838   ; renvoie vers ici pour bidouiller le boot suivant
      lda /boot0  ; adresse haute du label en $0839
      sta $0839
      jmp $0801
boot0   lda #$8d   ; modifie l'adresse de retour dans la pile pour l'envoyer vers un peu plus bas (retour)
      sta $03d2
      lda #$1e
      sta $03d3
      jmp $0301   ; saute à l'exécution de la phase 1

retour   lda #$4c   ; jmp
      sta $0497   ; notre dernier RTS remplacé par JMP
      lda #boot1 
      sta $0498   
      lda /boot1 
      sta $0499   ; on a ajouté JMP boot1 à la fin du remplacement de la pile dans le code du jeu
      jmp $0400   ; on saute là où devait revenir le soft au lieu de 'retour' plus haut


boot1   ldx #$00   ; la phase 2 revient ici après le chargement des de la nouvelle pile

.loop   lda $0100,x   ; on recopie la pile vers l'adresse $1100
      sta $1100,x
      inx
      bne .loop
      jmp MONITOR   ; et on rend la main

prog_end               ; fin du programme


La nouvelle pile a cette tête là :
Code:

0100: 7f 01 3F   BBR7 $9201          ; détermine l'adresse de saut du dernier RTS... puis saute en $0540 après la routine en $180
0103: 05 0c      ORA $0C             ; puis saut à $BE0D après le déplacement en piste 8
0105: be 01 05   LDX $0501,Y         
0108: ff 0e 04   BBS7 $040E         
010b: 01 05      ORA ($05,X)         
010d: de a2 06   DEC $06A2,X         


On voit que le soft saute en $017f + 1 (donc $0180) au rts sur lequel on a collé un breakpoint.

Voici la routine :

Code:

; chargement d'un secteur page zéro
0180: b9 8c c0   LDA $C08C,Y       
0183: 10 fb      BPL $0180
0185: c9 d5      CMP #$D5            ; d5  << pour changer... nouveau prologue :D
0187: d0 f7      BNE $180           
0189: ea         NOP                 
018a: b9 8c c0   LDA $C08C,Y         
018d: 10 fb      BPL $18A           
018f: c9 aa      CMP #$AA            ; aa 
0191: d0 ed      BNE $180           
0193: ea         NOP                 
0194: b9 8c c0   LDA $C08C,Y         
0197: 10 fb      BPL $194           
0199: c9 b5      CMP #$B5            ; b5 
019b: d0 e3      BNE $180             
 
019d: ea         NOP                 
019e: b9 8c c0   LDA $C08C,Y         
01a1: 10 fb      BPL $19E           
01a3: 38         SEC                 
01a4: 2a         ROL A               
01a5: 8d ff 01   STA $01FF           ; 4&4
01a8: b9 8c c0   LDA $C08C,Y         
01ab: 10 fb      BPL $1A8           
01ad: 2d ff 01   AND $01FF           ; décodage 4&4
01b0: 95 00      STA $00,X           
01b2: e8         INX                 ; remplit la page zéro
01b3: d0 e8      BNE $19D           

01b5: b9 8c c0   LDA $C08C,Y         
01b8: 10 fb      BPL $1B5           
01ba: c9 d4      CMP #$D4            ; marqueur de fin == d4 comme le premier
01bc: d0 c2      BNE $180            ; on recommence tout si pas trouvé
01be: a9 08      LDA #$08            ; déplacement sur une nouvelle piste
01c0: 60         RTS                 ; saute à $0540 ($053f + 1) conformément à la pile actuelle (déplace le bras)


Ce soft est un obsédé des sauts via RTS, c'est pas fini ^^'
La suite au prochain épisode.
Smile
Revenir en haut de page
Voir le profil de l'utilisateur Envoyer un message privé
toinet
Site Admin


Inscrit le: 15 Juin 2007
Messages: 3074
Localisation: Le Chesnay, France

MessagePosté le: Ven 19 Fév 2021, 17:07    Sujet du message: Répondre en citant

On veut la suite !

C'est une protection de Roland Gustaffson. Toujours long et sciant à suivre, à la mode Karateka...
Revenir en haut de page
Voir le profil de l'utilisateur Envoyer un message privé Visiter le site web de l'utilisateur
aloysiuscoincoin



Inscrit le: 17 Mar 2018
Messages: 21

MessagePosté le: Dim 21 Fév 2021, 11:06    Sujet du message: Répondre en citant

Re !
Sans m'étaler plus avant, j'ai beaucoup de boulot et assez peu de temps pour faire le rigolo sur internet, il y a un risque assez élevé que ce feuilleton se prolonge à coup de posts erratiques.
Embarassed

Allez, on reprend tranquillou.
Notre dernier RTS revient en $0540, rappelez-vous :
cf. la tête de la pile...
Code:
0100: 7f 01 3F   BBR7 $9201          ; détermine l'adresse de saut du dernier RTS... puis saute en $0540 après la routine en $180
0103: 05 0c      ORA $0C             ; puis saut à $BE0D après le déplacement en piste 8
0105: be 01 05   LDX $0501,Y         
0108: ff 0e 04   BBS7 $040E     


Il nous faut aller jeter un oeil en $0540 rapidement :
Code:

;*************************************************************
; retour de la deuxième pile (déplacement de la tête )
;*************************************************************
$4540 : A2 13      LDX #$13            ; valeur de temporisation
$4542 : 2C A2 0A   BIT $0AA2            ; cette instruction BIT est une astuce pour planquer le LDX #$0A à l'octet qui suit...
$4545 : 8E AE 05   STX $05AE
$4548 : 8D D0 05   STA $05D0            ; puis #$08 pour piste 4 ??
$454B : CD 48 BF   CMP $BF48            ; piste actuelle
$454E : F0 59      BEQ $45A9            ; on y est déjà ? OK alors on sort...

$4550 : A9 00      LDA #$00            ; routine SEEK pour déplacer la tête sur la piste voulue...
.
.
.
$45A6 : BD 80 C0   LDA $C080,X         ; << déplace le moteur pas à pas

$45A9 : AE 49 BF   LDX $BF49            ; LDX slot 6
$45AC : 60         RTS                  ; saute à la nouvelle adresse dans la pile ($BE0D)


Donc le soft continue à nous balader à coup de RTS. J'adore ce Roland Gustaffson Very Happy

Code:
be0d: ae 49 bf   LDX $BF49           ; #$60, slot 6
be10: a9 04      LDA #$04            ; nb de secteurs à charger
be12: 85 a1      STA $A1             
be14: a0 00      LDY #$00           
be16: a9 5c      LDA #$5C            ; ($A2) = $5c00 = adresse de chargement de la suite.
be18: 84 a2      STY $A2             
be1a: 85 a3      STA $A3             

be1c: bd 8c c0   LDA $C08C,X         ; ici on est piste 4
be1f: 10 fb      BPL $BE1C           
be21: c9 b5      CMP #$B5            ; B5
be23: d0 f7      BNE $BE1C           
be25: bd 8c c0   LDA $C08C,X         
be28: 10 fb      BPL $BE25           
be2a: c9 b6      CMP #$B6            ; B6
be2c: d0 f3      BNE $BE21           
be2e: bd 8c c0   LDA $C08C,X         
be31: 10 fb      BPL $BE2E           
be33: c9 b7      CMP #$B7            ; B7
be35: d0 f3      BNE $BE2A           

be37: bd 8c c0   LDA $C08C,X         
be3a: 10 fb      BPL $BE37           
be3c: 2a         ROL A               
be3d: 85 a0      STA $A0             ; adresse temporaire de décodage des nibbles
be3f: bd 8c c0   LDA $C08C,X         
be42: 10 fb      BPL $BE3F           
be44: 25 a0      AND $A0             ; octet reconstitué
be46: 91 a2      STA ($A2),Y         ; on stocke en $5c00 et plus
be48: c8         INY                 
be49: d0 ec      BNE $BE37           

be4b: 0e ff ff   ASL $FFFF           
be4e: bd 8c c0   LDA $C08C,X         
be51: 10 fb      BPL $BE4E           
be53: c9 d4      CMP #$D4            ; marqueur de fin de secteur
be55: d0 b9      BNE $BE10           ; si pas trouvé, on recommence

be57: e6 a3      INC $A3             ; sinon, on incrémente l'adresse haute de chgt
be59: c6 a1      DEC $A1             ; il reste un secteur de moins à charger
be5b: d0 da      BNE $BE37           ; tant que le nb de secteurs =/= 0 on continue

be5d: 4c a0 be   JMP $BEA0           ; on saute à la suite


Cette routine s'avère être un loader 'statique' en mémoire qui charge la routine de chargement à chaque 'fin' (oui... le soft prend pour ainsi dire tout l'espace mémoire disponible et lors d'un chargement (changement de niveau vers niveau supérieur ou retour au niveau 0 après la mort), il passe en HGR1 où il anime un rideau qui se ferme et charge ensuite dans l'espace mémoire HGR2 la routine qui va charger le nouveau niveau.


Code:
bea0: 20 00 5c   JSR $5C00           ; continue le chargement en sautant vers ce qu'il vient de charger (JSR donc on en revient normalement !)
bea3: 20 7f bf   JSR $BF7F           ; routine de déplacement en HGR2
bea6: a2 21      LDX #$21           
bea8: bd 80 73   LDA $7380,X         ; vide une partie de la mémoire (valeur : 00)
beab: 85 a0      STA $A0             
bead: bd 40 74   LDA $7440,X         
beb0: 85 a1      STA $A1             
beb2: a0 27      LDY #$27           
beb4: a9 00      LDA #$00           
beb6: 91 a0      STA ($A0),Y         
beb8: 88         DEY                 
beb9: 10 fb      BPL $BEB6           
bebb: e8         INX                 
bebc: e0 bc      CPX #$BC           
bebe: 90 e8      BCC $BEA8   
       
bec0: a9 00      LDA #$00           
bec2: a0 40      LDY #$40           
bec4: 85 a0      STA $A0             
bec6: 84 a1      STY $A1             
bec8: a2 20      LDX #$20           
beca: a0 78      LDY #$78           
becc: 91 a0      STA ($A0),Y         
bece: c8         INY                 
becf: 10 fb      BPL $BECC           
bed1: a0 f8      LDY #$F8           
bed3: 91 a0      STA ($A0),Y         
bed5: c8         INY                 
bed6: 30 fb      BMI $BED3           
bed8: e6 a1      INC $A1             
beda: ca         DEX                 
bedb: d0 ed      BNE $BECA           
bedd: 60         RTS              ; encore un RTS :D


Bien sûr, la routine en $5c00 nous intéresse, il faut donc la récupérer... et pour ça, un petit loader :
Code:
      .cr 6502 ; = choix du microprocesseur à assembler

      .or $86f8 ; = ORG
      .tf Drol_loadboot5.bin ,bin    ; (fichier assemblé)


; constantes
DRIVE2      .eq $c0eb   ; EQU
MONITOR      .eq $ff59

prog_begin               ; début du prog

;   début de la routine   
      sta DRIVE2
      lda #boot0  ; adresse basse du label en $0838
      sta $0838   ; renvoie vers ici pour bidouiller le boot suivant
      lda /boot0  ; adresse haute du label en $0839
      sta $0839
      jmp $0801
boot0   lda #$8d   ; modifie l'adresse de retour dans la pile pour l'envoyer vers un peu plus bas (retour)
      sta $03d2
      lda #$1e
      sta $03d3
      jmp $0301   ; saute à l'exécution de la phase 1

retour   lda #$59   ; au lieu de sauter en $5c00 après le chargement, on saute au moniteur
      sta $06a1 ; et on reprend la main
      lda #$ff
      sta $06a2
      
      jmp $0400   ; on saute là où devait revenir le soft au lieu de 'retour' plus haut

prog_end               ; fin du programme


Maintenant, on peut aller jeter un œil curieux du côté de $5c00, la fameuse routine de chargement... qui fait 4 secteurs, il y a un peu de monde...

Code:
5c00: a9 04      LDA #$04            ; phase 4 ou piste 4 ?
5c02: 20 00 5f   JSR $5F00             ; déplacement de la tête sur quelle piste ?
       
5c05: a9 00      LDA #$00            ; index pour les marqueurs
5c07: 85 e1      STA $E1             ; dans $E1
5c09: 20 00 5e  [b] JSR $5E00           ; charge 8 secteurs de $5000 à 5800...[/b]
[color=violet][b]5c0c:[/b][/color]

[b][color=red]5c0c: 4c 00 50   JMP $5000           ; <<<<<<<< on saute à BOOT 6 (Il faut modifier le boot loader pour reprendre la main ICI)[/b][/color]


Bien sûr, les commentaire au-dessus proviennent de l'analyse des routines ci-dessous...

Code:

; déplacement du bras
5f00: a2 13      LDX #$13            ; temporisation
5f02: 2c                         ; astuce qui permet de passer l'instruction suivante
                                    ; en faisant un BIT $xxxx sans intérêt :)
[color=red]5f03: a2 0a      LDX #$03           ; instruction ignorée à la première itération[/color]
                                    ; mais exécutée au second appel
5f05: 8e 6e 5f   STX $5F6E           ; temporisation qui change selon l'appel ?
5f08: 8d 90 5f   STA $5F90           ; << valeur A == 4 au premier passage mais 01 au second passage (nb de phases par piste ?)
5f0b: cd 48 bf   CMP $BF48           ; cmp #$00 ?
5f0e: f0 59      BEQ $5F69           ; si 0, on sort

5f10: a9 00      LDA #$00            ; sinon on continue
.
.
.
5f65: aa         TAX                 
5f66: bd 80 c0   LDA $C080,X         ; déplacement du bras

5f69: ae 49 bf   LDX $BF49           ; sortie
5f6c: 60         RTS               
 


et aussi :

Code:

;*********************************************************
; chargement des secteurs 2 par 2
;*********************************************************
5e00: a0 00      LDY #$00         
5e02: a9 50      LDA #$50           
5e04: 84 e2      STY $E2             ; $E2 == 00 == 'passe' actuelle de 2 secteurs
5e06: 48         PHA                 ; << 50
5e07: 20 30 5e   JSR $5E30           ; chargement Y secteurs ayant les mêmes marqueurs (d'abord 2)
 
5e0a: a4 e2      LDY $E2             
5e0c: 18         CLC                 
5e0d: ad 48 bf   LDA $BF48           ; 00
5e10: 79 28 5e   ADC $5E28,Y         ; on ajoute 1
5e13: 20 03 5f   [color=red]JSR $5F03[/color]           ; déplace le bras
5e16: 68         PLA                 ; A == 50
5e17: 18         CLC                 
5e18: 69 02      ADC #$02            ; augmente l'adresse haute de chgt ($5200 now)
5e1a: a4 e2      LDY $E2             ; 00
5e1c: c8         INY                 ; 01
5e1d: c0 04      CPY #$04            ; on charge 3 x 2 secteurs de plus en changeant les marqueurs...
5e1f: 90 e3      BCC $5E04           ; boucle si on n'est pas arrivé à Y = 4
5e21: 60         RTS                 ; revient en [b]$5c0c[/b]

5e22: 00         BRK                 
5e23: 00         BRK                 
5e24: 00         BRK                 
5e25: 00         BRK                 
5e26: 00         BRK                 
5e27: 00         BRK         
       
;*********************************************************
; table de ???
;*********************************************************
5e28: 01 ff      ORA ($FF,X)         
5e2a: 01 00      ORA ($00,X)         
5e2c: 00         BRK                 
5e2d: 00         BRK                 
5e2e: 00         BRK                 
5e2f: 00         BRK   

;*********************************************************
; vers le chargement des secteurs
;*********************************************************             
5e30: 48         PHA                 ; << 50
5e31: a5 e1      LDA $E1             ; index de la table
5e33: 29 07      AND #$07           
5e35: a8         TAY                 
5e36: b9 50 5e   LDA $5E50,Y         ; table des marqueurs de début de secteur
5e39: 85 90      STA $90             ; marqueur 1 stocké en $90
5e3b: a5 e1      LDA $E1             
5e3d: 4a         LSR A               
5e3e: 09 aa      ORA #$AA           
5e40: 85 91      STA $91             ; marqueur 2 en $91 calculé à partir de [u]l'[b]index[/b][/u] du premier marqueur
5e42: a5 e1      LDA $E1             
5e44: 09 aa      ORA #$AA           
5e46: 85 92      STA $92             ; marqueur 3 en $92 calculé à partir de [u][b]l'index[/b] [/u]du premier marqueur
5e48: 68         PLA                 ; <<A>$5800
prog_end         ; fin du programme


On peut maintenant regarder ce qui se passe en $5000 et plus
Code:

;******************************************************************************
; BOOT 6 - sert à charger un level (si l'on meurt ou si l'on passe au suivant)
;******************************************************************************
5000: ae 4a bf   LDX $BF4A           ; FF au premier appel donc négatif donc chgt phase 6
                               ; cet octet est le type de level à charger
                               ; la valeur FF correspond au tout premier chargement (jeu non démarré)
5003: 10 03      BPL $5008           ; on ne saute pas mais si $BF4A positif, on saute pour charger le niveau suivant
[b]5005: 4c 00 53   JMP $5300           ; entrypoint de la phase 6 qui est le loader final[/b]
; la suite est intéressante car cette routine n'est pas appelée qu'une seule fois, elle fait déjà partie du jeu

5008: e8         INX                 ; admettons que c'est le nb de vies restantes ou le level courant
5009: 8a         TXA                 
500a: 29 03      AND #$03            ; le 'level' à charger ne peut être que de zéro à 3
500c: aa         TAX                 
500d: 24 44      BIT $5053           ; test l'état du jeu (mort / pas mort) et donc si on revient au level 0 ?
500f: 30 02      BMI $5013           ; Le flag minus est triggered si le joueur est mort, sinon on ne recharge pas le Level 00

5011: a2 00      LDX #$00            ; remise à zéro du n° de level (après la mort ?)

5013: 8e 4a bf   STX $BF4A           ; n° de level à charger
5016: bc f0 50   LDY $50F0,X         ; #$A0 == offset dans la table de chgt à venir en $5500
5019: a9 14      LDA #$14            ; piste 20 (ou 10 si c'est des phases)
501b: 20 00 55   JSR $5500           ; chargement

501e: ae 4a bf   LDX $BF4A           ; n° de level
5021: a0 40      LDY #$40            ; offset dans la table de chgt à venir en $5500
5023: bd f8 50   LDA $50F8,X         ; phase $22 ? (donc piste $11 ?) prise dans la table des phases
5026: 20 00 55   JSR $5500           ; chargement

5029: a9 08      LDA #$08            ; piste 4 ?
502b: 20 00 57   JSR $5700           ; remet le bras piste 4 ?
502e: bd 88 c0   LDA $C088,X         ; éteint le moteur  ! c'est toujours bon signe !
5031: 60         RTS                 ; << revient à l'appelant
Revenir en haut de page
Voir le profil de l'utilisateur Envoyer un message privé
aloysiuscoincoin



Inscrit le: 17 Mar 2018
Messages: 21

MessagePosté le: Dim 21 Fév 2021, 11:41    Sujet du message: Répondre en citant

Je continue ici parce que tout mettre dans un seul post fait bugger l'affichage du post sur le forum :/

Code:

;*********************************************************************************   
; table des offsets à attribuer vers la table de chgt en $5500 - chgt partie 1
;*********************************************************************************   
50f0: 90 a0      BCC $5092           
50f2: b0 c0      BCS $50B4         
50f4: 00         BRK                 
50f5: 00         BRK                 
50f6: 00         BRK                 
50f7: 00         BRK   

;*********************************************************************************   
; table des phases à attribuer vers la table de chgt en $5500 - chgt partie 2
;*********************************************************************************               
50f8: 16 22      ASL $22,X           
50fa: 2e 3a 00   ROL $003A           
50fd: 00         BRK                 
50fe: 00         BRK                 
50ff: 00         BRK     


en $5300 :

;****************************************************************
; BOOT 6 - entrypoint - le nouveau chargement se fait en 3 parties
;****************************************************************
5300: a9 0a      LDA #$0A            ; piste ou phase $0a ?           
5302: a0 00      LDY #$00            ; offset dans la table des adresses hautes de chgt
5304: 20 00 55   JSR $5500           ; chargement partie 1

5307: a0 00      LDY #$00           
5309: b9 00 5c   LDA $5C00,Y         ; déplacement des portions $5c00 vers $100 et $5d00 vers $300
530c: 99 00 01   STA $0100,Y         
530f: b9 00 5d   LDA $5D00,Y         
5312: 99 00 03   STA $0300,Y         
5315: c8         INY                 
5316: c0 f0      CPY #$F0           
5318: 90 ef      BCC $5309           
531a: ee 4a bf   INC $BF4A           ; $BF4A ?

531d: a2 ff      LDX #$FF            ; reset du pointeur de pile
531f: 9a         TXS                 

5320: a9 14      LDA #$14            ; piste $14 ?
5322: a0 90      LDY #$90            ; offset dans la table des adresses hautes de chgt
5324: 20 00 55   JSR $5500           ; chargement partie 2

5327: a9 16      LDA #$16            ; piste $16 ?
5329: a0 40      LDY #$40            ; offset dans la table des adresses hautes de chgt
532b: 20 00 55   JSR [b]$5500           ; chargement partie 3

532e: a9 08      LDA #$08            ; piste $08 ou phase (donc piste 4) ?
5330: 20 00 57   JSR $5700           ; déplacement du bras
5333: bd 88 c0   LDA $C088,X         ; on éteint le drive ! youpi !

;******************************************
;******************************************
; à partir d'ici LE JEU COMMENCE
;******************************************
;******************************************
; mais on arrive ici via un JSR ce qui veut dire que l'état de la pile est important et qu'à un moment,
; il reviendra à l'adresse $BEA3 via un RTS !
;******************************************
5336: 20 00 40   JSR $4000           ; ADRESSE DE FIN DE BOOT TRACING
                               ; cette routine en $4000 affiche le bandeau haut et bas de DROL en HGR1 (image fixe)
5339: a9 00      LDA #$00           
533b: 8d f8 03   STA $03F8           
533e: 8d ff 03   STA $03FF           
5341: a9 43      LDA #$43           
5343: 8d f9 03   STA $03F9           
5346: a9 6b      LDA #$6B           
5348: 8d fa 03   STA $03FA           
534b: a9 93      LDA #$93           
534d: 8d fb 03   STA $03FB           
5350: a9 bb      LDA #$BB           
5352: 8d fc 03   STA $03FC           
5355: ad 70 c0   LDA $C070           ; manette
5358: a2 04      LDX #$04           
535a: a0 00      LDY #$00           
535c: ad 64 c0   LDA $C064           ; manette
535f: 0d 65 c0   ORA $C065           ; manette... on est dans la boucle principale ?
5362: 10 15      BPL $5379           ; on sort vers la suite
5364: 88         DEY                 
5365: d0 f5      BNE $535C           
5367: ca         DEX                 
5368: d0 f2      BNE $535C           

536a: a9 19      LDA #$19           
536c: 85 52      STA $52             
536e: 85 54      STA $54             
5370: a9 62      LDA #$62           
5372: 85 53      STA $53             
5374: 85 55      STA $55             
5376: d0 0f      BNE $5387           ; vers suite 2

5378: 00         BRK                 


Bien sûr, il nous faut le boot-tracer final qui va nous amener ici comme breakpoint :

Code:

5336: 20 00 40   JSR $4000           ; ADRESSE DE FIN DE BOOT TRACING
                               ; cette routine en $4000 affiche le bandeau haut et bas de DROL (image fixe)


Le voici :

Code:

.cr 6502 ; = choix du microprocesseur à assembler

      .or $86f8
      .tf Drol_loadFinal.bin ,bin


; constantes
DRIVE2      .eq $c0eb   ; EQU
MONITOR      .eq $ff59
PILE      .eq $bf00   ; le stockage de l'état du pointeur de pile se fait en dehors de la zone de chgt
                  ; pour qu'il ne soit pas écrasé... par le chargement...
                  ; la routine de gestion du reset semble un bon endroit pour ça
                  ; le reset revectorisé ne sert à rien tant qu'on appuie pas sur reset

prog_begin               ; début du prog

;   début de la routine   
      sta DRIVE2   ; mon wDrive est branché en tant que drive 2
      lda #boot0  ; adresse basse du label
      sta $0838   ; renvoie vers ici pour bidouiller le boot suivant
      lda /boot0  ; adresse haute du label
      sta $0839
      jmp $0801

boot0   
      sta saveA
      lda #retour-1    ; modifie l'adresse de retour dans la pile pour l'envoyer vers un peu plus bas (retour)
      eor #$99        ; il faut l'adapter pour le décodage à base de XOR et enlever 1 car on saute à cette adresse
      sta $03d2       ; via un RTS
      lda /retour2
      eor #$99
      sta $03d3
      lda saveA

      jmp $0301   ; saute à l'exécution de la phase 1

retour   
      ; ATTENTION, cette modification, une fois relogée ne sera pas écrasée par les chargements suivants
      ; En effet, elle est relogée en $Bea1 et $BEa2 (et cette partie n'est jamais rechargée !)
      ; tant qu'on ne veut pas démarrer le jeu, pas de souci si on n'oublie pas de 'réparer' cette instruction
      ; avant de sauvegarder la portion mémoire, mais si on laisse le jeu se lancer, lors d'un changement de niveau
      ; le jeu plante... évidemment :D
      sta saveA
      lda #retour2   ; au lieu de sauter en $5c00 après le chargement, on saute à la modification retour2
      sta $06a1
      lda /retour2
      sta $06a2
      lda saveA

      jmp $0400   ; on saute là où devait revenir le soft au lieu de 'retour' plus haut

retour2
      ; rétablissement de l'adresse en $Bea1 et $Bea2
      lda #$00
      sta $bea1
      lda #$5c
      sta $bea2

      sta saveA
      lda #retour3   
      sta $5c0d   ; modifie le JMP $5000 en JMP retour3 (moniteur)
      lda /retour3
      sta $5c0e
      lda saveA

      jmp $5c00   ; saute à la dernière routine modifiée qui charge $5000->$5800

retour3
      sta saveA   ; backup A
      stx saveX   ; backup X
      tsx         ; pointeur de pile vers X
      stx PILE   ; backup pointeur de pile
      ldx #$06   ; 6
.boucle   lda chgt3,x   ; ici on modifie les tables d'adresse haute de chgt des phases 1 et 3
      sta $5440,x   ; pour charger la partie 'fragile' (page texte etc.) dans la page HGR1
      dex
      bpl .boucle

bckPZ   
      ldx #$00   ; il est préférable de sauvegarder également la page zéro et la pile pour étude ultérieure du code
      stx $03f4   ; défonce la revectorisation du reset... ça peut toujours servir...
rd      .db $bd,$00,$00 ; (lda $0000,x) backup $0000-->$01ff (PZ et pile) ATTENTION il ne faut pas que l'assembleur produise LDA $00,X !
wt      sta $2000,x
      inx
      bne rd
      inc rd+2
      inc wt+2
      lda rd+2
      cmp #$02   ; stop à l'adresse $0200
      bne rd

      ldx #15      ; 21
.loop   lda chgt1,x
      sta $5402,x
      dex
      bpl .loop
      lda #$59   ; saut au moniteur au lieu du saut vers $4000
      sta $5337
      lda #$ff
      sta $5338
      lda saveA    ; A intact
      ldx PILE   
      tsx       ; on remet la pile comme avant
      ldx saveX   ; X intact
      jmp $5000   ; on continue l'exécution du code modifié et qui va stopper en $5336

chgt3
      .db $22,$33,$34,$35,$36,$37,$38
chgt1
      .db $24,$25,$26,$27,$28,$29,$2a,$2b,$2c,$2d,$2e,$2f,$30,$31
      .db $32,$39,$3a,$3b,$3c,$3d,$3e,$3f
saveA   .db $00
saveX   .db $00



Après ce loader, le jeu est totalement chargé et on peut sauvegarder toutes les plages mémoire que l'on veut pour une analyse en 'dead listing' tranquillou.
On peut aussi bidouiller ce loader pour lancer le jeu au lieu de reprendre la main et ainsi être en mesure de récupérer la page zéro à divers moments du jeu, par exemple pour faire un patch qui met plus de vies à ce jeu assez difficile.
A ce propos, c'est ce que j'ai fait et si l'on fait ceci, on peut lancer l'ORIGINAL du jeu avec 70 vies à chaque départ plutôt que 4 vies :

no comment :


Ensuite on tape le patch en ram


et si l'on a la chance d'avoir l'original et qu'on le boote direct du drive 1, il faut supprimer le passage au drive 2


*8600G
et le jeu original se lance avec 70 vies au lieu de 4
Very Happy

A ce stade, on peut aussi reconstituer une disquette bootable du jeu à l'arrache pour jouer le premier niveau en chargeant tout l'espace mémoire auquel on a maintenant accès.

D'ailleurs, c'est ce que j'ai fait :

crack de Drol en cours :
https://uptobox.com/y6mmoiu82ky1

Bien sûr, en bootant cette image, on constatera que le chien/reptile à réaction a un petit problème graphique et bien entendu, on ne peut à ce stade jouer que le premier niveau parce que les routines de chargement ne sont pas modifiées et le jeu plante quand on passe au niveau suivant, mais c'est un premier stade du déplombage pour rigoler et ça se copie au locksmith 5.0.

Maintenant, le plus compliqué sera de trouver la place pour modifier les routines de chargement sans trop déborder car celles de Drol sont très courtes et charger des secteurs 'normaux' en 6&2, ça prend plus de place. Il faudra également récupérer 'manuellement' les données chargées lors des autres niveaux afin de finaliser le tout et d'accorder ça avec les nouvelles routines de chargement.

C'est pas gagné du tout vu le sac de noeuds qu'est ce système de chargement mais tant qu'on s'amuse Wink
Revenir en haut de page
Voir le profil de l'utilisateur Envoyer un message privé
amauget



Inscrit le: 06 Déc 2009
Messages: 968
Localisation: Nantes

MessagePosté le: Dim 21 Fév 2021, 15:01    Sujet du message: Répondre en citant

Impressionnant !
_________________
Antony
Apple II forever
Revenir en haut de page
Voir le profil de l'utilisateur Envoyer un message privé
aloysiuscoincoin



Inscrit le: 17 Mar 2018
Messages: 21

MessagePosté le: Dim 21 Fév 2021, 18:21    Sujet du message: Répondre en citant

Ouaip, le type qui a pondu ce schéma n'était probablement pas un néophyte Laughing
Sacré foufou ce Roland... Shocked
Mais c 'est l'éclate d'essayer de comprendre comment il a agencé tout ça en écoutant du Madonna avec un walkman et en buvant du Get27. Effet "Machine à remonter dans le temps" assuré Mr. Green
Revenir en haut de page
Voir le profil de l'utilisateur Envoyer un message privé
toinet
Site Admin


Inscrit le: 15 Juin 2007
Messages: 3074
Localisation: Le Chesnay, France

MessagePosté le: Dim 21 Fév 2021, 21:09    Sujet du message: Répondre en citant

Well (temporary) done!
av
Revenir en haut de page
Voir le profil de l'utilisateur Envoyer un message privé Visiter le site web de l'utilisateur
aloysiuscoincoin



Inscrit le: 17 Mar 2018
Messages: 21

MessagePosté le: Ven 26 Fév 2021, 20:52    Sujet du message: Répondre en citant

Hop hop hop !
J'ai eu un peu de temps pour jeter un œil un peu moins distrait au code de chargement de Drol et je pense que le crack va pouvoir se faire.
On a la place en RAM et une fois le chargement bien compris, il faudra simplement un peu de temps pour remplacer les routines de lecture et refabriquer une disquette structurée convenablement.
Ce que j'ai pu déduire :
1 - l'émulateur que j'utilise afin de produire les listings (non, je ne retape pas tout ce que j'ai sorti sur une applewriter Wink ) est buggé au niveau du désassembleur et même si c'est rigolo, il a fallu que je m'étonne de certaines parties du code pour me rendre compte qu'il affichait parfois des trucs bizarres. Super émulateur à part ça : MicroM8.

Je ne sais pas s'il produit d'autres erreurs d'interprétation du code, on verra.
ps : je ne corrigerai pas les listing plus haut, trop de boulot.

2 - Drol :
La progression dans le jeu s'effectue via 4 'rounds' qui bouclent
0 - scorpion
1 - bestioles bizarres qui ressemblent à des lapins flippants quand on est myope
2 - serpents
3 - saynète résumant la progression

Chaque fois qu'on boucle sur ces 4 rounds, la difficulté augmente (ennemis qui crachent - aspirateur - plante carnivore - trucs explosifs - variation des paramètres de vitesse etc...)
Le soft appelle à chaque fois la routine en $5000 pour charger le niveau suivant, ce qui colle avec la logique d'écriture de cette routine :
Code:
5000: ae 4a bf   LDX $BF4A           ; FF au premier appel donc négatif donc chgt phase 6
                               ; cet octet est le type de level à charger
                               ; la valeur FF correspond au tout premier chargement (jeu non démarré)
5003: 10 03      BPL $5008           ; toutes les fois suivantes (donc les niveaux suivants) on saute au dessus du chgt en $5300
5005: 4c 00 53   JMP $5300           ; entrypoint de la phase 6 : cette partie n'est chargée qu'une seule fois !

5008: e8         INX                 ; C'est le level courant
5009: 8a         TXA                 
500a: 29 03      AND #$03            ; le 'level' à charger ne peut être que de 0 à 3, ce sont les 4 'rounds' cycliques
500c: aa         TAX                 
500d: 24 44      BIT $44              ; test l'état du jeu (mort / pas mort) et donc si on revient au level 0 ?
500f: 30 02      BMI $5013           ; Le flag minus est triggered si le joueur est mort, sinon on ne recharge pas le Level 00

5011: a2 00      LDX #$00            ; remise à zéro du n° de level (après la mort ?)

5013: 8e 4a bf   STX $BF4A           ; n° de level à charger
5016: bc f0 50   LDY $50F0,X         ; #$90 == offset dans la table des marqueurs à venir en $5500
5019: a9 14      LDA #$14            ; piste 20 (ou 10 si c'est des phases)
501b: 20 00 55   JSR $5500           ; chargement : A = phase et Y = index des marqueurs à employer

501e: ae 4a bf   LDX $BF4A           ; n° de level
5021: a0 40      LDY #$40            ; offset dans la table de chgt à venir en $5500
5023: bd f8 50   LDA $50F8,X         ; phase $22 ? (donc piste $11 ?) prise dans la table des phases
5026: 20 00 55   JSR $5500           ; chargement

5029: a9 08      LDA #$08            ; piste 4 ?
502b: 20 00 57   JSR $5700           ; remet le bras piste 4 ?
502e: bd 88 c0   LDA $C088,X         ; éteint le moteur également !
5031: 60         RTS                 ; << revient à l'appelant


Comme on peut le voir, il y a plusieurs appels en $5500 et c'est là que tout se passe :

Code:
;*********************************************************
; Chargement de la totalité de chaque "ROUND"
;*********************************************************             
5500: 48         PHA                 ; phase
5501: 84 88      STY $88             ; $88 == offset dans la table des adresses hautes de chgt
5503: 20 00 57   JSR $5700           ; SEEK - déplacement du bras
5506: a2 00      LDX #$00           
5508: a4 88      LDY $88             
550a: b9 00 54   LDA $5400,Y         ; remplit la table des 12 adresses hautes
550d: 9d 03 57   STA $5703,X         ; dans la routine de chargement
5510: c8         INY                 
5511: e8         INX                 
5512: e0 0c      CPX #$0C            ;
5514: 90 f4      BCC $550A           ;

5516: 20 30 55   JSR $5530           ; vers le chargement des 12 secteurs (1 piste)

5519: a5 88      LDA $88             ; offset de la table des adresse hautes de chgt
551b: 18         CLC                 
551c: 69 0c      ADC #$0C            ; plus douze
551e: a8         TAY                 
551f: b9 00 54   LDA $5400,Y         ; adresse haute suivante
5522: f0 07      BEQ $552B           ; si c'est zéro, on a fini ?
5524: 68         PLA                 ; piste récupérée
5525: 18         CLC                 
5526: 69 02      ADC #$02            ; phase +2
5528: d0 d6      BNE $5500           ; et on boucle tant qu'on n'a pas tout chargé (table complète)
552a: 00         BRK                 
552b: 68         PLA                 
552c: 60         RTS     


Comme on peut le voir, cette routine ne sait charger qu'une 'piste' complète à la fois (12 pseudo 'secteurs'). A chaque 'round', il charge 6 pistes complètes plus trois secteurs situés sur la piste $0A, c'est le pourquoi de cette table (un peu mieux commentée que précédemment) :

Code:
;*********************************************************     
; ces quatre tables (une par 'round') représentent des datas à charger pour chacun des rounds
; comme ils sont tous sur la même piste mais pas sur le même secteur
; le chargement utilise une sorte de masque qui permet de savoir quels secteurs charger sur cette piste
; l'adresse haute $5e00 en RAM est une 'adresse poubelle' qui joue comme 'chargement invalide ou inutile'
; on remarque que les secteurs 'utiles' sont toujours chargés à la même adresse.
; secteur : 00 01 02 03 04 05 06 07 08 09 0A 0B
; adresse : bb bc bd -- -- -- -- -- -- -- -- --     
             
5490: bb         ???                 ; adresses de chgt level 0 : caractéristiques de jeu
5491: bc bd 5e   LDY $5EBD,X         
5494: 5e 5e 5e   LSR $5E5E,X         
5497: 5e 5e 5e   LSR $5E5E,X         
549a: 5e 5e 00   LSR $005E,X         
549d: 00         BRK                 
549e: 00         BRK                 
549f: 00         BRK           

;*********************************************************   
; secteur : 00 01 02 03 04 05 06 07 08 09 0A 0B
; adresse : -- -- -- bb bc bd-- -- -- -- -- --
   
54a0: 5e 5e 5e   LSR $5E5E,X         ; adresses de chgt levels : caractéristiques de jeu
54a3: bb         ???                 
54a4: bc bd 5e   LDY $5EBD,X         
54a7: 5e 5e 5e   LSR $5E5E,X         
54aa: 5e 5e 00   LSR $005E,X         
54ad: 00         BRK                 
54ae: 00         BRK                 
54af: 00         BRK             

;*********************************************************
; secteur : 00 01 02 03 04 05 06 07 08 09 0A 0B
; adresse : -- -- -- -- -- -- bb bc bd -- -- --   

54b0: 5e 5e 5e   LSR $5E5E,X         ; adresses de chgt levels : caractéristiques de jeu
54b3: 5e 5e 5e   LSR $5E5E,X         
54b6: bb         ???                 
54b7: bc bd 5e   LDY $5EBD,X         
54ba: 5e 5e 00   LSR $005E,X         
54bd: 00         BRK                 
54be: 00         BRK                 
54bf: 00         BRK             

;*********************************************************
; secteur : 00 01 02 03 04 05 06 07 08 09 0A 0B
; adresse : -- -- -- -- -- -- -- -- -- bb bc bd
   
54c0: 5e 5e 5e   LSR $5E5E,X         ; adresses de chgt levels : caractéristiques de jeu
54c3: 5e 5e 5e   LSR $5E5E,X         
54c6: 5e 5e 5e   LSR $5E5E,X         
54c9: bb         ???                 
54ca: bc bd      ???
 
54cc: 00         BRK                 ; <<< fin de chargement.


Pour information, les datas spécifiques à chaque 'round' sont répartis comme suit :
round 0 : pistes $0B à $10 + 3 secteurs piste A
round 1 : pistes $11 à $16 + 3 secteurs piste A
round 2 : pistes $17 à $1C + 3 secteurs piste A
round 3 : pistes $1D à $22 + 3 secteurs piste A
... disposition tout à fait logique par ailleurs.

On peut en déduire que le jeu ne démarrait pas vraiment en $4000 comme je le croyais mais on pourrait situer le véritable démarrage à l'adresse $5C0C qui va lancer la boucle vers $5000 et qui reviendra toujours en $Be00 (qui est je le rappelle la routine rechargeant systématiquement tout ce qui est au dessus à chaque fin de 'round'.
En gros :
La partie $5xxx est en page HGR2 et sera détruite à chaque démarrage de partie, il est donc nécessaire de boucler sur un cycle :
- chargement du loader de level -> lancement du loader pour charger le level -> jeu qui détruit le loader -> fin du niveau -> chargement du loader de level -> etc...
C'est la routine en $BE00 qui est appelée par le jeu pour se charger de cela, car son espace mémoire n'est jamais écrasé.

On sait qu'on est un peu à l'étroit dans la routine de chargement principale ($BE00) mais il est possible d'utiliser la ROM du contrôleur disque pour charger (assez lentement) directement la nouvelle routine de chargement en $5500 en zappant la partie $5C00 qui me semble inutile (à creuser). Cette nouvelle routine de chargement dont la taille ne dépassera pas quelques secteurs serait alors assez rapide et efficace pour charger rapidos les 6 pistes de chaque level.

Ca vaut le coup de tenter l'affaire. Heureusement, demain c'est le W.E.
Very Happy
Revenir en haut de page
Voir le profil de l'utilisateur Envoyer un message privé
toinet
Site Admin


Inscrit le: 15 Juin 2007
Messages: 3074
Localisation: Le Chesnay, France

MessagePosté le: Sam 27 Fév 2021, 17:23    Sujet du message: Répondre en citant

Top, bientôt la fin !
Revenir en haut de page
Voir le profil de l'utilisateur Envoyer un message privé Visiter le site web de l'utilisateur
aloysiuscoincoin



Inscrit le: 17 Mar 2018
Messages: 21

MessagePosté le: Lun 01 Mar 2021, 13:29    Sujet du message: Répondre en citant

Bientôt..... Rolling Eyes euh... ça prend un peu de temps quand même Mr. Green mais ça avance...
Revenir en haut de page
Voir le profil de l'utilisateur Envoyer un message privé
Montrer les messages depuis:   
Poster un nouveau sujet   Répondre au sujet     Index du Forum -> PROTECTION MALEFIQUE Toutes les heures sont au format GMT + 1 Heure
Page 1 sur 1

 
Sauter vers:  
Vous ne pouvez pas poster de nouveaux sujets dans ce forum
Vous ne pouvez pas répondre aux sujets dans ce forum
Vous ne pouvez pas éditer vos messages dans ce forum
Vous ne pouvez pas supprimer vos messages dans ce forum
Vous ne pouvez pas voter dans les sondages de ce forum


Powered by phpBB © 2001, 2005 phpBB Group
Traduction par : phpBB-fr.com