TMNT: Tournament Fighters (SNES)

Aperto da White Dragon, Febbraio 21, 2007, 02:28:58

Discussione precedente - Discussione successiva

White Dragon

Vorrei tradurre questo gioco solo ke ho un problema..
non riesco a trovare il testo della schermata iniziale (quella dei diritti riservati).
appare appena parte la rom in pratika..

in sostanza tutto il testo sembra NON compresso.. e la table è questa:
10=a
11=b
12=c
13=d
14=e
15=f
16=g
17=h
18=i
19=j
1A=k
1B=l
1C=m
1D=n
1E=o
1F=p
20=q
21=r
22=s
23=t
24=u
25=v
26=w
27=x
28=y
29=z


cercando sul save state il testo della schermata iniziale mi appare nel seguente modo:

es. ciao=

12 21 18 21 10 21 1e 21

cioè a 16 bit intervallati dal byte 21.
ovviamente cercando nella rom, il testo nn appare come sul save state x cui nn lo trovo. è strano nn penso sia compresso.. questa rom è una lorom se può interessare. qualkuno saprebbe darmi una mano? ^__^

Gemini

Quello che tu chiami testo a 16 bit in realtà è la mappa dei tile. 21 indica raggio di tile 256-511 sul layer in uso senza flip orizzontale e verticale. L'unico modo che mi viene in mente per ritrovare quel testo è mettere un breakpoint sulla mappa dei tile in scrittura e tracciare il codice al contrario per vedere da dove provengono i dati.

White Dragon

