You are not logged in.

Wie bekomme ich Zugriff aufs Cartmoddingforum | Fire Emblem: Das Siegelschwert Übersetzer gesucht | Videotutorial - Spielpatches benutzen! | Spenden für die Seite

Dear visitor, welcome to Snes-Projects.de. If this is your first visit here, please read the Help. It explains in detail how this page works. To use all features of this page, you should consider registering. Please use the registration form, to register here or read more information about the registration process. If you are already registered, please login here.

manakoAT

Techniker

  • "manakoAT" is male
  • "manakoAT" started this thread

Posts: 165

Thanks: 30

  • Send private message

1

Sunday, September 11th 2011, 6:31pm

[Fortgeschritten] Textroutinen finden und MTE/DTE Routinen mit einbauen.

Status: Im Aufbau

Unser Testobjekt:
E.V.O. - Search for Eden (USA)
Ohne Header, CRC32: DD49911E

Benötigte Tools:
"Geiger's Snes9x Debugger"
"Lunar Adress und Lunar Expand", gibt's hier
"xkas v0.6", gibt's hier

Was sind MTEs/DTEs?
MTE (Multiple Table Entry) bedeutet dass mehrere Zeichen auf einem Byte in der Table liegen, zum Beispiel: 80=have
DTE (Dual Table Entry) bedeutet dass mehrere Zeichen auf 2 Bytes liegen, dabei wird das erste zum Identifizieren genommen (sollte eins sein was nicht in der normalen Table auftaucht), und das zweite legt fest welcher Eintrag es ist, zum Beispiel: 0367=someone

Bitte PM schreiben falls "MTE (Multiple Table Entry)" oder "DTE (Dual Table Entry)" die verkehrten Begriffe sind, kann mich da nur schwach erinnern :o)


Wozu dienen MTEs/DTEs?
Einfach um Platz zu sparen, eine Liste der meistbenutzten Wörter oder SIlben wird irgendwo abgelegt, mit Pointern versehen und im Haupttext wird jede dieser SIlben oder jedes dieser Wörter durch das jeweilige Byte ersetzt.

Beispiel MTE: "You have a question?" <- Länge 20 Bytes... Ersetzen wir jetzt "have" mit dem Wert 80 erhalten wir "You \0x80\ a question?" und unser Text ist nur noch 17 Bytes lang.
Beispiel DTE: "Ask someone else!" <- Länge 17 Bytes... Ersetzen wir jetzt "someone" mit dem Wert 0367 erhalten wir "Ask \0x0367\ else!" und unser Text ist nur noch 12 Bytes lang.


Vorbereiten der ROM (MTE):
Als erstes expandieren wir die ROM auf 16MBit, oder ihr sucht euch freien Platz irgendwo, dann erstellen wir uns eine Pointertable mit unseren TEST MTEs.

Beispiel: PC Offset 0x180800, SNES LoRom Adresse $30:8800



Finden der Textroutine:
Als erstes sucht ihr euch etwas Text in der Rom, am besten irgendwo am Anfang des Spiels, in unserem Beispiel nehmen wir "Hi! My name is Gaia......", zu finden an Offset 0xEE8F3, dann konvertieren wir das Ganze in eine LoRom Adresse $1D:E8F3, mit dieser Adresse starten wir nun Snes9x und warten das der Breakpoint ausgelöst wird.

Im Debug Log sollte nun dies auftauchen: $03/B608 B9 00 00 LDA $0000,y[$1D:E8F3] A:002E X:0000 Y:E8F3 P:envmxdIZc

Wenn wir jetzt einige Male "Step Into" machen, können wir so ziemlich die ganze Routine sehen:

Und so weiter, und so fort...

Ich habe die ganze Routine mal nachgeschrieben und mit Kommentaren versehen, damit man es besser nachvollziehen kann:
Einige Infos vorab:
- Unser Rombank im Beispiel ist $1D
- Unser erste Rombank Position ist
$E8F3 (also Register Y=$E8F3)
- Der OR Key an Offset $32 ist hier immer $2000


