/* ----------------------------------------------------------------------- *
*
* Copyright 2007-2009 H. Peter Anvin - All Rights Reserved
* Copyright 2009 Intel Corporation; author: H. Peter Anvin
*
* 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., 51 Franklin St, Fifth Floor,
* Boston MA 02110-1301, 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.
*/
#include <com32.h>
#include <stddef.h>
#include <string.h>
void rllpack(com32sys_t * regs)
{
uint8_t *i = (uint8_t *) (regs->esi.l);
uint8_t *o = (uint8_t *) (regs->edi.l);
size_t cnt = regs->ecx.l;
size_t run, vrun, tcnt;
uint8_t *hdr = NULL;
uint8_t c;
vrun = (size_t)-1;
while (cnt) {
c = *i;
run = 1;
tcnt = (cnt > 8191) ? 8191 : cnt;
while (run < tcnt && i[run] == c)
run++;
if (run < 3) {
if (vrun >= 128) {
hdr = --o;
vrun = 0;
}
*--o = c;
*hdr = ++vrun;
i++;
cnt--;
} else {
if (run < 224 - 126) {
*--o = run + 126;
} else {
o -= 2;
*(uint16_t *) o = run + (224 << 8);
}
*--o = c;
vrun = (size_t)-1;
i += run;
cnt -= run;
}
}
*--o = 0;
regs->esi.l = (size_t)i;
regs->edi.l = (size_t)o;
}
void rllunpack(com32sys_t * regs)
{
uint8_t *i = (uint8_t *) regs->esi.l;
uint8_t *o = (uint8_t *) regs->edi.l;
uint8_t c;
size_t n;
while ((c = *--i)) {
if (c <= 128) {
while (c--)
*o++ = *--i;
} else {
if (c < 224)
n = c - 126;
else
n = ((c - 224) << 8) + *--i;
c = *--i;
while (n--)
*o++ = c;
}
}
regs->esi.l = (size_t)i;
regs->ecx.l = (size_t)o - regs->edi.l;
regs->edi.l = (size_t)o;
}