dunque ho provato...
ho cercato il tile della font.. ma la grafika è compressa =((
mi sono aiutato col savestate e copiando i primi bytes ho visto ke nella rom cmq coincidevano. l'address è 0xc8f2b usando quest'indirizzo come breackpoint xò, il debugger nn brekka affatto (io ho provato con geiger snes9x dbg).
nn posso decomprimere la grafica neanke con lunar compress =((

Gemini

Evidentemente hai sbagliato la posizione del breakpoint. Posizionalo in ram invece che sulla rom, così saprai sicuramente quando viene scritto.

White Dragon

allora ti spiego bene cosa ho fatto (grazie per le dritte ke mi stai dando a prop.)
eseguo geiger snes9x debugger.
metto un bpx on write su d0f2b (cioè c8f2b+8000 xkè è una lorom) spero di aver fatto bene in questo modo^^
clicco su RUN e poi.. in effetti brekka.
poi clicco si SKIP x vedere le istruzioni successive.. ed eccole qui:


$80/8024 54 00 00    MVN 00 00               A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8027 AB          PLB                     A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8027 AB          PLB                     A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8028 A9 AB 51    LDA #$51AB              A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8028 A9 AB 51    LDA #$51AB              A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/802B 8D FE 1F    STA $1FFE  [$00:1FFE]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/802B 8D FE 1F    STA $1FFE  [$00:1FFE]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/802E A9 FF FF    LDA #$FFFF              A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/802E A9 FF FF    LDA #$FFFF              A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8031 8D DE 1F    STA $1FDE  [$00:1FDE]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8031 8D DE 1F    STA $1FDE  [$00:1FDE]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8034 22 E3 B6 83 JSL $83B6E3[$83:B6E3]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8034 22 E3 B6 83 JSL $83B6E3[$83:B6E3]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8038 22 93 A1 86 JSL $86A193[$86:A193]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8038 22 93 A1 86 JSL $86A193[$86:A193]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/803C 22 F8 B3 83 JSL $83B3F8[$83:B3F8]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/803C 22 F8 B3 83 JSL $83B3F8[$83:B3F8]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8040 22 E8 E2 86 JSL $86E2E8[$86:E2E8]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8040 22 E8 E2 86 JSL $86E2E8[$86:E2E8]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8044 80 1A       BRA $1A    [$8060]      A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8044 80 1A       BRA $1A    [$8060]      A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8046 C2 30       REP #$30                A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8046 C2 30       REP #$30                A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8048 8B          PHB                     A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8048 8B          PHB                     A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8049 A9 00 00    LDA #$0000              A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8049 A9 00 00    LDA #$0000              A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/804C 8F 00 00 00 STA $000000[$00:0000]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/804C 8F 00 00 00 STA $000000[$00:0000]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8050 A9 7D 1F    LDA #$1F7D              A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8050 A9 7D 1F    LDA #$1F7D              A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8053 A2 01 00    LDX #$0001              A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8053 A2 01 00    LDX #$0001              A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8056 9B          TXY                     A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8056 9B          TXY                     A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8057 C8          INY                     A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8057 C8          INY                     A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8058 54 00 00    MVN 00 00               A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8058 54 00 00    MVN 00 00               A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/805B AB          PLB                     A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/805B AB          PLB                     A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/805C 22 26 B4 83 JSL $83B426[$83:B426]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/805C 22 26 B4 83 JSL $83B426[$83:B426]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8060 C2 30       REP #$30                A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8060 C2 30       REP #$30                A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8062 8B          PHB                     A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8062 8B          PHB                     A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8063 A9 00 00    LDA #$0000              A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8063 A9 00 00    LDA #$0000              A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8066 8F 00 20 7E STA $7E2000[$7E:2000]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8066 8F 00 20 7E STA $7E2000[$7E:2000]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/806A A9 FD 5F    LDA #$5FFD              A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/806A A9 FD 5F    LDA #$5FFD              A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/806D A2 01 20    LDX #$2001              A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/806D A2 01 20    LDX #$2001              A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8070 9B          TXY                     A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8070 9B          TXY                     A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8071 C8          INY                     A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8071 C8          INY                     A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8072 54 7E 7E    MVN 7E 7E               A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8072 54 7E 7E    MVN 7E 7E               A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8075 AB          PLB                     A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8075 AB          PLB                     A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8076 A9 00 00    LDA #$0000              A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8076 A9 00 00    LDA #$0000              A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8079 5B          TCD                     A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8079 5B          TCD                     A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/807A E2 20       SEP #$20                A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/807A E2 20       SEP #$20                A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/807C A9 81 48    LDA #$4881              A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/807C A9 81 48    LDA #$4881              A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/807F AB          PLB                     A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/807F AB          PLB                     A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8080 C2 20       REP #$20                A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8080 C2 20       REP #$20                A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8082 E2 20       SEP #$20                A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8082 E2 20       SEP #$20                A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8084 AD 10 42    LDA $4210  [$00:4210]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8084 AD 10 42    LDA $4210  [$00:4210]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8087 9C 00 42    STZ $4200  [$00:4200]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8087 9C 00 42    STZ $4200  [$00:4200]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/808A A9 80 8D    LDA #$8D80              A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/808A A9 80 8D    LDA #$8D80              A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/808D 00 21       BRK #$21                A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/808D 00 21       BRK #$21                A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/808F C2 20       REP #$20                A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/808F C2 20       REP #$20                A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8091 22 58 89 80 JSL $808958[$80:8958]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8091 22 58 89 80 JSL $808958[$80:8958]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8095 C2 10       REP #$10                A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8095 C2 10       REP #$10                A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/8097 A0 FF 7F    LDY #$7FFF              A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/8097 A0 FF 7F    LDY #$7FFF              A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/809A A2 00 00    LDX #$0000              A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/809A A2 00 00    LDX #$0000              A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/809D 22 A2 97 80 JSL $8097A2[$80:97A2]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/809D 22 A2 97 80 JSL $8097A2[$80:97A2]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/80A1 E6 3C       INC $3C    [$00:003C]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/80A1 E6 3C       INC $3C    [$00:003C]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/80A3 9C A2 1C    STZ $1CA2  [$00:1CA2]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/80A3 9C A2 1C    STZ $1CA2  [$00:1CA2]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/80A6 8B          PHB                     A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/80A6 8B          PHB                     A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/80A7 A9 FF 7F    LDA #$7FFF              A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/80A7 A9 FF 7F    LDA #$7FFF              A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/80AA 8F 00 40 7E STA $7E4000[$7E:4000]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/80AA 8F 00 40 7E STA $7E4000[$7E:4000]   A:10D4 X:0F2A Y:0F2B P:envmxdIzC$80/80AE A9 FE 01    LDA #$01FE              A:10D4 X:0F2A Y:0F2B P:envmxdIzC
$80/80AE A9 FE 01    LDA #$01FE
...
...
...


quale potrebbe essere l'istruzione ke karika il testo?

Gemini

Più che andare in avanti con le istruzioni dovresti tornare indietro, magari usando un tracciato del codice per vedere esattamente da dove parte la funzione di "smaltimento" dei testi.

Morpher

Quella che hai li non è la routine giusta. Per vedere come il gioco decomprime il testo iniziale (perchè è testo e non grafica) posizionati in ram all'indirizzo 7E2000 (direttamente nell'hex editor del debugger), setta un break in scrittura all'indirizzo 7E20CA e poi vai con Run diverse volte, finchè non vedi in ram i soliti byte 21 00 21 00 21 00 ecc... Clicca su Step Out finchè non vedi questa istruzione

$80/A392 C9 80       CMP #$80                A:0083 X:00CC Y:0013 P:eNvMxdIzc

Da qui hai inzio la routine di decompressione del testo. I byte compressi nella rom li trovi all'indirizzo C8D0E (i primi byte sono 83 23 21 14 04 AC 85 1D 21 10).

In ogni caso sembra un sorta di Lz utilizzata però per nascondere i dati anzichè comprimerli. Se non lo hai già fatto leggiti la guida di Phoenix sulle Lz che trovi nella sezione Angolo della modestia magari può tornarti utile.

White Dragon

morpher ti ringrazio molto x la risposta...
dunque io vorrei a questo punto capire bene x essere "autosufficiente" ke se va tutto bene ci scrivo anke un de/compressore.
dunque si parte dall'indirizzo in ram 7e2000. e qui la prima domanda:
perkè il 2000? perkè è da quest'indirizzo ke parte il codice vero e proprio del prog in ram? cioè dopo aver letto tutto l'header ecc..?

poi anke settando un bpx on write a quest'indirizzo in ram prima o  poi mi vedrò
apparire i 21xx21xx bytes.. ed il testo inizierà all'indirizzo: 7E20CA in ram ormai  già decmpresso.

a quel punto dopo aver fatto un po' di RUN devo fermarmi all'istruzione immediatamente precedente a quando appaiono i 21xx21.. per poi fare un po' di SKIP per vedere il codice successivo (se faccio STEPOUT ke dovrebeb saltare tutte le chiamate, il gioco mi parte). quindi arrivo all'istruzione:
$80/A392 C9 80 CMP
attraverso gli SKIP dopo essermi fermato a $80/A31C.

solo che in questo modo con posso ricavarmi l'indirizzo C8D0E ke ti sei ricavato.
ed ecco la seconda domanda: come faccio a usare STEPOUT x far si ke
il gioco si fermi sull'istruzione $80/A392 C9 80 CMP senza ke il gioco parta come hai fatto tu?

ps.grazie x tutti gli aiuti ke mi state dando^__^
ps2.ho avuto a ke fare con dbg x pe x cracking e unpacking, ma x snes mai^__^

Morpher

Citazioneperkè il 2000? perkè è da quest'indirizzo ke parte il codice vero e proprio del prog in ram? cioè dopo aver letto tutto l'header ecc..?

Allora, ti posizioni in ram a 7E2000 non perchè li ha inizio la routine di decompressione ma è li, invece, che vengono inseriti i primi byte decompressi; è come un programma vero e proprio che svolge dei calcoli o lavori in una parte della memoria.

Citazionecome faccio a usare STEPOUT x far si ke
il gioco si fermi sull'istruzione $80/A392 C9 80 CMP senza ke il gioco parta come hai fatto tu?

Errore mio :D. Devi cliccare su Step Over


White Dragon

xfetto ti ringrazio molto. un'ultima sola cosa prima di studiarmi tutto il codice:
1) LDA [$00],y[$99:8D0E] è l'istruzione attraverso la quale ti sei ricavato l'addr della routine. l'istruzione significa:
carica in A (accumulatore) ciò ke si trova in $00+$99:8D0E offset. il risultato è
C8D0E, ma non capisco dove dice di sommare c0000 ad 8D0E. forse centra il registro Y:0013 cioè il contenuto di $00?
2) sapresti indicarmi una buona guida sull'assembler dello snes(motorola 65816)?
3) la routine di decompressione inizia dall'istruzione LDA [$00],y[$99:8D0E] perkè è la prima ke karika dalla rom dei valori da elaborare giusto?

