Grafikkomprimierung PKMN GSK
aus RHWiki, der freien Romhacking-Enzyklopädie
Die Komprimierung in Pokémon GSK ist eine Kombination aus RLE- und lz77-Komprimierung. Sie ist bytebasiert, d.h. es werden immer nur ganze Bytes betrachtet.
| Inhaltsverzeichnis |
Überblick
Die Komprimierung ist linear aufgebaut:
[Kontrollbyte][Daten]... (Es folgt immer ein Datensegment auf ein Kontrollbyte)
Das Ende der Daten ist durch einen speziellen Kontrollcode festgelegt. Es gibt also zu Beginn keine Größenangabe, sondern die Daten beginnen direkt mit dem ersten Kontrollbyte.
Es gibt 8 Kontrollcodes, die bestimmen auf welche Weise nachfolgende Daten interpretiert werden sollen.
Detailierte Beschreibung
Jedes Kontrollbyte enthält in den Bits 5-7 einen Kontrollcode. Man erhält ihn über eine bitweise AND-Operation von 0xE0 (Hexadezimal) mit dem Kontrollbyte.
Auf diese Weise gibt es die Kontrollcodes 0x00, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0 und 0xE0 (Hexadezimal)
In den restlichen 5 Bits 0-4 ist für die Codes 0x00-0xC0 die Länge der jeweils dekomprimierten Daten definiert, für 0xE0 haben die 5 Bits eine gesonderte Bedeutung (siehe weiter unten).
Die dekomprimierten Daten werden in einen Speicher, auch Puffer genannt, geschrieben.
Kontrollcodes
Für jeden dieser Codes erhält man die Länge der Daten N über die bitweise AND-Operation des Kontrollcodes mit 0x1F (Hexadezimal).
Code 0x00
Bedeutet, dass die nachfolgenden Daten unkomprimiert sind. Kopiere dann einfach N+1 Anzahl nachfolgende Bytes in den Ausgabepuffer.
Bitweise Struktur: [000][NNNNN] (N + 1)*[DDDDDDDD] Ausgabe: (N + 1)*[DDDDDDDD]
RLE-Codes
Die Codes 0x20 bis 0x60 wiederholen bestimmte Bytes mehrfach.
Code 0x20
RLE: Kopiere N+1 mal das selbe nachfolgende Byte in den Ausgabepuffer.
Bitweise Struktur: [001][NNNNN][DDDDDDDD] Ausgabe: (N + 1)*[DDDDDDDD]
Code 0x40
RLE: Kopiere abwechselnd die nächsten beiden Bytes in den Ausgabepuffer, bis N+1 Bytes geschrieben sind.
Bitweise Struktur: [010][NNNNN] [DDDDDDDD][EEEEEEEE] Ausgabe: (N / 2)*[DDDDDDDD][EEEEEEEE] + (N & 1)*[DDDDDDDD] Hinweis: Bei (N / 2) wird das Ergebnis abgerundet. (N & 1) ist die bitweise AND-Operation.
Code 0x60
RLE: Schreibe N+1 mal 0x00 in den Ausgabepuffer. Dieser Code benötigt keine weiteren Bytes
Bitweise Struktur: [011][NNNNN] Ausgabe: (N + 1)*[00000000]
lz77-Codes
Die Nachfolgenden Codes 0x80 bis 0xC0 recyceln Daten, die bereits dekomprimiert wurden.
Sie verwenden alle ein oder zwei weitere Bytes, um festzulegen von wo die Daten geholt werden sollen:
Nimm ein weiteres Byte A und betrachte dessen 7-tes Bit.
Ist das Bit 0, so folgt ein weiteres Byte. Die Bits 6-0 von A ergeben zusammen mit dem nächsten Byte das absolute Offset des Kopierbeginns im Ausgabepuffer.
Ist das Bit 1, so geben die Bits 6-0 von A das relative Offset rückwärts von Ende des Ausgabepuffers an. Dabei ist das zuletzt geschriebene Byte 0, das davor 1 usw.
Vom berechneten Offset werden N+1 Bytes ans Ende des Ausgabepuffers kopiert.
Code 0x80
lz77: Kopiere die Bytes direkt ohne Veränderung.
Bitweise Struktur: [100][NNNNN][0][SSSSSSS][SSSSSSSS] Ausgabe: (N + 1) Bytes von Offset SSS SSSS SSSS SSSS (Bit 6-0; 7-0) des Ausgabepuffers
Oder:
[100][NNNNN][1][RRRRRRR] Ausgabe: (N + 1) Bytes von (Aktuelles Offset - 1 - RRR RRRR) des Ausgabepuffers
Code 0xA0
lz77: Vertausche beim Kopieren von jedem Byte die Bitreihenfolge (Bit 7-0 -> Bit 0-7).
Bitweise Struktur: [101][NNNNN][0][SSSSSSS][SSSSSSSS] oder [101][NNNNN][1][RRRRRRR]
Sonst wie 0x80.
Code 0xC0
lz77: Kopiere die Bytes nicht vorwärts, sondern rückwärts.
Bitweise Struktur: [110][NNNNN][0][SSSSSSS][SSSSSSSS] oder [110][NNNNN][1][RRRRRRR]
Sonst wie 0x80.
Code 0xE0
Dieser Code ist kein eigenständiger Befehl, sondern mehr eine Erweiterung zu allen anderen. Er bewirkt, dass einer der anderen Befehle mit größerem N (Anzahl der Bytes) aufgerufen werden kann.
Die Bits 0-1 des Kontrollbytes ergeben zusammen mit dem nachfolgenden Byte das neue N. Es bewirkt im Prinzip für jeden Code eine größere Spanne/Reichweite von bis zu 0x0400 Bytes pro Kontrollcode.
Bits 2-4 ergeben den neuen Kontrollcode.
Bitweise Struktur: [111][CCC][NN][NNNNNNNN] Bewirkt: CCC ist neuer Kontrollcode und NN NNNN NNNN neues N. Fahre mit dem entsprechenden Kontrollcode fort.
Beispiel: E4FE [111][001][00][11111110] Bedeutet: Kontrollcode 0x20 mit N = 0x0FE Rechnung: 0xE4 And 0x1C *0x08 = 0x20
Code 0xFF
Der Code 0xFF bedeutet das Ende der Daten. Er ist ein Spezialfall des Codes 0xE0
Beispiele
1. Beipiel: 0312345678 wird zu: 12345678
2. Beispiel: 01234567 wird zu: 23450000000000000000
3. Beispiel: 3AAE6144E2E38C05 wird zu: AEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAE0000E2E3E2E3E200E2E3E2E3E200E2E3E2E3E200 | 27 mal 0xAE |2*00| 5*E2E3 || 13 Bytes von Pos-5 |
Format der Daten
Die dekomprimierten Daten liegen (Spezialfälle ausgeschlossen) im Standard-Gameboy-Grafikformat vor. Sie können mit Tile-Viewern betrachtet und geändert werden.
Tools
Zu dieser Komprimierung gibt es folgende Tools, die einem die Arbeit ungemein erleichtern:
- Advanced Gfx Inserter - Windows, Sehr hohe Komprimierungsrate, viele Funktionen, leider nicht überall lauffähig
- INS.EXE - DOS, von Meowth
- Lunar Compress - Windows

