hschumann2/TempleOS-Source-Code
0838
1 2//See ::/Doc/Credits.DD.3//See CArcCompress, CArcEntry, and CArcCtrl4 5asm {6/****7U0 ArcEntryGet(CArcCtrl *c)8{9 I64 i;10 CArcEntry *tmp,*tmp1;11 12 if (c->entry_used) {13 i=c->free_idx;14 15 c->entry_used=FALSE;16 c->cur_entry=c->next_entry;17 c->cur_bits_in_use=c->next_bits_in_use;18 if (c->next_bits_in_use<ARC_BITS_MAX) {19 c->next_entry = &c->compress[i++];20 if (i==c->free_limit) {21 c->next_bits_in_use++;22 c->free_limit=1<<c->next_bits_in_use;23 }24 } else {25 do if (++i==c->free_limit)26 i=c->min_table_entry;27 while (c->hash[i]);28 tmp=&c->compress[i];29 c->next_entry=tmp;30 tmp1=&c->hash[tmp->basecode];31 while (tmp1) {32 if (tmp1->next==tmp) {33 tmp1->next=tmp->next;34 break;35 } else36 tmp1=tmp1->next;37 }38 }39 c->free_idx=i;40 }41}42****/43_ARC_ENTRY_GET::44 PUSH RBP45 MOV RBP,RSP46 PUSH RSI47 PUSH RDI48 MOV RSI,U64 SF_ARG1[RBP]49 BTR U64 CArcCtrl.entry_used[RSI],050 JNC I32 @@3051 MOV RDX,U64 CArcCtrl.free_idx[RSI]52 MOV RAX,U64 CArcCtrl.next_entry[RSI]53 MOV U64 CArcCtrl.cur_entry[RSI],RAX54 MOV RCX,U64 CArcCtrl.next_bits_in_use[RSI]55 MOV U64 CArcCtrl.cur_bits_in_use[RSI],RCX56 CMP RCX,ARC_BITS_MAX57 JAE @@0558 MOV RAX,RDX59 SHL RAX,460 LEA RAX,U64 CArcCtrl.compress[RSI+RAX]61 MOV U64 CArcCtrl.next_entry[RSI],RAX62 INC RDX63 CMP U64 CArcCtrl.free_limit[RSI],RDX64 JNE @@2565 INC RCX66 MOV U64 CArcCtrl.next_bits_in_use[RSI],RCX67 MOV RAX,168 SHL RAX,CL69 MOV U64 CArcCtrl.free_limit[RSI],RAX70 JMP @@2571@@05: INC RDX72 CMP U64 CArcCtrl.free_limit[RSI],RDX73 JNE @@1074 MOV RDX,U64 CArcCtrl.min_table_entry[RSI]75@@10: MOV RAX,U64 CArcCtrl.hash[RSI+RDX*8]76 TEST RAX,RAX77 JNZ @@0578 MOV RDI,RDX79 SHL RDI,480 LEA RDI,U64 CArcCtrl.compress[RSI+RDI]81 MOV U32 CArcCtrl.next_entry[RSI],EDI82 MOVZX RBX,U16 CArcEntry.basecode[RDI]83 LEA RCX,U64 CArcCtrl.hash[RSI+RBX*8]84@@15: TEST RCX,RCX85 JZ @@2586 MOV RAX,U64 CArcEntry.next[RCX]87 CMP RDI,RAX88 JNE @@2089 MOV RAX,U64 CArcEntry.next[RDI]90 MOV U64 CArcEntry.next[RCX],RAX91 JMP @@2592@@20: MOV RCX,RAX93 JMP @@1594@@25: MOV U64 CArcCtrl.free_idx[RSI],RDX95@@30: POP RDI96 POP RSI97 POP RBP98 RET1 899}100 101_extern _ARC_ENTRY_GET U0 ArcEntryGet(CArcCtrl *c);102 103I64 ArcDetermineCompressionType(U8 *src,I64 size)104{105 while (size--)106 if (*src++&0x80)107 return CT_8_BIT;108 return CT_7_BIT;109}110 111U0 ArcCompressBuf(CArcCtrl *c)112{//Use CompressBuf() unless doing more than one buf.113 CArcEntry *tmp,*tmp1;114 I64 ch,basecode;115 U8 *src_ptr,*src_limit;116 117 src_ptr=c->src_buf+c->src_pos;118 src_limit=c->src_buf+c->src_size;119 120 if (c->saved_basecode==U32_MAX)121 basecode=*src_ptr++;122 else123 basecode=c->saved_basecode;124 125 while (src_ptr<src_limit && c->dst_pos+c->cur_bits_in_use<=c->dst_size) {126 ArcEntryGet(c);127ac_start:128 if (src_ptr>=src_limit) goto ac_done;129 ch=*src_ptr++;130 if (tmp=c->hash[basecode])131 do {132 if (tmp->ch==ch) {133 basecode=tmp-&c->compress[0];134 goto ac_start;135 }136 } while (tmp=tmp->next);137 138 BFieldOrU32(c->dst_buf,c->dst_pos,basecode);139 c->dst_pos+=c->cur_bits_in_use;140 141 c->entry_used=TRUE;142 tmp=c->cur_entry;143 tmp->basecode=basecode;144 tmp->ch=ch;145 tmp1=&c->hash[basecode];146 tmp->next=tmp1->next;147 tmp1->next=tmp;148 149 basecode=ch;150 }151ac_done:152 c->saved_basecode=basecode;153 c->src_pos=src_ptr-c->src_buf;154}155 156Bool ArcFinishCompression(CArcCtrl *c)157{//Do closing touch on archivew ctrl struct.158 if (c->dst_pos+c->cur_bits_in_use<=c->dst_size) {159 BFieldOrU32(c->dst_buf,c->dst_pos,c->saved_basecode);160 c->dst_pos+=c->next_bits_in_use;161 return TRUE;162 } else163 return FALSE;164}165 166U0 ArcExpandBuf(CArcCtrl *c)167{//Use ExpandBuf() unless you know what you're doing.168 U8 *dst_ptr,*dst_limit;169 I64 basecode,lastcode,code;170 CArcEntry *tmp,*tmp1;171 172 dst_ptr=c->dst_buf+c->dst_pos;173 dst_limit=c->dst_buf+c->dst_size;174 175 while (dst_ptr<dst_limit && c->stk_ptr!=c->stk_base)176 *dst_ptr++ = * -- c->stk_ptr;177 178 if (c->stk_ptr==c->stk_base && dst_ptr<dst_limit) {179 if (c->saved_basecode==U32_MAX) {180 lastcode=BFieldExtU32(c->src_buf,c->src_pos,181 c->next_bits_in_use);182 c->src_pos+=c->next_bits_in_use;183 *dst_ptr++=lastcode;184 ArcEntryGet(c);185 c->last_ch=lastcode;186 } else187 lastcode=c->saved_basecode;188 while (dst_ptr<dst_limit && c->src_pos+c->next_bits_in_use<=c->src_size) {189 basecode=BFieldExtU32(c->src_buf,c->src_pos,190 c->next_bits_in_use);191 c->src_pos+=c->next_bits_in_use;192 if (c->cur_entry==&c->compress[basecode]) {193 *c->stk_ptr++=c->last_ch;194 code=lastcode;195 } else196 code=basecode;197 while (code>=c->min_table_entry) {198 *c->stk_ptr++=c->compress[code].ch;199 code=c->compress[code].basecode;200 }201 *c->stk_ptr++=code;202 c->last_ch=code;203 204 c->entry_used=TRUE;205 tmp=c->cur_entry;206 tmp->basecode=lastcode;207 tmp->ch=c->last_ch;208 tmp1=&c->hash[lastcode];209 tmp->next=tmp1->next;210 tmp1->next=tmp;211 212 ArcEntryGet(c);213 while (dst_ptr<dst_limit && c->stk_ptr!=c->stk_base)214 *dst_ptr++ = * -- c->stk_ptr;215 lastcode=basecode;216 }217 c->saved_basecode=lastcode;218 }219 c->dst_pos=dst_ptr-c->dst_buf;220}221 222CArcCtrl *ArcCtrlNew(Bool expand,I64 compression_type=CT_8_BIT)223{//MAlloc archive ctrl struct.224 CArcCtrl *c;225 c=CAlloc(sizeof(CArcCtrl));226 if (expand) {227 c->stk_base=MAlloc(1<<ARC_BITS_MAX);228 c->stk_ptr=c->stk_base;229 }230 if (compression_type==CT_7_BIT)231 c->min_bits=7;232 else233 c->min_bits=8;234 c->min_table_entry=1<<c->min_bits;235 c->free_idx=c->min_table_entry;236 c->next_bits_in_use=c->min_bits+1;237 c->free_limit=1<<c->next_bits_in_use;238 c->saved_basecode=U32_MAX;239 c->entry_used=TRUE;240 ArcEntryGet(c);241 c->entry_used=TRUE;242 return c;243}244 245U0 ArcCtrlDel(CArcCtrl *c)246{//Free archive ctrl struct.247 Free(c->stk_base);248 Free(c);249}250 251U8 *ExpandBuf(CArcCompress *arc,CTask *mem_task=NULL)252{//See ::/Demo/Dsk/SerializeTree.HC.253 CArcCtrl *c;254 U8 *res;255 256 if (!(CT_NONE<=arc->compression_type<=CT_8_BIT) ||257 arc->expanded_size>mem_mapped_space)258 throw('Compress');259 260 res=MAlloc(arc->expanded_size+1,mem_task);261 res[arc->expanded_size]=0; //terminate262 switch [arc->compression_type] {263 case CT_NONE:264 MemCpy(res,&arc->body,arc->expanded_size);265 break;266 case CT_7_BIT:267 case CT_8_BIT:268 c=ArcCtrlNew(TRUE,arc->compression_type);269 c->src_size=arc->compressed_size<<3;270 c->src_pos=sizeof(CArcCompress)<<3;271 c->src_buf=arc;272 c->dst_size=arc->expanded_size;273 c->dst_buf=res;274 c->dst_pos=0;275 ArcExpandBuf(c);276 ArcCtrlDel(c);277 break;278 }279 return res;280}281 282CArcCompress *CompressBuf(U8 *src,I64 size,CTask *mem_task=NULL)283{//See ::/Demo/Dsk/SerializeTree.HC.284 CArcCompress *arc;285 I64 size_out,compression_type=ArcDetermineCompressionType(src,size);286 CArcCtrl *c=ArcCtrlNew(FALSE,compression_type);287 c->src_size=size;288 c->src_buf=src;289 c->dst_size=(size+sizeof(CArcCompress))<<3;290 c->dst_buf=CAlloc(c->dst_size>>3);291 c->dst_pos=sizeof(CArcCompress)<<3;292 ArcCompressBuf(c);293 if (ArcFinishCompression(c) && c->src_pos==c->src_size) {294 size_out=(c->dst_pos+7)>>3;295 arc=MAlloc(size_out,mem_task);296 MemCpy(arc,c->dst_buf,size_out);297 arc->compression_type=compression_type;298 arc->compressed_size=size_out;299 } else {300 arc=MAlloc(size+sizeof(CArcCompress),mem_task);301 MemCpy(&arc->body,src,size);302 arc->compression_type=CT_NONE;303 arc->compressed_size=size+sizeof(CArcCompress);304 }305 arc->expanded_size=size;306 Free(c->dst_buf);307 ArcCtrlDel(c);308 return arc;309}310 