static DWORD rng_decompress(BYTE *out, BYTE *in, DWORD in_len) { qsmodel qsm; rangecoder rc; int ch, syfreq, ltfreq; DWORD act_uncomprlen = 0; /* make an alphabet with 257 symbols, use 256 as end-of-file */ initqsmodel(&qsm, 257, 12, 2000, NULL, 0); /* unknown crypt_index[0], seems to be always 0x00 */ start_decoding(&rc, in + 1); while (1) { ltfreq = decode_culshift(&rc, 12); ch = qsgetsym(&qsm, ltfreq); if (ch == 256) /* check for end-of-file */ break; out[act_uncomprlen++] = ch; qsgetfreq(&qsm, ch, &syfreq, <freq); decode_update(&rc, syfreq, ltfreq, 1 << 12); qsupdate(&qsm, ch); } qsgetfreq(&qsm, 256, &syfreq, <freq); decode_update(&rc, syfreq, ltfreq, 1 << 12); done_decoding(&rc); deleteqsmodel(&qsm); return act_uncomprlen; }
int unpack(FILE* out,FILE* in) { freq cf; rangecoder rc; struct buffer buffer; struct ari_model model; size_t processed=0; buffer.offset = 0; buffer.len_power = 1+BLOCKSIZE_POWER; buffer.len = 1<<buffer.len_power; buffer.len_mask = buffer.len - 1; buffer.data = malloc(buffer.len); rc.in = in; model_setup(&model); if(!buffer.data) return -2; if (start_decoding(&rc) != 0) { return -1; } while ( (cf = decode_culfreq(&rc,2)) ) { freq i, blocksize; decode_update(&rc,1,1,2); blocksize = decode_short(&rc) | ((size_t)decode_short(&rc)) <<16; for (i=0; i<blocksize; i++) { freq symbol; cf = decode_culfreq(&rc,model.counts[SYMBOLS]); symbol = model_get_symbol(&model, cf); decode_update(&rc, model.counts[symbol+1]-model.counts[symbol],model.counts[symbol],model.counts[SYMBOLS]); model_update_freq(&model,symbol); /*fprintf(stderr,"Decoding:%d(%c),%ld,%ld\n",symbol,symbol,counts[symbol+1]-counts[symbol],counts[symbol]);*/ if(symbol > 0xff) { const uint8_t extra_bits = code_to_length[symbol-0x100].extra_bits; const size_t extra_data = decode_culshift(&rc, extra_bits); const size_t length = code_to_length[symbol-0x100].start + extra_data; size_t distance; size_t distance_hi; decode_update_shift(&rc, 1, extra_data, extra_bits); distance = decode_culshift(&rc,8); decode_update_shift(&rc, 1, distance, 8); distance_hi = decode_culshift(&rc,8); decode_update_shift(&rc, 1, distance_hi, 8); distance |= distance_hi<<8; /* fprintf(stderr,"Retrieved length,distance:%ld,%ld\n",length,distance);*/ buffer.offset = copy_back_bytes(&buffer,buffer.offset,distance,length); } else { buffer.data[buffer.offset++] = symbol; if(buffer.offset >= buffer.len) { buffer.offset = 0; fwrite(buffer.data,1,buffer.len,out); } } } processed += blocksize; if(processed > 1<<19) { done_decoding(&rc); start_decoding(&rc); processed=0; } /*fprintf(stderr,"%ld;;%d\n",blocksize,model.counts[SYMBOLS]);*/ } fwrite(buffer.data,1,buffer.offset,out); done_decoding(&rc); model_done(&model); free(buffer.data); fclose(out); return 0; }