READ_NEXT_LETTER:
LDA $0000,y —————————> ; Y enthält unsere derzeite Position in der Rombank in der wir uns befinden ($1D:E8F3)

AND #$00FF ——————————> ; AND Operation, z.B.: (Wert $6948 in A) -> $6948 AND &#00FF = $0048
ORA $32 —————————————> ; OR Operation, z.B.: (Wert $0048 in A) -> $0048 OR $32 = $2048
STA $34 —————————————> ; Speichern von A in die Ram Adresse $34 (Unsere Bytes $2048 nach Offset $34)
AND #$00FF ——————————> ; AND Operation mit A ($2048 AND #$00FF = $0048)
CMP #$00FF ——————————> ;
Vergleichen (CoMPare) ob der Wert in A $00FF ist
BEQ END_FOUND ———————> ; Wenn Ja (BRanch Equals), dann gehe zu END_FOUND (siehe weiter unten)
CMP #$00FE ——————————> ;
Vergleichen (CoMPare) ob der Wert in A $00FE ist
BEQ NEXT_LINE_FOUND —> ; Wenn Ja (BRanch Equals), dann gehe zu NEXT_LINE_FOUND (siehe weiter unten)
Wenn der Code bis hierhin durchläuft haben wir weder einen Zeilenumbruch, noch
das Ende unseres Textes erreicht, sondern wir haben einen normalen Buchstaben

PHX —————————————————> ; X in den STack schieben (PusH X)
TXA —————————————————> ; Transferiere X nach A
CLC —————————————————> ; CLear Carry, löscht den Carry falls was "drin" ist
ADC $36 —————————————> ; ADd with Carry , adde das was an Ram Offset $36 steht zu A
TAX —————————————————> ; Transferiere A nach X
LDA $34 —————————————> ; LaDe nach A was an Ram Offset $34 steht (Unser Buchstabe)
STA $7F6000,x ———————> ; STore A, Speichern von A an Ram Offset $7F6000+x
INY —————————————————> ; INcrease Y (Unsere derzeite Position in der Rom)
PLX —————————————————> ; PuLl X, jetzt holen wir uns unser Index Register X wieder zurück
INX —————————————————> ; INcrease X (Unser Schreiboffset für die Buchstaben)
INX —————————————————> ; INcrease X
JMP READ_NEXT_LETTER

NEXT_LINE_FOUND:
LDA $36 —————————————> ; LaDe nach A was an Ram Offset $36 steht
CLC —————————————————> ;
CLear Carry, löscht den Carry falls was "drin" ist
ADC #$002E ——————————> ; AD to Carry, adde $002E zu A
STA $36 —————————————> ; STore A, Speicher A in Ram Offset $36
INY —————————————————> ; INcrease Y, Y erhöhen (Unsere derzeite Position in der Rom)
LDX #$0000 ——————————> ; LaDe $0000 in X
JMP READ_NEXT_LETTER

END_FOUND:
TXA —————————————————> ; Transferiere X nach A
CLC —————————————————> ; CLear Carry
ADC $36 —————————————> ; ADd with Carry , adde das was an Ram Offset $36 steht zu A
TAX —————————————————> ; Transferiere A nach X
LDA #$FFFF ——————————> ; LaDe $FFFF in A
STA $7F6000,x ———————> ; STore A, Speicher A in Ram Offset $7F6000+x
JML $03B653 —————————> ; JuMp Long, Springt zu dem Punkt nach der Originalen Routine




Jetzt packen wir ein wenig eigenen Code dazu, alles was neu ist ist Rot markiert:

