summaryrefslogtreecommitdiff
path: root/core/rllpack.inc
diff options
context:
space:
mode:
Diffstat (limited to 'core/rllpack.inc')
-rw-r--r--core/rllpack.inc156
1 files changed, 156 insertions, 0 deletions
diff --git a/core/rllpack.inc b/core/rllpack.inc
new file mode 100644
index 00000000..a556e00a
--- /dev/null
+++ b/core/rllpack.inc
@@ -0,0 +1,156 @@
+; -*- fundamental -*- ---------------------------------------------------
+;
+; Copyright 2004-2008 H. Peter Anvin - All Rights Reserved
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+; Boston MA 02111-1307, USA; either version 2 of the License, or
+; (at your option) any later version; incorporated herein by reference.
+;
+; -----------------------------------------------------------------------
+
+;
+; rllpack.inc
+;
+; Very simple RLL compressor/decompressor, used to pack binary structures
+; together.
+;
+; Format of leading byte
+; 1-128 = x verbatim bytes follow
+; 129-223 = (x-126) times subsequent byte
+; 224-255 = (x-224)*256+(next byte) times the following byte
+; 0 = end of data
+;
+; These structures are stored *in reverse order* in high memory.
+; High memory pointers point to one byte beyond the end.
+;
+
+ section .text
+
+;
+; rllpack:
+; Pack CX bytes from SI into EDI.
+; Returns updated SI and EDI.
+;
+rllpack:
+ push word .pmentry
+ call simple_pm_call
+ ret
+
+.pmentry:
+ push cx
+ push ebx
+ push edx
+.startseq:
+ xor ax,ax ; Zero byte
+ xor ebx,ebx ; Run length zero
+ dec edi
+ mov edx,edi ; Pointer to header byte
+ mov [edi],al ; Create header byte
+ jcxz .done ; If done, this was the terminator
+.stdbyte:
+ lodsb
+ dec edi
+ mov [edi],al
+ dec cx
+ cmp ah,al
+ je .same
+.diff:
+ mov ah,al
+ xor bx,bx
+.plainbyte:
+ inc bx
+ inc byte [edx]
+ jcxz .startseq
+ jns .stdbyte
+ jmp .startseq
+.same:
+ cmp bl,2
+ jb .plainbyte
+ ; 3 bytes or more in a row, time to convert sequence
+ sub [edx],bl
+ jnz .normal
+ inc edi ; We killed a whole stretch,
+ ; drop start byte
+.normal:
+ inc bx
+ add edi,ebx ; Remove the stored run bytes
+.getrun:
+ jcxz .nomatch
+ lodsb
+ cmp al,ah
+ jne .nomatch
+ cmp bx,(256-224)*256-1 ; Maximum run size
+ jae .nomatch
+ inc bx
+ dec cx
+ jmp .getrun
+.nomatch:
+ cmp bx,224-126
+ jae .twobyte
+.onebyte:
+ add bl,126
+ dec edi
+ mov [edi],bl
+ jmp .storebyte
+.twobyte:
+ add bh,224
+ sub edi,2
+ mov [edi],bx
+.storebyte:
+ dec edi
+ mov [edi],ah
+ dec si ; Reload subsequent byte
+ jmp .startseq
+.done:
+ pop edx
+ pop ebx
+ pop cx
+ ret
+;
+; rllunpack:
+; Unpack bytes from ESI into DI
+; On return ESI, DI are updated and CX contains number of bytes output.
+;
+rllunpack:
+ push word .pmentry
+ call simple_pm_call
+ ret
+
+.pmentry:
+ push di
+ xor cx,cx
+.header:
+ dec esi
+ mov cl,[esi]
+ jcxz .done
+ cmp cl,129
+ jae .isrun
+ ; Not a run
+.copy:
+ dec esi
+ mov al,[esi]
+ stosb
+ loop .copy
+ jmp .header
+.isrun:
+ cmp cl,224
+ jae .longrun
+ sub cl,126
+.dorun:
+ dec esi
+ mov al,[esi]
+ rep stosb
+ jmp .header
+.longrun:
+ sub cl,224
+ mov ch,cl
+ dec esi
+ mov cl,[esi]
+ jmp .dorun
+.done:
+ pop cx
+ sub cx,di
+ neg cx
+ ret