SearchForCheats.de.vu » Tutorials » Advanced User Tutorial #1 - How To Create A Shiny Encounter


Tutorial avanzato #1 - Come incontrare uno shiny

This tutorial was translated by the User HackMew. The original version can be found in the tutorial-section.
If you want to provide your support to this website by translating this tutorial to another language, please contact me. (Details can be found in the imprint)
Thanks!
Mastermind_X

Oh, piacere di vederti qui. Questa parte 'segreta' del mio laboratorio pu essere scovata solo da programmatori veramente esperti. *scherza*
Ma, uhm... stai certo che non riuscirai a capire le procedure che andremo a 'hackare' qui, se hai appena finito la Lezione Hacking 4 o qualcosa del genere.
Allora... andiamo ad hackare (crackare?)! Vogliamo provare a realizzare un incontro shiny per la versione americana di Pokmon Rosso Fuoco. Diciamo che rivogliamo indietro il nostro shiny Gyarados vecchio stile. Le tue precedenti conoscenze dovrebbero essere qualcosa di simile:

  • operazioni standard con un editor esadecimale (qualcosa come copia e incolla :-P )
  • come eseguire il repoint di eventi in Advance Map / Elite Map
  • l'indirizzamento GBA (pointer => offset e opposto)
  • i comandi standard per lo scripting Advance
  • e... s... qualche conoscenza riguardo l'ASM aiuterebbe... (non ne avrai bisogno per il tutorial ma se sei interessato a capire come funziona lo script, sarebbe utile)