org $308000
READ_NEXT_LETTER:
LDA $0000,y —————————> ; Y enthält unsere derzeite Position in der Rom
AND #$00FF ——————————> ; Die letzten 8 Bit prüfen und in A laden
ORA $32 —————————————> ; R auf den Akkumulator mit dem Wert der in der Ram Adresse $32 steht
STA $34 —————————————> ; Speichern von A in die Ram Adresse $34 (Unser Buchstabe)
AND #$00FF ——————————> ; Die letzten 8 Bit prüfen und in A laden, entfernt OR wieder
CMP #$00FF ——————————> ; vergleichen ob der Wert in A $FF ist
BEQ END_FOUND ———————> ; Wenn Ja (BRanch Equals), dann gehe zu END_FOUND (siehe weiter unten)
CMP #$00FE ——————————> ; vergleichen ob der Wert in A $FE ist
BEQ NEXT_LINE_FOUND —> ; Wenn Ja (BRanch Equals), dann gehe zu NEXT_LINE_FOUND (siehe weiter unten)
CMP #$0080 ---------
—> ; CoMPare, Vergleichen ob A den Wert $0080 oder höher hat, wenn ja wird der "Carry Flag" gesetzt
BCS READ_MTE_POINTER-> ; Branch if Carry is Set, Wenn der Carry Flag gesetzt ist, springe weiter und lese den MTE Pointer
PHX —————————————————> ; PusH index register X, speichern von X im Stack
TXA —————————————————> ; Transferiere X nach A
CLC —————————————————> ; CLear Carry
ADC $36 —————————————> ; ADd to Carry , adde das was an Ram Offset $36 steht zu A
TAX —————————————————> ; Transferiere A nach X
LDA $34 —————————————> ; LaDe nach A was an Ram Offset $34 steht (Unser Buchstabe)
STA $7F6000,x ———————> ; STore A, Speichern von A an Ram Offset $7F6000+x
INY —————————————————> ; INcrease Y (Unsere derzeite Position in der Rom)
PLX —————————————————> ; PuLl X, jetzt holen wir uns unser Index Register X wieder zurück
INX —————————————————> ; INcrease X (Unser Schreiboffset für die Buchstaben)
INX —————————————————> ; INcrease X
JMP READ_NEXT_LETTER

Sollte unser "Carry Flag" gesetzt gewesen sein, landen wir hier
READ_MTE_POINTER:
INY -----------
------> ; Y erhöhen
PHY -----------
------> ; Y in den Stack verschieben
PHX ----------
-------> ; X in den Stack verschieben
SBC #$0080 ---
-------> ; SuBstract with Carry, wir ziehen jetzt $0080 von unserem gelesenen Wert ab
ASL ---------
--------> ; Arithmethik Shift Left, einmal nach links "shiften", ist dasselbe wie mit 2 multiplizieren
TAX ---------
--------> ; Transferiere A nach X
LDA $318800,x-
-------> ; LaDe nach A von Offset $318800+X
TAX ---------
--------> ; Transferiere A nach X
Das Lesen des Pointers der zum MTE Eintrag führt ist beendet, weiter zum lesen des MTEs
JMP READ_MTE


Jetzt lesen wir unseren MTE, den Pointer dahin haben wir vorher generiert und in X abgelegt
READ_MTE:
LDA $318800,x ---
---->
LaDe nach A von Offset $318800+X,
AND #$00FF ----------> Wir holen uns die Bits die wir brauchen
CMP #$00FF
----------> Vergleichen ob wir das Ende erreicht haben (Terminierer ist $FF hier)
BEQ MTE_READ_END ----> Wenn das Ende errecith wurde ($FF), dann sind wir fertig mit lesen und springen weiter
ORA $32 -----------
--> OR mit dem Wert an Offset $32 auf A
STA $34 -----------
--> Speichern von A an Offset $34
TXY ---------------
--> Transferiere X nach Y
INY ---------------
--> Erhöhe Y um 1
PLX ---------------
--> X aus dem Stack holen
TXA ---------------
--> Transferiere X nach A
CLC ---------------
--> CLear Carry
ADC $36 -----------
--> ADd with Carry, adde das was an Offset $36 steht zu A
INX
-----------------> Erhöhe X um 1
INX -----------------> Erhöhe X um 1
PHX -----------------> PusH X, Speichern von X im Stack
TAX ---------------
--> Transferiere A nach X
LDA $34 -----------
--> LaDe nach A von Adresse $34
STA $7F6000,x -----
--> Speichern unseres generierten Wertes im RAM
TYX ---------------
--> Transferiere Y nach X
JMP READ_MTE
--------> Da unser Vergleich am Anfang der Routine kein Ende errreicht hatte springen wir zurück und lesen das nächste Byte, bis es den Wert $FF hat

