M pc/devusb.c => pc/devusb.c +18 -56
@@ 369,9 369,9 @@ dumptd(TD *t, int follow)
if(t->status & LowSpeed)
*s++ = 'L';
*s = 0;
- print("td %8.8lux: l=%8.8lux s=%8.8lux d=%8.8lux b=%8.8lux %8.8lux f=%8.8lux\n",
+ XPRINT("td %8.8lux: l=%8.8lux s=%8.8lux d=%8.8lux b=%8.8lux %8.8lux f=%8.8lux\n",
t, t->link, t->status, t->dev, t->buffer, t->bp?(ulong)t->bp->rp:0, t->flags);
- print("\ts=%s,ep=%ld,d=%ld,D=%ld\n", buf, (t->dev>>15)&0xF, (t->dev>>8)&0xFF, (t->dev>>19)&1);
+ XPRINT("\ts=%s,ep=%ld,d=%ld,D=%ld\n", buf, (t->dev>>15)&0xF, (t->dev>>8)&0xFF, (t->dev>>19)&1);
if(t->bp)
dumpdata(t->bp, n);
if(!follow || t->link & Terminate || t->link & IsQH)
@@ 401,44 401,6 @@ alloctde(Endpt *e, int pid, int n)
return t;
}
-static TD *
-alloctdring(int nbuf, Endpt *e, int pid, int maxn)
-{
- TD *t, *lt, *ft;
- int id, i;
- ulong status, dev;
-
- if(!e->iso)
- nbuf = (nbuf+1)&~1;
- id = (e->x<<7)|(e->dev->x&0x7F);
- dev = ((maxn-1)<<21) | ((id&0x7FF)<<8) | pid;
- status = 0;
- if(e->dev->ls)
- status |= LowSpeed;
- ft = lt = nil;
- for(i=0; i<nbuf; i++){
- t = alloctd(&ubus);
- t->ep = e;
- t->status = status;
- t->dev = dev;
- if(!e->iso)
- dev ^= IsDATA1;
- if(pid == TokIN){
- t->bp = allocb(maxn);
- t->buffer = PADDR(t->bp->wp);
- }
- if(ft != nil){
- lt->next = t;
- lt->link = PADDR(t);
- }else
- ft = t;
- lt = t;
- }
- if(lt != nil)
- lt->link = PADDR(ft); /* loop to form ring */
- return ft;
-}
-
static QH *
allocqh(Ctlr *ub)
{
@@ 475,13 437,13 @@ dumpqh(QH *q)
q0 = q;
for(i = 0; q != nil && i < 10; i++){
- pprint("qh %8.8lux: %8.8lux %8.8lux\n", q, q->head, q->entries);
+ XPRINT("qh %8.8lux: %8.8lux %8.8lux\n", q, q->head, q->entries);
if((q->entries & Terminate) == 0)
dumptd(TFOL(q->entries), 1);
if(q->head & Terminate)
break;
if((q->head & IsQH) == 0){
- pprint("head:");
+ XPRINT("head:");
dumptd(TFOL(q->head), 1);
break;
}
@@ 525,7 487,7 @@ cleantd(TD *t, int discard)
err = t->status & (AnyError&~NAKed);
/* TO DO: on t->status&AnyError, q->entries will not have advanced */
if (err)
- print("cleanTD: Error %8.8lux %8.8lux %8.8lux %8.8lux\n", t->link, t->status, t->dev, t->buffer);
+ XPRINT("cleanTD: Error %8.8lux %8.8lux %8.8lux %8.8lux\n", t->link, t->status, t->dev, t->buffer);
switch(t->dev&0xFF){
case TokIN:
if(discard || (t->flags & CancelTD) || t->ep == nil || t->ep->x!=0&&err){
@@ 624,7 586,7 @@ canceltds(Ctlr *ub, QH *q, Endpt *e)
if(t->ep == e)
t->flags |= CancelTD;
iunlock(ub);
- pprint("cancel:\n");
+ XPRINT("cancel:\n");
dumpqh(q);
}
}
@@ 805,7 767,7 @@ mkqhtree(ulong *frame, int framesize, int maxms)
o |= 1;
}
if(leaf0+o >= n){
- pprint("leaf0=%d o=%d i=%d n=%d\n", leaf0, o, i, n);
+ XPRINT("leaf0=%d o=%d i=%d n=%d\n", leaf0, o, i, n);
break;
}
frame[i] = PADDR(&tree[leaf0+o]) | IsQH;
@@ 828,14 790,14 @@ dumpframe(int f, int t)
if(t < 0)
t = 32;
for(i=f; i<t; i++){
- pprint("F%.2d %8.8lux %8.8lux\n", i, frame[i], QFOL(frame[i])->head);
+ XPRINT("F%.2d %8.8lux %8.8lux\n", i, frame[i], QFOL(frame[i])->head);
for(p=frame[i]; (p & IsQH) && (p &Terminate) == 0; p = q->head){
q = QFOL(p);
if(!(q >= tree && q < &tree[n])){
- pprint("Q: p=%8.8lux out of range\n", p);
+ XPRINT("Q: p=%8.8lux out of range\n", p);
break;
}
- pprint(" -> %8.8lux h=%8.8lux e=%8.8lux\n", p, q->head, q->entries);
+ XPRINT(" -> %8.8lux h=%8.8lux e=%8.8lux\n", p, q->head, q->entries);
}
}
}
@@ 1104,9 1066,9 @@ interrupt(Ureg*, void *a)
ub = a;
s = IN(Status);
if (s & 0x1a) {
- print("usbint: #%x f%d\n", s, IN(Frnum));
- print("cmd #%x sofmod #%x\n", IN(Cmd), inb(ub->io+SOFMod));
- print("sc0 #%x sc1 #%x\n", IN(Portsc0), IN(Portsc1));
+ XPRINT("usbint: #%x f%d\n", s, IN(Frnum));
+ XPRINT("cmd #%x sofmod #%x\n", IN(Cmd), inb(ub->io+SOFMod));
+ XPRINT("sc0 #%x sc1 #%x\n", IN(Portsc0), IN(Portsc1));
}
OUT(Status, s);
@@ 1570,7 1532,7 @@ readusb(Endpt *e, void *a, long n)
p = a;
do {
if(e->eof) {
- pprint("e->eof\n");
+ XPRINT("e->eof\n");
break;
}
if(e->err)
@@ 1583,7 1545,7 @@ readusb(Endpt *e, void *a, long n)
error(e->err);
b = qget(e->rq); /* TO DO */
if(b == nil) {
- pprint("b == nil\n");
+ XPRINT("b == nil\n");
break;
}
if(waserror()){
@@ 1846,7 1808,7 @@ usbwrite(Chan *c, void *a, long n, vlong)
/* ep n maxpkt mode poll nbuf */
i = strtoul(fields[1], nil, 0);
if(i < 0 || i >= nelem(d->ep)) {
- pprint("field 1: 0 <= %d < %d\n", i, nelem(d->ep));
+ XPRINT("field 1: 0 <= %d < %d\n", i, nelem(d->ep));
error(Ebadarg);
}
if(d->ep[i] != nil)
@@ 1869,7 1831,7 @@ usbwrite(Chan *c, void *a, long n, vlong)
if(i > 0 && i <= 1000)
e->pollms = i;
else {
- pprint("field 4: 0 <= %d <= 1000\n", i);
+ XPRINT("field 4: 0 <= %d <= 1000\n", i);
error(Ebadarg);
}
}
@@ 1878,7 1840,7 @@ usbwrite(Chan *c, void *a, long n, vlong)
e->nbuf = i;
poperror();
}else {
- pprint("command %s, fields %d\n", fields[0], nf);
+ XPRINT("command %s, fields %d\n", fields[0], nf);
error(Ebadarg);
}
return n;
M pc/io.h => pc/io.h +1 -0
@@ 5,6 5,7 @@
enum {
VectorNMI = 2, /* non-maskable interrupt */
VectorBPT = 3, /* breakpoint */
+ VectorUD = 6, /* invalid opcode exception */
VectorCNA = 7, /* coprocessor not available */
VectorCSO = 9, /* coprocessor segment overrun */
VectorPF = 14, /* page fault */
A pc/vgat2r4.c => pc/vgat2r4.c +329 -0
@@ 0,0 1,329 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+/*
+ * #9 Ticket to Ride IV.
+ */
+enum {
+ IndexLo = 4,
+ IndexHi = 5,
+ Data = 6,
+ IndexCtl = 7,
+};
+
+enum { /* index registers */
+ CursorCtl = 0x30,
+ CursorXLo = 0x31,
+ CursorXHi = 0x32,
+ CursorYLo = 0x33,
+ CursorYHi = 0x34,
+ CursorHotX = 0x35,
+ CursorHotY = 0x36,
+
+ CursorR1 = 0x40,
+ CursorG1 = 0x41,
+ CursorB1 = 0x42,
+ CursorR2 = 0x43,
+ CursorG2 = 0x44,
+ CursorB2 = 0x45,
+ CursorR3 = 0x46,
+ CursorG3 = 0x47,
+ CursorB3 = 0x48,
+
+ CursorArray = 0x100,
+};
+
+static ulong
+t2r4linear(VGAscr* scr, int* size, int* align)
+{
+ ulong aperture, oaperture;
+ int oapsize, wasupamem;
+ Pcidev *p;
+
+ oaperture = scr->aperture;
+ oapsize = scr->apsize;
+ wasupamem = scr->isupamem;
+
+ aperture = 0;
+ if(p = pcimatch(nil, 0x105D, 0)){
+ switch(p->did){
+ case 0x5348:
+ aperture = p->mem[0].bar & ~0x0F;
+ *size = p->mem[0].size;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if(wasupamem){
+ if(oaperture == aperture)
+ return oaperture;
+ upafree(oaperture, oapsize);
+ }
+ scr->isupamem = 0;
+
+ aperture = upamalloc(aperture, *size, *align);
+ if(aperture == 0){
+ if(wasupamem && upamalloc(oaperture, oapsize, 0)){
+ aperture = oaperture;
+ scr->isupamem = 1;
+ }
+ else
+ scr->isupamem = 0;
+ }
+ else
+ scr->isupamem = 1;
+
+ return aperture;
+}
+
+static void
+t2r4enable(VGAscr* scr)
+{
+ Pcidev *p;
+ Physseg seg;
+ int size, align;
+ ulong aperture;
+
+ /*
+ * Only once, can't be disabled for now.
+ * scr->io holds the virtual address of
+ * the MMIO registers.
+ */
+ if(scr->io)
+ return;
+ if(p = pcimatch(nil, 0x105D, 0)){
+ switch(p->did){
+ case 0x5348:
+ break;
+ default:
+ return;
+ }
+ }
+ else
+ return;
+ scr->io = upamalloc(p->mem[4].bar & ~0x0F, p->mem[4].size, 0);
+ if(scr->io == 0)
+ return;
+
+ memset(&seg, 0, sizeof(seg));
+ seg.attr = SG_PHYSICAL;
+ seg.name = smalloc(NAMELEN);
+ snprint(seg.name, NAMELEN, "t2r4mmio");
+ seg.pa = scr->io;
+ seg.size = p->mem[4].size;
+ addphysseg(&seg);
+
+ scr->io = (ulong)KADDR(scr->io);
+
+ size = p->mem[0].size;
+ align = 0;
+ aperture = t2r4linear(scr, &size, &align);
+ if(aperture){
+ scr->aperture = aperture;
+ scr->apsize = size;
+ memset(&seg, 0, sizeof(seg));
+ seg.attr = SG_PHYSICAL;
+ seg.name = smalloc(NAMELEN);
+ snprint(seg.name, NAMELEN, "t2r4screen");
+ seg.pa = aperture;
+ seg.size = size;
+ addphysseg(&seg);
+ }
+}
+
+static void
+t2r4xo(VGAscr* scr, int index, uchar data)
+{
+ ulong *mmio;
+
+ mmio = (ulong*)scr->io;
+ mmio[IndexLo] = index & 0xFF;
+ mmio[IndexHi] = (index>>8) & 0xFF;
+
+ mmio[Data] = data;
+}
+
+static void
+t2r4curdisable(VGAscr* scr)
+{
+ if(scr->io == 0)
+ return;
+ t2r4xo(scr, CursorCtl, 0x00);
+}
+
+static void
+t2r4curload(VGAscr* scr, Cursor* curs)
+{
+ int x, y;
+ ulong *mmio;
+ uchar p, p0, p1;
+
+ if(scr->io == 0)
+ return;
+ mmio = (ulong*)scr->io;
+
+ /*
+ * Make sure cursor is off by initialising the cursor
+ * control to defaults.
+ */
+ t2r4xo(scr, CursorCtl, 0x00);
+
+ /*
+ * Set auto-increment mode for index-register addressing
+ * and initialise the cursor array index.
+ */
+ mmio[IndexCtl] = 0x01;
+ mmio[IndexLo] = CursorArray & 0xFF;
+ mmio[IndexHi] = (CursorArray>>8) & 0xFF;
+
+ /*
+ * Initialise the 32x32 cursor RAM array. There are 2 planes,
+ * p0 and p1. Data is written 4 pixels per byte, with p1 the
+ * MS bit of each pixel.
+ * The cursor is set in X-Windows mode which gives the following
+ * truth table:
+ * p1 p0 colour
+ * 0 0 underlying pixel colour
+ * 0 1 underlying pixel colour
+ * 1 0 cursor colour 1
+ * 1 1 cursor colour 2
+ * Put the cursor into the top-left of the 32x32 array.
+ */
+ for(y = 0; y < 32; y++){
+ for(x = 0; x < 32/8; x++){
+ if(x < 16/8 && y < 16){
+ p0 = curs->clr[x+y*2];
+ p1 = curs->set[x+y*2];
+
+ p = 0x00;
+ if(p1 & 0x80)
+ p |= 0xC0;
+ else if(p0 & 0x80)
+ p |= 0x80;
+ if(p1 & 0x40)
+ p |= 0x30;
+ else if(p0 & 0x40)
+ p |= 0x20;
+ if(p1 & 0x20)
+ p |= 0x0C;
+ else if(p0 & 0x20)
+ p |= 0x08;
+ if(p1 & 0x10)
+ p |= 0x03;
+ else if(p0 & 0x10)
+ p |= 0x02;
+ mmio[Data] = p;
+
+ p = 0x00;
+ if(p1 & 0x08)
+ p |= 0xC0;
+ else if(p0 & 0x08)
+ p |= 0x80;
+ if(p1 & 0x04)
+ p |= 0x30;
+ else if(p0 & 0x04)
+ p |= 0x20;
+ if(p1 & 0x02)
+ p |= 0x0C;
+ else if(p0 & 0x02)
+ p |= 0x08;
+ if(p1 & 0x01)
+ p |= 0x03;
+ else if(p0 & 0x01)
+ p |= 0x02;
+ mmio[Data] = p;
+ }
+ else{
+ mmio[Data] = 0x00;
+ mmio[Data] = 0x00;
+ }
+ }
+ }
+
+ /*
+ * Initialise the cursor hotpoint,
+ * enable the cursor and restore state.
+ */
+ t2r4xo(scr, CursorHotX, -curs->offset.x);
+ t2r4xo(scr, CursorHotY, -curs->offset.y);
+
+ t2r4xo(scr, CursorCtl, 0x23);
+}
+
+static int
+t2r4curmove(VGAscr* scr, Point p)
+{
+ if(scr->io == 0)
+ return 1;
+
+ t2r4xo(scr, CursorXLo, p.x & 0xFF);
+ t2r4xo(scr, CursorXHi, (p.x>>8) & 0x0F);
+ t2r4xo(scr, CursorYLo, p.y & 0xFF);
+ t2r4xo(scr, CursorYHi, (p.y>>8) & 0x0F);
+
+ return 0;
+}
+
+static void
+t2r4curenable(VGAscr* scr)
+{
+ t2r4enable(scr);
+ if(scr->io == 0)
+ return;
+
+ /*
+ * Make sure cursor is off by initialising the cursor
+ * control to defaults.
+ */
+ t2r4xo(scr, CursorCtl, 0x00);
+
+ /*
+ * Cursor colour 1 (white),
+ * cursor colour 2 (black).
+ */
+ t2r4xo(scr, CursorR1, Pwhite);
+ t2r4xo(scr, CursorG1, Pwhite);
+ t2r4xo(scr, CursorB1, Pwhite);
+
+ t2r4xo(scr, CursorR2, Pblack);
+ t2r4xo(scr, CursorG2, Pblack);
+ t2r4xo(scr, CursorB2, Pblack);
+
+ /*
+ * Load, locate and enable the cursor, 32x32, mode 2.
+ */
+ t2r4curload(scr, &arrow);
+ t2r4curmove(scr, ZP);
+ t2r4xo(scr, CursorCtl, 0x23);
+}
+
+VGAdev vgat2r4dev = {
+ "t2r4",
+
+ t2r4enable,
+ nil,
+ nil,
+ t2r4linear,
+};
+
+VGAcur vgat2r4cur = {
+ "t2r4hwgc",
+
+ t2r4curenable,
+ t2r4curdisable,
+ t2r4curload,
+ t2r4curmove,
+};
M port/segment.c => port/segment.c +2 -0
@@ 612,6 612,8 @@ segattach(Proc *p, ulong attr, char *name, ulong va, ulong len)
error(Enovmem);
len = PGROUND(len);
+ if(len == 0)
+ error(Ebadarg);
/*
* Find a hole in the address space.
M port/thwack.c => port/thwack.c +21 -60
@@ 1,5 1,5 @@
#include "u.h"
-#include "../port/lib.h"
+#include "lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
@@ 13,16 13,17 @@ struct Huff
ulong encode; /* the code */
};
-static Huff lentab[MaxLen] =
+static Huff lentab[MaxFastLen] =
{
{1, 0x0}, /* 0 */
{2, 0x2}, /* 10 */
{4, 0xc}, /* 1100 */
{4, 0xd}, /* 1101 */
- {5, 0x1e}, /* 11110 */
- {6, 0x3e}, /* 111110 */
- {6, 0x3f}, /* 111111 */
- {4, 0xe}, /* 1110 */
+ {5, 0x1c}, /* 11100 */
+ {6, 0x3a}, /* 111010 */
+ {6, 0x3b}, /* 111011 */
+ {7, 0x78}, /* 1111000 */
+ {7, 0x79}, /* 1111001 */
};
static void bitput(Thwack *tw, int c, int n);
@@ 139,9 140,9 @@ thwack(Thwack *tw, uchar *dst, uchar *src, int n, ulong seq)
{
ThwBlock *eblocks, *b, blocks[CompBlocks];
uchar *s, *ss, *sss, *esrc, *half;
- ulong cont, cseq, bseq, cmask;
+ ulong cont, cseq, bseq, cmask, code;
int now, toff;
- int h, m, slot, bits, totmatched;
+ int h, m, slot, bits, use, totmatched;
if(n > ThwMaxBlock || n < MinMatch || waserror())
return -1;
@@ 227,11 228,20 @@ thwack(Thwack *tw, uchar *dst, uchar *src, int n, ulong seq)
bitput(tw, toff & ((1 << bits) - 1), bits);
m -= MinMatch;
- if(m < MaxLen-1){
+ if(m < MaxFastLen){
bitput(tw, lentab[m].encode, lentab[m].bits);
}else{
- bitput(tw, lentab[MaxLen-1].encode, lentab[MaxLen-1].bits);
- iomegaput(tw, m - (MaxLen - 2));
+ code = BigLenCode;
+ bits = BigLenBits;
+ use = BigLenBase;
+ m -= MaxFastLen;
+ while(m >= use){
+ m -= use;
+ code = (code + use) << 1;
+ use <<= bits & 1;
+ bits++;
+ }
+ bitput(tw, (code + m), bits);
}
}
blocks->maxoff += ss - s;
@@ 274,52 284,3 @@ bitput(Thwack *tw, int c, int n)
*tw->dst++ = tw->bits >> (tw->nbits - 8);
}
}
-
-/*
- * elias's omega code, modified
- * for at least 3 bit transmission
- */
-static Huff omegatab[16] =
-{
- {0, 0}, /* 1 */
- {0, 0},
- {0, 0},
- {0, 0},
- {3, 0x4}, /* 5 */
- {3, 0x5},
- {3, 0x6},
- {3, 0x7},
- {7, 0x48},
- {7, 0x49}, /* 10 */
- {7, 0x4a},
- {7, 0x4b},
- {7, 0x4c},
- {7, 0x4d},
- {7, 0x4e}, /* 15 */
- {7, 0x4f},
-};
-
-static int
-iomegaput(Thwack *tw, ulong v)
-{
- int b, bb;
-
- v--;
- if(v < 4){
- bitput(tw, v, 3);
- return 3;
- }
- if(v < 16){
- b = omegatab[v].bits + 1;
- bitput(tw, omegatab[v].encode << 1, b);
- return b;
- }
-
- for(bb = 5; v >= (1 << bb); bb++)
- ;
- if(bb >= 16)
- error("thwack omegaput");
- b = bb + omegatab[bb].bits + 1;
- bitput(tw, (omegatab[bb].encode << (bb + 1)) | (v << 1), b);
- return b;
-}
M port/thwack.h => port/thwack.h +7 -7
@@ 12,11 12,16 @@ enum
HashSize = 1<<HashLog,
HashMask = HashSize - 1,
- MaxLen = 8,
+ MaxFastLen = 9,
+ BigLenCode = 0xf4, /* minimum code for large lenth encoding */
+ BigLenBase = 4, /* starting items to encode for big lens */
+ BigLenBits = 8,
MaxOff = 8,
OffBase = 6,
MinDecode = 9, /* minimum bits to decode a match or lit */
+ MaxOffDecode = 4 + MaxOff + OffBase - 1,
+ MaxLenDecode = 16,
EWinBlocks = 32, /* blocks held in encoder window */
DWinBlocks = 32, /* blocks held in decoder window */
@@ 44,7 49,7 @@ struct Thwack
uchar *dst; /* output buffer */
uchar *dmax;
- ulong slot; /* next block to use */
+ int slot; /* next block to use */
ThwBlock blocks[EWinBlocks];
ushort hash[EWinBlocks][HashSize];
uchar data[EWinBlocks][ThwMaxBlock];
@@ 59,11 64,6 @@ struct UnthwBlock
struct Unthwack
{
- ulong nbits; /* input bit buffer */
- ulong bits;
- uchar *src; /* input buffer */
- uchar *smax;
-
int slot; /* next block to use */
UnthwBlock blocks[DWinBlocks];
uchar data[DWinBlocks][ThwMaxBlock];
M port/unthwack.c => port/unthwack.c +62 -100
@@ 1,5 1,5 @@
#include "u.h"
-#include "../port/lib.h"
+#include "lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
@@ 10,28 10,26 @@ typedef struct HuffDec HuffDec;
struct HuffDec
{
- ulong maxcode[MaxLen];
- ulong last[MaxLen];
- ulong decode[MaxLen];
+ ulong maxcode[MaxFastLen];
+ ulong last[MaxFastLen];
+ ulong decode[MaxFastLen];
};
static HuffDec lentab =
{
-/* 0 1 2 3 4 5 6 */
- {0, 0, 0x2, 0, 0xe, 0x1e, 0x3f},
- {-1, 0+0, 0x2+1, -1, 0xe+2, 0x1e+5, 0x3f+6},
+/* 0 1 2 3 4 5 6 7 */
+ {0, 0, 0x2, 0, 0xd, 0x1c, 0x3b, 0x79},
+ {-1, 0+0, 0x2+1, -1, 0xd+2, 0x1c+4, 0x3b+5, 0x79+7},
{
0,
1,
- 7, 3, 2,
+ 3, 2,
4,
- 6, 5
+ 6, 5,
+ 8, 7,
},
};
-static ulong bitget(Unthwack *ut, int nb);
-static ulong iomegaget(Unthwack *ut);
-
void
unthwackinit(Unthwack *ut)
{
@@ 42,23 40,17 @@ unthwackinit(Unthwack *ut)
ut->blocks[i].data = ut->data[i];
}
-/*
- * to speed up, inline bitget
- */
int
unthwack(Unthwack *ut, uchar *dst, int ndst, uchar *src, int nsrc, ulong seq)
{
UnthwBlock blocks[CompBlocks], *b, *eblocks;
- uchar *s, *es, *d, *dmax;
- ulong cmask, cseq, bseq, utbits, utnbits;
- int off, len, bits, slot, tslot;
+ uchar *s, *es, *d, *dmax, *smax;
+ ulong cmask, cseq, bseq, utbits;
+ int off, len, bits, slot, tslot, use, code, utnbits, overbits;
- if(nsrc < 4 || nsrc > ThwMaxBlock || waserror())
+ if(nsrc < 4 || nsrc > ThwMaxBlock)
return -1;
- ut->src = src + 2;
- ut->smax = src + nsrc;
-
/*
* find the correct slot for this block,
* the oldest block around. the encoder
@@ 112,23 104,30 @@ unthwack(Unthwack *ut, uchar *dst, int ndst, uchar *src, int nsrc, ulong seq)
}
eblocks = b;
if(cseq != seq){
- print("blocks not in decompression window: cseq=%d seq=%d cmask=%ux nb=%d\n", cseq, seq, cmask, eblocks - blocks);
- error("unthwack bad window");
+ print("blocks not in decompression window: cseq=%ld seq=%ld cmask=%lux nb=%ld\n", cseq, seq, cmask, eblocks - blocks);
+ return -1;
}
+ smax = src + nsrc;
+ src += 2;
utnbits = 0;
utbits = 0;
- while(ut->src < ut->smax || ut->nbits >= MinDecode){
- while(utnbits < 9){
- if(ut->src >= ut->smax)
- error("unthwack eof");
+ overbits = 0;
+ while(src < smax || utnbits - overbits >= MinDecode){
+ while(utnbits < MaxOffDecode + BigLenBits){
utbits <<= 8;
- utbits |= *ut->src++;
+ if(src < smax)
+ utbits |= *src++;
+ else
+ overbits += 8;
utnbits += 8;
}
utnbits -= 9;
off = (utbits >> utnbits) & ((1 << 9) - 1);
+ /*
+ * literal
+ */
bits = off >> 5;
if(bits >= MaxOff){
*d++ = off;
@@ 143,41 142,46 @@ unthwack(Unthwack *ut, uchar *dst, int ndst, uchar *src, int nsrc, ulong seq)
bits += OffBase - 5;
off <<= bits;
- while(utnbits < bits){
- if(ut->src >= ut->smax)
- error("unthwack eof");
- utbits <<= 8;
- utbits |= *ut->src++;
- utnbits += 8;
- }
utnbits -= bits;
off |= (utbits >> utnbits) & ((1 << bits) - 1);
off++;
- len = 0;
bits = 0;
+ utbits &= (1 << utnbits) - 1;
do{
- len <<= 1;
- if(utnbits < 1){
- if(ut->src >= ut->smax)
- error("unthwack eof");
+ bits++;
+ len = utbits >> (utnbits - bits);
+ }while(bits < BigLenBits && len > lentab.maxcode[bits]);
+ utnbits -= bits;
+
+ if(bits < BigLenBits)
+ len = lentab.decode[lentab.last[bits] - len];
+ else{
+ while(utnbits < MaxLenDecode){
utbits <<= 8;
- utbits |= *ut->src++;
+ if(src < smax)
+ utbits |= *src++;
+ else
+ overbits += 8;
utnbits += 8;
}
- utnbits--;
- len |= (utbits >> utnbits) & 1;
- bits++;
- }while(len > lentab.maxcode[bits]);
- len = lentab.decode[lentab.last[bits] - len];
-
- if(len == MaxLen - 1){
- ut->nbits = utnbits;
- ut->bits = utbits;
- len += iomegaget(ut) - 1;
- utnbits = ut->nbits;
- utbits = ut->bits;
+
+ code = len - BigLenCode;
+ len = MaxFastLen;
+ bits = 8;
+ use = BigLenBase;
+ while(code >= use){
+ len += use;
+ code -= use;
+ code <<= 1;
+ utnbits--;
+ code |= (utbits >> utnbits) & 1;
+ use <<= bits & 1;
+ bits++;
+ }
+ len += code;
}
+
len += MinMatch;
b = blocks;
@@ 185,17 189,19 @@ unthwack(Unthwack *ut, uchar *dst, int ndst, uchar *src, int nsrc, ulong seq)
off -= b->maxoff;
b++;
if(b >= eblocks)
- error("unthwack offset");
+ return -1;
}
if(d + len > dmax
|| b != blocks && len > off)
- error("unthwack len");
+ return -1;
s = b->data + b->maxoff - off;
es = s + len;
while(s < es)
*d++ = *s++;
blocks->maxoff += len;
}
+ if(utnbits < overbits)
+ return -1;
len = d - blocks->data;
memmove(dst, blocks->data, len);
@@ 205,49 211,5 @@ unthwack(Unthwack *ut, uchar *dst, int ndst, uchar *src, int nsrc, ulong seq)
if(ut->slot >= DWinBlocks)
ut->slot = 0;
- poperror();
return len;
}
-
-/*
- * elias's omega code, modified
- * for at least 3 bit transmission
- */
-static ulong
-iomegaget(Unthwack *ut)
-{
- ulong v;
- int b;
-
- v = bitget(ut, 3);
- if((v & 0x4) == 0)
- return v + 1;
- for(;;){
- b = bitget(ut, 1);
- if(b == 0)
- return v + 1;
- if(v > 16)
- break;
- v--;
- v = (b << v) | bitget(ut, v);
- }
- error("unthwack iomegaget");
- return ~0;
-}
-
-static ulong
-bitget(Unthwack *ut, int nb)
-{
- int c;
-
- while(ut->nbits < nb){
- if(ut->src >= ut->smax)
- error("unthwack eof");
- c = *ut->src++;
- ut->bits <<= 8;
- ut->bits |= c;
- ut->nbits += 8;
- }
- ut->nbits -= nb;
- return (ut->bits >> ut->nbits) & ((1 << nb) - 1);
-}