Ecco ci di cui avremo bisogno:

  • un editor esadecimale (uh... non te l'aspettavi, vero?)
  • la ROM (non chiedermi dove ottenerla!)
  • un emulatore per verificare il risultato
  • il tuo cervello <= Importante!!1oneone

Cosa andremo a fare con tutto ci?
Beh, l'idea principale dovrebbe essere qualcosa del genere:

  • trovare la shiny-routine
  • dividerla in due parti - una patchata e una convenzionale - a seconda di un flag allocato nella RAM
  • scrivere uno script ASM che attivi o disattivi il flag
  • scrivere uno script con due chiamate allo script ASM

Forse ci saranno gi delle domande o dei dubbi. Qual il motivo per usare una soluzione cos complicata? Perch non chiamare semplicemente una routine che modifichi i byte necessari?
Beh, la risposta ... in questo modo, creiamo un flag opportuno, accessibile da qualunque script. A parte questo, non una soluzione veramente 'pulita' lasciare la ROM che si sovrascriva da sola, no?

Fai qualche ricerca standard nella RAM riguardo il PokmonID a 32 bit. Le possibilit che un Pokmon sia shiny o meno basata sul PokmonID. (conosciuto anche come Rnd#). anche la locazione del sesso, della natura, della forma degli Unown e cos via. Ma noi siamo interessati solamente nella 'brillantezza'. La 'brillantezza' calcolata dallo XOR fra i 16 bit pi significativi e quelli meno significati della cosidetta XKey. La XKey il risultato di uno XOR tra il PID e il TrainerIDs.
@_@ Suona molto complicato. Penso debba spiegarlo pi chiaramente. Facciamo un esempio: diciamo che il tuo Trainer ID (che sar un argomento passato per l'incontro di un Pokmon) sia 56432. Il tuo TrainerID 'segreto' Trainer ID (SID) ... ehm... 026025. Convertilo in esadecimale, in modo da ottenere 0xDC70 per l'OTID e 0x65A9 per l'OTSID. Mettili assieme cos:

(OTSID << 0x10) OR (OTID)

Ottieni cos l'OTrainerIDs 0x65A9DC70. Il primo valore il PID/Rnd#. calcolato casualmente. Diciamo che il PID per il Pokmon attualmente incontrato sia 0x57ADF001.
Basandoci sulla conoscenza di questi due valori, noi (o il gioco?) calcoleremo la XKey (suona eccezionale, vero?). La XKey, come ho detto prima, il risultato di uno XOR fra PID e OTrainerIDs. Perci otteniamo (nel nostro caso):

    0x57ADF001
XOR 0x65A9DC70
--------------
    0x32042C71

I dati per lo shiny sono memorizzati nel rapporto fra la semiparola pi significativa e quella meno significativa. Se il risultato dello XOR di questi due valori minore di otto, il Pokmon shiny. Okay. Controlliamo:

(Xkey >> 0x10) XOR (XKey AND 0xFFFF)

(Xkey >> 0x10)    ==     0x3204
(XKey AND 0xFFFF) == XOR 0x2C71
                     ----------
                         0x1E75

Il risultato 0x1E75 decisamente pi grande di 8. Il Pokmon non shiny. :-( Ma siamo qui perch abbiamo intenzione di cambiare tutto ci. La mia idea la seguente:
(Xkey >> 0x10) e (XKey AND 0xFFFF) non possono differire molto da 8. Se potessimo rendere (Xkey >> 0x10) sempre uguale a (XKey AND 0xFFFF), l'operazione di XOR restituirebbe zero. E 0 < 8. Cos avremmo il nostro shiny.
Ogni semiparola, che stata appena raddoppiata ad una parola, sarebbe un valido numero intero. Questo un punto.
Ma la Xkey giusto il risultato di un'altra operazione di XOR. Come possiamo riuscire a forzarla al nostro intero voluto? Il metodo seguente il pi semplice e quello che pi mi piace.
Prendiamo 0x00000000 come nostra XKey. un 'valido' intero shiny ed facile da calcolare da un operazione di XOR. Penso tu sappia come andremo avanti. Impostando il PID uguale all'OTrainerIDs, il calcolo dello XOR restituirebbe 0x00000000, esattamente ci che vogliamo al momento. Per tutti quelli che non riesco a capire nulla se non un'equazione:

((PID XOR OTrainerIDs) >> 0x10) XOR ((PID XOR OTrainerIDs) AND 0xFFFF) < 0x8

Ecco tutto. E se usiamo l'OTrainerIDs come PID otteniamo:

((OTrainerIDs XOR OTrainerIDs) >> 0x10) XOR ((OTrainerIDs XOR OTrainerIDs) AND 0xFFFF) < 8
(0x0 >> 0x10) XOR (0x0 AND 0xFFFF) < 0x8
0 XOR 0 < 0x8
0 < 8

Yeah. Abbiamo risolto il problema. Figo, no?
Cerca nella RAM i dati relativi al Pokmon selvatico. Suggerisco di iniziare con una ricerca "equal to 0" (SOLO PRIMA DEL PRIMO INCONTRO CON UN POKMON DOPO AVER CARICATO IL SALVATAGGIO!!) e di continuare con una ricerca a 32 bit per l'OTrainerIDs. (Puoi calcolarlo con la formula che c' un po' pi su).
Lo troverai attorno a 0x02024030. Magari esattamente l, al momento sono troppo pigro per controllare l'esistenza di un'eventuale protezione DMA. Okay. Apri la ROM nel tuo debugger preferito (io scelgo VBA-SDL-H). Tutti i passaggi seguenti sono per il debugger che uso, altrimenti esegui i passaggi appropriati.
Proveremo a scoprire quando o dove il valore a 32 bit dell'OtrainerIDs scritto nella RAM. Perci per prima cosa inserisco

mb 02024010

nella console e ne controllo la posizione. Non si mosso ancora; nel mio caso, la seconda parola si trova ancora a 0x02024030. (I dati del Pokmon iniziano a 0x0202402C con il PID, lo sapevi?)
Ora posiziono un breakpoint a32 bit (4 byte) su scrittura nella posizione dei dati.

bpw 02024030 4

Digita c nella finestra per continuare l'esecuzione. Quando potrebbe essere raggiunto quel punto, dove l'OTrainerIDs viene nuovamente calcolato? Forse durante l'incontro di un Pokmon selvatico?
Proviamo a camminare in mezzo all'erba. S! Il gioco si interrompe! Ecco cosa ci mostra il debugger:

Breakpoint (on write) address 02024030 old:00 new:00
R00=02024030 R04=0202402c R08=00000001 R12=00000001
R01=00000004 R05=02024220 R09=00000000 R13=03007d64
R02=0202402c R06=00000017 R10=00000000 R14=0803d99f
R03=00000000 R07=083c8d50 R11=00000000 R15=0803d98a
CPSR=0000003f (......T Mode: 1f)
0803d988 3101 add r1, #0x1

Merda. L'operazione scrive semplicemente il byte 0x00 in 0x02024030. Non siamo interessati nella modifica di una stupida procedura nop, perci digita c per continuare. Il gioco si interrompe di nuovo:

Breakpoint (on write) address 02024031 old:00 new:00
R00=02024031 R04=0202402c R08=00000001 R12=00000001
R01=00000005 R05=02024220 R09=00000000 R13=03007d64
R02=0202402c R06=00000017 R10=00000000 R14=0803d99f
R03=00000000 R07=083c8d50 R11=00000000 R15=0803d98a
CPSR=0000003f (......T Mode: 1f)
0803d988 3101 add r1, #0x1

Stessa locazione. Solo due registri (inferiori) cambiati. Un 4 diventato 5 e l'indirizzo in r0, forse (in effetti, cos) contenente la locazione di scrittura incrementato di uno. Siamo attualmente all'interno di un ciclo che elimina le informazioni sul vecchio Pokmon. Possiamo quindi aspettarci che andremo a seguire un po' di interruzioni ancora prima di quelle che stiamo cercando. Digita c e s'interromper di nuovo. Puoi studiare le modifiche o semplicemente ignorarle digitando c.
Ci sono della altre interruzioni in un'altra locazione della ROM ma sono ancora funzioni nop. Continua a digitare c.

Breakpoint (on write) address 02024030 old:00000000 new:65a9dc70
R00=bc000000 R04=03007cf8 R08=00000000 R12=00000008
R01=65a9dc70 R05=00000000 R09=00000000 R13=03007cc0
R02=03007cf8 R06=00000000 R10=00000001 R14=0803db9d
R03=0202402c R07=0202402c R11=00000000 R15=080406dc
CPSR=8000003f (N.....T Mode: 1f)
080406da e1fe b $08040ada

Evvai! Questa la nostra routine! La parola @ 02024030 si appena sovrascritta con 0x65a9dc70, il mio OTrainerIDs. Ora daremo un'occhiata a quella procedura. Disassemblala con

d 080406c2

Perch? solo una stima della lunghezza della procedura. Qualcosa vicino a 080406da, mi dice il debugger. Probabilmente i numeri e le lettere visualizzate non avranno alcun senso per te. Per questo motivo commenter parte per parte. La subroutine l'operando fra due codici che iniziano con 'b $'. 'b $locazione' sta per un operazione di salto (=branch). Questa la sub:

080406c4  7821 ldrb r1, [r4, #0x0]   // carica il byte @ r4 (=03007cf8) in r1
080406c6  7860 ldrb r0, [r4, #0x1]   // carica il byte @ r4+1 (=03007cf9) in r0
080406c8  0200 lsl r0, r0, #0x08   // il byte in r0 shiftato a sinistra di 1 byte (=8bit)
080406ca  1809 add r1, r1, r0   // somma r1 a r0. Otteniamo una semiparola r0+r1
080406cc  78a0 ldrb r0, [r4, #0x2]   // carica il byte @ r4+2 (=03007cfa) in r0
080406ce  0400 lsl r0, r0, #0x10   // r0 shiftato a sinistra di 2 byte
080406d0  1809 add r1, r1, r0   // r0 sommato a r1
080406d2  78e0 ldrb r0, [r4, #0x3]   // carica il byte @ r4+3 (=03007cfb) in r0
080406d4  0600 lsl r0, r0, #0x18   // r0 shiftato a sinistra di 3 byte
080406d6  1809 add r1, r1, r0   r0 // e sommato a r1. questo l'algoritmo che shifta assieme l'ID e il SID
080406d8  6079 str r1, [r7, #0x4]   // infine l'OTrainerIDs salvato in r7+4 (=0202402c) (l'operazione che ha captato il nostro breakpoint)
080406da  e1fe b $08040ada   // esce dalla routine e salta in qualche altro posto

Testiamo la nostra teoria. Se riuscissimo a cambiare

080406d6  1809 add r1, r1, r0   // somma r1 a r0

in qualcosa del genere

080406d6  xxxx str r1, [r7, #0x0]   // sovrascrivi il PID con l'OTrainerIDs

il PID sarebbe sempre uguale all'OTrainerIDs.
L'operando thumb per str r1, [r7, #0x0] 0x6039, non chiedermi come calcolarlo. Per ora sufficiente sapere cosa fa. (Beh... se sei veramente interessato, cerca il documento di Martin Korth e cerca il set d'istruzioni 'store word' - memorizza parola)
Patchiamo la nostra ROM 'al volo' inserendo nel nostro debugger il seguente comando:

eh 080406d6 6039

Quindi, per eliminare i noiosi breakpoint su scrittura:

bpwc

Digita c lascia andare l'incontro. Ma... non shiny! Oh, DANNAZIONE! Che successo???
La risposta : niente.
Il Pokmon non shiny perch la CPU aveva gi passato la locazione chiave quando l'abbiamo patchata.
Come risolvere?
Facile. Incontra un altro Pokmon. Otterai il tuo shiny. :-P
Conoscendo l'offset della patch e il valore, possiamo creare un cheat rapidamente. La sintassi per l'AR V3 la seguente:

00000000 18XXXXXX
0000YYYY 00000000

Uhm... XXXXXX sta per ((indirizzo AND 0x3FFFFF) >> 1) e YYYY semplicemente il valore da patchare. 0x18 dice all'AR di usare la prima patching-slot (z0C).

00000000 1802036B
00006039 00000000

Cripta il tutto con ARCrypt e il tuo cheat (funzionante) sempre-shiny ultimato:

A74320F4 175B5B22
18452A7D DDE55BCC

Fine della prima parte
Se sei semplicemente interessato ad ottenere un cheat per ottenere sempre Pokmon shiny, non hai bisogno di leggere avanti. Hai gi raggiunto il tuo obiettivo.
Ma se sei interessato ad integrare la patch sopra riportato in una cos chiamata hack ROM, hai ancora la parte finale che ti aspetta. Ora otterremo un buon vecchio shiny Gyarados. Pronti? Via!


Iniziamo (continuiamo?) con l'estrazione della... beh... sapendo che non una buona descrizione, la chiamer 'shiny routine'. Perch estrarla? Perch se vogliamo inserirci un flag, la subroutine cresce di dimensione. Quindi, tutti i byte successivi sarebbero sfasati e tutti i salti verrebbero invalidati. Come puoi vedere, non abbiamo scelta. Estraiamola. Ci che otteniamo:

080406c4  b402 push {r1} // salva il valore in r1 ponendolo nello stack
080406c6  4902 ldr r1, [$080406d0] (=$0871b701) // carica l'indirizzo della nuova routine
080406c8  f000 bl $080406cc 080406cc // salta con bl per salvare l'indirizzo di ritorno in lr (necessita di 2*16bit)
080406ca  f800 blh $0000 // appartiene a bl
080406cc  470f bx r1 // branch exchange. Scambia i valori di pc e r1
080406ce  0000 // non passato dalla cpu
080406d0  b701 // data1 (necessario in 0x080406c6)
080406d2  0871 // data2
080406d4  0000 lsl r0, r0, #0x0 // nop, spazio non necessario
080406d6  0000 lsl r0, r0, #0x0 // nop, spazio non necessario
080406d8  0000 lsl r0, r0, #0x0 // nop, spazio non necessario
080406da  e1fe b $08040ada // continua il normale svolgimento del programma

Apri la ROM con un editor esadecimale. Vai all'indirizzo 0x406C0. L troverai la 'shiny routine' che andremo a modificare.

000406c0h: 39 60 0A E2 21 78 60 78 00 02 09 18 A0 78 00 04 ; 9`.!x`x....x..
000406d0h: 09 18 E0 78 00 06 09 18 79 60 FE E1 00 22 3B 1C ; ..x....y`.";.

Sovrascrivi la routine precedentemente disassemblata con quella riportata qui sotto:

000406c0h: 39 60 0A E2 02 B4 02 49 00 F0 00 F8 0F 47 00 00 ; 9`...I...G.. 000406d0h: 01 B7 71 08 00 00 00 00 00 00 FE E1 00 22 3B 1C ; .q........";.

In questo modo la CPU salta sempre prima di un incontro alla ROM non allocata. Puoi provare a camminare in mezzo all'erba e vedrai l'incontro totalmente incasinato. ;-)
Inseriamo ora la 'shiny routine' all'indirizzo 0871b700. Perch 0x00 invece di 0x01?
Bene. L'ultimo bit di un'operazione di branch decreta se la seguente routine scritta in modalit ARM oTHUMB. 0 significa ARM e 1 sta per una thumb-routine. Noi usiamo una thumb-routine perci l'indirizzo finisce con 1, anche se inizia @ 0871b700.

0871b700  bc02 pop {r1} // ottiene il valore salvato
0871b702  b500 push {lr} // mette il valore di ritorno nello stack
0871b704  bc02 pop {r1} // carica di nuovo r1
0871b706  3108 add r1, #4 // sistema il valore di ritorno di 8. (per saltare i dati dell'indirizzo)
0871b708  b402 push {r1} // salva nuovamente l'indirizzo di ritorno
0871b70a  490e ldr r1, [$0871b744] (=$02022000) ) // aww... e qui sovrascritto...piuttosto inutile, lo so ^^
0871b70c  6809 ldr r1, [r1, #0x0] // carica il valore @ 02022000 in r1
0871b70e  2901 cmp r1, #0x1
0871b710  d00b beq $0871b72a
0871b712  7821 ldrb r1, [r4, #0x0]   // carica il byte @ r4 (=03007cf8) in r1
0871b714  7860 ldrb r0, [r4, #0x1]   // carica il byte @ r4+1 (=03007cf9) in r0
0871b716  0200 lsl r0, r0, #0x08   // il byte in r0 shiftato di 1 byte (=8bit)
0871b718  1809 add r1, r1, r0   // r1 e r0 sono sommati. otteniamo una semiparola r0+r1
0871b71a  78a0 ldrb r0, [r4, #0x2]   // carica il byte @ r4+2 (=03007cfa) in r0
0871b71c  0400 lsl r0, r0, #0x10   // r0 shiftato a sinistra di 2 byte
0871b71e  1809 add r1, r1, r0   // r0 sommato a r1
0871b720  78e0 ldrb r0, [r4, #0x3]   // carica il byte @ r4+3 (=03007cfb) in r0
0871b722  0600 lsl r0, r0, #0x18   // r0 shiftato a sinistra di 3 byte
0871b724  1809 add r1, r1, r0   // e sommato a r1
0871b726  6079 str r1, [r7, #0x4]   // infine l'OTrainerIDs salvato in r7+4 (=0202402c) 0871b728  e00b b $0871b742 // salta le se seguenti linee. Sono usate per gli shiny
0871b72a  7821 ldrb r1, [r4, #0x0]   // carica il byte @ r4 (=03007cf8) in r1
0871b72c  7860 ldrb r0, [r4, #0x1]   // carica il byte @ r4+1 (=03007cf9) in r0
0871b72e  0200 lsl r0, r0, #0x08   // il byte in r0 shifato a sinistra di 1 byte (=8bit)
0871b730  1809 add r1, r1, r0   // r1 e r0 sono sommati
0871b732  78a0 ldrb r0, [r4, #0x2]   // carica il byte @ r4+2 (=03007cfa) in r0
0871b734  0400 lsl r0, r0, #0x10   // r0 shiftato di 2 byte
0871b736  1809 add r1, r1, r0   // r0 sommato a r1
0871b738  78e0 ldrb r0, [r4, #0x3]   // carica il byte @ r4+3 (=03007cfb) in r0
0871b73a  0600 lsl r0, r0, #0x18   // r0 shiftato a sinistra di 3 byte
0871b73c  1809 add r1, r1, r0   // e sommato a r1
0871b73e  6079 str r1, [r7, #0x4]   // infine l'OTrainerIDs salvato in r7+4 (=0202402c)
0871b740  6039 str r1, [r7, #0x0]   // e qui c' la nostra patch. il PID soprascritto con l'OTrainerIDs
0871b742  bd00 pop {pc} // ritorna ed esci dalla sub
0871b744  0020 //data1
0871b746  0202 //data2

Bello. Magari ti sarai accorto che non ho sostituito i comandi come ho fatto prima con il cheat per l'AR.
Perch? Semplicemente perch sovrascrivendo l'operatore @0871b73c il primo byte dell'OTrainerIDs ne verrebbe affetto. Usando l'Action Replay siamo contenti di incontrare Pokmon shiny e non ci curiamo ulteriormente dell'OTrainerIDs. (Perci, cheaters, i vostri shiny hackati potrebbero sempre essere tracciati per il fatto che l'OTrainerIDs non corrisponde!)
Scrivendo diretta sulla ROM (che quello che andremo a fare) fornisce l'opportunit di correggere quel bug. Non c' bisogno di eliminare un operatore, cos aggiungiamo semplicemente una linea. Come ottenere tutti i valori calcolati al posto degli operatori? Le soluzioni sono due. Io, personalmente, ho scritto la funzione direttamente in ASM ma puoi anche usare un compilatore. (come il devkit pro's arm-eabi) A questo punto apriamo la ROM con un editor esadecimale e andiamo alla nostra locazione desiderata: 0x71b700. Inseriti i tuoi operatori, la ROM dovrebbe risultare cos:

0071b700h: 02 BC 00 B5 02 BC 08 31 02 B4 0E 49 09 68 01 29 ; ....1..I.h.)
0071b710h: 0B D0 21 78 60 78 00 02 09 18 A0 78 00 04 09 18 ; .!x`x....x....
0071b720h: E0 78 00 06 09 18 79 60 0B E0 21 78 60 78 00 02 ; x....y`.!x`x..
0071b730h: 09 18 A0 78 00 04 09 18 E0 78 00 06 09 18 79 60 ; ..x....x....y`
0071b740h: 39 60 00 BD 00 20 02 02 FF FF FF FF FF FF FF FF ; 9`.. ..

Un enorme massa di codice. Verifichiamone il risultato!
Carica la ROM nel VBA, apri il visualizzatore di memoria e vai a 02022000. Dovresti trovare il valore zero. sar un incontro 'normale'. Ora cambia il flag in 0x01. Incontra un Pokemon. shiny. Bene!
Ora abbiamo bisogno della possibilit di cambiare il flag tramite script. Useremo quindi il comando 0x23. Sta per una chiamata ASM. La routine chiamata deve attivare o disattivare il flag. Ci che creiamo il seguente:

0871b760  b507 push {r0, r1, r2, lr} // salva indirizzo di ritorno
0871b762  4803 ldr r0, [$0871b770] (=$02022000) // ottiene la posizione del flag
0871b764  6801 ldr r1, [r0, #0x0] // ottiene il valore del flag
0871b766  2201 mov r2, #0x1
0871b768  4051 eor r1, r2 // scambia il valore del flag
0871b76a  6001 str r1, [r0, #0x0] // salva il nuovo valore
0871b76c  bd07 pop {r0, r1, r2, pc} // ottiene il valore salvato, ritorna
0871b76e  0000 // non passato
0871b770  0020 //data1
0871b772  0202 //data2

Ogni volta che chiamiamo quella funzione, lo 'shinyflag' attivato o disattivato. Inseriscilo nella ROM.

0071b770h: 07 B5 03 48 01 68 01 22 51 40 01 60 07 BD 00 00 ; ..H.h."Q@.`...
0071b780h: 00 20 02 02 FF FF FF FF FF FF FF FF FF FF FF FF ; . ..

Evviva! Ora abbiamo finito la parte relativa all'ASM. L'ultima parte dovrebbe essere la pi facile. Abbiamo solo da scrivere uno script che chiami la funzione che attivi lo shiny-flag, realizzi l'incontro e infine disabiliti il flag. Lo script il seguente:

[23]        //chiamata asm
[XXXXXXXX]  //pointer alla thumb-sub +1
[00]        //nop
[B6]        //Pokmon selvatico
[XXXX]      //ID-Pokmon (INGAME)
[XX]        //livello
[XXXX]      //strumento tenuto
[00]
[25]        //evento speciale
[3801]      //incontro Pokmon selvatico!
[28]        //attendi
[0101]      //un secondo
[23]        //chiamata asm
[XXXXXXXX]  //pointer alla thumb-sub +1
[02]        //fine

Mettendo tutto assieme otteniamo (per uno shiny Gyarados, livello 30) il seguente script:

0071b7a0h: 23 71 B7 71 08 00 B6 82 00 1E 00 00 00 25 38 01 ; #qq.......%8.
0071b7b0h: 28 01 01 23 71 B7 71 08 02 FF FF FF FF FF FF FF ; (..#qq..

Scegli un evento e repointalo a $71b7a0 o inserisci lo script illustrato sopra come preferisci. ;-)



"Pokmon" ist ein eingetragenes Warenzeichen der Firma Nintendo
"Action Replay" ist ein eingetragenes Warenzeichen von Datel Interact.
© www.SearchForCheats.de.vu by Mastermind_X
© 2006 - 2008