MACE audio support with ffmpeg decoder
[mplayer/greg.git] / unrarlib.c
blob48bece58e0e9cb973ff9710f7ee3878d8b6f4a42
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.
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.
27 ************************************************************************** */
29 /* ***************************************************************************
31 ** UniquE RAR File Library
32 ** The free file lib for the demoscene
33 ** multi-OS version (Win32, Linux and SunOS)
35 *****************************************************************************
37 ** ==> Please configure the program in "unrarlib.h". <==
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)
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.
56 *****************************************************************************
58 ** ==> see the "CHANGES" file to see what's new
60 ************************************************************************** */
62 /* -- include files ------------------------------------------------------- */
63 #include "unrarlib.h" /* include global configuration */
64 /* ------------------------------------------------------------------------ */
68 /* -- global stuff -------------------------------------------------------- */
69 #ifdef _WIN_32
71 #include <windows.h> /* WIN32 definitions */
72 #include <stdio.h>
73 #include <string.h>
76 #define ENABLE_ACCESS
78 #define HOST_OS WIN_32
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
88 #define PATHDIVIDER "\\"
89 #define CPATHDIVIDER '\\'
90 #define MASKALL "*.*"
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"
99 #endif
101 #ifdef _UNIX
103 #include <stdio.h> /* LINUX/UNIX definitions */
104 #include <stdlib.h>
105 #include <ctype.h>
106 #include <string.h>
108 #define ENABLE_ACCESS
110 #define HOST_OS UNIX
112 #define FM_LABEL 0x0000
113 #define FM_DIREC 0x4000
115 #define PATHDIVIDER "/"
116 #define CPATHDIVIDER '/'
117 #define MASKALL "*.*"
119 #define READBINARY "r"
120 #define READTEXT "r"
121 #define UPDATEBINARY "r+"
122 #define CREATEBINARY "w+"
123 #define CREATETEXT "w"
124 #define APPENDTEXT "a"
127 /* emulation of the windows API and data types */
128 /* 20-08-2000 Johannes Winkelmann, jw@tks6.net */
130 typedef long DWORD;
131 typedef short BOOL;
132 #define TRUE 1
133 #define FALSE 0
136 #ifdef _DEBUG_LOG /* define macros for debugging */
137 #include <unistd.h>
138 #include <sys/time.h>
140 DWORD GetTickCount()
142 struct timeval tv;
143 gettimeofday( &tv, 0 );
144 return (tv.tv_usec / 1000);
146 #endif
148 #endif
154 #ifdef _DEBUG_LOG /* define macros for debugging */
156 BOOL debug_log_first_start = TRUE;
158 #define debug_log(a); debug_log_proc(a, __FILE__, __LINE__);
159 #define debug_init(a); debug_init_proc(a);
161 void debug_log_proc(char *text, char *sourcefile, int sourceline);
162 void debug_init_proc(char *file_name);
164 #else
165 #define debug_log(a); /* no debug this time */
166 #define debug_init(a); /* no debug this time */
167 #endif
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
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
191 #define PACK_VER 20 /* version of decompression code*/
192 #define UNP_VER 20
193 #define PROTECT_VER 20
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 };
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
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
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
228 #define LONG_BLOCK 0x8000
229 #define READSUBBLOCK 0x8000
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 };
237 struct MarkHeader
239 UBYTE Mark[7];
243 struct NewMainArchiveHeader
245 UWORD HeadCRC;
246 UBYTE HeadType;
247 UWORD Flags;
248 UWORD HeadSize;
249 UWORD Reserved;
250 UDWORD Reserved1;
254 struct NewFileHeader
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;
272 struct BlockHeader
274 UWORD HeadCRC;
275 UBYTE HeadType;
276 UWORD Flags;
277 UWORD HeadSize;
278 UDWORD DataSize;
282 struct Decode
284 unsigned int MaxNum;
285 unsigned int DecodeLen[16];
286 unsigned int DecodePos[16];
287 unsigned int DecodeNum[2];
291 struct MarkHeader MarkHead;
292 struct NewMainArchiveHeader NewMhd;
293 struct NewFileHeader NewLhd;
294 struct BlockHeader BlockHead;
296 UBYTE *TempMemory; /* temporary unpack-buffer */
297 char *CommMemory;
300 UBYTE *UnpMemory;
301 char ArgName[NM]; /* current file in rar archive */
302 char ArcFileName[NM]; /* file to decompress */
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 */
312 unsigned char *temp_output_buffer; /* extract files to this pointer*/
313 unsigned long *temp_output_buffer_offset; /* size of temp. extract buffer */
315 BOOL FileFound; /* TRUE=use current extracted */
316 /* data FALSE=throw data away, */
317 /* wrong file */
318 int MainHeadSize;
319 long CurBlockPos,NextBlockPos;
321 unsigned long CurUnpRead, CurUnpWrite;
322 long UnpPackedSize;
323 long DestUnpSize;
325 UDWORD HeaderCRC;
326 int Encryption;
328 unsigned int UnpWrSize;
329 unsigned char *UnpWrAddr;
330 unsigned int UnpPtr,WrPtr;
332 unsigned char PN1,PN2,PN3;
333 unsigned short OldKey[4];
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 /* ------------------------------------------------------------------------ */
367 /* -- global functions ---------------------------------------------------- */
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.
380 BOOL retcode = FALSE;
382 #ifdef _DEBUG_LOG
383 int str_offs; /* used for debug-strings */
384 char DebugMsg[500]; /* used to compose debug msg */
386 if(debug_log_first_start)
388 debug_log_first_start=FALSE; /* only create a new log file */
389 debug_init(_DEBUG_LOG_FILE); /* on startup */
392 #endif
394 InitCRC(); /* init some vars */
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 */
405 temp_output_buffer = NULL;
406 temp_output_buffer_offset=size; /* set size of the temp buffer */
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
414 retcode = ExtrFile(); /* unpack file now! */
416 memset(Password,0,sizeof(Password)); /* clear password */
418 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
419 if (ArcPtr!=NULL){
420 fclose(ArcPtr);
421 ArcPtr = NULL;
423 #endif
425 free(UnpMemory); /* free memory */
426 free(TempMemory);
427 free(CommMemory);
428 UnpMemory=NULL;
429 TempMemory=NULL;
430 CommMemory=NULL;
433 if(retcode == FALSE)
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
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!");
450 } else
452 sprintf(DebugMsg, "Extracted %u Bytes.", (unsigned int)*size);
454 debug_log(DebugMsg);
455 #else
457 #endif
458 *(DWORD*)output=(DWORD)temp_output_buffer;/* return pointer for unpacked*/
459 /* data */
461 return retcode;
465 int urarlib_list(void *rarfile, ArchiveList_struct *list)
467 ArchiveList_struct *tmp_List = NULL;
468 int NoOfFilesInArchive = 0; /* number of files in archive */
470 #ifdef _DEBUG_LOG
471 if(debug_log_first_start)
473 debug_log_first_start=FALSE; /* only create a new log file */
474 debug_init(_DEBUG_LOG_FILE); /* on startup */
476 #endif
478 InitCRC(); /* init some vars */
480 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
481 MemRARFile = rarfile; /* assign pointer to RAR file */
482 MemRARFile->offset = 0;
483 if (!IsArchive())
485 debug_log("Not a RAR file");
486 return NoOfFilesInArchive; /* error => exit! */
488 #else
489 /* open and identify archive */
490 if ((ArcPtr=fopen(rarfile,READBINARY))!=NULL)
492 if (!IsArchive())
494 debug_log("Not a RAR file");
495 fclose(ArcPtr);
496 ArcPtr = NULL;
497 return NoOfFilesInArchive; /* error => exit! */
500 else {
501 debug_log("Error opening file.");
502 return NoOfFilesInArchive;
504 #endif
506 if ((UnpMemory=malloc(UNP_MEMORY))==NULL)
508 debug_log("Can't allocate memory for decompression!");
509 return NoOfFilesInArchive;
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)
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)
528 debug_log("Sorry, sub-headers not supported.");
529 break; /* error => exit */
532 if((void*)(*(DWORD*)list) == NULL) /* first entry */
534 tmp_List = malloc(sizeof(ArchiveList_struct));
535 tmp_List->next = NULL;
537 (*(DWORD*)list) = (DWORD)tmp_List;
539 } else /* add entry */
541 tmp_List->next = malloc(sizeof(ArchiveList_struct));
542 tmp_List = (ArchiveList_struct*) tmp_List->next;
543 tmp_List->next = NULL;
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;
558 NoOfFilesInArchive++; /* count files */
560 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
561 MemRARFile->offset = NextBlockPos;
562 #else
563 if (ArcPtr!=NULL) tseek(ArcPtr,NextBlockPos,SEEK_SET);
564 #endif
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;
575 #endif
577 free(UnpMemory); /* free memory */
578 free(TempMemory);
579 free(CommMemory);
580 UnpMemory=NULL;
581 TempMemory=NULL;
582 CommMemory=NULL;
584 return NoOfFilesInArchive;
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.
594 * input: *list pointer to an ArchiveList_struct
595 * output: -
598 void urarlib_freelist(ArchiveList_struct *list)
600 ArchiveList_struct* tmp = list;
602 while ( list ) {
603 tmp = list->next;
604 free( list->item.Name );
605 free( list );
606 list = tmp;
611 /* ------------------------------------------------------------------------ */
629 /****************************************************************************
630 ****************************************************************************
631 ****************************************************************************
632 ****************************************************************************
633 ******* *******
634 ******* *******
635 ******* *******
636 ******* B L O C K I / O *******
637 ******* *******
638 ******* *******
639 ******* *******
640 ****************************************************************************
641 ****************************************************************************
642 ****************************************************************************
643 ****************************************************************************/
647 #define GetHeaderByte(N) Header[N]
649 #define GetHeaderWord(N) (Header[N]+((UWORD)Header[N+1]<<8))
651 #define GetHeaderDword(N) (Header[N]+((UWORD)Header[N+1]<<8)+\
652 ((UDWORD)Header[N+2]<<16)+\
653 ((UDWORD)Header[N+3]<<24))
656 int ReadBlock(int BlockType)
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;
666 while (1)
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)
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);
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
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;
704 if (BlockType!=NewLhd.HeadType) BlockType=ALL_HEAD;
706 if((FILE_HEAD == BlockType) && (Size>0))
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))
719 debug_log("file header broken");
721 #endif
722 Size+=NewLhd.NameSize;
723 } else
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
734 return(Size);
738 int ReadHeader(int BlockType)
740 int Size = 0;
741 unsigned char Header[64];
742 switch(BlockType)
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;
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
798 return(Size);
801 /* **************************************************************************
802 ****************************************************************************
803 ****************************************************************************
804 ************************************************************************** */
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 ************************************************************************** */
839 int IsArchive(void)
841 #ifdef _DEBUG_LOG
842 int str_offs; /* used for debug-strings */
843 char DebugMsg[500]; /* used to compose debug msg */
844 #endif
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)
857 debug_log("Attention: format as OLD detected! Can't handel archive!");
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]=='!'))
872 if (ReadHeader(MAIN_HEAD)!=SIZEOF_NEWMHD)
873 return(FALSE);
874 } else
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!)");
885 debug_log(DebugMsg);
886 #endif
891 MainHeadSize=SIZEOF_NEWMHD;
893 return(TRUE);
897 BOOL ExtrFile(void)
899 BOOL ReturnCode=TRUE;
900 FileFound=FALSE; /* no file found by default */
902 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
903 MemRARFile->offset = 0; /* start reading from offset 0 */
904 if (!IsArchive())
906 debug_log("Not a RAR file");
907 return FALSE; /* error => exit! */
910 #else
911 /* open and identify archive */
912 if ((ArcPtr=fopen(ArcName,READBINARY))!=NULL)
914 if (!IsArchive())
916 debug_log("Not a RAR file");
917 fclose(ArcPtr);
918 ArcPtr = NULL;
919 return FALSE; /* error => exit! */
921 } else
923 debug_log("Error opening file.");
924 return FALSE;
926 #endif
929 if ((UnpMemory=malloc(UNP_MEMORY))==NULL)
931 debug_log("Can't allocate memory for decompression!");
932 return FALSE;
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
941 /* do while file is not extracted and there's no error */
945 if (ReadBlock(FILE_HEAD | READSUBBLOCK) <= 0) /* read name of the next */
946 { /* file within the RAR archive */
949 * 21.11.2000 UnQ There's a problem with some linux distros when a file
950 * can not be found in an archive.
952 * debug_log("Couldn't read next filename from archive (I/O error).");
955 ReturnCode=FALSE;
956 break; /* error, file not found in */
957 } /* archive or I/O error */
958 if (BlockHead.HeadType==SUB_HEAD)
960 debug_log("Sorry, sub-headers not supported.");
961 ReturnCode=FALSE;
962 break; /* error => exit */
966 if(TRUE == (FileFound=(stricomp(ArgName, ArcFileName) == 0)))
967 /* *** file found! *** */
970 temp_output_buffer=malloc(NewLhd.UnpSize);/* allocate memory for the*/
972 *temp_output_buffer_offset=0; /* file. The default offset */
973 /* within the buffer is 0 */
975 if(temp_output_buffer == NULL)
977 debug_log("can't allocate memory for the file decompression");
978 ReturnCode=FALSE;
979 break; /* error, can't extract file! */
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.
990 if((NewMhd.Flags & 0x08) || FileFound)
992 if (NewLhd.UnpVer<13 || NewLhd.UnpVer>UNP_VER)
994 debug_log("unknown compression method");
995 ReturnCode=FALSE;
996 break; /* error, can't extract file! */
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);
1006 UnpPackedSize=NewLhd.PackSize;
1007 DestUnpSize=NewLhd.UnpSize;
1009 if (NewLhd.Method==0x30)
1011 UnstoreFile();
1012 } else
1014 Unpack(UnpMemory);
1019 #ifdef _DO_CRC32_CHECK /* calculate CRC32 */
1020 if((UBYTE*)temp_output_buffer != NULL)
1022 if(NewLhd.FileCRC!=~CalcCRC32(0xFFFFFFFFL,
1023 (UBYTE*)temp_output_buffer,
1024 NewLhd.UnpSize))
1026 debug_log("CRC32 error - file couldn't be decompressed correctly!");
1027 ReturnCode=FALSE;
1028 break; /* error, can't extract file! */
1031 #endif
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 */
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;
1050 #endif
1052 return ReturnCode; /* file extracted successful! */
1055 /* **************************************************************************
1056 ****************************************************************************
1057 ****************************************************************************
1058 ************************************************************************** */
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 ************************************************************************** */
1094 int tread(void *stream,void *buf,unsigned len)
1096 #ifdef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1098 if(((MemRARFile->offset + len) > MemRARFile->size) || (len == 0))
1099 return 0;
1101 memcpy(buf,
1102 (BYTE*)(((MemoryFile*)stream)->data)+((MemoryFile*)stream)->offset,
1103 len % ((((MemoryFile*)stream)->size) - 1));
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
1113 #ifndef _USE_MEMORY_TO_MEMORY_DECOMPRESSION
1114 int tseek(void *stream,long offset,int fromwhere)
1116 return(fseek((FILE*)stream,offset,fromwhere));
1118 #endif
1121 char* strupper(char *Str)
1123 char *ChPtr;
1124 for (ChPtr=Str;*ChPtr;ChPtr++)
1125 *ChPtr=(char)toupper(*ChPtr);
1126 return(Str);
1130 int stricomp(char *Str1,char *Str2)
1131 /* compare strings without regard of '\' and '/' */
1133 char S1[512],S2[512];
1134 char *chptr;
1136 strncpy(S1,Str1,sizeof(S1));
1137 strncpy(S2,Str2,sizeof(S2));
1139 while((chptr = strchr(S1, '\\')) != NULL) /* ignore backslash */
1141 *chptr = '_';
1144 while((chptr = strchr(S2, '\\')) != NULL) /* ignore backslash */
1146 *chptr = '_';
1149 while((chptr = strchr(S1, '/')) != NULL) /* ignore slash */
1151 *chptr = '_';
1154 while((chptr = strchr(S2, '/')) != NULL) /* ignore slash */
1156 *chptr = '_';
1159 return(strcmp(strupper(S1),strupper(S2)));
1163 /* **************************************************************************
1164 ****************************************************************************
1165 ****************************************************************************
1166 ************************************************************************** */
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 ************************************************************************** */
1202 /* *****************************
1203 * ** unpack stored RAR files **
1204 * *****************************/
1206 BOOL UnstoreFile(void)
1208 if ((long)(*temp_output_buffer_offset=UnpRead(temp_output_buffer,
1209 NewLhd.UnpSize))==-1)
1211 debug_log("Read error of stored file!");
1212 return FALSE;
1214 return TRUE;
1220 /* ****************************************
1221 * ** RAR decompression code starts here **
1222 * ****************************************/
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
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};
1234 struct AudioVariables
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;
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
1252 struct AudioVariables AudV[4];
1254 #define GetBits() \
1255 BitField = ( ( ( (UDWORD)InBuf[InAddr] << 16 ) | \
1256 ( (UWORD) InBuf[InAddr+1] << 8 ) | \
1257 ( InBuf[InAddr+2] ) ) \
1258 >> (8-InBit) ) & 0xffff;
1261 #define AddBits(Bits) \
1262 InAddr += ( InBit + (Bits) ) >> 3; \
1263 InBit = ( InBit + (Bits) ) & 7;
1265 static unsigned char *UnpBuf;
1266 static unsigned int BitField;
1267 static unsigned int Number;
1269 unsigned char InBuf[8192]; /* input read buffer */
1271 unsigned char UnpOldTable[MC*4];
1273 unsigned int InAddr,InBit,ReadTop;
1275 unsigned int LastDist,LastLength;
1276 static unsigned int Length,Distance;
1278 unsigned int OldDist[4],OldDistPtr;
1281 struct LitDecode
1283 unsigned int MaxNum;
1284 unsigned int DecodeLen[16];
1285 unsigned int DecodePos[16];
1286 unsigned int DecodeNum[NC];
1287 } LD;
1289 struct DistDecode
1291 unsigned int MaxNum;
1292 unsigned int DecodeLen[16];
1293 unsigned int DecodePos[16];
1294 unsigned int DecodeNum[DC];
1295 } DD;
1297 struct RepDecode
1299 unsigned int MaxNum;
1300 unsigned int DecodeLen[16];
1301 unsigned int DecodePos[16];
1302 unsigned int DecodeNum[RC];
1303 } RD;
1305 struct MultDecode
1307 unsigned int MaxNum;
1308 unsigned int DecodeLen[16];
1309 unsigned int DecodePos[16];
1310 unsigned int DecodeNum[MC];
1311 } MD[4];
1313 struct BitDecode
1315 unsigned int MaxNum;
1316 unsigned int DecodeLen[16];
1317 unsigned int DecodePos[16];
1318 unsigned int DecodeNum[BC];
1319 } BD;
1321 static struct MultDecode *MDPtr[4]={&MD[0],&MD[1],&MD[2],&MD[3]};
1323 int UnpAudioBlock,UnpChannels,CurChannel,ChannelDelta;
1326 void Unpack(unsigned char *UnpAddr)
1327 /* *** 38.3% of all CPU time is spent within this function!!! */
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;
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--;
1353 while (DestUnpSize>=0)
1355 UnpPtr&=MAXWINMASK;
1357 if (InAddr>sizeof(InBuf)-30)
1358 UnpReadBuf(0);
1359 if (((WrPtr-UnpPtr) & MAXWINMASK)<270 && WrPtr!=UnpPtr)
1363 if (FileFound)
1366 if (UnpPtr<WrPtr)
1368 if((*temp_output_buffer_offset + UnpPtr) > NewLhd.UnpSize)
1370 debug_log("Fatal! Buffer overrun during decompression!");
1371 DestUnpSize=-1;
1373 } else
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;
1386 } else
1388 if((*temp_output_buffer_offset + (UnpPtr-WrPtr)) > NewLhd.UnpSize)
1390 debug_log("Fatal! Buffer overrun during decompression!");
1391 DestUnpSize=-1;
1392 } else
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 */
1403 WrPtr=UnpPtr;
1406 if (UnpAudioBlock)
1408 DecodeNumber((struct Decode *)MDPtr[CurChannel]);
1409 if (Number==256)
1411 ReadTables();
1412 continue;
1414 UnpBuf[UnpPtr++]=DecodeAudio(Number);
1415 if (++CurChannel==UnpChannels)
1416 CurChannel=0;
1417 DestUnpSize--;
1418 continue;
1421 DecodeNumber((struct Decode *)&LD);
1422 if (Number<256)
1424 UnpBuf[UnpPtr++]=(UBYTE)Number;
1425 DestUnpSize--;
1426 continue;
1428 if (Number>269)
1430 Length=LDecode[Number-=270]+3;
1431 if ((Bits=LBits[Number])>0)
1433 GetBits();
1434 Length+=BitField>>(16-Bits);
1435 AddBits(Bits);
1438 DecodeNumber((struct Decode *)&DD);
1439 Distance=DDecode[Number]+1;
1440 if ((Bits=DBits[Number])>0)
1442 GetBits();
1443 Distance+=BitField>>(16-Bits);
1444 AddBits(Bits);
1447 if (Distance>=0x40000L)
1448 Length++;
1450 if (Distance>=0x2000)
1451 Length++;
1453 LastDist=OldDist[OldDistPtr++ & 3]=Distance;
1454 DestUnpSize-=(LastLength=Length);
1455 while (Length--)
1457 UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
1458 UnpPtr=(UnpPtr+1) & MAXWINMASK;
1461 continue;
1463 if (Number==269)
1465 ReadTables();
1466 continue;
1468 if (Number==256)
1470 Length=LastLength;
1471 Distance=LastDist;
1472 LastDist=OldDist[OldDistPtr++ & 3]=Distance;
1473 DestUnpSize-=(LastLength=Length);
1474 while (Length--)
1476 UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
1477 UnpPtr=(UnpPtr+1) & MAXWINMASK;
1479 continue;
1481 if (Number<261)
1483 Distance=OldDist[(OldDistPtr-(Number-256)) & 3];
1484 DecodeNumber((struct Decode *)&RD);
1485 Length=LDecode[Number]+2;
1486 if ((Bits=LBits[Number])>0)
1488 GetBits();
1489 Length+=BitField>>(16-Bits);
1490 AddBits(Bits);
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--)
1502 UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
1503 UnpPtr=(UnpPtr+1) & MAXWINMASK;
1505 continue;
1507 if (Number<270)
1509 Distance=SDDecode[Number-=261]+1;
1510 if ((Bits=SDBits[Number])>0)
1512 GetBits();
1513 Distance+=BitField>>(16-Bits);
1514 AddBits(Bits);
1516 Length=2;
1517 LastDist=OldDist[OldDistPtr++ & 3]=Distance;
1518 DestUnpSize-=(LastLength=Length);
1519 while (Length--)
1521 UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
1522 UnpPtr=(UnpPtr+1) & MAXWINMASK;
1524 continue;
1527 ReadLastTables();
1529 if (FileFound) /* flush buffer */
1532 if (UnpPtr<WrPtr)
1534 if((*temp_output_buffer_offset + UnpPtr) > NewLhd.UnpSize)
1536 debug_log("Fatal! Buffer overrun during decompression!");
1537 DestUnpSize=-1;
1538 } else
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;
1550 } else
1552 if((*temp_output_buffer_offset + (UnpPtr-WrPtr)) > NewLhd.UnpSize)
1554 debug_log("Fatal! Buffer overrun during decompression!");
1555 DestUnpSize=-1;
1556 } else
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;
1567 WrPtr=UnpPtr;
1571 unsigned int UnpRead(unsigned char *Addr,unsigned int Count)
1573 int RetCode=0;
1574 unsigned int I,ReadSize,TotalRead=0;
1575 unsigned char *ReadAddr;
1576 ReadAddr=Addr;
1577 while (Count > 0)
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;
1597 if (RetCode!= -1)
1599 RetCode=TotalRead;
1600 if (Encryption)
1602 if (Encryption<20)
1604 debug_log("Old Crypt() not supported!");
1606 else
1608 for (I=0;I<(unsigned int)RetCode;I+=16)
1609 DecryptBlock(&Addr[I]);
1613 return(RetCode);
1617 void UnpReadBuf(int FirstBuf)
1619 int RetCode;
1620 if (FirstBuf)
1622 ReadTop=UnpRead(InBuf,sizeof(InBuf));
1623 InAddr=0;
1625 else
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;
1638 void ReadTables(void)
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);
1648 if (!(BitField & 0x4000))
1649 memset(UnpOldTable,0,sizeof(UnpOldTable));
1650 AddBits(2);
1653 if (UnpAudioBlock)
1655 UnpChannels=((BitField>>12) & 3)+1;
1656 if (CurChannel>=UnpChannels)
1657 CurChannel=0;
1658 AddBits(2);
1659 TableSize=MC*UnpChannels;
1661 else
1662 TableSize=NC+DC+RC;
1665 for (I=0;I<BC;I++)
1667 GetBits();
1668 BitLength[I]=(UBYTE)(BitField >> 12);
1669 AddBits(4);
1671 MakeDecodeTables(BitLength,(struct Decode *)&BD,BC);
1672 I=0;
1673 while (I<TableSize)
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)
1683 GetBits();
1684 N=(BitField >> 14)+3;
1685 AddBits(2);
1686 while (N-- > 0 && I<TableSize)
1688 Table[I]=Table[I-1];
1689 I++;
1692 else
1694 if (Number==17)
1696 GetBits();
1697 N=(BitField >> 13)+3;
1698 AddBits(3);
1700 else
1702 GetBits();
1703 N=(BitField >> 9)+11;
1704 AddBits(7);
1706 while (N-- > 0 && I<TableSize)
1707 Table[I++]=0;
1710 if (UnpAudioBlock)
1711 for (I=0;I<UnpChannels;I++)
1712 MakeDecodeTables(&Table[I*MC],(struct Decode *)MDPtr[I],MC);
1713 else
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);
1719 memcpy(UnpOldTable,Table,sizeof(UnpOldTable));
1723 static void ReadLastTables(void)
1725 if (ReadTop>=InAddr+5)
1727 if (UnpAudioBlock)
1729 DecodeNumber((struct Decode *)MDPtr[CurChannel]);
1730 if (Number==256)
1731 ReadTables();
1733 else
1735 DecodeNumber((struct Decode *)&LD);
1736 if (Number==269)
1737 ReadTables();
1743 static void MakeDecodeTables(unsigned char *LenTab,
1744 struct Decode *Dec,
1745 int Size)
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]++;
1753 LenCount[0]=0;
1754 for (TmpPos[0]=Dec->DecodePos[0]=Dec->DecodeLen[0]=0,N=0,I=1;I<16;I++)
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];
1764 for (I=0;I<Size;I++)
1765 if (LenTab[I]!=0)
1766 Dec->DecodeNum[TmpPos[LenTab[I] & 0xF]++]=I;
1767 Dec->MaxNum=Size;
1771 static void DecodeNumber(struct Decode *Deco)
1772 /* *** 52.6% of all CPU time is spent within this function!!! */
1774 unsigned int I;
1775 register unsigned int N;
1776 GetBits();
1778 #ifdef _USE_ASM
1780 #ifdef _WIN_32
1781 __asm {
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
1789 cmp eax, dword ptr[edx + 8*4 + 4]// if (N<Dec->DecodeLen[8])
1790 jae else_G
1792 cmp eax, dword ptr[edx + 4*4 + 4]// if (N<Dec->DecodeLen[4])
1793 jae else_F
1796 cmp eax, dword ptr[edx + 2*4 + 4]// if (N<Dec->DecodeLen[2])
1797 jae else_C
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:
1807 jmp next_C
1808 else_C: // else
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:
1818 next_C: // else
1820 jmp next_F
1821 else_F:
1824 cmp eax, dword ptr[edx + 6*4 + 4]// if (N<Dec->DecodeLen[6])
1825 jae else_E
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:
1835 jmp next_E
1836 else_E: // else
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:
1846 next_E:
1848 next_F:
1850 jmp next_G
1851 else_G:
1853 cmp eax, dword ptr[edx + 12*4 + 4] // if (N<Dec->DecodeLen[12])
1854 jae else_D
1856 cmp eax, dword ptr[edx + 10*4 + 4]// if (N<Dec->DecodeLen[10])
1857 jae else_B
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:
1867 jmp next_B
1868 else_B: // else
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:
1878 next_B:
1881 jmp next_D
1882 else_D: // else
1884 cmp eax, dword ptr[edx + 14*4 + 4]// if (N<Dec->DecodeLen[14])
1885 jae else_A
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:
1895 jmp next_A
1896 else_A: // else
1897 mov I, 15 // I=15;
1898 next_A:
1900 next_D:
1901 next_G:
1903 #else
1904 __asm__ __volatile__ (
1905 "andl $0xFFFFFFFE, %%eax"
1906 " movl %%eax, %1"
1907 " cmpl 8*4(%%edx), %%eax /* 5379 */"
1908 " jae else_G"
1910 " cmpl 4*4(%%edx), %%eax"
1911 " jae else_F"
1913 " cmpl 2*4(%%edx), %%eax"
1914 " jae else_C"
1916 " cmpl 1*4(%%edx), %%eax"
1918 " jae else_1"
1919 " movl $1, %0"
1920 " jmp next_1"
1921 " else_1: "
1922 " movl $2, %0"
1923 " next_1:"
1925 " jmp next_C"
1926 " else_C: "
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:"
1936 " next_C: "
1938 " jmp next_F"
1939 " else_F:"
1941 " cmpl 6*4(%%edx), %%eax"
1942 " jae else_E"
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:"
1952 " jmp next_E"
1953 " else_E: "
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:"
1963 " next_E:"
1965 " next_F:"
1967 " jmp next_G"
1968 " else_G:"
1970 " cmpl 12*4(%%edx), %%eax"
1971 " jae else_D"
1973 " cmpl 10*4(%%edx), %%eax"
1974 " jae else_B"
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:"
1984 " jmp next_B"
1985 " else_B: "
1987 " cmpl 11*4(%%edx), %%eax"
1989 " jae else_6"
1990 " movl $11, %0 "
1991 " jmp next_6"
1992 " else_6: "
1993 " movl $12, %0 "
1994 " next_6:"
1996 " next_B:"
1999 " jmp next_D"
2000 " else_D: "
2002 " cmpl 14*4(%%edx), %%eax"
2003 " jae else_A"
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:"
2013 " jmp next_A"
2014 " else_A: "
2015 " movl $15, %0 "
2016 " next_A:"
2018 " next_D: "
2019 " next_G:"
2020 : "=g" (I), "=r"(N)
2021 : "eax" ((long)BitField), "edx"((long)Deco->DecodeLen)
2022 : "memory"
2024 #endif /* #ifdef _WIN_32 ... #elif defined _X86_ASM_ */
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;
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;
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;
2067 } else {
2068 if (N<Deco->DecodeLen[14]) {
2069 if (N<Deco->DecodeLen[13])
2070 I=13;
2071 else
2072 I=14;
2074 } else {
2075 I=15;
2080 #endif
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];
2089 void UnpInitData()
2091 InAddr=InBit=0;
2092 if (!(NewLhd.Flags & LHD_SOLID))
2094 ChannelDelta=CurChannel=0;
2096 #ifdef _USE_ASM
2098 #ifdef _WIN_32 /* Win32 with VisualC */
2100 __asm {
2101 push edi
2102 push eax
2103 push ecx
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 */
2111 mov ecx, SIZE OldDist
2112 mov edi, Offset OldDist
2113 rep stosb /* clear memory */
2115 mov ecx, SIZE UnpOldTable
2116 mov edi, Offset UnpOldTable
2117 rep stosb /* clear memory */
2119 pop ecx
2120 pop eax
2121 pop edi
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
2136 memset(UnpBuf,0,MAXWINSIZE);
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 */"
2148 " movl %2, %%ecx"
2149 " mov %3, %%edi"
2150 " rep "
2151 " stosb /* clear memory */"
2153 " movl %4, %%ecx"
2154 " movl %5, %%edi"
2155 " rep "
2156 " stosb /* clear memory */"
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)"
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"
2177 memset(UnpBuf,0,MAXWINSIZE);
2178 #endif
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
2194 UBYTE DecodeAudio(int Delta)
2196 struct AudioVariables *V;
2197 unsigned int Ch;
2198 unsigned int NumMinDif,MinDif;
2199 int PCh,I;
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;
2211 Ch=PCh-Delta;
2213 I=((signed char)Delta)<<3;
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);
2227 ChannelDelta=V->LastDelta=(signed char)(Ch-V->LastChar);
2228 V->LastChar=Ch;
2230 if ((V->ByteCount & 0x1F)==0)
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++)
2237 if (V->Dif[I]<MinDif)
2239 MinDif=V->Dif[I];
2240 NumMinDif=I;
2242 V->Dif[I]=0;
2244 switch(NumMinDif)
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;
2288 return((UBYTE)Ch);
2297 /* ***************************************************
2298 * ** CRCCrypt Code - decryption engine starts here **
2299 * ***************************************************/
2302 #define NROUNDS 32
2304 #define rol(x,n) (((x)<<(n)) | ((x)>>(8*sizeof(x)-(n))))
2305 #define ror(x,n) (((x)>>(n)) | ((x)<<(8*sizeof(x)-(n))))
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) )
2313 UDWORD CRCTab[256];
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
2335 UDWORD Key[4];
2338 void EncryptBlock(UBYTE *Buf)
2340 int I;
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++)
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;
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);
2402 void DecryptBlock(UBYTE *Buf)
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--)
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;
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);
2467 void UpdKeys(UBYTE *Buf)
2469 int I;
2470 for (I=0;I<16;I+=4)
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]];
2479 void SetCryptKeys(char *Password)
2481 unsigned int I,J,K,PswLength;
2482 unsigned char N1,N2;
2483 unsigned char Psw[256];
2485 #if !defined _USE_ASM
2486 UBYTE Ch;
2487 #endif
2489 SetOldKeys(Password);
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));
2500 for (J=0;J<256;J++)
2501 for (I=0;I<PswLength;I+=2)
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
2510 #ifdef _WIN_32
2511 __asm {
2513 mov ebx, Offset SubstTable
2514 mov edx, ebx
2516 xor ecx, ecx // read SubstTable[N1]...
2517 mov cl, N1
2518 add ebx, ecx
2519 mov al, byte ptr[ebx]
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]
2528 mov byte ptr[ebx], ah // and write back
2529 mov byte ptr[edx], al
2532 #else
2533 __asm__ __volatile__ (
2534 " xorl %%ecx, %%ecx"
2535 " movl %2, %%ecx /* ecx = N1 */"
2536 " mov %%ebx, %%edx"
2537 " addl %%ecx, %%ebx"
2539 " addl %0, %%ecx"
2540 " addl %1, %%ecx"
2541 " andl $0x000000FF, %%ecx"
2542 " addl %%ecx, %%edx"
2544 " movb (%%ebx), %%al"
2545 " movb (%%edx), %%ah"
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"
2556 #endif
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
2566 for (I=0;I<PswLength;I+=16)
2567 EncryptBlock(&Psw[I]);
2571 void SetOldKeys(char *Password)
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)
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++;
2592 void InitCRC(void)
2594 int I, J;
2595 UDWORD C;
2596 for (I=0;I<256;I++)
2598 for (C=I,J=0;J<8;J++)
2599 C=(C & 1) ? (C>>1)^0xEDB88320L : (C>>1);
2600 CRCTab[I]=C;
2605 UDWORD CalcCRC32(UDWORD StartCRC,UBYTE *Addr,UDWORD Size)
2607 unsigned int I;
2608 for (I=0; I<Size; I++)
2609 StartCRC = CRCTab[(UBYTE)StartCRC ^ Addr[I]] ^ (StartCRC >> 8);
2610 return(StartCRC);
2614 /* **************************************************************************
2615 ****************************************************************************
2616 ****************************************************************************
2617 ************************************************************************** */
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
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 /* ------------------------------------------------------------------------ */
2669 /* -- global functions ---------------------------------------------------- */
2670 void debug_init_proc(char *file_name)
2671 /* Create/Rewrite a log file */
2673 FILE *fp;
2674 char date[] = __DATE__;
2675 char time[] = __TIME__;
2677 debug_start_time = GetTickCount(); /* get start time */
2678 strcpy(log_file_name, file_name); /* save file name */
2680 if((fp = fopen(log_file_name, CREATETEXT)) != NULL)
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);
2691 void debug_log_proc(char *text, char *sourcefile, int sourceline)
2692 /* add a line to the log file */
2694 FILE *fp;
2696 if(debug_started == FALSE) return; /* exit if not initialized */
2698 if((fp = fopen(log_file_name, APPENDTEXT)) != NULL) /* append to logfile */
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);
2708 /* ------------------------------------------------------------------------ */
2709 #endif
2710 /* **************************************************************************
2711 ****************************************************************************
2712 ****************************************************************************
2713 ************************************************************************** */
2716 /* end of file urarlib.c */