Wenn unser Terminier-Byte ($FF) erreicht wurde ist das Lesen des MTEs beendet unn wir holen uns unsere Offsets für die normale Routine die wir ganz am Anfang in den Stack geschoben haben wieder zurück, damit die Routine damit weiter arbeiten kann
MTE_READ_END:
PLX
-----------------> X aus dem Stack holen
PLY
-----------------> Y aus dem Stack holen
JMP READ_NEXT_LETTER-> Und hier geht's wieder zurück um den nächsten Buchstaben zu lesen

NEXT_LINE_FOUND:
LDA $36 —————————————> ; LaDe nach A was an Ram Offset $36 steht
CLC —————————————————> ; CLear Carry
ADC #$002E ——————————> ; AD to Carry, adde 002E zu A
STA $36 —————————————> ; Speicher A in Ram Offset $36
INY —————————————————> ; INcrease Y (Unsere derzeite Position in der Rom)
LDX #$0000 ——————————> ; LaDe $0000 in X
JMP READ_NEXT_LETTER

END_FOUND:
TXA —————————————————> ; Transferiere X nach A
CLC —————————————————> ; Clear Carry
ADC $36 —————————————> ; ADd to Carry , adde das was an Ram Offset $36 steht zu A
TAX —————————————————> ; Transferiere A nach X
LDA #$FFFF ——————————> ; LaDe $FFFF in A
STA $7F6000,x ———————> ; Speicher A in Ram Offset $7F6000+x
JML $03B653 —————————> ; Springt zu dem Punkt nach der Originalen Routine
Signature from »manakoAT« Geht nicht, gibt's nicht!

This post has been edited 48 times, last edit by "KillBill_158" (Nov 13th 2011, 7:33pm)


manakoAT

Techniker

  • "manakoAT" is male
  • "manakoAT" started this thread

Posts: 165

Thanks: 30

  • Send private message

2

Sunday, September 11th 2011, 7:49pm

000
Signature from »manakoAT« Geht nicht, gibt's nicht!

This post has been edited 33 times, last edit by "manakoAT" (Oct 13th 2011, 7:18pm)


KillBill_158

Supergenie

  • "KillBill_158" is male

Posts: 1,967

Thanks: 136

  • Send private message

3

Monday, September 12th 2011, 8:09pm

Na hey was machst du denn hier still und heimlich O_o klasse Arbeit Ronny und im Aufbau ist es auch noch was los hier das nenn ich mal Einsatz … ^^
Signature from »KillBill_158«



Wer sich entschieden hat, etwas zu tun, und an nichts anderes denkt, überwindet alle Hindernisse.

blackerking

Creme de la Creme

  • "blackerking" is male

Posts: 481

Thanks: 37

  • Send private message

4

Tuesday, September 13th 2011, 8:43pm

Bin für eine Fortführung dieses Tutorials. :)

Bent[pG]

Ich übe noch

Posts: 20

  • Send private message

5

Thursday, October 13th 2011, 8:04pm

geiles ding ... :) mach weiter so! ich liebe dich, mein hase! :) :love:

RedScorpion

Abteilungsleiter

  • "RedScorpion" is male

Posts: 2,862

Thanks: 489

  • Send private message

6

Tuesday, October 25th 2011, 3:46pm

Mach mal bitte weiter... ich hab bis jetzt alles gerafft, aber die Neue Routine solltest du bitte noch erklären!
Kurze Frage noch: Wird bei der getracten Routine nur 1 Zeichen gelesen oder eine ganze Zeit bis zum Endbyte? Oder passiert für jedes Zeichen der komplette Code hintereinander weg?

Danke dir...


Gruß

red

Rate this thread