dopo queste domandine spero di aver finito di scassarti^__^

Morpher

Rispondo anche se con un po'di ritardo :D

Allora, l'asm del Snes è una vera cavolata; dopotutto ci sono davvero poche istruzioni. Se vai nella sezione documenti di romhacking.net dovresti trovare qualche guida. Per quanto riguarda la routine di decompressione posso dirti che è davvero semplice. Ci sono giusto un paio di operazioni matematiche da fare per calcolare il salto (assoluto) e i cicli di iterazione per recuperare i caratteri che si ripetono. Se poi vuoi evitarti casini puoi eliminare la routine di decompressione (in questo caso devi accertarti che la routine venga usata solo per quel testo) e far leggere direttamente i caratteri.

White Dragon

Ti ringrazio molto morpher, ma ti dico ke il mio obiettivo non è tanto tradurre il gioko quanto imparare ad interpretare l'asm dello snes e scrivere un de/compressore con algoritmo di tipo lz(x).
ho visto x es. ke il byte riconoscitore se lo calcola con un semplice AND 0x1F sull'accumulatore ecc..
quello ke proprio non riesco a capire è:
come sei riuscito a capire qual'è l'indirizzo fisiko in cui inizia il testo?
cioè l'istruzione LDA [$00],y[$99:8D0E] mi da l'indirizzo 8D0E, ma tu
mi hai giustamente detto ke l'indirizzo in cui inizia il testo compresso è
C8D0E. cioè C0000+8D0E. ecco io nn riesco a capire come hai fatto a ricavarti
quest'indirizzo. io leggo solo 8D0E =(((

