
ZLIB ohne Level 9
« | 15 Oct 2023 | »Viele Probleme meiner Arbeit am GATE Projekt liegen bei den Compilern. Man würde glauben, wenn dieses gelöst sind, also alles kompiliert, wäre man fertig.
Leider nicht ganz, denn plötzlich schlägt z.B.: die Initialisierung der ZLIB zur Laufzeit fehl.
Die ZLIB nutzt beim Komprimieren einige Parameter wie etwas Compression-Level, Memory-Level und Window-Bits. Hierfür existieren Konstanten wie
- compression-level:
Z_BEST_COMPRESSION
(==9
) - memory-level:
MAX_MEM_LEVEL
(==9
) - window-bits:
MAX_WBITS
(==15
)
Da ich die besten Ergebnisse haben möchte, nutzte ich diese Werte als Standard in meine Codes, nur das Compression-Level war von außen einstellbar.
Unter DOS kompiliert dieser Code zwar, kann jedoch dann nicht ausgeführt
werden, es kommt zum Abbruch der Initialisierung in deflateInit2_()
.
Mit jeder Menge printf()
Debugging kam ich dann zu den Zeilen, die die
Parameter umsetzen und hier findet die Allokation eines Puffers statt,
die vereinfacht so aussieht:
1Byte* window = malloc((1 << window_size) * 2 * sizeof(Byte));
Bei 2^15 * 2
landen wir bei 2^16
bytes, also 65536. Theoretisch würde das
ein vollständiges DOS Segment sein, doch mit malloc können wir kein ganzes
Segment in einem kapern.
Etwas ähnliches passiert dann auch noch beim Memory-Level, denn da wird zum
Level 7
addiert, womit man auch wieder auf 16 Bits kommt.
Lösung: Kleinere Parameter
Meine Lösung war dann denkbar einfach (und wurde zusätzlich auch gleich auf Windows CE angewendet):
Mit den gepatchten Parameter läuft die ZLib brav weiter und generiert mit
deflate
komprimierte Ergebnisse, allerdings sind die jetzt potentiell
etwas schlechter, weil die Wörterbücher kleiner sind. Aber damit kann
man auf diesen Plattformen leben.
Fazit
Ab sofort kann das arch
Tool .gz
und .zip
Archive erzeugen und auch
wieder unter DOS auspacken.
Damit bin ich schon zufrieden.
Ich müsste jetzt noch Tests mit Archiven machen, die unter Windows oder Linux
erzeugt wurden und größere Window-Bits hatten und ob die beim Entpacken
Probleme machen. Allerdings sehe ich im inflate()
Code keine Allokationen,
die davon abhängen, zumindest nicht bei der Initialisierung.
DOS ist inzwischen eine wichtige Plattform für mich geworden, um zu verifizieren, ob Code wirklich plattformunabhängig läuft. Die Window-Bits sind ein schönes Beispiel für Einschränkungen, die man einfach nur wissen muss, um sie mit wenig Code überwinden zu können.