Das ist schwer abzuschätzen, das sind etwas über 150.000 Pointer, ich hab davon die letzten Tage ca 2.000 gemacht, mehr oder weniger um den Editor zu testen.
MfG
Beiträge von manakoDE
-
-
Nur zur Info, es geht weiter mit neuem Editor. :o)
Der neue Editor hat eine komplette Preview was das In-Game testen unnötig macht,inklusive Tonnenweise anderer Funktionen die das Übersetzen wesentlich leichter gestalten.
Derzeit arbeiten leitwolf, Blatrix_FB und ich daran, und ich würde sagen wir haben in den letzten 2 Tagen ca 10% gemacht, wenn es wo weiter geht dauert es nicht mehr lange. -
Werte Community, ich würde gerne eine PD Rom erstellen um meine ASM Kentnisse zu erweitern... Leider fehlen mir die Ideen, ich dachte an sowas wie einen Roman oder etwas ähnliches!
Falls jemand Ideen oder Material hat dass ich verwenden könnte, dann mal los :o)MfG Ronny
-
Leitwolf ist ja leider verschwunden, der war am Beta testen, ich such mal alles raus und wir machen dann die neue Beta.
-
So, jetzt mal Butter auf die "FISCHE" ;o)
Status: Font und Grafiken dekomprimiert und wieder eingefügt, Texte gedumpt und fast fertig (schon länger), Probleme machen hier die ganzen Eigennamen... Neue, beschleunigte Routine um den Text zu lesen inklusive MTE-"Kompression" um möglicher weise die ROM nicht erweitern zu müssen...
Werde die nächsten Tage weitermachen und Updates posten, sofern ich Zeit finde, hab noch was "etwas mehr wichtigeres" nebenbei *wink*
Font:
Code:
lorom
org $3FFFFF
db $00org $03B608
JML $308000org $308000
;Read Letter and compare if it's a normal letter of a command >= 0x80
READ_NEXT_LETTER:
LDA $0000,y ; Y enthält unsere derzeite Position in der Rom (DBR+Y)
AND #$00FF ; Die letzten 8 Bit prüfen und in A laden
CMP #$0080 ; vergleichen ob der Wert in A $FF ist
BCS CHECK_FURTHER;Prepare Letter and Store it to a given RAM adress
ORA #$2000
STA $34
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 ; 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_LETTERCHECK_FURTHER:
CMP #$00FF
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)
JSR READ_MTE
JMP READ_NEXT_LETTER
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_LETTEREND_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 RoutineREAD_MTE:
INY
PHY
LDY #$0000
PHA
TXA
CLC
ADC $36
TAX
PLA
PHX
AND #$007F
ASL
TAX
LDA $308800,x
AND #$00FF
ORA #$2000
PLX
STA $7F6000,x
INY
INX
INX
PHX
TYX
LDA $308800,x
AND #$00FF
ORA #$2000
PLX
STA $7F6000,x
INX
INX
PLY
TXA
CLC
SEC
SBC $36
TAX
RTS
org $308800
db $69 : db $73 ; "is" -
Schonmal dran gedacht dass heute der 1. April ist? ;o)
-
So, mal bisschen was zum Status dieses Projekts... Ich habe mir endlich mal die Zeit genommen das Skript zu bearbeiten und in die ROM einzufügen, was mich dabei sehr verwundert hat ist, dass genau 102 Pointer beim Inserten fehlten, 2 davon waren "Flüchtigkeitsfehler" die beim Copy/Paste während des Übersetzens aufgetreten sind, die restlichen 100 Pointer wurden einfach ausgelassen und nicht in die Tabelle mit aufgenommen!
<#Pointer 0523> --> <#Pointer 0624>, alles dazwischen fehlt.
Ich möchte jetzt niemandem die Schuld in die Schuhe schieben, derjenige der das Skript hochgeladen hat möchte sich bitte bei mir melden via ICQ oder Skype, damit ich hier weitermachen kann.
mfG Ronny
-
Name: LZSS
Typ: LZ77-Erweiterung
Verlustfrei: Ja
Beispiel: Clock Tower II - The Struggle Within (PSX)
Link: WikipediaHier beschreibe ich an einem kleinen Beispiel wie LZSS funktioniert...
Auf die Herkunft und wie es entstanden ist gehe ich nicht weiter ein, dafür lest bitte den Wikipedia Artikel :o)Ein Screen von den Daten die wir dekodieren möchten:
Rauskommen soll dabei das hier:
Unser erstem 4 Bytes sind nur ein Header ("EXS") gefolgt von einer Nummer, die wahrscheinlich den Typ der Kompression angibt, bisher habe ich aber nur die ID 1 gefunden.
Die nächsten 4 Bytes geben die dekomprimierte Größe an, also 0x674D4 (423124 Bytes).
Danach startet unser LZSS Stream bei Offset 0x8.Ein LZSS-"Frame" besteht aus 3 Komponenten:
1.) das "Flag Byte"
2.) Unkomprimierte Einträge
3.) Komprimierte EinträgeDas erste Byte (Flag Byte) wird immer dazu genutzt um anzuzeigen wie die nachfolgenden Daten abgespeichert wurden, unser erstes Byte hier ist 0xBB, dieses müssen wir in seine Bits zerlegen, was 10111011 binär ergibt, in diesem Fall müssen wir die Bits noch umdrehen, da sie von hinten nach vorne gelesen werden, also: 11011101.
In unserem Beispiel wird die 1 für einen Unkomprimierten Eintrag verwendet, ein sogenanntes "Literal"-Byte (^Müllbyte^) und die 0 für Komprimierte Einträge.
Wie schon gesagt, das Literal ist nur 1 Byte, ein Komprimierter Eintrag besteht hier immer aus 2 Byte.Zerlegen wir mal unsere Bits:
1 - Literal - 1 Byte
1 - Literal - 1 Byte
0 - Komprimiert - 2 Byte
1 - Literal - 1 Byte
1 - Literal - 1 Byte
1 - Literal - 1 Byte
0 - Komprimiert - 2 Byte
1 - Literal - 1 ByteWir wissen nun, dass die ersten beiden Bytes nach dem Flag Byte unkomprimiert sind, also haben wir schonmal einen Output von: "05 00"
Jetzt kommt ein Komprimierter Eintrag, den wir wiederum zerlegen müssen, 0x0200
Komprimierte Einträge bestehen in unserem Fall aus 16 Bits, diese 16 Bits werden für Längen- und Positionsangaben verwendet, in unserem Beispiel 4 Bits für die Länge und 12 Bits für die Position, das macht 2^4 = 16 Bytes die mit diesen 4 Bits dekomprimiert werden können und 2^12 = 4096 Bytes für die Position wo sich diese Bytes befinden.
Wie diese Bits angeordnet sind, kann je nach Kompression variieren (Jenachdem was sich der Entwickler einfallen lässt), es gibt auch Kombinationen von 11 Bits für die Position mit 5 Bits für die Länge, oder 13 Bits für die Position und 3 Bits für die Länge, und es gibt sogar Spiele die verwenden nur 1 Byte für Komprimierte Einträge, wie Grandia 2 (6 Bits für die Position und 2 Bits für die Länge)
Wir drehen unseren Komprimierten EIntrag jetzt um, weil wir ja von rechts nach links lesen: 0x0002
Zerlegen ihn in Bits: 0000000000000010
Wir wissen das unsere Position 12 Bits hat und unser Länge 4 Bits:
0000 000000000010
LLLL PPPPPPPPPPPPWenn wir das jetzt wieder in normale Zahlen umwandeln, erhalten wir 0x02 als Positionsangabe und 0x00 als Längenangabe,
wir dekomprimieren also von Offset 0x02 0 Bytes....0 Bytes??? Da sgeht schlecht, wir zählen 2 dazu, so etwas wird meist gemacht, weil es Blödsinn ist zum Beispiel 1 Byte oder 2 Byte mit einem 16 Bit Eintrag zu kodieren (wobei letzteres doch hier gemacht wird),
desweiteren müssen wir den Offset -1 rechnen (Keine Ahnung warum das hier so ist)
Also: 0x01 Position, 0x02 Länge, Dekomprimiere 2 Bytes ab Offset 0x1Unser Derzeitiger Output ist "05 00",
Jetzt nehmen wir ein Byte von Offset 0x1 und packen es hinten ran: "05 00 00",
nehmen noch ein Byte von Offset 0x1 und packen es wieder hinten ran: "05 00 00 00".Die nächsten 3 Bytes sind Unkomprimiert, wir fügen sie einfach an den Output mit an und erhalten: "05 00 00 00 1D E6 20"
Jetzt kommt wieder ein Komprimierter Eintrag: 0x0710, einmal drehen = 0x1007
0001 000000000111
LLLL PPPPPPPPPPPP1 Länge, 0x7 Position
Länge = Länge + 2 = 3
Position = Position - 1 = 0x6Wir kopieren 3 Bytes ab Position 0x6
Einmal: "05 00 00 00 1D E6 20 20"
Zweimal: "05 00 00 00 1D E6 20 20 20"
Dreimal: "05 00 00 00 1D E6 20 20 20 20"Das nächste Byte ist wieder ein Literal und wird einfach an den Output angehängt, also: "05 00 00 00 1D E6 20 20 20 20 4D"
Somit haben wir 11 Bytes insgesamt dekomprimiert, damit ist die Dekodierung dieses Frames abgeschlossen und der nächste Frame wird dekodiert, dieser beginnt diesmal mit 0xFF
-
Alles gefixt, Script Editor ist auch fertig... jetzt müssen wir uns nur noch einig werden über Items/etc
-
-
Ok, das Projekt läuft ab heute offiziell weiter, am Wochenende gibts neue Infos... wird Zeit dass der Leckerbissen fertig wird!!!
mfG
-
Und ich hab das BoF Tool weitergegegen und auch noch vorher paar stunden Arbeit reingesteckt damit es mit den spanischen Sonderzeichen kompatibel ist, hab im Gegenzug Tools für Dragon View bekommen und ne Menge andere, sehr hilfreiche Infos: Also ich kann mich nicht beklagen...
-
Gibt's schon was neues hier? *nerv*
-
Eine Erweiterung auf 6 megabyte ist humbug, 3,5 höchstens 4 reichen völlig, allerdings müsste man das ganze ding dann neu machen :o)
-
Das Projekt liegt zurzeit vollständig auf Eis, wegen Zeitmangel, es läuft aber nicht weg
-
I decompressed everything already
-
Ja, das mit dem Font hab ich auch schonmal angesprochen, ich hätte auch gerne einen anderen :o)
-
Hier mal ein Statusupdate nachdem die R5 kläglich gescheitert ist: :o)
Das Skript muss nochmal angepasst werden, also auf Zeilenlänge gefixt werden, ansonsten sollte es das mit dem Skript gewesen sein... Jetzt warte ich nur drauf dass es fertig wird und ich es inserten kann, die Bugs die aufgetreten sind, wurden mittlerweile alle von mir behoben , wie Grafikfehler, falsche Texte an bestimmten Positionen, etc!
-
-
Status: Im Aufbau
Unser Testobjekt:
E.V.O. - Search for Eden (USA)
Ohne Header, CRC32: DD49911EBenötigte Tools:
"Geiger's Snes9x Debugger"
"Lunar Adress und Lunar Expand", gibt's hier
"xkas v0.6", gibt's hierWas 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=someoneBitte 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 $2000READ_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 �FF = $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_LETTERNEXT_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_LETTEREND_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 RoutineJetzt 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_MTEJetzt 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 hatWenn 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 lesenNEXT_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_LETTEREND_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