comparison unrarlib.c @ 7446:ad00ad5f25a9

Automatic unrar of vobsub. Does not work with rar v3
author kmkaplan
date Fri, 20 Sep 2002 01:26:39 +0000
parents
children fb88ccbc5ccc
comparison
equal deleted inserted replaced
7445:6a25ea5b2401 7446:ad00ad5f25a9
1 /* ***************************************************************************
2 **
3 ** This file is part of the UniquE RAR File Library.
4 **
5 ** Copyright (C) 2000-2002 by Christian Scheurer (www.ChristianScheurer.ch)
6 ** UNIX port copyright (c) 2000-2002 by Johannes Winkelmann (jw@tks6.net)
7 **
8 ** The contents of this file are subject to the UniquE RAR File Library
9 ** License (the "unrarlib-license.txt"). You may not use this file except
10 ** in compliance with the License. You may obtain a copy of the License
11 ** at http://www.unrarlib.org/license.html.
12 ** Software distributed under the License is distributed on an "AS IS"
13 ** basis, WITHOUT WARRANTY OF ANY KIND, either express or implied warranty.
14 **
15 ** Alternatively, the contents of this file may be used under the terms
16 ** of the GNU General Public License Version 2 or later (the "GPL"), in
17 ** which case the provisions of the GPL are applicable instead of those
18 ** above. If you wish to allow use of your version of this file only
19 ** under the terms of the GPL and not to allow others to use your version
20 ** of this file under the terms of the UniquE RAR File Library License,
21 ** indicate your decision by deleting the provisions above and replace
22 ** them with the notice and other provisions required by the GPL. If you
23 ** do not delete the provisions above, a recipient may use your version
24 ** of this file under the terms of the GPL or the UniquE RAR File Library
25 ** License.
26 **
27 ************************************************************************** */
28
29 /* ***************************************************************************
30 **
31 ** UniquE RAR File Library
32 ** The free file lib for the demoscene
33 ** multi-OS version (Win32, Linux and SunOS)
34 **
35 *****************************************************************************
36 **
37 ** ==> Please configure the program in "unrarlib.h". <==
38 **
39 ** RAR decompression code:
40 ** (C) Eugene Roshal
41 ** Modifications to a FileLib:
42 ** (C) 2000-2002 Christian Scheurer aka. UniquE/Vantage (cs@unrarlib.org)
43 ** Linux port:
44 ** (C) 2000-2002 Johannes Winkelmann (jw@tks6.net)
45 **
46 ** The UniquE RAR File Library gives you the ability to access RAR archives
47 ** (any compression method supported in RAR v2.0 including Multimedia
48 ** Compression and encryption) directly from your program with ease an by
49 ** adding only 12kB (6kB UPX-compressed) additional code to your program.
50 ** Both solid and normal (recommended for fast random access to the files!)
51 ** archives are supported. This FileLib is made for the Demo scene, so it's
52 ** designed for easy use within your demos and intros.
53 ** Please read "licence.txt" to learn more about how you may use URARFileLib
54 ** in your productions.
55 **
56 *****************************************************************************
57 **
58 ** ==> see the "CHANGES" file to see what's new
59 **
60 ************************************************************************** */
61
62 /* -- include files ------------------------------------------------------- */
63 #include "unrarlib.h" /* include global configuration */
64 /* ------------------------------------------------------------------------ */
65
66
67
68 /* -- global stuff -------------------------------------------------------- */
69 #ifdef _WIN_32
70
71 #include <windows.h> /* WIN32 definitions */
72 #include <stdio.h>
73 #include <string.h>
74
75
76 #define ENABLE_ACCESS
77
78 #define HOST_OS WIN_32
79
80 #define FM_NORMAL 0x00
81 #define FM_RDONLY 0x01
82 #define FM_HIDDEN 0x02
83 #define FM_SYSTEM 0x04
84 #define FM_LABEL 0x08
85 #define FM_DIREC 0x10
86 #define FM_ARCH 0x20
87
88 #define PATHDIVIDER "\\"
89 #define CPATHDIVIDER '\\'
90 #define MASKALL "*.*"
91
92 #define READBINARY "rb"
93 #define READTEXT "rt"
94 #define UPDATEBINARY "r+b"
95 #define CREATEBINARY "w+b"
96 #define CREATETEXT "w"
97 #define APPENDTEXT "at"
98
99 #endif
100
101 #ifdef _UNIX
102
103 #include <stdio.h> /* LINUX/UNIX definitions */
104 #include <stdlib.h>
105 #include <ctype.h>
106 #include <string.h>
107
108 #define ENABLE_ACCESS
109
110 #define HOST_OS UNIX
111
112 #define FM_LABEL 0x0000
113 #define FM_DIREC 0x4000
114
115 #define PATHDIVIDER "/"
116 #define CPATHDIVIDER '/'
117 #define MASKALL "*.*"
118
119 #define READBINARY "r"
120 #define READTEXT "r"
121 #define UPDATEBINARY "r+"
122 #define CREATEBINARY "w+"
123 #define CREATETEXT "w"
124 #define APPENDTEXT "a"
125
126
127 /* emulation of the windows API and data types */
128 /* 20-08-2000 Johannes Winkelmann, jw@tks6.net */
129
130 typedef long DWORD;
131 typedef short BOOL;
132 #define TRUE 1
133 #define FALSE 0
134
135
136 #ifdef _DEBUG_LOG /* define macros for debugging */
137 #include <unistd.h>
138 #include <sys/time.h>
139
140 DWORD GetTickCount()
141 {
142 struct timeval tv;
143 gettimeofday( &tv, 0 );
144 return (tv.tv_usec / 1000);
145 }
146 #endif
147
148 #endif
149
150
151
152
153
154 #ifdef _DEBUG_LOG /* define macros for debugging */
155
156 BOOL debug_log_first_start = TRUE;
157
158 #define debug_log(a); debug_log_proc(a, __FILE__, __LINE__);
159 #define debug_init(a); debug_init_proc(a);
160
161 void debug_log_proc(char *text, char *sourcefile, int sourceline);
162 void debug_init_proc(char *file_name);
163
164 #else
165 #define debug_log(a); /* no debug this time */
166 #define debug_init(a); /* no debug this time */
167 #endif
168
169
170
171
172
173 #define MAXWINSIZE 0x100000
174 #define MAXWINMASK (MAXWINSIZE-1)
175 #define UNP_MEMORY MAXWINSIZE
176 #define Min(x,y) (((x)<(y)) ? (x):(y))
177 #define Max(x,y) (((x)>(y)) ? (x):(y))
178 #define NM 260
179
180 #define SIZEOF_MARKHEAD 7
181 #define SIZEOF_OLDMHD 7
182 #define SIZEOF_NEWMHD 13
183 #define SIZEOF_OLDLHD 21
184 #define SIZEOF_NEWLHD 32
185 #define SIZEOF_SHORTBLOCKHEAD 7
186 #define SIZEOF_LONGBLOCKHEAD 11
187 #define SIZEOF_COMMHEAD 13
188 #define SIZEOF_PROTECTHEAD 26
189
190
191 #define PACK_VER 20 /* version of decompression code*/
192 #define UNP_VER 20
193 #define PROTECT_VER 20
194
195
196 enum { M_DENYREAD,M_DENYWRITE,M_DENYNONE,M_DENYALL };
197 enum { FILE_EMPTY,FILE_ADD,FILE_UPDATE,FILE_COPYOLD,FILE_COPYBLOCK };
198 enum { SUCCESS,WARNING,FATAL_ERROR,CRC_ERROR,LOCK_ERROR,WRITE_ERROR,
199 OPEN_ERROR,USER_ERROR,MEMORY_ERROR,USER_BREAK=255,IMM_ABORT=0x8000 };
200 enum { EN_LOCK=1,EN_VOL=2 };
201 enum { SD_MEMORY=1,SD_FILES=2 };
202 enum { NAMES_DONTCHANGE };
203 enum { LOG_ARC=1,LOG_FILE=2 };
204 enum { OLD_DECODE=0,OLD_ENCODE=1,NEW_CRYPT=2 };
205 enum { OLD_UNPACK,NEW_UNPACK };
206
207
208 #define MHD_COMMENT 2
209 #define MHD_LOCK 4
210 #define MHD_PACK_COMMENT 16
211 #define MHD_AV 32
212 #define MHD_PROTECT 64
213
214 #define LHD_SPLIT_BEFORE 1
215 #define LHD_SPLIT_AFTER 2
216 #define LHD_PASSWORD 4
217 #define LHD_COMMENT 8
218 #define LHD_SOLID 16
219
220 #define LHD_WINDOWMASK 0x00e0
221 #define LHD_WINDOW64 0
222 #define LHD_WINDOW128 32
223 #define LHD_WINDOW256 64
224 #define LHD_WINDOW512 96
225 #define LHD_WINDOW1024 128
226 #define LHD_DIRECTORY 0x00e0
227
228 #define LONG_BLOCK 0x8000
229 #define READSUBBLOCK 0x8000
230
231 enum { ALL_HEAD=0,MARK_HEAD=0x72,MAIN_HEAD=0x73,FILE_HEAD=0x74,
232 COMM_HEAD=0x75,AV_HEAD=0x76,SUB_HEAD=0x77,PROTECT_HEAD=0x78};
233 enum { EA_HEAD=0x100 };
234 enum { MS_DOS=0,OS2=1,WIN_32=2,UNIX=3 };
235
236
237 struct MarkHeader
238 {
239 UBYTE Mark[7];
240 };
241
242
243 struct NewMainArchiveHeader
244 {
245 UWORD HeadCRC;
246 UBYTE HeadType;
247 UWORD Flags;
248 UWORD HeadSize;
249 UWORD Reserved;
250 UDWORD Reserved1;
251 };
252
253
254 struct NewFileHeader
255 {
256 UWORD HeadCRC;
257 UBYTE HeadType;
258 UWORD Flags;
259 UWORD HeadSize;
260 UDWORD PackSize;
261 UDWORD UnpSize;
262 UBYTE HostOS;
263 UDWORD FileCRC;
264 UDWORD FileTime;
265 UBYTE UnpVer;
266 UBYTE Method;
267 UWORD NameSize;
268 UDWORD FileAttr;
269 };
270
271
272 struct BlockHeader
273 {
274 UWORD HeadCRC;
275 UBYTE HeadType;
276 UWORD Flags;
277 UWORD HeadSize;
278 UDWORD DataSize;
279 };
280
281
282 struct Decode
283 {
284 unsigned int MaxNum;
285 unsigned int DecodeLen[16];
286 unsigned int DecodePos[16];
287 unsigned int DecodeNum[2];
288 };
289
290
291 struct MarkHeader MarkHead;
292 struct NewMainArchiveHeader NewMhd;
293 struct NewFileHeader NewLhd;
294 struct BlockHeader BlockHead;
295
296 UBYTE *TempMemory; /* temporary unpack-buffer */
297 char *CommMemory;
298
299
300 UBYTE *UnpMemory;
301 char ArgName[NM]; /* current file in rar archive */
302 char ArcFileName[NM]; /* file to decompress */
303
304 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION /* mem-to-mem decompression */
305 MemoryFile *MemRARFile; /* pointer to RAR file in memory*/
306 #else
307 char ArcName[255]; /* RAR archive name */
308 FILE *ArcPtr; /* input RAR file handler */
309 #endif
310 char Password[255]; /* password to decrypt files */
311
312 unsigned char *temp_output_buffer; /* extract files to this pointer*/
313 unsigned long *temp_output_buffer_offset; /* size of temp. extract buffer */
314
315 BOOL FileFound; /* TRUE=use current extracted */
316 /* data FALSE=throw data away, */
317 /* wrong file */
318 int MainHeadSize;
319 long CurBlockPos,NextBlockPos;
320
321 unsigned long CurUnpRead, CurUnpWrite;
322 long UnpPackedSize;
323 long DestUnpSize;
324
325 UDWORD HeaderCRC;
326 int Encryption;
327
328 unsigned int UnpWrSize;
329 unsigned char *UnpWrAddr;
330 unsigned int UnpPtr,WrPtr;
331
332 unsigned char PN1,PN2,PN3;
333 unsigned short OldKey[4];
334
335
336
337 /* function header definitions */
338 int ReadHeader(int BlockType);
339 BOOL ExtrFile(void);
340 BOOL ListFile(void);
341 int tread(void *stream,void *buf,unsigned len);
342 int tseek(void *stream,long offset,int fromwhere);
343 BOOL UnstoreFile(void);
344 int IsArchive(void);
345 int ReadBlock(int BlockType);
346 unsigned int UnpRead(unsigned char *Addr,unsigned int Count);
347 void UnpInitData(void);
348 void Unpack(unsigned char *UnpAddr);
349 UBYTE DecodeAudio(int Delta);
350 static void DecodeNumber(struct Decode *Dec);
351 void UpdKeys(UBYTE *Buf);
352 void SetCryptKeys(char *Password);
353 void SetOldKeys(char *Password);
354 void DecryptBlock(unsigned char *Buf);
355 void InitCRC(void);
356 UDWORD CalcCRC32(UDWORD StartCRC,UBYTE *Addr,UDWORD Size);
357 void UnpReadBuf(int FirstBuf);
358 void ReadTables(void);
359 static void ReadLastTables(void);
360 static void MakeDecodeTables(unsigned char *LenTab,
361 struct Decode *Dec,
362 int Size);
363 int stricomp(char *Str1,char *Str2);
364 /* ------------------------------------------------------------------------ */
365
366
367 /* -- global functions ---------------------------------------------------- */
368
369 int urarlib_get(void *output,
370 unsigned long *size,
371 char *filename,
372 void *rarfile,
373 char *libpassword)
374 /* Get a file from a RAR file to the "output" buffer. The UniquE RAR FileLib
375 * does everything from allocating memory, decrypting and unpacking the file
376 * from the archive. TRUE is returned if the file could be successfully
377 * extracted, else a FALSE indicates a failure.
378 */
379 {
380 BOOL retcode = FALSE;
381
382 #ifdef _DEBUG_LOG
383 int str_offs; /* used for debug-strings */
384 char DebugMsg[500]; /* used to compose debug msg */
385
386 if(debug_log_first_start)
387 {
388 debug_log_first_start=FALSE; /* only create a new log file */
389 debug_init(_DEBUG_LOG_FILE); /* on startup */
390 }
391
392 #endif
393
394 InitCRC(); /* init some vars */
395
396 strcpy(ArgName, filename); /* set file(s) to extract */
397 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
398 MemRARFile = rarfile; /* set pointer to mem-RAR file */
399 #else
400 strcpy(ArcName, rarfile); /* set RAR file name */
401 #endif
402 if(libpassword != NULL)
403 strcpy(Password, libpassword); /* init password */
404
405 temp_output_buffer = NULL;
406 temp_output_buffer_offset=size; /* set size of the temp buffer */
407
408 #ifdef _DEBUG_LOG
409 sprintf(DebugMsg, "Extracting >%s< from >%s< (password is >%s<)...",
410 filename, (char*)rarfile, libpassword);
411 debug_log(DebugMsg);
412 #endif
413
414 retcode = ExtrFile(); /* unpack file now! */
415
416 memset(Password,0,sizeof(Password)); /* clear password */
417
418 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
419 if (ArcPtr!=NULL){
420 fclose(ArcPtr);
421 ArcPtr = NULL;
422 }
423 #endif
424
425 free(UnpMemory); /* free memory */
426 free(TempMemory);
427 free(CommMemory);
428 UnpMemory=NULL;
429 TempMemory=NULL;
430 CommMemory=NULL;
431
432
433 if(retcode == FALSE)
434 {
435 free(temp_output_buffer); /* free memory and return NULL */
436 temp_output_buffer=NULL;
437 *(DWORD*)output=0; /* pointer on errors */
438 *size=0;
439 #ifdef _DEBUG_LOG
440
441
442 /* sorry for this ugly code, but older SunOS gcc compilers don't support */
443 /* white spaces within strings */
444 str_offs = sprintf(DebugMsg, "Error - couldn't extract ");
445 str_offs += sprintf(DebugMsg + str_offs, ">%s<", filename);
446 str_offs += sprintf(DebugMsg + str_offs, " and allocated ");
447 str_offs += sprintf(DebugMsg + str_offs, "%u Bytes", (unsigned int)*size);
448 str_offs += sprintf(DebugMsg + str_offs, " of unused memory!");
449
450 } else
451 {
452 sprintf(DebugMsg, "Extracted %u Bytes.", (unsigned int)*size);
453 }
454 debug_log(DebugMsg);
455 #else
456 }
457 #endif
458 *(DWORD*)output=(DWORD)temp_output_buffer;/* return pointer for unpacked*/
459 /* data */
460
461 return retcode;
462 }
463
464
465 int urarlib_list(void *rarfile, ArchiveList_struct *list)
466 {
467 ArchiveList_struct *tmp_List = NULL;
468 int NoOfFilesInArchive = 0; /* number of files in archive */
469
470 #ifdef _DEBUG_LOG
471 if(debug_log_first_start)
472 {
473 debug_log_first_start=FALSE; /* only create a new log file */
474 debug_init(_DEBUG_LOG_FILE); /* on startup */
475 }
476 #endif
477
478 InitCRC(); /* init some vars */
479
480 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
481 MemRARFile = rarfile; /* assign pointer to RAR file */
482 MemRARFile->offset = 0;
483 if (!IsArchive())
484 {
485 debug_log("Not a RAR file");
486 return NoOfFilesInArchive; /* error => exit! */
487 }
488 #else
489 /* open and identify archive */
490 if ((ArcPtr=fopen(rarfile,READBINARY))!=NULL)
491 {
492 if (!IsArchive())
493 {
494 debug_log("Not a RAR file");
495 fclose(ArcPtr);
496 ArcPtr = NULL;
497 return NoOfFilesInArchive; /* error => exit! */
498 }
499 }
500 else {
501 debug_log("Error opening file.");
502 return NoOfFilesInArchive;
503 }
504 #endif
505
506 if ((UnpMemory=malloc(UNP_MEMORY))==NULL)
507 {
508 debug_log("Can't allocate memory for decompression!");
509 return NoOfFilesInArchive;
510 }
511
512 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
513 MemRARFile->offset+=NewMhd.HeadSize-MainHeadSize;
514 #else
515 tseek(ArcPtr,NewMhd.HeadSize-MainHeadSize,SEEK_CUR);
516 #endif
517 (*(DWORD*)list) = (DWORD)NULL; /* init file list */
518 /* do while file is not extracted and there's no error */
519 while (TRUE)
520 {
521 if (ReadBlock(FILE_HEAD | READSUBBLOCK) <= 0) /* read name of the next */
522 { /* file within the RAR archive */
523 debug_log("Couldn't read next filename from archive (I/O error).");
524 break; /* error, file not found in */
525 } /* archive or I/O error */
526 if (BlockHead.HeadType==SUB_HEAD)
527 {
528 debug_log("Sorry, sub-headers not supported.");
529 break; /* error => exit */
530 }
531
532 if((void*)(*(DWORD*)list) == NULL) /* first entry */
533 {
534 tmp_List = malloc(sizeof(ArchiveList_struct));
535 tmp_List->next = NULL;
536
537 (*(DWORD*)list) = (DWORD)tmp_List;
538
539 } else /* add entry */
540 {
541 tmp_List->next = malloc(sizeof(ArchiveList_struct));
542 tmp_List = (ArchiveList_struct*) tmp_List->next;
543 tmp_List->next = NULL;
544 }
545
546 tmp_List->item.Name = malloc(NewLhd.NameSize + 1);
547 strcpy(tmp_List->item.Name, ArcFileName);
548 tmp_List->item.NameSize = NewLhd.NameSize;
549 tmp_List->item.PackSize = NewLhd.PackSize;
550 tmp_List->item.UnpSize = NewLhd.UnpSize;
551 tmp_List->item.HostOS = NewLhd.HostOS;
552 tmp_List->item.FileCRC = NewLhd.FileCRC;
553 tmp_List->item.FileTime = NewLhd.FileTime;
554 tmp_List->item.UnpVer = NewLhd.UnpVer;
555 tmp_List->item.Method = NewLhd.Method;
556 tmp_List->item.FileAttr = NewLhd.FileAttr;
557
558 NoOfFilesInArchive++; /* count files */
559
560 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
561 MemRARFile->offset = NextBlockPos;
562 #else
563 if (ArcPtr!=NULL) tseek(ArcPtr,NextBlockPos,SEEK_SET);
564 #endif
565
566 };
567
568 /* free memory, clear password and close archive */
569 memset(Password,0,sizeof(Password)); /* clear password */
570 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
571 if (ArcPtr!=NULL){
572 fclose(ArcPtr);
573 ArcPtr = NULL;
574 }
575 #endif
576
577 free(UnpMemory); /* free memory */
578 free(TempMemory);
579 free(CommMemory);
580 UnpMemory=NULL;
581 TempMemory=NULL;
582 CommMemory=NULL;
583
584 return NoOfFilesInArchive;
585 }
586
587
588
589 /* urarlib_freelist:
590 * (after the suggestion and code of Duy Nguyen, Sean O'Blarney
591 * and Johannes Winkelmann who independently wrote a patch)
592 * free the memory of a ArchiveList_struct created by urarlib_list.
593 *
594 * input: *list pointer to an ArchiveList_struct
595 * output: -
596 */
597
598 void urarlib_freelist(ArchiveList_struct *list)
599 {
600 ArchiveList_struct* tmp = list;
601
602 while ( list ) {
603 tmp = list->next;
604 free( list->item.Name );
605 free( list );
606 list = tmp;
607 }
608 }
609
610
611 /* ------------------------------------------------------------------------ */
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629 /****************************************************************************
630 ****************************************************************************
631 ****************************************************************************
632 ****************************************************************************
633 ******* *******
634 ******* *******
635 ******* *******
636 ******* B L O C K I / O *******
637 ******* *******
638 ******* *******
639 ******* *******
640 ****************************************************************************
641 ****************************************************************************
642 ****************************************************************************
643 ****************************************************************************/
644
645
646
647 #define GetHeaderByte(N) Header[N]
648
649 #define GetHeaderWord(N) (Header[N]+((UWORD)Header[N+1]<<8))
650
651 #define GetHeaderDword(N) (Header[N]+((UWORD)Header[N+1]<<8)+\
652 ((UDWORD)Header[N+2]<<16)+\
653 ((UDWORD)Header[N+3]<<24))
654
655
656 int ReadBlock(int BlockType)
657 {
658 struct NewFileHeader SaveFileHead;
659 int Size=0,ReadSubBlock=0;
660 static int LastBlock;
661 memcpy(&SaveFileHead,&NewLhd,sizeof(SaveFileHead));
662 if (BlockType & READSUBBLOCK)
663 ReadSubBlock=1;
664 BlockType &= 0xff;
665 {
666 while (1)
667 {
668 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
669 CurBlockPos=MemRARFile->offset; /* get offset of mem-file */
670 #else
671 CurBlockPos=ftell(ArcPtr);
672 #endif
673 Size=ReadHeader(FILE_HEAD);
674 if (Size!=0)
675 {
676 if (NewLhd.HeadSize<SIZEOF_SHORTBLOCKHEAD)
677 return(0);
678 NextBlockPos=CurBlockPos+NewLhd.HeadSize;
679 if (NewLhd.Flags & LONG_BLOCK)
680 NextBlockPos+=NewLhd.PackSize;
681 if (NextBlockPos<=CurBlockPos)
682 return(0);
683 }
684
685 if (Size > 0 && BlockType!=SUB_HEAD)
686 LastBlock=BlockType;
687 if (Size==0 || BlockType==ALL_HEAD || NewLhd.HeadType==BlockType ||
688 (NewLhd.HeadType==SUB_HEAD && ReadSubBlock && LastBlock==BlockType))
689 break;
690 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
691 MemRARFile->offset = NextBlockPos;
692 #else
693 tseek(ArcPtr, NextBlockPos, SEEK_SET);
694 #endif
695 }
696 }
697
698 BlockHead.HeadCRC=NewLhd.HeadCRC;
699 BlockHead.HeadType=NewLhd.HeadType;
700 BlockHead.Flags=NewLhd.Flags;
701 BlockHead.HeadSize=NewLhd.HeadSize;
702 BlockHead.DataSize=NewLhd.PackSize;
703
704 if (BlockType!=NewLhd.HeadType) BlockType=ALL_HEAD;
705
706 if((FILE_HEAD == BlockType) && (Size>0))
707 {
708 NewLhd.NameSize=Min(NewLhd.NameSize,sizeof(ArcFileName)-1);
709 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
710 tread(MemRARFile, ArcFileName, NewLhd.NameSize);
711 #else
712 tread(ArcPtr,ArcFileName,NewLhd.NameSize);
713 #endif
714 ArcFileName[NewLhd.NameSize]=0;
715 #ifdef _DEBUG_LOG
716 if (NewLhd.HeadCRC!=(UWORD)~CalcCRC32(HeaderCRC,(UBYTE*)&ArcFileName[0],
717 NewLhd.NameSize))
718 {
719 debug_log("file header broken");
720 }
721 #endif
722 Size+=NewLhd.NameSize;
723 } else
724 {
725 memcpy(&NewLhd,&SaveFileHead,sizeof(NewLhd));
726 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
727 MemRARFile->offset = CurBlockPos;
728 #else
729 tseek(ArcPtr,CurBlockPos,SEEK_SET);
730 #endif
731 }
732
733
734 return(Size);
735 }
736
737
738 int ReadHeader(int BlockType)
739 {
740 int Size = 0;
741 unsigned char Header[64];
742 switch(BlockType)
743 {
744 case MAIN_HEAD:
745 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
746 Size=tread(MemRARFile, Header, SIZEOF_NEWMHD);
747 #else
748 Size=tread(ArcPtr,Header,SIZEOF_NEWMHD);
749 #endif
750 NewMhd.HeadCRC=(unsigned short)GetHeaderWord(0);
751 NewMhd.HeadType=GetHeaderByte(2);
752 NewMhd.Flags=(unsigned short)GetHeaderWord(3);
753 NewMhd.HeadSize=(unsigned short)GetHeaderWord(5);
754 NewMhd.Reserved=(unsigned short)GetHeaderWord(7);
755 NewMhd.Reserved1=GetHeaderDword(9);
756 HeaderCRC=CalcCRC32(0xFFFFFFFFL,&Header[2],SIZEOF_NEWMHD-2);
757 break;
758 case FILE_HEAD:
759 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
760 Size=tread(MemRARFile, Header, SIZEOF_NEWLHD);
761 #else
762 Size=tread(ArcPtr,Header,SIZEOF_NEWLHD);
763 #endif
764 NewLhd.HeadCRC=(unsigned short)GetHeaderWord(0);
765 NewLhd.HeadType=GetHeaderByte(2);
766 NewLhd.Flags=(unsigned short)GetHeaderWord(3);
767 NewLhd.HeadSize=(unsigned short)GetHeaderWord(5);
768 NewLhd.PackSize=GetHeaderDword(7);
769 NewLhd.UnpSize=GetHeaderDword(11);
770 NewLhd.HostOS=GetHeaderByte(15);
771 NewLhd.FileCRC=GetHeaderDword(16);
772 NewLhd.FileTime=GetHeaderDword(20);
773 NewLhd.UnpVer=GetHeaderByte(24);
774 NewLhd.Method=GetHeaderByte(25);
775 NewLhd.NameSize=(unsigned short)GetHeaderWord(26);
776 NewLhd.FileAttr=GetHeaderDword(28);
777 HeaderCRC=CalcCRC32(0xFFFFFFFFL,&Header[2],SIZEOF_NEWLHD-2);
778 break;
779
780 #ifdef _DEBUG_LOG
781 case COMM_HEAD: /* log errors in case of debug */
782 debug_log("Comment headers not supported! "\
783 "Please create archives without comments.");
784 break;
785 case PROTECT_HEAD:
786 debug_log("Protected headers not supported!");
787 break;
788 case ALL_HEAD:
789 debug_log("ShortBlockHeader not supported!");
790 break;
791 default:
792 debug_log("Unknown//unsupported !");
793 #else
794 default: /* else do nothing */
795 break;
796 #endif
797 }
798 return(Size);
799 }
800
801 /* **************************************************************************
802 ****************************************************************************
803 ****************************************************************************
804 ************************************************************************** */
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822 /* **************************************************************************
823 ****************************************************************************
824 ****************************************************************************
825 ****************************************************************************
826 ******* *******
827 ******* *******
828 ******* *******
829 ******* E X T R A C T L O O P *******
830 ******* *******
831 ******* *******
832 ******* *******
833 ****************************************************************************
834 ****************************************************************************
835 ****************************************************************************
836 ************************************************************************** */
837
838
839 int IsArchive(void)
840 {
841 #ifdef _DEBUG_LOG
842 int str_offs; /* used for debug-strings */
843 char DebugMsg[500]; /* used to compose debug msg */
844 #endif
845
846 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
847 if (tread(MemRARFile, MarkHead.Mark, SIZEOF_MARKHEAD) != SIZEOF_MARKHEAD)
848 return(FALSE);
849 #else
850 if (tread(ArcPtr,MarkHead.Mark,SIZEOF_MARKHEAD)!=SIZEOF_MARKHEAD)
851 return(FALSE);
852 #endif
853 /* Old archive => error */
854 if (MarkHead.Mark[0]==0x52 && MarkHead.Mark[1]==0x45 &&
855 MarkHead.Mark[2]==0x7e && MarkHead.Mark[3]==0x5e)
856 {
857 debug_log("Attention: format as OLD detected! Can't handel archive!");
858 }
859 else
860 /* original RAR v2.0 */
861 if ((MarkHead.Mark[0]==0x52 && MarkHead.Mark[1]==0x61 && /* original */
862 MarkHead.Mark[2]==0x72 && MarkHead.Mark[3]==0x21 && /* RAR header*/
863 MarkHead.Mark[4]==0x1a && MarkHead.Mark[5]==0x07 &&
864 MarkHead.Mark[6]==0x00) ||
865 /* "UniquE!" - header */
866 (MarkHead.Mark[0]=='U' && MarkHead.Mark[1]=='n' && /* "UniquE!" */
867 MarkHead.Mark[2]=='i' && MarkHead.Mark[3]=='q' && /* header */
868 MarkHead.Mark[4]=='u' && MarkHead.Mark[5]=='E' &&
869 MarkHead.Mark[6]=='!'))
870
871 {
872 if (ReadHeader(MAIN_HEAD)!=SIZEOF_NEWMHD)
873 return(FALSE);
874 } else
875 {
876
877 #ifdef _DEBUG_LOG
878 /* sorry for this ugly code, but older SunOS gcc compilers don't */
879 /* support white spaces within strings */
880 str_offs = sprintf(DebugMsg, "unknown archive type (only plain RAR ");
881 str_offs += sprintf(DebugMsg + str_offs, "supported (normal and solid ");
882 str_offs += sprintf(DebugMsg + str_offs, "archives), SFX and Volumes ");
883 str_offs += sprintf(DebugMsg + str_offs, "are NOT supported!)");
884
885 debug_log(DebugMsg);
886 #endif
887
888 }
889
890
891 MainHeadSize=SIZEOF_NEWMHD;
892
893 return(TRUE);
894 }
895
896
897 BOOL ExtrFile(void)
898 {
899 BOOL ReturnCode=TRUE;
900 FileFound=FALSE; /* no file found by default */
901
902 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
903 MemRARFile->offset = 0; /* start reading from offset 0 */
904 if (!IsArchive())
905 {
906 debug_log("Not a RAR file");
907 return FALSE; /* error => exit! */
908 }
909
910 #else
911 /* open and identify archive */
912 if ((ArcPtr=fopen(ArcName,READBINARY))!=NULL)
913 {
914 if (!IsArchive())
915 {
916 debug_log("Not a RAR file");
917 fclose(ArcPtr);
918 ArcPtr = NULL;
919 return FALSE; /* error => exit! */
920 }
921 } else
922 {
923 debug_log("Error opening file.");
924 return FALSE;
925 }
926 #endif
927
928
929 if ((UnpMemory=malloc(UNP_MEMORY))==NULL)
930 {
931 debug_log("Can't allocate memory for decompression!");
932 return FALSE;
933 }
934
935 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
936 MemRARFile->offset+=NewMhd.HeadSize-MainHeadSize;
937 #else
938 tseek(ArcPtr,NewMhd.HeadSize-MainHeadSize,SEEK_CUR);
939 #endif
940
941 /* do while file is not extracted and there's no error */
942 do
943 {
944
945 if (ReadBlock(FILE_HEAD | READSUBBLOCK) <= 0) /* read name of the next */
946 { /* file within the RAR archive */
947 /*
948 *
949 * 21.11.2000 UnQ There's a problem with some linux distros when a file
950 * can not be found in an archive.
951 *
952 * debug_log("Couldn't read next filename from archive (I/O error).");
953 *
954 */
955 ReturnCode=FALSE;
956 break; /* error, file not found in */
957 } /* archive or I/O error */
958 if (BlockHead.HeadType==SUB_HEAD)
959 {
960 debug_log("Sorry, sub-headers not supported.");
961 ReturnCode=FALSE;
962 break; /* error => exit */
963 }
964
965
966 if(TRUE == (FileFound=(stricomp(ArgName, ArcFileName) == 0)))
967 /* *** file found! *** */
968 {
969 {
970 temp_output_buffer=malloc(NewLhd.UnpSize);/* allocate memory for the*/
971 }
972 *temp_output_buffer_offset=0; /* file. The default offset */
973 /* within the buffer is 0 */
974
975 if(temp_output_buffer == NULL)
976 {
977 debug_log("can't allocate memory for the file decompression");
978 ReturnCode=FALSE;
979 break; /* error, can't extract file! */
980 }
981
982
983 }
984
985 /* in case of a solid archive, we need to decompress any single file till
986 * we have found the one we are looking for. In case of normal archives
987 * (recommended!!), we skip the files until we are sure that it is the
988 * one we want.
989 */
990 if((NewMhd.Flags & 0x08) || FileFound)
991 {
992 if (NewLhd.UnpVer<13 || NewLhd.UnpVer>UNP_VER)
993 {
994 debug_log("unknown compression method");
995 ReturnCode=FALSE;
996 break; /* error, can't extract file! */
997 }
998
999 CurUnpRead=CurUnpWrite=0;
1000 if ((*Password!=0) && (NewLhd.Flags & LHD_PASSWORD))
1001 Encryption=NewLhd.UnpVer;
1002 else
1003 Encryption=0;
1004 if (Encryption) SetCryptKeys(Password);
1005
1006 UnpPackedSize=NewLhd.PackSize;
1007 DestUnpSize=NewLhd.UnpSize;
1008
1009 if (NewLhd.Method==0x30)
1010 {
1011 UnstoreFile();
1012 } else
1013 {
1014 Unpack(UnpMemory);
1015 }
1016
1017
1018
1019 #ifdef _DO_CRC32_CHECK /* calculate CRC32 */
1020 if((UBYTE*)temp_output_buffer != NULL)
1021 {
1022 if(NewLhd.FileCRC!=~CalcCRC32(0xFFFFFFFFL,
1023 (UBYTE*)temp_output_buffer,
1024 NewLhd.UnpSize))
1025 {
1026 debug_log("CRC32 error - file couldn't be decompressed correctly!");
1027 ReturnCode=FALSE;
1028 break; /* error, can't extract file! */
1029 }
1030 }
1031 #endif
1032
1033 }
1034
1035 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1036 MemRARFile->offset = NextBlockPos;
1037 #else
1038 if (ArcPtr!=NULL) tseek(ArcPtr,NextBlockPos,SEEK_SET);
1039 #endif
1040 } while(stricomp(ArgName, ArcFileName) != 0);/* exit if file is extracted */
1041
1042 /* free memory, clear password and close archive */
1043 free(UnpMemory);
1044 UnpMemory=NULL;
1045 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1046 if (ArcPtr!=NULL){
1047 fclose(ArcPtr);
1048 ArcPtr = NULL;
1049 }
1050 #endif
1051
1052 return ReturnCode; /* file extracted successful! */
1053 }
1054
1055 /* **************************************************************************
1056 ****************************************************************************
1057 ****************************************************************************
1058 ************************************************************************** */
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077 /* **************************************************************************
1078 ****************************************************************************
1079 ****************************************************************************
1080 ****************************************************************************
1081 ******* *******
1082 ******* *******
1083 ******* *******
1084 ******* G L O B A L F U N C T I O N S *******
1085 ******* *******
1086 ******* *******
1087 ******* *******
1088 ****************************************************************************
1089 ****************************************************************************
1090 ****************************************************************************
1091 ************************************************************************** */
1092
1093
1094 int tread(void *stream,void *buf,unsigned len)
1095 {
1096 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1097
1098 if(((MemRARFile->offset + len) > MemRARFile->size) || (len == 0))
1099 return 0;
1100
1101 memcpy(buf,
1102 (BYTE*)(((MemoryFile*)stream)->data)+((MemoryFile*)stream)->offset,
1103 len % ((((MemoryFile*)stream)->size) - 1));
1104
1105 MemRARFile->offset+=len; /* update read pointer */
1106 return len % ((((MemoryFile*)stream)->size) - 1);
1107 #else
1108 return(fread(buf,1,len,(FILE*)stream));
1109 #endif
1110 }
1111
1112
1113 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1114 int tseek(void *stream,long offset,int fromwhere)
1115 {
1116 return(fseek((FILE*)stream,offset,fromwhere));
1117 }
1118 #endif
1119
1120
1121 char* strupper(char *Str)
1122 {
1123 char *ChPtr;
1124 for (ChPtr=Str;*ChPtr;ChPtr++)
1125 *ChPtr=(char)toupper(*ChPtr);
1126 return(Str);
1127 }
1128
1129
1130 int stricomp(char *Str1,char *Str2)
1131 /* compare strings without regard of '\' and '/' */
1132 {
1133 char S1[512],S2[512];
1134 char *chptr;
1135
1136 strncpy(S1,Str1,sizeof(S1));
1137 strncpy(S2,Str2,sizeof(S2));
1138
1139 while((chptr = strchr(S1, '\\')) != NULL) /* ignore backslash */
1140 {
1141 *chptr = '_';
1142 }
1143
1144 while((chptr = strchr(S2, '\\')) != NULL) /* ignore backslash */
1145 {
1146 *chptr = '_';
1147 }
1148
1149 while((chptr = strchr(S1, '/')) != NULL) /* ignore slash */
1150 {
1151 *chptr = '_';
1152 }
1153
1154 while((chptr = strchr(S2, '/')) != NULL) /* ignore slash */
1155 {
1156 *chptr = '_';
1157 }
1158
1159 return(strcmp(strupper(S1),strupper(S2)));
1160 }
1161
1162
1163 /* **************************************************************************
1164 ****************************************************************************
1165 ****************************************************************************
1166 ************************************************************************** */
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185 /* **************************************************************************
1186 ****************************************************************************
1187 ****************************************************************************
1188 ****************************************************************************
1189 ******* *******
1190 ******* *******
1191 ******* *******
1192 ******* U N P A C K C O D E *******
1193 ******* *******
1194 ******* *******
1195 ******* *******
1196 ****************************************************************************
1197 ****************************************************************************
1198 ****************************************************************************
1199 ************************************************************************** */
1200
1201
1202 /* *****************************
1203 * ** unpack stored RAR files **
1204 * *****************************/
1205
1206 BOOL UnstoreFile(void)
1207 {
1208 if ((long)(*temp_output_buffer_offset=UnpRead(temp_output_buffer,
1209 NewLhd.UnpSize))==-1)
1210 {
1211 debug_log("Read error of stored file!");
1212 return FALSE;
1213 }
1214 return TRUE;
1215 }
1216
1217
1218
1219
1220 /* ****************************************
1221 * ** RAR decompression code starts here **
1222 * ****************************************/
1223
1224 #define NC 298 /* alphabet = {0,1,2, .,NC - 1} */
1225 #define DC 48
1226 #define RC 28
1227 #define BC 19
1228 #define MC 257
1229
1230 enum {CODE_HUFFMAN=0,CODE_LZ=1,CODE_LZ2=2,CODE_REPEATLZ=3,CODE_CACHELZ=4,
1231 CODE_STARTFILE=5,CODE_ENDFILE=6,CODE_STARTMM=8,CODE_ENDMM=7,
1232 CODE_MMDELTA=9};
1233
1234 struct AudioVariables
1235 {
1236 int K1,K2,K3,K4,K5;
1237 int D1,D2,D3,D4;
1238 int LastDelta;
1239 unsigned int Dif[11];
1240 unsigned int ByteCount;
1241 int LastChar;
1242 };
1243
1244
1245 #define NC 298 /* alphabet = {0, 1, 2, ..., NC - 1} */
1246 #define DC 48
1247 #define RC 28
1248 #define BC 19
1249 #define MC 257
1250
1251
1252 struct AudioVariables AudV[4];
1253
1254 #define GetBits() \
1255 BitField = ( ( ( (UDWORD)InBuf[InAddr] << 16 ) | \
1256 ( (UWORD) InBuf[InAddr+1] << 8 ) | \
1257 ( InBuf[InAddr+2] ) ) \
1258 >> (8-InBit) ) & 0xffff;
1259
1260
1261 #define AddBits(Bits) \
1262 InAddr += ( InBit + (Bits) ) >> 3; \
1263 InBit = ( InBit + (Bits) ) & 7;
1264
1265 static unsigned char *UnpBuf;
1266 static unsigned int BitField;
1267 static unsigned int Number;
1268
1269 unsigned char InBuf[8192]; /* input read buffer */
1270
1271 unsigned char UnpOldTable[MC*4];
1272
1273 unsigned int InAddr,InBit,ReadTop;
1274
1275 unsigned int LastDist,LastLength;
1276 static unsigned int Length,Distance;
1277
1278 unsigned int OldDist[4],OldDistPtr;
1279
1280
1281 struct LitDecode
1282 {
1283 unsigned int MaxNum;
1284 unsigned int DecodeLen[16];
1285 unsigned int DecodePos[16];
1286 unsigned int DecodeNum[NC];
1287 } LD;
1288
1289 struct DistDecode
1290 {
1291 unsigned int MaxNum;
1292 unsigned int DecodeLen[16];
1293 unsigned int DecodePos[16];
1294 unsigned int DecodeNum[DC];
1295 } DD;
1296
1297 struct RepDecode
1298 {
1299 unsigned int MaxNum;
1300 unsigned int DecodeLen[16];
1301 unsigned int DecodePos[16];
1302 unsigned int DecodeNum[RC];
1303 } RD;
1304
1305 struct MultDecode
1306 {
1307 unsigned int MaxNum;
1308 unsigned int DecodeLen[16];
1309 unsigned int DecodePos[16];
1310 unsigned int DecodeNum[MC];
1311 } MD[4];
1312
1313 struct BitDecode
1314 {
1315 unsigned int MaxNum;
1316 unsigned int DecodeLen[16];
1317 unsigned int DecodePos[16];
1318 unsigned int DecodeNum[BC];
1319 } BD;
1320
1321 static struct MultDecode *MDPtr[4]={&MD[0],&MD[1],&MD[2],&MD[3]};
1322
1323 int UnpAudioBlock,UnpChannels,CurChannel,ChannelDelta;
1324
1325
1326 void Unpack(unsigned char *UnpAddr)
1327 /* *** 38.3% of all CPU time is spent within this function!!! */
1328 {
1329 static unsigned char LDecode[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,
1330 40,48,56,64,80,96,112,128,160,192,224};
1331 static unsigned char LBits[]= {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,
1332 3,3,3,4,4,4,4,5,5,5,5};
1333 static int DDecode[]={0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,
1334 512,768,1024,1536,2048,3072,4096,6144,8192,12288,
1335 16384,24576,32768U,49152U,65536,98304,131072,196608,
1336 262144,327680,393216,458752,524288,589824,655360,
1337 720896,786432,851968,917504,983040};
1338 static unsigned char DBits[]= {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,
1339 9,10,10,11,11,12,12,13,13,14,14,15,15,16,
1340 16,16,16,16,16,16,16,16,16,16,16,16,16};
1341 static unsigned char SDDecode[]={0,4,8,16,32,64,128,192};
1342 static unsigned char SDBits[]={2,2,3, 4, 5, 6, 6, 6};
1343 unsigned int Bits;
1344
1345
1346 UnpBuf=UnpAddr; /* UnpAddr is a pointer to the */
1347 UnpInitData(); /* unpack buffer */
1348 UnpReadBuf(1);
1349 if (!(NewLhd.Flags & LHD_SOLID))
1350 ReadTables();
1351 DestUnpSize--;
1352
1353 while (DestUnpSize>=0)
1354 {
1355 UnpPtr&=MAXWINMASK;
1356
1357 if (InAddr>sizeof(InBuf)-30)
1358 UnpReadBuf(0);
1359 if (((WrPtr-UnpPtr) & MAXWINMASK)<270 && WrPtr!=UnpPtr)
1360 {
1361
1362
1363 if (FileFound)
1364 {
1365
1366 if (UnpPtr<WrPtr)
1367 {
1368 if((*temp_output_buffer_offset + UnpPtr) > NewLhd.UnpSize)
1369 {
1370 debug_log("Fatal! Buffer overrun during decompression!");
1371 DestUnpSize=-1;
1372
1373 } else
1374 {
1375 /* copy extracted data to output buffer */
1376 memcpy(temp_output_buffer + *temp_output_buffer_offset,
1377 &UnpBuf[WrPtr], (0-WrPtr) & MAXWINMASK);
1378 /* update offset within buffer */
1379 *temp_output_buffer_offset+= (0-WrPtr) & MAXWINMASK;
1380 /* copy extracted data to output buffer */
1381 memcpy(temp_output_buffer + *temp_output_buffer_offset, UnpBuf,
1382 UnpPtr);
1383 /* update offset within buffer */
1384 *temp_output_buffer_offset+=UnpPtr;
1385 }
1386 } else
1387 {
1388 if((*temp_output_buffer_offset + (UnpPtr-WrPtr)) > NewLhd.UnpSize)
1389 {
1390 debug_log("Fatal! Buffer overrun during decompression!");
1391 DestUnpSize=-1;
1392 } else
1393 {
1394 /* copy extracted data to output buffer */
1395 memcpy(temp_output_buffer + *temp_output_buffer_offset,
1396 &UnpBuf[WrPtr], UnpPtr-WrPtr);
1397 *temp_output_buffer_offset+=UnpPtr-WrPtr; /* update offset within buffer */
1398 }
1399
1400 }
1401 }
1402
1403 WrPtr=UnpPtr;
1404 }
1405
1406 if (UnpAudioBlock)
1407 {
1408 DecodeNumber((struct Decode *)MDPtr[CurChannel]);
1409 if (Number==256)
1410 {
1411 ReadTables();
1412 continue;
1413 }
1414 UnpBuf[UnpPtr++]=DecodeAudio(Number);
1415 if (++CurChannel==UnpChannels)
1416 CurChannel=0;
1417 DestUnpSize--;
1418 continue;
1419 }
1420
1421 DecodeNumber((struct Decode *)&LD);
1422 if (Number<256)
1423 {
1424 UnpBuf[UnpPtr++]=(UBYTE)Number;
1425 DestUnpSize--;
1426 continue;
1427 }
1428 if (Number>269)
1429 {
1430 Length=LDecode[Number-=270]+3;
1431 if ((Bits=LBits[Number])>0)
1432 {
1433 GetBits();
1434 Length+=BitField>>(16-Bits);
1435 AddBits(Bits);
1436 }
1437
1438 DecodeNumber((struct Decode *)&DD);
1439 Distance=DDecode[Number]+1;
1440 if ((Bits=DBits[Number])>0)
1441 {
1442 GetBits();
1443 Distance+=BitField>>(16-Bits);
1444 AddBits(Bits);
1445 }
1446
1447 if (Distance>=0x40000L)
1448 Length++;
1449
1450 if (Distance>=0x2000)
1451 Length++;
1452
1453 LastDist=OldDist[OldDistPtr++ & 3]=Distance;
1454 DestUnpSize-=(LastLength=Length);
1455 while (Length--)
1456 {
1457 UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
1458 UnpPtr=(UnpPtr+1) & MAXWINMASK;
1459 }
1460
1461 continue;
1462 }
1463 if (Number==269)
1464 {
1465 ReadTables();
1466 continue;
1467 }
1468 if (Number==256)
1469 {
1470 Length=LastLength;
1471 Distance=LastDist;
1472 LastDist=OldDist[OldDistPtr++ & 3]=Distance;
1473 DestUnpSize-=(LastLength=Length);
1474 while (Length--)
1475 {
1476 UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
1477 UnpPtr=(UnpPtr+1) & MAXWINMASK;
1478 }
1479 continue;
1480 }
1481 if (Number<261)
1482 {
1483 Distance=OldDist[(OldDistPtr-(Number-256)) & 3];
1484 DecodeNumber((struct Decode *)&RD);
1485 Length=LDecode[Number]+2;
1486 if ((Bits=LBits[Number])>0)
1487 {
1488 GetBits();
1489 Length+=BitField>>(16-Bits);
1490 AddBits(Bits);
1491 }
1492 if (Distance>=0x40000)
1493 Length++;
1494 if (Distance>=0x2000)
1495 Length++;
1496 if (Distance>=0x101)
1497 Length++;
1498 LastDist=OldDist[OldDistPtr++ & 3]=Distance;
1499 DestUnpSize-=(LastLength=Length);
1500 while (Length--)
1501 {
1502 UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
1503 UnpPtr=(UnpPtr+1) & MAXWINMASK;
1504 }
1505 continue;
1506 }
1507 if (Number<270)
1508 {
1509 Distance=SDDecode[Number-=261]+1;
1510 if ((Bits=SDBits[Number])>0)
1511 {
1512 GetBits();
1513 Distance+=BitField>>(16-Bits);
1514 AddBits(Bits);
1515 }
1516 Length=2;
1517 LastDist=OldDist[OldDistPtr++ & 3]=Distance;
1518 DestUnpSize-=(LastLength=Length);
1519 while (Length--)
1520 {
1521 UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
1522 UnpPtr=(UnpPtr+1) & MAXWINMASK;
1523 }
1524 continue;
1525 }
1526 }
1527 ReadLastTables();
1528
1529 if (FileFound) /* flush buffer */
1530 {
1531
1532 if (UnpPtr<WrPtr)
1533 {
1534 if((*temp_output_buffer_offset + UnpPtr) > NewLhd.UnpSize)
1535 {
1536 debug_log("Fatal! Buffer overrun during decompression!");
1537 DestUnpSize=-1;
1538 } else
1539 {
1540 /* copy extracted data to output buffer */
1541 memcpy(temp_output_buffer + *temp_output_buffer_offset, &UnpBuf[WrPtr],
1542 (0-WrPtr) & MAXWINMASK);
1543 /* update offset within buffer */
1544 *temp_output_buffer_offset+= (0-WrPtr) & MAXWINMASK;
1545 /* copy extracted data to output buffer */
1546 memcpy(temp_output_buffer + *temp_output_buffer_offset, UnpBuf, UnpPtr);
1547 /* update offset within buffer */
1548 *temp_output_buffer_offset+=UnpPtr;
1549 }
1550 } else
1551 {
1552 if((*temp_output_buffer_offset + (UnpPtr-WrPtr)) > NewLhd.UnpSize)
1553 {
1554 debug_log("Fatal! Buffer overrun during decompression!");
1555 DestUnpSize=-1;
1556 } else
1557 {
1558 /* copy extracted data to output buffer */
1559 memcpy(temp_output_buffer + *temp_output_buffer_offset, &UnpBuf[WrPtr],
1560 UnpPtr-WrPtr);
1561 /* update offset within buffer */
1562 *temp_output_buffer_offset+=UnpPtr-WrPtr;
1563 }
1564 }
1565 }
1566
1567 WrPtr=UnpPtr;
1568 }
1569
1570
1571 unsigned int UnpRead(unsigned char *Addr,unsigned int Count)
1572 {
1573 int RetCode=0;
1574 unsigned int I,ReadSize,TotalRead=0;
1575 unsigned char *ReadAddr;
1576 ReadAddr=Addr;
1577 while (Count > 0)
1578 {
1579 ReadSize=(unsigned int)((Count>(unsigned long)UnpPackedSize) ?
1580 UnpPackedSize : Count);
1581 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1582 if(MemRARFile->data == NULL)
1583 return(0);
1584 RetCode=tread(MemRARFile, ReadAddr, ReadSize);
1585 #else
1586 if (ArcPtr==NULL)
1587 return(0);
1588 RetCode=tread(ArcPtr,ReadAddr,ReadSize);
1589 #endif
1590 CurUnpRead+=RetCode;
1591 ReadAddr+=RetCode;
1592 TotalRead+=RetCode;
1593 Count-=RetCode;
1594 UnpPackedSize-=RetCode;
1595 break;
1596 }
1597 if (RetCode!= -1)
1598 {
1599 RetCode=TotalRead;
1600 if (Encryption)
1601 {
1602 if (Encryption<20)
1603 {
1604 debug_log("Old Crypt() not supported!");
1605 }
1606 else
1607 {
1608 for (I=0;I<(unsigned int)RetCode;I+=16)
1609 DecryptBlock(&Addr[I]);
1610 }
1611 }
1612 }
1613 return(RetCode);
1614 }
1615
1616
1617 void UnpReadBuf(int FirstBuf)
1618 {
1619 int RetCode;
1620 if (FirstBuf)
1621 {
1622 ReadTop=UnpRead(InBuf,sizeof(InBuf));
1623 InAddr=0;
1624 }
1625 else
1626 {
1627 memcpy(InBuf,&InBuf[sizeof(InBuf)-32],32);
1628 InAddr&=0x1f;
1629 RetCode=UnpRead(&InBuf[32],sizeof(InBuf)-32);
1630 if (RetCode>0)
1631 ReadTop=RetCode+32;
1632 else
1633 ReadTop=InAddr;
1634 }
1635 }
1636
1637
1638 void ReadTables(void)
1639 {
1640 UBYTE BitLength[BC];
1641 unsigned char Table[MC*4];
1642 int TableSize,N,I;
1643 if (InAddr>sizeof(InBuf)-25)
1644 UnpReadBuf(0);
1645 GetBits();
1646 UnpAudioBlock=(BitField & 0x8000);
1647
1648 if (!(BitField & 0x4000))
1649 memset(UnpOldTable,0,sizeof(UnpOldTable));
1650 AddBits(2);
1651
1652
1653 if (UnpAudioBlock)
1654 {
1655 UnpChannels=((BitField>>12) & 3)+1;
1656 if (CurChannel>=UnpChannels)
1657 CurChannel=0;
1658 AddBits(2);
1659 TableSize=MC*UnpChannels;
1660 }
1661 else
1662 TableSize=NC+DC+RC;
1663
1664
1665 for (I=0;I<BC;I++)
1666 {
1667 GetBits();
1668 BitLength[I]=(UBYTE)(BitField >> 12);
1669 AddBits(4);
1670 }
1671 MakeDecodeTables(BitLength,(struct Decode *)&BD,BC);
1672 I=0;
1673 while (I<TableSize)
1674 {
1675 if (InAddr>sizeof(InBuf)-5)
1676 UnpReadBuf(0);
1677 DecodeNumber((struct Decode *)&BD);
1678 if (Number<16)
1679 Table[I++]=(Number+UnpOldTable[I]) & 0xf;
1680 else
1681 if (Number==16)
1682 {
1683 GetBits();
1684 N=(BitField >> 14)+3;
1685 AddBits(2);
1686 while (N-- > 0 && I<TableSize)
1687 {
1688 Table[I]=Table[I-1];
1689 I++;
1690 }
1691 }
1692 else
1693 {
1694 if (Number==17)
1695 {
1696 GetBits();
1697 N=(BitField >> 13)+3;
1698 AddBits(3);
1699 }
1700 else
1701 {
1702 GetBits();
1703 N=(BitField >> 9)+11;
1704 AddBits(7);
1705 }
1706 while (N-- > 0 && I<TableSize)
1707 Table[I++]=0;
1708 }
1709 }
1710 if (UnpAudioBlock)
1711 for (I=0;I<UnpChannels;I++)
1712 MakeDecodeTables(&Table[I*MC],(struct Decode *)MDPtr[I],MC);
1713 else
1714 {
1715 MakeDecodeTables(&Table[0],(struct Decode *)&LD,NC);
1716 MakeDecodeTables(&Table[NC],(struct Decode *)&DD,DC);
1717 MakeDecodeTables(&Table[NC+DC],(struct Decode *)&RD,RC);
1718 }
1719 memcpy(UnpOldTable,Table,sizeof(UnpOldTable));
1720 }
1721
1722
1723 static void ReadLastTables(void)
1724 {
1725 if (ReadTop>=InAddr+5)
1726 {
1727 if (UnpAudioBlock)
1728 {
1729 DecodeNumber((struct Decode *)MDPtr[CurChannel]);
1730 if (Number==256)
1731 ReadTables();
1732 }
1733 else
1734 {
1735 DecodeNumber((struct Decode *)&LD);
1736 if (Number==269)
1737 ReadTables();
1738 }
1739 }
1740 }
1741
1742
1743 static void MakeDecodeTables(unsigned char *LenTab,
1744 struct Decode *Dec,
1745 int Size)
1746 {
1747 int LenCount[16],TmpPos[16],I;
1748 long M,N;
1749 memset(LenCount,0,sizeof(LenCount));
1750 for (I=0;I<Size;I++)
1751 LenCount[LenTab[I] & 0xF]++;
1752
1753 LenCount[0]=0;
1754 for (TmpPos[0]=Dec->DecodePos[0]=Dec->DecodeLen[0]=0,N=0,I=1;I<16;I++)
1755 {
1756 N=2*(N+LenCount[I]);
1757 M=N<<(15-I);
1758 if (M>0xFFFF)
1759 M=0xFFFF;
1760 Dec->DecodeLen[I]=(unsigned int)M;
1761 TmpPos[I]=Dec->DecodePos[I]=Dec->DecodePos[I-1]+LenCount[I-1];
1762 }
1763
1764 for (I=0;I<Size;I++)
1765 if (LenTab[I]!=0)
1766 Dec->DecodeNum[TmpPos[LenTab[I] & 0xF]++]=I;
1767 Dec->MaxNum=Size;
1768 }
1769
1770
1771 static void DecodeNumber(struct Decode *Deco)
1772 /* *** 52.6% of all CPU time is spent within this function!!! */
1773 {
1774 unsigned int I;
1775 register unsigned int N;
1776 GetBits();
1777
1778 #ifdef _USE_ASM
1779
1780 #ifdef _WIN_32
1781 __asm {
1782
1783 xor eax, eax
1784 mov eax, BitField // N=BitField & 0xFFFE;
1785 and eax, 0xFFFFFFFE
1786 mov [N], eax
1787 mov edx, [Deco] // EAX=N, EDX=Deco
1788
1789 cmp eax, dword ptr[edx + 8*4 + 4]// if (N<Dec->DecodeLen[8])
1790 jae else_G
1791
1792 cmp eax, dword ptr[edx + 4*4 + 4]// if (N<Dec->DecodeLen[4])
1793 jae else_F
1794
1795
1796 cmp eax, dword ptr[edx + 2*4 + 4]// if (N<Dec->DecodeLen[2])
1797 jae else_C
1798
1799 cmp eax, dword ptr[edx + 1*4 + 4]// if (N<Dec->DecodeLen[1])
1800 jae else_1
1801 mov I, 1 // I=1;
1802 jmp next_1
1803 else_1: // else
1804 mov I, 2 // I=2;
1805 next_1:
1806
1807 jmp next_C
1808 else_C: // else
1809
1810 cmp eax, dword ptr[edx + 3*4 + 4]// if (N<Dec->DecodeLen[3])
1811 jae else_2
1812 mov I, 3 // I=3;
1813 jmp next_2
1814 else_2: // else
1815 mov I, 4 // I=4;
1816 next_2:
1817
1818 next_C: // else
1819
1820 jmp next_F
1821 else_F:
1822
1823
1824 cmp eax, dword ptr[edx + 6*4 + 4]// if (N<Dec->DecodeLen[6])
1825 jae else_E
1826
1827 cmp eax, dword ptr[edx + 5*4 + 4]// if (N<Dec->DecodeLen[5])
1828 jae else_3
1829 mov I, 5 // I=5;
1830 jmp next_3
1831 else_3: // else
1832 mov I, 6 // I=6;
1833 next_3:
1834
1835 jmp next_E
1836 else_E: // else
1837
1838 cmp eax, dword ptr[edx + 7*4 + 4]// if (N<Dec->DecodeLen[7])
1839 jae else_4
1840 mov I, 7 // I=7;
1841 jmp next_4
1842 else_4: // else
1843 mov I, 8 // I=8;
1844 next_4:
1845
1846 next_E:
1847
1848 next_F:
1849
1850 jmp next_G
1851 else_G:
1852
1853 cmp eax, dword ptr[edx + 12*4 + 4] // if (N<Dec->DecodeLen[12])
1854 jae else_D
1855
1856 cmp eax, dword ptr[edx + 10*4 + 4]// if (N<Dec->DecodeLen[10])
1857 jae else_B
1858
1859 cmp eax, dword ptr[edx + 9*4 + 4]// if (N<Dec->DecodeLen[9])
1860 jae else_5
1861 mov I, 9 // I=9;
1862 jmp next_5
1863 else_5: // else
1864 mov I, 10 // I=10;
1865 next_5:
1866
1867 jmp next_B
1868 else_B: // else
1869
1870 cmp eax, dword ptr[edx + 11*4 + 4]// if (N<Dec->DecodeLen[11])
1871 jae else_6
1872 mov I, 11 // I=11;
1873 jmp next_6
1874 else_6: // else
1875 mov I, 12 // I=12;
1876 next_6:
1877
1878 next_B:
1879
1880
1881 jmp next_D
1882 else_D: // else
1883
1884 cmp eax, dword ptr[edx + 14*4 + 4]// if (N<Dec->DecodeLen[14])
1885 jae else_A
1886
1887 cmp eax, dword ptr[edx + 13*4 + 4]// if (N<Dec->DecodeLen[13])
1888 jae else_7
1889 mov I, 13 // I=13;
1890 jmp next_7
1891 else_7: // else
1892 mov I, 14 // I=14;
1893 next_7:
1894
1895 jmp next_A
1896 else_A: // else
1897 mov I, 15 // I=15;
1898 next_A:
1899
1900 next_D:
1901 next_G:
1902 }
1903 #else
1904 __asm__ __volatile__ (
1905 "andl $0xFFFFFFFE, %%eax"
1906 " movl %%eax, %1"
1907 " cmpl 8*4(%%edx), %%eax /* 5379 */"
1908 " jae else_G"
1909 ""
1910 " cmpl 4*4(%%edx), %%eax"
1911 " jae else_F"
1912 ""
1913 " cmpl 2*4(%%edx), %%eax"
1914 " jae else_C"
1915 ""
1916 " cmpl 1*4(%%edx), %%eax"
1917 ""
1918 " jae else_1"
1919 " movl $1, %0"
1920 " jmp next_1"
1921 " else_1: "
1922 " movl $2, %0"
1923 " next_1:"
1924 " "
1925 " jmp next_C"
1926 " else_C: "
1927 ""
1928 " cmpl 3*4(%%edx), %%eax "
1929 " jae else_2"
1930 " movl $3, %0"
1931 " jmp next_2"
1932 " else_2: "
1933 " movl $4, %0"
1934 " next_2:"
1935 ""
1936 " next_C: "
1937 ""
1938 " jmp next_F"
1939 " else_F:"
1940 ""
1941 " cmpl 6*4(%%edx), %%eax"
1942 " jae else_E"
1943 ""
1944 " cmpl 5*4(%%edx), %%eax"
1945 " jae else_3"
1946 " movl $5, %0 "
1947 " jmp next_3"
1948 " else_3: "
1949 " movl $6, %0 "
1950 " next_3:"
1951 ""
1952 " jmp next_E"
1953 " else_E: "
1954 ""
1955 " cmpl 7*4(%%edx), %%eax"
1956 " jae else_4"
1957 " movl $7, %0 "
1958 " jmp next_4"
1959 " else_4: "
1960 " movl $8, %0 "
1961 " next_4:"
1962 ""
1963 " next_E:"
1964 ""
1965 " next_F:"
1966 ""
1967 " jmp next_G"
1968 " else_G:"
1969 ""
1970 " cmpl 12*4(%%edx), %%eax"
1971 " jae else_D"
1972 ""
1973 " cmpl 10*4(%%edx), %%eax"
1974 " jae else_B"
1975 ""
1976 " cmpl 9*4(%%edx), %%eax"
1977 " jae else_5"
1978 " movl $9, %0 "
1979 " jmp next_5"
1980 " else_5: "
1981 " movl $10, %0 "
1982 " next_5:"
1983 ""
1984 " jmp next_B"
1985 " else_B: "
1986 ""
1987 " cmpl 11*4(%%edx), %%eax"
1988 " "
1989 " jae else_6"
1990 " movl $11, %0 "
1991 " jmp next_6"
1992 " else_6: "
1993 " movl $12, %0 "
1994 " next_6:"
1995 ""
1996 " next_B:"
1997 " "
1998 " "
1999 " jmp next_D"
2000 " else_D: "
2001 ""
2002 " cmpl 14*4(%%edx), %%eax"
2003 " jae else_A"
2004 ""
2005 " cmpl 13*4(%%edx), %%eax"
2006 " jae else_7"
2007 " movl $13, %0"
2008 " jmp next_7"
2009 " else_7: "
2010 " movl $14, %0"
2011 " next_7:"
2012 ""
2013 " jmp next_A"
2014 " else_A: "
2015 " movl $15, %0 "
2016 " next_A:"
2017 " "
2018 " next_D: "
2019 " next_G:"
2020 : "=g" (I), "=r"(N)
2021 : "eax" ((long)BitField), "edx"((long)Deco->DecodeLen)
2022 : "memory"
2023 );
2024 #endif /* #ifdef _WIN_32 ... #elif defined _X86_ASM_ */
2025
2026 #else
2027 N=BitField & 0xFFFE;
2028 if (N<Deco->DecodeLen[8]) {
2029 if (N<Deco->DecodeLen[4]) {
2030 if (N<Deco->DecodeLen[2]) {
2031 if (N<Deco->DecodeLen[1])
2032 I=1;
2033 else
2034 I=2;
2035 } else {
2036 if (N<Deco->DecodeLen[3])
2037 I=3;
2038 else
2039 I=4;
2040 }
2041 } else {
2042 if (N<Deco->DecodeLen[6]) {
2043 if (N<Deco->DecodeLen[5])
2044 I=5;
2045 else
2046 I=6;
2047 } else {
2048 if (N<Deco->DecodeLen[7])
2049 I=7;
2050 else
2051 I=8;
2052 }
2053 }
2054 } else {
2055 if (N<Deco->DecodeLen[12]) {
2056 if (N<Deco->DecodeLen[10]) {
2057 if (N<Deco->DecodeLen[9])
2058 I=9;
2059 else
2060 I=10;
2061 } else {
2062 if (N<Deco->DecodeLen[11])
2063 I=11;
2064 else
2065 I=12;
2066 }
2067 } else {
2068 if (N<Deco->DecodeLen[14]) {
2069 if (N<Deco->DecodeLen[13])
2070 I=13;
2071 else
2072 I=14;
2073
2074 } else {
2075 I=15;
2076 }
2077 }
2078
2079 }
2080 #endif
2081
2082 AddBits(I);
2083 if ((N=Deco->DecodePos[I]+((N-Deco->DecodeLen[I-1])>>(16-I)))>=Deco->MaxNum)
2084 N=0;
2085 Number=Deco->DecodeNum[N];
2086 }
2087
2088
2089 void UnpInitData()
2090 {
2091 InAddr=InBit=0;
2092 if (!(NewLhd.Flags & LHD_SOLID))
2093 {
2094 ChannelDelta=CurChannel=0;
2095
2096 #ifdef _USE_ASM
2097
2098 #ifdef _WIN_32 /* Win32 with VisualC */
2099
2100 __asm {
2101 push edi
2102 push eax
2103 push ecx
2104
2105 cld /* increment EDI and ESI */
2106 mov al, 0x00
2107 mov ecx, SIZE AudV
2108 mov edi, Offset AudV
2109 rep stosb /* clear memory */
2110
2111 mov ecx, SIZE OldDist
2112 mov edi, Offset OldDist
2113 rep stosb /* clear memory */
2114
2115 mov ecx, SIZE UnpOldTable
2116 mov edi, Offset UnpOldTable
2117 rep stosb /* clear memory */
2118
2119 pop ecx
2120 pop eax
2121 pop edi
2122
2123
2124 mov [OldDistPtr], 0
2125 mov [LastDist], 0
2126 mov [LastLength], 0
2127 mov [UnpPtr], 0
2128 mov [WrPtr], 0
2129 mov [OldDistPtr], 0
2130 mov [LastLength], 0
2131 mov [LastDist], 0
2132 mov [UnpPtr], 0
2133 mov [WrPtr], 0
2134
2135 }
2136 memset(UnpBuf,0,MAXWINSIZE);
2137
2138
2139 #else /* unix/linux on i386 cpus */
2140 __asm__ __volatile (
2141 " cld /* increment EDI and ESI */"
2142 " movb $0x00, %%al"
2143 " movl %0, %%ecx"
2144 " movl %1, %%edi"
2145 " rep "
2146 " stosb /* clear memory */"
2147 ""
2148 " movl %2, %%ecx"
2149 " mov %3, %%edi"
2150 " rep "
2151 " stosb /* clear memory */"
2152 ""
2153 " movl %4, %%ecx"
2154 " movl %5, %%edi"
2155 " rep "
2156 " stosb /* clear memory */"
2157 ""
2158 " movl $0, (OldDistPtr)"
2159 " movl $0, (LastDist)"
2160 " movl $0, (LastLength)"
2161 " movl $0, (UnpPtr)"
2162 " movl $0, (WrPtr)"
2163 " movl $0, (OldDistPtr)"
2164 " movl $0, (LastLength)"
2165 " movl $0, (LastDist)"
2166 " movl $0, (UnpPtr)"
2167 " movl $0, (WrPtr)"
2168 :
2169 : "m" ((long)sizeof(AudV)),
2170 "m" ((long)AudV),
2171 "m" ((long)sizeof(OldDist)),
2172 "m" ((long)OldDist),
2173 "m" ((long)sizeof(UnpOldTable)),
2174 "m" ((long)UnpOldTable)
2175 : "memory", "edi", "eax", "ecx"
2176 );
2177 memset(UnpBuf,0,MAXWINSIZE);
2178 #endif
2179
2180 #else /* unix/linux on non-i386 cpu */
2181 memset(AudV,0,sizeof(AudV));
2182 memset(OldDist,0,sizeof(OldDist));
2183 OldDistPtr=0;
2184 LastDist=LastLength=0;
2185 memset(UnpBuf,0,MAXWINSIZE);
2186 memset(UnpOldTable,0,sizeof(UnpOldTable));
2187 UnpPtr=WrPtr=0;
2188 #endif
2189
2190 }
2191 }
2192
2193
2194 UBYTE DecodeAudio(int Delta)
2195 {
2196 struct AudioVariables *V;
2197 unsigned int Ch;
2198 unsigned int NumMinDif,MinDif;
2199 int PCh,I;
2200
2201 V=&AudV[CurChannel];
2202 V->ByteCount++;
2203 V->D4=V->D3;
2204 V->D3=V->D2;
2205 V->D2=V->LastDelta-V->D1;
2206 V->D1=V->LastDelta;
2207 PCh=8*V->LastChar+V->K1*V->D1+V->K2*V->D2+
2208 V->K3*V->D3+V->K4*V->D4+V->K5*ChannelDelta;
2209 PCh=(PCh>>3) & 0xFF;
2210
2211 Ch=PCh-Delta;
2212
2213 I=((signed char)Delta)<<3;
2214
2215 V->Dif[0]+=abs(I);
2216 V->Dif[1]+=abs(I-V->D1);
2217 V->Dif[2]+=abs(I+V->D1);
2218 V->Dif[3]+=abs(I-V->D2);
2219 V->Dif[4]+=abs(I+V->D2);
2220 V->Dif[5]+=abs(I-V->D3);
2221 V->Dif[6]+=abs(I+V->D3);
2222 V->Dif[7]+=abs(I-V->D4);
2223 V->Dif[8]+=abs(I+V->D4);
2224 V->Dif[9]+=abs(I-ChannelDelta);
2225 V->Dif[10]+=abs(I+ChannelDelta);
2226
2227 ChannelDelta=V->LastDelta=(signed char)(Ch-V->LastChar);
2228 V->LastChar=Ch;
2229
2230 if ((V->ByteCount & 0x1F)==0)
2231 {
2232 MinDif=V->Dif[0];
2233 NumMinDif=0;
2234 V->Dif[0]=0;
2235 for (I=1;(unsigned int)I<sizeof(V->Dif)/sizeof(V->Dif[0]);I++)
2236 {
2237 if (V->Dif[I]<MinDif)
2238 {
2239 MinDif=V->Dif[I];
2240 NumMinDif=I;
2241 }
2242 V->Dif[I]=0;
2243 }
2244 switch(NumMinDif)
2245 {
2246 case 1:
2247 if (V->K1>=-16)
2248 V->K1--;
2249 break;
2250 case 2:
2251 if (V->K1<16)
2252 V->K1++;
2253 break;
2254 case 3:
2255 if (V->K2>=-16)
2256 V->K2--;
2257 break;
2258 case 4:
2259 if (V->K2<16)
2260 V->K2++;
2261 break;
2262 case 5:
2263 if (V->K3>=-16)
2264 V->K3--;
2265 break;
2266 case 6:
2267 if (V->K3<16)
2268 V->K3++;
2269 break;
2270 case 7:
2271 if (V->K4>=-16)
2272 V->K4--;
2273 break;
2274 case 8:
2275 if (V->K4<16)
2276 V->K4++;
2277 break;
2278 case 9:
2279 if (V->K5>=-16)
2280 V->K5--;
2281 break;
2282 case 10:
2283 if (V->K5<16)
2284 V->K5++;
2285 break;
2286 }
2287 }
2288 return((UBYTE)Ch);
2289 }
2290
2291
2292
2293
2294
2295
2296
2297 /* ***************************************************
2298 * ** CRCCrypt Code - decryption engine starts here **
2299 * ***************************************************/
2300
2301
2302 #define NROUNDS 32
2303
2304 #define rol(x,n) (((x)<<(n)) | ((x)>>(8*sizeof(x)-(n))))
2305 #define ror(x,n) (((x)>>(n)) | ((x)<<(8*sizeof(x)-(n))))
2306
2307 #define substLong(t) ( (UDWORD)SubstTable[(int)t&255] | \
2308 ((UDWORD)SubstTable[(int)(t>> 8)&255]<< 8) | \
2309 ((UDWORD)SubstTable[(int)(t>>16)&255]<<16) | \
2310 ((UDWORD)SubstTable[(int)(t>>24)&255]<<24) )
2311
2312
2313 UDWORD CRCTab[256];
2314
2315 UBYTE SubstTable[256];
2316 UBYTE InitSubstTable[256]={
2317 215, 19,149, 35, 73,197,192,205,249, 28, 16,119, 48,221, 2, 42,
2318 232, 1,177,233, 14, 88,219, 25,223,195,244, 90, 87,239,153,137,
2319 255,199,147, 70, 92, 66,246, 13,216, 40, 62, 29,217,230, 86, 6,
2320 71, 24,171,196,101,113,218,123, 93, 91,163,178,202, 67, 44,235,
2321 107,250, 75,234, 49,167,125,211, 83,114,157,144, 32,193,143, 36,
2322 158,124,247,187, 89,214,141, 47,121,228, 61,130,213,194,174,251,
2323 97,110, 54,229,115, 57,152, 94,105,243,212, 55,209,245, 63, 11,
2324 164,200, 31,156, 81,176,227, 21, 76, 99,139,188,127, 17,248, 51,
2325 207,120,189,210, 8,226, 41, 72,183,203,135,165,166, 60, 98, 7,
2326 122, 38,155,170, 69,172,252,238, 39,134, 59,128,236, 27,240, 80,
2327 131, 3, 85,206,145, 79,154,142,159,220,201,133, 74, 64, 20,129,
2328 224,185,138,103,173,182, 43, 34,254, 82,198,151,231,180, 58, 10,
2329 118, 26,102, 12, 50,132, 22,191,136,111,162,179, 45, 4,148,108,
2330 161, 56, 78,126,242,222, 15,175,146, 23, 33,241,181,190, 77,225,
2331 0, 46,169,186, 68, 95,237, 65, 53,208,253,168, 9, 18,100, 52,
2332 116,184,160, 96,109, 37, 30,106,140,104,150, 5,204,117,112, 84
2333 };
2334
2335 UDWORD Key[4];
2336
2337
2338 void EncryptBlock(UBYTE *Buf)
2339 {
2340 int I;
2341
2342 UDWORD A,B,C,D,T,TA,TB;
2343 #ifdef NON_INTEL_BYTE_ORDER
2344 A=((UDWORD)Buf[0]|((UDWORD)Buf[1]<<8)|((UDWORD)Buf[2]<<16)|
2345 ((UDWORD)Buf[3]<<24))^Key[0];
2346 B=((UDWORD)Buf[4]|((UDWORD)Buf[5]<<8)|((UDWORD)Buf[6]<<16)|
2347 ((UDWORD)Buf[7]<<24))^Key[1];
2348 C=((UDWORD)Buf[8]|((UDWORD)Buf[9]<<8)|((UDWORD)Buf[10]<<16)|
2349 ((UDWORD)Buf[11]<<24))^Key[2];
2350 D=((UDWORD)Buf[12]|((UDWORD)Buf[13]<<8)|((UDWORD)Buf[14]<<16)|
2351 ((UDWORD)Buf[15]<<24))^Key[3];
2352 #else
2353 UDWORD *BufPtr;
2354 BufPtr=(UDWORD *)Buf;
2355 A=BufPtr[0]^Key[0];
2356 B=BufPtr[1]^Key[1];
2357 C=BufPtr[2]^Key[2];
2358 D=BufPtr[3]^Key[3];
2359 #endif
2360 for(I=0;I<NROUNDS;I++)
2361 {
2362 T=((C+rol(D,11))^Key[I&3]);
2363 TA=A^substLong(T);
2364 T=((D^rol(C,17))+Key[I&3]);
2365 TB=B^substLong(T);
2366 A=C;
2367 B=D;
2368 C=TA;
2369 D=TB;
2370 }
2371 #ifdef NON_INTEL_BYTE_ORDER
2372 C^=Key[0];
2373 Buf[0]=(UBYTE)C;
2374 Buf[1]=(UBYTE)(C>>8);
2375 Buf[2]=(UBYTE)(C>>16);
2376 Buf[3]=(UBYTE)(C>>24);
2377 D^=Key[1];
2378 Buf[4]=(UBYTE)D;
2379 Buf[5]=(UBYTE)(D>>8);
2380 Buf[6]=(UBYTE)(D>>16);
2381 Buf[7]=(UBYTE)(D>>24);
2382 A^=Key[2];
2383 Buf[8]=(UBYTE)A;
2384 Buf[9]=(UBYTE)(A>>8);
2385 Buf[10]=(UBYTE)(A>>16);
2386 Buf[11]=(UBYTE)(A>>24);
2387 B^=Key[3];
2388 Buf[12]=(UBYTE)B;
2389 Buf[13]=(UBYTE)(B>>8);
2390 Buf[14]=(UBYTE)(B>>16);
2391 Buf[15]=(UBYTE)(B>>24);
2392 #else
2393 BufPtr[0]=C^Key[0];
2394 BufPtr[1]=D^Key[1];
2395 BufPtr[2]=A^Key[2];
2396 BufPtr[3]=B^Key[3];
2397 #endif
2398 UpdKeys(Buf);
2399 }
2400
2401
2402 void DecryptBlock(UBYTE *Buf)
2403 {
2404 int I;
2405 UBYTE InBuf[16];
2406 UDWORD A,B,C,D,T,TA,TB;
2407 #ifdef NON_INTEL_BYTE_ORDER
2408 A=((UDWORD)Buf[0]|((UDWORD)Buf[1]<<8)|((UDWORD)Buf[2]<<16)|
2409 ((UDWORD)Buf[3]<<24))^Key[0];
2410 B=((UDWORD)Buf[4]|((UDWORD)Buf[5]<<8)|((UDWORD)Buf[6]<<16)|
2411 ((UDWORD)Buf[7]<<24))^Key[1];
2412 C=((UDWORD)Buf[8]|((UDWORD)Buf[9]<<8)|((UDWORD)Buf[10]<<16)|
2413 ((UDWORD)Buf[11]<<24))^Key[2];
2414 D=((UDWORD)Buf[12]|((UDWORD)Buf[13]<<8)|((UDWORD)Buf[14]<<16)|
2415 ((UDWORD)Buf[15]<<24))^Key[3];
2416 #else
2417 UDWORD *BufPtr;
2418 BufPtr=(UDWORD *)Buf;
2419 A=BufPtr[0]^Key[0]; /* xxx may be this can be */
2420 B=BufPtr[1]^Key[1]; /* optimized in assembler */
2421 C=BufPtr[2]^Key[2];
2422 D=BufPtr[3]^Key[3];
2423 #endif
2424 memcpy(InBuf,Buf,sizeof(InBuf));
2425 for(I=NROUNDS-1;I>=0;I--)
2426 {
2427 T=((C+rol(D,11))^Key[I&3]);
2428 TA=A^substLong(T);
2429 T=((D^rol(C,17))+Key[I&3]);
2430 TB=B^substLong(T);
2431 A=C;
2432 B=D;
2433 C=TA;
2434 D=TB;
2435 }
2436 #ifdef NON_INTEL_BYTE_ORDER
2437 C^=Key[0];
2438 Buf[0]=(UBYTE)C;
2439 Buf[1]=(UBYTE)(C>>8);
2440 Buf[2]=(UBYTE)(C>>16);
2441 Buf[3]=(UBYTE)(C>>24);
2442 D^=Key[1];
2443 Buf[4]=(UBYTE)D;
2444 Buf[5]=(UBYTE)(D>>8);
2445 Buf[6]=(UBYTE)(D>>16);
2446 Buf[7]=(UBYTE)(D>>24);
2447 A^=Key[2];
2448 Buf[8]=(UBYTE)A;
2449 Buf[9]=(UBYTE)(A>>8);
2450 Buf[10]=(UBYTE)(A>>16);
2451 Buf[11]=(UBYTE)(A>>24);
2452 B^=Key[3];
2453 Buf[12]=(UBYTE)B;
2454 Buf[13]=(UBYTE)(B>>8);
2455 Buf[14]=(UBYTE)(B>>16);
2456 Buf[15]=(UBYTE)(B>>24);
2457 #else
2458 BufPtr[0]=C^Key[0];
2459 BufPtr[1]=D^Key[1];
2460 BufPtr[2]=A^Key[2];
2461 BufPtr[3]=B^Key[3];
2462 #endif
2463 UpdKeys(InBuf);
2464 }
2465
2466
2467 void UpdKeys(UBYTE *Buf)
2468 {
2469 int I;
2470 for (I=0;I<16;I+=4)
2471 {
2472 Key[0]^=CRCTab[Buf[I]]; /* xxx may be I'll rewrite this */
2473 Key[1]^=CRCTab[Buf[I+1]]; /* in asm for speedup */
2474 Key[2]^=CRCTab[Buf[I+2]];
2475 Key[3]^=CRCTab[Buf[I+3]];
2476 }
2477 }
2478
2479 void SetCryptKeys(char *Password)
2480 {
2481 unsigned int I,J,K,PswLength;
2482 unsigned char N1,N2;
2483 unsigned char Psw[256];
2484
2485 #if !defined _USE_ASM
2486 UBYTE Ch;
2487 #endif
2488
2489 SetOldKeys(Password);
2490
2491 Key[0]=0xD3A3B879L;
2492 Key[1]=0x3F6D12F7L;
2493 Key[2]=0x7515A235L;
2494 Key[3]=0xA4E7F123L;
2495 memset(Psw,0,sizeof(Psw));
2496 strcpy((char *)Psw,Password);
2497 PswLength=strlen(Password);
2498 memcpy(SubstTable,InitSubstTable,sizeof(SubstTable));
2499
2500 for (J=0;J<256;J++)
2501 for (I=0;I<PswLength;I+=2)
2502 {
2503 N2=(unsigned char)CRCTab[(Psw[I+1]+J)&0xFF];
2504 for (K=1, N1=(unsigned char)CRCTab[(Psw[I]-J)&0xFF];
2505 (N1!=N2) && (N1 < 256); /* I had to add "&& (N1 < 256)", */
2506 N1++, K++) /* because the system crashed with */
2507 { /* encrypted RARs */
2508 #ifdef _USE_ASM
2509
2510 #ifdef _WIN_32
2511 __asm {
2512
2513 mov ebx, Offset SubstTable
2514 mov edx, ebx
2515
2516 xor ecx, ecx // read SubstTable[N1]...
2517 mov cl, N1
2518 add ebx, ecx
2519 mov al, byte ptr[ebx]
2520
2521 mov cl, N1 // read SubstTable[(N1+I+K)&0xFF]...
2522 add ecx, I
2523 add ecx, K
2524 and ecx, 0xFF
2525 add edx, ecx
2526 mov ah, byte ptr[edx]
2527
2528 mov byte ptr[ebx], ah // and write back
2529 mov byte ptr[edx], al
2530
2531 }
2532 #else
2533 __asm__ __volatile__ (
2534 " xorl %%ecx, %%ecx"
2535 " movl %2, %%ecx /* ecx = N1 */"
2536 " mov %%ebx, %%edx"
2537 " addl %%ecx, %%ebx"
2538 ""
2539 " addl %0, %%ecx"
2540 " addl %1, %%ecx"
2541 " andl $0x000000FF, %%ecx"
2542 " addl %%ecx, %%edx"
2543 " "
2544 " movb (%%ebx), %%al"
2545 " movb (%%edx), %%ah"
2546 ""
2547 " movb %%ah, (%%ebx) /* and write back */"
2548 " movb %%al, (%%edx)"
2549 : : "g" ((long)I),
2550 "g" ((long)K),
2551 "g" ((long)N1),
2552 "ebx"((long)SubstTable)
2553 : "ecx", "edx"
2554
2555 );
2556 #endif
2557
2558 #else
2559 /* Swap(&SubstTable[N1],&SubstTable[(N1+I+K)&0xFF]); */
2560 Ch=SubstTable[N1];
2561 SubstTable[N1]=SubstTable[(N1+I+K)&0xFF];
2562 SubstTable[(N1+I+K)&0xFF]=Ch;
2563 #endif
2564 }
2565 }
2566 for (I=0;I<PswLength;I+=16)
2567 EncryptBlock(&Psw[I]);
2568 }
2569
2570
2571 void SetOldKeys(char *Password)
2572 {
2573 UDWORD PswCRC;
2574 UBYTE Ch;
2575 PswCRC=CalcCRC32(0xFFFFFFFFL,(UBYTE*)Password,strlen(Password));
2576 OldKey[0]=(UWORD)PswCRC;
2577 OldKey[1]=(UWORD)(PswCRC>>16);
2578 OldKey[2]=OldKey[3]=0;
2579 PN1=PN2=PN3=0;
2580 while ((Ch=*Password)!=0)
2581 {
2582 PN1+=Ch;
2583 PN2^=Ch;
2584 PN3+=Ch;
2585 PN3=(UBYTE)rol(PN3,1);
2586 OldKey[2]^=((UWORD)(Ch^CRCTab[Ch]));
2587 OldKey[3]+=((UWORD)(Ch+(CRCTab[Ch]>>16)));
2588 Password++;
2589 }
2590 }
2591
2592 void InitCRC(void)
2593 {
2594 int I, J;
2595 UDWORD C;
2596 for (I=0;I<256;I++)
2597 {
2598 for (C=I,J=0;J<8;J++)
2599 C=(C & 1) ? (C>>1)^0xEDB88320L : (C>>1);
2600 CRCTab[I]=C;
2601 }
2602 }
2603
2604
2605 UDWORD CalcCRC32(UDWORD StartCRC,UBYTE *Addr,UDWORD Size)
2606 {
2607 unsigned int I;
2608 for (I=0; I<Size; I++)
2609 StartCRC = CRCTab[(UBYTE)StartCRC ^ Addr[I]] ^ (StartCRC >> 8);
2610 return(StartCRC);
2611 }
2612
2613
2614 /* **************************************************************************
2615 ****************************************************************************
2616 ****************************************************************************
2617 ************************************************************************** */
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643 /* **************************************************************************
2644 ****************************************************************************
2645 ****************************************************************************
2646 ****************************************************************************
2647 ******* *******
2648 ******* *******
2649 ******* *******
2650 ******* D E B U G F U N C T I O N S *******
2651 ******* *******
2652 ******* *******
2653 ******* *******
2654 ****************************************************************************
2655 ****************************************************************************
2656 ****************************************************************************
2657 ************************************************************************** */
2658 #ifdef _DEBUG_LOG
2659
2660
2661 /* -- global stuff -------------------------------------------------------- */
2662 char log_file_name[256]; /* file name for the log file */
2663 DWORD debug_start_time; /* starttime of debug */
2664 BOOL debug_started = FALSE; /* debug_log writes only if */
2665 /* this is TRUE */
2666 /* ------------------------------------------------------------------------ */
2667
2668
2669 /* -- global functions ---------------------------------------------------- */
2670 void debug_init_proc(char *file_name)
2671 /* Create/Rewrite a log file */
2672 {
2673 FILE *fp;
2674 char date[] = __DATE__;
2675 char time[] = __TIME__;
2676
2677 debug_start_time = GetTickCount(); /* get start time */
2678 strcpy(log_file_name, file_name); /* save file name */
2679
2680 if((fp = fopen(log_file_name, CREATETEXT)) != NULL)
2681 {
2682 debug_started = TRUE; /* enable debug */
2683 fprintf(fp, "Debug log of UniquE's RARFileLib\n"\
2684 "~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~\n");
2685 fprintf(fp, "(executable compiled on %s at %s)\n\n", date, time);
2686 fclose(fp);
2687 }
2688 }
2689
2690
2691 void debug_log_proc(char *text, char *sourcefile, int sourceline)
2692 /* add a line to the log file */
2693 {
2694 FILE *fp;
2695
2696 if(debug_started == FALSE) return; /* exit if not initialized */
2697
2698 if((fp = fopen(log_file_name, APPENDTEXT)) != NULL) /* append to logfile */
2699
2700 {
2701 fprintf(fp, " %8u ms (line %u in %s):\n - %s\n",
2702 (unsigned int)(GetTickCount() - debug_start_time),
2703 sourceline, sourcefile, text);
2704 fclose(fp);
2705 }
2706 }
2707
2708 /* ------------------------------------------------------------------------ */
2709 #endif
2710 /* **************************************************************************
2711 ****************************************************************************
2712 ****************************************************************************
2713 ************************************************************************** */
2714
2715
2716 /* end of file urarlib.c */