Morpher

Se ti posizioni all'indirizzo $998D0E nell'hex editor del debugger puoi vedere i byte. Ne copi alcuni e li cerchi in un hex editor come WinHex. Era questo il problema?

White Dragon

si ^__^ grazie... mi perdo in un bikkier d'acqua.. =)))
ho già cominciato a scrivere il de/compressore. poi lo posterò qui ovviamente^__^

ps. scriverò sul readme i dovuti ringraziamenti morpher. grazieeeee!!

White Dragon

dunque stavo programmando il compressore.. ma mentre lo stavo programmando mi è sorto un dubbio..
questo algoritmo LZ funziona così:
XX YY YY YY YY YY YY YY ZZ KK ZZ KK ZZ KK XX

dove XX è il byte riconoscitore
YY sono i bytes normali
e ZZ KK sono le coppie salto/recupero

il programma fa un'operazione di AND sul byte di salto ovvero
ZZ KK AND 0x3FF (ZZ e KK sono la coppia salto/recupero concatenata)
dopo aver sottratto 0x3DF
es. se la coppia è 7C 89 fa 7C89 -3DF = 78AA and 0x3FF = AA
AA poi si dovrà sommare a 7E2000 per ricaversi l'indirizzo della ram da cui recuperare i dati. nell'esempio 7E20AA
attraverso questo fatidico "AND 0x3FF" s'intuisce che il salto max è all'indirizzo 0x3FF...

a questo punto essendo la prima volta ke programmo un LZ (e kiedo a voi esperti)
mi viene il dubbio:

Non ho ben capito come funziona la WINDOW composta da buffer+look_ahead_buffer. mi spiego meglio:
finkè io per es. ho letto fino a 3FF caratteri e quindi mi trovo alla posizione 3FF (7E:23FF) allora tutto ok. ma poi una volta ke il mio SEARCH BUFFER (cioè il buffer carrikato in RAM che contiene i caratteri esaminati in precedenza) supera i 3FF caratteri come devo procedere? eh si perkè il salto arriva al massimo a dire:
"salta all'indirizzo 3FF"!
es. io mi trovo all'indirizzo 0x450. come faccio a dire: "preleva il carattere all'indirizzo 0x411"? forse dovrei resettare il buffer? sulle guide nn spiegano mai come funziona il SEARCH BUFFER e soprattutto con un salto ASSOLUTO (per indirizzo) come in uqesto caso... ahimè ke krepazione l'lzss...

ps. ho letto tutte le guide possibili, inglesi e italiane ma questa cosa nn l'ho trovata prooprio..

RISPOSTA: (ormai mi risp. anke da solo =))) )
Il buffer (search_buffer) che contiene i caratteri in cui cercare si intuisce dal salto che è grande 0x3FF. Poi arrivato al byte n° 0x3FF il buffer
scorre di X byte alla volta, dove X sono gli ultimi bytes codificati. se la lunghezza max del buffer viene superata, allora sovrascrivi dalla prima posizione del buffer i nuovi bytes codificati. ciò ovviamente avverrà anche durante il processo di decompressione.