mirror of
https://github.com/MacPaw/XADMaster.git
synced 2025-08-28 19:13:49 +02:00
274 lines
6.8 KiB
Objective-C
274 lines
6.8 KiB
Objective-C
/*
|
|
* XADRAR20Handle.m
|
|
*
|
|
* Copyright (c) 2017-present, MacPaw Inc. All rights reserved.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
* MA 02110-1301 USA
|
|
*/
|
|
#import "XADRAR20Handle.h"
|
|
#import "XADException.h"
|
|
|
|
@implementation XADRAR20Handle
|
|
|
|
-(id)initWithRARParser:(XADRARParser *)parentparser files:(NSArray *)filearray
|
|
{
|
|
if((self=[super initWithParentHandle:[parentparser handle] windowSize:0x100000]))
|
|
{
|
|
parser=parentparser;
|
|
files=[filearray retain];
|
|
|
|
maincode=nil;
|
|
offsetcode=nil;
|
|
lengthcode=nil;
|
|
for(int i=0;i<4;i++) audiocode[i]=nil;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
-(void)dealloc
|
|
{
|
|
[files release];
|
|
[maincode release];
|
|
[offsetcode release];
|
|
[lengthcode release];
|
|
for(int i=0;i<4;i++) [audiocode[i] release];
|
|
[super dealloc];
|
|
}
|
|
|
|
-(void)resetLZSSHandle
|
|
{
|
|
file=0;
|
|
endpos=0;
|
|
|
|
lastoffset=0;
|
|
lastlength=0;
|
|
memset(oldoffset,0,sizeof(oldoffset));
|
|
oldoffsetindex=0;
|
|
|
|
channel=channeldelta=0;
|
|
memset(audiostate,0,sizeof(audiostate));
|
|
|
|
memset(lengthtable,0,sizeof(lengthtable));
|
|
|
|
[self startNextFile];
|
|
[self allocAndParseCodes];
|
|
}
|
|
|
|
-(void)startNextFile
|
|
{
|
|
CSInputBuffer *buf=[parser inputBufferForFileWithIndex:file files:files];
|
|
off_t partlength=[parser outputLengthOfFileWithIndex:file files:files];
|
|
file++;
|
|
|
|
[self setInputBuffer:buf];
|
|
endpos+=partlength;
|
|
}
|
|
|
|
-(void)expandFromPosition:(off_t)pos
|
|
{
|
|
static const int lengthbases[28]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,
|
|
40,48,56,64,80,96,112,128,160,192,224};
|
|
static const int lengthbits[28]={0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5};
|
|
static const int offsetbases[48]={0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,
|
|
512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576,32768,49152,
|
|
65536,98304,131072,196608,262144,327680,393216,458752,524288,589824,655360,
|
|
720896,786432,851968,917504,983040};
|
|
static unsigned char offsetbits[48]={0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,
|
|
9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16,16};
|
|
static unsigned int shortbases[8]={0,4,8,16,32,64,128,192};
|
|
static unsigned int shortbits[8]={2,2,3,4,5,6,6,6};
|
|
|
|
while(XADLZSSShouldKeepExpanding(self))
|
|
{
|
|
if(pos==endpos)
|
|
{
|
|
[self startNextFile];
|
|
}
|
|
|
|
if(audioblock)
|
|
{
|
|
int symbol=CSInputNextSymbolUsingCode(input,audiocode[channel]);
|
|
if(symbol==256)
|
|
{
|
|
[self allocAndParseCodes];
|
|
continue;
|
|
//return [self nextLiteralOrOffset:offset andLength:length atPosition:pos];
|
|
}
|
|
else
|
|
{
|
|
int byte=DecodeRAR20Audio(&audiostate[channel],&channeldelta,symbol);
|
|
|
|
channel++;
|
|
if(channel==numchannels) channel=0;
|
|
|
|
XADEmitLZSSLiteral(self,byte,&pos);
|
|
//return byte;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int symbol=CSInputNextSymbolUsingCode(input,maincode);
|
|
int offs,len;
|
|
|
|
// if(symbol<256) return symbol;
|
|
if(symbol<256)
|
|
{
|
|
XADEmitLZSSLiteral(self,symbol,&pos);
|
|
continue;
|
|
}
|
|
else if(symbol==256)
|
|
{
|
|
offs=lastoffset;
|
|
len=lastlength;
|
|
}
|
|
else if(symbol<=260)
|
|
{
|
|
offs=oldoffset[(oldoffsetindex-(symbol-256))&3];
|
|
|
|
int lensymbol=CSInputNextSymbolUsingCode(input,lengthcode);
|
|
len=lengthbases[lensymbol]+2;
|
|
if(lengthbits[lensymbol]>0) len+=CSInputNextBitString(input,lengthbits[lensymbol]);
|
|
|
|
if(offs>=0x40000) len++;
|
|
if(offs>=0x2000) len++;
|
|
if(offs>=0x101) len++;
|
|
}
|
|
else if(symbol<=268)
|
|
{
|
|
offs=shortbases[symbol-261]+1;
|
|
if(shortbits[symbol-261]>0) offs+=CSInputNextBitString(input,shortbits[symbol-261]);
|
|
|
|
len=2;
|
|
}
|
|
else if(symbol==269)
|
|
{
|
|
[self allocAndParseCodes];
|
|
continue;
|
|
// return [self nextLiteralOrOffset:offset andLength:length atPosition:pos];
|
|
}
|
|
else //if(code>=270)
|
|
{
|
|
len=lengthbases[symbol-270]+3;
|
|
if(lengthbits[symbol-270]>0) len+=CSInputNextBitString(input,lengthbits[symbol-270]);
|
|
|
|
int offssymbol=CSInputNextSymbolUsingCode(input,offsetcode);
|
|
offs=offsetbases[offssymbol]+1;
|
|
if(offsetbits[offssymbol]>0) offs+=CSInputNextBitString(input,offsetbits[offssymbol]);
|
|
|
|
if(offs>=0x40000) len++;
|
|
if(offs>=0x2000) len++;
|
|
}
|
|
|
|
lastoffset=oldoffset[oldoffsetindex++&3]=offs;
|
|
lastlength=len;
|
|
|
|
// *offset=offs;
|
|
// *length=len;
|
|
//
|
|
// return XADLZSSMatch;
|
|
XADEmitLZSSMatch(self,offs,len,&pos);
|
|
}
|
|
}
|
|
}
|
|
|
|
-(void)allocAndParseCodes
|
|
{
|
|
[maincode release]; maincode=nil;
|
|
[offsetcode release]; offsetcode=nil;
|
|
[lengthcode release]; lengthcode=nil;
|
|
for(int i=0;i<4;i++) { [audiocode[i] release]; audiocode[i]=nil; }
|
|
|
|
audioblock=CSInputNextBit(input);
|
|
|
|
if(CSInputNextBit(input)==0) memset(lengthtable,0,sizeof(lengthtable));
|
|
|
|
int count;
|
|
if(audioblock)
|
|
{
|
|
numchannels=CSInputNextBitString(input,2)+1;
|
|
count=numchannels*257;
|
|
if(channel>=numchannels) channel=0;
|
|
}
|
|
else count=298+48+28;
|
|
|
|
XADPrefixCode *precode=nil;
|
|
@try
|
|
{
|
|
int prelengths[19];
|
|
for(int i=0;i<19;i++) prelengths[i]=CSInputNextBitString(input,4);
|
|
|
|
precode=[[XADPrefixCode alloc] initWithLengths:prelengths
|
|
numberOfSymbols:19 maximumLength:15 shortestCodeIsZeros:YES];
|
|
|
|
int i=0;
|
|
while(i<count)
|
|
{
|
|
int val=CSInputNextSymbolUsingCode(input,precode);
|
|
//NSLog(@"%d",val);
|
|
if(val<16)
|
|
{
|
|
lengthtable[i]=(lengthtable[i]+val)&0x0f;
|
|
i++;
|
|
}
|
|
else if(val==16)
|
|
{
|
|
if(i==0) [XADException raiseDecrunchException];
|
|
int n=CSInputNextBitString(input,2)+3;
|
|
for(int j=0;j<n && i<count;j++)
|
|
{
|
|
lengthtable[i]=lengthtable[i-1];
|
|
i++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int n;
|
|
if(val==17) n=CSInputNextBitString(input,3)+3;
|
|
else n=CSInputNextBitString(input,7)+11;
|
|
|
|
for(int j=0;j<n && i<count;j++) lengthtable[i++]=0;
|
|
}
|
|
}
|
|
|
|
[precode release];
|
|
}
|
|
@catch(id e)
|
|
{
|
|
[precode release];
|
|
@throw;
|
|
}
|
|
|
|
if(audioblock)
|
|
{
|
|
for(int i=0;i<numchannels;i++) audiocode[i]=[[XADPrefixCode alloc]
|
|
initWithLengths:&lengthtable[i*257]
|
|
numberOfSymbols:257 maximumLength:15 shortestCodeIsZeros:YES];
|
|
}
|
|
else
|
|
{
|
|
maincode=[[XADPrefixCode alloc] initWithLengths:&lengthtable[0]
|
|
numberOfSymbols:298 maximumLength:15 shortestCodeIsZeros:YES];
|
|
|
|
offsetcode=[[XADPrefixCode alloc] initWithLengths:&lengthtable[298]
|
|
numberOfSymbols:48 maximumLength:15 shortestCodeIsZeros:YES];
|
|
|
|
lengthcode=[[XADPrefixCode alloc] initWithLengths:&lengthtable[298+48]
|
|
numberOfSymbols:28 maximumLength:15 shortestCodeIsZeros:YES];
|
|
}
|
|
}
|
|
|
|
@end
|
|
|