mirror of
https://github.com/2003scape/deep-c-rsc.git
synced 2024-03-22 05:49:51 -04:00
514 lines
18 KiB
Java
514 lines
18 KiB
Java
public class BZLib {
|
|
|
|
public static int decompress(byte out[], int outSize, byte in[], int inSize, int offset) {
|
|
BZState block = new BZState();
|
|
block.input = in;
|
|
block.nextIn = offset;
|
|
block.output = out;
|
|
block.availOut = 0;
|
|
block.availIn = inSize;
|
|
block.decompressedSize = outSize;
|
|
block.bsLive = 0;
|
|
block.bsBuff = 0;
|
|
block.totalInLo32 = 0;
|
|
block.totalInHi32 = 0;
|
|
block.totalOutLo32 = 0;
|
|
block.totalOutHi32 = 0;
|
|
block.blockNo = 0;
|
|
decompress(block);
|
|
outSize -= block.decompressedSize;
|
|
return outSize;
|
|
}
|
|
|
|
private static void nextHeader(BZState state) {
|
|
byte cStateOutCh = state.stateOutCh;
|
|
int cStateOutLen = state.stateOutLen;
|
|
int cNblockUsed = state.nblockUsed;
|
|
int cK0 = state.k0;
|
|
int cTt[] = state.tt;
|
|
int cTpos = state.tpos;
|
|
byte output[] = state.output;
|
|
int csNextOut = state.availOut;
|
|
int csAvailOut = state.decompressedSize;
|
|
int asdasdasd = csAvailOut;
|
|
int sSaveNblockPP = state.saveNblock + 1;
|
|
returnNotr:
|
|
do {
|
|
if (cStateOutLen > 0) {
|
|
do {
|
|
if (csAvailOut == 0)
|
|
break returnNotr;
|
|
if (cStateOutLen == 1)
|
|
break;
|
|
output[csNextOut] = cStateOutCh;
|
|
cStateOutLen--;
|
|
csNextOut++;
|
|
csAvailOut--;
|
|
} while (true);
|
|
if (csAvailOut == 0) {
|
|
cStateOutLen = 1;
|
|
break;
|
|
}
|
|
output[csNextOut] = cStateOutCh;
|
|
csNextOut++;
|
|
csAvailOut--;
|
|
}
|
|
boolean flag = true;
|
|
while (flag) {
|
|
flag = false;
|
|
if (cNblockUsed == sSaveNblockPP) {
|
|
cStateOutLen = 0;
|
|
break returnNotr;
|
|
}
|
|
cStateOutCh = (byte) cK0;
|
|
cTpos = cTt[cTpos];
|
|
byte k1 = (byte) (cTpos & 0xff);
|
|
cTpos >>= 8;
|
|
cNblockUsed++;
|
|
if (k1 != cK0) {
|
|
cK0 = k1;
|
|
if (csAvailOut == 0) {
|
|
cStateOutLen = 1;
|
|
} else {
|
|
output[csNextOut] = cStateOutCh;
|
|
csNextOut++;
|
|
csAvailOut--;
|
|
flag = true;
|
|
continue;
|
|
}
|
|
break returnNotr;
|
|
}
|
|
if (cNblockUsed != sSaveNblockPP)
|
|
continue;
|
|
if (csAvailOut == 0) {
|
|
cStateOutLen = 1;
|
|
break returnNotr;
|
|
}
|
|
output[csNextOut] = cStateOutCh;
|
|
csNextOut++;
|
|
csAvailOut--;
|
|
flag = true;
|
|
}
|
|
cStateOutLen = 2;
|
|
cTpos = cTt[cTpos];
|
|
byte k2 = (byte) (cTpos & 0xff);
|
|
cTpos >>= 8;
|
|
if (++cNblockUsed != sSaveNblockPP)
|
|
if (k2 != cK0) {
|
|
cK0 = k2;
|
|
} else {
|
|
cStateOutLen = 3;
|
|
cTpos = cTt[cTpos];
|
|
byte k3 = (byte) (cTpos & 0xff);
|
|
cTpos >>= 8;
|
|
if (++cNblockUsed != sSaveNblockPP)
|
|
if (k3 != cK0) {
|
|
cK0 = k3;
|
|
} else {
|
|
cTpos = cTt[cTpos];
|
|
byte byte3 = (byte) (cTpos & 0xff);
|
|
cTpos >>= 8;
|
|
cNblockUsed++;
|
|
cStateOutLen = (byte3 & 0xff) + 4;
|
|
cTpos = cTt[cTpos];
|
|
cK0 = (byte) (cTpos & 0xff);
|
|
cTpos >>= 8;
|
|
cNblockUsed++;
|
|
}
|
|
}
|
|
} while (true);
|
|
int i2 = state.totalOutLo32;
|
|
state.totalOutLo32 += asdasdasd - csAvailOut;
|
|
if (state.totalOutLo32 < i2)
|
|
state.totalOutHi32++;
|
|
state.stateOutCh = cStateOutCh;
|
|
state.stateOutLen = cStateOutLen;
|
|
state.nblockUsed = cNblockUsed;
|
|
state.k0 = cK0;
|
|
state.tt = cTt;
|
|
state.tpos = cTpos;
|
|
state.output = output;
|
|
state.availOut = csNextOut;
|
|
state.decompressedSize = csAvailOut;
|
|
}
|
|
|
|
private static void decompress(BZState state) {
|
|
/*boolean flag = false;
|
|
boolean flag1 = false;
|
|
boolean flag2 = false;
|
|
boolean flag3 = false;
|
|
boolean flag4 = false;
|
|
boolean flag5 = false;
|
|
boolean flag6 = false;
|
|
boolean flag7 = false;
|
|
boolean flag8 = false;
|
|
boolean flag9 = false;
|
|
boolean flag10 = false;
|
|
boolean flag11 = false;
|
|
boolean flag12 = false;
|
|
boolean flag13 = false;
|
|
boolean flag14 = false;
|
|
boolean flag15 = false;
|
|
boolean flag16 = false;
|
|
boolean flag17 = false;
|
|
boolean flag18 = false;*/
|
|
int gMinLen = 0;
|
|
int gLimit[] = null;
|
|
int gBase[] = null;
|
|
int gPerm[] = null;
|
|
state.blocksize100k = 1;
|
|
if (state.tt == null)
|
|
state.tt = new int[state.blocksize100k * 100000];
|
|
boolean goingandshit = true;
|
|
while (goingandshit) {
|
|
byte uc = getUchar(state);
|
|
if (uc == 23)
|
|
return;
|
|
uc = getUchar(state);
|
|
uc = getUchar(state);
|
|
uc = getUchar(state);
|
|
uc = getUchar(state);
|
|
uc = getUchar(state);
|
|
state.blockNo++;
|
|
uc = getUchar(state);
|
|
uc = getUchar(state);
|
|
uc = getUchar(state);
|
|
uc = getUchar(state);
|
|
uc = getBit(state);
|
|
state.blockRandomised = uc != 0;
|
|
if (state.blockRandomised)
|
|
System.out.println("PANIC! RANDOMISED BLOCK!");
|
|
state.origPtr = 0;
|
|
uc = getUchar(state);
|
|
state.origPtr = state.origPtr << 8 | uc & 0xff;
|
|
uc = getUchar(state);
|
|
state.origPtr = state.origPtr << 8 | uc & 0xff;
|
|
uc = getUchar(state);
|
|
state.origPtr = state.origPtr << 8 | uc & 0xff;
|
|
for (int i = 0; i < 16; i++) {
|
|
uc = getBit(state);
|
|
state.inUse_16[i] = uc == 1;
|
|
}
|
|
|
|
for (int i = 0; i < 256; i++)
|
|
state.inUse[i] = false;
|
|
|
|
for (int i = 0; i < 16; i++)
|
|
if (state.inUse_16[i]) {
|
|
for (int j = 0; j < 16; j++) {
|
|
uc = getBit(state);
|
|
if (uc == 1)
|
|
state.inUse[i * 16 + j] = true;
|
|
}
|
|
|
|
}
|
|
|
|
makeMaps(state);
|
|
int alphaSize = state.nInUse + 2;
|
|
int nGroups = getBits(3, state);
|
|
int nSelectors = getBits(15, state);
|
|
for (int i = 0; i < nSelectors; i++) {
|
|
int j = 0;
|
|
do {
|
|
uc = getBit(state);
|
|
if (uc == 0)
|
|
break;
|
|
j++;
|
|
} while (true);
|
|
state.selectorMtf[i] = (byte) j;
|
|
}
|
|
|
|
byte pos[] = new byte[6];
|
|
for (byte v = 0; v < nGroups; v++)
|
|
pos[v] = v;
|
|
|
|
for (int i = 0; i < nSelectors; i++) {
|
|
byte v = state.selectorMtf[i];
|
|
byte tmp = pos[v];
|
|
for (; v > 0; v--)
|
|
pos[v] = pos[v - 1];
|
|
|
|
pos[0] = tmp;
|
|
state.selector[i] = tmp;
|
|
}
|
|
|
|
for (int t = 0; t < nGroups; t++) {
|
|
int curr = getBits(5, state);
|
|
for (int i = 0; i < alphaSize; i++) {
|
|
do {
|
|
uc = getBit(state);
|
|
if (uc == 0)
|
|
break;
|
|
uc = getBit(state);
|
|
if (uc == 0)
|
|
curr++;
|
|
else
|
|
curr--;
|
|
} while (true);
|
|
state.len[t][i] = (byte) curr;
|
|
}
|
|
|
|
}
|
|
|
|
for (int t = 0; t < nGroups; t++) {
|
|
byte minLen = 32;
|
|
int maxLen = 0;
|
|
for (int l1 = 0; l1 < alphaSize; l1++) {
|
|
if (state.len[t][l1] > maxLen)
|
|
maxLen = state.len[t][l1];
|
|
if (state.len[t][l1] < minLen)
|
|
minLen = state.len[t][l1];
|
|
}
|
|
|
|
createDecodeTables(state.limit[t], state.base[t], state.perm[t], state.len[t], minLen, maxLen, alphaSize);
|
|
state.minLens[t] = minLen;
|
|
}
|
|
|
|
int eob = state.nInUse + 1;
|
|
int nblockMax = 100000 * state.blocksize100k;
|
|
int groupNo = -1;
|
|
int groupPos = 0;
|
|
for (int i = 0; i <= 255; i++)
|
|
state.unzftab[i] = 0;
|
|
|
|
int kk = 4095; // MTFASIZE-1;
|
|
for (int ii = 15; ii >= 0; ii--) {
|
|
for (int jj = 15; jj >= 0; jj--) {
|
|
state.mtfa[kk] = (byte) (ii * 16 + jj);
|
|
kk--;
|
|
}
|
|
|
|
state.mtfbase[ii] = kk + 1;
|
|
}
|
|
|
|
int nblock = 0;
|
|
// GETMTFVAL
|
|
if (groupPos == 0) {
|
|
groupNo++;
|
|
groupPos = 50; // BZGSIZE
|
|
byte gSel = state.selector[groupNo];
|
|
gMinLen = state.minLens[gSel];
|
|
gLimit = state.limit[gSel];
|
|
gPerm = state.perm[gSel];
|
|
gBase = state.base[gSel];
|
|
}
|
|
groupPos--;
|
|
int zn = gMinLen;
|
|
int zvec;
|
|
byte zj;
|
|
for (zvec = getBits(zn, state); zvec > gLimit[zn]; zvec = zvec << 1 | zj) {
|
|
zn++;
|
|
zj = getBit(state);
|
|
}
|
|
|
|
for (int nextSym = gPerm[zvec - gBase[zn]]; nextSym != eob; )
|
|
if (nextSym == 0 || nextSym == 1) { // BZRUNA, BZRUNB
|
|
int es = -1;
|
|
int N = 1;
|
|
do {
|
|
if (nextSym == 0)
|
|
es += N;
|
|
else if (nextSym == 1)
|
|
es += 2 * N;
|
|
N *= 2;
|
|
// GETMTFVAL, y da fuk did they not subroutine this
|
|
if (groupPos == 0) {
|
|
groupNo++;
|
|
groupPos = 50;
|
|
byte gSel = state.selector[groupNo];
|
|
gMinLen = state.minLens[gSel];
|
|
gLimit = state.limit[gSel];
|
|
gPerm = state.perm[gSel];
|
|
gBase = state.base[gSel];
|
|
}
|
|
groupPos--;
|
|
int zn_2 = gMinLen;
|
|
int zvec_2;
|
|
byte zj_2;
|
|
for (zvec_2 = getBits(zn_2, state); zvec_2 > gLimit[zn_2]; zvec_2 = zvec_2 << 1 | zj_2) {
|
|
zn_2++;
|
|
zj_2 = getBit(state);
|
|
}
|
|
|
|
nextSym = gPerm[zvec_2 - gBase[zn_2]];
|
|
} while (nextSym == 0 || nextSym == 1);
|
|
es++;
|
|
uc = state.setToUnseq[state.mtfa[state.mtfbase[0]] & 0xff];
|
|
state.unzftab[uc & 0xff] += es;
|
|
for (; es > 0; es--) {
|
|
state.tt[nblock] = uc & 0xff;
|
|
nblock++;
|
|
}
|
|
|
|
} else {
|
|
int nn = nextSym - 1;
|
|
if (nn < 16) { // MTFLSIZE
|
|
int pp = state.mtfbase[0];
|
|
uc = state.mtfa[pp + nn];
|
|
for (; nn > 3; nn -= 4) {
|
|
int z = pp + nn;
|
|
state.mtfa[z] = state.mtfa[z - 1];
|
|
state.mtfa[z - 1] = state.mtfa[z - 2];
|
|
state.mtfa[z - 2] = state.mtfa[z - 3];
|
|
state.mtfa[z - 3] = state.mtfa[z - 4];
|
|
}
|
|
|
|
for (; nn > 0; nn--)
|
|
state.mtfa[pp + nn] = state.mtfa[(pp + nn) - 1];
|
|
|
|
state.mtfa[pp] = uc;
|
|
} else {
|
|
int lno = nn / 16;
|
|
int off = nn % 16;
|
|
int pp = state.mtfbase[lno] + off;
|
|
uc = state.mtfa[pp];
|
|
for (; pp > state.mtfbase[lno]; pp--)
|
|
state.mtfa[pp] = state.mtfa[pp - 1];
|
|
|
|
state.mtfbase[lno]++;
|
|
for (; lno > 0; lno--) {
|
|
state.mtfbase[lno]--;
|
|
state.mtfa[state.mtfbase[lno]] = state.mtfa[(state.mtfbase[lno - 1] + 16) - 1];
|
|
}
|
|
|
|
state.mtfbase[0]--;
|
|
state.mtfa[state.mtfbase[0]] = uc;
|
|
if (state.mtfbase[0] == 0) {
|
|
kk = 4095; // MTFASIZE - 1
|
|
for (int ii = 15; ii >= 0; ii--) {
|
|
for (int jj = 15; jj >= 0; jj--) {
|
|
state.mtfa[kk] = state.mtfa[state.mtfbase[ii] + jj];
|
|
kk--;
|
|
}
|
|
|
|
state.mtfbase[ii] = kk + 1;
|
|
}
|
|
|
|
}
|
|
}
|
|
state.unzftab[state.setToUnseq[uc & 0xff] & 0xff]++;
|
|
state.tt[nblock] = state.setToUnseq[uc & 0xff] & 0xff;
|
|
nblock++;
|
|
// GETMTFVAL here we go AGAIN
|
|
if (groupPos == 0) {
|
|
groupNo++;
|
|
groupPos = 50;
|
|
byte gSel = state.selector[groupNo];
|
|
gMinLen = state.minLens[gSel];
|
|
gLimit = state.limit[gSel];
|
|
gPerm = state.perm[gSel];
|
|
gBase = state.base[gSel];
|
|
}
|
|
groupPos--;
|
|
int zn_2 = gMinLen;
|
|
int zvec_2;
|
|
byte zj_2;
|
|
for (zvec_2 = getBits(zn_2, state); zvec_2 > gLimit[zn_2]; zvec_2 = zvec_2 << 1 | zj_2) {
|
|
zn_2++;
|
|
zj_2 = getBit(state);
|
|
}
|
|
|
|
nextSym = gPerm[zvec_2 - gBase[zn_2]];
|
|
}
|
|
|
|
state.stateOutLen = 0;
|
|
state.stateOutCh = 0;
|
|
state.cftab[0] = 0;
|
|
for (int i = 1; i <= 256; i++)
|
|
state.cftab[i] = state.unzftab[i - 1];
|
|
|
|
for (int i = 1; i <= 256; i++)
|
|
state.cftab[i] += state.cftab[i - 1];
|
|
|
|
for (int i = 0; i < nblock; i++) {
|
|
uc = (byte) (state.tt[i] & 0xff);
|
|
state.tt[state.cftab[uc & 0xff]] |= i << 8;
|
|
state.cftab[uc & 0xff]++;
|
|
}
|
|
|
|
state.tpos = state.tt[state.origPtr] >> 8;
|
|
state.nblockUsed = 0;
|
|
state.tpos = state.tt[state.tpos];
|
|
state.k0 = (byte) (state.tpos & 0xff);
|
|
state.tpos >>= 8;
|
|
state.nblockUsed++;
|
|
state.saveNblock = nblock;
|
|
nextHeader(state);
|
|
goingandshit = state.nblockUsed == state.saveNblock + 1 && state.stateOutLen == 0;
|
|
}
|
|
}
|
|
|
|
private static byte getUchar(BZState state) {
|
|
return (byte) getBits(8, state);
|
|
}
|
|
|
|
private static byte getBit(BZState state) {
|
|
return (byte) getBits(1, state);
|
|
}
|
|
|
|
private static int getBits(int i, BZState state) {
|
|
int vvv;
|
|
do {
|
|
if (state.bsLive >= i) {
|
|
int v = state.bsBuff >> state.bsLive - i & (1 << i) - 1;
|
|
state.bsLive -= i;
|
|
vvv = v;
|
|
break;
|
|
}
|
|
state.bsBuff = state.bsBuff << 8 | state.input[state.nextIn] & 0xff;
|
|
state.bsLive += 8;
|
|
state.nextIn++;
|
|
state.availIn--;
|
|
state.totalInLo32++;
|
|
if (state.totalInLo32 == 0)
|
|
state.totalInHi32++;
|
|
} while (true);
|
|
return vvv;
|
|
}
|
|
|
|
private static void makeMaps(BZState state) {
|
|
state.nInUse = 0;
|
|
for (int i = 0; i < 256; i++)
|
|
if (state.inUse[i]) {
|
|
state.setToUnseq[state.nInUse] = (byte) i;
|
|
state.nInUse++;
|
|
}
|
|
|
|
}
|
|
|
|
private static void createDecodeTables(int limit[], int base[], int perm[], byte length[], int minLen, int maxLen, int alphaSize) {
|
|
int pp = 0;
|
|
for (int i = minLen; i <= maxLen; i++) {
|
|
for (int j = 0; j < alphaSize; j++)
|
|
if (length[j] == i) {
|
|
perm[pp] = j;
|
|
pp++;
|
|
}
|
|
|
|
}
|
|
|
|
for (int i = 0; i < 23; i++)
|
|
base[i] = 0;
|
|
|
|
for (int i = 0; i < alphaSize; i++)
|
|
base[length[i] + 1]++;
|
|
|
|
for (int i = 1; i < 23; i++)
|
|
base[i] += base[i - 1];
|
|
|
|
for (int i = 0; i < 23; i++)
|
|
limit[i] = 0;
|
|
|
|
int vec = 0;
|
|
for (int i = minLen; i <= maxLen; i++) {
|
|
vec += base[i + 1] - base[i];
|
|
limit[i] = vec - 1;
|
|
vec <<= 1;
|
|
}
|
|
|
|
for (int i = minLen + 1; i <= maxLen; i++)
|
|
base[i] = (limit[i - 1] + 1 << 1) - base[i];
|
|
|
|
}
|
|
}
|